diff --git a/extensions/sqlite/Makefile b/extensions/sqlite/Makefile new file mode 100644 index 00000000..8c735d7d --- /dev/null +++ b/extensions/sqlite/Makefile @@ -0,0 +1,87 @@ +#(C)2004-2006 SourceMM Development Team +# Makefile written by David "BAILOPAN" Anderson + +SMSDK = ../.. +SRCDS = ~/srcds +SOURCEMM = ../../../../sourcemm + +##################################### +### EDIT BELOW FOR OTHER PROJECTS ### +##################################### + +PROJECT = sample + +#Uncomment for SourceMM-enabled extensions +#LINK_HL2 = $(HL2LIB)/tier1_i486.a vstdlib_i486.so tier0_i486.so + +OBJECTS = sdk/smsdk_ext.cpp extension.cpp + +############################################## +### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ### +############################################## + +C_OPT_FLAGS = -O3 -funroll-loops -s -pipe -fno-strict-aliasing +C_DEBUG_FLAGS = -g -ggdb3 +CPP_GCC4_FLAGS = -fvisibility=hidden -fvisibility-inlines-hidden +CPP = gcc-4.1 + +HL2PUB = $(HL2SDK)/public +HL2LIB = $(HL2SDK)/linux_sdk +HL2SDK = $(SOURCEMM)/hl2sdk +SMM_TRUNK = $(SOURCEMM)/trunk + +LINK = $(LINK_HL2) -static-libgcc + +INCLUDE = -I. -I.. -Isdk -I$(HL2PUB) -I$(HL2PUB)/dlls -I$(HL2PUB)/engine -I$(HL2PUB)/tier0 -I$(HL2PUB)/tier1 \ + -I$(HL2PUB)/vstdlib -I$(HL2SDK)/tier1 -I$(SMM_TRUNK) -I$(SMM_TRUNK)/sourcehook -I$(SMM_TRUNK)/sourcemm \ + -I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn -I$(SMSDK)/public/extensions \ + +CFLAGS = -D_LINUX -DNDEBUG -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -Werror -fPIC -msse -DSOURCEMOD_BUILD -DHAVE_STDINT_H +CPPFLAGS = -Wno-non-virtual-dtor -fno-exceptions -fno-rtti + +################################################ +### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ### +################################################ + +ifeq "$(DEBUG)" "true" + BIN_DIR = Debug + CFLAGS += $(C_DEBUG_FLAGS) +else + BIN_DIR = Release + CFLAGS += $(C_OPT_FLAGS) +endif + + +GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1) +ifeq "$(GCC_VERSION)" "4" + CPPFLAGS += $(CPP_GCC4_FLAGS) +endif + +BINARY = $(PROJECT).ext.so + +OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o) + +$(BIN_DIR)/%.o: %.cpp + $(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $< + +all: + mkdir -p $(BIN_DIR)/sdk + ln -sf $(SRCDS)/bin/vstdlib_i486.so vstdlib_i486.so + ln -sf $(SRCDS)/bin/tier0_i486.so tier0_i486.so + $(MAKE) extension + +extension: $(OBJ_LINUX) + $(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) $(OBJ_LINUX) $(LINK) -shared -ldl -lm -o$(BIN_DIR)/$(BINARY) + +debug: + $(MAKE) all DEBUG=true + +default: all + +clean: + rm -rf Release/*.o + rm -rf Release/sdk/*.o + rm -rf Release/$(BINARY) + rm -rf Debug/*.o + rm -rf Debug/sdk/*.o + rm -rf Debug/$(BINARY) diff --git a/extensions/sqlite/driver/SqDatabase.cpp b/extensions/sqlite/driver/SqDatabase.cpp new file mode 100644 index 00000000..624973bb --- /dev/null +++ b/extensions/sqlite/driver/SqDatabase.cpp @@ -0,0 +1,186 @@ +/** + * vim: set ts=4 : + * =============================================================== + * SourceMod SQLite Driver Extension + * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved. + * =============================================================== + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Version: $Id$ + */ + +#include "extension.h" +#include "SqDatabase.h" +#include "SqQuery.h" + +SqDatabase::SqDatabase(sqlite3 *sq3, bool persistent) : + m_sq3(sq3), m_refcount(1), m_pFullLock(NULL), m_Persistent(persistent) +{ + m_pRefLock = threader->MakeMutex(); +} + +SqDatabase::~SqDatabase() +{ + m_pRefLock->DestroyThis(); + if (m_pFullLock) + { + m_pFullLock->DestroyThis(); + } + sqlite3_close(m_sq3); +} + +void SqDatabase::IncReferenceCount() +{ + m_pRefLock->Lock(); + m_refcount++; + m_pRefLock->Unlock(); +} + +bool SqDatabase::Close() +{ + m_pRefLock->Lock(); + if (m_refcount > 1) + { + m_refcount--; + m_pRefLock->Unlock(); + return false; + } + m_pRefLock->Unlock(); + + if (m_Persistent) + { + g_SqDriver.RemovePersistent(this); + } + + delete this; + + return true; +} + +const char *SqDatabase::GetError(int *errorCode/* =NULL */) +{ + return sqlite3_errmsg(m_sq3); +} + +bool SqDatabase::LockForFullAtomicOperation() +{ + if (!m_pFullLock) + { + m_pFullLock = threader->MakeMutex(); + if (!m_pFullLock) + { + return false; + } + } + + m_pFullLock->Lock(); + + return true; +} + +void SqDatabase::UnlockFromFullAtomicOperation() +{ + if (m_pFullLock) + { + m_pFullLock->Unlock(); + } +} + +IDBDriver *SqDatabase::GetDriver() +{ + return &g_SqDriver; +} + +bool SqDatabase::QuoteString(const char *str, char buffer[], size_t maxlen, size_t *newSize) +{ + char *res = sqlite3_snprintf(static_cast(maxlen), buffer, "%q", str); + + if (res != NULL && newSize != NULL) + { + *newSize = strlen(buffer); + } + + return (res != NULL); +} + +unsigned int SqDatabase::GetInsertID() +{ + return (unsigned int)sqlite3_last_insert_rowid(m_sq3); +} + +unsigned int SqDatabase::GetAffectedRows() +{ + return (unsigned int)sqlite3_changes(m_sq3); +} + +bool SqDatabase::DoSimpleQuery(const char *query) +{ + IQuery *pQuery = DoQuery(query); + if (!pQuery) + { + return false; + } + pQuery->Destroy(); + return true; +} + +/* this sounds like daiquiri.. i'm tired. */ +IQuery *SqDatabase::DoQuery(const char *query) +{ + IPreparedQuery *pQuery = PrepareQuery(query, NULL, 0, NULL); + if (!pQuery) + { + return NULL; + } + if (!pQuery->Execute()) + { + pQuery->Destroy(); + return NULL; + } + return pQuery; +} + +IPreparedQuery *SqDatabase::PrepareQuery(const char *query, char *error, size_t maxlength, int *errCode/* =NULL */) +{ + sqlite3_stmt *stmt = NULL; + if ((m_LastErrorCode = sqlite3_prepare_v2(m_sq3, query, -1, &stmt, NULL)) != SQLITE_OK + || !stmt) + { + const char *msg; + if (m_LastErrorCode != SQLITE_OK) + { + msg = sqlite3_errmsg(m_sq3); + } else { + msg = "Invalid query string"; + m_LastErrorCode = SQLITE_MISUSE; + } + if (error) + { + strncopy(error, msg, maxlength); + } + m_LastError.assign(msg); + if (stmt) + { + sqlite3_finalize(stmt); + } + return NULL; + } + return new SqQuery(this, stmt); +} + +sqlite3 *SqDatabase::GetDb() +{ + return m_sq3; +} diff --git a/extensions/sqlite/driver/SqDatabase.h b/extensions/sqlite/driver/SqDatabase.h new file mode 100644 index 00000000..1b4d068b --- /dev/null +++ b/extensions/sqlite/driver/SqDatabase.h @@ -0,0 +1,60 @@ +/** + * vim: set ts=4 : + * =============================================================== + * SourceMod SQLite Driver Extension + * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved. + * =============================================================== + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Version: $Id$ + */ + +#ifndef _INCLUDE_SQLITE_SOURCEMOD_DATABASE_H_ +#define _INCLUDE_SQLITE_SOURCEMOD_DATABASE_H_ + +#include +#include "SqDriver.h" + +class SqDatabase : public IDatabase +{ +public: + SqDatabase(sqlite3 *sq3, bool persistent); + ~SqDatabase(); +public: + bool Close(); + const char *GetError(int *errorCode=NULL); + bool DoSimpleQuery(const char *query); + IQuery *DoQuery(const char *query); + IPreparedQuery *PrepareQuery(const char *query, char *error, size_t maxlength, int *errCode=NULL); + bool QuoteString(const char *str, char buffer[], size_t maxlen, size_t *newSize); + unsigned int GetAffectedRows(); + unsigned int GetInsertID(); + bool LockForFullAtomicOperation(); + void UnlockFromFullAtomicOperation(); + void IncReferenceCount(); + IDBDriver *GetDriver(); +public: + sqlite3 *GetDb(); +private: + sqlite3 *m_sq3; + unsigned int m_refcount; + IMutex *m_pFullLock; + IMutex *m_pRefLock; + bool m_Persistent; + String m_LastError; + int m_LastErrorCode; +}; + +#endif //_INCLUDE_SQLITE_SOURCEMOD_DATABASE_H_ diff --git a/extensions/sqlite/driver/SqDriver.cpp b/extensions/sqlite/driver/SqDriver.cpp new file mode 100644 index 00000000..de2d7a05 --- /dev/null +++ b/extensions/sqlite/driver/SqDriver.cpp @@ -0,0 +1,244 @@ +/** + * vim: set ts=4 : + * =============================================================== + * SourceMod SQLite Driver Extension + * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved. + * =============================================================== + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Version: $Id$ + */ + +#include +#include "extension.h" +#include "SqDriver.h" +#include "SqDatabase.h" + +SqDriver g_SqDriver; + +unsigned int strncopy(char *dest, const char *src, size_t count) +{ + if (!count) + { + return 0; + } + + char *start = dest; + while ((*src) && (--count)) + { + *dest++ = *src++; + } + *dest = '\0'; + + return (dest - start); +} + +SqDriver::SqDriver() +{ + m_Handle = BAD_HANDLE; + m_pOpenLock = NULL; +} + +void SqDriver::Initialize() +{ + m_pOpenLock = threader->MakeMutex(); +} + +void SqDriver::Shutdown() +{ + if (m_pOpenLock) + { + m_pOpenLock->DestroyThis(); + } +} + +bool SqDriver::IsThreadSafe() +{ + return true; +} + +bool SqDriver::InitializeThreadSafety() +{ + /* sqlite should be thread safe if the locks are done right. + * we don't enable the "shared cache" because it can corrupt + * open databases! + */ + return true; +} + +void SqDriver::ShutdownThreadSafety() +{ + return; +} + +IdentityToken_t *SqDriver::GetIdentity() +{ + return myself->GetIdentity(); +} + +const char *SqDriver::GetProductName() +{ + return "SQLite"; +} + +const char *SqDriver::GetIdentifier() +{ + return "sqlite"; +} + +Handle_t SqDriver::GetHandle() +{ + if (m_Handle == BAD_HANDLE) + { + m_Handle = dbi->CreateHandle(DBHandle_Driver, this, myself->GetIdentity()); + } + + return m_Handle; +} + +inline bool IsPathSepChar(char c) +{ +#if defined PLATFORM_WINDOWS + return (c == '\\' || c == '/'); +#elif defined PLATFORM_LINUX + return (c == '/'); +#endif +} + +IDatabase *SqDriver::Connect(const DatabaseInfo *info, bool persistent, char *error, size_t maxlength) +{ + /* We wrap most of the open process in a mutex just to be safe */ + m_pOpenLock->Lock(); + + /* Format our path */ + char path[PLATFORM_MAX_PATH]; + size_t len = libsys->PathFormat(path, sizeof(path), "sqlite/%s", info->database); + + /* Chop any filename off */ + for (size_t i = len-1; + i >= 0 && i <= len-1; + i--) + { + if (IsPathSepChar(path[i])) + { + path[i] = '\0'; + break; + } + } + + /* Test the full path */ + char fullpath[PLATFORM_MAX_PATH]; + g_pSM->BuildPath(Path_SM, fullpath, sizeof(fullpath), "data/%s", path); + if (!libsys->IsPathDirectory(fullpath)) + { + /* Make sure the data folder exists */ + len = g_pSM->BuildPath(Path_SM, fullpath, sizeof(fullpath), "data"); + if (!libsys->IsPathDirectory(fullpath)) + { + if (!libsys->CreateFolder(fullpath)) + { + strncopy(error, "Could not create or open \"data\" folder\"", maxlength); + m_pOpenLock->Unlock(); + return NULL; + } + } + + /* The data folder exists - create each subdir as needed! */ + char *cur_ptr = path; + + do + { + /* Find the next suitable path */ + char *next_ptr = cur_ptr; + while (*next_ptr != '\0') + { + if (IsPathSepChar(*next_ptr)) + { + *next_ptr = '\0'; + next_ptr++; + break; + } + next_ptr++; + } + if (*next_ptr == '\0') + { + next_ptr = NULL; + } + len += libsys->PathFormat(&fullpath[len], sizeof(fullpath)-len, "/%s", cur_ptr); + if (!libsys->IsPathDirectory(fullpath) && !libsys->CreateFolder(fullpath)) + { + break; + } + cur_ptr = next_ptr; + } while (cur_ptr); + } + + /* Build the FINAL path. */ + g_pSM->BuildPath(Path_SM, fullpath, sizeof(fullpath), "data/sqlite/%s.sq3", info->database); + + /* If we're requesting a persistent connection, see if something is already open */ + if (persistent) + { + /* See if anything in the cache matches */ + List::iterator iter; + for (iter = m_Cache.begin(); iter != m_Cache.end(); iter++) + { + if ((*iter).path.compare(fullpath) == 0) + { + (*iter).db->IncReferenceCount(); + m_pOpenLock->Unlock(); + return (*iter).db; + } + } + } + + /* Try to open a new connection */ + sqlite3 *sql; + int err = sqlite3_open(fullpath, &sql); + if (err != SQLITE_OK) + { + strncopy(error, sqlite3_errmsg(sql), maxlength); + sqlite3_close(sql); + m_pOpenLock->Unlock(); + return NULL; + } + + SqDatabase *pdb = new SqDatabase(sql, persistent); + + if (persistent) + { + SqDbInfo pinfo; + pinfo.path = fullpath; + pinfo.db = pdb; + m_Cache.push_back(pinfo); + } + + m_pOpenLock->Unlock(); + + return pdb; +} + +void SqDriver::RemovePersistent(IDatabase *pdb) +{ + List::iterator iter; + for (iter = m_Cache.begin(); iter != m_Cache.end(); iter++) + { + if ((*iter).db == pdb) + { + iter = m_Cache.erase(iter); + return; + } + } +} diff --git a/extensions/sqlite/driver/SqDriver.h b/extensions/sqlite/driver/SqDriver.h new file mode 100644 index 00000000..229ba8ce --- /dev/null +++ b/extensions/sqlite/driver/SqDriver.h @@ -0,0 +1,73 @@ +/** + * vim: set ts=4 : + * =============================================================== + * SourceMod SQLite Driver Extension + * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved. + * =============================================================== + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Version: $Id$ + */ + +#ifndef _INCLUDE_SQLITE_SOURCEMOD_DRIVER_H_ +#define _INCLUDE_SQLITE_SOURCEMOD_DRIVER_H_ + +#include +#include +#include +#include +#include "sqlite-source/sqlite3.h" + +using namespace SourceMod; +using namespace SourceHook; + +struct SqDbInfo +{ + String path; + IDatabase *db; +}; + +/** + * Tee-hee.. sounds like "screw driver," except maybe if + * Elmer Fudd was saying it. + */ +class SqDriver : public IDBDriver +{ +public: + SqDriver(); + void Initialize(); + void Shutdown(); +public: + IDatabase *Connect(const DatabaseInfo *info, bool persistent, char *error, size_t maxlength); + const char *GetIdentifier(); + const char *GetProductName(); + Handle_t GetHandle(); + IdentityToken_t *GetIdentity(); + bool IsThreadSafe(); + bool InitializeThreadSafety(); + void ShutdownThreadSafety(); +public: + void RemovePersistent(IDatabase *pdb); +private: + Handle_t m_Handle; + IMutex *m_pOpenLock; + List m_Cache; +}; + +extern SqDriver g_SqDriver; + +unsigned int strncopy(char *dest, const char *src, size_t count); + +#endif //_INCLUDE_SQLITE_SOURCEMOD_DRIVER_H_ diff --git a/extensions/sqlite/driver/SqQuery.cpp b/extensions/sqlite/driver/SqQuery.cpp new file mode 100644 index 00000000..11525213 --- /dev/null +++ b/extensions/sqlite/driver/SqQuery.cpp @@ -0,0 +1,186 @@ +/** + * vim: set ts=4 : + * =============================================================== + * SourceMod SQLite Driver Extension + * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved. + * =============================================================== + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Version: $Id$ + */ + +#include "SqQuery.h" + +SqQuery::SqQuery(SqDatabase *parent, sqlite3_stmt *stmt) : + m_pParent(parent), m_pStmt(stmt), m_pResults(NULL), m_AffectedRows(0), m_InsertID(0) +{ + m_ParamCount = sqlite3_bind_parameter_count(m_pStmt); + m_pParent->IncReferenceCount(); +} + +SqQuery::~SqQuery() +{ + delete m_pResults; + sqlite3_finalize(m_pStmt); + m_pParent->Close(); +} + +IResultSet *SqQuery::GetResultSet() +{ + return m_pResults; +} + +bool SqQuery::FetchMoreResults() +{ + /* We never have multiple result sets */ + return false; +} + +void SqQuery::Destroy() +{ + delete this; +} + +bool SqQuery::BindParamFloat(unsigned int param, float f) +{ + /* SQLite is 1 indexed */ + param++; + + if (param > m_ParamCount) + { + return false; + } + + return (sqlite3_bind_double(m_pStmt, param, (double)f) == SQLITE_OK); +} + +bool SqQuery::BindParamNull(unsigned int param) +{ + /* SQLite is 1 indexed */ + param++; + + if (param > m_ParamCount) + { + return false; + } + + return (sqlite3_bind_null(m_pStmt, param) == SQLITE_OK); +} + +bool SqQuery::BindParamString(unsigned int param, const char *text, bool copy) +{ + /* SQLite is 1 indexed */ + param++; + + if (param > m_ParamCount) + { + return false; + } + + return (sqlite3_bind_text(m_pStmt, param, text, -1, copy ? SQLITE_TRANSIENT : SQLITE_STATIC) == SQLITE_OK); +} + +bool SqQuery::BindParamInt(unsigned int param, int num, bool signd/* =true */) +{ + /* SQLite is 1 indexed */ + param++; + + if (param > m_ParamCount) + { + return false; + } + + return (sqlite3_bind_int(m_pStmt, param, num) == SQLITE_OK); +} + +bool SqQuery::BindParamBlob(unsigned int param, const void *data, size_t length, bool copy) +{ + /* SQLite is 1 indexed */ + param++; + + if (param > m_ParamCount) + { + return false; + } + + return (sqlite3_bind_blob(m_pStmt, param, data, length, copy ? SQLITE_TRANSIENT : SQLITE_STATIC) == SQLITE_OK); +} + +sqlite3_stmt *SqQuery::GetStmt() +{ + return m_pStmt; +} + +bool SqQuery::Execute() +{ + int rc; + + /* If we've got results, throw them away */ + if (m_pResults) + { + m_pResults->ResetResultCount(); + } + + while ((rc = sqlite3_step(m_pStmt)) == SQLITE_ROW) + { + /* Delay creation as long as possible... */ + if (!m_pResults) + { + m_pResults = new SqResults(this); + } + m_pResults->PushResult(); + } + + sqlite3 *db = m_pParent->GetDb(); + if (rc != SQLITE_OK && rc != SQLITE_DONE && rc == sqlite3_errcode(db)) + { + /* Something happened... */ + m_LastErrorCode = rc; + m_LastError.assign(sqlite3_errmsg(db)); + m_AffectedRows = 0; + m_InsertID = 0; + } else { + m_LastErrorCode = SQLITE_OK; + m_AffectedRows = (unsigned int)sqlite3_changes(db); + m_InsertID = (unsigned int)sqlite3_last_insert_rowid(db); + } + + /* Reset everything for the next execute */ + sqlite3_reset(m_pStmt); + sqlite3_clear_bindings(m_pStmt); + + return (m_LastErrorCode == SQLITE_OK); +} + +const char *SqQuery::GetError(int *errCode/* =NULL */) +{ + if (errCode) + { + *errCode = m_LastErrorCode; + } + return m_LastError.c_str(); +} + +unsigned int SqQuery::GetAffectedRows() +{ + return m_AffectedRows; +} + +unsigned int SqQuery::GetInsertID() +{ + return m_InsertID; +} + + diff --git a/extensions/sqlite/driver/SqQuery.h b/extensions/sqlite/driver/SqQuery.h new file mode 100644 index 00000000..73f11f26 --- /dev/null +++ b/extensions/sqlite/driver/SqQuery.h @@ -0,0 +1,86 @@ +/** + * vim: set ts=4 : + * =============================================================== + * SourceMod SQLite Driver Extension + * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved. + * =============================================================== + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Version: $Id$ + */ + +#ifndef _INCLUDE_SQLITE_SOURCEMOD_QUERY_H_ +#define _INCLUDE_SQLITE_SOURCEMOD_QUERY_H_ + +#include "SqDatabase.h" +#include "SqResults.h" + +class SqQuery : + public IPreparedQuery +{ +public: + SqQuery(SqDatabase *parent, sqlite3_stmt *stmt); + ~SqQuery(); +public: //IQuery + IResultSet *GetResultSet(); + bool FetchMoreResults(); + void Destroy(); +public: //IPreparedQuery + bool BindParamInt(unsigned int param, int num, bool signd=true); + bool BindParamFloat(unsigned int param, float f); + bool BindParamNull(unsigned int param); + bool BindParamString(unsigned int param, const char *text, bool copy); + bool BindParamBlob(unsigned int param, const void *data, size_t length, bool copy); + bool Execute(); + const char *GetError(int *errCode=NULL); + unsigned int GetAffectedRows(); + unsigned int GetInsertID(); +public: //IResultSet + unsigned int GetRowCount(); + unsigned int GetFieldCount(); + const char *FieldNumToName(unsigned int columnId); + bool FieldNameToNum(const char *name, unsigned int *columnId); + bool MoreRows(); + IResultRow *FetchRow(); + IResultRow *CurrentRow(); + bool Rewind(); + DBType GetFieldType(unsigned int field); + DBType GetFieldDataType(unsigned int field); +public: //IResultRow + DBResult GetString(unsigned int columnId, const char **pString, size_t *length); + DBResult CopyString(unsigned int columnId, + char *buffer, + size_t maxlength, + size_t *written); + DBResult GetFloat(unsigned int columnId, float *pFloat); + DBResult GetInt(unsigned int columnId, int *pInt); + bool IsNull(unsigned int columnId); + size_t GetDataSize(unsigned int columnId); + DBResult GetBlob(unsigned int columnId, const void **pData, size_t *length); + DBResult CopyBlob(unsigned int columnId, void *buffer, size_t maxlength, size_t *written); +public: + sqlite3_stmt *GetStmt(); +private: + SqDatabase *m_pParent; + sqlite3_stmt *m_pStmt; + SqResults *m_pResults; + unsigned int m_ParamCount; + String m_LastError; + int m_LastErrorCode; + unsigned int m_AffectedRows; + unsigned int m_InsertID; +}; + +#endif //_INCLUDE_SQLITE_SOURCEMOD_QUERY_H_ diff --git a/extensions/sqlite/driver/SqResults.cpp b/extensions/sqlite/driver/SqResults.cpp new file mode 100644 index 00000000..50cab12f --- /dev/null +++ b/extensions/sqlite/driver/SqResults.cpp @@ -0,0 +1,474 @@ +/** + * vim: set ts=4 : + * =============================================================== + * SourceMod SQLite Driver Extension + * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved. + * =============================================================== + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Version: $Id$ + */ + +#include +#include "extension.h" +#include "SqResults.h" +#include "SqQuery.h" + +SqResults::SqResults(SqQuery *query) : + m_pStmt(query->GetStmt()), m_Strings(1024), + m_RowCount(0), m_MaxRows(0), m_Rows(NULL), + m_CurRow(0), m_NextRow(0) +{ + m_ColCount = sqlite3_column_count(m_pStmt); + if (m_ColCount) + { + m_ColNames = new String[m_ColCount]; + for (unsigned int i=0; i= m_ColCount) + { + return NULL; + } + + return m_ColNames[columnId].c_str(); +} + +bool SqResults::FieldNameToNum(const char *name, unsigned int *columnId) +{ + for (unsigned int i=0; iReset(); +} + +void SqResults::PushResult() +{ + /* First make sure we can fit one more row */ + if (m_RowCount + 1 > m_MaxRows) + { + /* Create a new array */ + if (!m_Rows) + { + m_MaxRows = 8; + m_Rows = (SqField *)malloc(sizeof(SqField) * m_ColCount * m_MaxRows); + } else { + m_MaxRows *= 2; + m_Rows = (SqField *)realloc(m_Rows, sizeof(SqField) * m_ColCount * m_MaxRows); + } + } + + SqField *row = &m_Rows[m_RowCount * m_ColCount]; + for (unsigned int i=0; iCreateMem(bytes, &pAddr); + memcpy(pAddr, pOrig, bytes); + } else { + row[i].u.idx = -1; + } + row[i].size = sqlite3_column_bytes(m_pStmt, i); + } else if (row[i].type == SQLITE_TEXT) { + const char *str = (const char *)sqlite3_column_text(m_pStmt, i); + if (str) + { + row[i].u.idx = m_Strings.AddString(str); + } else { + row[i].u.idx = -1; + } + row[i].size = sqlite3_column_bytes(m_pStmt, i); + } else { + row[i].size = 0; + } + } + + /* Finally, increase the row count */ + m_RowCount++; +} + +bool SqResults::MoreRows() +{ + return (m_CurRow < m_RowCount); +} + +IResultRow *SqResults::FetchRow() +{ + m_CurRow = m_NextRow; + if (m_CurRow >= m_RowCount) + { + return NULL; + } + m_NextRow++; + return this; +} + +IResultRow *SqResults::CurrentRow() +{ + if (!m_RowCount || m_CurRow >= m_RowCount) + { + return NULL; + } + return this; +} + +bool SqResults::Rewind() +{ + m_CurRow = 0; + m_NextRow = 0; + return true; +} + +SqField *SqResults::GetField(unsigned int col) +{ + if (m_CurRow >= m_RowCount || col >= m_ColCount) + { + return NULL; + } + + return &m_Rows[(m_CurRow * m_ColCount) + col]; +} + +DBType SqResults::GetFieldType(unsigned int field) +{ + /* Leaving unimplemented... */ + return DBType_Unknown; +} + +DBType SqResults::GetFieldDataType(unsigned int field) +{ + /* Leaving unimplemented... */ + return DBType_Unknown; +} + +DBResult SqResults::GetString(unsigned int columnId, const char **pString, size_t *_length) +{ + SqField *field = GetField(columnId); + if (!field) + { + return DBVal_Error; + } + + DBResult res = DBVal_Data; + const char *ptr = NULL; + size_t length = 0; + if (field->type == SQLITE_TEXT || field->type == SQLITE_BLOB) + { + ptr = m_Strings.GetString(field->u.idx); + length = field->size; + } else if (field->type == SQLITE_INTEGER) { + char number[24]; + field->size = UTIL_Format(number, sizeof(number), "%d", field->u.idx); + field->type = SQLITE_TEXT; + field->u.idx = m_Strings.AddString(number); + ptr = m_Strings.GetString(field->u.idx); + length = field->size; + } else if (field->type == SQLITE_FLOAT) { + char number[24]; + field->size = UTIL_Format(number, sizeof(number), "%f", field->u.f); + field->type = SQLITE_TEXT; + field->u.idx = m_Strings.AddString(number); + ptr = m_Strings.GetString(field->u.idx); + length = field->size; + } else if (field->type == SQLITE_NULL) { + res = DBVal_Null; + } + + if (!ptr) + { + ptr = ""; + } + + if (*pString) + { + *pString = ptr; + } + if (_length) + { + *_length = length; + } + + return res; +} + +DBResult SqResults::CopyString(unsigned int columnId, char *buffer, size_t maxlength, size_t *written) +{ + SqField *field = GetField(columnId); + if (!field) + { + return DBVal_Error; + } + + DBResult res = DBVal_Data; + if (field->type == SQLITE_TEXT || field->type == SQLITE_BLOB) + { + const char *ptr = m_Strings.GetString(field->u.idx); + if (!ptr) + { + ptr = ""; + field->type = SQLITE_TEXT; + res = DBVal_Null; + } + size_t wr; + if (field->type == SQLITE_TEXT) + { + wr = strncopy(buffer, ptr, maxlength); + } else if (field->type == SQLITE_BLOB) { + wr = (maxlength < field->size) ? maxlength : field->size; + memcpy(buffer, ptr, wr); + } + if (written) + { + *written = wr; + } + return res; + } else if (field->type == SQLITE_INTEGER) { + size_t wr = 0; + if (buffer) + { + wr = UTIL_Format(buffer, maxlength, "%d", field->u.idx); + } + if (written) + { + *written = wr; + } + return DBVal_Data; + } else if (field->type == SQLITE_FLOAT) { + size_t wr = 0; + if (buffer) + { + wr = UTIL_Format(buffer, maxlength, "%f", field->u.f); + } + if (written) + { + *written = wr; + } + return DBVal_Data; + } + + if (buffer) + { + strncopy(buffer, "", maxlength); + } + if (written) + { + *written = 0; + } + + return DBVal_Null; +} + +bool SqResults::IsNull(unsigned int columnId) +{ + SqField *field = GetField(columnId); + if (!field) + { + return true; + } + + return (field->type == SQLITE_NULL); +} + +unsigned int SqResults::GetDataSize(unsigned int columnId) +{ + SqField *field = GetField(columnId); + if (!field) + { + return 0; + } + + return field->size; +} + +DBResult SqResults::GetFloat(unsigned int columnId, float *pFloat) +{ + SqField *field = GetField(columnId); + if (!field) + { + return DBVal_Error; + } else if (field->type == SQLITE_BLOB) { + return DBVal_Error; + } + + float fVal = 0.0f; + if (field->type == SQLITE_FLOAT) + { + fVal = field->u.f; + } else if (field->type == SQLITE_TEXT) { + const char *ptr = m_Strings.GetString(field->u.idx); + if (ptr) + { + fVal = (float)atof(ptr); + } + } else if (field->type == SQLITE_INTEGER) { + fVal = (float)field->u.idx; + } + + if (pFloat) + { + *pFloat = fVal; + } + + return (field->type == SQLITE_NULL) ? DBVal_Null : DBVal_Data; +} + +DBResult SqResults::GetInt(unsigned int columnId, int *pInt) +{ + SqField *field = GetField(columnId); + if (!field) + { + return DBVal_Error; + } else if (field->type == SQLITE_BLOB) { + return DBVal_Error; + } + + int val = 0; + if (field->type == SQLITE_INTEGER) + { + val = field->u.idx; + } else if (field->type == SQLITE_TEXT) { + const char *ptr = m_Strings.GetString(field->u.idx); + if (ptr) + { + val = atoi(ptr); + } + } else if (field->type == SQLITE_FLOAT) { + val = (int)field->u.f; + } + + if (pInt) + { + *pInt = val; + } + + return (field->type == SQLITE_NULL) ? DBVal_Null : DBVal_Data; +} + +DBResult SqResults::GetBlob(unsigned int columnId, const void **pData, size_t *length) +{ + SqField *field = GetField(columnId); + if (!field) + { + return DBVal_Error; + } + + void *addr = NULL; + + if (field->type == SQLITE_TEXT || field->type == SQLITE_BLOB) + { + addr = m_pMemory->GetAddress(field->u.idx); + } else if (field->type == SQLITE_FLOAT || field->type == SQLITE_INTEGER) { + addr = &(field->u); + } + + if (pData) + { + *pData = addr; + } + + if (length) + { + *length = field->size; + } + + return (field->type == SQLITE_NULL) ? DBVal_Null : DBVal_Data; +} + +DBResult SqResults::CopyBlob(unsigned int columnId, void *buffer, size_t maxlength, size_t *written) +{ + SqField *field = GetField(columnId); + if (!field) + { + return DBVal_Error; + } + + void *addr = NULL; + + if (field->type == SQLITE_TEXT || field->type == SQLITE_BLOB) + { + addr = m_pMemory->GetAddress(field->u.idx); + } else if (field->type == SQLITE_FLOAT || field->type == SQLITE_INTEGER) { + addr = &(field->u); + } + + size_t toCopy = field->size > maxlength ? maxlength : field->size; + if (buffer && addr && toCopy) + { + memcpy(buffer, addr, toCopy); + } else { + toCopy = 0; + } + + if (written) + { + *written = toCopy; + } + + return (field->type == SQLITE_NULL) ? DBVal_Null : DBVal_Data; +} diff --git a/extensions/sqlite/driver/SqResults.h b/extensions/sqlite/driver/SqResults.h new file mode 100644 index 00000000..bf87a34f --- /dev/null +++ b/extensions/sqlite/driver/SqResults.h @@ -0,0 +1,92 @@ +/** + * vim: set ts=4 : + * =============================================================== + * SourceMod SQLite Driver Extension + * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved. + * =============================================================== + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Version: $Id$ + */ + +#ifndef _INCLUDE_SQLITE_SOURCEMOD_RESULT_SET_H_ +#define _INCLUDE_SQLITE_SOURCEMOD_RESULT_SET_H_ + +#include "SqDriver.h" +#include "sm_memtable.h" + +class SqQuery; + +struct SqField +{ + int type; + union + { + int idx; + float f; + } u; + size_t size; +}; + +class SqResults : + public IResultSet, + public IResultRow +{ + friend class SqQuery; +public: + SqResults(SqQuery *query); + ~SqResults(); +public: //IResultSet + unsigned int GetRowCount(); + unsigned int GetFieldCount(); + const char *FieldNumToName(unsigned int columnId); + bool FieldNameToNum(const char *name, unsigned int *columnId); + bool MoreRows(); + IResultRow *FetchRow(); + IResultRow *CurrentRow(); + bool Rewind(); + DBType GetFieldType(unsigned int field); + DBType GetFieldDataType(unsigned int field); +public: //IResultRow + DBResult GetString(unsigned int columnId, const char **pString, size_t *length); + DBResult CopyString(unsigned int columnId, + char *buffer, + size_t maxlength, + size_t *written); + DBResult GetFloat(unsigned int columnId, float *pFloat); + DBResult GetInt(unsigned int columnId, int *pInt); + bool IsNull(unsigned int columnId); + size_t GetDataSize(unsigned int columnId); + DBResult GetBlob(unsigned int columnId, const void **pData, size_t *length); + DBResult CopyBlob(unsigned int columnId, void *buffer, size_t maxlength, size_t *written); +public: + void ResetResultCount(); + void PushResult(); +private: + SqField *GetField(unsigned int col); +private: + sqlite3_stmt *m_pStmt; /** DOES NOT CHANGE */ + String *m_ColNames; /** DOES NOT CHANGE */ + unsigned int m_ColCount; /** DOES NOT CHANGE */ + unsigned int m_RowCount; + unsigned int m_MaxRows; + BaseMemTable *m_pMemory; /** DOES NOT CHANGE */ + BaseStringTable m_Strings; /** DOES NOT CHANGE */ + SqField *m_Rows; + unsigned int m_CurRow; + unsigned int m_NextRow; +}; + +#endif //_INCLUDE_SQLITE_SOURCEMOD_RESULT_SET_H_ diff --git a/extensions/sqlite/driver/sqlite-source.h b/extensions/sqlite/driver/sqlite-source.h new file mode 100644 index 00000000..e69de29b diff --git a/extensions/sqlite/extension.cpp b/extensions/sqlite/extension.cpp new file mode 100644 index 00000000..53455e8d --- /dev/null +++ b/extensions/sqlite/extension.cpp @@ -0,0 +1,64 @@ +/** + * vim: set ts=4 : + * =============================================================== + * SourceMod SQLite Driver Extension + * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved. + * =============================================================== + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Version: $Id$ + */ + +#include "extension.h" +#include "driver/SqDriver.h" + +/** + * @file extension.cpp + * @brief Implement extension code here. + */ + +SqliteExt g_SqliteExt; /**< Global singleton for extension's main interface */ + +SMEXT_LINK(&g_SqliteExt); + +bool SqliteExt::SDK_OnLoad(char *error, size_t maxlength, bool late) +{ + g_SqDriver.Initialize(); + dbi->AddDriver(&g_SqDriver); + + return true; +} + +void SqliteExt::SDK_OnUnload() +{ + dbi->RemoveDriver(&g_SqDriver); + g_SqDriver.Shutdown(); +} + +size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + size_t len = vsnprintf(buffer, maxlength, fmt, ap); + va_end(ap); + + if (len >= maxlength) + { + buffer[maxlength - 1] = '\0'; + return (maxlength - 1); + } else { + return len; + } +} diff --git a/extensions/sqlite/extension.h b/extensions/sqlite/extension.h new file mode 100644 index 00000000..ca1a5abf --- /dev/null +++ b/extensions/sqlite/extension.h @@ -0,0 +1,113 @@ +/** + * vim: set ts=4 : + * =============================================================== + * SourceMod SQLite Driver Extension + * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved. + * =============================================================== + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Version: $Id$ + */ + +#ifndef _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ +#define _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ + +/** + * @file extension.h + * @brief Sample extension code header. + */ + +#include "smsdk_ext.h" + + +/** + * @brief Sample implementation of the SDK Extension. + * Note: Uncomment one of the pre-defined virtual functions in order to use it. + */ +class SqliteExt : public SDKExtension +{ +public: + /** + * @brief This is called after the initial loading sequence has been processed. + * + * @param error Error message buffer. + * @param maxlength Size of error message buffer. + * @param late Whether or not the module was loaded after map load. + * @return True to succeed loading, false to fail. + */ + virtual bool SDK_OnLoad(char *error, size_t maxlength, bool late); + + /** + * @brief This is called right before the extension is unloaded. + */ + virtual void SDK_OnUnload(); + + /** + * @brief This is called once all known extensions have been loaded. + * Note: It is is a good idea to add natives here, if any are provided. + */ + //virtual void SDK_OnAllLoaded(); + + /** + * @brief Called when the pause state is changed. + */ + //virtual void SDK_OnPauseChange(bool paused); + + /** + * @brief this is called when Core wants to know if your extension is working. + * + * @param error Error message buffer. + * @param maxlength Size of error message buffer. + * @return True if working, false otherwise. + */ + //virtual bool QueryRunning(char *error, size_t maxlength); +public: +#if defined SMEXT_CONF_METAMOD + /** + * @brief Called when Metamod is attached, before the extension version is called. + * + * @param error Error buffer. + * @param maxlength Maximum size of error buffer. + * @param late Whether or not Metamod considers this a late load. + * @return True to succeed, false to fail. + */ + //virtual bool SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlength, bool late); + + /** + * @brief Called when Metamod is detaching, after the extension version is called. + * NOTE: By default this is blocked unless sent from SourceMod. + * + * @param error Error buffer. + * @param maxlength Maximum size of error buffer. + * @return True to succeed, false to fail. + */ + //virtual bool SDK_OnMetamodUnload(char *error, size_t maxlength); + + /** + * @brief Called when Metamod's pause state is changing. + * NOTE: By default this is blocked unless sent from SourceMod. + * + * @param paused Pause state being set. + * @param error Error buffer. + * @param maxlength Maximum size of error buffer. + * @return True to succeed, false to fail. + */ + //virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlength); +#endif +}; + +size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...); + +#endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_ diff --git a/extensions/sqlite/msvc8/sm_sqlite.sln b/extensions/sqlite/msvc8/sm_sqlite.sln new file mode 100644 index 00000000..1805b0c9 --- /dev/null +++ b/extensions/sqlite/msvc8/sm_sqlite.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sm_sqlite", "sm_sqlite.vcproj", "{B3E797CF-4E77-4C9D-B8A8-7589B6902206}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B3E797CF-4E77-4C9D-B8A8-7589B6902206}.Debug|Win32.ActiveCfg = Debug|Win32 + {B3E797CF-4E77-4C9D-B8A8-7589B6902206}.Debug|Win32.Build.0 = Debug|Win32 + {B3E797CF-4E77-4C9D-B8A8-7589B6902206}.Release|Win32.ActiveCfg = Release|Win32 + {B3E797CF-4E77-4C9D-B8A8-7589B6902206}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/extensions/sqlite/msvc8/sm_sqlite.vcproj b/extensions/sqlite/msvc8/sm_sqlite.vcproj new file mode 100644 index 00000000..06a1168d --- /dev/null +++ b/extensions/sqlite/msvc8/sm_sqlite.vcproj @@ -0,0 +1,860 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/extensions/sqlite/sdk/smsdk_config.h b/extensions/sqlite/sdk/smsdk_config.h new file mode 100644 index 00000000..ad1d89a2 --- /dev/null +++ b/extensions/sqlite/sdk/smsdk_config.h @@ -0,0 +1,62 @@ +/** + * vim: set ts=4 : + * =============================================================== + * SourceMod, Copyright (C) 2004-2007 AlliedModders LLC. + * All rights reserved. + * =============================================================== + * + * This file is part of the SourceMod/SourcePawn SDK. This file may only be + * used or modified under the Terms and Conditions of its License Agreement, + * which is found in public/licenses/LICENSE.txt. As of this notice, derivative + * works must be licensed under the GNU General Public License (version 2 or + * greater). A copy of the GPL is included under public/licenses/GPL.txt. + * + * To view the latest information, see: http://www.sourcemod.net/license.php + * + * Version: $Id$ + */ + +#ifndef _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ +#define _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ + +#include "svn_version.h" + +/** + * @file smsdk_config.h + * @brief Contains macros for configuring basic extension information. + */ + +/* Basic information exposed publicly */ +#define SMEXT_CONF_NAME "SQLite" +#define SMEXT_CONF_DESCRIPTION "SQLite Driver" +#define SMEXT_CONF_VERSION SVN_FULL_VERSION +#define SMEXT_CONF_AUTHOR "AlliedModders" +#define SMEXT_CONF_URL "http://www.sourcemod.net/" +#define SMEXT_CONF_LOGTAG "SQLITE" +#define SMEXT_CONF_LICENSE "GPL" +#define SMEXT_CONF_DATESTRING __DATE__ + +/** + * @brief Exposes plugin's main interface. + */ +#define SMEXT_LINK(name) SDKExtension *g_pExtensionIface = name; + +/** + * @brief Sets whether or not this plugin required Metamod. + * NOTE: Uncomment to enable, comment to disable. + */ +//#define SMEXT_CONF_METAMOD + +/** Enable interfaces you want to use here by uncommenting lines */ +//#define SMEXT_ENABLE_FORWARDSYS +//#define SMEXT_ENABLE_HANDLESYS +//#define SMEXT_ENABLE_PLAYERHELPERS +#define SMEXT_ENABLE_DBMANAGER +//#define SMEXT_ENABLE_GAMECONF +//#define SMEXT_ENABLE_MEMUTILS +//#define SMEXT_ENABLE_GAMEHELPERS +//#define SMEXT_ENABLE_TIMERSYS +#define SMEXT_ENABLE_THREADER +#define SMEXT_ENABLE_LIBSYS + +#endif // _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_ diff --git a/extensions/sqlite/sdk/smsdk_ext.cpp b/extensions/sqlite/sdk/smsdk_ext.cpp new file mode 100644 index 00000000..c6bf694d --- /dev/null +++ b/extensions/sqlite/sdk/smsdk_ext.cpp @@ -0,0 +1,403 @@ +/** + * vim: set ts=4 : + * =============================================================== + * SourceMod, Copyright (C) 2004-2007 AlliedModders LLC. + * All rights reserved. + * =============================================================== + * + * This file is part of the SourceMod/SourcePawn SDK. This file may only be + * used or modified under the Terms and Conditions of its License Agreement, + * which is found in public/licenses/LICENSE.txt. As of this notice, derivative + * works must be licensed under the GNU General Public License (version 2 or + * greater). A copy of the GPL is included under public/licenses/GPL.txt. + * + * To view the latest information, see: http://www.sourcemod.net/license.php + * + * Version: $Id$ + */ + +#include +#include +#include "smsdk_ext.h" + +/** + * @file smsdk_ext.cpp + * @brief Contains wrappers for making Extensions easier to write. + */ + +IExtension *myself = NULL; /**< Ourself */ +IShareSys *g_pShareSys = NULL; /**< Share system */ +IShareSys *sharesys = NULL; /**< Share system */ +ISourceMod *g_pSM = NULL; /**< SourceMod helpers */ +ISourceMod *smutils = NULL; /**< SourceMod helpers */ + +#if defined SMEXT_ENABLE_FORWARDSYS +IForwardManager *g_pForwards = NULL; /**< Forward system */ +IForwardManager *forwards = NULL; /**< Forward system */ +#endif +#if defined SMEXT_ENABLE_HANDLESYS +IHandleSys *g_pHandleSys = NULL; /**< Handle system */ +IHandleSys *handlesys = NULL; /**< Handle system */ +#endif +#if defined SMEXT_ENABLE_PLAYERHELPERS +IPlayerManager *playerhelpers = NULL; /**< Player helpers */ +#endif //SMEXT_ENABLE_PLAYERHELPERS +#if defined SMEXT_ENABLE_DBMANAGER +IDBManager *dbi = NULL; /**< DB Manager */ +#endif //SMEXT_ENABLE_DBMANAGER +#if defined SMEXT_ENABLE_GAMECONF +IGameConfigManager *gameconfs = NULL; /**< Game config manager */ +#endif //SMEXT_ENABLE_DBMANAGER +#if defined SMEXT_ENABLE_MEMUTILS +IMemoryUtils *memutils = NULL; +#endif //SMEXT_ENABLE_DBMANAGER +#if defined SMEXT_ENABLE_GAMEHELPERS +IGameHelpers *gamehelpers = NULL; +#endif +#if defined SMEXT_ENABLE_TIMERSYS +ITimerSystem *timersys = NULL; +#endif +#if defined SMEXT_ENABLE_ADTFACTORY +IADTFactory *adtfactory = NULL; +#endif +#if defined SMEXT_ENABLE_THREADER +IThreader *threader = NULL; +#endif +#if defined SMEXT_ENABLE_LIBSYS +ILibrarySys *libsys = NULL; +#endif + +/** Exports the main interface */ +PLATFORM_EXTERN_C IExtensionInterface *GetSMExtAPI() +{ + return g_pExtensionIface; +} + +SDKExtension::SDKExtension() +{ +#if defined SMEXT_CONF_METAMOD + m_SourceMMLoaded = false; + m_WeAreUnloaded = false; + m_WeGotPauseChange = false; +#endif +} + +bool SDKExtension::OnExtensionLoad(IExtension *me, IShareSys *sys, char *error, size_t maxlength, bool late) +{ + g_pShareSys = sharesys = sys; + myself = me; + +#if defined SMEXT_CONF_METAMOD + m_WeAreUnloaded = true; + + if (!m_SourceMMLoaded) + { + if (error) + { + snprintf(error, maxlength, "Metamod attach failed"); + } + return false; + } +#endif + SM_GET_IFACE(SOURCEMOD, g_pSM); + smutils = g_pSM; +#if defined SMEXT_ENABLE_HANDLESYS + SM_GET_IFACE(HANDLESYSTEM, g_pHandleSys); + handlesys = g_pHandleSys; +#endif +#if defined SMEXT_ENABLE_FORWARDSYS + SM_GET_IFACE(FORWARDMANAGER, g_pForwards); + forwards = g_pForwards; +#endif +#if defined SMEXT_ENABLE_PLAYERHELPERS + SM_GET_IFACE(PLAYERMANAGER, playerhelpers); +#endif +#if defined SMEXT_ENABLE_DBMANAGER + SM_GET_IFACE(DBI, dbi); +#endif +#if defined SMEXT_ENABLE_GAMECONF + SM_GET_IFACE(GAMECONFIG, gameconfs); +#endif +#if defined SMEXT_ENABLE_MEMUTILS + SM_GET_IFACE(MEMORYUTILS, memutils); +#endif +#if defined SMEXT_ENABLE_GAMEHELPERS + SM_GET_IFACE(GAMEHELPERS, gamehelpers); +#endif +#if defined SMEXT_ENABLE_TIMERSYS + SM_GET_IFACE(TIMERSYS, timersys); +#endif +#if defined SMEXT_ENABLE_ADTFACTORY + SM_GET_IFACE(ADTFACTORY, adtfactory); +#endif +#if defined SMEXT_ENABLE_THREADER + SM_GET_IFACE(THREADER, threader); +#endif +#if defined SMEXT_ENABLE_LIBSYS + SM_GET_IFACE(LIBRARYSYS, libsys); +#endif + + if (SDK_OnLoad(error, maxlength, late)) + { +#if defined SMEXT_CONF_METAMOD + m_WeAreUnloaded = true; +#endif + return true; + } + + return false; +} + +bool SDKExtension::IsMetamodExtension() +{ +#if defined SMEXT_CONF_METAMOD + return true; +#else + return false; +#endif +} + +void SDKExtension::OnExtensionPauseChange(bool state) +{ +#if defined SMEXT_CONF_METAMOD + m_WeGotPauseChange = true; +#endif + SDK_OnPauseChange(state); +} + +void SDKExtension::OnExtensionsAllLoaded() +{ + SDK_OnAllLoaded(); +} + +void SDKExtension::OnExtensionUnload() +{ +#if defined SMEXT_CONF_METAMOD + m_WeAreUnloaded = true; +#endif + SDK_OnUnload(); +} + +const char *SDKExtension::GetExtensionAuthor() +{ + return SMEXT_CONF_AUTHOR; +} + +const char *SDKExtension::GetExtensionDateString() +{ + return SMEXT_CONF_DATESTRING; +} + +const char *SDKExtension::GetExtensionDescription() +{ + return SMEXT_CONF_DESCRIPTION; +} + +const char *SDKExtension::GetExtensionVerString() +{ + return SMEXT_CONF_VERSION; +} + +const char *SDKExtension::GetExtensionName() +{ + return SMEXT_CONF_NAME; +} + +const char *SDKExtension::GetExtensionTag() +{ + return SMEXT_CONF_LOGTAG; +} + +const char *SDKExtension::GetExtensionURL() +{ + return SMEXT_CONF_URL; +} + +bool SDKExtension::SDK_OnLoad(char *error, size_t maxlength, bool late) +{ + return true; +} + +void SDKExtension::SDK_OnUnload() +{ +} + +void SDKExtension::SDK_OnPauseChange(bool paused) +{ +} + +void SDKExtension::SDK_OnAllLoaded() +{ +} + +#if defined SMEXT_CONF_METAMOD + +PluginId g_PLID = 0; /**< Metamod plugin ID */ +ISmmPlugin *g_PLAPI = NULL; /**< Metamod plugin API */ +SourceHook::ISourceHook *g_SHPtr = NULL; /**< SourceHook pointer */ +ISmmAPI *g_SMAPI = NULL; /**< SourceMM API pointer */ + +IVEngineServer *engine = NULL; /**< IVEngineServer pointer */ +IServerGameDLL *gamedll = NULL; /**< IServerGameDLL pointer */ + +/** Exposes the extension to Metamod */ +SMM_API void *PL_EXPOSURE(const char *name, int *code) +{ + if (name && !strcmp(name, PLAPI_NAME)) + { + if (code) + { + *code = IFACE_OK; + } + return static_cast(g_pExtensionIface); + } + + if (code) + { + *code = IFACE_FAILED; + } + + return NULL; +} + +bool SDKExtension::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late) +{ + PLUGIN_SAVEVARS(); + + GET_V_IFACE_ANY(serverFactory, gamedll, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL); + GET_V_IFACE_CURRENT(engineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER); + + m_SourceMMLoaded = true; + + return SDK_OnMetamodLoad(ismm, error, maxlen, late); +} + +bool SDKExtension::Unload(char *error, size_t maxlen) +{ + if (!m_WeAreUnloaded) + { + if (error) + { + snprintf(error, maxlen, "This extension must be unloaded by SourceMod."); + } + return false; + } + + return SDK_OnMetamodUnload(error, maxlen); +} + +bool SDKExtension::Pause(char *error, size_t maxlen) +{ + if (!m_WeGotPauseChange) + { + if (error) + { + snprintf(error, maxlen, "This extension must be paused by SourceMod."); + } + return false; + } + + m_WeGotPauseChange = false; + + return SDK_OnMetamodPauseChange(true, error, maxlen); +} + +bool SDKExtension::Unpause(char *error, size_t maxlen) +{ + if (!m_WeGotPauseChange) + { + if (error) + { + snprintf(error, maxlen, "This extension must be unpaused by SourceMod."); + } + return false; + } + + m_WeGotPauseChange = false; + + return SDK_OnMetamodPauseChange(false, error, maxlen); +} + +const char *SDKExtension::GetAuthor() +{ + return GetExtensionAuthor(); +} + +const char *SDKExtension::GetDate() +{ + return GetExtensionDateString(); +} + +const char *SDKExtension::GetDescription() +{ + return GetExtensionDescription(); +} + +const char *SDKExtension::GetLicense() +{ + return SMEXT_CONF_LICENSE; +} + +const char *SDKExtension::GetLogTag() +{ + return GetExtensionTag(); +} + +const char *SDKExtension::GetName() +{ + return GetExtensionName(); +} + +const char *SDKExtension::GetURL() +{ + return GetExtensionURL(); +} + +const char *SDKExtension::GetVersion() +{ + return GetExtensionVerString(); +} + +bool SDKExtension::SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlength, bool late) +{ + return true; +} + +bool SDKExtension::SDK_OnMetamodUnload(char *error, size_t maxlength) +{ + return true; +} + +bool SDKExtension::SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlength) +{ + return true; +} + +#endif + +/* Overload a few things to prevent libstdc++ linking */ +#if defined __linux__ +extern "C" void __cxa_pure_virtual(void) +{ +} + +void *operator new(size_t size) +{ + return malloc(size); +} + +void *operator new[](size_t size) +{ + return malloc(size); +} + +void operator delete(void *ptr) +{ + free(ptr); +} + +void operator delete[](void * ptr) +{ + free(ptr); +} +#endif diff --git a/extensions/sqlite/sdk/smsdk_ext.h b/extensions/sqlite/sdk/smsdk_ext.h new file mode 100644 index 00000000..1615b9ee --- /dev/null +++ b/extensions/sqlite/sdk/smsdk_ext.h @@ -0,0 +1,279 @@ +/** + * vim: set ts=4 : + * =============================================================== + * SourceMod, Copyright (C) 2004-2007 AlliedModders LLC. + * All rights reserved. + * =============================================================== + * + * This file is part of the SourceMod/SourcePawn SDK. This file may only be + * used or modified under the Terms and Conditions of its License Agreement, + * which is found in public/licenses/LICENSE.txt. As of this notice, derivative + * works must be licensed under the GNU General Public License (version 2 or + * greater). A copy of the GPL is included under public/licenses/GPL.txt. + * + * To view the latest information, see: http://www.sourcemod.net/license.php + * + * Version: $Id$ + */ + +#ifndef _INCLUDE_SOURCEMOD_EXTENSION_BASESDK_H_ +#define _INCLUDE_SOURCEMOD_EXTENSION_BASESDK_H_ + +/** + * @file smsdk_ext.h + * @brief Contains wrappers for making Extensions easier to write. + */ + +#include "smsdk_config.h" +#include +#include +#include +#include +#include +#if defined SMEXT_ENABLE_FORWARDSYS +#include +#endif //SMEXT_ENABLE_FORWARDSYS +#if defined SMEXT_ENABLE_PLAYERHELPERS +#include +#endif //SMEXT_ENABLE_PlAYERHELPERS +#if defined SMEXT_ENABLE_DBMANAGER +#include +#endif //SMEXT_ENABLE_DBMANAGER +#if defined SMEXT_ENABLE_GAMECONF +#include +#endif +#if defined SMEXT_ENABLE_MEMUTILS +#include +#endif +#if defined SMEXT_ENABLE_GAMEHELPERS +#include +#endif +#if defined SMEXT_ENABLE_TIMERSYS +#include +#endif +#if defined SMEXT_ENABLE_ADTFACTORY +#include +#endif +#if defined SMEXT_ENABLE_THREADER +#include +#endif +#if defined SMEXT_ENABLE_LIBSYS +#include +#endif + +#if defined SMEXT_CONF_METAMOD +#include +#include +#endif + +using namespace SourceMod; +using namespace SourcePawn; + +class SDKExtension : +#if defined SMEXT_CONF_METAMOD + public ISmmPlugin, +#endif + public IExtensionInterface +{ +public: + /** Constructor */ + SDKExtension(); +public: + /** + * @brief This is called after the initial loading sequence has been processed. + * + * @param error Error message buffer. + * @param maxlength Size of error message buffer. + * @param late Whether or not the module was loaded after map load. + * @return True to succeed loading, false to fail. + */ + virtual bool SDK_OnLoad(char *error, size_t maxlength, bool late); + + /** + * @brief This is called right before the extension is unloaded. + */ + virtual void SDK_OnUnload(); + + /** + * @brief This is called once all known extensions have been loaded. + */ + virtual void SDK_OnAllLoaded(); + + /** + * @brief Called when the pause state is changed. + */ + virtual void SDK_OnPauseChange(bool paused); + +#if defined SMEXT_CONF_METAMOD + /** + * @brief Called when Metamod is attached, before the extension version is called. + * + * @param error Error buffer. + * @param maxlength Maximum size of error buffer. + * @param late Whether or not Metamod considers this a late load. + * @return True to succeed, false to fail. + */ + virtual bool SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlength, bool late); + + /** + * @brief Called when Metamod is detaching, after the extension version is called. + * NOTE: By default this is blocked unless sent from SourceMod. + * + * @param error Error buffer. + * @param maxlength Maximum size of error buffer. + * @return True to succeed, false to fail. + */ + virtual bool SDK_OnMetamodUnload(char *error, size_t maxlength); + + /** + * @brief Called when Metamod's pause state is changing. + * NOTE: By default this is blocked unless sent from SourceMod. + * + * @param paused Pause state being set. + * @param error Error buffer. + * @param maxlength Maximum size of error buffer. + * @return True to succeed, false to fail. + */ + virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlength); +#endif + +public: //IExtensionInterface + virtual bool OnExtensionLoad(IExtension *me, IShareSys *sys, char *error, size_t maxlength, bool late); + virtual void OnExtensionUnload(); + virtual void OnExtensionsAllLoaded(); + + /** Returns whether or not this is a Metamod-based extension */ + virtual bool IsMetamodExtension(); + + /** + * @brief Called when the pause state changes. + * + * @param state True if being paused, false if being unpaused. + */ + virtual void OnExtensionPauseChange(bool state); + + /** Returns name */ + virtual const char *GetExtensionName(); + /** Returns URL */ + virtual const char *GetExtensionURL(); + /** Returns log tag */ + virtual const char *GetExtensionTag(); + /** Returns author */ + virtual const char *GetExtensionAuthor(); + /** Returns version string */ + virtual const char *GetExtensionVerString(); + /** Returns description string */ + virtual const char *GetExtensionDescription(); + /** Returns date string */ + virtual const char *GetExtensionDateString(); +#if defined SMEXT_CONF_METAMOD +public: //ISmmPlugin + /** Called when the extension is attached to Metamod. */ + virtual bool Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlength, bool late); + /** Returns the author to MM */ + virtual const char *GetAuthor(); + /** Returns the name to MM */ + virtual const char *GetName(); + /** Returns the description to MM */ + virtual const char *GetDescription(); + /** Returns the URL to MM */ + virtual const char *GetURL(); + /** Returns the license to MM */ + virtual const char *GetLicense(); + /** Returns the version string to MM */ + virtual const char *GetVersion(); + /** Returns the date string to MM */ + virtual const char *GetDate(); + /** Returns the logtag to MM */ + virtual const char *GetLogTag(); + /** Called on unload */ + virtual bool Unload(char *error, size_t maxlength); + /** Called on pause */ + virtual bool Pause(char *error, size_t maxlength); + /** Called on unpause */ + virtual bool Unpause(char *error, size_t maxlength); +private: + bool m_SourceMMLoaded; + bool m_WeAreUnloaded; + bool m_WeGotPauseChange; +#endif +}; + +extern SDKExtension *g_pExtensionIface; +extern IExtension *myself; + +extern IShareSys *g_pShareSys; +extern IShareSys *sharesys; /* Note: Newer name */ +extern ISourceMod *g_pSM; +extern ISourceMod *smutils; /* Note: Newer name */ + +/* Optional interfaces are below */ +#if defined SMEXT_ENABLE_FORWARDSYS +extern IForwardManager *g_pForwards; +extern IForwardManager *forwards; /* Note: Newer name */ +#endif //SMEXT_ENABLE_FORWARDSYS +#if defined SMEXT_ENABLE_HANDLESYS +extern IHandleSys *g_pHandleSys; +extern IHandleSys *handlesys; /* Note: Newer name */ +#endif //SMEXT_ENABLE_HANDLESYS +#if defined SMEXT_ENABLE_PLAYERHELPERS +extern IPlayerManager *playerhelpers; +#endif //SMEXT_ENABLE_PLAYERHELPERS +#if defined SMEXT_ENABLE_DBMANAGER +extern IDBManager *dbi; +#endif //SMEXT_ENABLE_DBMANAGER +#if defined SMEXT_ENABLE_GAMECONF +extern IGameConfigManager *gameconfs; +#endif //SMEXT_ENABLE_DBMANAGER +#if defined SMEXT_ENABLE_MEMUTILS +extern IMemoryUtils *memutils; +#endif +#if defined SMEXT_ENABLE_GAMEHELPERS +extern IGameHelpers *gamehelpers; +#endif +#if defined SMEXT_ENABLE_TIMERSYS +extern ITimerSystem *timersys; +#endif +#if defined SMEXT_ENABLE_ADTFACTORY +extern IADTFactory *adtfactory; +#endif +#if defined SMEXT_ENABLE_THREADER +extern IThreader *threader; +#endif +#if defined SMEXT_ENABLE_LIBSYS +extern ILibrarySys *libsys; +#endif + +#if defined SMEXT_CONF_METAMOD +PLUGIN_GLOBALVARS(); +extern IVEngineServer *engine; +extern IServerGameDLL *gamedll; +#endif + +/** Creates a SourceMod interface macro pair */ +#define SM_MKIFACE(name) SMINTERFACE_##name##_NAME, SMINTERFACE_##name##_VERSION +/** Automates retrieving SourceMod interfaces */ +#define SM_GET_IFACE(prefix, addr) \ + if (!g_pShareSys->RequestInterface(SM_MKIFACE(prefix), myself, (SMInterface **)&addr)) \ + { \ + if (error) \ + { \ + snprintf(error, maxlength, "Could not find interface: %s (version: %d)", SMINTERFACE_##prefix##_NAME, SMINTERFACE_##prefix##_VERSION); \ + return false; \ + } \ + } +/** Automates retrieving SourceMod interfaces when needed outside of SDK_OnLoad() */ +#define SM_GET_LATE_IFACE(prefix, addr) \ + g_pShareSys->RequestInterface(SM_MKIFACE(prefix), myself, (SMInterface **)&addr) +/** Validates a SourceMod interface pointer */ +#define SM_CHECK_IFACE(prefix, addr) \ + if (!addr) \ + { \ + if (error) \ + { \ + snprintf(error, maxlength, "Could not find interface: %s", SMINTERFACE_##prefix##_NAME); \ + return false; \ + } \ + } + +#endif // _INCLUDE_SOURCEMOD_EXTENSION_BASESDK_H_ diff --git a/extensions/sqlite/sm_memtable.cpp b/extensions/sqlite/sm_memtable.cpp new file mode 100644 index 00000000..3adda916 --- /dev/null +++ b/extensions/sqlite/sm_memtable.cpp @@ -0,0 +1,104 @@ +/** + * vim: set ts=4 : + * =============================================================== + * SourceMod SQLite Driver Extension + * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved. + * =============================================================== + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Version: $Id$ + */ + +#include +#include +#include "sm_memtable.h" + +BaseMemTable::BaseMemTable(unsigned int init_size) +{ + membase = (unsigned char *)malloc(init_size); + size = init_size; + tail = 0; +} + +BaseMemTable::~BaseMemTable() +{ + free(membase); + membase = NULL; +} + +int BaseMemTable::CreateMem(unsigned int addsize, void **addr) +{ + int idx = (int)tail; + + while (tail + addsize >= size) + { + size *= 2; + membase = (unsigned char *)realloc(membase, size); + } + + tail += addsize; + + if (addr) + { + *addr = (void *)&membase[idx]; + } + + return idx; +} + +void *BaseMemTable::GetAddress(int index) +{ + if (index < 0 || (unsigned int)index >= tail) + { + return NULL; + } + + return &membase[index]; +} + +void BaseMemTable::Reset() +{ + tail = 0; +} + +BaseStringTable::BaseStringTable(unsigned int init_size) : m_table(init_size) +{ +} + +BaseStringTable::~BaseStringTable() +{ +} + +int BaseStringTable::AddString(const char *string) +{ + size_t len = strlen(string) + 1; + int idx; + char *addr; + + idx = m_table.CreateMem(len, (void **)&addr); + strcpy(addr, string); + + return idx; +} + +/*const char *BaseStringTable::GetString(int str) +{ + return (const char *)m_table.GetAddress(str); +}*/ + +void BaseStringTable::Reset() +{ + m_table.Reset(); +} diff --git a/extensions/sqlite/sm_memtable.h b/extensions/sqlite/sm_memtable.h new file mode 100644 index 00000000..49884fe0 --- /dev/null +++ b/extensions/sqlite/sm_memtable.h @@ -0,0 +1,97 @@ +/** + * vim: set ts=4 : + * =============================================================== + * SourceMod SQLite Driver Extension + * Copyright (C) 2004-2007 AlliedModders LLC. All rights reserved. + * =============================================================== + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Version: $Id$ + */ + +#ifndef _INCLUDE_SOURCEMOD_CORE_STRINGTABLE_H_ +#define _INCLUDE_SOURCEMOD_CORE_STRINGTABLE_H_ + +class BaseMemTable +{ +public: + BaseMemTable(unsigned int init_size); + ~BaseMemTable(); +public: + /** + * Allocates 'size' bytes of memory. + * Optionally outputs the address through 'addr'. + * Returns an index >= 0 on success, < 0 on failure. + */ + int CreateMem(unsigned int size, void **addr); + + /** + * Given an index into the memory table, returns its address. + * Returns NULL if invalid. + */ + void *GetAddress(int index); + + /** + * Scraps the memory table. For caching purposes, the memory + * is not freed, however subsequent calls to CreateMem() will + * begin at the first index again. + */ + void Reset(); + + +private: + unsigned char *membase; + unsigned int size; + unsigned int tail; +}; + +class BaseStringTable +{ +public: + BaseStringTable(unsigned int init_size); + ~BaseStringTable(); +public: + /** + * Adds a string to the string table and returns its index. + */ + int AddString(const char *string); + + /** + * Given an index into the string table, returns the associated string. + */ + inline const char *GetString(int str) + { + return (const char *)m_table.GetAddress(str); + } + + /** + * Scraps the string table. For caching purposes, the memory + * is not freed, however subsequent calls to AddString() will + * begin at the first index again. + */ + void Reset(); + + /** + * Returns the parent BaseMemTable that this string table uses. + */ + inline BaseMemTable *GetMemTable() + { + return &m_table; + } +private: + BaseMemTable m_table; +}; + +#endif //_INCLUDE_SOURCEMOD_CORE_STRINGTABLE_H_ diff --git a/extensions/sqlite/sqlite-source/alter.c b/extensions/sqlite/sqlite-source/alter.c new file mode 100644 index 00000000..c473a52d --- /dev/null +++ b/extensions/sqlite/sqlite-source/alter.c @@ -0,0 +1,609 @@ +/* +** 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$ +*/ +#include "sqliteInt.h" +#include + +/* +** 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 - or "USING" TK_USING. + */ + if( zSql ){ + do { + if( !*zCsr ){ + /* Ran out of input before finding an opening bracket. Return NULL. */ + return; + } + + /* 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 && token!=TK_USING ); + + 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 { + + if( !*zCsr ){ + /* Ran out of input before finding the table name. Return NULL. */ + return; + } + + /* 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; idb->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 */ + int nTabName; /* Number of UTF-8 characters in zTabName */ + const char *zTabName; /* Original name of the table */ + Vdbe *v; +#ifndef SQLITE_OMIT_TRIGGER + char *zWhere = 0; /* Where clause to locate temp triggers */ +#endif + int isVirtualRename = 0; /* True if this is a v-table with an xRename() */ + + if( sqlite3MallocFailed() ) goto exit_rename_table; + assert( pSrc->nSrc==1 ); + + pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase); + if( !pTab ) goto exit_rename_table; + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + zDb = db->aDb[iDb].zName; + + /* Get a NULL terminated version of the new table name. */ + zName = sqlite3NameFromToken(pName); + if( !zName ) goto exit_rename_table; + + /* Check that a table or index named 'zName' does not already exist + ** in database iDb. If so, this is an error. + */ + if( sqlite3FindTable(db, zName, zDb) || sqlite3FindIndex(db, zName, zDb) ){ + sqlite3ErrorMsg(pParse, + "there is already another table or index with this name: %s", zName); + goto exit_rename_table; + } + + /* Make sure it is not a system table being altered, or a reserved name + ** that the table is being renamed to. + */ + if( strlen(pTab->zName)>6 && 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7) ){ + sqlite3ErrorMsg(pParse, "table %s may not be altered", pTab->zName); + goto exit_rename_table; + } + if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ + goto exit_rename_table; + } + +#ifndef SQLITE_OMIT_AUTHORIZATION + /* Invoke the authorization callback. */ + if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){ + goto exit_rename_table; + } +#endif + +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( sqlite3ViewGetColumnNames(pParse, pTab) ){ + goto exit_rename_table; + } + if( IsVirtual(pTab) && pTab->pMod->pModule->xRename ){ + isVirtualRename = 1; + } +#endif + + /* Begin a transaction and code the VerifyCookie for database iDb. + ** Then modify the schema cookie (since the ALTER TABLE modifies the + ** schema). Open a statement transaction if the table is a virtual + ** table. + */ + v = sqlite3GetVdbe(pParse); + if( v==0 ){ + goto exit_rename_table; + } + sqlite3BeginWriteOperation(pParse, isVirtualRename, iDb); + sqlite3ChangeCookie(db, v, iDb); + + /* If this is a virtual table, invoke the xRename() function if + ** one is defined. The xRename() callback will modify the names + ** of any resources used by the v-table implementation (including other + ** SQLite tables) that are identified by the name of the virtual table. + */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( isVirtualRename ){ + sqlite3VdbeOp3(v, OP_String8, 0, 0, zName, 0); + sqlite3VdbeOp3(v, OP_VRename, 0, 0, (const char*)pTab->pVtab, P3_VTAB); + } +#endif + + /* figure out how many UTF-8 characters are in zName */ + zTabName = pTab->zName; + nTabName = sqlite3Utf8CharLen(zTabName, -1); + + /* 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, nTabName, zTabName + ); + +#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 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; inCol; 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 */ diff --git a/extensions/sqlite/sqlite-source/analyze.c b/extensions/sqlite/sqlite-source/analyze.c new file mode 100644 index 00000000..cb68fe09 --- /dev/null +++ b/extensions/sqlite/sqlite-source/analyze.c @@ -0,0 +1,410 @@ +/* +** 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$ +*/ +#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); + + if( v==0 ) return; + 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( v==0 || 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; i0 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; idb; + 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 -- 2 +** ANALYZE ?.? -- 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; inDb; 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); + if( z ){ + 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. +*/ +int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ + analysisInfo sInfo; + HashElem *i; + char *zSql; + int rc; + + /* 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 SQLITE_ERROR; + } + + + /* Load new statistics out of the sqlite_stat1 table */ + zSql = sqlite3MPrintf("SELECT idx, stat FROM %Q.sqlite_stat1", + sInfo.zDatabase); + sqlite3SafetyOff(db); + rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0); + sqlite3SafetyOn(db); + sqliteFree(zSql); + return rc; +} + + +#endif /* SQLITE_OMIT_ANALYZE */ diff --git a/extensions/sqlite/sqlite-source/attach.c b/extensions/sqlite/sqlite-source/attach.c new file mode 100644 index 00000000..65b5e4b9 --- /dev/null +++ b/extensions/sqlite/sqlite-source/attach.c @@ -0,0 +1,516 @@ +/* +** 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$ +*/ +#include "sqliteInt.h" + +#ifndef SQLITE_OMIT_ATTACH +/* +** 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); + if( rc==SQLITE_OK && !sqlite3ExprIsConstant(pExpr) ){ + sqlite3ErrorMsg(pName->pParse, "invalid name: \"%T\"", &pExpr->span); + return SQLITE_ERROR; + } + }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>=SQLITE_MAX_ATTACHED+2 ){ + sqlite3_snprintf( + sizeof(zErr), zErr, "too many attached databases - max %d", + SQLITE_MAX_ATTACHED + ); + goto attach_error; + } + if( !db->autoCommit ){ + sqlite3_snprintf(sizeof(zErr), zErr, + "cannot ATTACH database within transaction"); + goto attach_error; + } + for(i=0; inDb; 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, SQLITE_DEFAULT_CACHE_SIZE, &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) ){ + sqlite3_snprintf(sizeof(zErr), zErr, + "attached databases must use the same text encoding as main database"); + goto attach_error; + } + sqlite3PagerLockingMode(sqlite3BtreePager(aNew->pBt), db->dfltLockMode); + } + aNew->zName = sqliteStrDup(zName); + aNew->safety_level = 3; + +#if SQLITE_HAS_CODEC + { + extern int sqlite3CodecAttach(sqlite3*, int, const 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 ){ + 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; inDb; 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 ){ + sqlite3_snprintf(sizeof(zErr), 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); +} +#endif /* SQLITE_OMIT_ATTACH */ + +/* +** Register the functions sqlite_attach and sqlite_detach. +*/ +void sqlite3AttachFunctions(sqlite3 *db){ +#ifndef SQLITE_OMIT_ATTACH + 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); +#endif +} + +/* +** 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; inSrc; 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; inExpr; 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 diff --git a/extensions/sqlite/sqlite-source/auth.c b/extensions/sqlite/sqlite-source/auth.c new file mode 100644 index 00000000..b3d671ea --- /dev/null +++ b/extensions/sqlite/sqlite-source/auth.c @@ -0,0 +1,233 @@ +/* +** 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$ +*/ +#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_COLUMN ) return; + 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 && iSrcnSrc; iSrc++){ + if( pExpr->iTable==pTabList->a[iSrc].iCursor ) break; + } + if( iSrc>=0 && pTabList && iSrcnSrc ){ + 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->iColumnnCol ); + zCol = pTab->aCol[pExpr->iColumn].zName; + }else if( pTab->iPKey>=0 ){ + assert( pTab->iPKeynCol ); + zCol = pTab->aCol[pTab->iPKey].zName; + }else{ + zCol = "ROWID"; + } + assert( iDb>=0 && iDbnDb ); + 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 */ diff --git a/extensions/sqlite/sqlite-source/btree.c b/extensions/sqlite/sqlite-source/btree.c new file mode 100644 index 00000000..35381b7e --- /dev/null +++ b/extensions/sqlite/sqlite-source/btree.c @@ -0,0 +1,6370 @@ +/* +** 2004 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. +** +************************************************************************* +** $Id$ +** +** This file implements a external (disk-based) database using BTrees. +** See the header comment on "btreeInt.h" for additional information. +** Including a description of file format and an overview of operation. +*/ +#include "btreeInt.h" + +/* +** The header string that appears at the beginning of every +** SQLite database. +*/ +static const char zMagicHeader[] = SQLITE_FILE_HEADER; + + +/* +** Set this global variable to 1 to enable tracing using the TRACE +** macro. +*/ +#if SQLITE_TEST +int sqlite3_btree_trace=0; /* True to enable tracing */ +#endif + +/* +** Forward declaration +*/ +static int checkReadLocks(Btree*,Pgno,BtCursor*); + + +#ifdef SQLITE_OMIT_SHARED_CACHE + /* + ** The functions queryTableLock(), lockTable() and unlockAllTables() + ** manipulate entries in the BtShared.pLock linked list used to store + ** shared-cache table level locks. If the library is compiled with the + ** shared-cache feature disabled, then there is only ever one user + ** of each BtShared structure and so this locking is not necessary. + ** So define the lock related functions as no-ops. + */ + #define queryTableLock(a,b,c) SQLITE_OK + #define lockTable(a,b,c) SQLITE_OK + #define unlockAllTables(a) +#else + +/* +** Query to see if btree handle p may obtain a lock of type eLock +** (READ_LOCK or WRITE_LOCK) on the table with root-page iTab. Return +** SQLITE_OK if the lock may be obtained (by calling lockTable()), or +** SQLITE_LOCKED if not. +*/ +static int queryTableLock(Btree *p, Pgno iTab, u8 eLock){ + BtShared *pBt = p->pBt; + BtLock *pIter; + + /* This is a no-op if the shared-cache is not enabled */ + if( 0==sqlite3ThreadDataReadOnly()->useSharedData ){ + return SQLITE_OK; + } + + /* This (along with lockTable()) is where the ReadUncommitted flag is + ** dealt with. If the caller is querying for a read-lock and the flag is + ** set, it is unconditionally granted - even if there are write-locks + ** on the table. If a write-lock is requested, the ReadUncommitted flag + ** is not considered. + ** + ** In function lockTable(), if a read-lock is demanded and the + ** ReadUncommitted flag is set, no entry is added to the locks list + ** (BtShared.pLock). + ** + ** To summarize: If the ReadUncommitted flag is set, then read cursors do + ** not create or respect table locks. The locking procedure for a + ** write-cursor does not change. + */ + if( + !p->pSqlite || + 0==(p->pSqlite->flags&SQLITE_ReadUncommitted) || + eLock==WRITE_LOCK || + iTab==MASTER_ROOT + ){ + for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){ + if( pIter->pBtree!=p && pIter->iTable==iTab && + (pIter->eLock!=eLock || eLock!=READ_LOCK) ){ + return SQLITE_LOCKED; + } + } + } + return SQLITE_OK; +} + +/* +** Add a lock on the table with root-page iTable to the shared-btree used +** by Btree handle p. Parameter eLock must be either READ_LOCK or +** WRITE_LOCK. +** +** SQLITE_OK is returned if the lock is added successfully. SQLITE_BUSY and +** SQLITE_NOMEM may also be returned. +*/ +static int lockTable(Btree *p, Pgno iTable, u8 eLock){ + BtShared *pBt = p->pBt; + BtLock *pLock = 0; + BtLock *pIter; + + /* This is a no-op if the shared-cache is not enabled */ + if( 0==sqlite3ThreadDataReadOnly()->useSharedData ){ + return SQLITE_OK; + } + + assert( SQLITE_OK==queryTableLock(p, iTable, eLock) ); + + /* If the read-uncommitted flag is set and a read-lock is requested, + ** return early without adding an entry to the BtShared.pLock list. See + ** comment in function queryTableLock() for more info on handling + ** the ReadUncommitted flag. + */ + if( + (p->pSqlite) && + (p->pSqlite->flags&SQLITE_ReadUncommitted) && + (eLock==READ_LOCK) && + iTable!=MASTER_ROOT + ){ + return SQLITE_OK; + } + + /* First search the list for an existing lock on this table. */ + for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){ + if( pIter->iTable==iTable && pIter->pBtree==p ){ + pLock = pIter; + break; + } + } + + /* If the above search did not find a BtLock struct associating Btree p + ** with table iTable, allocate one and link it into the list. + */ + if( !pLock ){ + pLock = (BtLock *)sqliteMalloc(sizeof(BtLock)); + if( !pLock ){ + return SQLITE_NOMEM; + } + pLock->iTable = iTable; + pLock->pBtree = p; + pLock->pNext = pBt->pLock; + pBt->pLock = pLock; + } + + /* Set the BtLock.eLock variable to the maximum of the current lock + ** and the requested lock. This means if a write-lock was already held + ** and a read-lock requested, we don't incorrectly downgrade the lock. + */ + assert( WRITE_LOCK>READ_LOCK ); + if( eLock>pLock->eLock ){ + pLock->eLock = eLock; + } + + return SQLITE_OK; +} + +/* +** Release all the table locks (locks obtained via calls to the lockTable() +** procedure) held by Btree handle p. +*/ +static void unlockAllTables(Btree *p){ + BtLock **ppIter = &p->pBt->pLock; + + /* If the shared-cache extension is not enabled, there should be no + ** locks in the BtShared.pLock list, making this procedure a no-op. Assert + ** that this is the case. + */ + assert( sqlite3ThreadDataReadOnly()->useSharedData || 0==*ppIter ); + + while( *ppIter ){ + BtLock *pLock = *ppIter; + if( pLock->pBtree==p ){ + *ppIter = pLock->pNext; + sqliteFree(pLock); + }else{ + ppIter = &pLock->pNext; + } + } +} +#endif /* SQLITE_OMIT_SHARED_CACHE */ + +static void releasePage(MemPage *pPage); /* Forward reference */ + +#ifndef SQLITE_OMIT_INCRBLOB +/* +** Invalidate the overflow page-list cache for cursor pCur, if any. +*/ +static void invalidateOverflowCache(BtCursor *pCur){ + sqliteFree(pCur->aOverflow); + pCur->aOverflow = 0; +} + +/* +** Invalidate the overflow page-list cache for all cursors opened +** on the shared btree structure pBt. +*/ +static void invalidateAllOverflowCache(BtShared *pBt){ + BtCursor *p; + for(p=pBt->pCursor; p; p=p->pNext){ + invalidateOverflowCache(p); + } +} +#else + #define invalidateOverflowCache(x) + #define invalidateAllOverflowCache(x) +#endif + +/* +** Save the current cursor position in the variables BtCursor.nKey +** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK. +*/ +static int saveCursorPosition(BtCursor *pCur){ + int rc; + + assert( CURSOR_VALID==pCur->eState ); + assert( 0==pCur->pKey ); + + rc = sqlite3BtreeKeySize(pCur, &pCur->nKey); + + /* If this is an intKey table, then the above call to BtreeKeySize() + ** stores the integer key in pCur->nKey. In this case this value is + ** all that is required. Otherwise, if pCur is not open on an intKey + ** table, then malloc space for and store the pCur->nKey bytes of key + ** data. + */ + if( rc==SQLITE_OK && 0==pCur->pPage->intKey){ + void *pKey = sqliteMalloc((int)pCur->nKey); + if( pKey ){ + rc = sqlite3BtreeKey(pCur, 0, (int)pCur->nKey, pKey); + if( rc==SQLITE_OK ){ + pCur->pKey = pKey; + }else{ + sqliteFree(pKey); + } + }else{ + rc = SQLITE_NOMEM; + } + } + assert( !pCur->pPage->intKey || !pCur->pKey ); + + if( rc==SQLITE_OK ){ + releasePage(pCur->pPage); + pCur->pPage = 0; + pCur->eState = CURSOR_REQUIRESEEK; + } + + invalidateOverflowCache(pCur); + return rc; +} + +/* +** Save the positions of all cursors except pExcept open on the table +** with root-page iRoot. Usually, this is called just before cursor +** pExcept is used to modify the table (BtreeDelete() or BtreeInsert()). +*/ +static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){ + BtCursor *p; + for(p=pBt->pCursor; p; p=p->pNext){ + if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) && + p->eState==CURSOR_VALID ){ + int rc = saveCursorPosition(p); + if( SQLITE_OK!=rc ){ + return rc; + } + } + } + return SQLITE_OK; +} + +/* +** Clear the current cursor position. +*/ +static void clearCursorPosition(BtCursor *pCur){ + sqliteFree(pCur->pKey); + pCur->pKey = 0; + pCur->eState = CURSOR_INVALID; +} + +/* +** Restore the cursor to the position it was in (or as close to as possible) +** when saveCursorPosition() was called. Note that this call deletes the +** saved position info stored by saveCursorPosition(), so there can be +** at most one effective restoreOrClearCursorPosition() call after each +** saveCursorPosition(). +** +** If the second argument argument - doSeek - is false, then instead of +** returning the cursor to it's saved position, any saved position is deleted +** and the cursor state set to CURSOR_INVALID. +*/ +int sqlite3BtreeRestoreOrClearCursorPosition(BtCursor *pCur){ + int rc; + assert( pCur->eState==CURSOR_REQUIRESEEK ); +#ifndef SQLITE_OMIT_INCRBLOB + if( pCur->isIncrblobHandle ){ + return SQLITE_ABORT; + } +#endif + pCur->eState = CURSOR_INVALID; + rc = sqlite3BtreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &pCur->skip); + if( rc==SQLITE_OK ){ + sqliteFree(pCur->pKey); + pCur->pKey = 0; + assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID ); + } + return rc; +} + +#define restoreOrClearCursorPosition(p) \ + (p->eState==CURSOR_REQUIRESEEK ? \ + sqlite3BtreeRestoreOrClearCursorPosition(p) : \ + SQLITE_OK) + +#ifndef SQLITE_OMIT_AUTOVACUUM +/* +** Given a page number of a regular database page, return the page +** number for the pointer-map page that contains the entry for the +** input page number. +*/ +static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){ + int nPagesPerMapPage = (pBt->usableSize/5)+1; + int iPtrMap = (pgno-2)/nPagesPerMapPage; + int ret = (iPtrMap*nPagesPerMapPage) + 2; + if( ret==PENDING_BYTE_PAGE(pBt) ){ + ret++; + } + return ret; +} + +/* +** Write an entry into the pointer map. +** +** This routine updates the pointer map entry for page number 'key' +** so that it maps to type 'eType' and parent page number 'pgno'. +** An error code is returned if something goes wrong, otherwise SQLITE_OK. +*/ +static int ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent){ + DbPage *pDbPage; /* The pointer map page */ + u8 *pPtrmap; /* The pointer map data */ + Pgno iPtrmap; /* The pointer map page number */ + int offset; /* Offset in pointer map page */ + int rc; + + /* The master-journal page number must never be used as a pointer map page */ + assert( 0==PTRMAP_ISPAGE(pBt, PENDING_BYTE_PAGE(pBt)) ); + + assert( pBt->autoVacuum ); + if( key==0 ){ + return SQLITE_CORRUPT_BKPT; + } + iPtrmap = PTRMAP_PAGENO(pBt, key); + rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage); + if( rc!=SQLITE_OK ){ + return rc; + } + offset = PTRMAP_PTROFFSET(pBt, key); + pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage); + + if( eType!=pPtrmap[offset] || get4byte(&pPtrmap[offset+1])!=parent ){ + TRACE(("PTRMAP_UPDATE: %d->(%d,%d)\n", key, eType, parent)); + rc = sqlite3PagerWrite(pDbPage); + if( rc==SQLITE_OK ){ + pPtrmap[offset] = eType; + put4byte(&pPtrmap[offset+1], parent); + } + } + + sqlite3PagerUnref(pDbPage); + return rc; +} + +/* +** Read an entry from the pointer map. +** +** This routine retrieves the pointer map entry for page 'key', writing +** the type and parent page number to *pEType and *pPgno respectively. +** An error code is returned if something goes wrong, otherwise SQLITE_OK. +*/ +static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){ + DbPage *pDbPage; /* The pointer map page */ + int iPtrmap; /* Pointer map page index */ + u8 *pPtrmap; /* Pointer map page data */ + int offset; /* Offset of entry in pointer map */ + int rc; + + iPtrmap = PTRMAP_PAGENO(pBt, key); + rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage); + if( rc!=0 ){ + return rc; + } + pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage); + + offset = PTRMAP_PTROFFSET(pBt, key); + assert( pEType!=0 ); + *pEType = pPtrmap[offset]; + if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]); + + sqlite3PagerUnref(pDbPage); + if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT_BKPT; + return SQLITE_OK; +} + +#endif /* SQLITE_OMIT_AUTOVACUUM */ + +/* +** Given a btree page and a cell index (0 means the first cell on +** the page, 1 means the second cell, and so forth) return a pointer +** to the cell content. +** +** This routine works only for pages that do not contain overflow cells. +*/ +#define findCell(pPage, iCell) \ + ((pPage)->aData + get2byte(&(pPage)->aData[(pPage)->cellOffset+2*(iCell)])) +u8 *sqlite3BtreeFindCell(MemPage *pPage, int iCell){ + assert( iCell>=0 ); + assert( iCellaData[pPage->hdrOffset+3]) ); + return findCell(pPage, iCell); +} + +/* +** This a more complex version of sqlite3BtreeFindCell() that works for +** pages that do contain overflow cells. See insert +*/ +static u8 *findOverflowCell(MemPage *pPage, int iCell){ + int i; + for(i=pPage->nOverflow-1; i>=0; i--){ + int k; + struct _OvflCell *pOvfl; + pOvfl = &pPage->aOvfl[i]; + k = pOvfl->idx; + if( k<=iCell ){ + if( k==iCell ){ + return pOvfl->pCell; + } + iCell--; + } + } + return findCell(pPage, iCell); +} + +/* +** Parse a cell content block and fill in the CellInfo structure. There +** are two versions of this function. sqlite3BtreeParseCell() takes a +** cell index as the second argument and sqlite3BtreeParseCellPtr() +** takes a pointer to the body of the cell as its second argument. +** +** Within this file, the parseCell() macro can be called instead of +** sqlite3BtreeParseCellPtr(). Using some compilers, this will be faster. +*/ +void sqlite3BtreeParseCellPtr( + MemPage *pPage, /* Page containing the cell */ + u8 *pCell, /* Pointer to the cell text. */ + CellInfo *pInfo /* Fill in this structure */ +){ + int n; /* Number bytes in cell content header */ + u32 nPayload; /* Number of bytes of cell payload */ + + pInfo->pCell = pCell; + assert( pPage->leaf==0 || pPage->leaf==1 ); + n = pPage->childPtrSize; + assert( n==4-4*pPage->leaf ); + if( pPage->hasData ){ + n += getVarint32(&pCell[n], &nPayload); + }else{ + nPayload = 0; + } + pInfo->nData = nPayload; + if( pPage->intKey ){ + n += getVarint(&pCell[n], (u64 *)&pInfo->nKey); + }else{ + u32 x; + n += getVarint32(&pCell[n], &x); + pInfo->nKey = x; + nPayload += x; + } + pInfo->nPayload = nPayload; + pInfo->nHeader = n; + if( nPayload<=pPage->maxLocal ){ + /* This is the (easy) common case where the entire payload fits + ** on the local page. No overflow is required. + */ + int nSize; /* Total size of cell content in bytes */ + pInfo->nLocal = nPayload; + pInfo->iOverflow = 0; + nSize = nPayload + n; + if( nSize<4 ){ + nSize = 4; /* Minimum cell size is 4 */ + } + pInfo->nSize = nSize; + }else{ + /* If the payload will not fit completely on the local page, we have + ** to decide how much to store locally and how much to spill onto + ** overflow pages. The strategy is to minimize the amount of unused + ** space on overflow pages while keeping the amount of local storage + ** in between minLocal and maxLocal. + ** + ** Warning: changing the way overflow payload is distributed in any + ** way will result in an incompatible file format. + */ + int minLocal; /* Minimum amount of payload held locally */ + int maxLocal; /* Maximum amount of payload held locally */ + int surplus; /* Overflow payload available for local storage */ + + minLocal = pPage->minLocal; + maxLocal = pPage->maxLocal; + surplus = minLocal + (nPayload - minLocal)%(pPage->pBt->usableSize - 4); + if( surplus <= maxLocal ){ + pInfo->nLocal = surplus; + }else{ + pInfo->nLocal = minLocal; + } + pInfo->iOverflow = pInfo->nLocal + n; + pInfo->nSize = pInfo->iOverflow + 4; + } +} +#define parseCell(pPage, iCell, pInfo) \ + sqlite3BtreeParseCellPtr((pPage), findCell((pPage), (iCell)), (pInfo)) +void sqlite3BtreeParseCell( + MemPage *pPage, /* Page containing the cell */ + int iCell, /* The cell index. First cell is 0 */ + CellInfo *pInfo /* Fill in this structure */ +){ + parseCell(pPage, iCell, pInfo); +} + +/* +** Compute the total number of bytes that a Cell needs in the cell +** data area of the btree-page. The return number includes the cell +** data header and the local payload, but not any overflow page or +** the space used by the cell pointer. +*/ +#ifndef NDEBUG +static int cellSize(MemPage *pPage, int iCell){ + CellInfo info; + sqlite3BtreeParseCell(pPage, iCell, &info); + return info.nSize; +} +#endif +static int cellSizePtr(MemPage *pPage, u8 *pCell){ + CellInfo info; + sqlite3BtreeParseCellPtr(pPage, pCell, &info); + return info.nSize; +} + +#ifndef SQLITE_OMIT_AUTOVACUUM +/* +** If the cell pCell, part of page pPage contains a pointer +** to an overflow page, insert an entry into the pointer-map +** for the overflow page. +*/ +static int ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell){ + if( pCell ){ + CellInfo info; + sqlite3BtreeParseCellPtr(pPage, pCell, &info); + assert( (info.nData+(pPage->intKey?0:info.nKey))==info.nPayload ); + if( (info.nData+(pPage->intKey?0:info.nKey))>info.nLocal ){ + Pgno ovfl = get4byte(&pCell[info.iOverflow]); + return ptrmapPut(pPage->pBt, ovfl, PTRMAP_OVERFLOW1, pPage->pgno); + } + } + return SQLITE_OK; +} +/* +** If the cell with index iCell on page pPage contains a pointer +** to an overflow page, insert an entry into the pointer-map +** for the overflow page. +*/ +static int ptrmapPutOvfl(MemPage *pPage, int iCell){ + u8 *pCell; + pCell = findOverflowCell(pPage, iCell); + return ptrmapPutOvflPtr(pPage, pCell); +} +#endif + + +/* +** Defragment the page given. All Cells are moved to the +** end of the page and all free space is collected into one +** big FreeBlk that occurs in between the header and cell +** pointer array and the cell content area. +*/ +static int defragmentPage(MemPage *pPage){ + int i; /* Loop counter */ + int pc; /* Address of a i-th cell */ + int addr; /* Offset of first byte after cell pointer array */ + int hdr; /* Offset to the page header */ + int size; /* Size of a cell */ + int usableSize; /* Number of usable bytes on a page */ + int cellOffset; /* Offset to the cell pointer array */ + int brk; /* Offset to the cell content area */ + int nCell; /* Number of cells on the page */ + unsigned char *data; /* The page data */ + unsigned char *temp; /* Temp area for cell content */ + + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + assert( pPage->pBt!=0 ); + assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE ); + assert( pPage->nOverflow==0 ); + temp = sqliteMalloc( pPage->pBt->pageSize ); + if( temp==0 ) return SQLITE_NOMEM; + data = pPage->aData; + hdr = pPage->hdrOffset; + cellOffset = pPage->cellOffset; + nCell = pPage->nCell; + assert( nCell==get2byte(&data[hdr+3]) ); + usableSize = pPage->pBt->usableSize; + brk = get2byte(&data[hdr+5]); + memcpy(&temp[brk], &data[brk], usableSize - brk); + brk = usableSize; + for(i=0; ipBt->usableSize ); + size = cellSizePtr(pPage, &temp[pc]); + brk -= size; + memcpy(&data[brk], &temp[pc], size); + put2byte(pAddr, brk); + } + assert( brk>=cellOffset+2*nCell ); + put2byte(&data[hdr+5], brk); + data[hdr+1] = 0; + data[hdr+2] = 0; + data[hdr+7] = 0; + addr = cellOffset+2*nCell; + memset(&data[addr], 0, brk-addr); + sqliteFree(temp); + return SQLITE_OK; +} + +/* +** Allocate nByte bytes of space on a page. +** +** Return the index into pPage->aData[] of the first byte of +** the new allocation. Or return 0 if there is not enough free +** space on the page to satisfy the allocation request. +** +** If the page contains nBytes of free space but does not contain +** nBytes of contiguous free space, then this routine automatically +** calls defragementPage() to consolidate all free space before +** allocating the new chunk. +*/ +static int allocateSpace(MemPage *pPage, int nByte){ + int addr, pc, hdr; + int size; + int nFrag; + int top; + int nCell; + int cellOffset; + unsigned char *data; + + data = pPage->aData; + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + assert( pPage->pBt ); + if( nByte<4 ) nByte = 4; + if( pPage->nFreenOverflow>0 ) return 0; + pPage->nFree -= nByte; + hdr = pPage->hdrOffset; + + nFrag = data[hdr+7]; + if( nFrag<60 ){ + /* Search the freelist looking for a slot big enough to satisfy the + ** space request. */ + addr = hdr+1; + while( (pc = get2byte(&data[addr]))>0 ){ + size = get2byte(&data[pc+2]); + if( size>=nByte ){ + if( sizecellOffset; + if( nFrag>=60 || cellOffset + 2*nCell > top - nByte ){ + if( defragmentPage(pPage) ) return 0; + top = get2byte(&data[hdr+5]); + } + top -= nByte; + assert( cellOffset + 2*nCell <= top ); + put2byte(&data[hdr+5], top); + return top; +} + +/* +** Return a section of the pPage->aData to the freelist. +** The first byte of the new free block is pPage->aDisk[start] +** and the size of the block is "size" bytes. +** +** Most of the effort here is involved in coalesing adjacent +** free blocks into a single big free block. +*/ +static void freeSpace(MemPage *pPage, int start, int size){ + int addr, pbegin, hdr; + unsigned char *data = pPage->aData; + + assert( pPage->pBt!=0 ); + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + assert( start>=pPage->hdrOffset+6+(pPage->leaf?0:4) ); + assert( (start + size)<=pPage->pBt->usableSize ); + if( size<4 ) size = 4; + +#ifdef SQLITE_SECURE_DELETE + /* Overwrite deleted information with zeros when the SECURE_DELETE + ** option is enabled at compile-time */ + memset(&data[start], 0, size); +#endif + + /* Add the space back into the linked list of freeblocks */ + hdr = pPage->hdrOffset; + addr = hdr + 1; + while( (pbegin = get2byte(&data[addr]))0 ){ + assert( pbegin<=pPage->pBt->usableSize-4 ); + assert( pbegin>addr ); + addr = pbegin; + } + assert( pbegin<=pPage->pBt->usableSize-4 ); + assert( pbegin>addr || pbegin==0 ); + put2byte(&data[addr], start); + put2byte(&data[start], pbegin); + put2byte(&data[start+2], size); + pPage->nFree += size; + + /* Coalesce adjacent free blocks */ + addr = pPage->hdrOffset + 1; + while( (pbegin = get2byte(&data[addr]))>0 ){ + int pnext, psize; + assert( pbegin>addr ); + assert( pbegin<=pPage->pBt->usableSize-4 ); + pnext = get2byte(&data[pbegin]); + psize = get2byte(&data[pbegin+2]); + if( pbegin + psize + 3 >= pnext && pnext>0 ){ + int frag = pnext - (pbegin+psize); + assert( frag<=data[pPage->hdrOffset+7] ); + data[pPage->hdrOffset+7] -= frag; + put2byte(&data[pbegin], get2byte(&data[pnext])); + put2byte(&data[pbegin+2], pnext+get2byte(&data[pnext+2])-pbegin); + }else{ + addr = pbegin; + } + } + + /* If the cell content area begins with a freeblock, remove it. */ + if( data[hdr+1]==data[hdr+5] && data[hdr+2]==data[hdr+6] ){ + int top; + pbegin = get2byte(&data[hdr+1]); + memcpy(&data[hdr+1], &data[pbegin], 2); + top = get2byte(&data[hdr+5]); + put2byte(&data[hdr+5], top + get2byte(&data[pbegin+2])); + } +} + +/* +** Decode the flags byte (the first byte of the header) for a page +** and initialize fields of the MemPage structure accordingly. +*/ +static void decodeFlags(MemPage *pPage, int flagByte){ + BtShared *pBt; /* A copy of pPage->pBt */ + + assert( pPage->hdrOffset==(pPage->pgno==1 ? 100 : 0) ); + pPage->intKey = (flagByte & (PTF_INTKEY|PTF_LEAFDATA))!=0; + pPage->zeroData = (flagByte & PTF_ZERODATA)!=0; + pPage->leaf = (flagByte & PTF_LEAF)!=0; + pPage->childPtrSize = 4*(pPage->leaf==0); + pBt = pPage->pBt; + if( flagByte & PTF_LEAFDATA ){ + pPage->leafData = 1; + pPage->maxLocal = pBt->maxLeaf; + pPage->minLocal = pBt->minLeaf; + }else{ + pPage->leafData = 0; + pPage->maxLocal = pBt->maxLocal; + pPage->minLocal = pBt->minLocal; + } + pPage->hasData = !(pPage->zeroData || (!pPage->leaf && pPage->leafData)); +} + +/* +** Initialize the auxiliary information for a disk block. +** +** The pParent parameter must be a pointer to the MemPage which +** is the parent of the page being initialized. The root of a +** BTree has no parent and so for that page, pParent==NULL. +** +** Return SQLITE_OK on success. If we see that the page does +** not contain a well-formed database page, then return +** SQLITE_CORRUPT. Note that a return of SQLITE_OK does not +** guarantee that the page is well-formed. It only shows that +** we failed to detect any corruption. +*/ +int sqlite3BtreeInitPage( + MemPage *pPage, /* The page to be initialized */ + MemPage *pParent /* The parent. Might be NULL */ +){ + int pc; /* Address of a freeblock within pPage->aData[] */ + int hdr; /* Offset to beginning of page header */ + u8 *data; /* Equal to pPage->aData */ + BtShared *pBt; /* The main btree structure */ + int usableSize; /* Amount of usable space on each page */ + int cellOffset; /* Offset from start of page to first cell pointer */ + int nFree; /* Number of unused bytes on the page */ + int top; /* First byte of the cell content area */ + + pBt = pPage->pBt; + assert( pBt!=0 ); + assert( pParent==0 || pParent->pBt==pBt ); + assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) ); + assert( pPage->aData == &((unsigned char*)pPage)[-pBt->pageSize] ); + if( pPage->pParent!=pParent && (pPage->pParent!=0 || pPage->isInit) ){ + /* The parent page should never change unless the file is corrupt */ + return SQLITE_CORRUPT_BKPT; + } + if( pPage->isInit ) return SQLITE_OK; + if( pPage->pParent==0 && pParent!=0 ){ + pPage->pParent = pParent; + sqlite3PagerRef(pParent->pDbPage); + } + hdr = pPage->hdrOffset; + data = pPage->aData; + decodeFlags(pPage, data[hdr]); + pPage->nOverflow = 0; + pPage->idxShift = 0; + usableSize = pBt->usableSize; + pPage->cellOffset = cellOffset = hdr + 12 - 4*pPage->leaf; + top = get2byte(&data[hdr+5]); + pPage->nCell = get2byte(&data[hdr+3]); + if( pPage->nCell>MX_CELL(pBt) ){ + /* To many cells for a single page. The page must be corrupt */ + return SQLITE_CORRUPT_BKPT; + } + if( pPage->nCell==0 && pParent!=0 && pParent->pgno!=1 ){ + /* All pages must have at least one cell, except for root pages */ + return SQLITE_CORRUPT_BKPT; + } + + /* Compute the total free space on the page */ + pc = get2byte(&data[hdr+1]); + nFree = data[hdr+7] + top - (cellOffset + 2*pPage->nCell); + while( pc>0 ){ + int next, size; + if( pc>usableSize-4 ){ + /* Free block is off the page */ + return SQLITE_CORRUPT_BKPT; + } + next = get2byte(&data[pc]); + size = get2byte(&data[pc+2]); + if( next>0 && next<=pc+size+3 ){ + /* Free blocks must be in accending order */ + return SQLITE_CORRUPT_BKPT; + } + nFree += size; + pc = next; + } + pPage->nFree = nFree; + if( nFree>=usableSize ){ + /* Free space cannot exceed total page size */ + return SQLITE_CORRUPT_BKPT; + } + + pPage->isInit = 1; + return SQLITE_OK; +} + +/* +** Set up a raw page so that it looks like a database page holding +** no entries. +*/ +static void zeroPage(MemPage *pPage, int flags){ + unsigned char *data = pPage->aData; + BtShared *pBt = pPage->pBt; + int hdr = pPage->hdrOffset; + int first; + + assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno ); + assert( &data[pBt->pageSize] == (unsigned char*)pPage ); + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + memset(&data[hdr], 0, pBt->usableSize - hdr); + data[hdr] = flags; + first = hdr + 8 + 4*((flags&PTF_LEAF)==0); + memset(&data[hdr+1], 0, 4); + data[hdr+7] = 0; + put2byte(&data[hdr+5], pBt->usableSize); + pPage->nFree = pBt->usableSize - first; + decodeFlags(pPage, flags); + pPage->hdrOffset = hdr; + pPage->cellOffset = first; + pPage->nOverflow = 0; + pPage->idxShift = 0; + pPage->nCell = 0; + pPage->isInit = 1; +} + +/* +** Get a page from the pager. Initialize the MemPage.pBt and +** MemPage.aData elements if needed. +** +** If the noContent flag is set, it means that we do not care about +** the content of the page at this time. So do not go to the disk +** to fetch the content. Just fill in the content with zeros for now. +** If in the future we call sqlite3PagerWrite() on this page, that +** means we have started to be concerned about content and the disk +** read should occur at that point. +*/ +int sqlite3BtreeGetPage( + BtShared *pBt, /* The btree */ + Pgno pgno, /* Number of the page to fetch */ + MemPage **ppPage, /* Return the page in this parameter */ + int noContent /* Do not load page content if true */ +){ + int rc; + MemPage *pPage; + DbPage *pDbPage; + + rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, noContent); + if( rc ) return rc; + pPage = (MemPage *)sqlite3PagerGetExtra(pDbPage); + pPage->aData = sqlite3PagerGetData(pDbPage); + pPage->pDbPage = pDbPage; + pPage->pBt = pBt; + pPage->pgno = pgno; + pPage->hdrOffset = pPage->pgno==1 ? 100 : 0; + *ppPage = pPage; + return SQLITE_OK; +} + +/* +** Get a page from the pager and initialize it. This routine +** is just a convenience wrapper around separate calls to +** sqlite3BtreeGetPage() and sqlite3BtreeInitPage(). +*/ +static int getAndInitPage( + BtShared *pBt, /* The database file */ + Pgno pgno, /* Number of the page to get */ + MemPage **ppPage, /* Write the page pointer here */ + MemPage *pParent /* Parent of the page */ +){ + int rc; + if( pgno==0 ){ + return SQLITE_CORRUPT_BKPT; + } + rc = sqlite3BtreeGetPage(pBt, pgno, ppPage, 0); + if( rc==SQLITE_OK && (*ppPage)->isInit==0 ){ + rc = sqlite3BtreeInitPage(*ppPage, pParent); + } + return rc; +} + +/* +** Release a MemPage. This should be called once for each prior +** call to sqlite3BtreeGetPage. +*/ +static void releasePage(MemPage *pPage){ + if( pPage ){ + assert( pPage->aData ); + assert( pPage->pBt ); + assert( &pPage->aData[pPage->pBt->pageSize]==(unsigned char*)pPage ); + sqlite3PagerUnref(pPage->pDbPage); + } +} + +/* +** This routine is called when the reference count for a page +** reaches zero. We need to unref the pParent pointer when that +** happens. +*/ +static void pageDestructor(DbPage *pData, int pageSize){ + MemPage *pPage; + assert( (pageSize & 7)==0 ); + pPage = (MemPage *)sqlite3PagerGetExtra(pData); + if( pPage->pParent ){ + MemPage *pParent = pPage->pParent; + pPage->pParent = 0; + releasePage(pParent); + } + pPage->isInit = 0; +} + +/* +** During a rollback, when the pager reloads information into the cache +** so that the cache is restored to its original state at the start of +** the transaction, for each page restored this routine is called. +** +** This routine needs to reset the extra data section at the end of the +** page to agree with the restored data. +*/ +static void pageReinit(DbPage *pData, int pageSize){ + MemPage *pPage; + assert( (pageSize & 7)==0 ); + pPage = (MemPage *)sqlite3PagerGetExtra(pData); + if( pPage->isInit ){ + pPage->isInit = 0; + sqlite3BtreeInitPage(pPage, pPage->pParent); + } +} + +/* +** Open a database file. +** +** zFilename is the name of the database file. If zFilename is NULL +** a new database with a random name is created. This randomly named +** database file will be deleted when sqlite3BtreeClose() is called. +*/ +int sqlite3BtreeOpen( + const char *zFilename, /* Name of the file containing the BTree database */ + sqlite3 *pSqlite, /* Associated database handle */ + Btree **ppBtree, /* Pointer to new Btree object written here */ + int flags /* Options */ +){ + BtShared *pBt; /* Shared part of btree structure */ + Btree *p; /* Handle to return */ + int rc = SQLITE_OK; + int nReserve; + unsigned char zDbHeader[100]; +#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) + const ThreadData *pTsdro; +#endif + + /* Set the variable isMemdb to true for an in-memory database, or + ** false for a file-based database. This symbol is only required if + ** either of the shared-data or autovacuum features are compiled + ** into the library. + */ +#if !defined(SQLITE_OMIT_SHARED_CACHE) || !defined(SQLITE_OMIT_AUTOVACUUM) + #ifdef SQLITE_OMIT_MEMORYDB + const int isMemdb = 0; + #else + const int isMemdb = zFilename && !strcmp(zFilename, ":memory:"); + #endif +#endif + + p = sqliteMalloc(sizeof(Btree)); + if( !p ){ + return SQLITE_NOMEM; + } + p->inTrans = TRANS_NONE; + p->pSqlite = pSqlite; + + /* Try to find an existing Btree structure opened on zFilename. */ +#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) + pTsdro = sqlite3ThreadDataReadOnly(); + if( pTsdro->useSharedData && zFilename && !isMemdb ){ + char *zFullPathname = sqlite3OsFullPathname(zFilename); + if( !zFullPathname ){ + sqliteFree(p); + return SQLITE_NOMEM; + } + for(pBt=pTsdro->pBtree; pBt; pBt=pBt->pNext){ + assert( pBt->nRef>0 ); + if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager)) ){ + p->pBt = pBt; + *ppBtree = p; + pBt->nRef++; + sqliteFree(zFullPathname); + return SQLITE_OK; + } + } + sqliteFree(zFullPathname); + } +#endif + + /* + ** The following asserts make sure that structures used by the btree are + ** the right size. This is to guard against size changes that result + ** when compiling on a different architecture. + */ + assert( sizeof(i64)==8 || sizeof(i64)==4 ); + assert( sizeof(u64)==8 || sizeof(u64)==4 ); + assert( sizeof(u32)==4 ); + assert( sizeof(u16)==2 ); + assert( sizeof(Pgno)==4 ); + + pBt = sqliteMalloc( sizeof(*pBt) ); + if( pBt==0 ){ + rc = SQLITE_NOMEM; + goto btree_open_out; + } + rc = sqlite3PagerOpen(&pBt->pPager, zFilename, EXTRA_SIZE, flags); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader); + } + if( rc!=SQLITE_OK ){ + goto btree_open_out; + } + p->pBt = pBt; + + sqlite3PagerSetDestructor(pBt->pPager, pageDestructor); + sqlite3PagerSetReiniter(pBt->pPager, pageReinit); + pBt->pCursor = 0; + pBt->pPage1 = 0; + pBt->readOnly = sqlite3PagerIsreadonly(pBt->pPager); + pBt->pageSize = get2byte(&zDbHeader[16]); + if( pBt->pageSize<512 || pBt->pageSize>SQLITE_MAX_PAGE_SIZE + || ((pBt->pageSize-1)&pBt->pageSize)!=0 ){ + pBt->pageSize = SQLITE_DEFAULT_PAGE_SIZE; + pBt->maxEmbedFrac = 64; /* 25% */ + pBt->minEmbedFrac = 32; /* 12.5% */ + pBt->minLeafFrac = 32; /* 12.5% */ +#ifndef SQLITE_OMIT_AUTOVACUUM + /* If the magic name ":memory:" will create an in-memory database, then + ** leave the autoVacuum mode at 0 (do not auto-vacuum), even if + ** SQLITE_DEFAULT_AUTOVACUUM is true. On the other hand, if + ** SQLITE_OMIT_MEMORYDB has been defined, then ":memory:" is just a + ** regular file-name. In this case the auto-vacuum applies as per normal. + */ + if( zFilename && !isMemdb ){ + pBt->autoVacuum = (SQLITE_DEFAULT_AUTOVACUUM ? 1 : 0); + pBt->incrVacuum = (SQLITE_DEFAULT_AUTOVACUUM==2 ? 1 : 0); + } +#endif + nReserve = 0; + }else{ + nReserve = zDbHeader[20]; + pBt->maxEmbedFrac = zDbHeader[21]; + pBt->minEmbedFrac = zDbHeader[22]; + pBt->minLeafFrac = zDbHeader[23]; + pBt->pageSizeFixed = 1; +#ifndef SQLITE_OMIT_AUTOVACUUM + pBt->autoVacuum = (get4byte(&zDbHeader[36 + 4*4])?1:0); + pBt->incrVacuum = (get4byte(&zDbHeader[36 + 7*4])?1:0); +#endif + } + pBt->usableSize = pBt->pageSize - nReserve; + assert( (pBt->pageSize & 7)==0 ); /* 8-byte alignment of pageSize */ + sqlite3PagerSetPagesize(pBt->pPager, pBt->pageSize); + +#if !defined(SQLITE_OMIT_SHARED_CACHE) && !defined(SQLITE_OMIT_DISKIO) + /* Add the new btree to the linked list starting at ThreadData.pBtree. + ** There is no chance that a malloc() may fail inside of the + ** sqlite3ThreadData() call, as the ThreadData structure must have already + ** been allocated for pTsdro->useSharedData to be non-zero. + */ + if( pTsdro->useSharedData && zFilename && !isMemdb ){ + pBt->pNext = pTsdro->pBtree; + sqlite3ThreadData()->pBtree = pBt; + } +#endif + pBt->nRef = 1; + *ppBtree = p; + +btree_open_out: + if( rc!=SQLITE_OK ){ + if( pBt && pBt->pPager ){ + sqlite3PagerClose(pBt->pPager); + } + sqliteFree(pBt); + sqliteFree(p); + *ppBtree = 0; + } + return rc; +} + +/* +** Close an open database and invalidate all cursors. +*/ +int sqlite3BtreeClose(Btree *p){ + BtShared *pBt = p->pBt; + BtCursor *pCur; + +#ifndef SQLITE_OMIT_SHARED_CACHE + ThreadData *pTsd; +#endif + + /* Close all cursors opened via this handle. */ + pCur = pBt->pCursor; + while( pCur ){ + BtCursor *pTmp = pCur; + pCur = pCur->pNext; + if( pTmp->pBtree==p ){ + sqlite3BtreeCloseCursor(pTmp); + } + } + + /* Rollback any active transaction and free the handle structure. + ** The call to sqlite3BtreeRollback() drops any table-locks held by + ** this handle. + */ + sqlite3BtreeRollback(p); + sqliteFree(p); + +#ifndef SQLITE_OMIT_SHARED_CACHE + /* If there are still other outstanding references to the shared-btree + ** structure, return now. The remainder of this procedure cleans + ** up the shared-btree. + */ + assert( pBt->nRef>0 ); + pBt->nRef--; + if( pBt->nRef ){ + return SQLITE_OK; + } + + /* Remove the shared-btree from the thread wide list. Call + ** ThreadDataReadOnly() and then cast away the const property of the + ** pointer to avoid allocating thread data if it is not really required. + */ + pTsd = (ThreadData *)sqlite3ThreadDataReadOnly(); + if( pTsd->pBtree==pBt ){ + assert( pTsd==sqlite3ThreadData() ); + pTsd->pBtree = pBt->pNext; + }else{ + BtShared *pPrev; + for(pPrev=pTsd->pBtree; pPrev && pPrev->pNext!=pBt; pPrev=pPrev->pNext){} + if( pPrev ){ + assert( pTsd==sqlite3ThreadData() ); + pPrev->pNext = pBt->pNext; + } + } +#endif + + /* Close the pager and free the shared-btree structure */ + assert( !pBt->pCursor ); + sqlite3PagerClose(pBt->pPager); + if( pBt->xFreeSchema && pBt->pSchema ){ + pBt->xFreeSchema(pBt->pSchema); + } + sqliteFree(pBt->pSchema); + sqliteFree(pBt); + return SQLITE_OK; +} + +/* +** Change the busy handler callback function. +*/ +int sqlite3BtreeSetBusyHandler(Btree *p, BusyHandler *pHandler){ + BtShared *pBt = p->pBt; + pBt->pBusyHandler = pHandler; + sqlite3PagerSetBusyhandler(pBt->pPager, pHandler); + return SQLITE_OK; +} + +/* +** Change the limit on the number of pages allowed in the cache. +** +** The maximum number of cache pages is set to the absolute +** value of mxPage. If mxPage is negative, the pager will +** operate asynchronously - it will not stop to do fsync()s +** to insure data is written to the disk surface before +** continuing. Transactions still work if synchronous is off, +** and the database cannot be corrupted if this program +** crashes. But if the operating system crashes or there is +** an abrupt power failure when synchronous is off, the database +** could be left in an inconsistent and unrecoverable state. +** Synchronous is on by default so database corruption is not +** normally a worry. +*/ +int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){ + BtShared *pBt = p->pBt; + sqlite3PagerSetCachesize(pBt->pPager, mxPage); + return SQLITE_OK; +} + +/* +** Change the way data is synced to disk in order to increase or decrease +** how well the database resists damage due to OS crashes and power +** failures. Level 1 is the same as asynchronous (no syncs() occur and +** there is a high probability of damage) Level 2 is the default. There +** is a very low but non-zero probability of damage. Level 3 reduces the +** probability of damage to near zero but with a write performance reduction. +*/ +#ifndef SQLITE_OMIT_PAGER_PRAGMAS +int sqlite3BtreeSetSafetyLevel(Btree *p, int level, int fullSync){ + BtShared *pBt = p->pBt; + sqlite3PagerSetSafetyLevel(pBt->pPager, level, fullSync); + return SQLITE_OK; +} +#endif + +/* +** Return TRUE if the given btree is set to safety level 1. In other +** words, return TRUE if no sync() occurs on the disk files. +*/ +int sqlite3BtreeSyncDisabled(Btree *p){ + BtShared *pBt = p->pBt; + assert( pBt && pBt->pPager ); + return sqlite3PagerNosync(pBt->pPager); +} + +#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) +/* +** Change the default pages size and the number of reserved bytes per page. +** +** The page size must be a power of 2 between 512 and 65536. If the page +** size supplied does not meet this constraint then the page size is not +** changed. +** +** Page sizes are constrained to be a power of two so that the region +** of the database file used for locking (beginning at PENDING_BYTE, +** the first byte past the 1GB boundary, 0x40000000) needs to occur +** at the beginning of a page. +** +** If parameter nReserve is less than zero, then the number of reserved +** bytes per page is left unchanged. +*/ +int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve){ + BtShared *pBt = p->pBt; + if( pBt->pageSizeFixed ){ + return SQLITE_READONLY; + } + if( nReserve<0 ){ + nReserve = pBt->pageSize - pBt->usableSize; + } + if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE && + ((pageSize-1)&pageSize)==0 ){ + assert( (pageSize & 7)==0 ); + assert( !pBt->pPage1 && !pBt->pCursor ); + pBt->pageSize = sqlite3PagerSetPagesize(pBt->pPager, pageSize); + } + pBt->usableSize = pBt->pageSize - nReserve; + return SQLITE_OK; +} + +/* +** Return the currently defined page size +*/ +int sqlite3BtreeGetPageSize(Btree *p){ + return p->pBt->pageSize; +} +int sqlite3BtreeGetReserve(Btree *p){ + return p->pBt->pageSize - p->pBt->usableSize; +} + +/* +** Set the maximum page count for a database if mxPage is positive. +** No changes are made if mxPage is 0 or negative. +** Regardless of the value of mxPage, return the maximum page count. +*/ +int sqlite3BtreeMaxPageCount(Btree *p, int mxPage){ + return sqlite3PagerMaxPageCount(p->pBt->pPager, mxPage); +} +#endif /* !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) */ + +/* +** Change the 'auto-vacuum' property of the database. If the 'autoVacuum' +** parameter is non-zero, then auto-vacuum mode is enabled. If zero, it +** is disabled. The default value for the auto-vacuum property is +** determined by the SQLITE_DEFAULT_AUTOVACUUM macro. +*/ +int sqlite3BtreeSetAutoVacuum(Btree *p, int autoVacuum){ +#ifdef SQLITE_OMIT_AUTOVACUUM + return SQLITE_READONLY; +#else + BtShared *pBt = p->pBt; + int av = (autoVacuum?1:0); + if( pBt->pageSizeFixed && av!=pBt->autoVacuum ){ + return SQLITE_READONLY; + } + pBt->autoVacuum = av; + return SQLITE_OK; +#endif +} + +/* +** Return the value of the 'auto-vacuum' property. If auto-vacuum is +** enabled 1 is returned. Otherwise 0. +*/ +int sqlite3BtreeGetAutoVacuum(Btree *p){ +#ifdef SQLITE_OMIT_AUTOVACUUM + return BTREE_AUTOVACUUM_NONE; +#else + return ( + (!p->pBt->autoVacuum)?BTREE_AUTOVACUUM_NONE: + (!p->pBt->incrVacuum)?BTREE_AUTOVACUUM_FULL: + BTREE_AUTOVACUUM_INCR + ); +#endif +} + + +/* +** Get a reference to pPage1 of the database file. This will +** also acquire a readlock on that file. +** +** SQLITE_OK is returned on success. If the file is not a +** well-formed database file, then SQLITE_CORRUPT is returned. +** SQLITE_BUSY is returned if the database is locked. SQLITE_NOMEM +** is returned if we run out of memory. +*/ +static int lockBtree(BtShared *pBt){ + int rc, pageSize; + MemPage *pPage1; + if( pBt->pPage1 ) return SQLITE_OK; + rc = sqlite3BtreeGetPage(pBt, 1, &pPage1, 0); + if( rc!=SQLITE_OK ) return rc; + + + /* Do some checking to help insure the file we opened really is + ** a valid database file. + */ + rc = SQLITE_NOTADB; + if( sqlite3PagerPagecount(pBt->pPager)>0 ){ + u8 *page1 = pPage1->aData; + if( memcmp(page1, zMagicHeader, 16)!=0 ){ + goto page1_init_failed; + } + if( page1[18]>1 ){ + pBt->readOnly = 1; + } + if( page1[19]>1 ){ + goto page1_init_failed; + } + pageSize = get2byte(&page1[16]); + if( ((pageSize-1)&pageSize)!=0 || pageSize<512 ){ + goto page1_init_failed; + } + assert( (pageSize & 7)==0 ); + pBt->pageSize = pageSize; + pBt->usableSize = pageSize - page1[20]; + if( pBt->usableSize<500 ){ + goto page1_init_failed; + } + pBt->maxEmbedFrac = page1[21]; + pBt->minEmbedFrac = page1[22]; + pBt->minLeafFrac = page1[23]; +#ifndef SQLITE_OMIT_AUTOVACUUM + pBt->autoVacuum = (get4byte(&page1[36 + 4*4])?1:0); + pBt->incrVacuum = (get4byte(&page1[36 + 7*4])?1:0); +#endif + } + + /* maxLocal is the maximum amount of payload to store locally for + ** a cell. Make sure it is small enough so that at least minFanout + ** cells can will fit on one page. We assume a 10-byte page header. + ** Besides the payload, the cell must store: + ** 2-byte pointer to the cell + ** 4-byte child pointer + ** 9-byte nKey value + ** 4-byte nData value + ** 4-byte overflow page pointer + ** So a cell consists of a 2-byte poiner, a header which is as much as + ** 17 bytes long, 0 to N bytes of payload, and an optional 4 byte overflow + ** page pointer. + */ + pBt->maxLocal = (pBt->usableSize-12)*pBt->maxEmbedFrac/255 - 23; + pBt->minLocal = (pBt->usableSize-12)*pBt->minEmbedFrac/255 - 23; + pBt->maxLeaf = pBt->usableSize - 35; + pBt->minLeaf = (pBt->usableSize-12)*pBt->minLeafFrac/255 - 23; + if( pBt->minLocal>pBt->maxLocal || pBt->maxLocal<0 ){ + goto page1_init_failed; + } + assert( pBt->maxLeaf + 23 <= MX_CELL_SIZE(pBt) ); + pBt->pPage1 = pPage1; + return SQLITE_OK; + +page1_init_failed: + releasePage(pPage1); + pBt->pPage1 = 0; + return rc; +} + +/* +** This routine works like lockBtree() except that it also invokes the +** busy callback if there is lock contention. +*/ +static int lockBtreeWithRetry(Btree *pRef){ + int rc = SQLITE_OK; + if( pRef->inTrans==TRANS_NONE ){ + u8 inTransaction = pRef->pBt->inTransaction; + btreeIntegrity(pRef); + rc = sqlite3BtreeBeginTrans(pRef, 0); + pRef->pBt->inTransaction = inTransaction; + pRef->inTrans = TRANS_NONE; + if( rc==SQLITE_OK ){ + pRef->pBt->nTransaction--; + } + btreeIntegrity(pRef); + } + return rc; +} + + +/* +** If there are no outstanding cursors and we are not in the middle +** of a transaction but there is a read lock on the database, then +** this routine unrefs the first page of the database file which +** has the effect of releasing the read lock. +** +** If there are any outstanding cursors, this routine is a no-op. +** +** If there is a transaction in progress, this routine is a no-op. +*/ +static void unlockBtreeIfUnused(BtShared *pBt){ + if( pBt->inTransaction==TRANS_NONE && pBt->pCursor==0 && pBt->pPage1!=0 ){ + if( sqlite3PagerRefcount(pBt->pPager)>=1 ){ + if( pBt->pPage1->aData==0 ){ + MemPage *pPage = pBt->pPage1; + pPage->aData = &((u8*)pPage)[-pBt->pageSize]; + pPage->pBt = pBt; + pPage->pgno = 1; + } + releasePage(pBt->pPage1); + } + pBt->pPage1 = 0; + pBt->inStmt = 0; + } +} + +/* +** Create a new database by initializing the first page of the +** file. +*/ +static int newDatabase(BtShared *pBt){ + MemPage *pP1; + unsigned char *data; + int rc; + if( sqlite3PagerPagecount(pBt->pPager)>0 ) return SQLITE_OK; + pP1 = pBt->pPage1; + assert( pP1!=0 ); + data = pP1->aData; + rc = sqlite3PagerWrite(pP1->pDbPage); + if( rc ) return rc; + memcpy(data, zMagicHeader, sizeof(zMagicHeader)); + assert( sizeof(zMagicHeader)==16 ); + put2byte(&data[16], pBt->pageSize); + data[18] = 1; + data[19] = 1; + data[20] = pBt->pageSize - pBt->usableSize; + data[21] = pBt->maxEmbedFrac; + data[22] = pBt->minEmbedFrac; + data[23] = pBt->minLeafFrac; + memset(&data[24], 0, 100-24); + zeroPage(pP1, PTF_INTKEY|PTF_LEAF|PTF_LEAFDATA ); + pBt->pageSizeFixed = 1; +#ifndef SQLITE_OMIT_AUTOVACUUM + assert( pBt->autoVacuum==1 || pBt->autoVacuum==0 ); + assert( pBt->incrVacuum==1 || pBt->incrVacuum==0 ); + put4byte(&data[36 + 4*4], pBt->autoVacuum); + put4byte(&data[36 + 7*4], pBt->incrVacuum); +#endif + return SQLITE_OK; +} + +/* +** Attempt to start a new transaction. A write-transaction +** is started if the second argument is nonzero, otherwise a read- +** transaction. If the second argument is 2 or more and exclusive +** transaction is started, meaning that no other process is allowed +** to access the database. A preexisting transaction may not be +** upgraded to exclusive by calling this routine a second time - the +** exclusivity flag only works for a new transaction. +** +** A write-transaction must be started before attempting any +** changes to the database. None of the following routines +** will work unless a transaction is started first: +** +** sqlite3BtreeCreateTable() +** sqlite3BtreeCreateIndex() +** sqlite3BtreeClearTable() +** sqlite3BtreeDropTable() +** sqlite3BtreeInsert() +** sqlite3BtreeDelete() +** sqlite3BtreeUpdateMeta() +** +** If an initial attempt to acquire the lock fails because of lock contention +** and the database was previously unlocked, then invoke the busy handler +** if there is one. But if there was previously a read-lock, do not +** invoke the busy handler - just return SQLITE_BUSY. SQLITE_BUSY is +** returned when there is already a read-lock in order to avoid a deadlock. +** +** Suppose there are two processes A and B. A has a read lock and B has +** a reserved lock. B tries to promote to exclusive but is blocked because +** of A's read lock. A tries to promote to reserved but is blocked by B. +** One or the other of the two processes must give way or there can be +** no progress. By returning SQLITE_BUSY and not invoking the busy callback +** when A already has a read lock, we encourage A to give up and let B +** proceed. +*/ +int sqlite3BtreeBeginTrans(Btree *p, int wrflag){ + BtShared *pBt = p->pBt; + int rc = SQLITE_OK; + + btreeIntegrity(p); + + /* If the btree is already in a write-transaction, or it + ** is already in a read-transaction and a read-transaction + ** is requested, this is a no-op. + */ + if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){ + return SQLITE_OK; + } + + /* Write transactions are not possible on a read-only database */ + if( pBt->readOnly && wrflag ){ + return SQLITE_READONLY; + } + + /* If another database handle has already opened a write transaction + ** on this shared-btree structure and a second write transaction is + ** requested, return SQLITE_BUSY. + */ + if( pBt->inTransaction==TRANS_WRITE && wrflag ){ + return SQLITE_BUSY; + } + + do { + if( pBt->pPage1==0 ){ + rc = lockBtree(pBt); + } + + if( rc==SQLITE_OK && wrflag ){ + if( pBt->readOnly ){ + rc = SQLITE_READONLY; + }else{ + rc = sqlite3PagerBegin(pBt->pPage1->pDbPage, wrflag>1); + if( rc==SQLITE_OK ){ + rc = newDatabase(pBt); + } + } + } + + if( rc==SQLITE_OK ){ + if( wrflag ) pBt->inStmt = 0; + }else{ + unlockBtreeIfUnused(pBt); + } + }while( rc==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE && + sqlite3InvokeBusyHandler(pBt->pBusyHandler) ); + + if( rc==SQLITE_OK ){ + if( p->inTrans==TRANS_NONE ){ + pBt->nTransaction++; + } + p->inTrans = (wrflag?TRANS_WRITE:TRANS_READ); + if( p->inTrans>pBt->inTransaction ){ + pBt->inTransaction = p->inTrans; + } + } + + btreeIntegrity(p); + return rc; +} + +#ifndef SQLITE_OMIT_AUTOVACUUM + +/* +** Set the pointer-map entries for all children of page pPage. Also, if +** pPage contains cells that point to overflow pages, set the pointer +** map entries for the overflow pages as well. +*/ +static int setChildPtrmaps(MemPage *pPage){ + int i; /* Counter variable */ + int nCell; /* Number of cells in page pPage */ + int rc; /* Return code */ + BtShared *pBt = pPage->pBt; + int isInitOrig = pPage->isInit; + Pgno pgno = pPage->pgno; + + rc = sqlite3BtreeInitPage(pPage, pPage->pParent); + if( rc!=SQLITE_OK ){ + goto set_child_ptrmaps_out; + } + nCell = pPage->nCell; + + for(i=0; ileaf ){ + Pgno childPgno = get4byte(pCell); + rc = ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno); + if( rc!=SQLITE_OK ) goto set_child_ptrmaps_out; + } + } + + if( !pPage->leaf ){ + Pgno childPgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); + rc = ptrmapPut(pBt, childPgno, PTRMAP_BTREE, pgno); + } + +set_child_ptrmaps_out: + pPage->isInit = isInitOrig; + return rc; +} + +/* +** Somewhere on pPage, which is guarenteed to be a btree page, not an overflow +** page, is a pointer to page iFrom. Modify this pointer so that it points to +** iTo. Parameter eType describes the type of pointer to be modified, as +** follows: +** +** PTRMAP_BTREE: pPage is a btree-page. The pointer points at a child +** page of pPage. +** +** PTRMAP_OVERFLOW1: pPage is a btree-page. The pointer points at an overflow +** page pointed to by one of the cells on pPage. +** +** PTRMAP_OVERFLOW2: pPage is an overflow-page. The pointer points at the next +** overflow page in the list. +*/ +static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ + if( eType==PTRMAP_OVERFLOW2 ){ + /* The pointer is always the first 4 bytes of the page in this case. */ + if( get4byte(pPage->aData)!=iFrom ){ + return SQLITE_CORRUPT_BKPT; + } + put4byte(pPage->aData, iTo); + }else{ + int isInitOrig = pPage->isInit; + int i; + int nCell; + + sqlite3BtreeInitPage(pPage, 0); + nCell = pPage->nCell; + + for(i=0; iaData[pPage->hdrOffset+8])!=iFrom ){ + return SQLITE_CORRUPT_BKPT; + } + put4byte(&pPage->aData[pPage->hdrOffset+8], iTo); + } + + pPage->isInit = isInitOrig; + } + return SQLITE_OK; +} + + +/* +** Move the open database page pDbPage to location iFreePage in the +** database. The pDbPage reference remains valid. +*/ +static int relocatePage( + BtShared *pBt, /* Btree */ + MemPage *pDbPage, /* Open page to move */ + u8 eType, /* Pointer map 'type' entry for pDbPage */ + Pgno iPtrPage, /* Pointer map 'page-no' entry for pDbPage */ + Pgno iFreePage /* The location to move pDbPage to */ +){ + MemPage *pPtrPage; /* The page that contains a pointer to pDbPage */ + Pgno iDbPage = pDbPage->pgno; + Pager *pPager = pBt->pPager; + int rc; + + assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 || + eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE ); + + /* Move page iDbPage from it's current location to page number iFreePage */ + TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n", + iDbPage, iFreePage, iPtrPage, eType)); + rc = sqlite3PagerMovepage(pPager, pDbPage->pDbPage, iFreePage); + if( rc!=SQLITE_OK ){ + return rc; + } + pDbPage->pgno = iFreePage; + + /* If pDbPage was a btree-page, then it may have child pages and/or cells + ** that point to overflow pages. The pointer map entries for all these + ** pages need to be changed. + ** + ** If pDbPage is an overflow page, then the first 4 bytes may store a + ** pointer to a subsequent overflow page. If this is the case, then + ** the pointer map needs to be updated for the subsequent overflow page. + */ + if( eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE ){ + rc = setChildPtrmaps(pDbPage); + if( rc!=SQLITE_OK ){ + return rc; + } + }else{ + Pgno nextOvfl = get4byte(pDbPage->aData); + if( nextOvfl!=0 ){ + rc = ptrmapPut(pBt, nextOvfl, PTRMAP_OVERFLOW2, iFreePage); + if( rc!=SQLITE_OK ){ + return rc; + } + } + } + + /* Fix the database pointer on page iPtrPage that pointed at iDbPage so + ** that it points at iFreePage. Also fix the pointer map entry for + ** iPtrPage. + */ + if( eType!=PTRMAP_ROOTPAGE ){ + rc = sqlite3BtreeGetPage(pBt, iPtrPage, &pPtrPage, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + rc = sqlite3PagerWrite(pPtrPage->pDbPage); + if( rc!=SQLITE_OK ){ + releasePage(pPtrPage); + return rc; + } + rc = modifyPagePointer(pPtrPage, iDbPage, iFreePage, eType); + releasePage(pPtrPage); + if( rc==SQLITE_OK ){ + rc = ptrmapPut(pBt, iFreePage, eType, iPtrPage); + } + } + return rc; +} + +/* Forward declaration required by incrVacuumStep(). */ +static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8); + +/* +** Perform a single step of an incremental-vacuum. If successful, +** return SQLITE_OK. If there is no work to do (and therefore no +** point in calling this function again), return SQLITE_DONE. +** +** More specificly, this function attempts to re-organize the +** database so that the last page of the file currently in use +** is no longer in use. +** +** If the nFin parameter is non-zero, the implementation assumes +** that the caller will keep calling incrVacuumStep() until +** it returns SQLITE_DONE or an error, and that nFin is the +** number of pages the database file will contain after this +** process is complete. +*/ +static int incrVacuumStep(BtShared *pBt, Pgno nFin){ + Pgno iLastPg; /* Last page in the database */ + Pgno nFreeList; /* Number of pages still on the free-list */ + + iLastPg = pBt->nTrunc; + if( iLastPg==0 ){ + iLastPg = sqlite3PagerPagecount(pBt->pPager); + } + + if( !PTRMAP_ISPAGE(pBt, iLastPg) && iLastPg!=PENDING_BYTE_PAGE(pBt) ){ + int rc; + u8 eType; + Pgno iPtrPage; + + nFreeList = get4byte(&pBt->pPage1->aData[36]); + if( nFreeList==0 || nFin==iLastPg ){ + return SQLITE_DONE; + } + + rc = ptrmapGet(pBt, iLastPg, &eType, &iPtrPage); + if( rc!=SQLITE_OK ){ + return rc; + } + if( eType==PTRMAP_ROOTPAGE ){ + return SQLITE_CORRUPT_BKPT; + } + + if( eType==PTRMAP_FREEPAGE ){ + if( nFin==0 ){ + /* Remove the page from the files free-list. This is not required + ** if nFin is non-zero. In that case, the free-list will be + ** truncated to zero after this function returns, so it doesn't + ** matter if it still contains some garbage entries. + */ + Pgno iFreePg; + MemPage *pFreePg; + rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iLastPg, 1); + if( rc!=SQLITE_OK ){ + return rc; + } + assert( iFreePg==iLastPg ); + releasePage(pFreePg); + } + } else { + Pgno iFreePg; /* Index of free page to move pLastPg to */ + MemPage *pLastPg; + + rc = sqlite3BtreeGetPage(pBt, iLastPg, &pLastPg, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + + /* If nFin is zero, this loop runs exactly once and page pLastPg + ** is swapped with the first free page pulled off the free list. + ** + ** On the other hand, if nFin is greater than zero, then keep + ** looping until a free-page located within the first nFin pages + ** of the file is found. + */ + do { + MemPage *pFreePg; + rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, 0, 0); + if( rc!=SQLITE_OK ){ + releasePage(pLastPg); + return rc; + } + releasePage(pFreePg); + }while( nFin!=0 && iFreePg>nFin ); + assert( iFreePgpDbPage); + if( rc!=SQLITE_OK ){ + return rc; + } + rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg); + releasePage(pLastPg); + if( rc!=SQLITE_OK ){ + return rc; + } + } + } + + pBt->nTrunc = iLastPg - 1; + while( pBt->nTrunc==PENDING_BYTE_PAGE(pBt)||PTRMAP_ISPAGE(pBt, pBt->nTrunc) ){ + pBt->nTrunc--; + } + return SQLITE_OK; +} + +/* +** A write-transaction must be opened before calling this function. +** It performs a single unit of work towards an incremental vacuum. +** +** If the incremental vacuum is finished after this function has run, +** SQLITE_DONE is returned. If it is not finished, but no error occured, +** SQLITE_OK is returned. Otherwise an SQLite error code. +*/ +int sqlite3BtreeIncrVacuum(Btree *p){ + BtShared *pBt = p->pBt; + assert( pBt->inTransaction==TRANS_WRITE && p->inTrans==TRANS_WRITE ); + if( !pBt->autoVacuum ){ + return SQLITE_DONE; + } + invalidateAllOverflowCache(pBt); + return incrVacuumStep(pBt, 0); +} + +/* +** This routine is called prior to sqlite3PagerCommit when a transaction +** is commited for an auto-vacuum database. +** +** If SQLITE_OK is returned, then *pnTrunc is set to the number of pages +** the database file should be truncated to during the commit process. +** i.e. the database has been reorganized so that only the first *pnTrunc +** pages are in use. +*/ +static int autoVacuumCommit(BtShared *pBt, Pgno *pnTrunc){ + int rc = SQLITE_OK; + Pager *pPager = pBt->pPager; +#ifndef NDEBUG + int nRef = sqlite3PagerRefcount(pPager); +#endif + + invalidateAllOverflowCache(pBt); + assert(pBt->autoVacuum); + if( !pBt->incrVacuum ){ + Pgno nFin = 0; + + if( pBt->nTrunc==0 ){ + Pgno nFree; + Pgno nPtrmap; + const int pgsz = pBt->pageSize; + Pgno nOrig = sqlite3PagerPagecount(pBt->pPager); + + if( PTRMAP_ISPAGE(pBt, nOrig) ){ + return SQLITE_CORRUPT_BKPT; + } + if( nOrig==PENDING_BYTE_PAGE(pBt) ){ + nOrig--; + } + nFree = get4byte(&pBt->pPage1->aData[36]); + nPtrmap = (nFree-nOrig+PTRMAP_PAGENO(pBt, nOrig)+pgsz/5)/(pgsz/5); + nFin = nOrig - nFree - nPtrmap; + if( nOrig>(unsigned)PENDING_BYTE_PAGE(pBt) && nFin<=PENDING_BYTE_PAGE(pBt) ){ + nFin--; + } + while( PTRMAP_ISPAGE(pBt, nFin) || nFin==PENDING_BYTE_PAGE(pBt) ){ + nFin--; + } + } + + while( rc==SQLITE_OK ){ + rc = incrVacuumStep(pBt, nFin); + } + if( rc==SQLITE_DONE ){ + assert(nFin==0 || pBt->nTrunc==0 || nFin<=pBt->nTrunc); + rc = SQLITE_OK; + if( pBt->nTrunc ){ + sqlite3PagerWrite(pBt->pPage1->pDbPage); + put4byte(&pBt->pPage1->aData[32], 0); + put4byte(&pBt->pPage1->aData[36], 0); + pBt->nTrunc = nFin; + } + } + if( rc!=SQLITE_OK ){ + sqlite3PagerRollback(pPager); + } + } + + if( rc==SQLITE_OK ){ + *pnTrunc = pBt->nTrunc; + pBt->nTrunc = 0; + } + assert( nRef==sqlite3PagerRefcount(pPager) ); + return rc; +} + +#endif + +/* +** This routine does the first phase of a two-phase commit. This routine +** causes a rollback journal to be created (if it does not already exist) +** and populated with enough information so that if a power loss occurs +** the database can be restored to its original state by playing back +** the journal. Then the contents of the journal are flushed out to +** the disk. After the journal is safely on oxide, the changes to the +** database are written into the database file and flushed to oxide. +** At the end of this call, the rollback journal still exists on the +** disk and we are still holding all locks, so the transaction has not +** committed. See sqlite3BtreeCommit() for the second phase of the +** commit process. +** +** This call is a no-op if no write-transaction is currently active on pBt. +** +** Otherwise, sync the database file for the btree pBt. zMaster points to +** the name of a master journal file that should be written into the +** individual journal file, or is NULL, indicating no master journal file +** (single database transaction). +** +** When this is called, the master journal should already have been +** created, populated with this journal pointer and synced to disk. +** +** Once this is routine has returned, the only thing required to commit +** the write-transaction for this database file is to delete the journal. +*/ +int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){ + int rc = SQLITE_OK; + if( p->inTrans==TRANS_WRITE ){ + BtShared *pBt = p->pBt; + Pgno nTrunc = 0; +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ + rc = autoVacuumCommit(pBt, &nTrunc); + if( rc!=SQLITE_OK ){ + return rc; + } + } +#endif + rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, nTrunc); + } + return rc; +} + +/* +** Commit the transaction currently in progress. +** +** This routine implements the second phase of a 2-phase commit. The +** sqlite3BtreeSync() routine does the first phase and should be invoked +** prior to calling this routine. The sqlite3BtreeSync() routine did +** all the work of writing information out to disk and flushing the +** contents so that they are written onto the disk platter. All this +** routine has to do is delete or truncate the rollback journal +** (which causes the transaction to commit) and drop locks. +** +** This will release the write lock on the database file. If there +** are no active cursors, it also releases the read lock. +*/ +int sqlite3BtreeCommitPhaseTwo(Btree *p){ + BtShared *pBt = p->pBt; + + btreeIntegrity(p); + + /* If the handle has a write-transaction open, commit the shared-btrees + ** transaction and set the shared state to TRANS_READ. + */ + if( p->inTrans==TRANS_WRITE ){ + int rc; + assert( pBt->inTransaction==TRANS_WRITE ); + assert( pBt->nTransaction>0 ); + rc = sqlite3PagerCommitPhaseTwo(pBt->pPager); + if( rc!=SQLITE_OK ){ + return rc; + } + pBt->inTransaction = TRANS_READ; + pBt->inStmt = 0; + } + unlockAllTables(p); + + /* If the handle has any kind of transaction open, decrement the transaction + ** count of the shared btree. If the transaction count reaches 0, set + ** the shared state to TRANS_NONE. The unlockBtreeIfUnused() call below + ** will unlock the pager. + */ + if( p->inTrans!=TRANS_NONE ){ + pBt->nTransaction--; + if( 0==pBt->nTransaction ){ + pBt->inTransaction = TRANS_NONE; + } + } + + /* Set the handles current transaction state to TRANS_NONE and unlock + ** the pager if this call closed the only read or write transaction. + */ + p->inTrans = TRANS_NONE; + unlockBtreeIfUnused(pBt); + + btreeIntegrity(p); + return SQLITE_OK; +} + +/* +** Do both phases of a commit. +*/ +int sqlite3BtreeCommit(Btree *p){ + int rc; + rc = sqlite3BtreeCommitPhaseOne(p, 0); + if( rc==SQLITE_OK ){ + rc = sqlite3BtreeCommitPhaseTwo(p); + } + return rc; +} + +#ifndef NDEBUG +/* +** Return the number of write-cursors open on this handle. This is for use +** in assert() expressions, so it is only compiled if NDEBUG is not +** defined. +*/ +static int countWriteCursors(BtShared *pBt){ + BtCursor *pCur; + int r = 0; + for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){ + if( pCur->wrFlag ) r++; + } + return r; +} +#endif + +/* +** Rollback the transaction in progress. All cursors will be +** invalided by this operation. Any attempt to use a cursor +** that was open at the beginning of this operation will result +** in an error. +** +** This will release the write lock on the database file. If there +** are no active cursors, it also releases the read lock. +*/ +int sqlite3BtreeRollback(Btree *p){ + int rc; + BtShared *pBt = p->pBt; + MemPage *pPage1; + + rc = saveAllCursors(pBt, 0, 0); +#ifndef SQLITE_OMIT_SHARED_CACHE + if( rc!=SQLITE_OK ){ + /* This is a horrible situation. An IO or malloc() error occured whilst + ** trying to save cursor positions. If this is an automatic rollback (as + ** the result of a constraint, malloc() failure or IO error) then + ** the cache may be internally inconsistent (not contain valid trees) so + ** we cannot simply return the error to the caller. Instead, abort + ** all queries that may be using any of the cursors that failed to save. + */ + while( pBt->pCursor ){ + sqlite3 *db = pBt->pCursor->pBtree->pSqlite; + if( db ){ + sqlite3AbortOtherActiveVdbes(db, 0); + } + } + } +#endif + btreeIntegrity(p); + unlockAllTables(p); + + if( p->inTrans==TRANS_WRITE ){ + int rc2; + +#ifndef SQLITE_OMIT_AUTOVACUUM + pBt->nTrunc = 0; +#endif + + assert( TRANS_WRITE==pBt->inTransaction ); + rc2 = sqlite3PagerRollback(pBt->pPager); + if( rc2!=SQLITE_OK ){ + rc = rc2; + } + + /* The rollback may have destroyed the pPage1->aData value. So + ** call sqlite3BtreeGetPage() on page 1 again to make + ** sure pPage1->aData is set correctly. */ + if( sqlite3BtreeGetPage(pBt, 1, &pPage1, 0)==SQLITE_OK ){ + releasePage(pPage1); + } + assert( countWriteCursors(pBt)==0 ); + pBt->inTransaction = TRANS_READ; + } + + if( p->inTrans!=TRANS_NONE ){ + assert( pBt->nTransaction>0 ); + pBt->nTransaction--; + if( 0==pBt->nTransaction ){ + pBt->inTransaction = TRANS_NONE; + } + } + + p->inTrans = TRANS_NONE; + pBt->inStmt = 0; + unlockBtreeIfUnused(pBt); + + btreeIntegrity(p); + return rc; +} + +/* +** Start a statement subtransaction. The subtransaction can +** can be rolled back independently of the main transaction. +** You must start a transaction before starting a subtransaction. +** The subtransaction is ended automatically if the main transaction +** commits or rolls back. +** +** Only one subtransaction may be active at a time. It is an error to try +** to start a new subtransaction if another subtransaction is already active. +** +** Statement subtransactions are used around individual SQL statements +** that are contained within a BEGIN...COMMIT block. If a constraint +** error occurs within the statement, the effect of that one statement +** can be rolled back without having to rollback the entire transaction. +*/ +int sqlite3BtreeBeginStmt(Btree *p){ + int rc; + BtShared *pBt = p->pBt; + if( (p->inTrans!=TRANS_WRITE) || pBt->inStmt ){ + return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; + } + assert( pBt->inTransaction==TRANS_WRITE ); + rc = pBt->readOnly ? SQLITE_OK : sqlite3PagerStmtBegin(pBt->pPager); + pBt->inStmt = 1; + return rc; +} + + +/* +** Commit the statment subtransaction currently in progress. If no +** subtransaction is active, this is a no-op. +*/ +int sqlite3BtreeCommitStmt(Btree *p){ + int rc; + BtShared *pBt = p->pBt; + if( pBt->inStmt && !pBt->readOnly ){ + rc = sqlite3PagerStmtCommit(pBt->pPager); + }else{ + rc = SQLITE_OK; + } + pBt->inStmt = 0; + return rc; +} + +/* +** Rollback the active statement subtransaction. If no subtransaction +** is active this routine is a no-op. +** +** All cursors will be invalidated by this operation. Any attempt +** to use a cursor that was open at the beginning of this operation +** will result in an error. +*/ +int sqlite3BtreeRollbackStmt(Btree *p){ + int rc = SQLITE_OK; + BtShared *pBt = p->pBt; + sqlite3MallocDisallow(); + if( pBt->inStmt && !pBt->readOnly ){ + rc = sqlite3PagerStmtRollback(pBt->pPager); + assert( countWriteCursors(pBt)==0 ); + pBt->inStmt = 0; + } + sqlite3MallocAllow(); + return rc; +} + +/* +** Default key comparison function to be used if no comparison function +** is specified on the sqlite3BtreeCursor() call. +*/ +static int dfltCompare( + void *NotUsed, /* User data is not used */ + int n1, const void *p1, /* First key to compare */ + int n2, const void *p2 /* Second key to compare */ +){ + int c; + c = memcmp(p1, p2, n1pBt; + + *ppCur = 0; + if( wrFlag ){ + if( pBt->readOnly ){ + return SQLITE_READONLY; + } + if( checkReadLocks(p, iTable, 0) ){ + return SQLITE_LOCKED; + } + } + + if( pBt->pPage1==0 ){ + rc = lockBtreeWithRetry(p); + if( rc!=SQLITE_OK ){ + return rc; + } + if( pBt->readOnly && wrFlag ){ + return SQLITE_READONLY; + } + } + pCur = sqliteMalloc( sizeof(*pCur) ); + if( pCur==0 ){ + rc = SQLITE_NOMEM; + goto create_cursor_exception; + } + pCur->pgnoRoot = (Pgno)iTable; + if( iTable==1 && sqlite3PagerPagecount(pBt->pPager)==0 ){ + rc = SQLITE_EMPTY; + goto create_cursor_exception; + } + rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->pPage, 0); + if( rc!=SQLITE_OK ){ + goto create_cursor_exception; + } + + /* Now that no other errors can occur, finish filling in the BtCursor + ** variables, link the cursor into the BtShared list and set *ppCur (the + ** output argument to this function). + */ + pCur->xCompare = xCmp ? xCmp : dfltCompare; + pCur->pArg = pArg; + pCur->pBtree = p; + pCur->wrFlag = wrFlag; + pCur->pNext = pBt->pCursor; + if( pCur->pNext ){ + pCur->pNext->pPrev = pCur; + } + pBt->pCursor = pCur; + pCur->eState = CURSOR_INVALID; + *ppCur = pCur; + + return SQLITE_OK; +create_cursor_exception: + if( pCur ){ + releasePage(pCur->pPage); + sqliteFree(pCur); + } + unlockBtreeIfUnused(pBt); + return rc; +} + +/* +** Close a cursor. The read lock on the database file is released +** when the last cursor is closed. +*/ +int sqlite3BtreeCloseCursor(BtCursor *pCur){ + BtShared *pBt = pCur->pBtree->pBt; + clearCursorPosition(pCur); + if( pCur->pPrev ){ + pCur->pPrev->pNext = pCur->pNext; + }else{ + pBt->pCursor = pCur->pNext; + } + if( pCur->pNext ){ + pCur->pNext->pPrev = pCur->pPrev; + } + releasePage(pCur->pPage); + unlockBtreeIfUnused(pBt); + invalidateOverflowCache(pCur); + sqliteFree(pCur); + return SQLITE_OK; +} + +/* +** Make a temporary cursor by filling in the fields of pTempCur. +** The temporary cursor is not on the cursor list for the Btree. +*/ +void sqlite3BtreeGetTempCursor(BtCursor *pCur, BtCursor *pTempCur){ + memcpy(pTempCur, pCur, sizeof(*pCur)); + pTempCur->pNext = 0; + pTempCur->pPrev = 0; + if( pTempCur->pPage ){ + sqlite3PagerRef(pTempCur->pPage->pDbPage); + } +} + +/* +** Delete a temporary cursor such as was made by the CreateTemporaryCursor() +** function above. +*/ +void sqlite3BtreeReleaseTempCursor(BtCursor *pCur){ + if( pCur->pPage ){ + sqlite3PagerUnref(pCur->pPage->pDbPage); + } +} + +/* +** Make sure the BtCursor* given in the argument has a valid +** BtCursor.info structure. If it is not already valid, call +** sqlite3BtreeParseCell() to fill it in. +** +** BtCursor.info is a cache of the information in the current cell. +** Using this cache reduces the number of calls to sqlite3BtreeParseCell(). +** +** 2007-06-25: There is a bug in some versions of MSVC that cause the +** compiler to crash when getCellInfo() is implemented as a macro. +** But there is a measureable speed advantage to using the macro on gcc +** (when less compiler optimizations like -Os or -O0 are used and the +** compiler is not doing agressive inlining.) So we use a real function +** for MSVC and a macro for everything else. Ticket #2457. +*/ +#ifndef NDEBUG + static void assertCellInfo(BtCursor *pCur){ + CellInfo info; + memset(&info, 0, sizeof(info)); + sqlite3BtreeParseCell(pCur->pPage, pCur->idx, &info); + assert( memcmp(&info, &pCur->info, sizeof(info))==0 ); + } +#else + #define assertCellInfo(x) +#endif +#ifdef _MSC_VER + /* Use a real function in MSVC to work around bugs in that compiler. */ + static void getCellInfo(BtCursor *pCur){ + if( pCur->info.nSize==0 ){ + sqlite3BtreeParseCell(pCur->pPage, pCur->idx, &pCur->info); + }else{ + assertCellInfo(pCur); + } + } +#else /* if not _MSC_VER */ + /* Use a macro in all other compilers so that the function is inlined */ +#define getCellInfo(pCur) \ + if( pCur->info.nSize==0 ){ \ + sqlite3BtreeParseCell(pCur->pPage, pCur->idx, &pCur->info); \ + }else{ \ + assertCellInfo(pCur); \ + } +#endif /* _MSC_VER */ + +/* +** Set *pSize to the size of the buffer needed to hold the value of +** the key for the current entry. If the cursor is not pointing +** to a valid entry, *pSize is set to 0. +** +** For a table with the INTKEY flag set, this routine returns the key +** itself, not the number of bytes in the key. +*/ +int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ + int rc = restoreOrClearCursorPosition(pCur); + if( rc==SQLITE_OK ){ + assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID ); + if( pCur->eState==CURSOR_INVALID ){ + *pSize = 0; + }else{ + getCellInfo(pCur); + *pSize = pCur->info.nKey; + } + } + return rc; +} + +/* +** Set *pSize to the number of bytes of data in the entry the +** cursor currently points to. Always return SQLITE_OK. +** Failure is not possible. If the cursor is not currently +** pointing to an entry (which can happen, for example, if +** the database is empty) then *pSize is set to 0. +*/ +int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){ + int rc = restoreOrClearCursorPosition(pCur); + if( rc==SQLITE_OK ){ + assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID ); + if( pCur->eState==CURSOR_INVALID ){ + /* Not pointing at a valid entry - set *pSize to 0. */ + *pSize = 0; + }else{ + getCellInfo(pCur); + *pSize = pCur->info.nData; + } + } + return rc; +} + +/* +** Given the page number of an overflow page in the database (parameter +** ovfl), this function finds the page number of the next page in the +** linked list of overflow pages. If possible, it uses the auto-vacuum +** pointer-map data instead of reading the content of page ovfl to do so. +** +** If an error occurs an SQLite error code is returned. Otherwise: +** +** Unless pPgnoNext is NULL, the page number of the next overflow +** page in the linked list is written to *pPgnoNext. If page ovfl +** is the last page in it's linked list, *pPgnoNext is set to zero. +** +** If ppPage is not NULL, *ppPage is set to the MemPage* handle +** for page ovfl. The underlying pager page may have been requested +** with the noContent flag set, so the page data accessable via +** this handle may not be trusted. +*/ +static int getOverflowPage( + BtShared *pBt, + Pgno ovfl, /* Overflow page */ + MemPage **ppPage, /* OUT: MemPage handle */ + Pgno *pPgnoNext /* OUT: Next overflow page number */ +){ + Pgno next = 0; + int rc; + + /* One of these must not be NULL. Otherwise, why call this function? */ + assert(ppPage || pPgnoNext); + + /* If pPgnoNext is NULL, then this function is being called to obtain + ** a MemPage* reference only. No page-data is required in this case. + */ + if( !pPgnoNext ){ + return sqlite3BtreeGetPage(pBt, ovfl, ppPage, 1); + } + +#ifndef SQLITE_OMIT_AUTOVACUUM + /* Try to find the next page in the overflow list using the + ** autovacuum pointer-map pages. Guess that the next page in + ** the overflow list is page number (ovfl+1). If that guess turns + ** out to be wrong, fall back to loading the data of page + ** number ovfl to determine the next page number. + */ + if( pBt->autoVacuum ){ + Pgno pgno; + Pgno iGuess = ovfl+1; + u8 eType; + + while( PTRMAP_ISPAGE(pBt, iGuess) || iGuess==PENDING_BYTE_PAGE(pBt) ){ + iGuess++; + } + + if( iGuess<=sqlite3PagerPagecount(pBt->pPager) ){ + rc = ptrmapGet(pBt, iGuess, &eType, &pgno); + if( rc!=SQLITE_OK ){ + return rc; + } + if( eType==PTRMAP_OVERFLOW2 && pgno==ovfl ){ + next = iGuess; + } + } + } +#endif + + if( next==0 || ppPage ){ + MemPage *pPage = 0; + + rc = sqlite3BtreeGetPage(pBt, ovfl, &pPage, next!=0); + assert(rc==SQLITE_OK || pPage==0); + if( next==0 && rc==SQLITE_OK ){ + next = get4byte(pPage->aData); + } + + if( ppPage ){ + *ppPage = pPage; + }else{ + releasePage(pPage); + } + } + *pPgnoNext = next; + + return rc; +} + +/* +** Copy data from a buffer to a page, or from a page to a buffer. +** +** pPayload is a pointer to data stored on database page pDbPage. +** If argument eOp is false, then nByte bytes of data are copied +** from pPayload to the buffer pointed at by pBuf. If eOp is true, +** then sqlite3PagerWrite() is called on pDbPage and nByte bytes +** of data are copied from the buffer pBuf to pPayload. +** +** SQLITE_OK is returned on success, otherwise an error code. +*/ +static int copyPayload( + void *pPayload, /* Pointer to page data */ + void *pBuf, /* Pointer to buffer */ + int nByte, /* Number of bytes to copy */ + int eOp, /* 0 -> copy from page, 1 -> copy to page */ + DbPage *pDbPage /* Page containing pPayload */ +){ + if( eOp ){ + /* Copy data from buffer to page (a write operation) */ + int rc = sqlite3PagerWrite(pDbPage); + if( rc!=SQLITE_OK ){ + return rc; + } + memcpy(pPayload, pBuf, nByte); + }else{ + /* Copy data from page to buffer (a read operation) */ + memcpy(pBuf, pPayload, nByte); + } + return SQLITE_OK; +} + +/* +** This function is used to read or overwrite payload information +** for the entry that the pCur cursor is pointing to. If the eOp +** parameter is 0, this is a read operation (data copied into +** buffer pBuf). If it is non-zero, a write (data copied from +** buffer pBuf). +** +** A total of "amt" bytes are read or written beginning at "offset". +** Data is read to or from the buffer pBuf. +** +** This routine does not make a distinction between key and data. +** It just reads or writes bytes from the payload area. Data might +** appear on the main page or be scattered out on multiple overflow +** pages. +** +** If the BtCursor.isIncrblobHandle flag is set, and the current +** cursor entry uses one or more overflow pages, this function +** allocates space for and lazily popluates the overflow page-list +** cache array (BtCursor.aOverflow). Subsequent calls use this +** cache to make seeking to the supplied offset more efficient. +** +** Once an overflow page-list cache has been allocated, it may be +** invalidated if some other cursor writes to the same table, or if +** the cursor is moved to a different row. Additionally, in auto-vacuum +** mode, the following events may invalidate an overflow page-list cache. +** +** * An incremental vacuum, +** * A commit in auto_vacuum="full" mode, +** * Creating a table (may require moving an overflow page). +*/ +static int accessPayload( + BtCursor *pCur, /* Cursor pointing to entry to read from */ + int offset, /* Begin reading this far into payload */ + int amt, /* Read this many bytes */ + unsigned char *pBuf, /* Write the bytes into this buffer */ + int skipKey, /* offset begins at data if this is true */ + int eOp /* zero to read. non-zero to write. */ +){ + unsigned char *aPayload; + int rc = SQLITE_OK; + u32 nKey; + int iIdx = 0; + MemPage *pPage = pCur->pPage; /* Btree page of current cursor entry */ + BtShared *pBt = pCur->pBtree->pBt; /* Btree this cursor belongs to */ + + assert( pPage ); + assert( pCur->eState==CURSOR_VALID ); + assert( pCur->idx>=0 && pCur->idxnCell ); + assert( offset>=0 ); + + getCellInfo(pCur); + aPayload = pCur->info.pCell + pCur->info.nHeader; + nKey = (pPage->intKey ? 0 : pCur->info.nKey); + + if( skipKey ){ + offset += nKey; + } + if( offset+amt > nKey+pCur->info.nData ){ + /* Trying to read or write past the end of the data is an error */ + return SQLITE_ERROR; + } + + /* Check if data must be read/written to/from the btree page itself. */ + if( offsetinfo.nLocal ){ + int a = amt; + if( a+offset>pCur->info.nLocal ){ + a = pCur->info.nLocal - offset; + } + rc = copyPayload(&aPayload[offset], pBuf, a, eOp, pPage->pDbPage); + offset = 0; + pBuf += a; + amt -= a; + }else{ + offset -= pCur->info.nLocal; + } + + if( rc==SQLITE_OK && amt>0 ){ + const int ovflSize = pBt->usableSize - 4; /* Bytes content per ovfl page */ + Pgno nextPage; + + nextPage = get4byte(&aPayload[pCur->info.nLocal]); + +#ifndef SQLITE_OMIT_INCRBLOB + /* If the isIncrblobHandle flag is set and the BtCursor.aOverflow[] + ** has not been allocated, allocate it now. The array is sized at + ** one entry for each overflow page in the overflow chain. The + ** page number of the first overflow page is stored in aOverflow[0], + ** etc. A value of 0 in the aOverflow[] array means "not yet known" + ** (the cache is lazily populated). + */ + if( pCur->isIncrblobHandle && !pCur->aOverflow ){ + int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize; + pCur->aOverflow = (Pgno *)sqliteMalloc(sizeof(Pgno)*nOvfl); + if( nOvfl && !pCur->aOverflow ){ + rc = SQLITE_NOMEM; + } + } + + /* If the overflow page-list cache has been allocated and the + ** entry for the first required overflow page is valid, skip + ** directly to it. + */ + if( pCur->aOverflow && pCur->aOverflow[offset/ovflSize] ){ + iIdx = (offset/ovflSize); + nextPage = pCur->aOverflow[iIdx]; + offset = (offset%ovflSize); + } +#endif + + for( ; rc==SQLITE_OK && amt>0 && nextPage; iIdx++){ + +#ifndef SQLITE_OMIT_INCRBLOB + /* If required, populate the overflow page-list cache. */ + if( pCur->aOverflow ){ + assert(!pCur->aOverflow[iIdx] || pCur->aOverflow[iIdx]==nextPage); + pCur->aOverflow[iIdx] = nextPage; + } +#endif + + if( offset>=ovflSize ){ + /* The only reason to read this page is to obtain the page + ** number for the next page in the overflow chain. The page + ** data is not required. So first try to lookup the overflow + ** page-list cache, if any, then fall back to the getOverflowPage() + ** function. + */ +#ifndef SQLITE_OMIT_INCRBLOB + if( pCur->aOverflow && pCur->aOverflow[iIdx+1] ){ + nextPage = pCur->aOverflow[iIdx+1]; + } else +#endif + rc = getOverflowPage(pBt, nextPage, 0, &nextPage); + offset -= ovflSize; + }else{ + /* Need to read this page properly. It contains some of the + ** range of data that is being read (eOp==0) or written (eOp!=0). + */ + DbPage *pDbPage; + int a = amt; + rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage); + if( rc==SQLITE_OK ){ + aPayload = sqlite3PagerGetData(pDbPage); + nextPage = get4byte(aPayload); + if( a + offset > ovflSize ){ + a = ovflSize - offset; + } + rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage); + sqlite3PagerUnref(pDbPage); + offset = 0; + amt -= a; + pBuf += a; + } + } + } + } + + if( rc==SQLITE_OK && amt>0 ){ + return SQLITE_CORRUPT_BKPT; + } + return rc; +} + +/* +** Read part of the key associated with cursor pCur. Exactly +** "amt" bytes will be transfered into pBuf[]. The transfer +** begins at "offset". +** +** Return SQLITE_OK on success or an error code if anything goes +** wrong. An error is returned if "offset+amt" is larger than +** the available payload. +*/ +int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ + int rc = restoreOrClearCursorPosition(pCur); + if( rc==SQLITE_OK ){ + assert( pCur->eState==CURSOR_VALID ); + assert( pCur->pPage!=0 ); + if( pCur->pPage->intKey ){ + return SQLITE_CORRUPT_BKPT; + } + assert( pCur->pPage->intKey==0 ); + assert( pCur->idx>=0 && pCur->idxpPage->nCell ); + rc = accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0, 0); + } + return rc; +} + +/* +** Read part of the data associated with cursor pCur. Exactly +** "amt" bytes will be transfered into pBuf[]. The transfer +** begins at "offset". +** +** Return SQLITE_OK on success or an error code if anything goes +** wrong. An error is returned if "offset+amt" is larger than +** the available payload. +*/ +int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ + int rc = restoreOrClearCursorPosition(pCur); + if( rc==SQLITE_OK ){ + assert( pCur->eState==CURSOR_VALID ); + assert( pCur->pPage!=0 ); + assert( pCur->idx>=0 && pCur->idxpPage->nCell ); + rc = accessPayload(pCur, offset, amt, pBuf, 1, 0); + } + return rc; +} + +/* +** Return a pointer to payload information from the entry that the +** pCur cursor is pointing to. The pointer is to the beginning of +** the key if skipKey==0 and it points to the beginning of data if +** skipKey==1. The number of bytes of available key/data is written +** into *pAmt. If *pAmt==0, then the value returned will not be +** a valid pointer. +** +** This routine is an optimization. It is common for the entire key +** and data to fit on the local page and for there to be no overflow +** pages. When that is so, this routine can be used to access the +** key and data without making a copy. If the key and/or data spills +** onto overflow pages, then accessPayload() must be used to reassembly +** the key/data and copy it into a preallocated buffer. +** +** The pointer returned by this routine looks directly into the cached +** page of the database. The data might change or move the next time +** any btree routine is called. +*/ +static const unsigned char *fetchPayload( + BtCursor *pCur, /* Cursor pointing to entry to read from */ + int *pAmt, /* Write the number of available bytes here */ + int skipKey /* read beginning at data if this is true */ +){ + unsigned char *aPayload; + MemPage *pPage; + u32 nKey; + int nLocal; + + assert( pCur!=0 && pCur->pPage!=0 ); + assert( pCur->eState==CURSOR_VALID ); + pPage = pCur->pPage; + assert( pCur->idx>=0 && pCur->idxnCell ); + getCellInfo(pCur); + aPayload = pCur->info.pCell; + aPayload += pCur->info.nHeader; + if( pPage->intKey ){ + nKey = 0; + }else{ + nKey = pCur->info.nKey; + } + if( skipKey ){ + aPayload += nKey; + nLocal = pCur->info.nLocal - nKey; + }else{ + nLocal = pCur->info.nLocal; + if( nLocal>nKey ){ + nLocal = nKey; + } + } + *pAmt = nLocal; + return aPayload; +} + + +/* +** For the entry that cursor pCur is point to, return as +** many bytes of the key or data as are available on the local +** b-tree page. Write the number of available bytes into *pAmt. +** +** The pointer returned is ephemeral. The key/data may move +** or be destroyed on the next call to any Btree routine. +** +** These routines is used to get quick access to key and data +** in the common case where no overflow pages are used. +*/ +const void *sqlite3BtreeKeyFetch(BtCursor *pCur, int *pAmt){ + if( pCur->eState==CURSOR_VALID ){ + return (const void*)fetchPayload(pCur, pAmt, 0); + } + return 0; +} +const void *sqlite3BtreeDataFetch(BtCursor *pCur, int *pAmt){ + if( pCur->eState==CURSOR_VALID ){ + return (const void*)fetchPayload(pCur, pAmt, 1); + } + return 0; +} + + +/* +** Move the cursor down to a new child page. The newPgno argument is the +** page number of the child page to move to. +*/ +static int moveToChild(BtCursor *pCur, u32 newPgno){ + int rc; + MemPage *pNewPage; + MemPage *pOldPage; + BtShared *pBt = pCur->pBtree->pBt; + + assert( pCur->eState==CURSOR_VALID ); + rc = getAndInitPage(pBt, newPgno, &pNewPage, pCur->pPage); + if( rc ) return rc; + pNewPage->idxParent = pCur->idx; + pOldPage = pCur->pPage; + pOldPage->idxShift = 0; + releasePage(pOldPage); + pCur->pPage = pNewPage; + pCur->idx = 0; + pCur->info.nSize = 0; + if( pNewPage->nCell<1 ){ + return SQLITE_CORRUPT_BKPT; + } + return SQLITE_OK; +} + +/* +** Return true if the page is the virtual root of its table. +** +** The virtual root page is the root page for most tables. But +** for the table rooted on page 1, sometime the real root page +** is empty except for the right-pointer. In such cases the +** virtual root page is the page that the right-pointer of page +** 1 is pointing to. +*/ +int sqlite3BtreeIsRootPage(MemPage *pPage){ + MemPage *pParent = pPage->pParent; + if( pParent==0 ) return 1; + if( pParent->pgno>1 ) return 0; + if( get2byte(&pParent->aData[pParent->hdrOffset+3])==0 ) return 1; + return 0; +} + +/* +** Move the cursor up to the parent page. +** +** pCur->idx is set to the cell index that contains the pointer +** to the page we are coming from. If we are coming from the +** right-most child page then pCur->idx is set to one more than +** the largest cell index. +*/ +void sqlite3BtreeMoveToParent(BtCursor *pCur){ + MemPage *pParent; + MemPage *pPage; + int idxParent; + + assert( pCur->eState==CURSOR_VALID ); + pPage = pCur->pPage; + assert( pPage!=0 ); + assert( !sqlite3BtreeIsRootPage(pPage) ); + pParent = pPage->pParent; + assert( pParent!=0 ); + idxParent = pPage->idxParent; + sqlite3PagerRef(pParent->pDbPage); + releasePage(pPage); + pCur->pPage = pParent; + pCur->info.nSize = 0; + assert( pParent->idxShift==0 ); + pCur->idx = idxParent; +} + +/* +** Move the cursor to the root page +*/ +static int moveToRoot(BtCursor *pCur){ + MemPage *pRoot; + int rc = SQLITE_OK; + BtShared *pBt = pCur->pBtree->pBt; + + if( pCur->eState==CURSOR_REQUIRESEEK ){ + clearCursorPosition(pCur); + } + pRoot = pCur->pPage; + if( pRoot && pRoot->pgno==pCur->pgnoRoot ){ + assert( pRoot->isInit ); + }else{ + if( + SQLITE_OK!=(rc = getAndInitPage(pBt, pCur->pgnoRoot, &pRoot, 0)) + ){ + pCur->eState = CURSOR_INVALID; + return rc; + } + releasePage(pCur->pPage); + pCur->pPage = pRoot; + } + pCur->idx = 0; + pCur->info.nSize = 0; + if( pRoot->nCell==0 && !pRoot->leaf ){ + Pgno subpage; + assert( pRoot->pgno==1 ); + subpage = get4byte(&pRoot->aData[pRoot->hdrOffset+8]); + assert( subpage>0 ); + pCur->eState = CURSOR_VALID; + rc = moveToChild(pCur, subpage); + } + pCur->eState = ((pCur->pPage->nCell>0)?CURSOR_VALID:CURSOR_INVALID); + return rc; +} + +/* +** Move the cursor down to the left-most leaf entry beneath the +** entry to which it is currently pointing. +** +** The left-most leaf is the one with the smallest key - the first +** in ascending order. +*/ +static int moveToLeftmost(BtCursor *pCur){ + Pgno pgno; + int rc; + MemPage *pPage; + + assert( pCur->eState==CURSOR_VALID ); + while( !(pPage = pCur->pPage)->leaf ){ + assert( pCur->idx>=0 && pCur->idxnCell ); + pgno = get4byte(findCell(pPage, pCur->idx)); + rc = moveToChild(pCur, pgno); + if( rc ) return rc; + } + return SQLITE_OK; +} + +/* +** Move the cursor down to the right-most leaf entry beneath the +** page to which it is currently pointing. Notice the difference +** between moveToLeftmost() and moveToRightmost(). moveToLeftmost() +** finds the left-most entry beneath the *entry* whereas moveToRightmost() +** finds the right-most entry beneath the *page*. +** +** The right-most entry is the one with the largest key - the last +** key in ascending order. +*/ +static int moveToRightmost(BtCursor *pCur){ + Pgno pgno; + int rc; + MemPage *pPage; + + assert( pCur->eState==CURSOR_VALID ); + while( !(pPage = pCur->pPage)->leaf ){ + pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); + pCur->idx = pPage->nCell; + rc = moveToChild(pCur, pgno); + if( rc ) return rc; + } + pCur->idx = pPage->nCell - 1; + pCur->info.nSize = 0; + return SQLITE_OK; +} + +/* Move the cursor to the first entry in the table. Return SQLITE_OK +** on success. Set *pRes to 0 if the cursor actually points to something +** or set *pRes to 1 if the table is empty. +*/ +int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){ + int rc; + rc = moveToRoot(pCur); + if( rc ) return rc; + if( pCur->eState==CURSOR_INVALID ){ + assert( pCur->pPage->nCell==0 ); + *pRes = 1; + return SQLITE_OK; + } + assert( pCur->pPage->nCell>0 ); + *pRes = 0; + rc = moveToLeftmost(pCur); + return rc; +} + +/* Move the cursor to the last entry in the table. Return SQLITE_OK +** on success. Set *pRes to 0 if the cursor actually points to something +** or set *pRes to 1 if the table is empty. +*/ +int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ + int rc; + rc = moveToRoot(pCur); + if( rc ) return rc; + if( CURSOR_INVALID==pCur->eState ){ + assert( pCur->pPage->nCell==0 ); + *pRes = 1; + return SQLITE_OK; + } + assert( pCur->eState==CURSOR_VALID ); + *pRes = 0; + rc = moveToRightmost(pCur); + return rc; +} + +/* Move the cursor so that it points to an entry near pKey/nKey. +** Return a success code. +** +** For INTKEY tables, only the nKey parameter is used. pKey is +** ignored. For other tables, nKey is the number of bytes of data +** in pKey. The comparison function specified when the cursor was +** created is used to compare keys. +** +** If an exact match is not found, then the cursor is always +** left pointing at a leaf page which would hold the entry if it +** were present. The cursor might point to an entry that comes +** before or after the key. +** +** The result of comparing the key with the entry to which the +** cursor is written to *pRes if pRes!=NULL. The meaning of +** this value is as follows: +** +** *pRes<0 The cursor is left pointing at an entry that +** is smaller than pKey or if the table is empty +** and the cursor is therefore left point to nothing. +** +** *pRes==0 The cursor is left pointing at an entry that +** exactly matches pKey. +** +** *pRes>0 The cursor is left pointing at an entry that +** is larger than pKey. +*/ +int sqlite3BtreeMoveto( + BtCursor *pCur, /* The cursor to be moved */ + const void *pKey, /* The key content for indices. Not used by tables */ + i64 nKey, /* Size of pKey. Or the key for tables */ + int biasRight, /* If true, bias the search to the high end */ + int *pRes /* Search result flag */ +){ + int rc; + rc = moveToRoot(pCur); + if( rc ) return rc; + assert( pCur->pPage ); + assert( pCur->pPage->isInit ); + if( pCur->eState==CURSOR_INVALID ){ + *pRes = -1; + assert( pCur->pPage->nCell==0 ); + return SQLITE_OK; + } + for(;;){ + int lwr, upr; + Pgno chldPg; + MemPage *pPage = pCur->pPage; + int c = -1; /* pRes return if table is empty must be -1 */ + lwr = 0; + upr = pPage->nCell-1; + if( !pPage->intKey && pKey==0 ){ + return SQLITE_CORRUPT_BKPT; + } + if( biasRight ){ + pCur->idx = upr; + }else{ + pCur->idx = (upr+lwr)/2; + } + if( lwr<=upr ) for(;;){ + void *pCellKey; + i64 nCellKey; + pCur->info.nSize = 0; + if( pPage->intKey ){ + u8 *pCell; + pCell = findCell(pPage, pCur->idx) + pPage->childPtrSize; + if( pPage->hasData ){ + u32 dummy; + pCell += getVarint32(pCell, &dummy); + } + getVarint(pCell, (u64 *)&nCellKey); + if( nCellKeynKey ){ + c = +1; + }else{ + c = 0; + } + }else{ + int available; + pCellKey = (void *)fetchPayload(pCur, &available, 0); + nCellKey = pCur->info.nKey; + if( available>=nCellKey ){ + c = pCur->xCompare(pCur->pArg, nCellKey, pCellKey, nKey, pKey); + }else{ + pCellKey = sqliteMallocRaw( nCellKey ); + if( pCellKey==0 ) return SQLITE_NOMEM; + rc = sqlite3BtreeKey(pCur, 0, nCellKey, (void *)pCellKey); + c = pCur->xCompare(pCur->pArg, nCellKey, pCellKey, nKey, pKey); + sqliteFree(pCellKey); + if( rc ) return rc; + } + } + if( c==0 ){ + if( pPage->leafData && !pPage->leaf ){ + lwr = pCur->idx; + upr = lwr - 1; + break; + }else{ + if( pRes ) *pRes = 0; + return SQLITE_OK; + } + } + if( c<0 ){ + lwr = pCur->idx+1; + }else{ + upr = pCur->idx-1; + } + if( lwr>upr ){ + break; + } + pCur->idx = (lwr+upr)/2; + } + assert( lwr==upr+1 ); + assert( pPage->isInit ); + if( pPage->leaf ){ + chldPg = 0; + }else if( lwr>=pPage->nCell ){ + chldPg = get4byte(&pPage->aData[pPage->hdrOffset+8]); + }else{ + chldPg = get4byte(findCell(pPage, lwr)); + } + if( chldPg==0 ){ + assert( pCur->idx>=0 && pCur->idxpPage->nCell ); + if( pRes ) *pRes = c; + return SQLITE_OK; + } + pCur->idx = lwr; + pCur->info.nSize = 0; + rc = moveToChild(pCur, chldPg); + if( rc ){ + return rc; + } + } + /* NOT REACHED */ +} + +/* +** Return TRUE if the cursor is not pointing at an entry of the table. +** +** TRUE will be returned after a call to sqlite3BtreeNext() moves +** past the last entry in the table or sqlite3BtreePrev() moves past +** the first entry. TRUE is also returned if the table is empty. +*/ +int sqlite3BtreeEof(BtCursor *pCur){ + /* TODO: What if the cursor is in CURSOR_REQUIRESEEK but all table entries + ** have been deleted? This API will need to change to return an error code + ** as well as the boolean result value. + */ + return (CURSOR_VALID!=pCur->eState); +} + +/* +** Advance the cursor to the next entry in the database. If +** successful then set *pRes=0. If the cursor +** was already pointing to the last entry in the database before +** this routine was called, then set *pRes=1. +*/ +int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ + int rc; + MemPage *pPage; + + rc = restoreOrClearCursorPosition(pCur); + if( rc!=SQLITE_OK ){ + return rc; + } + assert( pRes!=0 ); + pPage = pCur->pPage; + if( CURSOR_INVALID==pCur->eState ){ + *pRes = 1; + return SQLITE_OK; + } + if( pCur->skip>0 ){ + pCur->skip = 0; + *pRes = 0; + return SQLITE_OK; + } + pCur->skip = 0; + + assert( pPage->isInit ); + assert( pCur->idxnCell ); + + pCur->idx++; + pCur->info.nSize = 0; + if( pCur->idx>=pPage->nCell ){ + if( !pPage->leaf ){ + rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8])); + if( rc ) return rc; + rc = moveToLeftmost(pCur); + *pRes = 0; + return rc; + } + do{ + if( sqlite3BtreeIsRootPage(pPage) ){ + *pRes = 1; + pCur->eState = CURSOR_INVALID; + return SQLITE_OK; + } + sqlite3BtreeMoveToParent(pCur); + pPage = pCur->pPage; + }while( pCur->idx>=pPage->nCell ); + *pRes = 0; + if( pPage->leafData ){ + rc = sqlite3BtreeNext(pCur, pRes); + }else{ + rc = SQLITE_OK; + } + return rc; + } + *pRes = 0; + if( pPage->leaf ){ + return SQLITE_OK; + } + rc = moveToLeftmost(pCur); + return rc; +} + +/* +** Step the cursor to the back to the previous entry in the database. If +** successful then set *pRes=0. If the cursor +** was already pointing to the first entry in the database before +** this routine was called, then set *pRes=1. +*/ +int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ + int rc; + Pgno pgno; + MemPage *pPage; + + rc = restoreOrClearCursorPosition(pCur); + if( rc!=SQLITE_OK ){ + return rc; + } + if( CURSOR_INVALID==pCur->eState ){ + *pRes = 1; + return SQLITE_OK; + } + if( pCur->skip<0 ){ + pCur->skip = 0; + *pRes = 0; + return SQLITE_OK; + } + pCur->skip = 0; + + pPage = pCur->pPage; + assert( pPage->isInit ); + assert( pCur->idx>=0 ); + if( !pPage->leaf ){ + pgno = get4byte( findCell(pPage, pCur->idx) ); + rc = moveToChild(pCur, pgno); + if( rc ) return rc; + rc = moveToRightmost(pCur); + }else{ + while( pCur->idx==0 ){ + if( sqlite3BtreeIsRootPage(pPage) ){ + pCur->eState = CURSOR_INVALID; + *pRes = 1; + return SQLITE_OK; + } + sqlite3BtreeMoveToParent(pCur); + pPage = pCur->pPage; + } + pCur->idx--; + pCur->info.nSize = 0; + if( pPage->leafData && !pPage->leaf ){ + rc = sqlite3BtreePrevious(pCur, pRes); + }else{ + rc = SQLITE_OK; + } + } + *pRes = 0; + return rc; +} + +/* +** Allocate a new page from the database file. +** +** The new page is marked as dirty. (In other words, sqlite3PagerWrite() +** has already been called on the new page.) The new page has also +** been referenced and the calling routine is responsible for calling +** sqlite3PagerUnref() on the new page when it is done. +** +** SQLITE_OK is returned on success. Any other return value indicates +** an error. *ppPage and *pPgno are undefined in the event of an error. +** Do not invoke sqlite3PagerUnref() on *ppPage if an error is returned. +** +** If the "nearby" parameter is not 0, then a (feeble) effort is made to +** locate a page close to the page number "nearby". This can be used in an +** attempt to keep related pages close to each other in the database file, +** which in turn can make database access faster. +** +** If the "exact" parameter is not 0, and the page-number nearby exists +** anywhere on the free-list, then it is guarenteed to be returned. This +** is only used by auto-vacuum databases when allocating a new table. +*/ +static int allocateBtreePage( + BtShared *pBt, + MemPage **ppPage, + Pgno *pPgno, + Pgno nearby, + u8 exact +){ + MemPage *pPage1; + int rc; + int n; /* Number of pages on the freelist */ + int k; /* Number of leaves on the trunk of the freelist */ + MemPage *pTrunk = 0; + MemPage *pPrevTrunk = 0; + + pPage1 = pBt->pPage1; + n = get4byte(&pPage1->aData[36]); + if( n>0 ){ + /* There are pages on the freelist. Reuse one of those pages. */ + Pgno iTrunk; + u8 searchList = 0; /* If the free-list must be searched for 'nearby' */ + + /* If the 'exact' parameter was true and a query of the pointer-map + ** shows that the page 'nearby' is somewhere on the free-list, then + ** the entire-list will be searched for that page. + */ +#ifndef SQLITE_OMIT_AUTOVACUUM + if( exact && nearby<=sqlite3PagerPagecount(pBt->pPager) ){ + u8 eType; + assert( nearby>0 ); + assert( pBt->autoVacuum ); + rc = ptrmapGet(pBt, nearby, &eType, 0); + if( rc ) return rc; + if( eType==PTRMAP_FREEPAGE ){ + searchList = 1; + } + *pPgno = nearby; + } +#endif + + /* Decrement the free-list count by 1. Set iTrunk to the index of the + ** first free-list trunk page. iPrevTrunk is initially 1. + */ + rc = sqlite3PagerWrite(pPage1->pDbPage); + if( rc ) return rc; + put4byte(&pPage1->aData[36], n-1); + + /* The code within this loop is run only once if the 'searchList' variable + ** is not true. Otherwise, it runs once for each trunk-page on the + ** free-list until the page 'nearby' is located. + */ + do { + pPrevTrunk = pTrunk; + if( pPrevTrunk ){ + iTrunk = get4byte(&pPrevTrunk->aData[0]); + }else{ + iTrunk = get4byte(&pPage1->aData[32]); + } + rc = sqlite3BtreeGetPage(pBt, iTrunk, &pTrunk, 0); + if( rc ){ + pTrunk = 0; + goto end_allocate_page; + } + + k = get4byte(&pTrunk->aData[4]); + if( k==0 && !searchList ){ + /* The trunk has no leaves and the list is not being searched. + ** So extract the trunk page itself and use it as the newly + ** allocated page */ + assert( pPrevTrunk==0 ); + rc = sqlite3PagerWrite(pTrunk->pDbPage); + if( rc ){ + goto end_allocate_page; + } + *pPgno = iTrunk; + memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4); + *ppPage = pTrunk; + pTrunk = 0; + TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1)); + }else if( k>pBt->usableSize/4 - 8 ){ + /* Value of k is out of range. Database corruption */ + rc = SQLITE_CORRUPT_BKPT; + goto end_allocate_page; +#ifndef SQLITE_OMIT_AUTOVACUUM + }else if( searchList && nearby==iTrunk ){ + /* The list is being searched and this trunk page is the page + ** to allocate, regardless of whether it has leaves. + */ + assert( *pPgno==iTrunk ); + *ppPage = pTrunk; + searchList = 0; + rc = sqlite3PagerWrite(pTrunk->pDbPage); + if( rc ){ + goto end_allocate_page; + } + if( k==0 ){ + if( !pPrevTrunk ){ + memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4); + }else{ + memcpy(&pPrevTrunk->aData[0], &pTrunk->aData[0], 4); + } + }else{ + /* The trunk page is required by the caller but it contains + ** pointers to free-list leaves. The first leaf becomes a trunk + ** page in this case. + */ + MemPage *pNewTrunk; + Pgno iNewTrunk = get4byte(&pTrunk->aData[8]); + rc = sqlite3BtreeGetPage(pBt, iNewTrunk, &pNewTrunk, 0); + if( rc!=SQLITE_OK ){ + goto end_allocate_page; + } + rc = sqlite3PagerWrite(pNewTrunk->pDbPage); + if( rc!=SQLITE_OK ){ + releasePage(pNewTrunk); + goto end_allocate_page; + } + memcpy(&pNewTrunk->aData[0], &pTrunk->aData[0], 4); + put4byte(&pNewTrunk->aData[4], k-1); + memcpy(&pNewTrunk->aData[8], &pTrunk->aData[12], (k-1)*4); + releasePage(pNewTrunk); + if( !pPrevTrunk ){ + put4byte(&pPage1->aData[32], iNewTrunk); + }else{ + rc = sqlite3PagerWrite(pPrevTrunk->pDbPage); + if( rc ){ + goto end_allocate_page; + } + put4byte(&pPrevTrunk->aData[0], iNewTrunk); + } + } + pTrunk = 0; + TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1)); +#endif + }else{ + /* Extract a leaf from the trunk */ + int closest; + Pgno iPage; + unsigned char *aData = pTrunk->aData; + rc = sqlite3PagerWrite(pTrunk->pDbPage); + if( rc ){ + goto end_allocate_page; + } + if( nearby>0 ){ + int i, dist; + closest = 0; + dist = get4byte(&aData[8]) - nearby; + if( dist<0 ) dist = -dist; + for(i=1; isqlite3PagerPagecount(pBt->pPager) ){ + /* Free page off the end of the file */ + return SQLITE_CORRUPT_BKPT; + } + TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d" + ": %d more free pages\n", + *pPgno, closest+1, k, pTrunk->pgno, n-1)); + if( closestpDbPage); + rc = sqlite3PagerWrite((*ppPage)->pDbPage); + if( rc!=SQLITE_OK ){ + releasePage(*ppPage); + } + } + searchList = 0; + } + } + releasePage(pPrevTrunk); + pPrevTrunk = 0; + }while( searchList ); + }else{ + /* There are no pages on the freelist, so create a new page at the + ** end of the file */ + *pPgno = sqlite3PagerPagecount(pBt->pPager) + 1; + +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->nTrunc ){ + /* An incr-vacuum has already run within this transaction. So the + ** page to allocate is not from the physical end of the file, but + ** at pBt->nTrunc. + */ + *pPgno = pBt->nTrunc+1; + if( *pPgno==PENDING_BYTE_PAGE(pBt) ){ + (*pPgno)++; + } + } + if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt, *pPgno) ){ + /* If *pPgno refers to a pointer-map page, allocate two new pages + ** at the end of the file instead of one. The first allocated page + ** becomes a new pointer-map page, the second is used by the caller. + */ + TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", *pPgno)); + assert( *pPgno!=PENDING_BYTE_PAGE(pBt) ); + (*pPgno)++; + } + if( pBt->nTrunc ){ + pBt->nTrunc = *pPgno; + } +#endif + + assert( *pPgno!=PENDING_BYTE_PAGE(pBt) ); + rc = sqlite3BtreeGetPage(pBt, *pPgno, ppPage, 0); + if( rc ) return rc; + rc = sqlite3PagerWrite((*ppPage)->pDbPage); + if( rc!=SQLITE_OK ){ + releasePage(*ppPage); + } + TRACE(("ALLOCATE: %d from end of file\n", *pPgno)); + } + + assert( *pPgno!=PENDING_BYTE_PAGE(pBt) ); + +end_allocate_page: + releasePage(pTrunk); + releasePage(pPrevTrunk); + return rc; +} + +/* +** Add a page of the database file to the freelist. +** +** sqlite3PagerUnref() is NOT called for pPage. +*/ +static int freePage(MemPage *pPage){ + BtShared *pBt = pPage->pBt; + MemPage *pPage1 = pBt->pPage1; + int rc, n, k; + + /* Prepare the page for freeing */ + assert( pPage->pgno>1 ); + pPage->isInit = 0; + releasePage(pPage->pParent); + pPage->pParent = 0; + + /* Increment the free page count on pPage1 */ + rc = sqlite3PagerWrite(pPage1->pDbPage); + if( rc ) return rc; + n = get4byte(&pPage1->aData[36]); + put4byte(&pPage1->aData[36], n+1); + +#ifdef SQLITE_SECURE_DELETE + /* If the SQLITE_SECURE_DELETE compile-time option is enabled, then + ** always fully overwrite deleted information with zeros. + */ + rc = sqlite3PagerWrite(pPage->pDbPage); + if( rc ) return rc; + memset(pPage->aData, 0, pPage->pBt->pageSize); +#endif + +#ifndef SQLITE_OMIT_AUTOVACUUM + /* If the database supports auto-vacuum, write an entry in the pointer-map + ** to indicate that the page is free. + */ + if( pBt->autoVacuum ){ + rc = ptrmapPut(pBt, pPage->pgno, PTRMAP_FREEPAGE, 0); + if( rc ) return rc; + } +#endif + + if( n==0 ){ + /* This is the first free page */ + rc = sqlite3PagerWrite(pPage->pDbPage); + if( rc ) return rc; + memset(pPage->aData, 0, 8); + put4byte(&pPage1->aData[32], pPage->pgno); + TRACE(("FREE-PAGE: %d first\n", pPage->pgno)); + }else{ + /* Other free pages already exist. Retrive the first trunk page + ** of the freelist and find out how many leaves it has. */ + MemPage *pTrunk; + rc = sqlite3BtreeGetPage(pBt, get4byte(&pPage1->aData[32]), &pTrunk, 0); + if( rc ) return rc; + k = get4byte(&pTrunk->aData[4]); + if( k>=pBt->usableSize/4 - 8 ){ + /* The trunk is full. Turn the page being freed into a new + ** trunk page with no leaves. */ + rc = sqlite3PagerWrite(pPage->pDbPage); + if( rc ) return rc; + put4byte(pPage->aData, pTrunk->pgno); + put4byte(&pPage->aData[4], 0); + put4byte(&pPage1->aData[32], pPage->pgno); + TRACE(("FREE-PAGE: %d new trunk page replacing %d\n", + pPage->pgno, pTrunk->pgno)); + }else{ + /* Add the newly freed page as a leaf on the current trunk */ + rc = sqlite3PagerWrite(pTrunk->pDbPage); + if( rc==SQLITE_OK ){ + put4byte(&pTrunk->aData[4], k+1); + put4byte(&pTrunk->aData[8+k*4], pPage->pgno); +#ifndef SQLITE_SECURE_DELETE + sqlite3PagerDontWrite(pPage->pDbPage); +#endif + } + TRACE(("FREE-PAGE: %d leaf on trunk page %d\n",pPage->pgno,pTrunk->pgno)); + } + releasePage(pTrunk); + } + return rc; +} + +/* +** Free any overflow pages associated with the given Cell. +*/ +static int clearCell(MemPage *pPage, unsigned char *pCell){ + BtShared *pBt = pPage->pBt; + CellInfo info; + Pgno ovflPgno; + int rc; + int nOvfl; + int ovflPageSize; + + sqlite3BtreeParseCellPtr(pPage, pCell, &info); + if( info.iOverflow==0 ){ + return SQLITE_OK; /* No overflow pages. Return without doing anything */ + } + ovflPgno = get4byte(&pCell[info.iOverflow]); + ovflPageSize = pBt->usableSize - 4; + nOvfl = (info.nPayload - info.nLocal + ovflPageSize - 1)/ovflPageSize; + assert( ovflPgno==0 || nOvfl>0 ); + while( nOvfl-- ){ + MemPage *pOvfl; + if( ovflPgno==0 || ovflPgno>sqlite3PagerPagecount(pBt->pPager) ){ + return SQLITE_CORRUPT_BKPT; + } + + rc = getOverflowPage(pBt, ovflPgno, &pOvfl, (nOvfl==0)?0:&ovflPgno); + if( rc ) return rc; + rc = freePage(pOvfl); + sqlite3PagerUnref(pOvfl->pDbPage); + if( rc ) return rc; + } + return SQLITE_OK; +} + +/* +** Create the byte sequence used to represent a cell on page pPage +** and write that byte sequence into pCell[]. Overflow pages are +** allocated and filled in as necessary. The calling procedure +** is responsible for making sure sufficient space has been allocated +** for pCell[]. +** +** Note that pCell does not necessary need to point to the pPage->aData +** area. pCell might point to some temporary storage. The cell will +** be constructed in this temporary area then copied into pPage->aData +** later. +*/ +static int fillInCell( + MemPage *pPage, /* The page that contains the cell */ + unsigned char *pCell, /* Complete text of the cell */ + const void *pKey, i64 nKey, /* The key */ + const void *pData,int nData, /* The data */ + int nZero, /* Extra zero bytes to append to pData */ + int *pnSize /* Write cell size here */ +){ + int nPayload; + const u8 *pSrc; + int nSrc, n, rc; + int spaceLeft; + MemPage *pOvfl = 0; + MemPage *pToRelease = 0; + unsigned char *pPrior; + unsigned char *pPayload; + BtShared *pBt = pPage->pBt; + Pgno pgnoOvfl = 0; + int nHeader; + CellInfo info; + + /* Fill in the header. */ + nHeader = 0; + if( !pPage->leaf ){ + nHeader += 4; + } + if( pPage->hasData ){ + nHeader += putVarint(&pCell[nHeader], nData+nZero); + }else{ + nData = nZero = 0; + } + nHeader += putVarint(&pCell[nHeader], *(u64*)&nKey); + sqlite3BtreeParseCellPtr(pPage, pCell, &info); + assert( info.nHeader==nHeader ); + assert( info.nKey==nKey ); + assert( info.nData==nData+nZero ); + + /* Fill in the payload */ + nPayload = nData + nZero; + if( pPage->intKey ){ + pSrc = pData; + nSrc = nData; + nData = 0; + }else{ + nPayload += nKey; + pSrc = pKey; + nSrc = nKey; + } + *pnSize = info.nSize; + spaceLeft = info.nLocal; + pPayload = &pCell[nHeader]; + pPrior = &pCell[info.iOverflow]; + + while( nPayload>0 ){ + if( spaceLeft==0 ){ + int isExact = 0; +#ifndef SQLITE_OMIT_AUTOVACUUM + Pgno pgnoPtrmap = pgnoOvfl; /* Overflow page pointer-map entry page */ + if( pBt->autoVacuum ){ + do{ + pgnoOvfl++; + } while( + PTRMAP_ISPAGE(pBt, pgnoOvfl) || pgnoOvfl==PENDING_BYTE_PAGE(pBt) + ); + if( pgnoOvfl>1 ){ + /* isExact = 1; */ + } + } +#endif + rc = allocateBtreePage(pBt, &pOvfl, &pgnoOvfl, pgnoOvfl, isExact); +#ifndef SQLITE_OMIT_AUTOVACUUM + /* If the database supports auto-vacuum, and the second or subsequent + ** overflow page is being allocated, add an entry to the pointer-map + ** for that page now. + ** + ** If this is the first overflow page, then write a partial entry + ** to the pointer-map. If we write nothing to this pointer-map slot, + ** then the optimistic overflow chain processing in clearCell() + ** may misinterpret the uninitialised values and delete the + ** wrong pages from the database. + */ + if( pBt->autoVacuum && rc==SQLITE_OK ){ + u8 eType = (pgnoPtrmap?PTRMAP_OVERFLOW2:PTRMAP_OVERFLOW1); + rc = ptrmapPut(pBt, pgnoOvfl, eType, pgnoPtrmap); + if( rc ){ + releasePage(pOvfl); + } + } +#endif + if( rc ){ + releasePage(pToRelease); + return rc; + } + put4byte(pPrior, pgnoOvfl); + releasePage(pToRelease); + pToRelease = pOvfl; + pPrior = pOvfl->aData; + put4byte(pPrior, 0); + pPayload = &pOvfl->aData[4]; + spaceLeft = pBt->usableSize - 4; + } + n = nPayload; + if( n>spaceLeft ) n = spaceLeft; + if( nSrc>0 ){ + if( n>nSrc ) n = nSrc; + assert( pSrc ); + memcpy(pPayload, pSrc, n); + }else{ + memset(pPayload, 0, n); + } + nPayload -= n; + pPayload += n; + pSrc += n; + nSrc -= n; + spaceLeft -= n; + if( nSrc==0 ){ + nSrc = nData; + pSrc = pData; + } + } + releasePage(pToRelease); + return SQLITE_OK; +} + +/* +** Change the MemPage.pParent pointer on the page whose number is +** given in the second argument so that MemPage.pParent holds the +** pointer in the third argument. +*/ +static int reparentPage(BtShared *pBt, Pgno pgno, MemPage *pNewParent, int idx){ + MemPage *pThis; + DbPage *pDbPage; + + assert( pNewParent!=0 ); + if( pgno==0 ) return SQLITE_OK; + assert( pBt->pPager!=0 ); + pDbPage = sqlite3PagerLookup(pBt->pPager, pgno); + if( pDbPage ){ + pThis = (MemPage *)sqlite3PagerGetExtra(pDbPage); + if( pThis->isInit ){ + assert( pThis->aData==(sqlite3PagerGetData(pDbPage)) ); + if( pThis->pParent!=pNewParent ){ + if( pThis->pParent ) sqlite3PagerUnref(pThis->pParent->pDbPage); + pThis->pParent = pNewParent; + sqlite3PagerRef(pNewParent->pDbPage); + } + pThis->idxParent = idx; + } + sqlite3PagerUnref(pDbPage); + } + +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ + return ptrmapPut(pBt, pgno, PTRMAP_BTREE, pNewParent->pgno); + } +#endif + return SQLITE_OK; +} + + + +/* +** Change the pParent pointer of all children of pPage to point back +** to pPage. +** +** In other words, for every child of pPage, invoke reparentPage() +** to make sure that each child knows that pPage is its parent. +** +** This routine gets called after you memcpy() one page into +** another. +*/ +static int reparentChildPages(MemPage *pPage){ + int i; + BtShared *pBt = pPage->pBt; + int rc = SQLITE_OK; + + if( pPage->leaf ) return SQLITE_OK; + + for(i=0; inCell; i++){ + u8 *pCell = findCell(pPage, i); + if( !pPage->leaf ){ + rc = reparentPage(pBt, get4byte(pCell), pPage, i); + if( rc!=SQLITE_OK ) return rc; + } + } + if( !pPage->leaf ){ + rc = reparentPage(pBt, get4byte(&pPage->aData[pPage->hdrOffset+8]), + pPage, i); + pPage->idxShift = 0; + } + return rc; +} + +/* +** Remove the i-th cell from pPage. This routine effects pPage only. +** The cell content is not freed or deallocated. It is assumed that +** the cell content has been copied someplace else. This routine just +** removes the reference to the cell from pPage. +** +** "sz" must be the number of bytes in the cell. +*/ +static void dropCell(MemPage *pPage, int idx, int sz){ + int i; /* Loop counter */ + int pc; /* Offset to cell content of cell being deleted */ + u8 *data; /* pPage->aData */ + u8 *ptr; /* Used to move bytes around within data[] */ + + assert( idx>=0 && idxnCell ); + assert( sz==cellSize(pPage, idx) ); + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + data = pPage->aData; + ptr = &data[pPage->cellOffset + 2*idx]; + pc = get2byte(ptr); + assert( pc>10 && pc+sz<=pPage->pBt->usableSize ); + freeSpace(pPage, pc, sz); + for(i=idx+1; inCell; i++, ptr+=2){ + ptr[0] = ptr[2]; + ptr[1] = ptr[3]; + } + pPage->nCell--; + put2byte(&data[pPage->hdrOffset+3], pPage->nCell); + pPage->nFree += 2; + pPage->idxShift = 1; +} + +/* +** Insert a new cell on pPage at cell index "i". pCell points to the +** content of the cell. +** +** If the cell content will fit on the page, then put it there. If it +** will not fit, then make a copy of the cell content into pTemp if +** pTemp is not null. Regardless of pTemp, allocate a new entry +** in pPage->aOvfl[] and make it point to the cell content (either +** in pTemp or the original pCell) and also record its index. +** Allocating a new entry in pPage->aCell[] implies that +** pPage->nOverflow is incremented. +** +** If nSkip is non-zero, then do not copy the first nSkip bytes of the +** cell. The caller will overwrite them after this function returns. If +** nSkip is non-zero, then pCell may not point to an invalid memory location +** (but pCell+nSkip is always valid). +*/ +static int insertCell( + MemPage *pPage, /* Page into which we are copying */ + int i, /* New cell becomes the i-th cell of the page */ + u8 *pCell, /* Content of the new cell */ + int sz, /* Bytes of content in pCell */ + u8 *pTemp, /* Temp storage space for pCell, if needed */ + u8 nSkip /* Do not write the first nSkip bytes of the cell */ +){ + int idx; /* Where to write new cell content in data[] */ + int j; /* Loop counter */ + int top; /* First byte of content for any cell in data[] */ + int end; /* First byte past the last cell pointer in data[] */ + int ins; /* Index in data[] where new cell pointer is inserted */ + int hdr; /* Offset into data[] of the page header */ + int cellOffset; /* Address of first cell pointer in data[] */ + u8 *data; /* The content of the whole page */ + u8 *ptr; /* Used for moving information around in data[] */ + + assert( i>=0 && i<=pPage->nCell+pPage->nOverflow ); + assert( sz==cellSizePtr(pPage, pCell) ); + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + if( pPage->nOverflow || sz+2>pPage->nFree ){ + if( pTemp ){ + memcpy(pTemp+nSkip, pCell+nSkip, sz-nSkip); + pCell = pTemp; + } + j = pPage->nOverflow++; + assert( jaOvfl)/sizeof(pPage->aOvfl[0]) ); + pPage->aOvfl[j].pCell = pCell; + pPage->aOvfl[j].idx = i; + pPage->nFree = 0; + }else{ + data = pPage->aData; + hdr = pPage->hdrOffset; + top = get2byte(&data[hdr+5]); + cellOffset = pPage->cellOffset; + end = cellOffset + 2*pPage->nCell + 2; + ins = cellOffset + 2*i; + if( end > top - sz ){ + int rc = defragmentPage(pPage); + if( rc!=SQLITE_OK ) return rc; + top = get2byte(&data[hdr+5]); + assert( end + sz <= top ); + } + idx = allocateSpace(pPage, sz); + assert( idx>0 ); + assert( end <= get2byte(&data[hdr+5]) ); + pPage->nCell++; + pPage->nFree -= 2; + memcpy(&data[idx+nSkip], pCell+nSkip, sz-nSkip); + for(j=end-2, ptr=&data[j]; j>ins; j-=2, ptr-=2){ + ptr[0] = ptr[-2]; + ptr[1] = ptr[-1]; + } + put2byte(&data[ins], idx); + put2byte(&data[hdr+3], pPage->nCell); + pPage->idxShift = 1; +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pPage->pBt->autoVacuum ){ + /* The cell may contain a pointer to an overflow page. If so, write + ** the entry for the overflow page into the pointer map. + */ + CellInfo info; + sqlite3BtreeParseCellPtr(pPage, pCell, &info); + assert( (info.nData+(pPage->intKey?0:info.nKey))==info.nPayload ); + if( (info.nData+(pPage->intKey?0:info.nKey))>info.nLocal ){ + Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]); + int rc = ptrmapPut(pPage->pBt, pgnoOvfl, PTRMAP_OVERFLOW1, pPage->pgno); + if( rc!=SQLITE_OK ) return rc; + } + } +#endif + } + + return SQLITE_OK; +} + +/* +** Add a list of cells to a page. The page should be initially empty. +** The cells are guaranteed to fit on the page. +*/ +static void assemblePage( + MemPage *pPage, /* The page to be assemblied */ + int nCell, /* The number of cells to add to this page */ + u8 **apCell, /* Pointers to cell bodies */ + int *aSize /* Sizes of the cells */ +){ + int i; /* Loop counter */ + int totalSize; /* Total size of all cells */ + int hdr; /* Index of page header */ + int cellptr; /* Address of next cell pointer */ + int cellbody; /* Address of next cell body */ + u8 *data; /* Data for the page */ + + assert( pPage->nOverflow==0 ); + totalSize = 0; + for(i=0; inFree ); + assert( pPage->nCell==0 ); + cellptr = pPage->cellOffset; + data = pPage->aData; + hdr = pPage->hdrOffset; + put2byte(&data[hdr+3], nCell); + if( nCell ){ + cellbody = allocateSpace(pPage, totalSize); + assert( cellbody>0 ); + assert( pPage->nFree >= 2*nCell ); + pPage->nFree -= 2*nCell; + for(i=0; ipBt->usableSize ); + } + pPage->nCell = nCell; +} + +/* +** The following parameters determine how many adjacent pages get involved +** in a balancing operation. NN is the number of neighbors on either side +** of the page that participate in the balancing operation. NB is the +** total number of pages that participate, including the target page and +** NN neighbors on either side. +** +** The minimum value of NN is 1 (of course). Increasing NN above 1 +** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance +** in exchange for a larger degradation in INSERT and UPDATE performance. +** The value of NN appears to give the best results overall. +*/ +#define NN 1 /* Number of neighbors on either side of pPage */ +#define NB (NN*2+1) /* Total pages involved in the balance */ + +/* Forward reference */ +static int balance(MemPage*, int); + +#ifndef SQLITE_OMIT_QUICKBALANCE +/* +** This version of balance() handles the common special case where +** a new entry is being inserted on the extreme right-end of the +** tree, in other words, when the new entry will become the largest +** entry in the tree. +** +** Instead of trying balance the 3 right-most leaf pages, just add +** a new page to the right-hand side and put the one new entry in +** that page. This leaves the right side of the tree somewhat +** unbalanced. But odds are that we will be inserting new entries +** at the end soon afterwards so the nearly empty page will quickly +** fill up. On average. +** +** pPage is the leaf page which is the right-most page in the tree. +** pParent is its parent. pPage must have a single overflow entry +** which is also the right-most entry on the page. +*/ +static int balance_quick(MemPage *pPage, MemPage *pParent){ + int rc; + MemPage *pNew; + Pgno pgnoNew; + u8 *pCell; + int szCell; + CellInfo info; + BtShared *pBt = pPage->pBt; + int parentIdx = pParent->nCell; /* pParent new divider cell index */ + int parentSize; /* Size of new divider cell */ + u8 parentCell[64]; /* Space for the new divider cell */ + + /* Allocate a new page. Insert the overflow cell from pPage + ** into it. Then remove the overflow cell from pPage. + */ + rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + pCell = pPage->aOvfl[0].pCell; + szCell = cellSizePtr(pPage, pCell); + zeroPage(pNew, pPage->aData[0]); + assemblePage(pNew, 1, &pCell, &szCell); + pPage->nOverflow = 0; + + /* Set the parent of the newly allocated page to pParent. */ + pNew->pParent = pParent; + sqlite3PagerRef(pParent->pDbPage); + + /* pPage is currently the right-child of pParent. Change this + ** so that the right-child is the new page allocated above and + ** pPage is the next-to-right child. + */ + assert( pPage->nCell>0 ); + pCell = findCell(pPage, pPage->nCell-1); + sqlite3BtreeParseCellPtr(pPage, pCell, &info); + rc = fillInCell(pParent, parentCell, 0, info.nKey, 0, 0, 0, &parentSize); + if( rc!=SQLITE_OK ){ + return rc; + } + assert( parentSize<64 ); + rc = insertCell(pParent, parentIdx, parentCell, parentSize, 0, 4); + if( rc!=SQLITE_OK ){ + return rc; + } + put4byte(findOverflowCell(pParent,parentIdx), pPage->pgno); + put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew); + +#ifndef SQLITE_OMIT_AUTOVACUUM + /* If this is an auto-vacuum database, update the pointer map + ** with entries for the new page, and any pointer from the + ** cell on the page to an overflow page. + */ + if( pBt->autoVacuum ){ + rc = ptrmapPut(pBt, pgnoNew, PTRMAP_BTREE, pParent->pgno); + if( rc==SQLITE_OK ){ + rc = ptrmapPutOvfl(pNew, 0); + } + if( rc!=SQLITE_OK ){ + releasePage(pNew); + return rc; + } + } +#endif + + /* Release the reference to the new page and balance the parent page, + ** in case the divider cell inserted caused it to become overfull. + */ + releasePage(pNew); + return balance(pParent, 0); +} +#endif /* SQLITE_OMIT_QUICKBALANCE */ + +/* +** This routine redistributes Cells on pPage and up to NN*2 siblings +** of pPage so that all pages have about the same amount of free space. +** Usually NN siblings on either side of pPage is used in the balancing, +** though more siblings might come from one side if pPage is the first +** or last child of its parent. If pPage has fewer than 2*NN siblings +** (something which can only happen if pPage is the root page or a +** child of root) then all available siblings participate in the balancing. +** +** The number of siblings of pPage might be increased or decreased by one or +** two in an effort to keep pages nearly full but not over full. The root page +** is special and is allowed to be nearly empty. If pPage is +** the root page, then the depth of the tree might be increased +** or decreased by one, as necessary, to keep the root page from being +** overfull or completely empty. +** +** Note that when this routine is called, some of the Cells on pPage +** might not actually be stored in pPage->aData[]. This can happen +** if the page is overfull. Part of the job of this routine is to +** make sure all Cells for pPage once again fit in pPage->aData[]. +** +** In the course of balancing the siblings of pPage, the parent of pPage +** might become overfull or underfull. If that happens, then this routine +** is called recursively on the parent. +** +** If this routine fails for any reason, it might leave the database +** in a corrupted state. So if this routine fails, the database should +** be rolled back. +*/ +static int balance_nonroot(MemPage *pPage){ + MemPage *pParent; /* The parent of pPage */ + BtShared *pBt; /* The whole database */ + int nCell = 0; /* Number of cells in apCell[] */ + int nMaxCells = 0; /* Allocated size of apCell, szCell, aFrom. */ + int nOld; /* Number of pages in apOld[] */ + int nNew; /* Number of pages in apNew[] */ + int nDiv; /* Number of cells in apDiv[] */ + int i, j, k; /* Loop counters */ + int idx; /* Index of pPage in pParent->aCell[] */ + int nxDiv; /* Next divider slot in pParent->aCell[] */ + int rc; /* The return code */ + int leafCorrection; /* 4 if pPage is a leaf. 0 if not */ + int leafData; /* True if pPage is a leaf of a LEAFDATA tree */ + int usableSpace; /* Bytes in pPage beyond the header */ + int pageFlags; /* Value of pPage->aData[0] */ + int subtotal; /* Subtotal of bytes in cells on one page */ + int iSpace = 0; /* First unused byte of aSpace[] */ + MemPage *apOld[NB]; /* pPage and up to two siblings */ + Pgno pgnoOld[NB]; /* Page numbers for each page in apOld[] */ + MemPage *apCopy[NB]; /* Private copies of apOld[] pages */ + MemPage *apNew[NB+2]; /* pPage and up to NB siblings after balancing */ + Pgno pgnoNew[NB+2]; /* Page numbers for each page in apNew[] */ + u8 *apDiv[NB]; /* Divider cells in pParent */ + int cntNew[NB+2]; /* Index in aCell[] of cell after i-th page */ + int szNew[NB+2]; /* Combined size of cells place on i-th page */ + u8 **apCell = 0; /* All cells begin balanced */ + int *szCell; /* Local size of all cells in apCell[] */ + u8 *aCopy[NB]; /* Space for holding data of apCopy[] */ + u8 *aSpace; /* Space to hold copies of dividers cells */ +#ifndef SQLITE_OMIT_AUTOVACUUM + u8 *aFrom = 0; +#endif + + /* + ** Find the parent page. + */ + assert( pPage->isInit ); + assert( sqlite3PagerIswriteable(pPage->pDbPage) ); + pBt = pPage->pBt; + pParent = pPage->pParent; + assert( pParent ); + if( SQLITE_OK!=(rc = sqlite3PagerWrite(pParent->pDbPage)) ){ + return rc; + } + TRACE(("BALANCE: begin page %d child of %d\n", pPage->pgno, pParent->pgno)); + +#ifndef SQLITE_OMIT_QUICKBALANCE + /* + ** A special case: If a new entry has just been inserted into a + ** table (that is, a btree with integer keys and all data at the leaves) + ** and the new entry is the right-most entry in the tree (it has the + ** largest key) then use the special balance_quick() routine for + ** balancing. balance_quick() is much faster and results in a tighter + ** packing of data in the common case. + */ + if( pPage->leaf && + pPage->intKey && + pPage->leafData && + pPage->nOverflow==1 && + pPage->aOvfl[0].idx==pPage->nCell && + pPage->pParent->pgno!=1 && + get4byte(&pParent->aData[pParent->hdrOffset+8])==pPage->pgno + ){ + /* + ** TODO: Check the siblings to the left of pPage. It may be that + ** they are not full and no new page is required. + */ + return balance_quick(pPage, pParent); + } +#endif + + /* + ** Find the cell in the parent page whose left child points back + ** to pPage. The "idx" variable is the index of that cell. If pPage + ** is the rightmost child of pParent then set idx to pParent->nCell + */ + if( pParent->idxShift ){ + Pgno pgno; + pgno = pPage->pgno; + assert( pgno==sqlite3PagerPagenumber(pPage->pDbPage) ); + for(idx=0; idxnCell; idx++){ + if( get4byte(findCell(pParent, idx))==pgno ){ + break; + } + } + assert( idxnCell + || get4byte(&pParent->aData[pParent->hdrOffset+8])==pgno ); + }else{ + idx = pPage->idxParent; + } + + /* + ** Initialize variables so that it will be safe to jump + ** directly to balance_cleanup at any moment. + */ + nOld = nNew = 0; + sqlite3PagerRef(pParent->pDbPage); + + /* + ** Find sibling pages to pPage and the cells in pParent that divide + ** the siblings. An attempt is made to find NN siblings on either + ** side of pPage. More siblings are taken from one side, however, if + ** pPage there are fewer than NN siblings on the other side. If pParent + ** has NB or fewer children then all children of pParent are taken. + */ + nxDiv = idx - NN; + if( nxDiv + NB > pParent->nCell ){ + nxDiv = pParent->nCell - NB + 1; + } + if( nxDiv<0 ){ + nxDiv = 0; + } + nDiv = 0; + for(i=0, k=nxDiv; inCell ){ + apDiv[i] = findCell(pParent, k); + nDiv++; + assert( !pParent->leaf ); + pgnoOld[i] = get4byte(apDiv[i]); + }else if( k==pParent->nCell ){ + pgnoOld[i] = get4byte(&pParent->aData[pParent->hdrOffset+8]); + }else{ + break; + } + rc = getAndInitPage(pBt, pgnoOld[i], &apOld[i], pParent); + if( rc ) goto balance_cleanup; + apOld[i]->idxParent = k; + apCopy[i] = 0; + assert( i==nOld ); + nOld++; + nMaxCells += 1+apOld[i]->nCell+apOld[i]->nOverflow; + } + + /* Make nMaxCells a multiple of 2 in order to preserve 8-byte + ** alignment */ + nMaxCells = (nMaxCells + 1)&~1; + + /* + ** Allocate space for memory structures + */ + apCell = sqliteMallocRaw( + nMaxCells*sizeof(u8*) /* apCell */ + + nMaxCells*sizeof(int) /* szCell */ + + ROUND8(sizeof(MemPage))*NB /* aCopy */ + + pBt->pageSize*(5+NB) /* aSpace */ + + (ISAUTOVACUUM ? nMaxCells : 0) /* aFrom */ + ); + if( apCell==0 ){ + rc = SQLITE_NOMEM; + goto balance_cleanup; + } + szCell = (int*)&apCell[nMaxCells]; + aCopy[0] = (u8*)&szCell[nMaxCells]; + assert( ((aCopy[0] - (u8*)apCell) & 7)==0 ); /* 8-byte alignment required */ + for(i=1; ipageSize+ROUND8(sizeof(MemPage))]; + assert( ((aCopy[i] - (u8*)apCell) & 7)==0 ); /* 8-byte alignment required */ + } + aSpace = &aCopy[NB-1][pBt->pageSize+ROUND8(sizeof(MemPage))]; + assert( ((aSpace - (u8*)apCell) & 7)==0 ); /* 8-byte alignment required */ +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ + aFrom = &aSpace[5*pBt->pageSize]; + } +#endif + + /* + ** Make copies of the content of pPage and its siblings into aOld[]. + ** The rest of this function will use data from the copies rather + ** that the original pages since the original pages will be in the + ** process of being overwritten. + */ + for(i=0; ipageSize]; + p->aData = &((u8*)p)[-pBt->pageSize]; + memcpy(p->aData, apOld[i]->aData, pBt->pageSize + sizeof(MemPage)); + /* The memcpy() above changes the value of p->aData so we have to + ** set it again. */ + p->aData = &((u8*)p)[-pBt->pageSize]; + } + + /* + ** Load pointers to all cells on sibling pages and the divider cells + ** into the local apCell[] array. Make copies of the divider cells + ** into space obtained form aSpace[] and remove the the divider Cells + ** from pParent. + ** + ** If the siblings are on leaf pages, then the child pointers of the + ** divider cells are stripped from the cells before they are copied + ** into aSpace[]. In this way, all cells in apCell[] are without + ** child pointers. If siblings are not leaves, then all cell in + ** apCell[] include child pointers. Either way, all cells in apCell[] + ** are alike. + ** + ** leafCorrection: 4 if pPage is a leaf. 0 if pPage is not a leaf. + ** leafData: 1 if pPage holds key+data and pParent holds only keys. + */ + nCell = 0; + leafCorrection = pPage->leaf*4; + leafData = pPage->leafData && pPage->leaf; + for(i=0; inCell+pOld->nOverflow; + for(j=0; jautoVacuum ){ + int a; + aFrom[nCell] = i; + for(a=0; anOverflow; a++){ + if( pOld->aOvfl[a].pCell==apCell[nCell] ){ + aFrom[nCell] = 0xFF; + break; + } + } + } +#endif + nCell++; + } + if( ipageSize*5 ); + memcpy(pTemp, apDiv[i], sz); + apCell[nCell] = pTemp+leafCorrection; +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ + aFrom[nCell] = 0xFF; + } +#endif + dropCell(pParent, nxDiv, sz); + szCell[nCell] -= leafCorrection; + assert( get4byte(pTemp)==pgnoOld[i] ); + if( !pOld->leaf ){ + assert( leafCorrection==0 ); + /* The right pointer of the child page pOld becomes the left + ** pointer of the divider cell */ + memcpy(apCell[nCell], &pOld->aData[pOld->hdrOffset+8], 4); + }else{ + assert( leafCorrection==4 ); + if( szCell[nCell]<4 ){ + /* Do not allow any cells smaller than 4 bytes. */ + szCell[nCell] = 4; + } + } + nCell++; + } + } + } + + /* + ** Figure out the number of pages needed to hold all nCell cells. + ** Store this number in "k". Also compute szNew[] which is the total + ** size of all cells on the i-th page and cntNew[] which is the index + ** in apCell[] of the cell that divides page i from page i+1. + ** cntNew[k] should equal nCell. + ** + ** Values computed by this block: + ** + ** k: The total number of sibling pages + ** szNew[i]: Spaced used on the i-th sibling page. + ** cntNew[i]: Index in apCell[] and szCell[] for the first cell to + ** the right of the i-th sibling page. + ** usableSpace: Number of bytes of space available on each sibling. + ** + */ + usableSpace = pBt->usableSize - 12 + leafCorrection; + for(subtotal=k=i=0; i usableSpace ){ + szNew[k] = subtotal - szCell[i]; + cntNew[k] = i; + if( leafData ){ i--; } + subtotal = 0; + k++; + } + } + szNew[k] = subtotal; + cntNew[k] = nCell; + k++; + + /* + ** The packing computed by the previous block is biased toward the siblings + ** on the left side. The left siblings are always nearly full, while the + ** right-most sibling might be nearly empty. This block of code attempts + ** to adjust the packing of siblings to get a better balance. + ** + ** This adjustment is more than an optimization. The packing above might + ** be so out of balance as to be illegal. For example, the right-most + ** sibling might be completely empty. This adjustment is not optional. + */ + for(i=k-1; i>0; i--){ + int szRight = szNew[i]; /* Size of sibling on the right */ + int szLeft = szNew[i-1]; /* Size of sibling on the left */ + int r; /* Index of right-most cell in left sibling */ + int d; /* Index of first cell to the left of right sibling */ + + r = cntNew[i-1] - 1; + d = r + 1 - leafData; + assert( d0) or we are the + ** a virtual root page. A virtual root page is when the real root + ** page is page 1 and we are the only child of that page. + */ + assert( cntNew[0]>0 || (pParent->pgno==1 && pParent->nCell==0) ); + + /* + ** Allocate k new pages. Reuse old pages where possible. + */ + assert( pPage->pgno>1 ); + pageFlags = pPage->aData[0]; + for(i=0; ipDbPage); + nNew++; + if( rc ) goto balance_cleanup; + }else{ + assert( i>0 ); + rc = allocateBtreePage(pBt, &pNew, &pgnoNew[i], pgnoNew[i-1], 0); + if( rc ) goto balance_cleanup; + apNew[i] = pNew; + nNew++; + } + zeroPage(pNew, pageFlags); + } + + /* Free any old pages that were not reused as new pages. + */ + while( ii ){ + int t; + MemPage *pT; + t = pgnoNew[i]; + pT = apNew[i]; + pgnoNew[i] = pgnoNew[minI]; + apNew[i] = apNew[minI]; + pgnoNew[minI] = t; + apNew[minI] = pT; + } + } + TRACE(("BALANCE: old: %d %d %d new: %d(%d) %d(%d) %d(%d) %d(%d) %d(%d)\n", + pgnoOld[0], + nOld>=2 ? pgnoOld[1] : 0, + nOld>=3 ? pgnoOld[2] : 0, + pgnoNew[0], szNew[0], + nNew>=2 ? pgnoNew[1] : 0, nNew>=2 ? szNew[1] : 0, + nNew>=3 ? pgnoNew[2] : 0, nNew>=3 ? szNew[2] : 0, + nNew>=4 ? pgnoNew[3] : 0, nNew>=4 ? szNew[3] : 0, + nNew>=5 ? pgnoNew[4] : 0, nNew>=5 ? szNew[4] : 0)); + + /* + ** Evenly distribute the data in apCell[] across the new pages. + ** Insert divider cells into pParent as necessary. + */ + j = 0; + for(i=0; ipgno==pgnoNew[i] ); + assemblePage(pNew, cntNew[i]-j, &apCell[j], &szCell[j]); + assert( pNew->nCell>0 || (nNew==1 && cntNew[0]==0) ); + assert( pNew->nOverflow==0 ); + +#ifndef SQLITE_OMIT_AUTOVACUUM + /* If this is an auto-vacuum database, update the pointer map entries + ** that point to the siblings that were rearranged. These can be: left + ** children of cells, the right-child of the page, or overflow pages + ** pointed to by cells. + */ + if( pBt->autoVacuum ){ + for(k=j; kpgno!=pNew->pgno ){ + rc = ptrmapPutOvfl(pNew, k-j); + if( rc!=SQLITE_OK ){ + goto balance_cleanup; + } + } + } + } +#endif + + j = cntNew[i]; + + /* If the sibling page assembled above was not the right-most sibling, + ** insert a divider cell into the parent page. + */ + if( ileaf ){ + memcpy(&pNew->aData[8], pCell, 4); + pTemp = 0; + }else if( leafData ){ + /* If the tree is a leaf-data tree, and the siblings are leaves, + ** then there is no divider cell in apCell[]. Instead, the divider + ** cell consists of the integer key for the right-most cell of + ** the sibling-page assembled above only. + */ + CellInfo info; + j--; + sqlite3BtreeParseCellPtr(pNew, apCell[j], &info); + pCell = &aSpace[iSpace]; + fillInCell(pParent, pCell, 0, info.nKey, 0, 0, 0, &sz); + iSpace += sz; + assert( iSpace<=pBt->pageSize*5 ); + pTemp = 0; + }else{ + pCell -= 4; + pTemp = &aSpace[iSpace]; + iSpace += sz; + assert( iSpace<=pBt->pageSize*5 ); + /* Obscure case for non-leaf-data trees: If the cell at pCell was + ** previously stored on a leaf node, and it's reported size was 4 + ** bytes, then it may actually be smaller than this + ** (see sqlite3BtreeParseCellPtr(), 4 bytes is the minimum size of + ** any cell). But it's important to pass the correct size to + ** insertCell(), so reparse the cell now. + ** + ** Note that this can never happen in an SQLite data file, as all + ** cells are at least 4 bytes. It only happens in b-trees used + ** to evaluate "IN (SELECT ...)" and similar clauses. + */ + if( szCell[j]==4 ){ + assert(leafCorrection==4); + sz = cellSizePtr(pParent, pCell); + } + } + rc = insertCell(pParent, nxDiv, pCell, sz, pTemp, 4); + if( rc!=SQLITE_OK ) goto balance_cleanup; + put4byte(findOverflowCell(pParent,nxDiv), pNew->pgno); +#ifndef SQLITE_OMIT_AUTOVACUUM + /* If this is an auto-vacuum database, and not a leaf-data tree, + ** then update the pointer map with an entry for the overflow page + ** that the cell just inserted points to (if any). + */ + if( pBt->autoVacuum && !leafData ){ + rc = ptrmapPutOvfl(pParent, nxDiv); + if( rc!=SQLITE_OK ){ + goto balance_cleanup; + } + } +#endif + j++; + nxDiv++; + } + } + assert( j==nCell ); + assert( nOld>0 ); + assert( nNew>0 ); + if( (pageFlags & PTF_LEAF)==0 ){ + memcpy(&apNew[nNew-1]->aData[8], &apCopy[nOld-1]->aData[8], 4); + } + if( nxDiv==pParent->nCell+pParent->nOverflow ){ + /* Right-most sibling is the right-most child of pParent */ + put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew[nNew-1]); + }else{ + /* Right-most sibling is the left child of the first entry in pParent + ** past the right-most divider entry */ + put4byte(findOverflowCell(pParent, nxDiv), pgnoNew[nNew-1]); + } + + /* + ** Reparent children of all cells. + */ + for(i=0; iisInit ); + rc = balance(pParent, 0); + + /* + ** Cleanup before returning. + */ +balance_cleanup: + sqliteFree(apCell); + for(i=0; ipgno, nOld, nNew, nCell)); + return rc; +} + +/* +** This routine is called for the root page of a btree when the root +** page contains no cells. This is an opportunity to make the tree +** shallower by one level. +*/ +static int balance_shallower(MemPage *pPage){ + MemPage *pChild; /* The only child page of pPage */ + Pgno pgnoChild; /* Page number for pChild */ + int rc = SQLITE_OK; /* Return code from subprocedures */ + BtShared *pBt; /* The main BTree structure */ + int mxCellPerPage; /* Maximum number of cells per page */ + u8 **apCell; /* All cells from pages being balanced */ + int *szCell; /* Local size of all cells */ + + assert( pPage->pParent==0 ); + assert( pPage->nCell==0 ); + pBt = pPage->pBt; + mxCellPerPage = MX_CELL(pBt); + apCell = sqliteMallocRaw( mxCellPerPage*(sizeof(u8*)+sizeof(int)) ); + if( apCell==0 ) return SQLITE_NOMEM; + szCell = (int*)&apCell[mxCellPerPage]; + if( pPage->leaf ){ + /* The table is completely empty */ + TRACE(("BALANCE: empty table %d\n", pPage->pgno)); + }else{ + /* The root page is empty but has one child. Transfer the + ** information from that one child into the root page if it + ** will fit. This reduces the depth of the tree by one. + ** + ** If the root page is page 1, it has less space available than + ** its child (due to the 100 byte header that occurs at the beginning + ** of the database fle), so it might not be able to hold all of the + ** information currently contained in the child. If this is the + ** case, then do not do the transfer. Leave page 1 empty except + ** for the right-pointer to the child page. The child page becomes + ** the virtual root of the tree. + */ + pgnoChild = get4byte(&pPage->aData[pPage->hdrOffset+8]); + assert( pgnoChild>0 ); + assert( pgnoChild<=sqlite3PagerPagecount(pPage->pBt->pPager) ); + rc = sqlite3BtreeGetPage(pPage->pBt, pgnoChild, &pChild, 0); + if( rc ) goto end_shallow_balance; + if( pPage->pgno==1 ){ + rc = sqlite3BtreeInitPage(pChild, pPage); + if( rc ) goto end_shallow_balance; + assert( pChild->nOverflow==0 ); + if( pChild->nFree>=100 ){ + /* The child information will fit on the root page, so do the + ** copy */ + int i; + zeroPage(pPage, pChild->aData[0]); + for(i=0; inCell; i++){ + apCell[i] = findCell(pChild,i); + szCell[i] = cellSizePtr(pChild, apCell[i]); + } + assemblePage(pPage, pChild->nCell, apCell, szCell); + /* Copy the right-pointer of the child to the parent. */ + put4byte(&pPage->aData[pPage->hdrOffset+8], + get4byte(&pChild->aData[pChild->hdrOffset+8])); + freePage(pChild); + TRACE(("BALANCE: child %d transfer to page 1\n", pChild->pgno)); + }else{ + /* The child has more information that will fit on the root. + ** The tree is already balanced. Do nothing. */ + TRACE(("BALANCE: child %d will not fit on page 1\n", pChild->pgno)); + } + }else{ + memcpy(pPage->aData, pChild->aData, pPage->pBt->usableSize); + pPage->isInit = 0; + pPage->pParent = 0; + rc = sqlite3BtreeInitPage(pPage, 0); + assert( rc==SQLITE_OK ); + freePage(pChild); + TRACE(("BALANCE: transfer child %d into root %d\n", + pChild->pgno, pPage->pgno)); + } + rc = reparentChildPages(pPage); + assert( pPage->nOverflow==0 ); +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ + int i; + for(i=0; inCell; i++){ + rc = ptrmapPutOvfl(pPage, i); + if( rc!=SQLITE_OK ){ + goto end_shallow_balance; + } + } + } +#endif + if( rc!=SQLITE_OK ) goto end_shallow_balance; + releasePage(pChild); + } +end_shallow_balance: + sqliteFree(apCell); + return rc; +} + + +/* +** The root page is overfull +** +** When this happens, Create a new child page and copy the +** contents of the root into the child. Then make the root +** page an empty page with rightChild pointing to the new +** child. Finally, call balance_internal() on the new child +** to cause it to split. +*/ +static int balance_deeper(MemPage *pPage){ + int rc; /* Return value from subprocedures */ + MemPage *pChild; /* Pointer to a new child page */ + Pgno pgnoChild; /* Page number of the new child page */ + BtShared *pBt; /* The BTree */ + int usableSize; /* Total usable size of a page */ + u8 *data; /* Content of the parent page */ + u8 *cdata; /* Content of the child page */ + int hdr; /* Offset to page header in parent */ + int brk; /* Offset to content of first cell in parent */ + + assert( pPage->pParent==0 ); + assert( pPage->nOverflow>0 ); + pBt = pPage->pBt; + rc = allocateBtreePage(pBt, &pChild, &pgnoChild, pPage->pgno, 0); + if( rc ) return rc; + assert( sqlite3PagerIswriteable(pChild->pDbPage) ); + usableSize = pBt->usableSize; + data = pPage->aData; + hdr = pPage->hdrOffset; + brk = get2byte(&data[hdr+5]); + cdata = pChild->aData; + memcpy(cdata, &data[hdr], pPage->cellOffset+2*pPage->nCell-hdr); + memcpy(&cdata[brk], &data[brk], usableSize-brk); + assert( pChild->isInit==0 ); + rc = sqlite3BtreeInitPage(pChild, pPage); + if( rc ) goto balancedeeper_out; + memcpy(pChild->aOvfl, pPage->aOvfl, pPage->nOverflow*sizeof(pPage->aOvfl[0])); + pChild->nOverflow = pPage->nOverflow; + if( pChild->nOverflow ){ + pChild->nFree = 0; + } + assert( pChild->nCell==pPage->nCell ); + zeroPage(pPage, pChild->aData[0] & ~PTF_LEAF); + put4byte(&pPage->aData[pPage->hdrOffset+8], pgnoChild); + TRACE(("BALANCE: copy root %d into %d\n", pPage->pgno, pChild->pgno)); +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ + int i; + rc = ptrmapPut(pBt, pChild->pgno, PTRMAP_BTREE, pPage->pgno); + if( rc ) goto balancedeeper_out; + for(i=0; inCell; i++){ + rc = ptrmapPutOvfl(pChild, i); + if( rc!=SQLITE_OK ){ + return rc; + } + } + } +#endif + rc = balance_nonroot(pChild); + +balancedeeper_out: + releasePage(pChild); + return rc; +} + +/* +** Decide if the page pPage needs to be balanced. If balancing is +** required, call the appropriate balancing routine. +*/ +static int balance(MemPage *pPage, int insert){ + int rc = SQLITE_OK; + if( pPage->pParent==0 ){ + if( pPage->nOverflow>0 ){ + rc = balance_deeper(pPage); + } + if( rc==SQLITE_OK && pPage->nCell==0 ){ + rc = balance_shallower(pPage); + } + }else{ + if( pPage->nOverflow>0 || + (!insert && pPage->nFree>pPage->pBt->usableSize*2/3) ){ + rc = balance_nonroot(pPage); + } + } + return rc; +} + +/* +** This routine checks all cursors that point to table pgnoRoot. +** If any of those cursors were opened with wrFlag==0 in a different +** database connection (a database connection that shares the pager +** cache with the current connection) and that other connection +** is not in the ReadUncommmitted state, then this routine returns +** SQLITE_LOCKED. +** +** In addition to checking for read-locks (where a read-lock +** means a cursor opened with wrFlag==0) this routine also moves +** all write cursors so that they are pointing to the +** first Cell on the root page. This is necessary because an insert +** or delete might change the number of cells on a page or delete +** a page entirely and we do not want to leave any cursors +** pointing to non-existant pages or cells. +*/ +static int checkReadLocks(Btree *pBtree, Pgno pgnoRoot, BtCursor *pExclude){ + BtCursor *p; + BtShared *pBt = pBtree->pBt; + sqlite3 *db = pBtree->pSqlite; + for(p=pBt->pCursor; p; p=p->pNext){ + if( p==pExclude ) continue; + if( p->eState!=CURSOR_VALID ) continue; + if( p->pgnoRoot!=pgnoRoot ) continue; + if( p->wrFlag==0 ){ + sqlite3 *dbOther = p->pBtree->pSqlite; + if( dbOther==0 || + (dbOther!=db && (dbOther->flags & SQLITE_ReadUncommitted)==0) ){ + return SQLITE_LOCKED; + } + }else if( p->pPage->pgno!=p->pgnoRoot ){ + moveToRoot(p); + } + } + return SQLITE_OK; +} + +/* +** Insert a new record into the BTree. The key is given by (pKey,nKey) +** and the data is given by (pData,nData). The cursor is used only to +** define what table the record should be inserted into. The cursor +** is left pointing at a random location. +** +** For an INTKEY table, only the nKey value of the key is used. pKey is +** ignored. For a ZERODATA table, the pData and nData are both ignored. +*/ +int sqlite3BtreeInsert( + BtCursor *pCur, /* Insert data into the table of this cursor */ + const void *pKey, i64 nKey, /* The key of the new record */ + const void *pData, int nData, /* The data of the new record */ + int nZero, /* Number of extra 0 bytes to append to data */ + int appendBias /* True if this is likely an append */ +){ + int rc; + int loc; + int szNew; + MemPage *pPage; + BtShared *pBt = pCur->pBtree->pBt; + unsigned char *oldCell; + unsigned char *newCell = 0; + + if( pBt->inTransaction!=TRANS_WRITE ){ + /* Must start a transaction before doing an insert */ + return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; + } + assert( !pBt->readOnly ); + if( !pCur->wrFlag ){ + return SQLITE_PERM; /* Cursor not open for writing */ + } + if( checkReadLocks(pCur->pBtree, pCur->pgnoRoot, pCur) ){ + return SQLITE_LOCKED; /* The table pCur points to has a read lock */ + } + + /* Save the positions of any other cursors open on this table */ + clearCursorPosition(pCur); + if( + SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) || + SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, appendBias, &loc)) + ){ + return rc; + } + + pPage = pCur->pPage; + assert( pPage->intKey || nKey>=0 ); + assert( pPage->leaf || !pPage->leafData ); + TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n", + pCur->pgnoRoot, nKey, nData, pPage->pgno, + loc==0 ? "overwrite" : "new entry")); + assert( pPage->isInit ); + rc = sqlite3PagerWrite(pPage->pDbPage); + if( rc ) return rc; + newCell = sqliteMallocRaw( MX_CELL_SIZE(pBt) ); + if( newCell==0 ) return SQLITE_NOMEM; + rc = fillInCell(pPage, newCell, pKey, nKey, pData, nData, nZero, &szNew); + if( rc ) goto end_insert; + assert( szNew==cellSizePtr(pPage, newCell) ); + assert( szNew<=MX_CELL_SIZE(pBt) ); + if( loc==0 && CURSOR_VALID==pCur->eState ){ + int szOld; + assert( pCur->idx>=0 && pCur->idxnCell ); + oldCell = findCell(pPage, pCur->idx); + if( !pPage->leaf ){ + memcpy(newCell, oldCell, 4); + } + szOld = cellSizePtr(pPage, oldCell); + rc = clearCell(pPage, oldCell); + if( rc ) goto end_insert; + dropCell(pPage, pCur->idx, szOld); + }else if( loc<0 && pPage->nCell>0 ){ + assert( pPage->leaf ); + pCur->idx++; + pCur->info.nSize = 0; + }else{ + assert( pPage->leaf ); + } + rc = insertCell(pPage, pCur->idx, newCell, szNew, 0, 0); + if( rc!=SQLITE_OK ) goto end_insert; + rc = balance(pPage, 1); + /* sqlite3BtreePageDump(pCur->pBt, pCur->pgnoRoot, 1); */ + /* fflush(stdout); */ + if( rc==SQLITE_OK ){ + moveToRoot(pCur); + } +end_insert: + sqliteFree(newCell); + return rc; +} + +/* +** Delete the entry that the cursor is pointing to. The cursor +** is left pointing at a random location. +*/ +int sqlite3BtreeDelete(BtCursor *pCur){ + MemPage *pPage = pCur->pPage; + unsigned char *pCell; + int rc; + Pgno pgnoChild = 0; + BtShared *pBt = pCur->pBtree->pBt; + + assert( pPage->isInit ); + if( pBt->inTransaction!=TRANS_WRITE ){ + /* Must start a transaction before doing a delete */ + return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; + } + assert( !pBt->readOnly ); + if( pCur->idx >= pPage->nCell ){ + return SQLITE_ERROR; /* The cursor is not pointing to anything */ + } + if( !pCur->wrFlag ){ + return SQLITE_PERM; /* Did not open this cursor for writing */ + } + if( checkReadLocks(pCur->pBtree, pCur->pgnoRoot, pCur) ){ + return SQLITE_LOCKED; /* The table pCur points to has a read lock */ + } + + /* Restore the current cursor position (a no-op if the cursor is not in + ** CURSOR_REQUIRESEEK state) and save the positions of any other cursors + ** open on the same table. Then call sqlite3PagerWrite() on the page + ** that the entry will be deleted from. + */ + if( + (rc = restoreOrClearCursorPosition(pCur))!=0 || + (rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur))!=0 || + (rc = sqlite3PagerWrite(pPage->pDbPage))!=0 + ){ + return rc; + } + + /* Locate the cell within it's page and leave pCell pointing to the + ** data. The clearCell() call frees any overflow pages associated with the + ** cell. The cell itself is still intact. + */ + pCell = findCell(pPage, pCur->idx); + if( !pPage->leaf ){ + pgnoChild = get4byte(pCell); + } + rc = clearCell(pPage, pCell); + if( rc ) return rc; + + if( !pPage->leaf ){ + /* + ** The entry we are about to delete is not a leaf so if we do not + ** do something we will leave a hole on an internal page. + ** We have to fill the hole by moving in a cell from a leaf. The + ** next Cell after the one to be deleted is guaranteed to exist and + ** to be a leaf so we can use it. + */ + BtCursor leafCur; + unsigned char *pNext; + int szNext; /* The compiler warning is wrong: szNext is always + ** initialized before use. Adding an extra initialization + ** to silence the compiler slows down the code. */ + int notUsed; + unsigned char *tempCell = 0; + assert( !pPage->leafData ); + sqlite3BtreeGetTempCursor(pCur, &leafCur); + rc = sqlite3BtreeNext(&leafCur, ¬Used); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerWrite(leafCur.pPage->pDbPage); + } + if( rc==SQLITE_OK ){ + TRACE(("DELETE: table=%d delete internal from %d replace from leaf %d\n", + pCur->pgnoRoot, pPage->pgno, leafCur.pPage->pgno)); + dropCell(pPage, pCur->idx, cellSizePtr(pPage, pCell)); + pNext = findCell(leafCur.pPage, leafCur.idx); + szNext = cellSizePtr(leafCur.pPage, pNext); + assert( MX_CELL_SIZE(pBt)>=szNext+4 ); + tempCell = sqliteMallocRaw( MX_CELL_SIZE(pBt) ); + if( tempCell==0 ){ + rc = SQLITE_NOMEM; + } + } + if( rc==SQLITE_OK ){ + rc = insertCell(pPage, pCur->idx, pNext-4, szNext+4, tempCell, 0); + } + if( rc==SQLITE_OK ){ + put4byte(findOverflowCell(pPage, pCur->idx), pgnoChild); + rc = balance(pPage, 0); + } + if( rc==SQLITE_OK ){ + dropCell(leafCur.pPage, leafCur.idx, szNext); + rc = balance(leafCur.pPage, 0); + } + sqliteFree(tempCell); + sqlite3BtreeReleaseTempCursor(&leafCur); + }else{ + TRACE(("DELETE: table=%d delete from leaf %d\n", + pCur->pgnoRoot, pPage->pgno)); + dropCell(pPage, pCur->idx, cellSizePtr(pPage, pCell)); + rc = balance(pPage, 0); + } + if( rc==SQLITE_OK ){ + moveToRoot(pCur); + } + return rc; +} + +/* +** Create a new BTree table. Write into *piTable the page +** number for the root page of the new table. +** +** The type of type is determined by the flags parameter. Only the +** following values of flags are currently in use. Other values for +** flags might not work: +** +** BTREE_INTKEY|BTREE_LEAFDATA Used for SQL tables with rowid keys +** BTREE_ZERODATA Used for SQL indices +*/ +int sqlite3BtreeCreateTable(Btree *p, int *piTable, int flags){ + BtShared *pBt = p->pBt; + MemPage *pRoot; + Pgno pgnoRoot; + int rc; + if( pBt->inTransaction!=TRANS_WRITE ){ + /* Must start a transaction first */ + return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; + } + assert( !pBt->readOnly ); + +#ifdef SQLITE_OMIT_AUTOVACUUM + rc = allocateBtreePage(pBt, &pRoot, &pgnoRoot, 1, 0); + if( rc ) return rc; +#else + if( pBt->autoVacuum ){ + Pgno pgnoMove; /* Move a page here to make room for the root-page */ + MemPage *pPageMove; /* The page to move to. */ + + /* Creating a new table may probably require moving an existing database + ** to make room for the new tables root page. In case this page turns + ** out to be an overflow page, delete all overflow page-map caches + ** held by open cursors. + */ + invalidateAllOverflowCache(pBt); + + /* Read the value of meta[3] from the database to determine where the + ** root page of the new table should go. meta[3] is the largest root-page + ** created so far, so the new root-page is (meta[3]+1). + */ + rc = sqlite3BtreeGetMeta(p, 4, &pgnoRoot); + if( rc!=SQLITE_OK ) return rc; + pgnoRoot++; + + /* The new root-page may not be allocated on a pointer-map page, or the + ** PENDING_BYTE page. + */ + if( pgnoRoot==PTRMAP_PAGENO(pBt, pgnoRoot) || + pgnoRoot==PENDING_BYTE_PAGE(pBt) ){ + pgnoRoot++; + } + assert( pgnoRoot>=3 ); + + /* Allocate a page. The page that currently resides at pgnoRoot will + ** be moved to the allocated page (unless the allocated page happens + ** to reside at pgnoRoot). + */ + rc = allocateBtreePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, 1); + if( rc!=SQLITE_OK ){ + return rc; + } + + if( pgnoMove!=pgnoRoot ){ + /* pgnoRoot is the page that will be used for the root-page of + ** the new table (assuming an error did not occur). But we were + ** allocated pgnoMove. If required (i.e. if it was not allocated + ** by extending the file), the current page at position pgnoMove + ** is already journaled. + */ + u8 eType; + Pgno iPtrPage; + + releasePage(pPageMove); + + /* Move the page currently at pgnoRoot to pgnoMove. */ + rc = sqlite3BtreeGetPage(pBt, pgnoRoot, &pRoot, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + rc = ptrmapGet(pBt, pgnoRoot, &eType, &iPtrPage); + if( rc!=SQLITE_OK || eType==PTRMAP_ROOTPAGE || eType==PTRMAP_FREEPAGE ){ + releasePage(pRoot); + return rc; + } + assert( eType!=PTRMAP_ROOTPAGE ); + assert( eType!=PTRMAP_FREEPAGE ); + rc = sqlite3PagerWrite(pRoot->pDbPage); + if( rc!=SQLITE_OK ){ + releasePage(pRoot); + return rc; + } + rc = relocatePage(pBt, pRoot, eType, iPtrPage, pgnoMove); + releasePage(pRoot); + + /* Obtain the page at pgnoRoot */ + if( rc!=SQLITE_OK ){ + return rc; + } + rc = sqlite3BtreeGetPage(pBt, pgnoRoot, &pRoot, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + rc = sqlite3PagerWrite(pRoot->pDbPage); + if( rc!=SQLITE_OK ){ + releasePage(pRoot); + return rc; + } + }else{ + pRoot = pPageMove; + } + + /* Update the pointer-map and meta-data with the new root-page number. */ + rc = ptrmapPut(pBt, pgnoRoot, PTRMAP_ROOTPAGE, 0); + if( rc ){ + releasePage(pRoot); + return rc; + } + rc = sqlite3BtreeUpdateMeta(p, 4, pgnoRoot); + if( rc ){ + releasePage(pRoot); + return rc; + } + + }else{ + rc = allocateBtreePage(pBt, &pRoot, &pgnoRoot, 1, 0); + if( rc ) return rc; + } +#endif + assert( sqlite3PagerIswriteable(pRoot->pDbPage) ); + zeroPage(pRoot, flags | PTF_LEAF); + sqlite3PagerUnref(pRoot->pDbPage); + *piTable = (int)pgnoRoot; + return SQLITE_OK; +} + +/* +** Erase the given database page and all its children. Return +** the page to the freelist. +*/ +static int clearDatabasePage( + BtShared *pBt, /* The BTree that contains the table */ + Pgno pgno, /* Page number to clear */ + MemPage *pParent, /* Parent page. NULL for the root */ + int freePageFlag /* Deallocate page if true */ +){ + MemPage *pPage = 0; + int rc; + unsigned char *pCell; + int i; + + if( pgno>sqlite3PagerPagecount(pBt->pPager) ){ + return SQLITE_CORRUPT_BKPT; + } + + rc = getAndInitPage(pBt, pgno, &pPage, pParent); + if( rc ) goto cleardatabasepage_out; + for(i=0; inCell; i++){ + pCell = findCell(pPage, i); + if( !pPage->leaf ){ + rc = clearDatabasePage(pBt, get4byte(pCell), pPage->pParent, 1); + if( rc ) goto cleardatabasepage_out; + } + rc = clearCell(pPage, pCell); + if( rc ) goto cleardatabasepage_out; + } + if( !pPage->leaf ){ + rc = clearDatabasePage(pBt, get4byte(&pPage->aData[8]), pPage->pParent, 1); + if( rc ) goto cleardatabasepage_out; + } + if( freePageFlag ){ + rc = freePage(pPage); + }else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){ + zeroPage(pPage, pPage->aData[0] | PTF_LEAF); + } + +cleardatabasepage_out: + releasePage(pPage); + return rc; +} + +/* +** Delete all information from a single table in the database. iTable is +** the page number of the root of the table. After this routine returns, +** the root page is empty, but still exists. +** +** This routine will fail with SQLITE_LOCKED if there are any open +** read cursors on the table. Open write cursors are moved to the +** root of the table. +*/ +int sqlite3BtreeClearTable(Btree *p, int iTable){ + int rc; + BtShared *pBt = p->pBt; + if( p->inTrans!=TRANS_WRITE ){ + return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; + } + rc = checkReadLocks(p, iTable, 0); + if( rc ){ + return rc; + } + + /* Save the position of all cursors open on this table */ + if( SQLITE_OK!=(rc = saveAllCursors(pBt, iTable, 0)) ){ + return rc; + } + + return clearDatabasePage(pBt, (Pgno)iTable, 0, 0); +} + +/* +** Erase all information in a table and add the root of the table to +** the freelist. Except, the root of the principle table (the one on +** page 1) is never added to the freelist. +** +** This routine will fail with SQLITE_LOCKED if there are any open +** cursors on the table. +** +** If AUTOVACUUM is enabled and the page at iTable is not the last +** root page in the database file, then the last root page +** in the database file is moved into the slot formerly occupied by +** iTable and that last slot formerly occupied by the last root page +** is added to the freelist instead of iTable. In this say, all +** root pages are kept at the beginning of the database file, which +** is necessary for AUTOVACUUM to work right. *piMoved is set to the +** page number that used to be the last root page in the file before +** the move. If no page gets moved, *piMoved is set to 0. +** The last root page is recorded in meta[3] and the value of +** meta[3] is updated by this procedure. +*/ +int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){ + int rc; + MemPage *pPage = 0; + BtShared *pBt = p->pBt; + + if( p->inTrans!=TRANS_WRITE ){ + return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; + } + + /* It is illegal to drop a table if any cursors are open on the + ** database. This is because in auto-vacuum mode the backend may + ** need to move another root-page to fill a gap left by the deleted + ** root page. If an open cursor was using this page a problem would + ** occur. + */ + if( pBt->pCursor ){ + return SQLITE_LOCKED; + } + + rc = sqlite3BtreeGetPage(pBt, (Pgno)iTable, &pPage, 0); + if( rc ) return rc; + rc = sqlite3BtreeClearTable(p, iTable); + if( rc ){ + releasePage(pPage); + return rc; + } + + *piMoved = 0; + + if( iTable>1 ){ +#ifdef SQLITE_OMIT_AUTOVACUUM + rc = freePage(pPage); + releasePage(pPage); +#else + if( pBt->autoVacuum ){ + Pgno maxRootPgno; + rc = sqlite3BtreeGetMeta(p, 4, &maxRootPgno); + if( rc!=SQLITE_OK ){ + releasePage(pPage); + return rc; + } + + if( iTable==maxRootPgno ){ + /* If the table being dropped is the table with the largest root-page + ** number in the database, put the root page on the free list. + */ + rc = freePage(pPage); + releasePage(pPage); + if( rc!=SQLITE_OK ){ + return rc; + } + }else{ + /* The table being dropped does not have the largest root-page + ** number in the database. So move the page that does into the + ** gap left by the deleted root-page. + */ + MemPage *pMove; + releasePage(pPage); + rc = sqlite3BtreeGetPage(pBt, maxRootPgno, &pMove, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + rc = relocatePage(pBt, pMove, PTRMAP_ROOTPAGE, 0, iTable); + releasePage(pMove); + if( rc!=SQLITE_OK ){ + return rc; + } + rc = sqlite3BtreeGetPage(pBt, maxRootPgno, &pMove, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + rc = freePage(pMove); + releasePage(pMove); + if( rc!=SQLITE_OK ){ + return rc; + } + *piMoved = maxRootPgno; + } + + /* Set the new 'max-root-page' value in the database header. This + ** is the old value less one, less one more if that happens to + ** be a root-page number, less one again if that is the + ** PENDING_BYTE_PAGE. + */ + maxRootPgno--; + if( maxRootPgno==PENDING_BYTE_PAGE(pBt) ){ + maxRootPgno--; + } + if( maxRootPgno==PTRMAP_PAGENO(pBt, maxRootPgno) ){ + maxRootPgno--; + } + assert( maxRootPgno!=PENDING_BYTE_PAGE(pBt) ); + + rc = sqlite3BtreeUpdateMeta(p, 4, maxRootPgno); + }else{ + rc = freePage(pPage); + releasePage(pPage); + } +#endif + }else{ + /* If sqlite3BtreeDropTable was called on page 1. */ + zeroPage(pPage, PTF_INTKEY|PTF_LEAF ); + releasePage(pPage); + } + return rc; +} + + +/* +** Read the meta-information out of a database file. Meta[0] +** is the number of free pages currently in the database. Meta[1] +** through meta[15] are available for use by higher layers. Meta[0] +** is read-only, the others are read/write. +** +** The schema layer numbers meta values differently. At the schema +** layer (and the SetCookie and ReadCookie opcodes) the number of +** free pages is not visible. So Cookie[0] is the same as Meta[1]. +*/ +int sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){ + DbPage *pDbPage; + int rc; + unsigned char *pP1; + BtShared *pBt = p->pBt; + + /* Reading a meta-data value requires a read-lock on page 1 (and hence + ** the sqlite_master table. We grab this lock regardless of whether or + ** not the SQLITE_ReadUncommitted flag is set (the table rooted at page + ** 1 is treated as a special case by queryTableLock() and lockTable()). + */ + rc = queryTableLock(p, 1, READ_LOCK); + if( rc!=SQLITE_OK ){ + return rc; + } + + assert( idx>=0 && idx<=15 ); + rc = sqlite3PagerGet(pBt->pPager, 1, &pDbPage); + if( rc ) return rc; + pP1 = (unsigned char *)sqlite3PagerGetData(pDbPage); + *pMeta = get4byte(&pP1[36 + idx*4]); + sqlite3PagerUnref(pDbPage); + + /* If autovacuumed is disabled in this build but we are trying to + ** access an autovacuumed database, then make the database readonly. + */ +#ifdef SQLITE_OMIT_AUTOVACUUM + if( idx==4 && *pMeta>0 ) pBt->readOnly = 1; +#endif + + /* Grab the read-lock on page 1. */ + rc = lockTable(p, 1, READ_LOCK); + return rc; +} + +/* +** Write meta-information back into the database. Meta[0] is +** read-only and may not be written. +*/ +int sqlite3BtreeUpdateMeta(Btree *p, int idx, u32 iMeta){ + BtShared *pBt = p->pBt; + unsigned char *pP1; + int rc; + assert( idx>=1 && idx<=15 ); + if( p->inTrans!=TRANS_WRITE ){ + return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; + } + assert( pBt->pPage1!=0 ); + pP1 = pBt->pPage1->aData; + rc = sqlite3PagerWrite(pBt->pPage1->pDbPage); + if( rc ) return rc; + put4byte(&pP1[36 + idx*4], iMeta); + if( idx==7 ){ + assert( pBt->autoVacuum || iMeta==0 ); + assert( iMeta==0 || iMeta==1 ); + pBt->incrVacuum = iMeta; + } + return SQLITE_OK; +} + +/* +** Return the flag byte at the beginning of the page that the cursor +** is currently pointing to. +*/ +int sqlite3BtreeFlags(BtCursor *pCur){ + /* TODO: What about CURSOR_REQUIRESEEK state? Probably need to call + ** restoreOrClearCursorPosition() here. + */ + MemPage *pPage = pCur->pPage; + return pPage ? pPage->aData[pPage->hdrOffset] : 0; +} + + +/* +** Return the pager associated with a BTree. This routine is used for +** testing and debugging only. +*/ +Pager *sqlite3BtreePager(Btree *p){ + return p->pBt->pPager; +} + +#ifndef SQLITE_OMIT_INTEGRITY_CHECK +/* +** Append a message to the error message string. +*/ +static void checkAppendMsg( + IntegrityCk *pCheck, + char *zMsg1, + const char *zFormat, + ... +){ + va_list ap; + char *zMsg2; + if( !pCheck->mxErr ) return; + pCheck->mxErr--; + pCheck->nErr++; + va_start(ap, zFormat); + zMsg2 = sqlite3VMPrintf(zFormat, ap); + va_end(ap); + if( zMsg1==0 ) zMsg1 = ""; + if( pCheck->zErrMsg ){ + char *zOld = pCheck->zErrMsg; + pCheck->zErrMsg = 0; + sqlite3SetString(&pCheck->zErrMsg, zOld, "\n", zMsg1, zMsg2, (char*)0); + sqliteFree(zOld); + }else{ + sqlite3SetString(&pCheck->zErrMsg, zMsg1, zMsg2, (char*)0); + } + sqliteFree(zMsg2); +} +#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ + +#ifndef SQLITE_OMIT_INTEGRITY_CHECK +/* +** Add 1 to the reference count for page iPage. If this is the second +** reference to the page, add an error message to pCheck->zErrMsg. +** Return 1 if there are 2 ore more references to the page and 0 if +** if this is the first reference to the page. +** +** Also check that the page number is in bounds. +*/ +static int checkRef(IntegrityCk *pCheck, int iPage, char *zContext){ + if( iPage==0 ) return 1; + if( iPage>pCheck->nPage || iPage<0 ){ + checkAppendMsg(pCheck, zContext, "invalid page number %d", iPage); + return 1; + } + if( pCheck->anRef[iPage]==1 ){ + checkAppendMsg(pCheck, zContext, "2nd reference to page %d", iPage); + return 1; + } + return (pCheck->anRef[iPage]++)>1; +} + +#ifndef SQLITE_OMIT_AUTOVACUUM +/* +** Check that the entry in the pointer-map for page iChild maps to +** page iParent, pointer type ptrType. If not, append an error message +** to pCheck. +*/ +static void checkPtrmap( + IntegrityCk *pCheck, /* Integrity check context */ + Pgno iChild, /* Child page number */ + u8 eType, /* Expected pointer map type */ + Pgno iParent, /* Expected pointer map parent page number */ + char *zContext /* Context description (used for error msg) */ +){ + int rc; + u8 ePtrmapType; + Pgno iPtrmapParent; + + rc = ptrmapGet(pCheck->pBt, iChild, &ePtrmapType, &iPtrmapParent); + if( rc!=SQLITE_OK ){ + checkAppendMsg(pCheck, zContext, "Failed to read ptrmap key=%d", iChild); + return; + } + + if( ePtrmapType!=eType || iPtrmapParent!=iParent ){ + checkAppendMsg(pCheck, zContext, + "Bad ptr map entry key=%d expected=(%d,%d) got=(%d,%d)", + iChild, eType, iParent, ePtrmapType, iPtrmapParent); + } +} +#endif + +/* +** Check the integrity of the freelist or of an overflow page list. +** Verify that the number of pages on the list is N. +*/ +static void checkList( + IntegrityCk *pCheck, /* Integrity checking context */ + int isFreeList, /* True for a freelist. False for overflow page list */ + int iPage, /* Page number for first page in the list */ + int N, /* Expected number of pages in the list */ + char *zContext /* Context for error messages */ +){ + int i; + int expected = N; + int iFirst = iPage; + while( N-- > 0 && pCheck->mxErr ){ + DbPage *pOvflPage; + unsigned char *pOvflData; + if( iPage<1 ){ + checkAppendMsg(pCheck, zContext, + "%d of %d pages missing from overflow list starting at %d", + N+1, expected, iFirst); + break; + } + if( checkRef(pCheck, iPage, zContext) ) break; + if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage) ){ + checkAppendMsg(pCheck, zContext, "failed to get page %d", iPage); + break; + } + pOvflData = (unsigned char *)sqlite3PagerGetData(pOvflPage); + if( isFreeList ){ + int n = get4byte(&pOvflData[4]); +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pCheck->pBt->autoVacuum ){ + checkPtrmap(pCheck, iPage, PTRMAP_FREEPAGE, 0, zContext); + } +#endif + if( n>pCheck->pBt->usableSize/4-8 ){ + checkAppendMsg(pCheck, zContext, + "freelist leaf count too big on page %d", iPage); + N--; + }else{ + for(i=0; ipBt->autoVacuum ){ + checkPtrmap(pCheck, iFreePage, PTRMAP_FREEPAGE, 0, zContext); + } +#endif + checkRef(pCheck, iFreePage, zContext); + } + N -= n; + } + } +#ifndef SQLITE_OMIT_AUTOVACUUM + else{ + /* If this database supports auto-vacuum and iPage is not the last + ** page in this overflow list, check that the pointer-map entry for + ** the following page matches iPage. + */ + if( pCheck->pBt->autoVacuum && N>0 ){ + i = get4byte(pOvflData); + checkPtrmap(pCheck, i, PTRMAP_OVERFLOW2, iPage, zContext); + } + } +#endif + iPage = get4byte(pOvflData); + sqlite3PagerUnref(pOvflPage); + } +} +#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ + +#ifndef SQLITE_OMIT_INTEGRITY_CHECK +/* +** Do various sanity checks on a single page of a tree. Return +** the tree depth. Root pages return 0. Parents of root pages +** return 1, and so forth. +** +** These checks are done: +** +** 1. Make sure that cells and freeblocks do not overlap +** but combine to completely cover the page. +** NO 2. Make sure cell keys are in order. +** NO 3. Make sure no key is less than or equal to zLowerBound. +** NO 4. Make sure no key is greater than or equal to zUpperBound. +** 5. Check the integrity of overflow pages. +** 6. Recursively call checkTreePage on all children. +** 7. Verify that the depth of all children is the same. +** 8. Make sure this page is at least 33% full or else it is +** the root of the tree. +*/ +static int checkTreePage( + IntegrityCk *pCheck, /* Context for the sanity check */ + int iPage, /* Page number of the page to check */ + MemPage *pParent, /* Parent page */ + char *zParentContext /* Parent context */ +){ + MemPage *pPage; + int i, rc, depth, d2, pgno, cnt; + int hdr, cellStart; + int nCell; + u8 *data; + BtShared *pBt; + int usableSize; + char zContext[100]; + char *hit; + + sqlite3_snprintf(sizeof(zContext), zContext, "Page %d: ", iPage); + + /* Check that the page exists + */ + pBt = pCheck->pBt; + usableSize = pBt->usableSize; + if( iPage==0 ) return 0; + if( checkRef(pCheck, iPage, zParentContext) ) return 0; + if( (rc = sqlite3BtreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){ + checkAppendMsg(pCheck, zContext, + "unable to get the page. error code=%d", rc); + return 0; + } + if( (rc = sqlite3BtreeInitPage(pPage, pParent))!=0 ){ + checkAppendMsg(pCheck, zContext, + "sqlite3BtreeInitPage() returns error code %d", rc); + releasePage(pPage); + return 0; + } + + /* Check out all the cells. + */ + depth = 0; + for(i=0; inCell && pCheck->mxErr; i++){ + u8 *pCell; + int sz; + CellInfo info; + + /* Check payload overflow pages + */ + sqlite3_snprintf(sizeof(zContext), zContext, + "On tree page %d cell %d: ", iPage, i); + pCell = findCell(pPage,i); + sqlite3BtreeParseCellPtr(pPage, pCell, &info); + sz = info.nData; + if( !pPage->intKey ) sz += info.nKey; + assert( sz==info.nPayload ); + if( sz>info.nLocal ){ + int nPage = (sz - info.nLocal + usableSize - 5)/(usableSize - 4); + Pgno pgnoOvfl = get4byte(&pCell[info.iOverflow]); +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ + checkPtrmap(pCheck, pgnoOvfl, PTRMAP_OVERFLOW1, iPage, zContext); + } +#endif + checkList(pCheck, 0, pgnoOvfl, nPage, zContext); + } + + /* Check sanity of left child page. + */ + if( !pPage->leaf ){ + pgno = get4byte(pCell); +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ + checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext); + } +#endif + d2 = checkTreePage(pCheck,pgno,pPage,zContext); + if( i>0 && d2!=depth ){ + checkAppendMsg(pCheck, zContext, "Child page depth differs"); + } + depth = d2; + } + } + if( !pPage->leaf ){ + pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); + sqlite3_snprintf(sizeof(zContext), zContext, + "On page %d at right child: ", iPage); +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->autoVacuum ){ + checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, 0); + } +#endif + checkTreePage(pCheck, pgno, pPage, zContext); + } + + /* Check for complete coverage of the page + */ + data = pPage->aData; + hdr = pPage->hdrOffset; + hit = sqliteMalloc( usableSize ); + if( hit ){ + memset(hit, 1, get2byte(&data[hdr+5])); + nCell = get2byte(&data[hdr+3]); + cellStart = hdr + 12 - 4*pPage->leaf; + for(i=0; i=usableSize || pc<0 ){ + checkAppendMsg(pCheck, 0, + "Corruption detected in cell %d on page %d",i,iPage,0); + }else{ + for(j=pc+size-1; j>=pc; j--) hit[j]++; + } + } + for(cnt=0, i=get2byte(&data[hdr+1]); i>0 && i=usableSize || i<0 ){ + checkAppendMsg(pCheck, 0, + "Corruption detected in cell %d on page %d",i,iPage,0); + }else{ + for(j=i+size-1; j>=i; j--) hit[j]++; + } + i = get2byte(&data[i]); + } + for(i=cnt=0; i1 ){ + checkAppendMsg(pCheck, 0, + "Multiple uses for byte %d of page %d", i, iPage); + break; + } + } + if( cnt!=data[hdr+7] ){ + checkAppendMsg(pCheck, 0, + "Fragmented space is %d byte reported as %d on page %d", + cnt, data[hdr+7], iPage); + } + } + sqliteFree(hit); + + releasePage(pPage); + return depth+1; +} +#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ + +#ifndef SQLITE_OMIT_INTEGRITY_CHECK +/* +** This routine does a complete check of the given BTree file. aRoot[] is +** an array of pages numbers were each page number is the root page of +** a table. nRoot is the number of entries in aRoot. +** +** If everything checks out, this routine returns NULL. If something is +** amiss, an error message is written into memory obtained from malloc() +** and a pointer to that error message is returned. The calling function +** is responsible for freeing the error message when it is done. +*/ +char *sqlite3BtreeIntegrityCheck( + Btree *p, /* The btree to be checked */ + int *aRoot, /* An array of root pages numbers for individual trees */ + int nRoot, /* Number of entries in aRoot[] */ + int mxErr, /* Stop reporting errors after this many */ + int *pnErr /* Write number of errors seen to this variable */ +){ + int i; + int nRef; + IntegrityCk sCheck; + BtShared *pBt = p->pBt; + + nRef = sqlite3PagerRefcount(pBt->pPager); + if( lockBtreeWithRetry(p)!=SQLITE_OK ){ + return sqliteStrDup("Unable to acquire a read lock on the database"); + } + sCheck.pBt = pBt; + sCheck.pPager = pBt->pPager; + sCheck.nPage = sqlite3PagerPagecount(sCheck.pPager); + sCheck.mxErr = mxErr; + sCheck.nErr = 0; + *pnErr = 0; +#ifndef SQLITE_OMIT_AUTOVACUUM + if( pBt->nTrunc!=0 ){ + sCheck.nPage = pBt->nTrunc; + } +#endif + if( sCheck.nPage==0 ){ + unlockBtreeIfUnused(pBt); + return 0; + } + sCheck.anRef = sqliteMallocRaw( (sCheck.nPage+1)*sizeof(sCheck.anRef[0]) ); + if( !sCheck.anRef ){ + unlockBtreeIfUnused(pBt); + *pnErr = 1; + return sqlite3MPrintf("Unable to malloc %d bytes", + (sCheck.nPage+1)*sizeof(sCheck.anRef[0])); + } + for(i=0; i<=sCheck.nPage; i++){ sCheck.anRef[i] = 0; } + i = PENDING_BYTE_PAGE(pBt); + if( i<=sCheck.nPage ){ + sCheck.anRef[i] = 1; + } + sCheck.zErrMsg = 0; + + /* Check the integrity of the freelist + */ + checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]), + get4byte(&pBt->pPage1->aData[36]), "Main freelist: "); + + /* Check all the tables. + */ + for(i=0; iautoVacuum && aRoot[i]>1 ){ + checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0, 0); + } +#endif + checkTreePage(&sCheck, aRoot[i], 0, "List of tree roots: "); + } + + /* Make sure every page in the file is referenced + */ + for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){ +#ifdef SQLITE_OMIT_AUTOVACUUM + if( sCheck.anRef[i]==0 ){ + checkAppendMsg(&sCheck, 0, "Page %d is never used", i); + } +#else + /* If the database supports auto-vacuum, make sure no tables contain + ** references to pointer-map pages. + */ + if( sCheck.anRef[i]==0 && + (PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){ + checkAppendMsg(&sCheck, 0, "Page %d is never used", i); + } + if( sCheck.anRef[i]!=0 && + (PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){ + checkAppendMsg(&sCheck, 0, "Pointer map page %d is referenced", i); + } +#endif + } + + /* Make sure this analysis did not leave any unref() pages + */ + unlockBtreeIfUnused(pBt); + if( nRef != sqlite3PagerRefcount(pBt->pPager) ){ + checkAppendMsg(&sCheck, 0, + "Outstanding page count goes from %d to %d during this analysis", + nRef, sqlite3PagerRefcount(pBt->pPager) + ); + } + + /* Clean up and report errors. + */ + sqliteFree(sCheck.anRef); + *pnErr = sCheck.nErr; + return sCheck.zErrMsg; +} +#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ + +/* +** Return the full pathname of the underlying database file. +*/ +const char *sqlite3BtreeGetFilename(Btree *p){ + assert( p->pBt->pPager!=0 ); + return sqlite3PagerFilename(p->pBt->pPager); +} + +/* +** Return the pathname of the directory that contains the database file. +*/ +const char *sqlite3BtreeGetDirname(Btree *p){ + assert( p->pBt->pPager!=0 ); + return sqlite3PagerDirname(p->pBt->pPager); +} + +/* +** Return the pathname of the journal file for this database. The return +** value of this routine is the same regardless of whether the journal file +** has been created or not. +*/ +const char *sqlite3BtreeGetJournalname(Btree *p){ + assert( p->pBt->pPager!=0 ); + return sqlite3PagerJournalname(p->pBt->pPager); +} + +#ifndef SQLITE_OMIT_VACUUM +/* +** Copy the complete content of pBtFrom into pBtTo. A transaction +** must be active for both files. +** +** The size of file pBtFrom may be reduced by this operation. +** If anything goes wrong, the transaction on pBtFrom is rolled back. +*/ +int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){ + int rc = SQLITE_OK; + Pgno i, nPage, nToPage, iSkip; + + BtShared *pBtTo = pTo->pBt; + BtShared *pBtFrom = pFrom->pBt; + + if( pTo->inTrans!=TRANS_WRITE || pFrom->inTrans!=TRANS_WRITE ){ + return SQLITE_ERROR; + } + if( pBtTo->pCursor ) return SQLITE_BUSY; + nToPage = sqlite3PagerPagecount(pBtTo->pPager); + nPage = sqlite3PagerPagecount(pBtFrom->pPager); + iSkip = PENDING_BYTE_PAGE(pBtTo); + for(i=1; rc==SQLITE_OK && i<=nPage; i++){ + DbPage *pDbPage; + if( i==iSkip ) continue; + rc = sqlite3PagerGet(pBtFrom->pPager, i, &pDbPage); + if( rc ) break; + rc = sqlite3PagerOverwrite(pBtTo->pPager, i, sqlite3PagerGetData(pDbPage)); + sqlite3PagerUnref(pDbPage); + } + + /* If the file is shrinking, journal the pages that are being truncated + ** so that they can be rolled back if the commit fails. + */ + for(i=nPage+1; rc==SQLITE_OK && i<=nToPage; i++){ + DbPage *pDbPage; + if( i==iSkip ) continue; + rc = sqlite3PagerGet(pBtTo->pPager, i, &pDbPage); + if( rc ) break; + rc = sqlite3PagerWrite(pDbPage); + sqlite3PagerDontWrite(pDbPage); + /* Yeah. It seems wierd to call DontWrite() right after Write(). But + ** that is because the names of those procedures do not exactly + ** represent what they do. Write() really means "put this page in the + ** rollback journal and mark it as dirty so that it will be written + ** to the database file later." DontWrite() undoes the second part of + ** that and prevents the page from being written to the database. The + ** page is still on the rollback journal, though. And that is the whole + ** point of this loop: to put pages on the rollback journal. */ + sqlite3PagerUnref(pDbPage); + } + if( !rc && nPagepPager, nPage); + } + + if( rc ){ + sqlite3BtreeRollback(pTo); + } + return rc; +} +#endif /* SQLITE_OMIT_VACUUM */ + +/* +** Return non-zero if a transaction is active. +*/ +int sqlite3BtreeIsInTrans(Btree *p){ + return (p && (p->inTrans==TRANS_WRITE)); +} + +/* +** Return non-zero if a statement transaction is active. +*/ +int sqlite3BtreeIsInStmt(Btree *p){ + return (p->pBt && p->pBt->inStmt); +} + +/* +** Return non-zero if a read (or write) transaction is active. +*/ +int sqlite3BtreeIsInReadTrans(Btree *p){ + return (p && (p->inTrans!=TRANS_NONE)); +} + +/* +** This function returns a pointer to a blob of memory associated with +** a single shared-btree. The memory is used by client code for it's own +** purposes (for example, to store a high-level schema associated with +** the shared-btree). The btree layer manages reference counting issues. +** +** The first time this is called on a shared-btree, nBytes bytes of memory +** are allocated, zeroed, and returned to the caller. For each subsequent +** call the nBytes parameter is ignored and a pointer to the same blob +** of memory returned. +** +** Just before the shared-btree is closed, the function passed as the +** xFree argument when the memory allocation was made is invoked on the +** blob of allocated memory. This function should not call sqliteFree() +** on the memory, the btree layer does that. +*/ +void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){ + BtShared *pBt = p->pBt; + if( !pBt->pSchema ){ + pBt->pSchema = sqliteMalloc(nBytes); + pBt->xFreeSchema = xFree; + } + return pBt->pSchema; +} + +/* +** Return true if another user of the same shared btree as the argument +** handle holds an exclusive lock on the sqlite_master table. +*/ +int sqlite3BtreeSchemaLocked(Btree *p){ + return (queryTableLock(p, MASTER_ROOT, READ_LOCK)!=SQLITE_OK); +} + + +#ifndef SQLITE_OMIT_SHARED_CACHE +/* +** Obtain a lock on the table whose root page is iTab. The +** lock is a write lock if isWritelock is true or a read lock +** if it is false. +*/ +int sqlite3BtreeLockTable(Btree *p, int iTab, u8 isWriteLock){ + int rc = SQLITE_OK; + u8 lockType = (isWriteLock?WRITE_LOCK:READ_LOCK); + rc = queryTableLock(p, iTab, lockType); + if( rc==SQLITE_OK ){ + rc = lockTable(p, iTab, lockType); + } + return rc; +} +#endif + +#ifndef SQLITE_OMIT_INCRBLOB +/* +** Argument pCsr must be a cursor opened for writing on an +** INTKEY table currently pointing at a valid table entry. +** This function modifies the data stored as part of that entry. +** Only the data content may only be modified, it is not possible +** to change the length of the data stored. +*/ +int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){ + + assert(pCsr->isIncrblobHandle); + if( pCsr->eState==CURSOR_REQUIRESEEK ){ + return SQLITE_ABORT; + } + + /* Check some preconditions: + ** (a) the cursor is open for writing, + ** (b) there is no read-lock on the table being modified and + ** (c) the cursor points at a valid row of an intKey table. + */ + if( !pCsr->wrFlag ){ + return SQLITE_READONLY; + } + assert( !pCsr->pBtree->pBt->readOnly + && pCsr->pBtree->pBt->inTransaction==TRANS_WRITE ); + if( checkReadLocks(pCsr->pBtree, pCsr->pgnoRoot, pCsr) ){ + return SQLITE_LOCKED; /* The table pCur points to has a read lock */ + } + if( pCsr->eState==CURSOR_INVALID || !pCsr->pPage->intKey ){ + return SQLITE_ERROR; + } + + return accessPayload(pCsr, offset, amt, (unsigned char *)z, 0, 1); +} + +/* +** Set a flag on this cursor to cache the locations of pages from the +** overflow list for the current row. This is used by cursors opened +** for incremental blob IO only. +** +** This function sets a flag only. The actual page location cache +** (stored in BtCursor.aOverflow[]) is allocated and used by function +** accessPayload() (the worker function for sqlite3BtreeData() and +** sqlite3BtreePutData()). +*/ +void sqlite3BtreeCacheOverflow(BtCursor *pCur){ + assert(!pCur->isIncrblobHandle); + assert(!pCur->aOverflow); + pCur->isIncrblobHandle = 1; +} +#endif diff --git a/extensions/sqlite/sqlite-source/btree.h b/extensions/sqlite/sqlite-source/btree.h new file mode 100644 index 00000000..60188463 --- /dev/null +++ b/extensions/sqlite/sqlite-source/btree.h @@ -0,0 +1,149 @@ +/* +** 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$ +*/ +#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 + +#define BTREE_AUTOVACUUM_NONE 0 /* Do not do auto-vacuum */ +#define BTREE_AUTOVACUUM_FULL 1 /* Do full auto-vacuum */ +#define BTREE_AUTOVACUUM_INCR 2 /* Incremental vacuum */ + +/* +** 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 sqlite3BtreeMaxPageCount(Btree*,int); +int sqlite3BtreeGetReserve(Btree*); +int sqlite3BtreeSetAutoVacuum(Btree *, int); +int sqlite3BtreeGetAutoVacuum(Btree *); +int sqlite3BtreeBeginTrans(Btree*,int); +int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster); +int sqlite3BtreeCommitPhaseTwo(Btree*); +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*); +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 *); + +int sqlite3BtreeIncrVacuum(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 */ +); + +int sqlite3BtreeCloseCursor(BtCursor*); +int sqlite3BtreeMoveto(BtCursor*,const void *pKey,i64 nKey,int bias,int *pRes); +int sqlite3BtreeDelete(BtCursor*); +int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey, + const void *pData, int nData, + int nZero, int bias); +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*); + +int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); +void sqlite3BtreeCacheOverflow(BtCursor *); + +#ifdef SQLITE_TEST +int sqlite3BtreeCursorInfo(BtCursor*, int*, int); +void sqlite3BtreeCursorList(Btree*); +int sqlite3BtreePageDump(Btree*, int, int recursive); +#endif + +#endif /* _BTREE_H_ */ diff --git a/extensions/sqlite/sqlite-source/btreeInt.h b/extensions/sqlite/sqlite-source/btreeInt.h new file mode 100644 index 00000000..1d73ff58 --- /dev/null +++ b/extensions/sqlite/sqlite-source/btreeInt.h @@ -0,0 +1,588 @@ +/* +** 2004 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. +** +************************************************************************* +** $Id$ +** +** This file implements a external (disk-based) database using BTrees. +** For a detailed discussion of BTrees, refer to +** +** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3: +** "Sorting And Searching", pages 473-480. Addison-Wesley +** Publishing Company, Reading, Massachusetts. +** +** The basic idea is that each page of the file contains N database +** entries and N+1 pointers to subpages. +** +** ---------------------------------------------------------------- +** | Ptr(0) | Key(0) | Ptr(1) | Key(1) | ... | Key(N-1) | Ptr(N) | +** ---------------------------------------------------------------- +** +** All of the keys on the page that Ptr(0) points to have values less +** than Key(0). All of the keys on page Ptr(1) and its subpages have +** values greater than Key(0) and less than Key(1). All of the keys +** on Ptr(N) and its subpages have values greater than Key(N-1). And +** so forth. +** +** Finding a particular key requires reading O(log(M)) pages from the +** disk where M is the number of entries in the tree. +** +** In this implementation, a single file can hold one or more separate +** BTrees. Each BTree is identified by the index of its root page. The +** key and data for any entry are combined to form the "payload". A +** fixed amount of payload can be carried directly on the database +** page. If the payload is larger than the preset amount then surplus +** bytes are stored on overflow pages. The payload for an entry +** and the preceding pointer are combined to form a "Cell". Each +** page has a small header which contains the Ptr(N) pointer and other +** information such as the size of key and data. +** +** FORMAT DETAILS +** +** The file is divided into pages. The first page is called page 1, +** the second is page 2, and so forth. A page number of zero indicates +** "no such page". The page size can be anything between 512 and 65536. +** Each page can be either a btree page, a freelist page or an overflow +** page. +** +** The first page is always a btree page. The first 100 bytes of the first +** page contain a special header (the "file header") that describes the file. +** The format of the file header is as follows: +** +** OFFSET SIZE DESCRIPTION +** 0 16 Header string: "SQLite format 3\000" +** 16 2 Page size in bytes. +** 18 1 File format write version +** 19 1 File format read version +** 20 1 Bytes of unused space at the end of each page +** 21 1 Max embedded payload fraction +** 22 1 Min embedded payload fraction +** 23 1 Min leaf payload fraction +** 24 4 File change counter +** 28 4 Reserved for future use +** 32 4 First freelist page +** 36 4 Number of freelist pages in the file +** 40 60 15 4-byte meta values passed to higher layers +** +** All of the integer values are big-endian (most significant byte first). +** +** The file change counter is incremented when the database is changed +** This counter allows other processes to know when the file has changed +** and thus when they need to flush their cache. +** +** The max embedded payload fraction is the amount of the total usable +** space in a page that can be consumed by a single cell for standard +** B-tree (non-LEAFDATA) tables. A value of 255 means 100%. The default +** is to limit the maximum cell size so that at least 4 cells will fit +** on one page. Thus the default max embedded payload fraction is 64. +** +** If the payload for a cell is larger than the max payload, then extra +** payload is spilled to overflow pages. Once an overflow page is allocated, +** as many bytes as possible are moved into the overflow pages without letting +** the cell size drop below the min embedded payload fraction. +** +** The min leaf payload fraction is like the min embedded payload fraction +** except that it applies to leaf nodes in a LEAFDATA tree. The maximum +** payload fraction for a LEAFDATA tree is always 100% (or 255) and it +** not specified in the header. +** +** Each btree pages is divided into three sections: The header, the +** cell pointer array, and the cell content area. Page 1 also has a 100-byte +** file header that occurs before the page header. +** +** |----------------| +** | file header | 100 bytes. Page 1 only. +** |----------------| +** | page header | 8 bytes for leaves. 12 bytes for interior nodes +** |----------------| +** | cell pointer | | 2 bytes per cell. Sorted order. +** | array | | Grows downward +** | | v +** |----------------| +** | unallocated | +** | space | +** |----------------| ^ Grows upwards +** | cell content | | Arbitrary order interspersed with freeblocks. +** | area | | and free space fragments. +** |----------------| +** +** The page headers looks like this: +** +** OFFSET SIZE DESCRIPTION +** 0 1 Flags. 1: intkey, 2: zerodata, 4: leafdata, 8: leaf +** 1 2 byte offset to the first freeblock +** 3 2 number of cells on this page +** 5 2 first byte of the cell content area +** 7 1 number of fragmented free bytes +** 8 4 Right child (the Ptr(N) value). Omitted on leaves. +** +** The flags define the format of this btree page. The leaf flag means that +** this page has no children. The zerodata flag means that this page carries +** only keys and no data. The intkey flag means that the key is a integer +** which is stored in the key size entry of the cell header rather than in +** the payload area. +** +** The cell pointer array begins on the first byte after the page header. +** The cell pointer array contains zero or more 2-byte numbers which are +** offsets from the beginning of the page to the cell content in the cell +** content area. The cell pointers occur in sorted order. The system strives +** to keep free space after the last cell pointer so that new cells can +** be easily added without having to defragment the page. +** +** Cell content is stored at the very end of the page and grows toward the +** beginning of the page. +** +** Unused space within the cell content area is collected into a linked list of +** freeblocks. Each freeblock is at least 4 bytes in size. The byte offset +** to the first freeblock is given in the header. Freeblocks occur in +** increasing order. Because a freeblock must be at least 4 bytes in size, +** any group of 3 or fewer unused bytes in the cell content area cannot +** exist on the freeblock chain. A group of 3 or fewer free bytes is called +** a fragment. The total number of bytes in all fragments is recorded. +** in the page header at offset 7. +** +** SIZE DESCRIPTION +** 2 Byte offset of the next freeblock +** 2 Bytes in this freeblock +** +** Cells are of variable length. Cells are stored in the cell content area at +** the end of the page. Pointers to the cells are in the cell pointer array +** that immediately follows the page header. Cells is not necessarily +** contiguous or in order, but cell pointers are contiguous and in order. +** +** Cell content makes use of variable length integers. A variable +** length integer is 1 to 9 bytes where the lower 7 bits of each +** byte are used. The integer consists of all bytes that have bit 8 set and +** the first byte with bit 8 clear. The most significant byte of the integer +** appears first. A variable-length integer may not be more than 9 bytes long. +** As a special case, all 8 bytes of the 9th byte are used as data. This +** allows a 64-bit integer to be encoded in 9 bytes. +** +** 0x00 becomes 0x00000000 +** 0x7f becomes 0x0000007f +** 0x81 0x00 becomes 0x00000080 +** 0x82 0x00 becomes 0x00000100 +** 0x80 0x7f becomes 0x0000007f +** 0x8a 0x91 0xd1 0xac 0x78 becomes 0x12345678 +** 0x81 0x81 0x81 0x81 0x01 becomes 0x10204081 +** +** Variable length integers are used for rowids and to hold the number of +** bytes of key and data in a btree cell. +** +** The content of a cell looks like this: +** +** SIZE DESCRIPTION +** 4 Page number of the left child. Omitted if leaf flag is set. +** var Number of bytes of data. Omitted if the zerodata flag is set. +** var Number of bytes of key. Or the key itself if intkey flag is set. +** * Payload +** 4 First page of the overflow chain. Omitted if no overflow +** +** Overflow pages form a linked list. Each page except the last is completely +** filled with data (pagesize - 4 bytes). The last page can have as little +** as 1 byte of data. +** +** SIZE DESCRIPTION +** 4 Page number of next overflow page +** * Data +** +** Freelist pages come in two subtypes: trunk pages and leaf pages. The +** file header points to the first in a linked list of trunk page. Each trunk +** page points to multiple leaf pages. The content of a leaf page is +** unspecified. A trunk page looks like this: +** +** SIZE DESCRIPTION +** 4 Page number of next trunk page +** 4 Number of leaf pointers on this page +** * zero or more pages numbers of leaves +*/ +#include "sqliteInt.h" +#include "pager.h" +#include "btree.h" +#include "os.h" +#include + +/* Round up a number to the next larger multiple of 8. This is used +** to force 8-byte alignment on 64-bit architectures. +*/ +#define ROUND8(x) ((x+7)&~7) + + +/* The following value is the maximum cell size assuming a maximum page +** size give above. +*/ +#define MX_CELL_SIZE(pBt) (pBt->pageSize-8) + +/* The maximum number of cells on a single page of the database. This +** assumes a minimum cell size of 3 bytes. Such small cells will be +** exceedingly rare, but they are possible. +*/ +#define MX_CELL(pBt) ((pBt->pageSize-8)/3) + +/* Forward declarations */ +typedef struct MemPage MemPage; +typedef struct BtLock BtLock; + +/* +** This is a magic string that appears at the beginning of every +** SQLite database in order to identify the file as a real database. +** +** You can change this value at compile-time by specifying a +** -DSQLITE_FILE_HEADER="..." on the compiler command-line. The +** header must be exactly 16 bytes including the zero-terminator so +** the string itself should be 15 characters long. If you change +** the header, then your custom library will not be able to read +** databases generated by the standard tools and the standard tools +** will not be able to read databases created by your custom library. +*/ +#ifndef SQLITE_FILE_HEADER /* 123456789 123456 */ +# define SQLITE_FILE_HEADER "SQLite format 3" +#endif + +/* +** Page type flags. An ORed combination of these flags appear as the +** first byte of every BTree page. +*/ +#define PTF_INTKEY 0x01 +#define PTF_ZERODATA 0x02 +#define PTF_LEAFDATA 0x04 +#define PTF_LEAF 0x08 + +/* +** As each page of the file is loaded into memory, an instance of the following +** structure is appended and initialized to zero. This structure stores +** information about the page that is decoded from the raw file page. +** +** The pParent field points back to the parent page. This allows us to +** walk up the BTree from any leaf to the root. Care must be taken to +** unref() the parent page pointer when this page is no longer referenced. +** The pageDestructor() routine handles that chore. +*/ +struct MemPage { + u8 isInit; /* True if previously initialized. MUST BE FIRST! */ + u8 idxShift; /* True if Cell indices have changed */ + u8 nOverflow; /* Number of overflow cell bodies in aCell[] */ + u8 intKey; /* True if intkey flag is set */ + u8 leaf; /* True if leaf flag is set */ + u8 zeroData; /* True if table stores keys only */ + u8 leafData; /* True if tables stores data on leaves only */ + u8 hasData; /* True if this page stores data */ + u8 hdrOffset; /* 100 for page 1. 0 otherwise */ + u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */ + u16 maxLocal; /* Copy of Btree.maxLocal or Btree.maxLeaf */ + u16 minLocal; /* Copy of Btree.minLocal or Btree.minLeaf */ + u16 cellOffset; /* Index in aData of first cell pointer */ + u16 idxParent; /* Index in parent of this node */ + u16 nFree; /* Number of free bytes on the page */ + u16 nCell; /* Number of cells on this page, local and ovfl */ + struct _OvflCell { /* Cells that will not fit on aData[] */ + u8 *pCell; /* Pointers to the body of the overflow cell */ + u16 idx; /* Insert this cell before idx-th non-overflow cell */ + } aOvfl[5]; + BtShared *pBt; /* Pointer back to BTree structure */ + u8 *aData; /* Pointer back to the start of the page */ + DbPage *pDbPage; /* Pager page handle */ + Pgno pgno; /* Page number for this page */ + MemPage *pParent; /* The parent of this page. NULL for root */ +}; + +/* +** The in-memory image of a disk page has the auxiliary information appended +** to the end. EXTRA_SIZE is the number of bytes of space needed to hold +** that extra information. +*/ +#define EXTRA_SIZE sizeof(MemPage) + +/* Btree handle */ +struct Btree { + sqlite3 *pSqlite; + BtShared *pBt; + u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */ +}; + +/* +** Btree.inTrans may take one of the following values. +** +** If the shared-data extension is enabled, there may be multiple users +** of the Btree structure. At most one of these may open a write transaction, +** but any number may have active read transactions. Variable Btree.pDb +** points to the handle that owns any current write-transaction. +*/ +#define TRANS_NONE 0 +#define TRANS_READ 1 +#define TRANS_WRITE 2 + +/* +** Everything we need to know about an open database +*/ +struct BtShared { + Pager *pPager; /* The page cache */ + BtCursor *pCursor; /* A list of all open cursors */ + MemPage *pPage1; /* First page of the database */ + u8 inStmt; /* True if we are in a statement subtransaction */ + u8 readOnly; /* True if the underlying file is readonly */ + u8 maxEmbedFrac; /* Maximum payload as % of total page size */ + u8 minEmbedFrac; /* Minimum payload as % of total page size */ + u8 minLeafFrac; /* Minimum leaf payload as % of total page size */ + u8 pageSizeFixed; /* True if the page size can no longer be changed */ +#ifndef SQLITE_OMIT_AUTOVACUUM + u8 autoVacuum; /* True if auto-vacuum is enabled */ + u8 incrVacuum; /* True if incr-vacuum is enabled */ + Pgno nTrunc; /* Non-zero if the db will be truncated (incr vacuum) */ +#endif + u16 pageSize; /* Total number of bytes on a page */ + u16 usableSize; /* Number of usable bytes on each page */ + int maxLocal; /* Maximum local payload in non-LEAFDATA tables */ + int minLocal; /* Minimum local payload in non-LEAFDATA tables */ + int maxLeaf; /* Maximum local payload in a LEAFDATA table */ + int minLeaf; /* Minimum local payload in a LEAFDATA table */ + BusyHandler *pBusyHandler; /* Callback for when there is lock contention */ + u8 inTransaction; /* Transaction state */ + int nRef; /* Number of references to this structure */ + int nTransaction; /* Number of open transactions (read + write) */ + void *pSchema; /* Pointer to space allocated by sqlite3BtreeSchema() */ + void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */ +#ifndef SQLITE_OMIT_SHARED_CACHE + BtLock *pLock; /* List of locks held on this shared-btree struct */ + BtShared *pNext; /* Next in ThreadData.pBtree linked list */ +#endif +}; + +/* +** An instance of the following structure is used to hold information +** about a cell. The parseCellPtr() function fills in this structure +** based on information extract from the raw disk page. +*/ +typedef struct CellInfo CellInfo; +struct CellInfo { + u8 *pCell; /* Pointer to the start of cell content */ + i64 nKey; /* The key for INTKEY tables, or number of bytes in key */ + u32 nData; /* Number of bytes of data */ + u32 nPayload; /* Total amount of payload */ + u16 nHeader; /* Size of the cell content header in bytes */ + u16 nLocal; /* Amount of payload held locally */ + u16 iOverflow; /* Offset to overflow page number. Zero if no overflow */ + u16 nSize; /* Size of the cell content on the main b-tree page */ +}; + +/* +** A cursor is a pointer to a particular entry in the BTree. +** The entry is identified by its MemPage and the index in +** MemPage.aCell[] of the entry. +*/ +struct BtCursor { + Btree *pBtree; /* The Btree to which this cursor belongs */ + BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */ + int (*xCompare)(void*,int,const void*,int,const void*); /* Key comp func */ + void *pArg; /* First arg to xCompare() */ + Pgno pgnoRoot; /* The root page of this tree */ + MemPage *pPage; /* Page that contains the entry */ + int idx; /* Index of the entry in pPage->aCell[] */ + CellInfo info; /* A parse of the cell we are pointing at */ + u8 wrFlag; /* True if writable */ + u8 eState; /* One of the CURSOR_XXX constants (see below) */ + void *pKey; /* Saved key that was cursor's last known position */ + i64 nKey; /* Size of pKey, or last integer key */ + int skip; /* (skip<0) -> Prev() is a no-op. (skip>0) -> Next() is */ +#ifndef SQLITE_OMIT_INCRBLOB + u8 isIncrblobHandle; /* True if this cursor is an incr. io handle */ + Pgno *aOverflow; /* Cache of overflow page locations */ +#endif +}; + +/* +** Potential values for BtCursor.eState. +** +** CURSOR_VALID: +** Cursor points to a valid entry. getPayload() etc. may be called. +** +** CURSOR_INVALID: +** Cursor does not point to a valid entry. This can happen (for example) +** because the table is empty or because BtreeCursorFirst() has not been +** called. +** +** CURSOR_REQUIRESEEK: +** The table that this cursor was opened on still exists, but has been +** modified since the cursor was last used. The cursor position is saved +** in variables BtCursor.pKey and BtCursor.nKey. When a cursor is in +** this state, restoreOrClearCursorPosition() can be called to attempt to +** seek the cursor to the saved position. +*/ +#define CURSOR_INVALID 0 +#define CURSOR_VALID 1 +#define CURSOR_REQUIRESEEK 2 + +/* +** The TRACE macro will print high-level status information about the +** btree operation when the global variable sqlite3_btree_trace is +** enabled. +*/ +#if SQLITE_TEST +# define TRACE(X) if( sqlite3_btree_trace ){ printf X; fflush(stdout); } +#else +# define TRACE(X) +#endif + +/* +** Routines to read and write variable-length integers. These used to +** be defined locally, but now we use the varint routines in the util.c +** file. +*/ +#define getVarint sqlite3GetVarint +#define getVarint32(A,B) ((*B=*(A))<=0x7f?1:sqlite3GetVarint32(A,B)) +#define putVarint sqlite3PutVarint + +/* The database page the PENDING_BYTE occupies. This page is never used. +** TODO: This macro is very similary to PAGER_MJ_PGNO() in pager.c. They +** should possibly be consolidated (presumably in pager.h). +** +** If disk I/O is omitted (meaning that the database is stored purely +** in memory) then there is no pending byte. +*/ +#ifdef SQLITE_OMIT_DISKIO +# define PENDING_BYTE_PAGE(pBt) 0x7fffffff +#else +# define PENDING_BYTE_PAGE(pBt) ((PENDING_BYTE/(pBt)->pageSize)+1) +#endif + +/* +** A linked list of the following structures is stored at BtShared.pLock. +** Locks are added (or upgraded from READ_LOCK to WRITE_LOCK) when a cursor +** is opened on the table with root page BtShared.iTable. Locks are removed +** from this list when a transaction is committed or rolled back, or when +** a btree handle is closed. +*/ +struct BtLock { + Btree *pBtree; /* Btree handle holding this lock */ + Pgno iTable; /* Root page of table */ + u8 eLock; /* READ_LOCK or WRITE_LOCK */ + BtLock *pNext; /* Next in BtShared.pLock list */ +}; + +/* Candidate values for BtLock.eLock */ +#define READ_LOCK 1 +#define WRITE_LOCK 2 + +/* +** These macros define the location of the pointer-map entry for a +** database page. The first argument to each is the number of usable +** bytes on each page of the database (often 1024). The second is the +** page number to look up in the pointer map. +** +** PTRMAP_PAGENO returns the database page number of the pointer-map +** page that stores the required pointer. PTRMAP_PTROFFSET returns +** the offset of the requested map entry. +** +** If the pgno argument passed to PTRMAP_PAGENO is a pointer-map page, +** then pgno is returned. So (pgno==PTRMAP_PAGENO(pgsz, pgno)) can be +** used to test if pgno is a pointer-map page. PTRMAP_ISPAGE implements +** this test. +*/ +#define PTRMAP_PAGENO(pBt, pgno) ptrmapPageno(pBt, pgno) +#define PTRMAP_PTROFFSET(pBt, pgno) (5*(pgno-ptrmapPageno(pBt, pgno)-1)) +#define PTRMAP_ISPAGE(pBt, pgno) (PTRMAP_PAGENO((pBt),(pgno))==(pgno)) + +/* +** The pointer map is a lookup table that identifies the parent page for +** each child page in the database file. The parent page is the page that +** contains a pointer to the child. Every page in the database contains +** 0 or 1 parent pages. (In this context 'database page' refers +** to any page that is not part of the pointer map itself.) Each pointer map +** entry consists of a single byte 'type' and a 4 byte parent page number. +** The PTRMAP_XXX identifiers below are the valid types. +** +** The purpose of the pointer map is to facility moving pages from one +** position in the file to another as part of autovacuum. When a page +** is moved, the pointer in its parent must be updated to point to the +** new location. The pointer map is used to locate the parent page quickly. +** +** PTRMAP_ROOTPAGE: The database page is a root-page. The page-number is not +** used in this case. +** +** PTRMAP_FREEPAGE: The database page is an unused (free) page. The page-number +** is not used in this case. +** +** PTRMAP_OVERFLOW1: The database page is the first page in a list of +** overflow pages. The page number identifies the page that +** contains the cell with a pointer to this overflow page. +** +** PTRMAP_OVERFLOW2: The database page is the second or later page in a list of +** overflow pages. The page-number identifies the previous +** page in the overflow page list. +** +** PTRMAP_BTREE: The database page is a non-root btree page. The page number +** identifies the parent page in the btree. +*/ +#define PTRMAP_ROOTPAGE 1 +#define PTRMAP_FREEPAGE 2 +#define PTRMAP_OVERFLOW1 3 +#define PTRMAP_OVERFLOW2 4 +#define PTRMAP_BTREE 5 + +/* A bunch of assert() statements to check the transaction state variables +** of handle p (type Btree*) are internally consistent. +*/ +#define btreeIntegrity(p) \ + assert( p->inTrans!=TRANS_NONE || p->pBt->nTransactionpBt->nRef ); \ + assert( p->pBt->nTransaction<=p->pBt->nRef ); \ + assert( p->pBt->inTransaction!=TRANS_NONE || p->pBt->nTransaction==0 ); \ + assert( p->pBt->inTransaction>=p->inTrans ); + + +/* +** The ISAUTOVACUUM macro is used within balance_nonroot() to determine +** if the database supports auto-vacuum or not. Because it is used +** within an expression that is an argument to another macro +** (sqliteMallocRaw), it is not possible to use conditional compilation. +** So, this macro is defined instead. +*/ +#ifndef SQLITE_OMIT_AUTOVACUUM +#define ISAUTOVACUUM (pBt->autoVacuum) +#else +#define ISAUTOVACUUM 0 +#endif + + +/* +** This structure is passed around through all the sanity checking routines +** in order to keep track of some global state information. +*/ +typedef struct IntegrityCk IntegrityCk; +struct IntegrityCk { + BtShared *pBt; /* The tree being checked out */ + Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */ + int nPage; /* Number of pages in the database */ + int *anRef; /* Number of times each page is referenced */ + int mxErr; /* Stop accumulating errors when this reaches zero */ + char *zErrMsg; /* An error message. NULL if no errors seen. */ + int nErr; /* Number of messages written to zErrMsg so far */ +}; + +/* +** Read or write a two- and four-byte big-endian integer values. +*/ +#define get2byte(x) ((x)[0]<<8 | (x)[1]) +#define put2byte(p,v) ((p)[0] = (v)>>8, (p)[1] = (v)) +#define get4byte sqlite3Get4byte +#define put4byte sqlite3Put4byte + +/* +** Internal routines that should be accessed by the btree layer only. +*/ +int sqlite3BtreeGetPage(BtShared*, Pgno, MemPage**, int); +int sqlite3BtreeInitPage(MemPage *pPage, MemPage *pParent); +void sqlite3BtreeParseCellPtr(MemPage*, u8*, CellInfo*); +void sqlite3BtreeParseCell(MemPage*, int, CellInfo*); +u8 *sqlite3BtreeFindCell(MemPage *pPage, int iCell); +int sqlite3BtreeRestoreOrClearCursorPosition(BtCursor *pCur); +void sqlite3BtreeGetTempCursor(BtCursor *pCur, BtCursor *pTempCur); +void sqlite3BtreeReleaseTempCursor(BtCursor *pCur); +int sqlite3BtreeIsRootPage(MemPage *pPage); +void sqlite3BtreeMoveToParent(BtCursor *pCur); diff --git a/extensions/sqlite/sqlite-source/build.c b/extensions/sqlite/sqlite-source/build.c new file mode 100644 index 00000000..6ff50330 --- /dev/null +++ b/extensions/sqlite/sqlite-source/build.c @@ -0,0 +1,3361 @@ +/* +** 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 SQLite parser +** when syntax rules are reduced. The routines in this file handle the +** following kinds of SQL syntax: +** +** CREATE TABLE +** DROP TABLE +** CREATE INDEX +** DROP INDEX +** creating ID lists +** BEGIN TRANSACTION +** COMMIT +** ROLLBACK +** +** $Id$ +*/ +#include "sqliteInt.h" +#include + +/* +** This routine is called when a new SQL statement is beginning to +** be parsed. Initialize the pParse structure as needed. +*/ +void sqlite3BeginParse(Parse *pParse, int explainFlag){ + pParse->explain = explainFlag; + pParse->nVar = 0; +} + +#ifndef SQLITE_OMIT_SHARED_CACHE +/* +** The TableLock structure is only used by the sqlite3TableLock() and +** codeTableLocks() functions. +*/ +struct TableLock { + int iDb; /* The database containing the table to be locked */ + int iTab; /* The root page of the table to be locked */ + u8 isWriteLock; /* True for write lock. False for a read lock */ + const char *zName; /* Name of the table */ +}; + +/* +** Record the fact that we want to lock a table at run-time. +** +** The table to be locked has root page iTab and is found in database iDb. +** A read or a write lock can be taken depending on isWritelock. +** +** This routine just records the fact that the lock is desired. The +** code to make the lock occur is generated by a later call to +** codeTableLocks() which occurs during sqlite3FinishCoding(). +*/ +void sqlite3TableLock( + Parse *pParse, /* Parsing context */ + int iDb, /* Index of the database containing the table to lock */ + int iTab, /* Root page number of the table to be locked */ + u8 isWriteLock, /* True for a write lock */ + const char *zName /* Name of the table to be locked */ +){ + int i; + int nBytes; + TableLock *p; + + if( 0==sqlite3ThreadDataReadOnly()->useSharedData || iDb<0 ){ + return; + } + + for(i=0; inTableLock; i++){ + p = &pParse->aTableLock[i]; + if( p->iDb==iDb && p->iTab==iTab ){ + p->isWriteLock = (p->isWriteLock || isWriteLock); + return; + } + } + + nBytes = sizeof(TableLock) * (pParse->nTableLock+1); + pParse->aTableLock = sqliteReallocOrFree(pParse->aTableLock, nBytes); + if( pParse->aTableLock ){ + p = &pParse->aTableLock[pParse->nTableLock++]; + p->iDb = iDb; + p->iTab = iTab; + p->isWriteLock = isWriteLock; + p->zName = zName; + } +} + +/* +** Code an OP_TableLock instruction for each table locked by the +** statement (configured by calls to sqlite3TableLock()). +*/ +static void codeTableLocks(Parse *pParse){ + int i; + Vdbe *pVdbe; + assert( sqlite3ThreadDataReadOnly()->useSharedData || pParse->nTableLock==0 ); + + if( 0==(pVdbe = sqlite3GetVdbe(pParse)) ){ + return; + } + + for(i=0; inTableLock; i++){ + TableLock *p = &pParse->aTableLock[i]; + int p1 = p->iDb; + if( p->isWriteLock ){ + p1 = -1*(p1+1); + } + sqlite3VdbeOp3(pVdbe, OP_TableLock, p1, p->iTab, p->zName, P3_STATIC); + } +} +#else + #define codeTableLocks(x) +#endif + +/* +** This routine is called after a single SQL statement has been +** parsed and a VDBE program to execute that statement has been +** prepared. This routine puts the finishing touches on the +** VDBE program and resets the pParse structure for the next +** parse. +** +** Note that if an error occurred, it might be the case that +** no VDBE code was generated. +*/ +void sqlite3FinishCoding(Parse *pParse){ + sqlite3 *db; + Vdbe *v; + + if( sqlite3MallocFailed() ) return; + if( pParse->nested ) return; + if( !pParse->pVdbe ){ + if( pParse->rc==SQLITE_OK && pParse->nErr ){ + pParse->rc = SQLITE_ERROR; + return; + } + } + + /* Begin by generating some termination code at the end of the + ** vdbe program + */ + db = pParse->db; + v = sqlite3GetVdbe(pParse); + if( v ){ + sqlite3VdbeAddOp(v, OP_Halt, 0, 0); + + /* The cookie mask contains one bit for each database file open. + ** (Bit 0 is for main, bit 1 is for temp, and so forth.) Bits are + ** set for each database that is used. Generate code to start a + ** transaction on each used database and to verify the schema cookie + ** on each used database. + */ + if( pParse->cookieGoto>0 ){ + u32 mask; + int iDb; + sqlite3VdbeJumpHere(v, pParse->cookieGoto-1); + for(iDb=0, mask=1; iDbnDb; mask<<=1, iDb++){ + if( (mask & pParse->cookieMask)==0 ) continue; + sqlite3VdbeAddOp(v, OP_Transaction, iDb, (mask & pParse->writeMask)!=0); + sqlite3VdbeAddOp(v, OP_VerifyCookie, iDb, pParse->cookieValue[iDb]); + } +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( pParse->pVirtualLock ){ + char *vtab = (char *)pParse->pVirtualLock->pVtab; + sqlite3VdbeOp3(v, OP_VBegin, 0, 0, vtab, P3_VTAB); + } +#endif + + /* Once all the cookies have been verified and transactions opened, + ** obtain the required table-locks. This is a no-op unless the + ** shared-cache feature is enabled. + */ + codeTableLocks(pParse); + sqlite3VdbeAddOp(v, OP_Goto, 0, pParse->cookieGoto); + } + +#ifndef SQLITE_OMIT_TRACE + /* Add a No-op that contains the complete text of the compiled SQL + ** statement as its P3 argument. This does not change the functionality + ** of the program. + ** + ** This is used to implement sqlite3_trace(). + */ + sqlite3VdbeOp3(v, OP_Noop, 0, 0, pParse->zSql, pParse->zTail-pParse->zSql); +#endif /* SQLITE_OMIT_TRACE */ + } + + + /* Get the VDBE program ready for execution + */ + if( v && pParse->nErr==0 && !sqlite3MallocFailed() ){ +#ifdef SQLITE_DEBUG + FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0; + sqlite3VdbeTrace(v, trace); +#endif + sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem+3, + pParse->nTab+3, pParse->explain); + pParse->rc = SQLITE_DONE; + pParse->colNamesSet = 0; + }else if( pParse->rc==SQLITE_OK ){ + pParse->rc = SQLITE_ERROR; + } + pParse->nTab = 0; + pParse->nMem = 0; + pParse->nSet = 0; + pParse->nVar = 0; + pParse->cookieMask = 0; + pParse->cookieGoto = 0; +} + +/* +** Run the parser and code generator recursively in order to generate +** code for the SQL statement given onto the end of the pParse context +** currently under construction. When the parser is run recursively +** this way, the final OP_Halt is not appended and other initialization +** and finalization steps are omitted because those are handling by the +** outermost parser. +** +** Not everything is nestable. This facility is designed to permit +** INSERT, UPDATE, and DELETE operations against SQLITE_MASTER. Use +** care if you decide to try to use this routine for some other purposes. +*/ +void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){ + va_list ap; + char *zSql; +# define SAVE_SZ (sizeof(Parse) - offsetof(Parse,nVar)) + char saveBuf[SAVE_SZ]; + + if( pParse->nErr ) return; + assert( pParse->nested<10 ); /* Nesting should only be of limited depth */ + va_start(ap, zFormat); + zSql = sqlite3VMPrintf(zFormat, ap); + va_end(ap); + if( zSql==0 ){ + return; /* A malloc must have failed */ + } + pParse->nested++; + memcpy(saveBuf, &pParse->nVar, SAVE_SZ); + memset(&pParse->nVar, 0, SAVE_SZ); + sqlite3RunParser(pParse, zSql, 0); + sqliteFree(zSql); + memcpy(&pParse->nVar, saveBuf, SAVE_SZ); + pParse->nested--; +} + +/* +** Locate the in-memory structure that describes a particular database +** table given the name of that table and (optionally) the name of the +** database containing the table. Return NULL if not found. +** +** If zDatabase is 0, all databases are searched for the table and the +** first matching table is returned. (No checking for duplicate table +** names is done.) The search order is TEMP first, then MAIN, then any +** auxiliary databases added using the ATTACH command. +** +** See also sqlite3LocateTable(). +*/ +Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){ + Table *p = 0; + int i; + assert( zName!=0 ); + for(i=OMIT_TEMPDB; inDb; i++){ + int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ + if( zDatabase!=0 && sqlite3StrICmp(zDatabase, db->aDb[j].zName) ) continue; + p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName, strlen(zName)+1); + if( p ) break; + } + return p; +} + +/* +** Locate the in-memory structure that describes a particular database +** table given the name of that table and (optionally) the name of the +** database containing the table. Return NULL if not found. Also leave an +** error message in pParse->zErrMsg. +** +** The difference between this routine and sqlite3FindTable() is that this +** routine leaves an error message in pParse->zErrMsg where +** sqlite3FindTable() does not. +*/ +Table *sqlite3LocateTable(Parse *pParse, const char *zName, const char *zDbase){ + Table *p; + + /* 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 0; + } + + p = sqlite3FindTable(pParse->db, zName, zDbase); + if( p==0 ){ + if( zDbase ){ + sqlite3ErrorMsg(pParse, "no such table: %s.%s", zDbase, zName); + }else{ + sqlite3ErrorMsg(pParse, "no such table: %s", zName); + } + pParse->checkSchema = 1; + } + return p; +} + +/* +** Locate the in-memory structure that describes +** a particular index given the name of that index +** and the name of the database that contains the index. +** Return NULL if not found. +** +** If zDatabase is 0, all databases are searched for the +** table and the first matching index is returned. (No checking +** for duplicate index names is done.) The search order is +** TEMP first, then MAIN, then any auxiliary databases added +** using the ATTACH command. +*/ +Index *sqlite3FindIndex(sqlite3 *db, const char *zName, const char *zDb){ + Index *p = 0; + int i; + for(i=OMIT_TEMPDB; inDb; i++){ + int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */ + Schema *pSchema = db->aDb[j].pSchema; + if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zName) ) continue; + assert( pSchema || (j==1 && !db->aDb[1].pBt) ); + if( pSchema ){ + p = sqlite3HashFind(&pSchema->idxHash, zName, strlen(zName)+1); + } + if( p ) break; + } + return p; +} + +/* +** Reclaim the memory used by an index +*/ +static void freeIndex(Index *p){ + sqliteFree(p->zColAff); + sqliteFree(p); +} + +/* +** Remove the given index from the index hash table, and free +** its memory structures. +** +** The index is removed from the database hash tables but +** it is not unlinked from the Table that it indexes. +** Unlinking from the Table must be done by the calling function. +*/ +static void sqliteDeleteIndex(Index *p){ + Index *pOld; + const char *zName = p->zName; + + pOld = sqlite3HashInsert(&p->pSchema->idxHash, zName, strlen( zName)+1, 0); + assert( pOld==0 || pOld==p ); + freeIndex(p); +} + +/* +** For the index called zIdxName which is found in the database iDb, +** unlike that index from its Table then remove the index from +** the index hash table and free all memory structures associated +** with the index. +*/ +void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){ + Index *pIndex; + int len; + Hash *pHash = &db->aDb[iDb].pSchema->idxHash; + + len = strlen(zIdxName); + pIndex = sqlite3HashInsert(pHash, zIdxName, len+1, 0); + if( pIndex ){ + if( pIndex->pTable->pIndex==pIndex ){ + pIndex->pTable->pIndex = pIndex->pNext; + }else{ + Index *p; + for(p=pIndex->pTable->pIndex; p && p->pNext!=pIndex; p=p->pNext){} + if( p && p->pNext==pIndex ){ + p->pNext = pIndex->pNext; + } + } + freeIndex(pIndex); + } + db->flags |= SQLITE_InternChanges; +} + +/* +** Erase all schema information from the in-memory hash tables of +** a single database. This routine is called to reclaim memory +** before the database closes. It is also called during a rollback +** if there were schema changes during the transaction or if a +** schema-cookie mismatch occurs. +** +** If iDb<=0 then reset the internal schema tables for all database +** files. If iDb>=2 then reset the internal schema for only the +** single file indicated. +*/ +void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){ + int i, j; + + assert( iDb>=0 && iDbnDb ); + for(i=iDb; inDb; i++){ + Db *pDb = &db->aDb[i]; + if( pDb->pSchema ){ + sqlite3SchemaFree(pDb->pSchema); + } + if( iDb>0 ) return; + } + assert( iDb==0 ); + db->flags &= ~SQLITE_InternChanges; + + /* If one or more of the auxiliary database files has been closed, + ** then remove them from the auxiliary database list. We take the + ** opportunity to do this here since we have just deleted all of the + ** schema hash tables and therefore do not have to make any changes + ** to any of those tables. + */ + for(i=0; inDb; i++){ + struct Db *pDb = &db->aDb[i]; + if( pDb->pBt==0 ){ + if( pDb->pAux && pDb->xFreeAux ) pDb->xFreeAux(pDb->pAux); + pDb->pAux = 0; + } + } + for(i=j=2; inDb; i++){ + struct Db *pDb = &db->aDb[i]; + if( pDb->pBt==0 ){ + sqliteFree(pDb->zName); + pDb->zName = 0; + continue; + } + if( jaDb[j] = db->aDb[i]; + } + j++; + } + memset(&db->aDb[j], 0, (db->nDb-j)*sizeof(db->aDb[j])); + db->nDb = j; + if( db->nDb<=2 && db->aDb!=db->aDbStatic ){ + memcpy(db->aDbStatic, db->aDb, 2*sizeof(db->aDb[0])); + sqliteFree(db->aDb); + db->aDb = db->aDbStatic; + } +} + +/* +** This routine is called when a commit occurs. +*/ +void sqlite3CommitInternalChanges(sqlite3 *db){ + db->flags &= ~SQLITE_InternChanges; +} + +/* +** Clear the column names from a table or view. +*/ +static void sqliteResetColumnNames(Table *pTable){ + int i; + Column *pCol; + assert( pTable!=0 ); + if( (pCol = pTable->aCol)!=0 ){ + for(i=0; inCol; i++, pCol++){ + sqliteFree(pCol->zName); + sqlite3ExprDelete(pCol->pDflt); + sqliteFree(pCol->zType); + sqliteFree(pCol->zColl); + } + sqliteFree(pTable->aCol); + } + pTable->aCol = 0; + pTable->nCol = 0; +} + +/* +** Remove the memory data structures associated with the given +** Table. No changes are made to disk by this routine. +** +** This routine just deletes the data structure. It does not unlink +** the table data structure from the hash table. Nor does it remove +** foreign keys from the sqlite.aFKey hash table. But it does destroy +** memory structures of the indices and foreign keys associated with +** the table. +*/ +void sqlite3DeleteTable(Table *pTable){ + Index *pIndex, *pNext; + FKey *pFKey, *pNextFKey; + + if( pTable==0 ) return; + + /* Do not delete the table until the reference count reaches zero. */ + pTable->nRef--; + if( pTable->nRef>0 ){ + return; + } + assert( pTable->nRef==0 ); + + /* Delete all indices associated with this table + */ + for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){ + pNext = pIndex->pNext; + assert( pIndex->pSchema==pTable->pSchema ); + sqliteDeleteIndex(pIndex); + } + +#ifndef SQLITE_OMIT_FOREIGN_KEY + /* Delete all foreign keys associated with this table. The keys + ** should have already been unlinked from the pSchema->aFKey hash table + */ + for(pFKey=pTable->pFKey; pFKey; pFKey=pNextFKey){ + pNextFKey = pFKey->pNextFrom; + assert( sqlite3HashFind(&pTable->pSchema->aFKey, + pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey ); + sqliteFree(pFKey); + } +#endif + + /* Delete the Table structure itself. + */ + sqliteResetColumnNames(pTable); + sqliteFree(pTable->zName); + sqliteFree(pTable->zColAff); + sqlite3SelectDelete(pTable->pSelect); +#ifndef SQLITE_OMIT_CHECK + sqlite3ExprDelete(pTable->pCheck); +#endif + sqlite3VtabClear(pTable); + sqliteFree(pTable); +} + +/* +** Unlink the given table from the hash tables and the delete the +** table structure with all its indices and foreign keys. +*/ +void sqlite3UnlinkAndDeleteTable(sqlite3 *db, int iDb, const char *zTabName){ + Table *p; + FKey *pF1, *pF2; + Db *pDb; + + assert( db!=0 ); + assert( iDb>=0 && iDbnDb ); + assert( zTabName && zTabName[0] ); + pDb = &db->aDb[iDb]; + p = sqlite3HashInsert(&pDb->pSchema->tblHash, zTabName, strlen(zTabName)+1,0); + if( p ){ +#ifndef SQLITE_OMIT_FOREIGN_KEY + for(pF1=p->pFKey; pF1; pF1=pF1->pNextFrom){ + int nTo = strlen(pF1->zTo) + 1; + pF2 = sqlite3HashFind(&pDb->pSchema->aFKey, pF1->zTo, nTo); + if( pF2==pF1 ){ + sqlite3HashInsert(&pDb->pSchema->aFKey, pF1->zTo, nTo, pF1->pNextTo); + }else{ + while( pF2 && pF2->pNextTo!=pF1 ){ pF2=pF2->pNextTo; } + if( pF2 ){ + pF2->pNextTo = pF1->pNextTo; + } + } + } +#endif + sqlite3DeleteTable(p); + } + db->flags |= SQLITE_InternChanges; +} + +/* +** Given a token, return a string that consists of the text of that +** token with any quotations removed. Space to hold the returned string +** is obtained from sqliteMalloc() and must be freed by the calling +** function. +** +** Tokens are often just pointers into the original SQL text and so +** are not \000 terminated and are not persistent. The returned string +** is \000 terminated and is persistent. +*/ +char *sqlite3NameFromToken(Token *pName){ + char *zName; + if( pName ){ + zName = sqliteStrNDup((char*)pName->z, pName->n); + sqlite3Dequote(zName); + }else{ + zName = 0; + } + return zName; +} + +/* +** Open the sqlite_master table stored in database number iDb for +** writing. The table is opened using cursor 0. +*/ +void sqlite3OpenMasterTable(Parse *p, int iDb){ + Vdbe *v = sqlite3GetVdbe(p); + sqlite3TableLock(p, iDb, MASTER_ROOT, 1, SCHEMA_TABLE(iDb)); + sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); + sqlite3VdbeAddOp(v, OP_OpenWrite, 0, MASTER_ROOT); + sqlite3VdbeAddOp(v, OP_SetNumColumns, 0, 5); /* sqlite_master has 5 columns */ +} + +/* +** The token *pName contains the name of a database (either "main" or +** "temp" or the name of an attached db). This routine returns the +** index of the named database in db->aDb[], or -1 if the named db +** does not exist. +*/ +int sqlite3FindDb(sqlite3 *db, Token *pName){ + int i = -1; /* Database number */ + int n; /* Number of characters in the name */ + Db *pDb; /* A database whose name space is being searched */ + char *zName; /* Name we are searching for */ + + zName = sqlite3NameFromToken(pName); + if( zName ){ + n = strlen(zName); + for(i=(db->nDb-1), pDb=&db->aDb[i]; i>=0; i--, pDb--){ + if( (!OMIT_TEMPDB || i!=1 ) && n==strlen(pDb->zName) && + 0==sqlite3StrICmp(pDb->zName, zName) ){ + break; + } + } + sqliteFree(zName); + } + return i; +} + +/* The table or view or trigger name is passed to this routine via tokens +** pName1 and pName2. If the table name was fully qualified, for example: +** +** CREATE TABLE xxx.yyy (...); +** +** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if +** the table name is not fully qualified, i.e.: +** +** CREATE TABLE yyy(...); +** +** Then pName1 is set to "yyy" and pName2 is "". +** +** This routine sets the *ppUnqual pointer to point at the token (pName1 or +** pName2) that stores the unqualified table name. The index of the +** database "xxx" is returned. +*/ +int sqlite3TwoPartName( + Parse *pParse, /* Parsing and code generating context */ + Token *pName1, /* The "xxx" in the name "xxx.yyy" or "xxx" */ + Token *pName2, /* The "yyy" in the name "xxx.yyy" */ + Token **pUnqual /* Write the unqualified object name here */ +){ + int iDb; /* Database holding the object */ + sqlite3 *db = pParse->db; + + if( pName2 && pName2->n>0 ){ + assert( !db->init.busy ); + *pUnqual = pName2; + iDb = sqlite3FindDb(db, pName1); + if( iDb<0 ){ + sqlite3ErrorMsg(pParse, "unknown database %T", pName1); + pParse->nErr++; + return -1; + } + }else{ + assert( db->init.iDb==0 || db->init.busy ); + iDb = db->init.iDb; + *pUnqual = pName1; + } + return iDb; +} + +/* +** This routine is used to check if the UTF-8 string zName is a legal +** unqualified name for a new schema object (table, index, view or +** trigger). All names are legal except those that begin with the string +** "sqlite_" (in upper, lower or mixed case). This portion of the namespace +** is reserved for internal use. +*/ +int sqlite3CheckObjectName(Parse *pParse, const char *zName){ + if( !pParse->db->init.busy && pParse->nested==0 + && (pParse->db->flags & SQLITE_WriteSchema)==0 + && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){ + sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName); + return SQLITE_ERROR; + } + return SQLITE_OK; +} + +/* +** Begin constructing a new table representation in memory. This is +** the first of several action routines that get called in response +** to a CREATE TABLE statement. In particular, this routine is called +** after seeing tokens "CREATE" and "TABLE" and the table name. The isTemp +** flag is true if the table should be stored in the auxiliary database +** file instead of in the main database file. This is normally the case +** when the "TEMP" or "TEMPORARY" keyword occurs in between +** CREATE and TABLE. +** +** The new table record is initialized and put in pParse->pNewTable. +** As more of the CREATE TABLE statement is parsed, additional action +** routines will be called to add more information to this record. +** At the end of the CREATE TABLE statement, the sqlite3EndTable() routine +** is called to complete the construction of the new table record. +*/ +void sqlite3StartTable( + Parse *pParse, /* Parser context */ + Token *pName1, /* First part of the name of the table or view */ + Token *pName2, /* Second part of the name of the table or view */ + int isTemp, /* True if this is a TEMP table */ + int isView, /* True if this is a VIEW */ + int isVirtual, /* True if this is a VIRTUAL table */ + int noErr /* Do nothing if table already exists */ +){ + Table *pTable; + char *zName = 0; /* The name of the new table */ + sqlite3 *db = pParse->db; + Vdbe *v; + int iDb; /* Database number to create the table in */ + Token *pName; /* Unqualified name of the table to create */ + + /* The table or view name to create is passed to this routine via tokens + ** pName1 and pName2. If the table name was fully qualified, for example: + ** + ** CREATE TABLE xxx.yyy (...); + ** + ** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if + ** the table name is not fully qualified, i.e.: + ** + ** CREATE TABLE yyy(...); + ** + ** Then pName1 is set to "yyy" and pName2 is "". + ** + ** The call below sets the pName pointer to point at the token (pName1 or + ** pName2) that stores the unqualified table name. The variable iDb is + ** set to the index of the database that the table or view is to be + ** created in. + */ + iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName); + if( iDb<0 ) return; + if( !OMIT_TEMPDB && isTemp && iDb>1 ){ + /* If creating a temp table, the name may not be qualified */ + sqlite3ErrorMsg(pParse, "temporary table name must be unqualified"); + return; + } + if( !OMIT_TEMPDB && isTemp ) iDb = 1; + + pParse->sNameToken = *pName; + zName = sqlite3NameFromToken(pName); + if( zName==0 ) return; + if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ + goto begin_table_error; + } + if( db->init.iDb==1 ) isTemp = 1; +#ifndef SQLITE_OMIT_AUTHORIZATION + assert( (isTemp & 1)==isTemp ); + { + int code; + char *zDb = db->aDb[iDb].zName; + if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(isTemp), 0, zDb) ){ + goto begin_table_error; + } + if( isView ){ + if( !OMIT_TEMPDB && isTemp ){ + code = SQLITE_CREATE_TEMP_VIEW; + }else{ + code = SQLITE_CREATE_VIEW; + } + }else{ + if( !OMIT_TEMPDB && isTemp ){ + code = SQLITE_CREATE_TEMP_TABLE; + }else{ + code = SQLITE_CREATE_TABLE; + } + } + if( !isVirtual && sqlite3AuthCheck(pParse, code, zName, 0, zDb) ){ + goto begin_table_error; + } + } +#endif + + /* Make sure the new table name does not collide with an existing + ** index or table name in the same database. Issue an error message if + ** it does. The exception is if the statement being parsed was passed + ** to an sqlite3_declare_vtab() call. In that case only the column names + ** and types will be used, so there is no need to test for namespace + ** collisions. + */ + if( !IN_DECLARE_VTAB ){ + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ + goto begin_table_error; + } + pTable = sqlite3FindTable(db, zName, db->aDb[iDb].zName); + if( pTable ){ + if( !noErr ){ + sqlite3ErrorMsg(pParse, "table %T already exists", pName); + } + goto begin_table_error; + } + if( sqlite3FindIndex(db, zName, 0)!=0 && (iDb==0 || !db->init.busy) ){ + sqlite3ErrorMsg(pParse, "there is already an index named %s", zName); + goto begin_table_error; + } + } + + pTable = sqliteMalloc( sizeof(Table) ); + if( pTable==0 ){ + pParse->rc = SQLITE_NOMEM; + pParse->nErr++; + goto begin_table_error; + } + pTable->zName = zName; + pTable->iPKey = -1; + pTable->pSchema = db->aDb[iDb].pSchema; + pTable->nRef = 1; + if( pParse->pNewTable ) sqlite3DeleteTable(pParse->pNewTable); + pParse->pNewTable = pTable; + + /* If this is the magic sqlite_sequence table used by autoincrement, + ** then record a pointer to this table in the main database structure + ** so that INSERT can find the table easily. + */ +#ifndef SQLITE_OMIT_AUTOINCREMENT + if( !pParse->nested && strcmp(zName, "sqlite_sequence")==0 ){ + pTable->pSchema->pSeqTab = pTable; + } +#endif + + /* Begin generating the code that will insert the table record into + ** the SQLITE_MASTER table. Note in particular that we must go ahead + ** and allocate the record number for the table entry now. Before any + ** PRIMARY KEY or UNIQUE keywords are parsed. Those keywords will cause + ** indices to be created and the table record must come before the + ** indices. Hence, the record number for the table must be allocated + ** now. + */ + if( !db->init.busy && (v = sqlite3GetVdbe(pParse))!=0 ){ + int lbl; + int fileFormat; + sqlite3BeginWriteOperation(pParse, 0, iDb); + +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( isVirtual ){ + sqlite3VdbeAddOp(v, OP_VBegin, 0, 0); + } +#endif + + /* If the file format and encoding in the database have not been set, + ** set them now. + */ + sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 1); /* file_format */ + lbl = sqlite3VdbeMakeLabel(v); + sqlite3VdbeAddOp(v, OP_If, 0, lbl); + fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ? + 1 : SQLITE_MAX_FILE_FORMAT; + sqlite3VdbeAddOp(v, OP_Integer, fileFormat, 0); + sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 1); + sqlite3VdbeAddOp(v, OP_Integer, ENC(db), 0); + sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 4); + sqlite3VdbeResolveLabel(v, lbl); + + /* This just creates a place-holder record in the sqlite_master table. + ** The record created does not contain anything yet. It will be replaced + ** by the real entry in code generated at sqlite3EndTable(). + ** + ** The rowid for the new entry is left on the top of the stack. + ** The rowid value is needed by the code that sqlite3EndTable will + ** generate. + */ +#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) + if( isView || isVirtual ){ + sqlite3VdbeAddOp(v, OP_Integer, 0, 0); + }else +#endif + { + sqlite3VdbeAddOp(v, OP_CreateTable, iDb, 0); + } + sqlite3OpenMasterTable(pParse, iDb); + sqlite3VdbeAddOp(v, OP_NewRowid, 0, 0); + sqlite3VdbeAddOp(v, OP_Dup, 0, 0); + sqlite3VdbeAddOp(v, OP_Null, 0, 0); + sqlite3VdbeAddOp(v, OP_Insert, 0, OPFLAG_APPEND); + sqlite3VdbeAddOp(v, OP_Close, 0, 0); + sqlite3VdbeAddOp(v, OP_Pull, 1, 0); + } + + /* Normal (non-error) return. */ + return; + + /* If an error occurs, we jump here */ +begin_table_error: + sqliteFree(zName); + return; +} + +/* +** This macro is used to compare two strings in a case-insensitive manner. +** It is slightly faster than calling sqlite3StrICmp() directly, but +** produces larger code. +** +** WARNING: This macro is not compatible with the strcmp() family. It +** returns true if the two strings are equal, otherwise false. +*/ +#define STRICMP(x, y) (\ +sqlite3UpperToLower[*(unsigned char *)(x)]== \ +sqlite3UpperToLower[*(unsigned char *)(y)] \ +&& sqlite3StrICmp((x)+1,(y)+1)==0 ) + +/* +** Add a new column to the table currently being constructed. +** +** The parser calls this routine once for each column declaration +** in a CREATE TABLE statement. sqlite3StartTable() gets called +** first to get things going. Then this routine is called for each +** column. +*/ +void sqlite3AddColumn(Parse *pParse, Token *pName){ + Table *p; + int i; + char *z; + Column *pCol; + if( (p = pParse->pNewTable)==0 ) return; + if( p->nCol+1>SQLITE_MAX_COLUMN ){ + sqlite3ErrorMsg(pParse, "too many columns on %s", p->zName); + return; + } + z = sqlite3NameFromToken(pName); + if( z==0 ) return; + for(i=0; inCol; i++){ + if( STRICMP(z, p->aCol[i].zName) ){ + sqlite3ErrorMsg(pParse, "duplicate column name: %s", z); + sqliteFree(z); + return; + } + } + if( (p->nCol & 0x7)==0 ){ + Column *aNew; + aNew = sqliteRealloc( p->aCol, (p->nCol+8)*sizeof(p->aCol[0])); + if( aNew==0 ){ + sqliteFree(z); + return; + } + p->aCol = aNew; + } + pCol = &p->aCol[p->nCol]; + memset(pCol, 0, sizeof(p->aCol[0])); + pCol->zName = z; + + /* If there is no type specified, columns have the default affinity + ** 'NONE'. If there is a type specified, then sqlite3AddColumnType() will + ** be called next to set pCol->affinity correctly. + */ + pCol->affinity = SQLITE_AFF_NONE; + p->nCol++; +} + +/* +** This routine is called by the parser while in the middle of +** parsing a CREATE TABLE statement. A "NOT NULL" constraint has +** been seen on a column. This routine sets the notNull flag on +** the column currently under construction. +*/ +void sqlite3AddNotNull(Parse *pParse, int onError){ + Table *p; + int i; + if( (p = pParse->pNewTable)==0 ) return; + i = p->nCol-1; + if( i>=0 ) p->aCol[i].notNull = onError; +} + +/* +** Scan the column type name zType (length nType) and return the +** associated affinity type. +** +** This routine does a case-independent search of zType for the +** substrings in the following table. If one of the substrings is +** found, the corresponding affinity is returned. If zType contains +** more than one of the substrings, entries toward the top of +** the table take priority. For example, if zType is 'BLOBINT', +** SQLITE_AFF_INTEGER is returned. +** +** Substring | Affinity +** -------------------------------- +** 'INT' | SQLITE_AFF_INTEGER +** 'CHAR' | SQLITE_AFF_TEXT +** 'CLOB' | SQLITE_AFF_TEXT +** 'TEXT' | SQLITE_AFF_TEXT +** 'BLOB' | SQLITE_AFF_NONE +** 'REAL' | SQLITE_AFF_REAL +** 'FLOA' | SQLITE_AFF_REAL +** 'DOUB' | SQLITE_AFF_REAL +** +** If none of the substrings in the above table are found, +** SQLITE_AFF_NUMERIC is returned. +*/ +char sqlite3AffinityType(const Token *pType){ + u32 h = 0; + char aff = SQLITE_AFF_NUMERIC; + const unsigned char *zIn = pType->z; + const unsigned char *zEnd = &pType->z[pType->n]; + + while( zIn!=zEnd ){ + h = (h<<8) + sqlite3UpperToLower[*zIn]; + zIn++; + if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */ + aff = SQLITE_AFF_TEXT; + }else if( h==(('c'<<24)+('l'<<16)+('o'<<8)+'b') ){ /* CLOB */ + aff = SQLITE_AFF_TEXT; + }else if( h==(('t'<<24)+('e'<<16)+('x'<<8)+'t') ){ /* TEXT */ + aff = SQLITE_AFF_TEXT; + }else if( h==(('b'<<24)+('l'<<16)+('o'<<8)+'b') /* BLOB */ + && (aff==SQLITE_AFF_NUMERIC || aff==SQLITE_AFF_REAL) ){ + aff = SQLITE_AFF_NONE; +#ifndef SQLITE_OMIT_FLOATING_POINT + }else if( h==(('r'<<24)+('e'<<16)+('a'<<8)+'l') /* REAL */ + && aff==SQLITE_AFF_NUMERIC ){ + aff = SQLITE_AFF_REAL; + }else if( h==(('f'<<24)+('l'<<16)+('o'<<8)+'a') /* FLOA */ + && aff==SQLITE_AFF_NUMERIC ){ + aff = SQLITE_AFF_REAL; + }else if( h==(('d'<<24)+('o'<<16)+('u'<<8)+'b') /* DOUB */ + && aff==SQLITE_AFF_NUMERIC ){ + aff = SQLITE_AFF_REAL; +#endif + }else if( (h&0x00FFFFFF)==(('i'<<16)+('n'<<8)+'t') ){ /* INT */ + aff = SQLITE_AFF_INTEGER; + break; + } + } + + return aff; +} + +/* +** This routine is called by the parser while in the middle of +** parsing a CREATE TABLE statement. The pFirst token is the first +** token in the sequence of tokens that describe the type of the +** column currently under construction. pLast is the last token +** in the sequence. Use this information to construct a string +** that contains the typename of the column and store that string +** in zType. +*/ +void sqlite3AddColumnType(Parse *pParse, Token *pType){ + Table *p; + int i; + Column *pCol; + + if( (p = pParse->pNewTable)==0 ) return; + i = p->nCol-1; + if( i<0 ) return; + pCol = &p->aCol[i]; + sqliteFree(pCol->zType); + pCol->zType = sqlite3NameFromToken(pType); + pCol->affinity = sqlite3AffinityType(pType); +} + +/* +** The expression is the default value for the most recently added column +** of the table currently under construction. +** +** Default value expressions must be constant. Raise an exception if this +** is not the case. +** +** This routine is called by the parser while in the middle of +** parsing a CREATE TABLE statement. +*/ +void sqlite3AddDefaultValue(Parse *pParse, Expr *pExpr){ + Table *p; + Column *pCol; + if( (p = pParse->pNewTable)!=0 ){ + pCol = &(p->aCol[p->nCol-1]); + if( !sqlite3ExprIsConstantOrFunction(pExpr) ){ + sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant", + pCol->zName); + }else{ + Expr *pCopy; + sqlite3ExprDelete(pCol->pDflt); + pCol->pDflt = pCopy = sqlite3ExprDup(pExpr); + if( pCopy ){ + sqlite3TokenCopy(&pCopy->span, &pExpr->span); + } + } + } + sqlite3ExprDelete(pExpr); +} + +/* +** Designate the PRIMARY KEY for the table. pList is a list of names +** of columns that form the primary key. If pList is NULL, then the +** most recently added column of the table is the primary key. +** +** A table can have at most one primary key. If the table already has +** a primary key (and this is the second primary key) then create an +** error. +** +** If the PRIMARY KEY is on a single column whose datatype is INTEGER, +** then we will try to use that column as the rowid. Set the Table.iPKey +** field of the table under construction to be the index of the +** INTEGER PRIMARY KEY column. Table.iPKey is set to -1 if there is +** no INTEGER PRIMARY KEY. +** +** If the key is not an INTEGER PRIMARY KEY, then create a unique +** index for the key. No index is created for INTEGER PRIMARY KEYs. +*/ +void sqlite3AddPrimaryKey( + Parse *pParse, /* Parsing context */ + ExprList *pList, /* List of field names to be indexed */ + int onError, /* What to do with a uniqueness conflict */ + int autoInc, /* True if the AUTOINCREMENT keyword is present */ + int sortOrder /* SQLITE_SO_ASC or SQLITE_SO_DESC */ +){ + Table *pTab = pParse->pNewTable; + char *zType = 0; + int iCol = -1, i; + if( pTab==0 || IN_DECLARE_VTAB ) goto primary_key_exit; + if( pTab->hasPrimKey ){ + sqlite3ErrorMsg(pParse, + "table \"%s\" has more than one primary key", pTab->zName); + goto primary_key_exit; + } + pTab->hasPrimKey = 1; + if( pList==0 ){ + iCol = pTab->nCol - 1; + pTab->aCol[iCol].isPrimKey = 1; + }else{ + for(i=0; inExpr; i++){ + for(iCol=0; iColnCol; iCol++){ + if( sqlite3StrICmp(pList->a[i].zName, pTab->aCol[iCol].zName)==0 ){ + break; + } + } + if( iColnCol ){ + pTab->aCol[iCol].isPrimKey = 1; + } + } + if( pList->nExpr>1 ) iCol = -1; + } + if( iCol>=0 && iColnCol ){ + zType = pTab->aCol[iCol].zType; + } + if( zType && sqlite3StrICmp(zType, "INTEGER")==0 + && sortOrder==SQLITE_SO_ASC ){ + pTab->iPKey = iCol; + pTab->keyConf = onError; + pTab->autoInc = autoInc; + }else if( autoInc ){ +#ifndef SQLITE_OMIT_AUTOINCREMENT + sqlite3ErrorMsg(pParse, "AUTOINCREMENT is only allowed on an " + "INTEGER PRIMARY KEY"); +#endif + }else{ + sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, 0, sortOrder, 0); + pList = 0; + } + +primary_key_exit: + sqlite3ExprListDelete(pList); + return; +} + +/* +** Add a new CHECK constraint to the table currently under construction. +*/ +void sqlite3AddCheckConstraint( + Parse *pParse, /* Parsing context */ + Expr *pCheckExpr /* The check expression */ +){ +#ifndef SQLITE_OMIT_CHECK + Table *pTab = pParse->pNewTable; + if( pTab && !IN_DECLARE_VTAB ){ + /* The CHECK expression must be duplicated so that tokens refer + ** to malloced space and not the (ephemeral) text of the CREATE TABLE + ** statement */ + pTab->pCheck = sqlite3ExprAnd(pTab->pCheck, sqlite3ExprDup(pCheckExpr)); + } +#endif + sqlite3ExprDelete(pCheckExpr); +} + +/* +** Set the collation function of the most recently parsed table column +** to the CollSeq given. +*/ +void sqlite3AddCollateType(Parse *pParse, const char *zType, int nType){ + Table *p; + int i; + + if( (p = pParse->pNewTable)==0 ) return; + i = p->nCol-1; + + if( sqlite3LocateCollSeq(pParse, zType, nType) ){ + Index *pIdx; + p->aCol[i].zColl = sqliteStrNDup(zType, nType); + + /* If the column is declared as " PRIMARY KEY COLLATE ", + ** then an index may have been created on this column before the + ** collation type was added. Correct this if it is the case. + */ + for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){ + assert( pIdx->nColumn==1 ); + if( pIdx->aiColumn[0]==i ){ + pIdx->azColl[0] = p->aCol[i].zColl; + } + } + } +} + +/* +** This function returns the collation sequence for database native text +** encoding identified by the string zName, length nName. +** +** If the requested collation sequence is not available, or not available +** in the database native encoding, the collation factory is invoked to +** request it. If the collation factory does not supply such a sequence, +** and the sequence is available in another text encoding, then that is +** returned instead. +** +** If no versions of the requested collations sequence are available, or +** another error occurs, NULL is returned and an error message written into +** pParse. +** +** This routine is a wrapper around sqlite3FindCollSeq(). This routine +** invokes the collation factory if the named collation cannot be found +** and generates an error message. +*/ +CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName){ + sqlite3 *db = pParse->db; + u8 enc = ENC(db); + u8 initbusy = db->init.busy; + CollSeq *pColl; + + pColl = sqlite3FindCollSeq(db, enc, zName, nName, initbusy); + if( !initbusy && (!pColl || !pColl->xCmp) ){ + pColl = sqlite3GetCollSeq(db, pColl, zName, nName); + if( !pColl ){ + if( nName<0 ){ + nName = strlen(zName); + } + sqlite3ErrorMsg(pParse, "no such collation sequence: %.*s", nName, zName); + pColl = 0; + } + } + + return pColl; +} + + +/* +** Generate code that will increment the schema cookie. +** +** The schema cookie is used to determine when the schema for the +** database changes. After each schema change, the cookie value +** changes. When a process first reads the schema it records the +** cookie. Thereafter, whenever it goes to access the database, +** it checks the cookie to make sure the schema has not changed +** since it was last read. +** +** This plan is not completely bullet-proof. It is possible for +** the schema to change multiple times and for the cookie to be +** set back to prior value. But schema changes are infrequent +** and the probability of hitting the same cookie value is only +** 1 chance in 2^32. So we're safe enough. +*/ +void sqlite3ChangeCookie(sqlite3 *db, Vdbe *v, int iDb){ + sqlite3VdbeAddOp(v, OP_Integer, db->aDb[iDb].pSchema->schema_cookie+1, 0); + sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 0); +} + +/* +** Measure the number of characters needed to output the given +** identifier. The number returned includes any quotes used +** but does not include the null terminator. +** +** The estimate is conservative. It might be larger that what is +** really needed. +*/ +static int identLength(const char *z){ + int n; + for(n=0; *z; n++, z++){ + if( *z=='"' ){ n++; } + } + return n + 2; +} + +/* +** Write an identifier onto the end of the given string. Add +** quote characters as needed. +*/ +static void identPut(char *z, int *pIdx, char *zSignedIdent){ + unsigned char *zIdent = (unsigned char*)zSignedIdent; + int i, j, needQuote; + i = *pIdx; + for(j=0; zIdent[j]; j++){ + if( !isalnum(zIdent[j]) && zIdent[j]!='_' ) break; + } + needQuote = zIdent[j]!=0 || isdigit(zIdent[0]) + || sqlite3KeywordCode(zIdent, j)!=TK_ID; + if( needQuote ) z[i++] = '"'; + for(j=0; zIdent[j]; j++){ + z[i++] = zIdent[j]; + if( zIdent[j]=='"' ) z[i++] = '"'; + } + if( needQuote ) z[i++] = '"'; + z[i] = 0; + *pIdx = i; +} + +/* +** Generate a CREATE TABLE statement appropriate for the given +** table. Memory to hold the text of the statement is obtained +** from sqliteMalloc() and must be freed by the calling function. +*/ +static char *createTableStmt(Table *p, int isTemp){ + int i, k, n; + char *zStmt; + char *zSep, *zSep2, *zEnd, *z; + Column *pCol; + n = 0; + for(pCol = p->aCol, i=0; inCol; i++, pCol++){ + n += identLength(pCol->zName); + z = pCol->zType; + if( z ){ + n += (strlen(z) + 1); + } + } + n += identLength(p->zName); + if( n<50 ){ + zSep = ""; + zSep2 = ","; + zEnd = ")"; + }else{ + zSep = "\n "; + zSep2 = ",\n "; + zEnd = "\n)"; + } + n += 35 + 6*p->nCol; + zStmt = sqliteMallocRaw( n ); + if( zStmt==0 ) return 0; + sqlite3_snprintf(n, zStmt, + !OMIT_TEMPDB&&isTemp ? "CREATE TEMP TABLE ":"CREATE TABLE "); + k = strlen(zStmt); + identPut(zStmt, &k, p->zName); + zStmt[k++] = '('; + for(pCol=p->aCol, i=0; inCol; i++, pCol++){ + sqlite3_snprintf(n-k, &zStmt[k], zSep); + k += strlen(&zStmt[k]); + zSep = zSep2; + identPut(zStmt, &k, pCol->zName); + if( (z = pCol->zType)!=0 ){ + zStmt[k++] = ' '; + assert( strlen(z)+k+1<=n ); + sqlite3_snprintf(n-k, &zStmt[k], "%s", z); + k += strlen(z); + } + } + sqlite3_snprintf(n-k, &zStmt[k], "%s", zEnd); + return zStmt; +} + +/* +** This routine is called to report the final ")" that terminates +** a CREATE TABLE statement. +** +** The table structure that other action routines have been building +** is added to the internal hash tables, assuming no errors have +** occurred. +** +** An entry for the table is made in the master table on disk, unless +** this is a temporary table or db->init.busy==1. When db->init.busy==1 +** it means we are reading the sqlite_master table because we just +** connected to the database or because the sqlite_master table has +** recently changed, so the entry for this table already exists in +** the sqlite_master table. We do not want to create it again. +** +** If the pSelect argument is not NULL, it means that this routine +** was called to create a table generated from a +** "CREATE TABLE ... AS SELECT ..." statement. The column names of +** the new table will match the result set of the SELECT. +*/ +void sqlite3EndTable( + Parse *pParse, /* Parse context */ + Token *pCons, /* The ',' token after the last column defn. */ + Token *pEnd, /* The final ')' token in the CREATE TABLE */ + Select *pSelect /* Select from a "CREATE ... AS SELECT" */ +){ + Table *p; + sqlite3 *db = pParse->db; + int iDb; + + if( (pEnd==0 && pSelect==0) || pParse->nErr || sqlite3MallocFailed() ) { + return; + } + p = pParse->pNewTable; + if( p==0 ) return; + + assert( !db->init.busy || !pSelect ); + + iDb = sqlite3SchemaToIndex(db, p->pSchema); + +#ifndef SQLITE_OMIT_CHECK + /* Resolve names in all CHECK constraint expressions. + */ + if( p->pCheck ){ + SrcList sSrc; /* Fake SrcList for pParse->pNewTable */ + NameContext sNC; /* Name context for pParse->pNewTable */ + + memset(&sNC, 0, sizeof(sNC)); + memset(&sSrc, 0, sizeof(sSrc)); + sSrc.nSrc = 1; + sSrc.a[0].zName = p->zName; + sSrc.a[0].pTab = p; + sSrc.a[0].iCursor = -1; + sNC.pParse = pParse; + sNC.pSrcList = &sSrc; + sNC.isCheck = 1; + if( sqlite3ExprResolveNames(&sNC, p->pCheck) ){ + return; + } + } +#endif /* !defined(SQLITE_OMIT_CHECK) */ + + /* If the db->init.busy is 1 it means we are reading the SQL off the + ** "sqlite_master" or "sqlite_temp_master" table on the disk. + ** So do not write to the disk again. Extract the root page number + ** for the table from the db->init.newTnum field. (The page number + ** should have been put there by the sqliteOpenCb routine.) + */ + if( db->init.busy ){ + p->tnum = db->init.newTnum; + } + + /* If not initializing, then create a record for the new table + ** in the SQLITE_MASTER table of the database. The record number + ** for the new table entry should already be on the stack. + ** + ** If this is a TEMPORARY table, write the entry into the auxiliary + ** file instead of into the main database file. + */ + if( !db->init.busy ){ + int n; + Vdbe *v; + char *zType; /* "view" or "table" */ + char *zType2; /* "VIEW" or "TABLE" */ + char *zStmt; /* Text of the CREATE TABLE or CREATE VIEW statement */ + + v = sqlite3GetVdbe(pParse); + if( v==0 ) return; + + sqlite3VdbeAddOp(v, OP_Close, 0, 0); + + /* Create the rootpage for the new table and push it onto the stack. + ** A view has no rootpage, so just push a zero onto the stack for + ** views. Initialize zType at the same time. + */ + if( p->pSelect==0 ){ + /* A regular table */ + zType = "table"; + zType2 = "TABLE"; +#ifndef SQLITE_OMIT_VIEW + }else{ + /* A view */ + zType = "view"; + zType2 = "VIEW"; +#endif + } + + /* If this is a CREATE TABLE xx AS SELECT ..., execute the SELECT + ** statement to populate the new table. The root-page number for the + ** new table is on the top of the vdbe stack. + ** + ** Once the SELECT has been coded by sqlite3Select(), it is in a + ** suitable state to query for the column names and types to be used + ** by the new table. + ** + ** A shared-cache write-lock is not required to write to the new table, + ** as a schema-lock must have already been obtained to create it. Since + ** a schema-lock excludes all other database users, the write-lock would + ** be redundant. + */ + if( pSelect ){ + Table *pSelTab; + sqlite3VdbeAddOp(v, OP_Dup, 0, 0); + sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); + sqlite3VdbeAddOp(v, OP_OpenWrite, 1, 0); + pParse->nTab = 2; + sqlite3Select(pParse, pSelect, SRT_Table, 1, 0, 0, 0, 0); + sqlite3VdbeAddOp(v, OP_Close, 1, 0); + if( pParse->nErr==0 ){ + pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSelect); + if( pSelTab==0 ) return; + assert( p->aCol==0 ); + p->nCol = pSelTab->nCol; + p->aCol = pSelTab->aCol; + pSelTab->nCol = 0; + pSelTab->aCol = 0; + sqlite3DeleteTable(pSelTab); + } + } + + /* Compute the complete text of the CREATE statement */ + if( pSelect ){ + zStmt = createTableStmt(p, p->pSchema==pParse->db->aDb[1].pSchema); + }else{ + n = pEnd->z - pParse->sNameToken.z + 1; + zStmt = sqlite3MPrintf("CREATE %s %.*s", zType2, n, pParse->sNameToken.z); + } + + /* 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 rowid for the preallocated + ** slot is the 2nd item on the stack. The top of the stack is the + ** root page for the new table (or a 0 if this is a view). + */ + sqlite3NestedParse(pParse, + "UPDATE %Q.%s " + "SET type='%s', name=%Q, tbl_name=%Q, rootpage=#0, sql=%Q " + "WHERE rowid=#1", + db->aDb[iDb].zName, SCHEMA_TABLE(iDb), + zType, + p->zName, + p->zName, + zStmt + ); + sqliteFree(zStmt); + sqlite3ChangeCookie(db, v, iDb); + +#ifndef SQLITE_OMIT_AUTOINCREMENT + /* Check to see if we need to create an sqlite_sequence table for + ** keeping track of autoincrement keys. + */ + if( p->autoInc ){ + Db *pDb = &db->aDb[iDb]; + if( pDb->pSchema->pSeqTab==0 ){ + sqlite3NestedParse(pParse, + "CREATE TABLE %Q.sqlite_sequence(name,seq)", + pDb->zName + ); + } + } +#endif + + /* Reparse everything to update our internal data structures */ + sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, + sqlite3MPrintf("tbl_name='%q'",p->zName), P3_DYNAMIC); + } + + + /* Add the table to the in-memory representation of the database. + */ + if( db->init.busy && pParse->nErr==0 ){ + Table *pOld; + FKey *pFKey; + Schema *pSchema = p->pSchema; + pOld = sqlite3HashInsert(&pSchema->tblHash, p->zName, strlen(p->zName)+1,p); + if( pOld ){ + assert( p==pOld ); /* Malloc must have failed inside HashInsert() */ + return; + } +#ifndef SQLITE_OMIT_FOREIGN_KEY + for(pFKey=p->pFKey; pFKey; pFKey=pFKey->pNextFrom){ + int nTo = strlen(pFKey->zTo) + 1; + pFKey->pNextTo = sqlite3HashFind(&pSchema->aFKey, pFKey->zTo, nTo); + sqlite3HashInsert(&pSchema->aFKey, pFKey->zTo, nTo, pFKey); + } +#endif + pParse->pNewTable = 0; + db->nTable++; + db->flags |= SQLITE_InternChanges; + +#ifndef SQLITE_OMIT_ALTERTABLE + if( !p->pSelect ){ + const char *zName = (const char *)pParse->sNameToken.z; + int nName; + assert( !pSelect && pCons && pEnd ); + if( pCons->z==0 ){ + pCons = pEnd; + } + nName = (const char *)pCons->z - zName; + p->addColOffset = 13 + sqlite3Utf8CharLen(zName, nName); + } +#endif + } +} + +#ifndef SQLITE_OMIT_VIEW +/* +** The parser calls this routine in order to create a new VIEW +*/ +void sqlite3CreateView( + Parse *pParse, /* The parsing context */ + Token *pBegin, /* The CREATE token that begins the statement */ + Token *pName1, /* The token that holds the name of the view */ + Token *pName2, /* The token that holds the name of the view */ + Select *pSelect, /* A SELECT statement that will become the new view */ + int isTemp, /* TRUE for a TEMPORARY view */ + int noErr /* Suppress error messages if VIEW already exists */ +){ + Table *p; + int n; + const unsigned char *z; + Token sEnd; + DbFixer sFix; + Token *pName; + int iDb; + + if( pParse->nVar>0 ){ + sqlite3ErrorMsg(pParse, "parameters are not allowed in views"); + sqlite3SelectDelete(pSelect); + return; + } + sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr); + p = pParse->pNewTable; + if( p==0 || pParse->nErr ){ + sqlite3SelectDelete(pSelect); + return; + } + sqlite3TwoPartName(pParse, pName1, pName2, &pName); + iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema); + if( sqlite3FixInit(&sFix, pParse, iDb, "view", pName) + && sqlite3FixSelect(&sFix, pSelect) + ){ + sqlite3SelectDelete(pSelect); + return; + } + + /* Make a copy of the entire SELECT statement that defines the view. + ** This will force all the Expr.token.z values to be dynamically + ** allocated rather than point to the input string - which means that + ** they will persist after the current sqlite3_exec() call returns. + */ + p->pSelect = sqlite3SelectDup(pSelect); + sqlite3SelectDelete(pSelect); + if( sqlite3MallocFailed() ){ + return; + } + if( !pParse->db->init.busy ){ + sqlite3ViewGetColumnNames(pParse, p); + } + + /* Locate the end of the CREATE VIEW statement. Make sEnd point to + ** the end. + */ + sEnd = pParse->sLastToken; + if( sEnd.z[0]!=0 && sEnd.z[0]!=';' ){ + sEnd.z += sEnd.n; + } + sEnd.n = 0; + n = sEnd.z - pBegin->z; + z = (const unsigned char*)pBegin->z; + while( n>0 && (z[n-1]==';' || isspace(z[n-1])) ){ n--; } + sEnd.z = &z[n-1]; + sEnd.n = 1; + + /* Use sqlite3EndTable() to add the view to the SQLITE_MASTER table */ + sqlite3EndTable(pParse, 0, &sEnd, 0); + return; +} +#endif /* SQLITE_OMIT_VIEW */ + +#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) +/* +** The Table structure pTable is really a VIEW. Fill in the names of +** the columns of the view in the pTable structure. Return the number +** of errors. If an error is seen leave an error message in pParse->zErrMsg. +*/ +int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ + Table *pSelTab; /* A fake table from which we get the result set */ + Select *pSel; /* Copy of the SELECT that implements the view */ + int nErr = 0; /* Number of errors encountered */ + int n; /* Temporarily holds the number of cursors assigned */ + + assert( pTable ); + +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( sqlite3VtabCallConnect(pParse, pTable) ){ + return SQLITE_ERROR; + } + if( IsVirtual(pTable) ) return 0; +#endif + +#ifndef SQLITE_OMIT_VIEW + /* A positive nCol means the columns names for this view are + ** already known. + */ + if( pTable->nCol>0 ) return 0; + + /* A negative nCol is a special marker meaning that we are currently + ** trying to compute the column names. If we enter this routine with + ** a negative nCol, it means two or more views form a loop, like this: + ** + ** CREATE VIEW one AS SELECT * FROM two; + ** CREATE VIEW two AS SELECT * FROM one; + ** + ** Actually, this error is caught previously and so the following test + ** should always fail. But we will leave it in place just to be safe. + */ + if( pTable->nCol<0 ){ + sqlite3ErrorMsg(pParse, "view %s is circularly defined", pTable->zName); + return 1; + } + assert( pTable->nCol>=0 ); + + /* If we get this far, it means we need to compute the table names. + ** Note that the call to sqlite3ResultSetOfSelect() will expand any + ** "*" elements in the results set of the view and will assign cursors + ** to the elements of the FROM clause. But we do not want these changes + ** to be permanent. So the computation is done on a copy of the SELECT + ** statement that defines the view. + */ + assert( pTable->pSelect ); + pSel = sqlite3SelectDup(pTable->pSelect); + if( pSel ){ + n = pParse->nTab; + sqlite3SrcListAssignCursors(pParse, pSel->pSrc); + pTable->nCol = -1; + pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSel); + pParse->nTab = n; + if( pSelTab ){ + assert( pTable->aCol==0 ); + pTable->nCol = pSelTab->nCol; + pTable->aCol = pSelTab->aCol; + pSelTab->nCol = 0; + pSelTab->aCol = 0; + sqlite3DeleteTable(pSelTab); + pTable->pSchema->flags |= DB_UnresetViews; + }else{ + pTable->nCol = 0; + nErr++; + } + sqlite3SelectDelete(pSel); + } else { + nErr++; + } +#endif /* SQLITE_OMIT_VIEW */ + return nErr; +} +#endif /* !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE) */ + +#ifndef SQLITE_OMIT_VIEW +/* +** Clear the column names from every VIEW in database idx. +*/ +static void sqliteViewResetAll(sqlite3 *db, int idx){ + HashElem *i; + if( !DbHasProperty(db, idx, DB_UnresetViews) ) return; + for(i=sqliteHashFirst(&db->aDb[idx].pSchema->tblHash); i;i=sqliteHashNext(i)){ + Table *pTab = sqliteHashData(i); + if( pTab->pSelect ){ + sqliteResetColumnNames(pTab); + } + } + DbClearProperty(db, idx, DB_UnresetViews); +} +#else +# define sqliteViewResetAll(A,B) +#endif /* SQLITE_OMIT_VIEW */ + +/* +** This function is called by the VDBE to adjust the internal schema +** used by SQLite when the btree layer moves a table root page. The +** root-page of a table or index in database iDb has changed from iFrom +** to iTo. +** +** Ticket #1728: The symbol table might still contain information +** on tables and/or indices that are the process of being deleted. +** If you are unlucky, one of those deleted indices or tables might +** have the same rootpage number as the real table or index that is +** being moved. So we cannot stop searching after the first match +** because the first match might be for one of the deleted indices +** or tables and not the table/index that is actually being moved. +** We must continue looping until all tables and indices with +** rootpage==iFrom have been converted to have a rootpage of iTo +** in order to be certain that we got the right one. +*/ +#ifndef SQLITE_OMIT_AUTOVACUUM +void sqlite3RootPageMoved(Db *pDb, int iFrom, int iTo){ + HashElem *pElem; + Hash *pHash; + + pHash = &pDb->pSchema->tblHash; + for(pElem=sqliteHashFirst(pHash); pElem; pElem=sqliteHashNext(pElem)){ + Table *pTab = sqliteHashData(pElem); + if( pTab->tnum==iFrom ){ + pTab->tnum = iTo; + } + } + pHash = &pDb->pSchema->idxHash; + for(pElem=sqliteHashFirst(pHash); pElem; pElem=sqliteHashNext(pElem)){ + Index *pIdx = sqliteHashData(pElem); + if( pIdx->tnum==iFrom ){ + pIdx->tnum = iTo; + } + } +} +#endif + +/* +** Write code to erase the table with root-page iTable from database iDb. +** Also write code to modify the sqlite_master table and internal schema +** if a root-page of another table is moved by the btree-layer whilst +** erasing iTable (this can happen with an auto-vacuum database). +*/ +static void destroyRootPage(Parse *pParse, int iTable, int iDb){ + Vdbe *v = sqlite3GetVdbe(pParse); + sqlite3VdbeAddOp(v, OP_Destroy, iTable, iDb); +#ifndef SQLITE_OMIT_AUTOVACUUM + /* OP_Destroy pushes an integer onto the stack. If this integer + ** is non-zero, then it is the root page number of a table moved to + ** location iTable. The following code modifies the sqlite_master table to + ** reflect this. + ** + ** The "#0" in the SQL is a special constant that means whatever value + ** is on the top of the stack. See sqlite3RegisterExpr(). + */ + sqlite3NestedParse(pParse, + "UPDATE %Q.%s SET rootpage=%d WHERE #0 AND rootpage=#0", + pParse->db->aDb[iDb].zName, SCHEMA_TABLE(iDb), iTable); +#endif +} + +/* +** Write VDBE code to erase table pTab and all associated indices on disk. +** Code to update the sqlite_master tables and internal schema definitions +** in case a root-page belonging to another table is moved by the btree layer +** is also added (this can happen with an auto-vacuum database). +*/ +static void destroyTable(Parse *pParse, Table *pTab){ +#ifdef SQLITE_OMIT_AUTOVACUUM + Index *pIdx; + int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + destroyRootPage(pParse, pTab->tnum, iDb); + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + destroyRootPage(pParse, pIdx->tnum, iDb); + } +#else + /* If the database may be auto-vacuum capable (if SQLITE_OMIT_AUTOVACUUM + ** is not defined), then it is important to call OP_Destroy on the + ** table and index root-pages in order, starting with the numerically + ** largest root-page number. This guarantees that none of the root-pages + ** to be destroyed is relocated by an earlier OP_Destroy. i.e. if the + ** following were coded: + ** + ** OP_Destroy 4 0 + ** ... + ** OP_Destroy 5 0 + ** + ** and root page 5 happened to be the largest root-page number in the + ** database, then root page 5 would be moved to page 4 by the + ** "OP_Destroy 4 0" opcode. The subsequent "OP_Destroy 5 0" would hit + ** a free-list page. + */ + int iTab = pTab->tnum; + int iDestroyed = 0; + + while( 1 ){ + Index *pIdx; + int iLargest = 0; + + if( iDestroyed==0 || iTabpIndex; pIdx; pIdx=pIdx->pNext){ + int iIdx = pIdx->tnum; + assert( pIdx->pSchema==pTab->pSchema ); + if( (iDestroyed==0 || (iIdxiLargest ){ + iLargest = iIdx; + } + } + if( iLargest==0 ){ + return; + }else{ + int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + destroyRootPage(pParse, iLargest, iDb); + iDestroyed = iLargest; + } + } +#endif +} + +/* +** This routine is called to do the work of a DROP TABLE statement. +** pName is the name of the table to be dropped. +*/ +void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){ + Table *pTab; + Vdbe *v; + sqlite3 *db = pParse->db; + int iDb; + + if( pParse->nErr || sqlite3MallocFailed() ){ + goto exit_drop_table; + } + assert( pName->nSrc==1 ); + pTab = sqlite3LocateTable(pParse, pName->a[0].zName, pName->a[0].zDatabase); + + if( pTab==0 ){ + if( noErr ){ + sqlite3ErrorClear(pParse); + } + goto exit_drop_table; + } + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); + assert( iDb>=0 && iDbnDb ); +#ifndef SQLITE_OMIT_AUTHORIZATION + { + int code; + const char *zTab = SCHEMA_TABLE(iDb); + const char *zDb = db->aDb[iDb].zName; + const char *zArg2 = 0; + if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){ + goto exit_drop_table; + } + if( isView ){ + if( !OMIT_TEMPDB && iDb==1 ){ + code = SQLITE_DROP_TEMP_VIEW; + }else{ + code = SQLITE_DROP_VIEW; + } +#ifndef SQLITE_OMIT_VIRTUALTABLE + }else if( IsVirtual(pTab) ){ + if( sqlite3ViewGetColumnNames(pParse, pTab) ){ + goto exit_drop_table; + } + code = SQLITE_DROP_VTABLE; + zArg2 = pTab->pMod->zName; +#endif + }else{ + if( !OMIT_TEMPDB && iDb==1 ){ + code = SQLITE_DROP_TEMP_TABLE; + }else{ + code = SQLITE_DROP_TABLE; + } + } + if( sqlite3AuthCheck(pParse, code, pTab->zName, zArg2, zDb) ){ + goto exit_drop_table; + } + if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){ + goto exit_drop_table; + } + } +#endif + if( pTab->readOnly || pTab==db->aDb[iDb].pSchema->pSeqTab ){ + sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName); + goto exit_drop_table; + } + +#ifndef SQLITE_OMIT_VIEW + /* Ensure DROP TABLE is not used on a view, and DROP VIEW is not used + ** on a table. + */ + if( isView && pTab->pSelect==0 ){ + sqlite3ErrorMsg(pParse, "use DROP TABLE to delete table %s", pTab->zName); + goto exit_drop_table; + } + if( !isView && pTab->pSelect ){ + sqlite3ErrorMsg(pParse, "use DROP VIEW to delete view %s", pTab->zName); + goto exit_drop_table; + } +#endif + + /* Generate code to remove the table from the master table + ** on disk. + */ + v = sqlite3GetVdbe(pParse); + if( v ){ + Trigger *pTrigger; + Db *pDb = &db->aDb[iDb]; + sqlite3BeginWriteOperation(pParse, 0, iDb); + +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( IsVirtual(pTab) ){ + Vdbe *v = sqlite3GetVdbe(pParse); + if( v ){ + sqlite3VdbeAddOp(v, OP_VBegin, 0, 0); + } + } +#endif + + /* Drop all triggers associated with the table being dropped. Code + ** is generated to remove entries from sqlite_master and/or + ** sqlite_temp_master if required. + */ + pTrigger = pTab->pTrigger; + while( pTrigger ){ + assert( pTrigger->pSchema==pTab->pSchema || + pTrigger->pSchema==db->aDb[1].pSchema ); + sqlite3DropTriggerPtr(pParse, pTrigger); + pTrigger = pTrigger->pNext; + } + +#ifndef SQLITE_OMIT_AUTOINCREMENT + /* Remove any entries of the sqlite_sequence table associated with + ** the table being dropped. This is done before the table is dropped + ** at the btree level, in case the sqlite_sequence table needs to + ** move as a result of the drop (can happen in auto-vacuum mode). + */ + if( pTab->autoInc ){ + sqlite3NestedParse(pParse, + "DELETE FROM %s.sqlite_sequence WHERE name=%Q", + pDb->zName, pTab->zName + ); + } +#endif + + /* Drop all SQLITE_MASTER table and index entries that refer to the + ** table. The program name loops through the master table and deletes + ** every row that refers to a table of the same name as the one being + ** dropped. Triggers are handled seperately because a trigger can be + ** created in the temp database that refers to a table in another + ** database. + */ + sqlite3NestedParse(pParse, + "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'", + pDb->zName, SCHEMA_TABLE(iDb), pTab->zName); + if( !isView && !IsVirtual(pTab) ){ + destroyTable(pParse, pTab); + } + + /* Remove the table entry from SQLite's internal schema and modify + ** the schema cookie. + */ + if( IsVirtual(pTab) ){ + sqlite3VdbeOp3(v, OP_VDestroy, iDb, 0, pTab->zName, 0); + } + sqlite3VdbeOp3(v, OP_DropTable, iDb, 0, pTab->zName, 0); + sqlite3ChangeCookie(db, v, iDb); + } + sqliteViewResetAll(db, iDb); + +exit_drop_table: + sqlite3SrcListDelete(pName); +} + +/* +** This routine is called to create a new foreign key on the table +** currently under construction. pFromCol determines which columns +** in the current table point to the foreign key. If pFromCol==0 then +** connect the key to the last column inserted. pTo is the name of +** the table referred to. pToCol is a list of tables in the other +** pTo table that the foreign key points to. flags contains all +** information about the conflict resolution algorithms specified +** in the ON DELETE, ON UPDATE and ON INSERT clauses. +** +** An FKey structure is created and added to the table currently +** under construction in the pParse->pNewTable field. The new FKey +** is not linked into db->aFKey at this point - that does not happen +** until sqlite3EndTable(). +** +** The foreign key is set for IMMEDIATE processing. A subsequent call +** to sqlite3DeferForeignKey() might change this to DEFERRED. +*/ +void sqlite3CreateForeignKey( + Parse *pParse, /* Parsing context */ + ExprList *pFromCol, /* Columns in this table that point to other table */ + Token *pTo, /* Name of the other table */ + ExprList *pToCol, /* Columns in the other table */ + int flags /* Conflict resolution algorithms. */ +){ +#ifndef SQLITE_OMIT_FOREIGN_KEY + FKey *pFKey = 0; + Table *p = pParse->pNewTable; + int nByte; + int i; + int nCol; + char *z; + + assert( pTo!=0 ); + if( p==0 || pParse->nErr || IN_DECLARE_VTAB ) goto fk_end; + if( pFromCol==0 ){ + int iCol = p->nCol-1; + if( iCol<0 ) goto fk_end; + if( pToCol && pToCol->nExpr!=1 ){ + sqlite3ErrorMsg(pParse, "foreign key on %s" + " should reference only one column of table %T", + p->aCol[iCol].zName, pTo); + goto fk_end; + } + nCol = 1; + }else if( pToCol && pToCol->nExpr!=pFromCol->nExpr ){ + sqlite3ErrorMsg(pParse, + "number of columns in foreign key does not match the number of " + "columns in the referenced table"); + goto fk_end; + }else{ + nCol = pFromCol->nExpr; + } + nByte = sizeof(*pFKey) + nCol*sizeof(pFKey->aCol[0]) + pTo->n + 1; + if( pToCol ){ + for(i=0; inExpr; i++){ + nByte += strlen(pToCol->a[i].zName) + 1; + } + } + pFKey = sqliteMalloc( nByte ); + if( pFKey==0 ) goto fk_end; + pFKey->pFrom = p; + pFKey->pNextFrom = p->pFKey; + z = (char*)&pFKey[1]; + pFKey->aCol = (struct sColMap*)z; + z += sizeof(struct sColMap)*nCol; + pFKey->zTo = z; + memcpy(z, pTo->z, pTo->n); + z[pTo->n] = 0; + z += pTo->n+1; + pFKey->pNextTo = 0; + pFKey->nCol = nCol; + if( pFromCol==0 ){ + pFKey->aCol[0].iFrom = p->nCol-1; + }else{ + for(i=0; inCol; j++){ + if( sqlite3StrICmp(p->aCol[j].zName, pFromCol->a[i].zName)==0 ){ + pFKey->aCol[i].iFrom = j; + break; + } + } + if( j>=p->nCol ){ + sqlite3ErrorMsg(pParse, + "unknown column \"%s\" in foreign key definition", + pFromCol->a[i].zName); + goto fk_end; + } + } + } + if( pToCol ){ + for(i=0; ia[i].zName); + pFKey->aCol[i].zCol = z; + memcpy(z, pToCol->a[i].zName, n); + z[n] = 0; + z += n+1; + } + } + pFKey->isDeferred = 0; + pFKey->deleteConf = flags & 0xff; + pFKey->updateConf = (flags >> 8 ) & 0xff; + pFKey->insertConf = (flags >> 16 ) & 0xff; + + /* Link the foreign key to the table as the last step. + */ + p->pFKey = pFKey; + pFKey = 0; + +fk_end: + sqliteFree(pFKey); +#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ + sqlite3ExprListDelete(pFromCol); + sqlite3ExprListDelete(pToCol); +} + +/* +** This routine is called when an INITIALLY IMMEDIATE or INITIALLY DEFERRED +** clause is seen as part of a foreign key definition. The isDeferred +** parameter is 1 for INITIALLY DEFERRED and 0 for INITIALLY IMMEDIATE. +** The behavior of the most recently created foreign key is adjusted +** accordingly. +*/ +void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){ +#ifndef SQLITE_OMIT_FOREIGN_KEY + Table *pTab; + FKey *pFKey; + if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return; + pFKey->isDeferred = isDeferred; +#endif +} + +/* +** Generate code that will erase and refill index *pIdx. This is +** used to initialize a newly created index or to recompute the +** content of an index in response to a REINDEX command. +** +** if memRootPage is not negative, it means that the index is newly +** created. The memory cell specified by memRootPage contains the +** root page number of the index. If memRootPage is negative, then +** the index already exists and must be cleared before being refilled and +** the root page number of the index is taken from pIndex->tnum. +*/ +static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ + Table *pTab = pIndex->pTable; /* The table that is indexed */ + int iTab = pParse->nTab; /* Btree cursor used for pTab */ + int iIdx = pParse->nTab+1; /* Btree cursor used for pIndex */ + int addr1; /* Address of top of loop */ + int tnum; /* Root page of index */ + Vdbe *v; /* Generate code into this virtual machine */ + KeyInfo *pKey; /* KeyInfo for index */ + int iDb = sqlite3SchemaToIndex(pParse->db, pIndex->pSchema); + +#ifndef SQLITE_OMIT_AUTHORIZATION + if( sqlite3AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0, + pParse->db->aDb[iDb].zName ) ){ + return; + } +#endif + + /* Require a write-lock on the table to perform this operation */ + sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName); + + v = sqlite3GetVdbe(pParse); + if( v==0 ) return; + if( memRootPage>=0 ){ + sqlite3VdbeAddOp(v, OP_MemLoad, memRootPage, 0); + tnum = 0; + }else{ + tnum = pIndex->tnum; + sqlite3VdbeAddOp(v, OP_Clear, tnum, iDb); + } + sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); + pKey = sqlite3IndexKeyinfo(pParse, pIndex); + sqlite3VdbeOp3(v, OP_OpenWrite, iIdx, tnum, (char *)pKey, P3_KEYINFO_HANDOFF); + sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); + addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iTab, 0); + sqlite3GenerateIndexKey(v, pIndex, iTab); + if( pIndex->onError!=OE_None ){ + int curaddr = sqlite3VdbeCurrentAddr(v); + int addr2 = curaddr+4; + sqlite3VdbeChangeP2(v, curaddr-1, addr2); + sqlite3VdbeAddOp(v, OP_Rowid, iTab, 0); + sqlite3VdbeAddOp(v, OP_AddImm, 1, 0); + sqlite3VdbeAddOp(v, OP_IsUnique, iIdx, addr2); + sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, OE_Abort, + "indexed columns are not unique", P3_STATIC); + assert( sqlite3MallocFailed() || addr2==sqlite3VdbeCurrentAddr(v) ); + } + sqlite3VdbeAddOp(v, OP_IdxInsert, iIdx, 0); + sqlite3VdbeAddOp(v, OP_Next, iTab, addr1+1); + sqlite3VdbeJumpHere(v, addr1); + sqlite3VdbeAddOp(v, OP_Close, iTab, 0); + sqlite3VdbeAddOp(v, OP_Close, iIdx, 0); +} + +/* +** Create a new index for an SQL table. pName1.pName2 is the name of the index +** and pTblList is the name of the table that is to be indexed. Both will +** be NULL for a primary key or an index that is created to satisfy a +** UNIQUE constraint. If pTable and pIndex are NULL, use pParse->pNewTable +** as the table to be indexed. pParse->pNewTable is a table that is +** currently being constructed by a CREATE TABLE statement. +** +** pList is a list of columns to be indexed. pList will be NULL if this +** is a primary key or unique-constraint on the most recent column added +** to the table currently under construction. +*/ +void sqlite3CreateIndex( + Parse *pParse, /* All information about this parse */ + Token *pName1, /* First part of index name. May be NULL */ + Token *pName2, /* Second part of index name. May be NULL */ + SrcList *pTblName, /* Table to index. Use pParse->pNewTable if 0 */ + ExprList *pList, /* A list of columns to be indexed */ + int onError, /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ + Token *pStart, /* The CREATE token that begins this statement */ + Token *pEnd, /* The ")" that closes the CREATE INDEX statement */ + int sortOrder, /* Sort order of primary key when pList==NULL */ + int ifNotExist /* Omit error if index already exists */ +){ + Table *pTab = 0; /* Table to be indexed */ + Index *pIndex = 0; /* The index to be created */ + char *zName = 0; /* Name of the index */ + int nName; /* Number of characters in zName */ + int i, j; + Token nullId; /* Fake token for an empty ID list */ + DbFixer sFix; /* For assigning database names to pTable */ + int sortOrderMask; /* 1 to honor DESC in index. 0 to ignore. */ + sqlite3 *db = pParse->db; + Db *pDb; /* The specific table containing the indexed database */ + int iDb; /* Index of the database that is being written */ + Token *pName = 0; /* Unqualified name of the index to create */ + struct ExprList_item *pListItem; /* For looping over pList */ + int nCol; + int nExtra = 0; + char *zExtra; + + if( pParse->nErr || sqlite3MallocFailed() || IN_DECLARE_VTAB ){ + goto exit_create_index; + } + + /* + ** Find the table that is to be indexed. Return early if not found. + */ + if( pTblName!=0 ){ + + /* Use the two-part index name to determine the database + ** to search for the table. 'Fix' the table name to this db + ** before looking up the table. + */ + assert( pName1 && pName2 ); + iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pName); + if( iDb<0 ) goto exit_create_index; + +#ifndef SQLITE_OMIT_TEMPDB + /* If the index name was unqualified, check if the the table + ** is a temp table. If so, set the database to 1. + */ + pTab = sqlite3SrcListLookup(pParse, pTblName); + if( pName2 && pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){ + iDb = 1; + } +#endif + + if( sqlite3FixInit(&sFix, pParse, iDb, "index", pName) && + sqlite3FixSrcList(&sFix, pTblName) + ){ + /* Because the parser constructs pTblName from a single identifier, + ** sqlite3FixSrcList can never fail. */ + assert(0); + } + pTab = sqlite3LocateTable(pParse, pTblName->a[0].zName, + pTblName->a[0].zDatabase); + if( !pTab ) goto exit_create_index; + assert( db->aDb[iDb].pSchema==pTab->pSchema ); + }else{ + assert( pName==0 ); + pTab = pParse->pNewTable; + if( !pTab ) goto exit_create_index; + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); + } + pDb = &db->aDb[iDb]; + + if( pTab==0 || pParse->nErr ) goto exit_create_index; + if( pTab->readOnly ){ + sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName); + goto exit_create_index; + } +#ifndef SQLITE_OMIT_VIEW + if( pTab->pSelect ){ + sqlite3ErrorMsg(pParse, "views may not be indexed"); + goto exit_create_index; + } +#endif +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( IsVirtual(pTab) ){ + sqlite3ErrorMsg(pParse, "virtual tables may not be indexed"); + goto exit_create_index; + } +#endif + + /* + ** Find the name of the index. Make sure there is not already another + ** index or table with the same name. + ** + ** Exception: If we are reading the names of permanent indices from the + ** sqlite_master table (because some other process changed the schema) and + ** one of the index names collides with the name of a temporary table or + ** index, then we will continue to process this index. + ** + ** If pName==0 it means that we are + ** dealing with a primary key or UNIQUE constraint. We have to invent our + ** own name. + */ + if( pName ){ + zName = sqlite3NameFromToken(pName); + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto exit_create_index; + if( zName==0 ) goto exit_create_index; + if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ + goto exit_create_index; + } + if( !db->init.busy ){ + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto exit_create_index; + if( sqlite3FindTable(db, zName, 0)!=0 ){ + sqlite3ErrorMsg(pParse, "there is already a table named %s", zName); + goto exit_create_index; + } + } + if( sqlite3FindIndex(db, zName, pDb->zName)!=0 ){ + if( !ifNotExist ){ + sqlite3ErrorMsg(pParse, "index %s already exists", zName); + } + goto exit_create_index; + } + }else{ + char zBuf[30]; + int n; + Index *pLoop; + for(pLoop=pTab->pIndex, n=1; pLoop; pLoop=pLoop->pNext, n++){} + sqlite3_snprintf(sizeof(zBuf),zBuf,"_%d",n); + zName = 0; + sqlite3SetString(&zName, "sqlite_autoindex_", pTab->zName, zBuf, (char*)0); + if( zName==0 ) goto exit_create_index; + } + + /* Check for authorization to create an index. + */ +#ifndef SQLITE_OMIT_AUTHORIZATION + { + const char *zDb = pDb->zName; + if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iDb), 0, zDb) ){ + goto exit_create_index; + } + i = SQLITE_CREATE_INDEX; + if( !OMIT_TEMPDB && iDb==1 ) i = SQLITE_CREATE_TEMP_INDEX; + if( sqlite3AuthCheck(pParse, i, zName, pTab->zName, zDb) ){ + goto exit_create_index; + } + } +#endif + + /* If pList==0, it means this routine was called to make a primary + ** key out of the last column added to the table under construction. + ** So create a fake list to simulate this. + */ + if( pList==0 ){ + nullId.z = (u8*)pTab->aCol[pTab->nCol-1].zName; + nullId.n = strlen((char*)nullId.z); + pList = sqlite3ExprListAppend(0, 0, &nullId); + if( pList==0 ) goto exit_create_index; + pList->a[0].sortOrder = sortOrder; + } + + /* Figure out how many bytes of space are required to store explicitly + ** specified collation sequence names. + */ + for(i=0; inExpr; i++){ + Expr *pExpr = pList->a[i].pExpr; + if( pExpr ){ + nExtra += (1 + strlen(pExpr->pColl->zName)); + } + } + + /* + ** Allocate the index structure. + */ + nName = strlen(zName); + nCol = pList->nExpr; + pIndex = sqliteMalloc( + sizeof(Index) + /* Index structure */ + sizeof(int)*nCol + /* Index.aiColumn */ + sizeof(int)*(nCol+1) + /* Index.aiRowEst */ + sizeof(char *)*nCol + /* Index.azColl */ + sizeof(u8)*nCol + /* Index.aSortOrder */ + nName + 1 + /* Index.zName */ + nExtra /* Collation sequence names */ + ); + if( sqlite3MallocFailed() ) goto exit_create_index; + pIndex->azColl = (char**)(&pIndex[1]); + pIndex->aiColumn = (int *)(&pIndex->azColl[nCol]); + pIndex->aiRowEst = (unsigned *)(&pIndex->aiColumn[nCol]); + pIndex->aSortOrder = (u8 *)(&pIndex->aiRowEst[nCol+1]); + pIndex->zName = (char *)(&pIndex->aSortOrder[nCol]); + zExtra = (char *)(&pIndex->zName[nName+1]); + memcpy(pIndex->zName, zName, nName+1); + pIndex->pTable = pTab; + pIndex->nColumn = pList->nExpr; + pIndex->onError = onError; + pIndex->autoIndex = pName==0; + pIndex->pSchema = db->aDb[iDb].pSchema; + + /* Check to see if we should honor DESC requests on index columns + */ + if( pDb->pSchema->file_format>=4 ){ + sortOrderMask = -1; /* Honor DESC */ + }else{ + sortOrderMask = 0; /* Ignore DESC */ + } + + /* Scan the names of the columns of the table to be indexed and + ** load the column indices into the Index structure. Report an error + ** if any column is not found. + */ + for(i=0, pListItem=pList->a; inExpr; i++, pListItem++){ + const char *zColName = pListItem->zName; + Column *pTabCol; + int requestedSortOrder; + char *zColl; /* Collation sequence name */ + + for(j=0, pTabCol=pTab->aCol; jnCol; j++, pTabCol++){ + if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break; + } + if( j>=pTab->nCol ){ + sqlite3ErrorMsg(pParse, "table %s has no column named %s", + pTab->zName, zColName); + goto exit_create_index; + } + /* TODO: Add a test to make sure that the same column is not named + ** more than once within the same index. Only the first instance of + ** the column will ever be used by the optimizer. Note that using the + ** same column more than once cannot be an error because that would + ** break backwards compatibility - it needs to be a warning. + */ + pIndex->aiColumn[i] = j; + if( pListItem->pExpr ){ + assert( pListItem->pExpr->pColl ); + zColl = zExtra; + sqlite3_snprintf(nExtra, zExtra, "%s", pListItem->pExpr->pColl->zName); + zExtra += (strlen(zColl) + 1); + }else{ + zColl = pTab->aCol[j].zColl; + if( !zColl ){ + zColl = db->pDfltColl->zName; + } + } + if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl, -1) ){ + goto exit_create_index; + } + pIndex->azColl[i] = zColl; + requestedSortOrder = pListItem->sortOrder & sortOrderMask; + pIndex->aSortOrder[i] = requestedSortOrder; + } + sqlite3DefaultRowEst(pIndex); + + if( pTab==pParse->pNewTable ){ + /* This routine has been called to create an automatic index as a + ** result of a PRIMARY KEY or UNIQUE clause on a column definition, or + ** a PRIMARY KEY or UNIQUE clause following the column definitions. + ** i.e. one of: + ** + ** CREATE TABLE t(x PRIMARY KEY, y); + ** CREATE TABLE t(x, y, UNIQUE(x, y)); + ** + ** Either way, check to see if the table already has such an index. If + ** so, don't bother creating this one. This only applies to + ** automatically created indices. Users can do as they wish with + ** explicit indices. + */ + Index *pIdx; + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + int k; + assert( pIdx->onError!=OE_None ); + assert( pIdx->autoIndex ); + assert( pIndex->onError!=OE_None ); + + if( pIdx->nColumn!=pIndex->nColumn ) continue; + for(k=0; knColumn; k++){ + const char *z1 = pIdx->azColl[k]; + const char *z2 = pIndex->azColl[k]; + if( pIdx->aiColumn[k]!=pIndex->aiColumn[k] ) break; + if( pIdx->aSortOrder[k]!=pIndex->aSortOrder[k] ) break; + if( z1!=z2 && sqlite3StrICmp(z1, z2) ) break; + } + if( k==pIdx->nColumn ){ + if( pIdx->onError!=pIndex->onError ){ + /* This constraint creates the same index as a previous + ** constraint specified somewhere in the CREATE TABLE statement. + ** However the ON CONFLICT clauses are different. If both this + ** constraint and the previous equivalent constraint have explicit + ** ON CONFLICT clauses this is an error. Otherwise, use the + ** explicitly specified behaviour for the index. + */ + if( !(pIdx->onError==OE_Default || pIndex->onError==OE_Default) ){ + sqlite3ErrorMsg(pParse, + "conflicting ON CONFLICT clauses specified", 0); + } + if( pIdx->onError==OE_Default ){ + pIdx->onError = pIndex->onError; + } + } + goto exit_create_index; + } + } + } + + /* Link the new Index structure to its table and to the other + ** in-memory database structures. + */ + if( db->init.busy ){ + Index *p; + p = sqlite3HashInsert(&pIndex->pSchema->idxHash, + pIndex->zName, strlen(pIndex->zName)+1, pIndex); + if( p ){ + assert( p==pIndex ); /* Malloc must have failed */ + goto exit_create_index; + } + db->flags |= SQLITE_InternChanges; + if( pTblName!=0 ){ + pIndex->tnum = db->init.newTnum; + } + } + + /* If the db->init.busy is 0 then create the index on disk. This + ** involves writing the index into the master table and filling in the + ** index with the current table contents. + ** + ** The db->init.busy is 0 when the user first enters a CREATE INDEX + ** command. db->init.busy is 1 when a database is opened and + ** CREATE INDEX statements are read out of the master table. In + ** the latter case the index already exists on disk, which is why + ** we don't want to recreate it. + ** + ** If pTblName==0 it means this index is generated as a primary key + ** or UNIQUE constraint of a CREATE TABLE statement. Since the table + ** has just been created, it contains no data and the index initialization + ** step can be skipped. + */ + else if( db->init.busy==0 ){ + Vdbe *v; + char *zStmt; + int iMem = pParse->nMem++; + + v = sqlite3GetVdbe(pParse); + if( v==0 ) goto exit_create_index; + + + /* Create the rootpage for the index + */ + sqlite3BeginWriteOperation(pParse, 1, iDb); + sqlite3VdbeAddOp(v, OP_CreateIndex, iDb, 0); + sqlite3VdbeAddOp(v, OP_MemStore, iMem, 0); + + /* Gather the complete text of the CREATE INDEX statement into + ** the zStmt variable + */ + if( pStart && pEnd ){ + /* A named index with an explicit CREATE INDEX statement */ + zStmt = sqlite3MPrintf("CREATE%s INDEX %.*s", + onError==OE_None ? "" : " UNIQUE", + pEnd->z - pName->z + 1, + pName->z); + }else{ + /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */ + /* zStmt = sqlite3MPrintf(""); */ + zStmt = 0; + } + + /* Add an entry in sqlite_master for this index + */ + sqlite3NestedParse(pParse, + "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#0,%Q);", + db->aDb[iDb].zName, SCHEMA_TABLE(iDb), + pIndex->zName, + pTab->zName, + zStmt + ); + sqlite3VdbeAddOp(v, OP_Pop, 1, 0); + sqliteFree(zStmt); + + /* Fill the index with data and reparse the schema. Code an OP_Expire + ** to invalidate all pre-compiled statements. + */ + if( pTblName ){ + sqlite3RefillIndex(pParse, pIndex, iMem); + sqlite3ChangeCookie(db, v, iDb); + sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, + sqlite3MPrintf("name='%q'", pIndex->zName), P3_DYNAMIC); + sqlite3VdbeAddOp(v, OP_Expire, 0, 0); + } + } + + /* When adding an index to the list of indices for a table, make + ** sure all indices labeled OE_Replace come after all those labeled + ** OE_Ignore. This is necessary for the correct operation of UPDATE + ** and INSERT. + */ + if( db->init.busy || pTblName==0 ){ + if( onError!=OE_Replace || pTab->pIndex==0 + || pTab->pIndex->onError==OE_Replace){ + pIndex->pNext = pTab->pIndex; + pTab->pIndex = pIndex; + }else{ + Index *pOther = pTab->pIndex; + while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){ + pOther = pOther->pNext; + } + pIndex->pNext = pOther->pNext; + pOther->pNext = pIndex; + } + pIndex = 0; + } + + /* Clean up before exiting */ +exit_create_index: + if( pIndex ){ + freeIndex(pIndex); + } + sqlite3ExprListDelete(pList); + sqlite3SrcListDelete(pTblName); + sqliteFree(zName); + return; +} + +/* +** Generate code to make sure the file format number is at least minFormat. +** The generated code will increase the file format number if necessary. +*/ +void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minFormat){ + Vdbe *v; + v = sqlite3GetVdbe(pParse); + if( v ){ + sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 1); + sqlite3VdbeAddOp(v, OP_Integer, minFormat, 0); + sqlite3VdbeAddOp(v, OP_Ge, 0, sqlite3VdbeCurrentAddr(v)+3); + sqlite3VdbeAddOp(v, OP_Integer, minFormat, 0); + sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 1); + } +} + +/* +** Fill the Index.aiRowEst[] array with default information - information +** to be used when we have not run the ANALYZE command. +** +** aiRowEst[0] is suppose to contain the number of elements in the index. +** Since we do not know, guess 1 million. aiRowEst[1] is an estimate of the +** number of rows in the table that match any particular value of the +** first column of the index. aiRowEst[2] is an estimate of the number +** of rows that match any particular combiniation of the first 2 columns +** of the index. And so forth. It must always be the case that +* +** aiRowEst[N]<=aiRowEst[N-1] +** aiRowEst[N]>=1 +** +** Apart from that, we have little to go on besides intuition as to +** how aiRowEst[] should be initialized. The numbers generated here +** are based on typical values found in actual indices. +*/ +void sqlite3DefaultRowEst(Index *pIdx){ + unsigned *a = pIdx->aiRowEst; + int i; + assert( a!=0 ); + a[0] = 1000000; + for(i=pIdx->nColumn; i>=5; i--){ + a[i] = 5; + } + while( i>=1 ){ + a[i] = 11 - i; + i--; + } + if( pIdx->onError!=OE_None ){ + a[pIdx->nColumn] = 1; + } +} + +/* +** This routine will drop an existing named index. This routine +** implements the DROP INDEX statement. +*/ +void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){ + Index *pIndex; + Vdbe *v; + sqlite3 *db = pParse->db; + int iDb; + + if( pParse->nErr || sqlite3MallocFailed() ){ + goto exit_drop_index; + } + assert( pName->nSrc==1 ); + if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ + goto exit_drop_index; + } + pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase); + if( pIndex==0 ){ + if( !ifExists ){ + sqlite3ErrorMsg(pParse, "no such index: %S", pName, 0); + } + pParse->checkSchema = 1; + goto exit_drop_index; + } + if( pIndex->autoIndex ){ + sqlite3ErrorMsg(pParse, "index associated with UNIQUE " + "or PRIMARY KEY constraint cannot be dropped", 0); + goto exit_drop_index; + } + iDb = sqlite3SchemaToIndex(db, pIndex->pSchema); +#ifndef SQLITE_OMIT_AUTHORIZATION + { + int code = SQLITE_DROP_INDEX; + Table *pTab = pIndex->pTable; + const char *zDb = db->aDb[iDb].zName; + const char *zTab = SCHEMA_TABLE(iDb); + if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ + goto exit_drop_index; + } + if( !OMIT_TEMPDB && iDb ) code = SQLITE_DROP_TEMP_INDEX; + if( sqlite3AuthCheck(pParse, code, pIndex->zName, pTab->zName, zDb) ){ + goto exit_drop_index; + } + } +#endif + + /* Generate code to remove the index and from the master table */ + v = sqlite3GetVdbe(pParse); + if( v ){ + sqlite3NestedParse(pParse, + "DELETE FROM %Q.%s WHERE name=%Q", + db->aDb[iDb].zName, SCHEMA_TABLE(iDb), + pIndex->zName + ); + sqlite3ChangeCookie(db, v, iDb); + destroyRootPage(pParse, pIndex->tnum, iDb); + sqlite3VdbeOp3(v, OP_DropIndex, iDb, 0, pIndex->zName, 0); + } + +exit_drop_index: + sqlite3SrcListDelete(pName); +} + +/* +** pArray is a pointer to an array of objects. Each object in the +** array is szEntry bytes in size. This routine allocates a new +** object on the end of the array. +** +** *pnEntry is the number of entries already in use. *pnAlloc is +** the previously allocated size of the array. initSize is the +** suggested initial array size allocation. +** +** The index of the new entry is returned in *pIdx. +** +** This routine returns a pointer to the array of objects. This +** might be the same as the pArray parameter or it might be a different +** pointer if the array was resized. +*/ +void *sqlite3ArrayAllocate( + void *pArray, /* Array of objects. Might be reallocated */ + int szEntry, /* Size of each object in the array */ + int initSize, /* Suggested initial allocation, in elements */ + int *pnEntry, /* Number of objects currently in use */ + int *pnAlloc, /* Current size of the allocation, in elements */ + int *pIdx /* Write the index of a new slot here */ +){ + char *z; + if( *pnEntry >= *pnAlloc ){ + void *pNew; + int newSize; + newSize = (*pnAlloc)*2 + initSize; + pNew = sqliteRealloc(pArray, newSize*szEntry); + if( pNew==0 ){ + *pIdx = -1; + return pArray; + } + *pnAlloc = newSize; + pArray = pNew; + } + z = (char*)pArray; + memset(&z[*pnEntry * szEntry], 0, szEntry); + *pIdx = *pnEntry; + ++*pnEntry; + return pArray; +} + +/* +** Append a new element to the given IdList. Create a new IdList if +** need be. +** +** A new IdList is returned, or NULL if malloc() fails. +*/ +IdList *sqlite3IdListAppend(IdList *pList, Token *pToken){ + int i; + if( pList==0 ){ + pList = sqliteMalloc( sizeof(IdList) ); + if( pList==0 ) return 0; + pList->nAlloc = 0; + } + pList->a = sqlite3ArrayAllocate( + pList->a, + sizeof(pList->a[0]), + 5, + &pList->nId, + &pList->nAlloc, + &i + ); + if( i<0 ){ + sqlite3IdListDelete(pList); + return 0; + } + pList->a[i].zName = sqlite3NameFromToken(pToken); + return pList; +} + +/* +** Delete an IdList. +*/ +void sqlite3IdListDelete(IdList *pList){ + int i; + if( pList==0 ) return; + for(i=0; inId; i++){ + sqliteFree(pList->a[i].zName); + } + sqliteFree(pList->a); + sqliteFree(pList); +} + +/* +** Return the index in pList of the identifier named zId. Return -1 +** if not found. +*/ +int sqlite3IdListIndex(IdList *pList, const char *zName){ + int i; + if( pList==0 ) return -1; + for(i=0; inId; i++){ + if( sqlite3StrICmp(pList->a[i].zName, zName)==0 ) return i; + } + return -1; +} + +/* +** Append a new table name to the given SrcList. Create a new SrcList if +** need be. A new entry is created in the SrcList even if pToken is NULL. +** +** A new SrcList is returned, or NULL if malloc() fails. +** +** If pDatabase is not null, it means that the table has an optional +** database name prefix. Like this: "database.table". The pDatabase +** points to the table name and the pTable points to the database name. +** The SrcList.a[].zName field is filled with the table name which might +** come from pTable (if pDatabase is NULL) or from pDatabase. +** SrcList.a[].zDatabase is filled with the database name from pTable, +** or with NULL if no database is specified. +** +** In other words, if call like this: +** +** sqlite3SrcListAppend(A,B,0); +** +** Then B is a table name and the database name is unspecified. If called +** like this: +** +** sqlite3SrcListAppend(A,B,C); +** +** Then C is the table name and B is the database name. +*/ +SrcList *sqlite3SrcListAppend(SrcList *pList, Token *pTable, Token *pDatabase){ + struct SrcList_item *pItem; + if( pList==0 ){ + pList = sqliteMalloc( sizeof(SrcList) ); + if( pList==0 ) return 0; + pList->nAlloc = 1; + } + if( pList->nSrc>=pList->nAlloc ){ + SrcList *pNew; + pList->nAlloc *= 2; + pNew = sqliteRealloc(pList, + sizeof(*pList) + (pList->nAlloc-1)*sizeof(pList->a[0]) ); + if( pNew==0 ){ + sqlite3SrcListDelete(pList); + return 0; + } + pList = pNew; + } + pItem = &pList->a[pList->nSrc]; + memset(pItem, 0, sizeof(pList->a[0])); + if( pDatabase && pDatabase->z==0 ){ + pDatabase = 0; + } + if( pDatabase && pTable ){ + Token *pTemp = pDatabase; + pDatabase = pTable; + pTable = pTemp; + } + pItem->zName = sqlite3NameFromToken(pTable); + pItem->zDatabase = sqlite3NameFromToken(pDatabase); + pItem->iCursor = -1; + pItem->isPopulated = 0; + pList->nSrc++; + return pList; +} + +/* +** Assign cursors to all tables in a SrcList +*/ +void sqlite3SrcListAssignCursors(Parse *pParse, SrcList *pList){ + int i; + struct SrcList_item *pItem; + assert(pList || sqlite3MallocFailed() ); + if( pList ){ + for(i=0, pItem=pList->a; inSrc; i++, pItem++){ + if( pItem->iCursor>=0 ) break; + pItem->iCursor = pParse->nTab++; + if( pItem->pSelect ){ + sqlite3SrcListAssignCursors(pParse, pItem->pSelect->pSrc); + } + } + } +} + +/* +** Delete an entire SrcList including all its substructure. +*/ +void sqlite3SrcListDelete(SrcList *pList){ + int i; + struct SrcList_item *pItem; + if( pList==0 ) return; + for(pItem=pList->a, i=0; inSrc; i++, pItem++){ + sqliteFree(pItem->zDatabase); + sqliteFree(pItem->zName); + sqliteFree(pItem->zAlias); + sqlite3DeleteTable(pItem->pTab); + sqlite3SelectDelete(pItem->pSelect); + sqlite3ExprDelete(pItem->pOn); + sqlite3IdListDelete(pItem->pUsing); + } + sqliteFree(pList); +} + +/* +** This routine is called by the parser to add a new term to the +** end of a growing FROM clause. The "p" parameter is the part of +** the FROM clause that has already been constructed. "p" is NULL +** if this is the first term of the FROM clause. pTable and pDatabase +** are the name of the table and database named in the FROM clause term. +** pDatabase is NULL if the database name qualifier is missing - the +** usual case. If the term has a alias, then pAlias points to the +** alias token. If the term is a subquery, then pSubquery is the +** SELECT statement that the subquery encodes. The pTable and +** pDatabase parameters are NULL for subqueries. The pOn and pUsing +** parameters are the content of the ON and USING clauses. +** +** Return a new SrcList which encodes is the FROM with the new +** term added. +*/ +SrcList *sqlite3SrcListAppendFromTerm( + SrcList *p, /* The left part of the FROM clause already seen */ + Token *pTable, /* Name of the table to add to the FROM clause */ + Token *pDatabase, /* Name of the database containing pTable */ + Token *pAlias, /* The right-hand side of the AS subexpression */ + Select *pSubquery, /* A subquery used in place of a table name */ + Expr *pOn, /* The ON clause of a join */ + IdList *pUsing /* The USING clause of a join */ +){ + struct SrcList_item *pItem; + p = sqlite3SrcListAppend(p, pTable, pDatabase); + if( p==0 || p->nSrc==0 ){ + sqlite3ExprDelete(pOn); + sqlite3IdListDelete(pUsing); + sqlite3SelectDelete(pSubquery); + return p; + } + pItem = &p->a[p->nSrc-1]; + if( pAlias && pAlias->n ){ + pItem->zAlias = sqlite3NameFromToken(pAlias); + } + pItem->pSelect = pSubquery; + pItem->pOn = pOn; + pItem->pUsing = pUsing; + return p; +} + +/* +** When building up a FROM clause in the parser, the join operator +** is initially attached to the left operand. But the code generator +** expects the join operator to be on the right operand. This routine +** Shifts all join operators from left to right for an entire FROM +** clause. +** +** Example: Suppose the join is like this: +** +** A natural cross join B +** +** The operator is "natural cross join". The A and B operands are stored +** in p->a[0] and p->a[1], respectively. The parser initially stores the +** operator with A. This routine shifts that operator over to B. +*/ +void sqlite3SrcListShiftJoinType(SrcList *p){ + if( p && p->a ){ + int i; + for(i=p->nSrc-1; i>0; i--){ + p->a[i].jointype = p->a[i-1].jointype; + } + p->a[0].jointype = 0; + } +} + +/* +** Begin a transaction +*/ +void sqlite3BeginTransaction(Parse *pParse, int type){ + sqlite3 *db; + Vdbe *v; + int i; + + if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; + if( pParse->nErr || sqlite3MallocFailed() ) return; + if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ) return; + + v = sqlite3GetVdbe(pParse); + if( !v ) return; + if( type!=TK_DEFERRED ){ + for(i=0; inDb; i++){ + sqlite3VdbeAddOp(v, OP_Transaction, i, (type==TK_EXCLUSIVE)+1); + } + } + sqlite3VdbeAddOp(v, OP_AutoCommit, 0, 0); +} + +/* +** Commit a transaction +*/ +void sqlite3CommitTransaction(Parse *pParse){ + sqlite3 *db; + Vdbe *v; + + if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; + if( pParse->nErr || sqlite3MallocFailed() ) return; + if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ) return; + + v = sqlite3GetVdbe(pParse); + if( v ){ + sqlite3VdbeAddOp(v, OP_AutoCommit, 1, 0); + } +} + +/* +** Rollback a transaction +*/ +void sqlite3RollbackTransaction(Parse *pParse){ + sqlite3 *db; + Vdbe *v; + + if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; + if( pParse->nErr || sqlite3MallocFailed() ) return; + if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0, 0) ) return; + + v = sqlite3GetVdbe(pParse); + if( v ){ + sqlite3VdbeAddOp(v, OP_AutoCommit, 1, 1); + } +} + +/* +** Make sure the TEMP database is open and available for use. Return +** the number of errors. Leave any error messages in the pParse structure. +*/ +int sqlite3OpenTempDatabase(Parse *pParse){ + sqlite3 *db = pParse->db; + if( db->aDb[1].pBt==0 && !pParse->explain ){ + int rc = sqlite3BtreeFactory(db, 0, 0, SQLITE_DEFAULT_CACHE_SIZE, + &db->aDb[1].pBt); + if( rc!=SQLITE_OK ){ + sqlite3ErrorMsg(pParse, "unable to open a temporary database " + "file for storing temporary tables"); + pParse->rc = rc; + return 1; + } + if( db->flags & !db->autoCommit ){ + rc = sqlite3BtreeBeginTrans(db->aDb[1].pBt, 1); + if( rc!=SQLITE_OK ){ + sqlite3ErrorMsg(pParse, "unable to get a write lock on " + "the temporary database file"); + pParse->rc = rc; + return 1; + } + } + assert( db->aDb[1].pSchema ); + } + return 0; +} + +/* +** Generate VDBE code that will verify the schema cookie and start +** a read-transaction for all named database files. +** +** It is important that all schema cookies be verified and all +** read transactions be started before anything else happens in +** the VDBE program. But this routine can be called after much other +** code has been generated. So here is what we do: +** +** The first time this routine is called, we code an OP_Goto that +** will jump to a subroutine at the end of the program. Then we +** record every database that needs its schema verified in the +** pParse->cookieMask field. Later, after all other code has been +** generated, the subroutine that does the cookie verifications and +** starts the transactions will be coded and the OP_Goto P2 value +** will be made to point to that subroutine. The generation of the +** cookie verification subroutine code happens in sqlite3FinishCoding(). +** +** If iDb<0 then code the OP_Goto only - don't set flag to verify the +** schema on any databases. This can be used to position the OP_Goto +** early in the code, before we know if any database tables will be used. +*/ +void sqlite3CodeVerifySchema(Parse *pParse, int iDb){ + sqlite3 *db; + Vdbe *v; + int mask; + + v = sqlite3GetVdbe(pParse); + if( v==0 ) return; /* This only happens if there was a prior error */ + db = pParse->db; + if( pParse->cookieGoto==0 ){ + pParse->cookieGoto = sqlite3VdbeAddOp(v, OP_Goto, 0, 0)+1; + } + if( iDb>=0 ){ + assert( iDbnDb ); + assert( db->aDb[iDb].pBt!=0 || iDb==1 ); + assert( iDbcookieMask & mask)==0 ){ + pParse->cookieMask |= mask; + pParse->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie; + if( !OMIT_TEMPDB && iDb==1 ){ + sqlite3OpenTempDatabase(pParse); + } + } + } +} + +/* +** Generate VDBE code that prepares for doing an operation that +** might change the database. +** +** This routine starts a new transaction if we are not already within +** a transaction. If we are already within a transaction, then a checkpoint +** is set if the setStatement parameter is true. A checkpoint should +** be set for operations that might fail (due to a constraint) part of +** the way through and which will need to undo some writes without having to +** rollback the whole transaction. For operations where all constraints +** can be checked before any changes are made to the database, it is never +** necessary to undo a write and the checkpoint should not be set. +** +** Only database iDb and the temp database are made writable by this call. +** If iDb==0, then the main and temp databases are made writable. If +** iDb==1 then only the temp database is made writable. If iDb>1 then the +** specified auxiliary database and the temp database are made writable. +*/ +void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){ + Vdbe *v = sqlite3GetVdbe(pParse); + if( v==0 ) return; + sqlite3CodeVerifySchema(pParse, iDb); + pParse->writeMask |= 1<nested==0 ){ + sqlite3VdbeAddOp(v, OP_Statement, iDb, 0); + } + if( (OMIT_TEMPDB || iDb!=1) && pParse->db->aDb[1].pBt!=0 ){ + sqlite3BeginWriteOperation(pParse, setStatement, 1); + } +} + +/* +** Check to see if pIndex uses the collating sequence pColl. Return +** true if it does and false if it does not. +*/ +#ifndef SQLITE_OMIT_REINDEX +static int collationMatch(const char *zColl, Index *pIndex){ + int i; + for(i=0; inColumn; i++){ + const char *z = pIndex->azColl[i]; + if( z==zColl || (z && zColl && 0==sqlite3StrICmp(z, zColl)) ){ + return 1; + } + } + return 0; +} +#endif + +/* +** Recompute all indices of pTab that use the collating sequence pColl. +** If pColl==0 then recompute all indices of pTab. +*/ +#ifndef SQLITE_OMIT_REINDEX +static void reindexTable(Parse *pParse, Table *pTab, char const *zColl){ + Index *pIndex; /* An index associated with pTab */ + + for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){ + if( zColl==0 || collationMatch(zColl, pIndex) ){ + int iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + sqlite3BeginWriteOperation(pParse, 0, iDb); + sqlite3RefillIndex(pParse, pIndex, -1); + } + } +} +#endif + +/* +** Recompute all indices of all tables in all databases where the +** indices use the collating sequence pColl. If pColl==0 then recompute +** all indices everywhere. +*/ +#ifndef SQLITE_OMIT_REINDEX +static void reindexDatabases(Parse *pParse, char const *zColl){ + Db *pDb; /* A single database */ + int iDb; /* The database index number */ + sqlite3 *db = pParse->db; /* The database connection */ + HashElem *k; /* For looping over tables in pDb */ + Table *pTab; /* A table in the database */ + + for(iDb=0, pDb=db->aDb; iDbnDb; iDb++, pDb++){ + assert( pDb!=0 ); + for(k=sqliteHashFirst(&pDb->pSchema->tblHash); k; k=sqliteHashNext(k)){ + pTab = (Table*)sqliteHashData(k); + reindexTable(pParse, pTab, zColl); + } + } +} +#endif + +/* +** Generate code for the REINDEX command. +** +** REINDEX -- 1 +** REINDEX -- 2 +** REINDEX ?.? -- 3 +** REINDEX ?.? -- 4 +** +** Form 1 causes all indices in all attached databases to be rebuilt. +** Form 2 rebuilds all indices in all databases that use the named +** collating function. Forms 3 and 4 rebuild the named index or all +** indices associated with the named table. +*/ +#ifndef SQLITE_OMIT_REINDEX +void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){ + CollSeq *pColl; /* Collating sequence to be reindexed, or NULL */ + char *z; /* Name of a table or index */ + const char *zDb; /* Name of the database */ + Table *pTab; /* A table in the database */ + Index *pIndex; /* An index associated with pTab */ + int iDb; /* The database index number */ + sqlite3 *db = pParse->db; /* The database connection */ + Token *pObjName; /* Name of the table or index to be reindexed */ + + /* 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 || pName1->z==0 ){ + reindexDatabases(pParse, 0); + return; + }else if( pName2==0 || pName2->z==0 ){ + assert( pName1->z ); + pColl = sqlite3FindCollSeq(db, ENC(db), (char*)pName1->z, pName1->n, 0); + if( pColl ){ + char *zColl = sqliteStrNDup((const char *)pName1->z, pName1->n); + if( zColl ){ + reindexDatabases(pParse, zColl); + sqliteFree(zColl); + } + return; + } + } + iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pObjName); + if( iDb<0 ) return; + z = sqlite3NameFromToken(pObjName); + if( z==0 ) return; + zDb = db->aDb[iDb].zName; + pTab = sqlite3FindTable(db, z, zDb); + if( pTab ){ + reindexTable(pParse, pTab, 0); + sqliteFree(z); + return; + } + pIndex = sqlite3FindIndex(db, z, zDb); + sqliteFree(z); + if( pIndex ){ + sqlite3BeginWriteOperation(pParse, 0, iDb); + sqlite3RefillIndex(pParse, pIndex, -1); + return; + } + sqlite3ErrorMsg(pParse, "unable to identify the object to be reindexed"); +} +#endif + +/* +** Return a dynamicly allocated KeyInfo structure that can be used +** with OP_OpenRead or OP_OpenWrite to access database index pIdx. +** +** If successful, a pointer to the new structure is returned. In this case +** the caller is responsible for calling sqliteFree() on the returned +** pointer. If an error occurs (out of memory or missing collation +** sequence), NULL is returned and the state of pParse updated to reflect +** the error. +*/ +KeyInfo *sqlite3IndexKeyinfo(Parse *pParse, Index *pIdx){ + int i; + int nCol = pIdx->nColumn; + int nBytes = sizeof(KeyInfo) + (nCol-1)*sizeof(CollSeq*) + nCol; + KeyInfo *pKey = (KeyInfo *)sqliteMalloc(nBytes); + + if( pKey ){ + pKey->aSortOrder = (u8 *)&(pKey->aColl[nCol]); + assert( &pKey->aSortOrder[nCol]==&(((u8 *)pKey)[nBytes]) ); + for(i=0; iazColl[i]; + assert( zColl ); + pKey->aColl[i] = sqlite3LocateCollSeq(pParse, zColl, -1); + pKey->aSortOrder[i] = pIdx->aSortOrder[i]; + } + pKey->nField = nCol; + } + + if( pParse->nErr ){ + sqliteFree(pKey); + pKey = 0; + } + return pKey; +} diff --git a/extensions/sqlite/sqlite-source/callback.c b/extensions/sqlite/sqlite-source/callback.c new file mode 100644 index 00000000..33797932 --- /dev/null +++ b/extensions/sqlite/sqlite-source/callback.c @@ -0,0 +1,374 @@ +/* +** 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$ +*/ + +#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)); + pColl->xDel = 0; /* Do not copy the destructor */ + 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(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; +} diff --git a/extensions/sqlite/sqlite-source/complete.c b/extensions/sqlite/sqlite-source/complete.c new file mode 100644 index 00000000..660417b0 --- /dev/null +++ b/extensions/sqlite/sqlite-source/complete.c @@ -0,0 +1,263 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** An tokenizer for SQL +** +** This file contains C code that implements the sqlite3_complete() API. +** This code used to be part of the tokenizer.c source file. But by +** separating it out, the code will be automatically omitted from +** static links that do not use it. +** +** $Id$ +*/ +#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 */ diff --git a/extensions/sqlite/sqlite-source/date.c b/extensions/sqlite/sqlite-source/date.c new file mode 100644 index 00000000..545107a0 --- /dev/null +++ b/extensions/sqlite/sqlite-source/date.c @@ -0,0 +1,1036 @@ +/* +** 2003 October 31 +** +** 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 C functions that implement date and time +** functions for SQLite. +** +** There is only one exported symbol in this file - the function +** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. +** All other code has file scope. +** +** $Id$ +** +** SQLite processes all times and dates as Julian Day numbers. The +** dates and times are stored as the number of days since noon +** in Greenwich on November 24, 4714 B.C. according to the Gregorian +** calendar system. +** +** 1970-01-01 00:00:00 is JD 2440587.5 +** 2000-01-01 00:00:00 is JD 2451544.5 +** +** This implemention requires years to be expressed as a 4-digit number +** which means that only dates between 0000-01-01 and 9999-12-31 can +** be represented, even though julian day numbers allow a much wider +** range of dates. +** +** The Gregorian calendar system is used for all dates and times, +** even those that predate the Gregorian calendar. Historians usually +** use the Julian calendar for dates prior to 1582-10-15 and for some +** dates afterwards, depending on locale. Beware of this difference. +** +** The conversion algorithms are implemented based on descriptions +** in the following text: +** +** Jean Meeus +** Astronomical Algorithms, 2nd Edition, 1998 +** ISBM 0-943396-61-1 +** Willmann-Bell, Inc +** Richmond, Virginia (USA) +*/ +#include "sqliteInt.h" +#include "os.h" +#include +#include +#include +#include + +#ifndef SQLITE_OMIT_DATETIME_FUNCS + +/* +** A structure for holding a single date and time. +*/ +typedef struct DateTime DateTime; +struct DateTime { + double rJD; /* The julian day number */ + int Y, M, D; /* Year, month, and day */ + int h, m; /* Hour and minutes */ + int tz; /* Timezone offset in minutes */ + double s; /* Seconds */ + char validYMD; /* True if Y,M,D are valid */ + char validHMS; /* True if h,m,s are valid */ + char validJD; /* True if rJD is valid */ + char validTZ; /* True if tz is valid */ +}; + + +/* +** Convert zDate into one or more integers. Additional arguments +** come in groups of 5 as follows: +** +** N number of digits in the integer +** min minimum allowed value of the integer +** max maximum allowed value of the integer +** nextC first character after the integer +** pVal where to write the integers value. +** +** Conversions continue until one with nextC==0 is encountered. +** The function returns the number of successful conversions. +*/ +static int getDigits(const char *zDate, ...){ + va_list ap; + int val; + int N; + int min; + int max; + int nextC; + int *pVal; + int cnt = 0; + va_start(ap, zDate); + do{ + N = va_arg(ap, int); + min = va_arg(ap, int); + max = va_arg(ap, int); + nextC = va_arg(ap, int); + pVal = va_arg(ap, int*); + val = 0; + while( N-- ){ + if( !isdigit(*(u8*)zDate) ){ + goto end_getDigits; + } + val = val*10 + *zDate - '0'; + zDate++; + } + if( valmax || (nextC!=0 && nextC!=*zDate) ){ + goto end_getDigits; + } + *pVal = val; + zDate++; + cnt++; + }while( nextC ); +end_getDigits: + va_end(ap); + return cnt; +} + +/* +** Read text from z[] and convert into a floating point number. Return +** the number of digits converted. +*/ +#define getValue sqlite3AtoF + +/* +** Parse a timezone extension on the end of a date-time. +** The extension is of the form: +** +** (+/-)HH:MM +** +** If the parse is successful, write the number of minutes +** of change in *pnMin and return 0. If a parser error occurs, +** return 0. +** +** A missing specifier is not considered an error. +*/ +static int parseTimezone(const char *zDate, DateTime *p){ + int sgn = 0; + int nHr, nMn; + while( isspace(*(u8*)zDate) ){ zDate++; } + p->tz = 0; + if( *zDate=='-' ){ + sgn = -1; + }else if( *zDate=='+' ){ + sgn = +1; + }else{ + return *zDate!=0; + } + zDate++; + if( getDigits(zDate, 2, 0, 14, ':', &nHr, 2, 0, 59, 0, &nMn)!=2 ){ + return 1; + } + zDate += 5; + p->tz = sgn*(nMn + nHr*60); + while( isspace(*(u8*)zDate) ){ zDate++; } + return *zDate!=0; +} + +/* +** Parse times of the form HH:MM or HH:MM:SS or HH:MM:SS.FFFF. +** The HH, MM, and SS must each be exactly 2 digits. The +** fractional seconds FFFF can be one or more digits. +** +** Return 1 if there is a parsing error and 0 on success. +*/ +static int parseHhMmSs(const char *zDate, DateTime *p){ + int h, m, s; + double ms = 0.0; + if( getDigits(zDate, 2, 0, 24, ':', &h, 2, 0, 59, 0, &m)!=2 ){ + return 1; + } + zDate += 5; + if( *zDate==':' ){ + zDate++; + if( getDigits(zDate, 2, 0, 59, 0, &s)!=1 ){ + return 1; + } + zDate += 2; + if( *zDate=='.' && isdigit((u8)zDate[1]) ){ + double rScale = 1.0; + zDate++; + while( isdigit(*(u8*)zDate) ){ + ms = ms*10.0 + *zDate - '0'; + rScale *= 10.0; + zDate++; + } + ms /= rScale; + } + }else{ + s = 0; + } + p->validJD = 0; + p->validHMS = 1; + p->h = h; + p->m = m; + p->s = s + ms; + if( parseTimezone(zDate, p) ) return 1; + p->validTZ = p->tz!=0; + return 0; +} + +/* +** Convert from YYYY-MM-DD HH:MM:SS to julian day. We always assume +** that the YYYY-MM-DD is according to the Gregorian calendar. +** +** Reference: Meeus page 61 +*/ +static void computeJD(DateTime *p){ + int Y, M, D, A, B, X1, X2; + + if( p->validJD ) return; + if( p->validYMD ){ + Y = p->Y; + M = p->M; + D = p->D; + }else{ + Y = 2000; /* If no YMD specified, assume 2000-Jan-01 */ + M = 1; + D = 1; + } + if( M<=2 ){ + Y--; + M += 12; + } + A = Y/100; + B = 2 - A + (A/4); + X1 = 365.25*(Y+4716); + X2 = 30.6001*(M+1); + p->rJD = X1 + X2 + D + B - 1524.5; + p->validJD = 1; + if( p->validHMS ){ + p->rJD += (p->h*3600.0 + p->m*60.0 + p->s)/86400.0; + if( p->validTZ ){ + p->rJD -= p->tz*60/86400.0; + p->validYMD = 0; + p->validHMS = 0; + p->validTZ = 0; + } + } +} + +/* +** Parse dates of the form +** +** YYYY-MM-DD HH:MM:SS.FFF +** YYYY-MM-DD HH:MM:SS +** YYYY-MM-DD HH:MM +** YYYY-MM-DD +** +** Write the result into the DateTime structure and return 0 +** on success and 1 if the input string is not a well-formed +** date. +*/ +static int parseYyyyMmDd(const char *zDate, DateTime *p){ + int Y, M, D, neg; + + if( zDate[0]=='-' ){ + zDate++; + neg = 1; + }else{ + neg = 0; + } + if( getDigits(zDate,4,0,9999,'-',&Y,2,1,12,'-',&M,2,1,31,0,&D)!=3 ){ + return 1; + } + zDate += 10; + while( isspace(*(u8*)zDate) || 'T'==*(u8*)zDate ){ zDate++; } + if( parseHhMmSs(zDate, p)==0 ){ + /* We got the time */ + }else if( *zDate==0 ){ + p->validHMS = 0; + }else{ + return 1; + } + p->validJD = 0; + p->validYMD = 1; + p->Y = neg ? -Y : Y; + p->M = M; + p->D = D; + if( p->validTZ ){ + computeJD(p); + } + return 0; +} + +/* +** Attempt to parse the given string into a Julian Day Number. Return +** the number of errors. +** +** The following are acceptable forms for the input string: +** +** YYYY-MM-DD HH:MM:SS.FFF +/-HH:MM +** DDDD.DD +** now +** +** In the first form, the +/-HH:MM is always optional. The fractional +** seconds extension (the ".FFF") is optional. The seconds portion +** (":SS.FFF") is option. The year and date can be omitted as long +** as there is a time string. The time string can be omitted as long +** as there is a year and date. +*/ +static int parseDateOrTime(const char *zDate, DateTime *p){ + memset(p, 0, sizeof(*p)); + if( parseYyyyMmDd(zDate,p)==0 ){ + return 0; + }else if( parseHhMmSs(zDate, p)==0 ){ + return 0; + }else if( sqlite3StrICmp(zDate,"now")==0){ + double r; + sqlite3OsCurrentTime(&r); + p->rJD = r; + p->validJD = 1; + return 0; + }else if( sqlite3IsNumber(zDate, 0, SQLITE_UTF8) ){ + getValue(zDate, &p->rJD); + p->validJD = 1; + return 0; + } + return 1; +} + +/* +** Compute the Year, Month, and Day from the julian day number. +*/ +static void computeYMD(DateTime *p){ + int Z, A, B, C, D, E, X1; + if( p->validYMD ) return; + if( !p->validJD ){ + p->Y = 2000; + p->M = 1; + p->D = 1; + }else{ + Z = p->rJD + 0.5; + A = (Z - 1867216.25)/36524.25; + A = Z + 1 + A - (A/4); + B = A + 1524; + C = (B - 122.1)/365.25; + D = 365.25*C; + E = (B-D)/30.6001; + X1 = 30.6001*E; + p->D = B - D - X1; + p->M = E<14 ? E-1 : E-13; + p->Y = p->M>2 ? C - 4716 : C - 4715; + } + p->validYMD = 1; +} + +/* +** Compute the Hour, Minute, and Seconds from the julian day number. +*/ +static void computeHMS(DateTime *p){ + int Z, s; + if( p->validHMS ) return; + computeJD(p); + Z = p->rJD + 0.5; + s = (p->rJD + 0.5 - Z)*86400000.0 + 0.5; + p->s = 0.001*s; + s = p->s; + p->s -= s; + p->h = s/3600; + s -= p->h*3600; + p->m = s/60; + p->s += s - p->m*60; + p->validHMS = 1; +} + +/* +** Compute both YMD and HMS +*/ +static void computeYMD_HMS(DateTime *p){ + computeYMD(p); + computeHMS(p); +} + +/* +** Clear the YMD and HMS and the TZ +*/ +static void clearYMD_HMS_TZ(DateTime *p){ + p->validYMD = 0; + p->validHMS = 0; + p->validTZ = 0; +} + +/* +** Compute the difference (in days) between localtime and UTC (a.k.a. GMT) +** for the time value p where p is in UTC. +*/ +static double localtimeOffset(DateTime *p){ + DateTime x, y; + time_t t; + x = *p; + computeYMD_HMS(&x); + if( x.Y<1971 || x.Y>=2038 ){ + x.Y = 2000; + x.M = 1; + x.D = 1; + x.h = 0; + x.m = 0; + x.s = 0.0; + } else { + int s = x.s + 0.5; + x.s = s; + } + x.tz = 0; + x.validJD = 0; + computeJD(&x); + t = (x.rJD-2440587.5)*86400.0 + 0.5; +#ifdef HAVE_LOCALTIME_R + { + struct tm sLocal; + localtime_r(&t, &sLocal); + y.Y = sLocal.tm_year + 1900; + y.M = sLocal.tm_mon + 1; + y.D = sLocal.tm_mday; + y.h = sLocal.tm_hour; + y.m = sLocal.tm_min; + y.s = sLocal.tm_sec; + } +#else + { + struct tm *pTm; + sqlite3OsEnterMutex(); + pTm = localtime(&t); + y.Y = pTm->tm_year + 1900; + y.M = pTm->tm_mon + 1; + y.D = pTm->tm_mday; + y.h = pTm->tm_hour; + y.m = pTm->tm_min; + y.s = pTm->tm_sec; + sqlite3OsLeaveMutex(); + } +#endif + y.validYMD = 1; + y.validHMS = 1; + y.validJD = 0; + y.validTZ = 0; + computeJD(&y); + return y.rJD - x.rJD; +} + +/* +** Process a modifier to a date-time stamp. The modifiers are +** as follows: +** +** NNN days +** NNN hours +** NNN minutes +** NNN.NNNN seconds +** NNN months +** NNN years +** start of month +** start of year +** start of week +** start of day +** weekday N +** unixepoch +** localtime +** utc +** +** Return 0 on success and 1 if there is any kind of error. +*/ +static int parseModifier(const char *zMod, DateTime *p){ + int rc = 1; + int n; + double r; + char *z, zBuf[30]; + z = zBuf; + for(n=0; nrJD += localtimeOffset(p); + clearYMD_HMS_TZ(p); + rc = 0; + } + break; + } + case 'u': { + /* + ** unixepoch + ** + ** Treat the current value of p->rJD as the number of + ** seconds since 1970. Convert to a real julian day number. + */ + if( strcmp(z, "unixepoch")==0 && p->validJD ){ + p->rJD = p->rJD/86400.0 + 2440587.5; + clearYMD_HMS_TZ(p); + rc = 0; + }else if( strcmp(z, "utc")==0 ){ + double c1; + computeJD(p); + c1 = localtimeOffset(p); + p->rJD -= c1; + clearYMD_HMS_TZ(p); + p->rJD += c1 - localtimeOffset(p); + rc = 0; + } + break; + } + case 'w': { + /* + ** weekday N + ** + ** Move the date to the same time on the next occurrence of + ** weekday N where 0==Sunday, 1==Monday, and so forth. If the + ** date is already on the appropriate weekday, this is a no-op. + */ + if( strncmp(z, "weekday ", 8)==0 && getValue(&z[8],&r)>0 + && (n=r)==r && n>=0 && r<7 ){ + int Z; + computeYMD_HMS(p); + p->validTZ = 0; + p->validJD = 0; + computeJD(p); + Z = p->rJD + 1.5; + Z %= 7; + if( Z>n ) Z -= 7; + p->rJD += n - Z; + clearYMD_HMS_TZ(p); + rc = 0; + } + break; + } + case 's': { + /* + ** start of TTTTT + ** + ** Move the date backwards to the beginning of the current day, + ** or month or year. + */ + if( strncmp(z, "start of ", 9)!=0 ) break; + z += 9; + computeYMD(p); + p->validHMS = 1; + p->h = p->m = 0; + p->s = 0.0; + p->validTZ = 0; + p->validJD = 0; + if( strcmp(z,"month")==0 ){ + p->D = 1; + rc = 0; + }else if( strcmp(z,"year")==0 ){ + computeYMD(p); + p->M = 1; + p->D = 1; + rc = 0; + }else if( strcmp(z,"day")==0 ){ + rc = 0; + } + break; + } + case '+': + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + n = getValue(z, &r); + assert( n>=1 ); + if( z[n]==':' ){ + /* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the + ** specified number of hours, minutes, seconds, and fractional seconds + ** to the time. The ".FFF" may be omitted. The ":SS.FFF" may be + ** omitted. + */ + const char *z2 = z; + DateTime tx; + int day; + if( !isdigit(*(u8*)z2) ) z2++; + memset(&tx, 0, sizeof(tx)); + if( parseHhMmSs(z2, &tx) ) break; + computeJD(&tx); + tx.rJD -= 0.5; + day = (int)tx.rJD; + tx.rJD -= day; + if( z[0]=='-' ) tx.rJD = -tx.rJD; + computeJD(p); + clearYMD_HMS_TZ(p); + p->rJD += tx.rJD; + rc = 0; + break; + } + z += n; + while( isspace(*(u8*)z) ) z++; + n = strlen(z); + if( n>10 || n<3 ) break; + if( z[n-1]=='s' ){ z[n-1] = 0; n--; } + computeJD(p); + rc = 0; + if( n==3 && strcmp(z,"day")==0 ){ + p->rJD += r; + }else if( n==4 && strcmp(z,"hour")==0 ){ + p->rJD += r/24.0; + }else if( n==6 && strcmp(z,"minute")==0 ){ + p->rJD += r/(24.0*60.0); + }else if( n==6 && strcmp(z,"second")==0 ){ + p->rJD += r/(24.0*60.0*60.0); + }else if( n==5 && strcmp(z,"month")==0 ){ + int x, y; + computeYMD_HMS(p); + p->M += r; + x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12; + p->Y += x; + p->M -= x*12; + p->validJD = 0; + computeJD(p); + y = r; + if( y!=r ){ + p->rJD += (r - y)*30.0; + } + }else if( n==4 && strcmp(z,"year")==0 ){ + computeYMD_HMS(p); + p->Y += r; + p->validJD = 0; + computeJD(p); + }else{ + rc = 1; + } + clearYMD_HMS_TZ(p); + break; + } + default: { + break; + } + } + return rc; +} + +/* +** Process time function arguments. argv[0] is a date-time stamp. +** argv[1] and following are modifiers. Parse them all and write +** the resulting time into the DateTime structure p. Return 0 +** on success and 1 if there are any errors. +*/ +static int isDate(int argc, sqlite3_value **argv, DateTime *p){ + int i; + const unsigned char *z; + if( argc==0 ) return 1; + if( (z = sqlite3_value_text(argv[0]))==0 || parseDateOrTime((char*)z, p) ){ + return 1; + } + for(i=1; iSQLITE_MAX_LENGTH ){ + sqlite3_result_error_toobig(context); + return; + }else{ + z = sqliteMalloc( n ); + if( z==0 ) return; + } + computeJD(&x); + computeYMD_HMS(&x); + for(i=j=0; zFmt[i]; i++){ + if( zFmt[i]!='%' ){ + z[j++] = zFmt[i]; + }else{ + i++; + switch( zFmt[i] ){ + case 'd': sqlite3_snprintf(3, &z[j],"%02d",x.D); j+=2; break; + case 'f': { + double s = x.s; + if( s>59.999 ) s = 59.999; + sqlite3_snprintf(7, &z[j],"%06.3f", s); + j += strlen(&z[j]); + break; + } + case 'H': sqlite3_snprintf(3, &z[j],"%02d",x.h); j+=2; break; + case 'W': /* Fall thru */ + case 'j': { + int nDay; /* Number of days since 1st day of year */ + DateTime y = x; + y.validJD = 0; + y.M = 1; + y.D = 1; + computeJD(&y); + nDay = x.rJD - y.rJD + 0.5; + if( zFmt[i]=='W' ){ + int wd; /* 0=Monday, 1=Tuesday, ... 6=Sunday */ + wd = ((int)(x.rJD+0.5)) % 7; + sqlite3_snprintf(3, &z[j],"%02d",(nDay+7-wd)/7); + j += 2; + }else{ + sqlite3_snprintf(4, &z[j],"%03d",nDay+1); + j += 3; + } + break; + } + case 'J': { + sqlite3_snprintf(20, &z[j],"%.16g",x.rJD); + j+=strlen(&z[j]); + break; + } + case 'm': sqlite3_snprintf(3, &z[j],"%02d",x.M); j+=2; break; + case 'M': sqlite3_snprintf(3, &z[j],"%02d",x.m); j+=2; break; + case 's': { + sqlite3_snprintf(30,&z[j],"%d", + (int)((x.rJD-2440587.5)*86400.0 + 0.5)); + j += strlen(&z[j]); + break; + } + case 'S': sqlite3_snprintf(3,&z[j],"%02d",(int)x.s); j+=2; break; + case 'w': z[j++] = (((int)(x.rJD+1.5)) % 7) + '0'; break; + case 'Y': sqlite3_snprintf(5,&z[j],"%04d",x.Y); j+=strlen(&z[j]);break; + case '%': z[j++] = '%'; break; + } + } + } + z[j] = 0; + sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT); + if( z!=zBuf ){ + sqliteFree(z); + } +} + +/* +** current_time() +** +** This function returns the same value as time('now'). +*/ +static void ctimeFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + sqlite3_value *pVal = sqlite3ValueNew(); + if( pVal ){ + sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC); + timeFunc(context, 1, &pVal); + sqlite3ValueFree(pVal); + } +} + +/* +** current_date() +** +** This function returns the same value as date('now'). +*/ +static void cdateFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + sqlite3_value *pVal = sqlite3ValueNew(); + if( pVal ){ + sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC); + dateFunc(context, 1, &pVal); + sqlite3ValueFree(pVal); + } +} + +/* +** current_timestamp() +** +** This function returns the same value as datetime('now'). +*/ +static void ctimestampFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + sqlite3_value *pVal = sqlite3ValueNew(); + if( pVal ){ + sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC); + datetimeFunc(context, 1, &pVal); + sqlite3ValueFree(pVal); + } +} +#endif /* !defined(SQLITE_OMIT_DATETIME_FUNCS) */ + +#ifdef SQLITE_OMIT_DATETIME_FUNCS +/* +** If the library is compiled to omit the full-scale date and time +** handling (to get a smaller binary), the following minimal version +** of the functions current_time(), current_date() and current_timestamp() +** are included instead. This is to support column declarations that +** include "DEFAULT CURRENT_TIME" etc. +** +** This function uses the C-library functions time(), gmtime() +** and strftime(). The format string to pass to strftime() is supplied +** as the user-data for the function. +*/ +static void currentTimeFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + time_t t; + char *zFormat = (char *)sqlite3_user_data(context); + char zBuf[20]; + + time(&t); +#ifdef SQLITE_TEST + { + extern int sqlite3_current_time; /* See os_XXX.c */ + if( sqlite3_current_time ){ + t = sqlite3_current_time; + } + } +#endif + +#ifdef HAVE_GMTIME_R + { + struct tm sNow; + gmtime_r(&t, &sNow); + strftime(zBuf, 20, zFormat, &sNow); + } +#else + { + struct tm *pTm; + sqlite3OsEnterMutex(); + pTm = gmtime(&t); + strftime(zBuf, 20, zFormat, pTm); + sqlite3OsLeaveMutex(); + } +#endif + + sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); +} +#endif + +/* +** This function registered all of the above C functions as SQL +** functions. This should be the only routine in this file with +** external linkage. +*/ +void sqlite3RegisterDateTimeFunctions(sqlite3 *db){ +#ifndef SQLITE_OMIT_DATETIME_FUNCS + static const struct { + char *zName; + int nArg; + void (*xFunc)(sqlite3_context*,int,sqlite3_value**); + } aFuncs[] = { + { "julianday", -1, juliandayFunc }, + { "date", -1, dateFunc }, + { "time", -1, timeFunc }, + { "datetime", -1, datetimeFunc }, + { "strftime", -1, strftimeFunc }, + { "current_time", 0, ctimeFunc }, + { "current_timestamp", 0, ctimestampFunc }, + { "current_date", 0, cdateFunc }, + }; + int i; + + for(i=0; izErrMsg 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; inSrc; i++, pItem++){ + pTab = sqlite3LocateTable(pParse, pItem->zName, pItem->zDatabase); + sqlite3DeleteTable(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( iDbnDb ); + 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; jnColumn; 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); +} diff --git a/extensions/sqlite/sqlite-source/expr.c b/extensions/sqlite/sqlite-source/expr.c new file mode 100644 index 00000000..09d9e54a --- /dev/null +++ b/extensions/sqlite/sqlite-source/expr.c @@ -0,0 +1,2581 @@ +/* +** 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 routines used for analyzing expressions and +** for generating VDBE code that evaluates expressions in SQLite. +** +** $Id$ +*/ +#include "sqliteInt.h" +#include + +/* +** Return the 'affinity' of the expression pExpr if any. +** +** If pExpr is a column, a reference to a column via an 'AS' alias, +** or a sub-select with a column as the return value, then the +** affinity of that column is returned. Otherwise, 0x00 is returned, +** indicating no affinity for the expression. +** +** i.e. the WHERE clause expresssions in the following statements all +** have an affinity: +** +** CREATE TABLE t1(a); +** SELECT * FROM t1 WHERE a; +** SELECT a AS b FROM t1 WHERE b; +** SELECT * FROM t1 WHERE (select a from t1); +*/ +char sqlite3ExprAffinity(Expr *pExpr){ + int op = pExpr->op; + if( op==TK_SELECT ){ + return sqlite3ExprAffinity(pExpr->pSelect->pEList->a[0].pExpr); + } +#ifndef SQLITE_OMIT_CAST + if( op==TK_CAST ){ + return sqlite3AffinityType(&pExpr->token); + } +#endif + return pExpr->affinity; +} + +/* +** Set the collating sequence for expression pExpr to be the collating +** sequence named by pToken. Return a pointer to the revised expression. +** The collating sequence is marked as "explicit" using the EP_ExpCollate +** flag. An explicit collating sequence will override implicit +** collating sequences. +*/ +Expr *sqlite3ExprSetColl(Parse *pParse, Expr *pExpr, Token *pName){ + CollSeq *pColl; + if( pExpr==0 ) return 0; + pColl = sqlite3LocateCollSeq(pParse, (char*)pName->z, pName->n); + if( pColl ){ + pExpr->pColl = pColl; + pExpr->flags |= EP_ExpCollate; + } + return pExpr; +} + +/* +** Return the default collation sequence for the expression pExpr. If +** there is no default collation type, return 0. +*/ +CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ + CollSeq *pColl = 0; + if( pExpr ){ + int op; + pColl = pExpr->pColl; + op = pExpr->op; + if( (op==TK_CAST || op==TK_UPLUS) && !pColl ){ + return sqlite3ExprCollSeq(pParse, pExpr->pLeft); + } + } + if( sqlite3CheckCollSeq(pParse, pColl) ){ + pColl = 0; + } + return pColl; +} + +/* +** pExpr is an operand of a comparison operator. aff2 is the +** type affinity of the other operand. This routine returns the +** type affinity that should be used for the comparison operator. +*/ +char sqlite3CompareAffinity(Expr *pExpr, char aff2){ + char aff1 = sqlite3ExprAffinity(pExpr); + if( aff1 && aff2 ){ + /* Both sides of the comparison are columns. If one has numeric + ** affinity, use that. Otherwise use no affinity. + */ + if( sqlite3IsNumericAffinity(aff1) || sqlite3IsNumericAffinity(aff2) ){ + return SQLITE_AFF_NUMERIC; + }else{ + return SQLITE_AFF_NONE; + } + }else if( !aff1 && !aff2 ){ + /* Neither side of the comparison is a column. Compare the + ** results directly. + */ + return SQLITE_AFF_NONE; + }else{ + /* One side is a column, the other is not. Use the columns affinity. */ + assert( aff1==0 || aff2==0 ); + return (aff1 + aff2); + } +} + +/* +** pExpr is a comparison operator. Return the type affinity that should +** be applied to both operands prior to doing the comparison. +*/ +static char comparisonAffinity(Expr *pExpr){ + char aff; + assert( pExpr->op==TK_EQ || pExpr->op==TK_IN || pExpr->op==TK_LT || + pExpr->op==TK_GT || pExpr->op==TK_GE || pExpr->op==TK_LE || + pExpr->op==TK_NE ); + assert( pExpr->pLeft ); + aff = sqlite3ExprAffinity(pExpr->pLeft); + if( pExpr->pRight ){ + aff = sqlite3CompareAffinity(pExpr->pRight, aff); + } + else if( pExpr->pSelect ){ + aff = sqlite3CompareAffinity(pExpr->pSelect->pEList->a[0].pExpr, aff); + } + else if( !aff ){ + aff = SQLITE_AFF_NONE; + } + return aff; +} + +/* +** pExpr is a comparison expression, eg. '=', '<', IN(...) etc. +** idx_affinity is the affinity of an indexed column. Return true +** if the index with affinity idx_affinity may be used to implement +** the comparison in pExpr. +*/ +int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){ + char aff = comparisonAffinity(pExpr); + switch( aff ){ + case SQLITE_AFF_NONE: + return 1; + case SQLITE_AFF_TEXT: + return idx_affinity==SQLITE_AFF_TEXT; + default: + return sqlite3IsNumericAffinity(idx_affinity); + } +} + +/* +** Return the P1 value that should be used for a binary comparison +** opcode (OP_Eq, OP_Ge etc.) used to compare pExpr1 and pExpr2. +** If jumpIfNull is true, then set the low byte of the returned +** P1 value to tell the opcode to jump if either expression +** evaluates to NULL. +*/ +static int binaryCompareP1(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){ + char aff = sqlite3ExprAffinity(pExpr2); + return ((int)sqlite3CompareAffinity(pExpr1, aff))+(jumpIfNull?0x100:0); +} + +/* +** Return a pointer to the collation sequence that should be used by +** a binary comparison operator comparing pLeft and pRight. +** +** If the left hand expression has a collating sequence type, then it is +** used. Otherwise the collation sequence for the right hand expression +** is used, or the default (BINARY) if neither expression has a collating +** type. +** +** Argument pRight (but not pLeft) may be a null pointer. In this case, +** it is not considered. +*/ +CollSeq* sqlite3BinaryCompareCollSeq( + Parse *pParse, + Expr *pLeft, + Expr *pRight +){ + CollSeq *pColl; + assert( pLeft ); + if( pLeft->flags & EP_ExpCollate ){ + assert( pLeft->pColl ); + pColl = pLeft->pColl; + }else if( pRight && pRight->flags & EP_ExpCollate ){ + assert( pRight->pColl ); + pColl = pRight->pColl; + }else{ + pColl = sqlite3ExprCollSeq(pParse, pLeft); + if( !pColl ){ + pColl = sqlite3ExprCollSeq(pParse, pRight); + } + } + return pColl; +} + +/* +** Generate code for a comparison operator. +*/ +static int codeCompare( + Parse *pParse, /* The parsing (and code generating) context */ + Expr *pLeft, /* The left operand */ + Expr *pRight, /* The right operand */ + int opcode, /* The comparison opcode */ + int dest, /* Jump here if true. */ + int jumpIfNull /* If true, jump if either operand is NULL */ +){ + int p1 = binaryCompareP1(pLeft, pRight, jumpIfNull); + CollSeq *p3 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight); + return sqlite3VdbeOp3(pParse->pVdbe, opcode, p1, dest, (void*)p3, P3_COLLSEQ); +} + +/* +** Construct a new expression node and return a pointer to it. Memory +** for this node is obtained from sqliteMalloc(). The calling function +** is responsible for making sure the node eventually gets freed. +*/ +Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, const Token *pToken){ + Expr *pNew; + pNew = sqliteMalloc( sizeof(Expr) ); + if( pNew==0 ){ + /* When malloc fails, delete pLeft and pRight. Expressions passed to + ** this function must always be allocated with sqlite3Expr() for this + ** reason. + */ + sqlite3ExprDelete(pLeft); + sqlite3ExprDelete(pRight); + return 0; + } + pNew->op = op; + pNew->pLeft = pLeft; + pNew->pRight = pRight; + pNew->iAgg = -1; + if( pToken ){ + assert( pToken->dyn==0 ); + pNew->span = pNew->token = *pToken; + }else if( pLeft ){ + if( pRight ){ + sqlite3ExprSpan(pNew, &pLeft->span, &pRight->span); + if( pRight->flags & EP_ExpCollate ){ + pNew->flags |= EP_ExpCollate; + pNew->pColl = pRight->pColl; + } + } + if( pLeft->flags & EP_ExpCollate ){ + pNew->flags |= EP_ExpCollate; + pNew->pColl = pLeft->pColl; + } + } + + sqlite3ExprSetHeight(pNew); + return pNew; +} + +/* +** Works like sqlite3Expr() but frees its pLeft and pRight arguments +** if it fails due to a malloc problem. +*/ +Expr *sqlite3ExprOrFree(int op, Expr *pLeft, Expr *pRight, const Token *pToken){ + Expr *pNew = sqlite3Expr(op, pLeft, pRight, pToken); + if( pNew==0 ){ + sqlite3ExprDelete(pLeft); + sqlite3ExprDelete(pRight); + } + return pNew; +} + +/* +** When doing a nested parse, you can include terms in an expression +** that look like this: #0 #1 #2 ... These terms refer to elements +** on the stack. "#0" means the top of the stack. +** "#1" means the next down on the stack. And so forth. +** +** This routine is called by the parser to deal with on of those terms. +** It immediately generates code to store the value in a memory location. +** The returns an expression that will code to extract the value from +** that memory location as needed. +*/ +Expr *sqlite3RegisterExpr(Parse *pParse, Token *pToken){ + Vdbe *v = pParse->pVdbe; + Expr *p; + int depth; + if( pParse->nested==0 ){ + sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", pToken); + return sqlite3Expr(TK_NULL, 0, 0, 0); + } + if( v==0 ) return 0; + p = sqlite3Expr(TK_REGISTER, 0, 0, pToken); + if( p==0 ){ + return 0; /* Malloc failed */ + } + depth = atoi((char*)&pToken->z[1]); + p->iTable = pParse->nMem++; + sqlite3VdbeAddOp(v, OP_Dup, depth, 0); + sqlite3VdbeAddOp(v, OP_MemStore, p->iTable, 1); + return p; +} + +/* +** Join two expressions using an AND operator. If either expression is +** NULL, then just return the other expression. +*/ +Expr *sqlite3ExprAnd(Expr *pLeft, Expr *pRight){ + if( pLeft==0 ){ + return pRight; + }else if( pRight==0 ){ + return pLeft; + }else{ + return sqlite3Expr(TK_AND, pLeft, pRight, 0); + } +} + +/* +** Set the Expr.span field of the given expression to span all +** text between the two given tokens. +*/ +void sqlite3ExprSpan(Expr *pExpr, Token *pLeft, Token *pRight){ + assert( pRight!=0 ); + assert( pLeft!=0 ); + if( !sqlite3MallocFailed() && pRight->z && pLeft->z ){ + assert( pLeft->dyn==0 || pLeft->z[pLeft->n]==0 ); + if( pLeft->dyn==0 && pRight->dyn==0 ){ + pExpr->span.z = pLeft->z; + pExpr->span.n = pRight->n + (pRight->z - pLeft->z); + }else{ + pExpr->span.z = 0; + } + } +} + +/* +** Construct a new expression node for a function with multiple +** arguments. +*/ +Expr *sqlite3ExprFunction(ExprList *pList, Token *pToken){ + Expr *pNew; + assert( pToken ); + pNew = sqliteMalloc( sizeof(Expr) ); + if( pNew==0 ){ + sqlite3ExprListDelete(pList); /* Avoid leaking memory when malloc fails */ + return 0; + } + pNew->op = TK_FUNCTION; + pNew->pList = pList; + assert( pToken->dyn==0 ); + pNew->token = *pToken; + pNew->span = pNew->token; + + sqlite3ExprSetHeight(pNew); + return pNew; +} + +/* +** Assign a variable number to an expression that encodes a wildcard +** in the original SQL statement. +** +** Wildcards consisting of a single "?" are assigned the next sequential +** variable number. +** +** Wildcards of the form "?nnn" are assigned the number "nnn". We make +** sure "nnn" is not too be to avoid a denial of service attack when +** the SQL statement comes from an external source. +** +** Wildcards of the form ":aaa" or "$aaa" are assigned the same number +** as the previous instance of the same wildcard. Or if this is the first +** instance of the wildcard, the next sequenial variable number is +** assigned. +*/ +void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ + Token *pToken; + if( pExpr==0 ) return; + pToken = &pExpr->token; + assert( pToken->n>=1 ); + assert( pToken->z!=0 ); + assert( pToken->z[0]!=0 ); + if( pToken->n==1 ){ + /* Wildcard of the form "?". Assign the next variable number */ + pExpr->iTable = ++pParse->nVar; + }else if( pToken->z[0]=='?' ){ + /* Wildcard of the form "?nnn". Convert "nnn" to an integer and + ** use it as the variable number */ + int i; + pExpr->iTable = i = atoi((char*)&pToken->z[1]); + if( i<1 || i>SQLITE_MAX_VARIABLE_NUMBER ){ + sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d", + SQLITE_MAX_VARIABLE_NUMBER); + } + if( i>pParse->nVar ){ + pParse->nVar = i; + } + }else{ + /* Wildcards of the form ":aaa" or "$aaa". Reuse the same variable + ** number as the prior appearance of the same name, or if the name + ** has never appeared before, reuse the same variable number + */ + int i, n; + n = pToken->n; + for(i=0; inVarExpr; i++){ + Expr *pE; + if( (pE = pParse->apVarExpr[i])!=0 + && pE->token.n==n + && memcmp(pE->token.z, pToken->z, n)==0 ){ + pExpr->iTable = pE->iTable; + break; + } + } + if( i>=pParse->nVarExpr ){ + pExpr->iTable = ++pParse->nVar; + if( pParse->nVarExpr>=pParse->nVarExprAlloc-1 ){ + pParse->nVarExprAlloc += pParse->nVarExprAlloc + 10; + pParse->apVarExpr = sqliteReallocOrFree(pParse->apVarExpr, + pParse->nVarExprAlloc*sizeof(pParse->apVarExpr[0]) ); + } + if( !sqlite3MallocFailed() ){ + assert( pParse->apVarExpr!=0 ); + pParse->apVarExpr[pParse->nVarExpr++] = pExpr; + } + } + } + if( !pParse->nErr && pParse->nVar>SQLITE_MAX_VARIABLE_NUMBER ){ + sqlite3ErrorMsg(pParse, "too many SQL variables"); + } +} + +/* +** Recursively delete an expression tree. +*/ +void sqlite3ExprDelete(Expr *p){ + if( p==0 ) return; + if( p->span.dyn ) sqliteFree((char*)p->span.z); + if( p->token.dyn ) sqliteFree((char*)p->token.z); + sqlite3ExprDelete(p->pLeft); + sqlite3ExprDelete(p->pRight); + sqlite3ExprListDelete(p->pList); + sqlite3SelectDelete(p->pSelect); + sqliteFree(p); +} + +/* +** The Expr.token field might be a string literal that is quoted. +** If so, remove the quotation marks. +*/ +void sqlite3DequoteExpr(Expr *p){ + if( ExprHasAnyProperty(p, EP_Dequoted) ){ + return; + } + ExprSetProperty(p, EP_Dequoted); + if( p->token.dyn==0 ){ + sqlite3TokenCopy(&p->token, &p->token); + } + sqlite3Dequote((char*)p->token.z); +} + + +/* +** The following group of routines make deep copies of expressions, +** expression lists, ID lists, and select statements. The copies can +** be deleted (by being passed to their respective ...Delete() routines) +** without effecting the originals. +** +** The expression list, ID, and source lists return by sqlite3ExprListDup(), +** sqlite3IdListDup(), and sqlite3SrcListDup() can not be further expanded +** by subsequent calls to sqlite*ListAppend() routines. +** +** Any tables that the SrcList might point to are not duplicated. +*/ +Expr *sqlite3ExprDup(Expr *p){ + Expr *pNew; + if( p==0 ) return 0; + pNew = sqliteMallocRaw( sizeof(*p) ); + if( pNew==0 ) return 0; + memcpy(pNew, p, sizeof(*pNew)); + if( p->token.z!=0 ){ + pNew->token.z = (u8*)sqliteStrNDup((char*)p->token.z, p->token.n); + pNew->token.dyn = 1; + }else{ + assert( pNew->token.z==0 ); + } + pNew->span.z = 0; + pNew->pLeft = sqlite3ExprDup(p->pLeft); + pNew->pRight = sqlite3ExprDup(p->pRight); + pNew->pList = sqlite3ExprListDup(p->pList); + pNew->pSelect = sqlite3SelectDup(p->pSelect); + return pNew; +} +void sqlite3TokenCopy(Token *pTo, Token *pFrom){ + if( pTo->dyn ) sqliteFree((char*)pTo->z); + if( pFrom->z ){ + pTo->n = pFrom->n; + pTo->z = (u8*)sqliteStrNDup((char*)pFrom->z, pFrom->n); + pTo->dyn = 1; + }else{ + pTo->z = 0; + } +} +ExprList *sqlite3ExprListDup(ExprList *p){ + ExprList *pNew; + struct ExprList_item *pItem, *pOldItem; + int i; + if( p==0 ) return 0; + pNew = sqliteMalloc( sizeof(*pNew) ); + if( pNew==0 ) return 0; + pNew->nExpr = pNew->nAlloc = p->nExpr; + pNew->a = pItem = sqliteMalloc( p->nExpr*sizeof(p->a[0]) ); + if( pItem==0 ){ + sqliteFree(pNew); + return 0; + } + pOldItem = p->a; + for(i=0; inExpr; i++, pItem++, pOldItem++){ + Expr *pNewExpr, *pOldExpr; + pItem->pExpr = pNewExpr = sqlite3ExprDup(pOldExpr = pOldItem->pExpr); + if( pOldExpr->span.z!=0 && pNewExpr ){ + /* Always make a copy of the span for top-level expressions in the + ** expression list. The logic in SELECT processing that determines + ** the names of columns in the result set needs this information */ + sqlite3TokenCopy(&pNewExpr->span, &pOldExpr->span); + } + assert( pNewExpr==0 || pNewExpr->span.z!=0 + || pOldExpr->span.z==0 + || sqlite3MallocFailed() ); + pItem->zName = sqliteStrDup(pOldItem->zName); + pItem->sortOrder = pOldItem->sortOrder; + pItem->isAgg = pOldItem->isAgg; + pItem->done = 0; + } + return pNew; +} + +/* +** If cursors, triggers, views and subqueries are all omitted from +** the build, then none of the following routines, except for +** sqlite3SelectDup(), can be called. sqlite3SelectDup() is sometimes +** called with a NULL argument. +*/ +#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) \ + || !defined(SQLITE_OMIT_SUBQUERY) +SrcList *sqlite3SrcListDup(SrcList *p){ + SrcList *pNew; + int i; + int nByte; + if( p==0 ) return 0; + nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0); + pNew = sqliteMallocRaw( nByte ); + if( pNew==0 ) return 0; + pNew->nSrc = pNew->nAlloc = p->nSrc; + for(i=0; inSrc; i++){ + struct SrcList_item *pNewItem = &pNew->a[i]; + struct SrcList_item *pOldItem = &p->a[i]; + Table *pTab; + pNewItem->zDatabase = sqliteStrDup(pOldItem->zDatabase); + pNewItem->zName = sqliteStrDup(pOldItem->zName); + pNewItem->zAlias = sqliteStrDup(pOldItem->zAlias); + pNewItem->jointype = pOldItem->jointype; + pNewItem->iCursor = pOldItem->iCursor; + pNewItem->isPopulated = pOldItem->isPopulated; + pTab = pNewItem->pTab = pOldItem->pTab; + if( pTab ){ + pTab->nRef++; + } + pNewItem->pSelect = sqlite3SelectDup(pOldItem->pSelect); + pNewItem->pOn = sqlite3ExprDup(pOldItem->pOn); + pNewItem->pUsing = sqlite3IdListDup(pOldItem->pUsing); + pNewItem->colUsed = pOldItem->colUsed; + } + return pNew; +} +IdList *sqlite3IdListDup(IdList *p){ + IdList *pNew; + int i; + if( p==0 ) return 0; + pNew = sqliteMallocRaw( sizeof(*pNew) ); + if( pNew==0 ) return 0; + pNew->nId = pNew->nAlloc = p->nId; + pNew->a = sqliteMallocRaw( p->nId*sizeof(p->a[0]) ); + if( pNew->a==0 ){ + sqliteFree(pNew); + return 0; + } + for(i=0; inId; i++){ + struct IdList_item *pNewItem = &pNew->a[i]; + struct IdList_item *pOldItem = &p->a[i]; + pNewItem->zName = sqliteStrDup(pOldItem->zName); + pNewItem->idx = pOldItem->idx; + } + return pNew; +} +Select *sqlite3SelectDup(Select *p){ + Select *pNew; + if( p==0 ) return 0; + pNew = sqliteMallocRaw( sizeof(*p) ); + if( pNew==0 ) return 0; + pNew->isDistinct = p->isDistinct; + pNew->pEList = sqlite3ExprListDup(p->pEList); + pNew->pSrc = sqlite3SrcListDup(p->pSrc); + pNew->pWhere = sqlite3ExprDup(p->pWhere); + pNew->pGroupBy = sqlite3ExprListDup(p->pGroupBy); + pNew->pHaving = sqlite3ExprDup(p->pHaving); + pNew->pOrderBy = sqlite3ExprListDup(p->pOrderBy); + pNew->op = p->op; + pNew->pPrior = sqlite3SelectDup(p->pPrior); + pNew->pLimit = sqlite3ExprDup(p->pLimit); + pNew->pOffset = sqlite3ExprDup(p->pOffset); + pNew->iLimit = -1; + pNew->iOffset = -1; + pNew->isResolved = p->isResolved; + pNew->isAgg = p->isAgg; + pNew->usesEphm = 0; + pNew->disallowOrderBy = 0; + pNew->pRightmost = 0; + pNew->addrOpenEphm[0] = -1; + pNew->addrOpenEphm[1] = -1; + pNew->addrOpenEphm[2] = -1; + return pNew; +} +#else +Select *sqlite3SelectDup(Select *p){ + assert( p==0 ); + return 0; +} +#endif + + +/* +** Add a new element to the end of an expression list. If pList is +** initially NULL, then create a new expression list. +*/ +ExprList *sqlite3ExprListAppend(ExprList *pList, Expr *pExpr, Token *pName){ + if( pList==0 ){ + pList = sqliteMalloc( sizeof(ExprList) ); + if( pList==0 ){ + goto no_mem; + } + assert( pList->nAlloc==0 ); + } + if( pList->nAlloc<=pList->nExpr ){ + struct ExprList_item *a; + int n = pList->nAlloc*2 + 4; + a = sqliteRealloc(pList->a, n*sizeof(pList->a[0])); + if( a==0 ){ + goto no_mem; + } + pList->a = a; + pList->nAlloc = n; + } + assert( pList->a!=0 ); + if( pExpr || pName ){ + struct ExprList_item *pItem = &pList->a[pList->nExpr++]; + memset(pItem, 0, sizeof(*pItem)); + pItem->zName = sqlite3NameFromToken(pName); + pItem->pExpr = pExpr; + } + return pList; + +no_mem: + /* Avoid leaking memory if malloc has failed. */ + sqlite3ExprDelete(pExpr); + sqlite3ExprListDelete(pList); + return 0; +} + +/* +** If the expression list pEList contains more than iLimit elements, +** leave an error message in pParse. +*/ +void sqlite3ExprListCheckLength( + Parse *pParse, + ExprList *pEList, + int iLimit, + const char *zObject +){ + if( pEList && pEList->nExpr>iLimit ){ + sqlite3ErrorMsg(pParse, "too many columns in %s", zObject); + } +} + + +#if SQLITE_MAX_EXPR_DEPTH>0 +/* The following three functions, heightOfExpr(), heightOfExprList() +** and heightOfSelect(), are used to determine the maximum height +** of any expression tree referenced by the structure passed as the +** first argument. +** +** If this maximum height is greater than the current value pointed +** to by pnHeight, the second parameter, then set *pnHeight to that +** value. +*/ +static void heightOfExpr(Expr *p, int *pnHeight){ + if( p ){ + if( p->nHeight>*pnHeight ){ + *pnHeight = p->nHeight; + } + } +} +static void heightOfExprList(ExprList *p, int *pnHeight){ + if( p ){ + int i; + for(i=0; inExpr; i++){ + heightOfExpr(p->a[i].pExpr, pnHeight); + } + } +} +static void heightOfSelect(Select *p, int *pnHeight){ + if( p ){ + heightOfExpr(p->pWhere, pnHeight); + heightOfExpr(p->pHaving, pnHeight); + heightOfExpr(p->pLimit, pnHeight); + heightOfExpr(p->pOffset, pnHeight); + heightOfExprList(p->pEList, pnHeight); + heightOfExprList(p->pGroupBy, pnHeight); + heightOfExprList(p->pOrderBy, pnHeight); + heightOfSelect(p->pPrior, pnHeight); + } +} + +/* +** Set the Expr.nHeight variable in the structure passed as an +** argument. An expression with no children, Expr.pList or +** Expr.pSelect member has a height of 1. Any other expression +** has a height equal to the maximum height of any other +** referenced Expr plus one. +*/ +void sqlite3ExprSetHeight(Expr *p){ + int nHeight = 0; + heightOfExpr(p->pLeft, &nHeight); + heightOfExpr(p->pRight, &nHeight); + heightOfExprList(p->pList, &nHeight); + heightOfSelect(p->pSelect, &nHeight); + p->nHeight = nHeight + 1; +} + +/* +** Return the maximum height of any expression tree referenced +** by the select statement passed as an argument. +*/ +int sqlite3SelectExprHeight(Select *p){ + int nHeight = 0; + heightOfSelect(p, &nHeight); + return nHeight; +} +#endif + +/* +** Delete an entire expression list. +*/ +void sqlite3ExprListDelete(ExprList *pList){ + int i; + struct ExprList_item *pItem; + if( pList==0 ) return; + assert( pList->a!=0 || (pList->nExpr==0 && pList->nAlloc==0) ); + assert( pList->nExpr<=pList->nAlloc ); + for(pItem=pList->a, i=0; inExpr; i++, pItem++){ + sqlite3ExprDelete(pItem->pExpr); + sqliteFree(pItem->zName); + } + sqliteFree(pList->a); + sqliteFree(pList); +} + +/* +** Walk an expression tree. Call xFunc for each node visited. +** +** The return value from xFunc determines whether the tree walk continues. +** 0 means continue walking the tree. 1 means do not walk children +** of the current node but continue with siblings. 2 means abandon +** the tree walk completely. +** +** The return value from this routine is 1 to abandon the tree walk +** and 0 to continue. +** +** NOTICE: This routine does *not* descend into subqueries. +*/ +static int walkExprList(ExprList *, int (*)(void *, Expr*), void *); +static int walkExprTree(Expr *pExpr, int (*xFunc)(void*,Expr*), void *pArg){ + int rc; + if( pExpr==0 ) return 0; + rc = (*xFunc)(pArg, pExpr); + if( rc==0 ){ + if( walkExprTree(pExpr->pLeft, xFunc, pArg) ) return 1; + if( walkExprTree(pExpr->pRight, xFunc, pArg) ) return 1; + if( walkExprList(pExpr->pList, xFunc, pArg) ) return 1; + } + return rc>1; +} + +/* +** Call walkExprTree() for every expression in list p. +*/ +static int walkExprList(ExprList *p, int (*xFunc)(void *, Expr*), void *pArg){ + int i; + struct ExprList_item *pItem; + if( !p ) return 0; + for(i=p->nExpr, pItem=p->a; i>0; i--, pItem++){ + if( walkExprTree(pItem->pExpr, xFunc, pArg) ) return 1; + } + return 0; +} + +/* +** Call walkExprTree() for every expression in Select p, not including +** expressions that are part of sub-selects in any FROM clause or the LIMIT +** or OFFSET expressions.. +*/ +static int walkSelectExpr(Select *p, int (*xFunc)(void *, Expr*), void *pArg){ + walkExprList(p->pEList, xFunc, pArg); + walkExprTree(p->pWhere, xFunc, pArg); + walkExprList(p->pGroupBy, xFunc, pArg); + walkExprTree(p->pHaving, xFunc, pArg); + walkExprList(p->pOrderBy, xFunc, pArg); + if( p->pPrior ){ + walkSelectExpr(p->pPrior, xFunc, pArg); + } + return 0; +} + + +/* +** This routine is designed as an xFunc for walkExprTree(). +** +** pArg is really a pointer to an integer. If we can tell by looking +** at pExpr that the expression that contains pExpr is not a constant +** expression, then set *pArg to 0 and return 2 to abandon the tree walk. +** If pExpr does does not disqualify the expression from being a constant +** then do nothing. +** +** After walking the whole tree, if no nodes are found that disqualify +** the expression as constant, then we assume the whole expression +** is constant. See sqlite3ExprIsConstant() for additional information. +*/ +static int exprNodeIsConstant(void *pArg, Expr *pExpr){ + int *pN = (int*)pArg; + + /* If *pArg is 3 then any term of the expression that comes from + ** the ON or USING clauses of a join disqualifies the expression + ** from being considered constant. */ + if( (*pN)==3 && ExprHasAnyProperty(pExpr, EP_FromJoin) ){ + *pN = 0; + return 2; + } + + switch( pExpr->op ){ + /* Consider functions to be constant if all their arguments are constant + ** and *pArg==2 */ + case TK_FUNCTION: + if( (*pN)==2 ) return 0; + /* Fall through */ + case TK_ID: + case TK_COLUMN: + case TK_DOT: + case TK_AGG_FUNCTION: + case TK_AGG_COLUMN: +#ifndef SQLITE_OMIT_SUBQUERY + case TK_SELECT: + case TK_EXISTS: +#endif + *pN = 0; + return 2; + case TK_IN: + if( pExpr->pSelect ){ + *pN = 0; + return 2; + } + default: + return 0; + } +} + +/* +** Walk an expression tree. Return 1 if the expression is constant +** and 0 if it involves variables or function calls. +** +** For the purposes of this function, a double-quoted string (ex: "abc") +** is considered a variable but a single-quoted string (ex: 'abc') is +** a constant. +*/ +int sqlite3ExprIsConstant(Expr *p){ + int isConst = 1; + walkExprTree(p, exprNodeIsConstant, &isConst); + return isConst; +} + +/* +** Walk an expression tree. Return 1 if the expression is constant +** that does no originate from the ON or USING clauses of a join. +** Return 0 if it involves variables or function calls or terms from +** an ON or USING clause. +*/ +int sqlite3ExprIsConstantNotJoin(Expr *p){ + int isConst = 3; + walkExprTree(p, exprNodeIsConstant, &isConst); + return isConst!=0; +} + +/* +** Walk an expression tree. Return 1 if the expression is constant +** or a function call with constant arguments. Return and 0 if there +** are any variables. +** +** For the purposes of this function, a double-quoted string (ex: "abc") +** is considered a variable but a single-quoted string (ex: 'abc') is +** a constant. +*/ +int sqlite3ExprIsConstantOrFunction(Expr *p){ + int isConst = 2; + walkExprTree(p, exprNodeIsConstant, &isConst); + return isConst!=0; +} + +/* +** If the expression p codes a constant integer that is small enough +** to fit in a 32-bit integer, return 1 and put the value of the integer +** in *pValue. If the expression is not an integer or if it is too big +** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged. +*/ +int sqlite3ExprIsInteger(Expr *p, int *pValue){ + switch( p->op ){ + case TK_INTEGER: { + if( sqlite3GetInt32((char*)p->token.z, pValue) ){ + return 1; + } + break; + } + case TK_UPLUS: { + return sqlite3ExprIsInteger(p->pLeft, pValue); + } + case TK_UMINUS: { + int v; + if( sqlite3ExprIsInteger(p->pLeft, &v) ){ + *pValue = -v; + return 1; + } + break; + } + default: break; + } + return 0; +} + +/* +** Return TRUE if the given string is a row-id column name. +*/ +int sqlite3IsRowid(const char *z){ + if( sqlite3StrICmp(z, "_ROWID_")==0 ) return 1; + if( sqlite3StrICmp(z, "ROWID")==0 ) return 1; + if( sqlite3StrICmp(z, "OID")==0 ) return 1; + return 0; +} + +/* +** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up +** that name in the set of source tables in pSrcList and make the pExpr +** expression node refer back to that source column. The following changes +** are made to pExpr: +** +** pExpr->iDb Set the index in db->aDb[] of the database holding +** the table. +** pExpr->iTable Set to the cursor number for the table obtained +** from pSrcList. +** pExpr->iColumn Set to the column number within the table. +** pExpr->op Set to TK_COLUMN. +** pExpr->pLeft Any expression this points to is deleted +** pExpr->pRight Any expression this points to is deleted. +** +** The pDbToken is the name of the database (the "X"). This value may be +** NULL meaning that name is of the form Y.Z or Z. Any available database +** can be used. The pTableToken is the name of the table (the "Y"). This +** value can be NULL if pDbToken is also NULL. If pTableToken is NULL it +** means that the form of the name is Z and that columns from any table +** can be used. +** +** If the name cannot be resolved unambiguously, leave an error message +** in pParse and return non-zero. Return zero on success. +*/ +static int lookupName( + Parse *pParse, /* The parsing context */ + Token *pDbToken, /* Name of the database containing table, or NULL */ + Token *pTableToken, /* Name of table containing column, or NULL */ + Token *pColumnToken, /* Name of the column. */ + NameContext *pNC, /* The name context used to resolve the name */ + Expr *pExpr /* Make this EXPR node point to the selected column */ +){ + char *zDb = 0; /* Name of the database. The "X" in X.Y.Z */ + char *zTab = 0; /* Name of the table. The "Y" in X.Y.Z or Y.Z */ + char *zCol = 0; /* Name of the column. The "Z" */ + int i, j; /* Loop counters */ + int cnt = 0; /* Number of matching column names */ + int cntTab = 0; /* Number of matching table names */ + sqlite3 *db = pParse->db; /* The database */ + struct SrcList_item *pItem; /* Use for looping over pSrcList items */ + struct SrcList_item *pMatch = 0; /* The matching pSrcList item */ + NameContext *pTopNC = pNC; /* First namecontext in the list */ + + assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */ + zDb = sqlite3NameFromToken(pDbToken); + zTab = sqlite3NameFromToken(pTableToken); + zCol = sqlite3NameFromToken(pColumnToken); + if( sqlite3MallocFailed() ){ + goto lookupname_end; + } + + pExpr->iTable = -1; + while( pNC && cnt==0 ){ + ExprList *pEList; + SrcList *pSrcList = pNC->pSrcList; + + if( pSrcList ){ + for(i=0, pItem=pSrcList->a; inSrc; i++, pItem++){ + Table *pTab; + int iDb; + Column *pCol; + + pTab = pItem->pTab; + assert( pTab!=0 ); + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); + assert( pTab->nCol>0 ); + if( zTab ){ + if( pItem->zAlias ){ + char *zTabName = pItem->zAlias; + if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue; + }else{ + char *zTabName = pTab->zName; + if( zTabName==0 || sqlite3StrICmp(zTabName, zTab)!=0 ) continue; + if( zDb!=0 && sqlite3StrICmp(db->aDb[iDb].zName, zDb)!=0 ){ + continue; + } + } + } + if( 0==(cntTab++) ){ + pExpr->iTable = pItem->iCursor; + pExpr->pSchema = pTab->pSchema; + pMatch = pItem; + } + for(j=0, pCol=pTab->aCol; jnCol; j++, pCol++){ + if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ + const char *zColl = pTab->aCol[j].zColl; + IdList *pUsing; + cnt++; + pExpr->iTable = pItem->iCursor; + pMatch = pItem; + pExpr->pSchema = pTab->pSchema; + /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ + pExpr->iColumn = j==pTab->iPKey ? -1 : j; + pExpr->affinity = pTab->aCol[j].affinity; + if( (pExpr->flags & EP_ExpCollate)==0 ){ + pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0); + } + if( inSrc-1 ){ + if( pItem[1].jointype & JT_NATURAL ){ + /* If this match occurred in the left table of a natural join, + ** then skip the right table to avoid a duplicate match */ + pItem++; + i++; + }else if( (pUsing = pItem[1].pUsing)!=0 ){ + /* If this match occurs on a column that is in the USING clause + ** of a join, skip the search of the right table of the join + ** to avoid a duplicate match there. */ + int k; + for(k=0; knId; k++){ + if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ){ + pItem++; + i++; + break; + } + } + } + } + break; + } + } + } + } + +#ifndef SQLITE_OMIT_TRIGGER + /* If we have not already resolved the name, then maybe + ** it is a new.* or old.* trigger argument reference + */ + if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){ + TriggerStack *pTriggerStack = pParse->trigStack; + Table *pTab = 0; + if( pTriggerStack->newIdx != -1 && sqlite3StrICmp("new", zTab) == 0 ){ + pExpr->iTable = pTriggerStack->newIdx; + assert( pTriggerStack->pTab ); + pTab = pTriggerStack->pTab; + }else if( pTriggerStack->oldIdx != -1 && sqlite3StrICmp("old", zTab)==0 ){ + pExpr->iTable = pTriggerStack->oldIdx; + assert( pTriggerStack->pTab ); + pTab = pTriggerStack->pTab; + } + + if( pTab ){ + int iCol; + Column *pCol = pTab->aCol; + + pExpr->pSchema = pTab->pSchema; + cntTab++; + for(iCol=0; iCol < pTab->nCol; iCol++, pCol++) { + if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ + const char *zColl = pTab->aCol[iCol].zColl; + cnt++; + pExpr->iColumn = iCol==pTab->iPKey ? -1 : iCol; + pExpr->affinity = pTab->aCol[iCol].affinity; + if( (pExpr->flags & EP_ExpCollate)==0 ){ + pExpr->pColl = sqlite3FindCollSeq(db, ENC(db), zColl,-1, 0); + } + pExpr->pTab = pTab; + break; + } + } + } + } +#endif /* !defined(SQLITE_OMIT_TRIGGER) */ + + /* + ** Perhaps the name is a reference to the ROWID + */ + if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) ){ + cnt = 1; + pExpr->iColumn = -1; + pExpr->affinity = SQLITE_AFF_INTEGER; + } + + /* + ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z + ** might refer to an result-set alias. This happens, for example, when + ** we are resolving names in the WHERE clause of the following command: + ** + ** SELECT a+b AS x FROM table WHERE x<10; + ** + ** In cases like this, replace pExpr with a copy of the expression that + ** forms the result set entry ("a+b" in the example) and return immediately. + ** Note that the expression in the result set should have already been + ** resolved by the time the WHERE clause is resolved. + */ + if( cnt==0 && (pEList = pNC->pEList)!=0 && zTab==0 ){ + for(j=0; jnExpr; j++){ + char *zAs = pEList->a[j].zName; + if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){ + Expr *pDup; + assert( pExpr->pLeft==0 && pExpr->pRight==0 ); + assert( pExpr->pList==0 ); + assert( pExpr->pSelect==0 ); + pDup = sqlite3ExprDup(pEList->a[j].pExpr); + if( pExpr->flags & EP_ExpCollate ){ + pDup->pColl = pExpr->pColl; + pDup->flags |= EP_ExpCollate; + } + if( pExpr->span.dyn ) sqliteFree((char*)pExpr->span.z); + if( pExpr->token.dyn ) sqliteFree((char*)pExpr->token.z); + memcpy(pExpr, pDup, sizeof(*pExpr)); + sqliteFree(pDup); + cnt = 1; + pMatch = 0; + assert( zTab==0 && zDb==0 ); + goto lookupname_end_2; + } + } + } + + /* Advance to the next name context. The loop will exit when either + ** we have a match (cnt>0) or when we run out of name contexts. + */ + if( cnt==0 ){ + pNC = pNC->pNext; + } + } + + /* + ** If X and Y are NULL (in other words if only the column name Z is + ** supplied) and the value of Z is enclosed in double-quotes, then + ** Z is a string literal if it doesn't match any column names. In that + ** case, we need to return right away and not make any changes to + ** pExpr. + ** + ** Because no reference was made to outer contexts, the pNC->nRef + ** fields are not changed in any context. + */ + if( cnt==0 && zTab==0 && pColumnToken->z[0]=='"' ){ + sqliteFree(zCol); + return 0; + } + + /* + ** cnt==0 means there was not match. cnt>1 means there were two or + ** more matches. Either way, we have an error. + */ + if( cnt!=1 ){ + char *z = 0; + char *zErr; + zErr = cnt==0 ? "no such column: %s" : "ambiguous column name: %s"; + if( zDb ){ + sqlite3SetString(&z, zDb, ".", zTab, ".", zCol, (char*)0); + }else if( zTab ){ + sqlite3SetString(&z, zTab, ".", zCol, (char*)0); + }else{ + z = sqliteStrDup(zCol); + } + sqlite3ErrorMsg(pParse, zErr, z); + sqliteFree(z); + pTopNC->nErr++; + } + + /* If a column from a table in pSrcList is referenced, then record + ** this fact in the pSrcList.a[].colUsed bitmask. Column 0 causes + ** bit 0 to be set. Column 1 sets bit 1. And so forth. If the + ** column number is greater than the number of bits in the bitmask + ** then set the high-order bit of the bitmask. + */ + if( pExpr->iColumn>=0 && pMatch!=0 ){ + int n = pExpr->iColumn; + if( n>=sizeof(Bitmask)*8 ){ + n = sizeof(Bitmask)*8-1; + } + assert( pMatch->iCursor==pExpr->iTable ); + pMatch->colUsed |= ((Bitmask)1)<pLeft); + pExpr->pLeft = 0; + sqlite3ExprDelete(pExpr->pRight); + pExpr->pRight = 0; + pExpr->op = TK_COLUMN; +lookupname_end_2: + sqliteFree(zCol); + if( cnt==1 ){ + assert( pNC!=0 ); + sqlite3AuthRead(pParse, pExpr, pNC->pSrcList); + if( pMatch && !pMatch->pSelect ){ + pExpr->pTab = pMatch->pTab; + } + /* Increment the nRef value on all name contexts from TopNC up to + ** the point where the name matched. */ + for(;;){ + assert( pTopNC!=0 ); + pTopNC->nRef++; + if( pTopNC==pNC ) break; + pTopNC = pTopNC->pNext; + } + return 0; + } else { + return 1; + } +} + +/* +** This routine is designed as an xFunc for walkExprTree(). +** +** Resolve symbolic names into TK_COLUMN operators for the current +** node in the expression tree. Return 0 to continue the search down +** the tree or 2 to abort the tree walk. +** +** This routine also does error checking and name resolution for +** function names. The operator for aggregate functions is changed +** to TK_AGG_FUNCTION. +*/ +static int nameResolverStep(void *pArg, Expr *pExpr){ + NameContext *pNC = (NameContext*)pArg; + Parse *pParse; + + if( pExpr==0 ) return 1; + assert( pNC!=0 ); + pParse = pNC->pParse; + + if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return 1; + ExprSetProperty(pExpr, EP_Resolved); +#ifndef NDEBUG + if( pNC->pSrcList && pNC->pSrcList->nAlloc>0 ){ + SrcList *pSrcList = pNC->pSrcList; + int i; + for(i=0; ipSrcList->nSrc; i++){ + assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursornTab); + } + } +#endif + switch( pExpr->op ){ + /* Double-quoted strings (ex: "abc") are used as identifiers if + ** possible. Otherwise they remain as strings. Single-quoted + ** strings (ex: 'abc') are always string literals. + */ + case TK_STRING: { + if( pExpr->token.z[0]=='\'' ) break; + /* Fall thru into the TK_ID case if this is a double-quoted string */ + } + /* A lone identifier is the name of a column. + */ + case TK_ID: { + lookupName(pParse, 0, 0, &pExpr->token, pNC, pExpr); + return 1; + } + + /* A table name and column name: ID.ID + ** Or a database, table and column: ID.ID.ID + */ + case TK_DOT: { + Token *pColumn; + Token *pTable; + Token *pDb; + Expr *pRight; + + /* if( pSrcList==0 ) break; */ + pRight = pExpr->pRight; + if( pRight->op==TK_ID ){ + pDb = 0; + pTable = &pExpr->pLeft->token; + pColumn = &pRight->token; + }else{ + assert( pRight->op==TK_DOT ); + pDb = &pExpr->pLeft->token; + pTable = &pRight->pLeft->token; + pColumn = &pRight->pRight->token; + } + lookupName(pParse, pDb, pTable, pColumn, pNC, pExpr); + return 1; + } + + /* Resolve function names + */ + case TK_CONST_FUNC: + case TK_FUNCTION: { + ExprList *pList = pExpr->pList; /* The argument list */ + int n = pList ? pList->nExpr : 0; /* Number of arguments */ + int no_such_func = 0; /* True if no such function exists */ + int wrong_num_args = 0; /* True if wrong number of arguments */ + int is_agg = 0; /* True if is an aggregate function */ + int i; + int auth; /* Authorization to use the function */ + int nId; /* Number of characters in function name */ + const char *zId; /* The function name. */ + FuncDef *pDef; /* Information about the function */ + int enc = ENC(pParse->db); /* The database encoding */ + + zId = (char*)pExpr->token.z; + nId = pExpr->token.n; + pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); + if( pDef==0 ){ + pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0); + if( pDef==0 ){ + no_such_func = 1; + }else{ + wrong_num_args = 1; + } + }else{ + is_agg = pDef->xFunc==0; + } +#ifndef SQLITE_OMIT_AUTHORIZATION + if( pDef ){ + auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0); + if( auth!=SQLITE_OK ){ + if( auth==SQLITE_DENY ){ + sqlite3ErrorMsg(pParse, "not authorized to use function: %s", + pDef->zName); + pNC->nErr++; + } + pExpr->op = TK_NULL; + return 1; + } + } +#endif + if( is_agg && !pNC->allowAgg ){ + sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId); + pNC->nErr++; + is_agg = 0; + }else if( no_such_func ){ + sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId); + pNC->nErr++; + }else if( wrong_num_args ){ + sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()", + nId, zId); + pNC->nErr++; + } + if( is_agg ){ + pExpr->op = TK_AGG_FUNCTION; + pNC->hasAgg = 1; + } + if( is_agg ) pNC->allowAgg = 0; + for(i=0; pNC->nErr==0 && ia[i].pExpr, nameResolverStep, pNC); + } + if( is_agg ) pNC->allowAgg = 1; + /* FIX ME: Compute pExpr->affinity based on the expected return + ** type of the function + */ + return is_agg; + } +#ifndef SQLITE_OMIT_SUBQUERY + case TK_SELECT: + case TK_EXISTS: +#endif + case TK_IN: { + if( pExpr->pSelect ){ + int nRef = pNC->nRef; +#ifndef SQLITE_OMIT_CHECK + if( pNC->isCheck ){ + sqlite3ErrorMsg(pParse,"subqueries prohibited in CHECK constraints"); + } +#endif + sqlite3SelectResolve(pParse, pExpr->pSelect, pNC); + assert( pNC->nRef>=nRef ); + if( nRef!=pNC->nRef ){ + ExprSetProperty(pExpr, EP_VarSelect); + } + } + break; + } +#ifndef SQLITE_OMIT_CHECK + case TK_VARIABLE: { + if( pNC->isCheck ){ + sqlite3ErrorMsg(pParse,"parameters prohibited in CHECK constraints"); + } + break; + } +#endif + } + return 0; +} + +/* +** This routine walks an expression tree and resolves references to +** table columns. Nodes of the form ID.ID or ID resolve into an +** index to the table in the table list and a column offset. The +** Expr.opcode for such nodes is changed to TK_COLUMN. The Expr.iTable +** value is changed to the index of the referenced table in pTabList +** plus the "base" value. The base value will ultimately become the +** VDBE cursor number for a cursor that is pointing into the referenced +** table. The Expr.iColumn value is changed to the index of the column +** of the referenced table. The Expr.iColumn value for the special +** ROWID column is -1. Any INTEGER PRIMARY KEY column is tried as an +** alias for ROWID. +** +** Also resolve function names and check the functions for proper +** usage. Make sure all function names are recognized and all functions +** have the correct number of arguments. Leave an error message +** in pParse->zErrMsg if anything is amiss. Return the number of errors. +** +** If the expression contains aggregate functions then set the EP_Agg +** property on the expression. +*/ +int sqlite3ExprResolveNames( + NameContext *pNC, /* Namespace to resolve expressions in. */ + Expr *pExpr /* The expression to be analyzed. */ +){ + int savedHasAgg; + if( pExpr==0 ) return 0; +#if SQLITE_MAX_EXPR_DEPTH>0 + if( (pExpr->nHeight+pNC->pParse->nHeight)>SQLITE_MAX_EXPR_DEPTH ){ + sqlite3ErrorMsg(pNC->pParse, + "Expression tree is too large (maximum depth %d)", + SQLITE_MAX_EXPR_DEPTH + ); + return 1; + } + pNC->pParse->nHeight += pExpr->nHeight; +#endif + savedHasAgg = pNC->hasAgg; + pNC->hasAgg = 0; + walkExprTree(pExpr, nameResolverStep, pNC); +#if SQLITE_MAX_EXPR_DEPTH>0 + pNC->pParse->nHeight -= pExpr->nHeight; +#endif + if( pNC->nErr>0 ){ + ExprSetProperty(pExpr, EP_Error); + } + if( pNC->hasAgg ){ + ExprSetProperty(pExpr, EP_Agg); + }else if( savedHasAgg ){ + pNC->hasAgg = 1; + } + return ExprHasProperty(pExpr, EP_Error); +} + +/* +** A pointer instance of this structure is used to pass information +** through walkExprTree into codeSubqueryStep(). +*/ +typedef struct QueryCoder QueryCoder; +struct QueryCoder { + Parse *pParse; /* The parsing context */ + NameContext *pNC; /* Namespace of first enclosing query */ +}; + + +/* +** Generate code for scalar subqueries used as an expression +** and IN operators. Examples: +** +** (SELECT a FROM b) -- subquery +** EXISTS (SELECT a FROM b) -- EXISTS subquery +** x IN (4,5,11) -- IN operator with list on right-hand side +** x IN (SELECT a FROM b) -- IN operator with subquery on the right +** +** The pExpr parameter describes the expression that contains the IN +** operator or subquery. +*/ +#ifndef SQLITE_OMIT_SUBQUERY +void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ + int testAddr = 0; /* One-time test address */ + Vdbe *v = sqlite3GetVdbe(pParse); + if( v==0 ) return; + + + /* This code must be run in its entirety every time it is encountered + ** if any of the following is true: + ** + ** * The right-hand side is a correlated subquery + ** * The right-hand side is an expression list containing variables + ** * We are inside a trigger + ** + ** If all of the above are false, then we can run this code just once + ** save the results, and reuse the same result on subsequent invocations. + */ + if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->trigStack ){ + int mem = pParse->nMem++; + sqlite3VdbeAddOp(v, OP_MemLoad, mem, 0); + testAddr = sqlite3VdbeAddOp(v, OP_If, 0, 0); + assert( testAddr>0 || sqlite3MallocFailed() ); + sqlite3VdbeAddOp(v, OP_MemInt, 1, mem); + } + + switch( pExpr->op ){ + case TK_IN: { + char affinity; + KeyInfo keyInfo; + int addr; /* Address of OP_OpenEphemeral instruction */ + + affinity = sqlite3ExprAffinity(pExpr->pLeft); + + /* Whether this is an 'x IN(SELECT...)' or an 'x IN()' + ** expression it is handled the same way. A virtual table is + ** filled with single-field index keys representing the results + ** from the SELECT or the . + ** + ** If the 'x' expression is a column value, or the SELECT... + ** statement returns a column value, then the affinity of that + ** column is used to build the index keys. If both 'x' and the + ** SELECT... statement are columns, then numeric affinity is used + ** if either column has NUMERIC or INTEGER affinity. If neither + ** 'x' nor the SELECT... statement are columns, then numeric affinity + ** is used. + */ + pExpr->iTable = pParse->nTab++; + addr = sqlite3VdbeAddOp(v, OP_OpenEphemeral, pExpr->iTable, 0); + memset(&keyInfo, 0, sizeof(keyInfo)); + keyInfo.nField = 1; + sqlite3VdbeAddOp(v, OP_SetNumColumns, pExpr->iTable, 1); + + if( pExpr->pSelect ){ + /* Case 1: expr IN (SELECT ...) + ** + ** Generate code to write the results of the select into the temporary + ** table allocated and opened above. + */ + int iParm = pExpr->iTable + (((int)affinity)<<16); + ExprList *pEList; + assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable ); + if( sqlite3Select(pParse, pExpr->pSelect, SRT_Set, iParm, 0, 0, 0, 0) ){ + return; + } + pEList = pExpr->pSelect->pEList; + if( pEList && pEList->nExpr>0 ){ + keyInfo.aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, + pEList->a[0].pExpr); + } + }else if( pExpr->pList ){ + /* Case 2: expr IN (exprlist) + ** + ** For each expression, build an index key from the evaluation and + ** store it in the temporary table. If is a column, then use + ** that columns affinity when building index keys. If is not + ** a column, use numeric affinity. + */ + int i; + ExprList *pList = pExpr->pList; + struct ExprList_item *pItem; + + if( !affinity ){ + affinity = SQLITE_AFF_NONE; + } + keyInfo.aColl[0] = pExpr->pLeft->pColl; + + /* Loop through each expression in . */ + for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){ + Expr *pE2 = pItem->pExpr; + + /* If the expression is not constant then we will need to + ** disable the test that was generated above that makes sure + ** this code only executes once. Because for a non-constant + ** expression we need to rerun this code each time. + */ + if( testAddr>0 && !sqlite3ExprIsConstant(pE2) ){ + sqlite3VdbeChangeToNoop(v, testAddr-1, 3); + testAddr = 0; + } + + /* Evaluate the expression and insert it into the temp table */ + sqlite3ExprCode(pParse, pE2); + sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &affinity, 1); + sqlite3VdbeAddOp(v, OP_IdxInsert, pExpr->iTable, 0); + } + } + sqlite3VdbeChangeP3(v, addr, (void *)&keyInfo, P3_KEYINFO); + break; + } + + case TK_EXISTS: + case TK_SELECT: { + /* This has to be a scalar SELECT. Generate code to put the + ** value of this select in a memory cell and record the number + ** of the memory cell in iColumn. + */ + static const Token one = { (u8*)"1", 0, 1 }; + Select *pSel; + int iMem; + int sop; + + pExpr->iColumn = iMem = pParse->nMem++; + pSel = pExpr->pSelect; + if( pExpr->op==TK_SELECT ){ + sop = SRT_Mem; + sqlite3VdbeAddOp(v, OP_MemNull, iMem, 0); + VdbeComment((v, "# Init subquery result")); + }else{ + sop = SRT_Exists; + sqlite3VdbeAddOp(v, OP_MemInt, 0, iMem); + VdbeComment((v, "# Init EXISTS result")); + } + sqlite3ExprDelete(pSel->pLimit); + pSel->pLimit = sqlite3Expr(TK_INTEGER, 0, 0, &one); + if( sqlite3Select(pParse, pSel, sop, iMem, 0, 0, 0, 0) ){ + return; + } + break; + } + } + + if( testAddr ){ + sqlite3VdbeJumpHere(v, testAddr); + } + + return; +} +#endif /* SQLITE_OMIT_SUBQUERY */ + +/* +** Generate an instruction that will put the integer describe by +** text z[0..n-1] on the stack. +*/ +static void codeInteger(Vdbe *v, const char *z, int n){ + assert( z || sqlite3MallocFailed() ); + if( z ){ + int i; + if( sqlite3GetInt32(z, &i) ){ + sqlite3VdbeAddOp(v, OP_Integer, i, 0); + }else if( sqlite3FitsIn64Bits(z) ){ + sqlite3VdbeOp3(v, OP_Int64, 0, 0, z, n); + }else{ + sqlite3VdbeOp3(v, OP_Real, 0, 0, z, n); + } + } +} + + +/* +** Generate code that will extract the iColumn-th column from +** table pTab and push that column value on the stack. There +** is an open cursor to pTab in iTable. If iColumn<0 then +** code is generated that extracts the rowid. +*/ +void sqlite3ExprCodeGetColumn(Vdbe *v, Table *pTab, int iColumn, int iTable){ + if( iColumn<0 ){ + int op = (pTab && IsVirtual(pTab)) ? OP_VRowid : OP_Rowid; + sqlite3VdbeAddOp(v, op, iTable, 0); + }else if( pTab==0 ){ + sqlite3VdbeAddOp(v, OP_Column, iTable, iColumn); + }else{ + int op = IsVirtual(pTab) ? OP_VColumn : OP_Column; + sqlite3VdbeAddOp(v, op, iTable, iColumn); + sqlite3ColumnDefault(v, pTab, iColumn); +#ifndef SQLITE_OMIT_FLOATING_POINT + if( pTab->aCol[iColumn].affinity==SQLITE_AFF_REAL ){ + sqlite3VdbeAddOp(v, OP_RealAffinity, 0, 0); + } +#endif + } +} + +/* +** Generate code into the current Vdbe to evaluate the given +** expression and leave the result on the top of stack. +** +** This code depends on the fact that certain token values (ex: TK_EQ) +** are the same as opcode values (ex: OP_Eq) that implement the corresponding +** operation. Special comments in vdbe.c and the mkopcodeh.awk script in +** the make process cause these values to align. Assert()s in the code +** below verify that the numbers are aligned correctly. +*/ +void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ + Vdbe *v = pParse->pVdbe; + int op; + int stackChng = 1; /* Amount of change to stack depth */ + + if( v==0 ) return; + if( pExpr==0 ){ + sqlite3VdbeAddOp(v, OP_Null, 0, 0); + return; + } + op = pExpr->op; + switch( op ){ + case TK_AGG_COLUMN: { + AggInfo *pAggInfo = pExpr->pAggInfo; + struct AggInfo_col *pCol = &pAggInfo->aCol[pExpr->iAgg]; + if( !pAggInfo->directMode ){ + sqlite3VdbeAddOp(v, OP_MemLoad, pCol->iMem, 0); + break; + }else if( pAggInfo->useSortingIdx ){ + sqlite3VdbeAddOp(v, OP_Column, pAggInfo->sortingIdx, + pCol->iSorterColumn); + break; + } + /* Otherwise, fall thru into the TK_COLUMN case */ + } + case TK_COLUMN: { + if( pExpr->iTable<0 ){ + /* This only happens when coding check constraints */ + assert( pParse->ckOffset>0 ); + sqlite3VdbeAddOp(v, OP_Dup, pParse->ckOffset-pExpr->iColumn-1, 1); + }else{ + sqlite3ExprCodeGetColumn(v, pExpr->pTab, pExpr->iColumn, pExpr->iTable); + } + break; + } + case TK_INTEGER: { + codeInteger(v, (char*)pExpr->token.z, pExpr->token.n); + break; + } + case TK_FLOAT: + case TK_STRING: { + assert( TK_FLOAT==OP_Real ); + assert( TK_STRING==OP_String8 ); + sqlite3DequoteExpr(pExpr); + sqlite3VdbeOp3(v, op, 0, 0, (char*)pExpr->token.z, pExpr->token.n); + break; + } + case TK_NULL: { + sqlite3VdbeAddOp(v, OP_Null, 0, 0); + break; + } +#ifndef SQLITE_OMIT_BLOB_LITERAL + case TK_BLOB: { + int n; + const char *z; + assert( TK_BLOB==OP_HexBlob ); + n = pExpr->token.n - 3; + z = (char*)pExpr->token.z + 2; + assert( n>=0 ); + if( n==0 ){ + z = ""; + } + sqlite3VdbeOp3(v, op, 0, 0, z, n); + break; + } +#endif + case TK_VARIABLE: { + sqlite3VdbeAddOp(v, OP_Variable, pExpr->iTable, 0); + if( pExpr->token.n>1 ){ + sqlite3VdbeChangeP3(v, -1, (char*)pExpr->token.z, pExpr->token.n); + } + break; + } + case TK_REGISTER: { + sqlite3VdbeAddOp(v, OP_MemLoad, pExpr->iTable, 0); + break; + } +#ifndef SQLITE_OMIT_CAST + case TK_CAST: { + /* Expressions of the form: CAST(pLeft AS token) */ + int aff, to_op; + sqlite3ExprCode(pParse, pExpr->pLeft); + aff = sqlite3AffinityType(&pExpr->token); + to_op = aff - SQLITE_AFF_TEXT + OP_ToText; + assert( to_op==OP_ToText || aff!=SQLITE_AFF_TEXT ); + assert( to_op==OP_ToBlob || aff!=SQLITE_AFF_NONE ); + assert( to_op==OP_ToNumeric || aff!=SQLITE_AFF_NUMERIC ); + assert( to_op==OP_ToInt || aff!=SQLITE_AFF_INTEGER ); + assert( to_op==OP_ToReal || aff!=SQLITE_AFF_REAL ); + sqlite3VdbeAddOp(v, to_op, 0, 0); + stackChng = 0; + break; + } +#endif /* SQLITE_OMIT_CAST */ + case TK_LT: + case TK_LE: + case TK_GT: + case TK_GE: + case TK_NE: + case TK_EQ: { + assert( TK_LT==OP_Lt ); + assert( TK_LE==OP_Le ); + assert( TK_GT==OP_Gt ); + assert( TK_GE==OP_Ge ); + assert( TK_EQ==OP_Eq ); + assert( TK_NE==OP_Ne ); + sqlite3ExprCode(pParse, pExpr->pLeft); + sqlite3ExprCode(pParse, pExpr->pRight); + codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, 0, 0); + stackChng = -1; + break; + } + case TK_AND: + case TK_OR: + case TK_PLUS: + case TK_STAR: + case TK_MINUS: + case TK_REM: + case TK_BITAND: + case TK_BITOR: + case TK_SLASH: + case TK_LSHIFT: + case TK_RSHIFT: + case TK_CONCAT: { + assert( TK_AND==OP_And ); + assert( TK_OR==OP_Or ); + assert( TK_PLUS==OP_Add ); + assert( TK_MINUS==OP_Subtract ); + assert( TK_REM==OP_Remainder ); + assert( TK_BITAND==OP_BitAnd ); + assert( TK_BITOR==OP_BitOr ); + assert( TK_SLASH==OP_Divide ); + assert( TK_LSHIFT==OP_ShiftLeft ); + assert( TK_RSHIFT==OP_ShiftRight ); + assert( TK_CONCAT==OP_Concat ); + sqlite3ExprCode(pParse, pExpr->pLeft); + sqlite3ExprCode(pParse, pExpr->pRight); + sqlite3VdbeAddOp(v, op, 0, 0); + stackChng = -1; + break; + } + case TK_UMINUS: { + Expr *pLeft = pExpr->pLeft; + assert( pLeft ); + if( pLeft->op==TK_FLOAT || pLeft->op==TK_INTEGER ){ + Token *p = &pLeft->token; + char *z = sqlite3MPrintf("-%.*s", p->n, p->z); + if( pLeft->op==TK_FLOAT ){ + sqlite3VdbeOp3(v, OP_Real, 0, 0, z, p->n+1); + }else{ + codeInteger(v, z, p->n+1); + } + sqliteFree(z); + break; + } + /* Fall through into TK_NOT */ + } + case TK_BITNOT: + case TK_NOT: { + assert( TK_BITNOT==OP_BitNot ); + assert( TK_NOT==OP_Not ); + sqlite3ExprCode(pParse, pExpr->pLeft); + sqlite3VdbeAddOp(v, op, 0, 0); + stackChng = 0; + break; + } + case TK_ISNULL: + case TK_NOTNULL: { + int dest; + assert( TK_ISNULL==OP_IsNull ); + assert( TK_NOTNULL==OP_NotNull ); + sqlite3VdbeAddOp(v, OP_Integer, 1, 0); + sqlite3ExprCode(pParse, pExpr->pLeft); + dest = sqlite3VdbeCurrentAddr(v) + 2; + sqlite3VdbeAddOp(v, op, 1, dest); + sqlite3VdbeAddOp(v, OP_AddImm, -1, 0); + stackChng = 0; + break; + } + case TK_AGG_FUNCTION: { + AggInfo *pInfo = pExpr->pAggInfo; + if( pInfo==0 ){ + sqlite3ErrorMsg(pParse, "misuse of aggregate: %T", + &pExpr->span); + }else{ + sqlite3VdbeAddOp(v, OP_MemLoad, pInfo->aFunc[pExpr->iAgg].iMem, 0); + } + break; + } + case TK_CONST_FUNC: + case TK_FUNCTION: { + ExprList *pList = pExpr->pList; + int nExpr = pList ? pList->nExpr : 0; + FuncDef *pDef; + int nId; + const char *zId; + int constMask = 0; + int i; + u8 enc = ENC(pParse->db); + CollSeq *pColl = 0; + zId = (char*)pExpr->token.z; + nId = pExpr->token.n; + pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, enc, 0); + assert( pDef!=0 ); + nExpr = sqlite3ExprCodeExprList(pParse, pList); +#ifndef SQLITE_OMIT_VIRTUALTABLE + /* Possibly overload the function if the first argument is + ** a virtual table column. + ** + ** For infix functions (LIKE, GLOB, REGEXP, and MATCH) use the + ** second argument, not the first, as the argument to test to + ** see if it is a column in a virtual table. This is done because + ** the left operand of infix functions (the operand we want to + ** control overloading) ends up as the second argument to the + ** function. The expression "A glob B" is equivalent to + ** "glob(B,A). We want to use the A in "A glob B" to test + ** for function overloading. But we use the B term in "glob(B,A)". + */ + if( nExpr>=2 && (pExpr->flags & EP_InfixFunc) ){ + pDef = sqlite3VtabOverloadFunction(pDef, nExpr, pList->a[1].pExpr); + }else if( nExpr>0 ){ + pDef = sqlite3VtabOverloadFunction(pDef, nExpr, pList->a[0].pExpr); + } +#endif + for(i=0; ia[i].pExpr) ){ + constMask |= (1<needCollSeq && !pColl ){ + pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr); + } + } + if( pDef->needCollSeq ){ + if( !pColl ) pColl = pParse->db->pDfltColl; + sqlite3VdbeOp3(v, OP_CollSeq, 0, 0, (char *)pColl, P3_COLLSEQ); + } + sqlite3VdbeOp3(v, OP_Function, constMask, nExpr, (char*)pDef, P3_FUNCDEF); + stackChng = 1-nExpr; + break; + } +#ifndef SQLITE_OMIT_SUBQUERY + case TK_EXISTS: + case TK_SELECT: { + if( pExpr->iColumn==0 ){ + sqlite3CodeSubselect(pParse, pExpr); + } + sqlite3VdbeAddOp(v, OP_MemLoad, pExpr->iColumn, 0); + VdbeComment((v, "# load subquery result")); + break; + } + case TK_IN: { + int addr; + char affinity; + int ckOffset = pParse->ckOffset; + sqlite3CodeSubselect(pParse, pExpr); + + /* Figure out the affinity to use to create a key from the results + ** of the expression. affinityStr stores a static string suitable for + ** P3 of OP_MakeRecord. + */ + affinity = comparisonAffinity(pExpr); + + sqlite3VdbeAddOp(v, OP_Integer, 1, 0); + pParse->ckOffset = (ckOffset ? (ckOffset+1) : 0); + + /* Code the from " IN (...)". The temporary table + ** pExpr->iTable contains the values that make up the (...) set. + */ + sqlite3ExprCode(pParse, pExpr->pLeft); + addr = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeAddOp(v, OP_NotNull, -1, addr+4); /* addr + 0 */ + sqlite3VdbeAddOp(v, OP_Pop, 2, 0); + sqlite3VdbeAddOp(v, OP_Null, 0, 0); + sqlite3VdbeAddOp(v, OP_Goto, 0, addr+7); + sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &affinity, 1); /* addr + 4 */ + sqlite3VdbeAddOp(v, OP_Found, pExpr->iTable, addr+7); + sqlite3VdbeAddOp(v, OP_AddImm, -1, 0); /* addr + 6 */ + + break; + } +#endif + case TK_BETWEEN: { + Expr *pLeft = pExpr->pLeft; + struct ExprList_item *pLItem = pExpr->pList->a; + Expr *pRight = pLItem->pExpr; + sqlite3ExprCode(pParse, pLeft); + sqlite3VdbeAddOp(v, OP_Dup, 0, 0); + sqlite3ExprCode(pParse, pRight); + codeCompare(pParse, pLeft, pRight, OP_Ge, 0, 0); + sqlite3VdbeAddOp(v, OP_Pull, 1, 0); + pLItem++; + pRight = pLItem->pExpr; + sqlite3ExprCode(pParse, pRight); + codeCompare(pParse, pLeft, pRight, OP_Le, 0, 0); + sqlite3VdbeAddOp(v, OP_And, 0, 0); + break; + } + case TK_UPLUS: { + sqlite3ExprCode(pParse, pExpr->pLeft); + stackChng = 0; + break; + } + case TK_CASE: { + int expr_end_label; + int jumpInst; + int nExpr; + int i; + ExprList *pEList; + struct ExprList_item *aListelem; + + assert(pExpr->pList); + assert((pExpr->pList->nExpr % 2) == 0); + assert(pExpr->pList->nExpr > 0); + pEList = pExpr->pList; + aListelem = pEList->a; + nExpr = pEList->nExpr; + expr_end_label = sqlite3VdbeMakeLabel(v); + if( pExpr->pLeft ){ + sqlite3ExprCode(pParse, pExpr->pLeft); + } + for(i=0; ipLeft ){ + sqlite3VdbeAddOp(v, OP_Dup, 1, 1); + jumpInst = codeCompare(pParse, pExpr->pLeft, aListelem[i].pExpr, + OP_Ne, 0, 1); + sqlite3VdbeAddOp(v, OP_Pop, 1, 0); + }else{ + jumpInst = sqlite3VdbeAddOp(v, OP_IfNot, 1, 0); + } + sqlite3ExprCode(pParse, aListelem[i+1].pExpr); + sqlite3VdbeAddOp(v, OP_Goto, 0, expr_end_label); + sqlite3VdbeJumpHere(v, jumpInst); + } + if( pExpr->pLeft ){ + sqlite3VdbeAddOp(v, OP_Pop, 1, 0); + } + if( pExpr->pRight ){ + sqlite3ExprCode(pParse, pExpr->pRight); + }else{ + sqlite3VdbeAddOp(v, OP_Null, 0, 0); + } + sqlite3VdbeResolveLabel(v, expr_end_label); + break; + } +#ifndef SQLITE_OMIT_TRIGGER + case TK_RAISE: { + if( !pParse->trigStack ){ + sqlite3ErrorMsg(pParse, + "RAISE() may only be used within a trigger-program"); + return; + } + if( pExpr->iColumn!=OE_Ignore ){ + assert( pExpr->iColumn==OE_Rollback || + pExpr->iColumn == OE_Abort || + pExpr->iColumn == OE_Fail ); + sqlite3DequoteExpr(pExpr); + sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn, + (char*)pExpr->token.z, pExpr->token.n); + } else { + assert( pExpr->iColumn == OE_Ignore ); + sqlite3VdbeAddOp(v, OP_ContextPop, 0, 0); + sqlite3VdbeAddOp(v, OP_Goto, 0, pParse->trigStack->ignoreJump); + VdbeComment((v, "# raise(IGNORE)")); + } + stackChng = 0; + break; + } +#endif + } + + if( pParse->ckOffset ){ + pParse->ckOffset += stackChng; + assert( pParse->ckOffset ); + } +} + +#ifndef SQLITE_OMIT_TRIGGER +/* +** Generate code that evalutes the given expression and leaves the result +** on the stack. See also sqlite3ExprCode(). +** +** This routine might also cache the result and modify the pExpr tree +** so that it will make use of the cached result on subsequent evaluations +** rather than evaluate the whole expression again. Trivial expressions are +** not cached. If the expression is cached, its result is stored in a +** memory location. +*/ +void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr){ + Vdbe *v = pParse->pVdbe; + int iMem; + int addr1, addr2; + if( v==0 ) return; + addr1 = sqlite3VdbeCurrentAddr(v); + sqlite3ExprCode(pParse, pExpr); + addr2 = sqlite3VdbeCurrentAddr(v); + if( addr2>addr1+1 || sqlite3VdbeGetOp(v, addr1)->opcode==OP_Function ){ + iMem = pExpr->iTable = pParse->nMem++; + sqlite3VdbeAddOp(v, OP_MemStore, iMem, 0); + pExpr->op = TK_REGISTER; + } +} +#endif + +/* +** Generate code that pushes the value of every element of the given +** expression list onto the stack. +** +** Return the number of elements pushed onto the stack. +*/ +int sqlite3ExprCodeExprList( + Parse *pParse, /* Parsing context */ + ExprList *pList /* The expression list to be coded */ +){ + struct ExprList_item *pItem; + int i, n; + if( pList==0 ) return 0; + n = pList->nExpr; + for(pItem=pList->a, i=n; i>0; i--, pItem++){ + sqlite3ExprCode(pParse, pItem->pExpr); + } + return n; +} + +/* +** Generate code for a boolean expression such that a jump is made +** to the label "dest" if the expression is true but execution +** continues straight thru if the expression is false. +** +** If the expression evaluates to NULL (neither true nor false), then +** take the jump if the jumpIfNull flag is true. +** +** This code depends on the fact that certain token values (ex: TK_EQ) +** are the same as opcode values (ex: OP_Eq) that implement the corresponding +** operation. Special comments in vdbe.c and the mkopcodeh.awk script in +** the make process cause these values to align. Assert()s in the code +** below verify that the numbers are aligned correctly. +*/ +void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ + Vdbe *v = pParse->pVdbe; + int op = 0; + int ckOffset = pParse->ckOffset; + if( v==0 || pExpr==0 ) return; + op = pExpr->op; + switch( op ){ + case TK_AND: { + int d2 = sqlite3VdbeMakeLabel(v); + sqlite3ExprIfFalse(pParse, pExpr->pLeft, d2, !jumpIfNull); + sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); + sqlite3VdbeResolveLabel(v, d2); + break; + } + case TK_OR: { + sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); + sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull); + break; + } + case TK_NOT: { + sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); + break; + } + case TK_LT: + case TK_LE: + case TK_GT: + case TK_GE: + case TK_NE: + case TK_EQ: { + assert( TK_LT==OP_Lt ); + assert( TK_LE==OP_Le ); + assert( TK_GT==OP_Gt ); + assert( TK_GE==OP_Ge ); + assert( TK_EQ==OP_Eq ); + assert( TK_NE==OP_Ne ); + sqlite3ExprCode(pParse, pExpr->pLeft); + sqlite3ExprCode(pParse, pExpr->pRight); + codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, dest, jumpIfNull); + break; + } + case TK_ISNULL: + case TK_NOTNULL: { + assert( TK_ISNULL==OP_IsNull ); + assert( TK_NOTNULL==OP_NotNull ); + sqlite3ExprCode(pParse, pExpr->pLeft); + sqlite3VdbeAddOp(v, op, 1, dest); + break; + } + case TK_BETWEEN: { + /* The expression "x BETWEEN y AND z" is implemented as: + ** + ** 1 IF (x < y) GOTO 3 + ** 2 IF (x <= z) GOTO + ** 3 ... + */ + int addr; + Expr *pLeft = pExpr->pLeft; + Expr *pRight = pExpr->pList->a[0].pExpr; + sqlite3ExprCode(pParse, pLeft); + sqlite3VdbeAddOp(v, OP_Dup, 0, 0); + sqlite3ExprCode(pParse, pRight); + addr = codeCompare(pParse, pLeft, pRight, OP_Lt, 0, !jumpIfNull); + + pRight = pExpr->pList->a[1].pExpr; + sqlite3ExprCode(pParse, pRight); + codeCompare(pParse, pLeft, pRight, OP_Le, dest, jumpIfNull); + + sqlite3VdbeAddOp(v, OP_Integer, 0, 0); + sqlite3VdbeJumpHere(v, addr); + sqlite3VdbeAddOp(v, OP_Pop, 1, 0); + break; + } + default: { + sqlite3ExprCode(pParse, pExpr); + sqlite3VdbeAddOp(v, OP_If, jumpIfNull, dest); + break; + } + } + pParse->ckOffset = ckOffset; +} + +/* +** Generate code for a boolean expression such that a jump is made +** to the label "dest" if the expression is false but execution +** continues straight thru if the expression is true. +** +** If the expression evaluates to NULL (neither true nor false) then +** jump if jumpIfNull is true or fall through if jumpIfNull is false. +*/ +void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ + Vdbe *v = pParse->pVdbe; + int op = 0; + int ckOffset = pParse->ckOffset; + if( v==0 || pExpr==0 ) return; + + /* The value of pExpr->op and op are related as follows: + ** + ** pExpr->op op + ** --------- ---------- + ** TK_ISNULL OP_NotNull + ** TK_NOTNULL OP_IsNull + ** TK_NE OP_Eq + ** TK_EQ OP_Ne + ** TK_GT OP_Le + ** TK_LE OP_Gt + ** TK_GE OP_Lt + ** TK_LT OP_Ge + ** + ** For other values of pExpr->op, op is undefined and unused. + ** The value of TK_ and OP_ constants are arranged such that we + ** can compute the mapping above using the following expression. + ** Assert()s verify that the computation is correct. + */ + op = ((pExpr->op+(TK_ISNULL&1))^1)-(TK_ISNULL&1); + + /* Verify correct alignment of TK_ and OP_ constants + */ + assert( pExpr->op!=TK_ISNULL || op==OP_NotNull ); + assert( pExpr->op!=TK_NOTNULL || op==OP_IsNull ); + assert( pExpr->op!=TK_NE || op==OP_Eq ); + assert( pExpr->op!=TK_EQ || op==OP_Ne ); + assert( pExpr->op!=TK_LT || op==OP_Ge ); + assert( pExpr->op!=TK_LE || op==OP_Gt ); + assert( pExpr->op!=TK_GT || op==OP_Le ); + assert( pExpr->op!=TK_GE || op==OP_Lt ); + + switch( pExpr->op ){ + case TK_AND: { + sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); + sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); + break; + } + case TK_OR: { + int d2 = sqlite3VdbeMakeLabel(v); + sqlite3ExprIfTrue(pParse, pExpr->pLeft, d2, !jumpIfNull); + sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull); + sqlite3VdbeResolveLabel(v, d2); + break; + } + case TK_NOT: { + sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); + break; + } + case TK_LT: + case TK_LE: + case TK_GT: + case TK_GE: + case TK_NE: + case TK_EQ: { + sqlite3ExprCode(pParse, pExpr->pLeft); + sqlite3ExprCode(pParse, pExpr->pRight); + codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, dest, jumpIfNull); + break; + } + case TK_ISNULL: + case TK_NOTNULL: { + sqlite3ExprCode(pParse, pExpr->pLeft); + sqlite3VdbeAddOp(v, op, 1, dest); + break; + } + case TK_BETWEEN: { + /* The expression is "x BETWEEN y AND z". It is implemented as: + ** + ** 1 IF (x >= y) GOTO 3 + ** 2 GOTO + ** 3 IF (x > z) GOTO + */ + int addr; + Expr *pLeft = pExpr->pLeft; + Expr *pRight = pExpr->pList->a[0].pExpr; + sqlite3ExprCode(pParse, pLeft); + sqlite3VdbeAddOp(v, OP_Dup, 0, 0); + sqlite3ExprCode(pParse, pRight); + addr = sqlite3VdbeCurrentAddr(v); + codeCompare(pParse, pLeft, pRight, OP_Ge, addr+3, !jumpIfNull); + + sqlite3VdbeAddOp(v, OP_Pop, 1, 0); + sqlite3VdbeAddOp(v, OP_Goto, 0, dest); + pRight = pExpr->pList->a[1].pExpr; + sqlite3ExprCode(pParse, pRight); + codeCompare(pParse, pLeft, pRight, OP_Gt, dest, jumpIfNull); + break; + } + default: { + sqlite3ExprCode(pParse, pExpr); + sqlite3VdbeAddOp(v, OP_IfNot, jumpIfNull, dest); + break; + } + } + pParse->ckOffset = ckOffset; +} + +/* +** Do a deep comparison of two expression trees. Return TRUE (non-zero) +** if they are identical and return FALSE if they differ in any way. +** +** Sometimes this routine will return FALSE even if the two expressions +** really are equivalent. If we cannot prove that the expressions are +** identical, we return FALSE just to be safe. So if this routine +** returns false, then you do not really know for certain if the two +** expressions are the same. But if you get a TRUE return, then you +** can be sure the expressions are the same. In the places where +** this routine is used, it does not hurt to get an extra FALSE - that +** just might result in some slightly slower code. But returning +** an incorrect TRUE could lead to a malfunction. +*/ +int sqlite3ExprCompare(Expr *pA, Expr *pB){ + int i; + if( pA==0||pB==0 ){ + return pB==pA; + } + if( pA->op!=pB->op ) return 0; + if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 0; + if( !sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 0; + if( !sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 0; + if( pA->pList ){ + if( pB->pList==0 ) return 0; + if( pA->pList->nExpr!=pB->pList->nExpr ) return 0; + for(i=0; ipList->nExpr; i++){ + if( !sqlite3ExprCompare(pA->pList->a[i].pExpr, pB->pList->a[i].pExpr) ){ + return 0; + } + } + }else if( pB->pList ){ + return 0; + } + if( pA->pSelect || pB->pSelect ) return 0; + if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 0; + if( pA->op!=TK_COLUMN && pA->token.z ){ + if( pB->token.z==0 ) return 0; + if( pB->token.n!=pA->token.n ) return 0; + if( sqlite3StrNICmp((char*)pA->token.z,(char*)pB->token.z,pB->token.n)!=0 ){ + return 0; + } + } + return 1; +} + + +/* +** Add a new element to the pAggInfo->aCol[] array. Return the index of +** the new element. Return a negative number if malloc fails. +*/ +static int addAggInfoColumn(AggInfo *pInfo){ + int i; + pInfo->aCol = sqlite3ArrayAllocate( + pInfo->aCol, + sizeof(pInfo->aCol[0]), + 3, + &pInfo->nColumn, + &pInfo->nColumnAlloc, + &i + ); + return i; +} + +/* +** Add a new element to the pAggInfo->aFunc[] array. Return the index of +** the new element. Return a negative number if malloc fails. +*/ +static int addAggInfoFunc(AggInfo *pInfo){ + int i; + pInfo->aFunc = sqlite3ArrayAllocate( + pInfo->aFunc, + sizeof(pInfo->aFunc[0]), + 3, + &pInfo->nFunc, + &pInfo->nFuncAlloc, + &i + ); + return i; +} + +/* +** This is an xFunc for walkExprTree() used to implement +** sqlite3ExprAnalyzeAggregates(). See sqlite3ExprAnalyzeAggregates +** for additional information. +** +** This routine analyzes the aggregate function at pExpr. +*/ +static int analyzeAggregate(void *pArg, Expr *pExpr){ + int i; + NameContext *pNC = (NameContext *)pArg; + Parse *pParse = pNC->pParse; + SrcList *pSrcList = pNC->pSrcList; + AggInfo *pAggInfo = pNC->pAggInfo; + + + switch( pExpr->op ){ + case TK_AGG_COLUMN: + case TK_COLUMN: { + /* Check to see if the column is in one of the tables in the FROM + ** clause of the aggregate query */ + if( pSrcList ){ + struct SrcList_item *pItem = pSrcList->a; + for(i=0; inSrc; i++, pItem++){ + struct AggInfo_col *pCol; + if( pExpr->iTable==pItem->iCursor ){ + /* If we reach this point, it means that pExpr refers to a table + ** that is in the FROM clause of the aggregate query. + ** + ** Make an entry for the column in pAggInfo->aCol[] if there + ** is not an entry there already. + */ + int k; + pCol = pAggInfo->aCol; + for(k=0; knColumn; k++, pCol++){ + if( pCol->iTable==pExpr->iTable && + pCol->iColumn==pExpr->iColumn ){ + break; + } + } + if( k>=pAggInfo->nColumn && (k = addAggInfoColumn(pAggInfo))>=0 ){ + pCol = &pAggInfo->aCol[k]; + pCol->pTab = pExpr->pTab; + pCol->iTable = pExpr->iTable; + pCol->iColumn = pExpr->iColumn; + pCol->iMem = pParse->nMem++; + pCol->iSorterColumn = -1; + pCol->pExpr = pExpr; + if( pAggInfo->pGroupBy ){ + int j, n; + ExprList *pGB = pAggInfo->pGroupBy; + struct ExprList_item *pTerm = pGB->a; + n = pGB->nExpr; + for(j=0; jpExpr; + if( pE->op==TK_COLUMN && pE->iTable==pExpr->iTable && + pE->iColumn==pExpr->iColumn ){ + pCol->iSorterColumn = j; + break; + } + } + } + if( pCol->iSorterColumn<0 ){ + pCol->iSorterColumn = pAggInfo->nSortingColumn++; + } + } + /* There is now an entry for pExpr in pAggInfo->aCol[] (either + ** because it was there before or because we just created it). + ** Convert the pExpr to be a TK_AGG_COLUMN referring to that + ** pAggInfo->aCol[] entry. + */ + pExpr->pAggInfo = pAggInfo; + pExpr->op = TK_AGG_COLUMN; + pExpr->iAgg = k; + break; + } /* endif pExpr->iTable==pItem->iCursor */ + } /* end loop over pSrcList */ + } + return 1; + } + case TK_AGG_FUNCTION: { + /* The pNC->nDepth==0 test causes aggregate functions in subqueries + ** to be ignored */ + if( pNC->nDepth==0 ){ + /* Check to see if pExpr is a duplicate of another aggregate + ** function that is already in the pAggInfo structure + */ + struct AggInfo_func *pItem = pAggInfo->aFunc; + for(i=0; inFunc; i++, pItem++){ + if( sqlite3ExprCompare(pItem->pExpr, pExpr) ){ + break; + } + } + if( i>=pAggInfo->nFunc ){ + /* pExpr is original. Make a new entry in pAggInfo->aFunc[] + */ + u8 enc = ENC(pParse->db); + i = addAggInfoFunc(pAggInfo); + if( i>=0 ){ + pItem = &pAggInfo->aFunc[i]; + pItem->pExpr = pExpr; + pItem->iMem = pParse->nMem++; + pItem->pFunc = sqlite3FindFunction(pParse->db, + (char*)pExpr->token.z, pExpr->token.n, + pExpr->pList ? pExpr->pList->nExpr : 0, enc, 0); + if( pExpr->flags & EP_Distinct ){ + pItem->iDistinct = pParse->nTab++; + }else{ + pItem->iDistinct = -1; + } + } + } + /* Make pExpr point to the appropriate pAggInfo->aFunc[] entry + */ + pExpr->iAgg = i; + pExpr->pAggInfo = pAggInfo; + return 1; + } + } + } + + /* Recursively walk subqueries looking for TK_COLUMN nodes that need + ** to be changed to TK_AGG_COLUMN. But increment nDepth so that + ** TK_AGG_FUNCTION nodes in subqueries will be unchanged. + */ + if( pExpr->pSelect ){ + pNC->nDepth++; + walkSelectExpr(pExpr->pSelect, analyzeAggregate, pNC); + pNC->nDepth--; + } + return 0; +} + +/* +** Analyze the given expression looking for aggregate functions and +** for variables that need to be added to the pParse->aAgg[] array. +** Make additional entries to the pParse->aAgg[] array as necessary. +** +** This routine should only be called after the expression has been +** analyzed by sqlite3ExprResolveNames(). +** +** If errors are seen, leave an error message in zErrMsg and return +** the number of errors. +*/ +int sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){ + int nErr = pNC->pParse->nErr; + walkExprTree(pExpr, analyzeAggregate, pNC); + return pNC->pParse->nErr - nErr; +} + +/* +** Call sqlite3ExprAnalyzeAggregates() for every expression in an +** expression list. Return the number of errors. +** +** If an error is found, the analysis is cut short. +*/ +int sqlite3ExprAnalyzeAggList(NameContext *pNC, ExprList *pList){ + struct ExprList_item *pItem; + int i; + int nErr = 0; + if( pList ){ + for(pItem=pList->a, i=0; nErr==0 && inExpr; i++, pItem++){ + nErr += sqlite3ExprAnalyzeAggregates(pNC, pItem->pExpr); + } + } + return nErr; +} diff --git a/extensions/sqlite/sqlite-source/func.c b/extensions/sqlite/sqlite-source/func.c new file mode 100644 index 00000000..3bac3e85 --- /dev/null +++ b/extensions/sqlite/sqlite-source/func.c @@ -0,0 +1,1493 @@ +/* +** 2002 February 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 the C functions that implement various SQL +** functions of SQLite. +** +** There is only one exported symbol in this file - the function +** sqliteRegisterBuildinFunctions() found at the bottom of the file. +** All other code has file scope. +** +** $Id$ +*/ +#include "sqliteInt.h" +#include +/* #include */ +#include +#include +#include "vdbeInt.h" +#include "os.h" + +/* +** Return the collating function associated with a function. +*/ +static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){ + return context->pColl; +} + +/* +** Implementation of the non-aggregate min() and max() functions +*/ +static void minmaxFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + int i; + int mask; /* 0 for min() or 0xffffffff for max() */ + int iBest; + CollSeq *pColl; + + if( argc==0 ) return; + mask = sqlite3_user_data(context)==0 ? 0 : -1; + pColl = sqlite3GetFuncCollSeq(context); + assert( pColl ); + assert( mask==-1 || mask==0 ); + iBest = 0; + if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; + for(i=1; i=0 ){ + iBest = i; + } + } + sqlite3_result_value(context, argv[iBest]); +} + +/* +** Return the type of the argument. +*/ +static void typeofFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const char *z = 0; + switch( sqlite3_value_type(argv[0]) ){ + case SQLITE_NULL: z = "null"; break; + case SQLITE_INTEGER: z = "integer"; break; + case SQLITE_TEXT: z = "text"; break; + case SQLITE_FLOAT: z = "real"; break; + case SQLITE_BLOB: z = "blob"; break; + } + sqlite3_result_text(context, z, -1, SQLITE_STATIC); +} + + +/* +** Implementation of the length() function +*/ +static void lengthFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + int len; + + assert( argc==1 ); + switch( sqlite3_value_type(argv[0]) ){ + case SQLITE_BLOB: + case SQLITE_INTEGER: + case SQLITE_FLOAT: { + sqlite3_result_int(context, sqlite3_value_bytes(argv[0])); + break; + } + case SQLITE_TEXT: { + const unsigned char *z = sqlite3_value_text(argv[0]); + if( z==0 ) return; + len = 0; + while( *z ){ + len++; + SQLITE_SKIP_UTF8(z); + } + sqlite3_result_int(context, len); + break; + } + default: { + sqlite3_result_null(context); + break; + } + } +} + +/* +** Implementation of the abs() function +*/ +static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + assert( argc==1 ); + switch( sqlite3_value_type(argv[0]) ){ + case SQLITE_INTEGER: { + i64 iVal = sqlite3_value_int64(argv[0]); + if( iVal<0 ){ + if( (iVal<<1)==0 ){ + sqlite3_result_error(context, "integer overflow", -1); + return; + } + iVal = -iVal; + } + sqlite3_result_int64(context, iVal); + break; + } + case SQLITE_NULL: { + sqlite3_result_null(context); + break; + } + default: { + double rVal = sqlite3_value_double(argv[0]); + if( rVal<0 ) rVal = -rVal; + sqlite3_result_double(context, rVal); + break; + } + } +} + +/* +** Implementation of the substr() function. +** +** substr(x,p1,p2) returns p2 characters of x[] beginning with p1. +** p1 is 1-indexed. So substr(x,1,1) returns the first character +** of x. If x is text, then we actually count UTF-8 characters. +** If x is a blob, then we count bytes. +** +** If p1 is negative, then we begin abs(p1) from the end of x[]. +*/ +static void substrFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const unsigned char *z; + const unsigned char *z2; + int len; + int p0type; + i64 p1, p2; + + assert( argc==3 ); + p0type = sqlite3_value_type(argv[0]); + if( p0type==SQLITE_BLOB ){ + len = sqlite3_value_bytes(argv[0]); + z = sqlite3_value_blob(argv[0]); + if( z==0 ) return; + assert( len==sqlite3_value_bytes(argv[0]) ); + }else{ + z = sqlite3_value_text(argv[0]); + if( z==0 ) return; + len = 0; + for(z2=z; *z2; len++){ + SQLITE_SKIP_UTF8(z2); + } + } + p1 = sqlite3_value_int(argv[1]); + p2 = sqlite3_value_int(argv[2]); + if( p1<0 ){ + p1 += len; + if( p1<0 ){ + p2 += p1; + p1 = 0; + } + }else if( p1>0 ){ + p1--; + } + if( p1+p2>len ){ + p2 = len-p1; + } + if( p0type!=SQLITE_BLOB ){ + while( *z && p1 ){ + SQLITE_SKIP_UTF8(z); + p1--; + } + for(z2=z; *z2 && p2; p2--){ + SQLITE_SKIP_UTF8(z2); + } + sqlite3_result_text(context, (char*)z, z2-z, SQLITE_TRANSIENT); + }else{ + if( p2<0 ) p2 = 0; + sqlite3_result_blob(context, (char*)&z[p1], p2, SQLITE_TRANSIENT); + } +} + +/* +** Implementation of the round() function +*/ +static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + int n = 0; + double r; + char zBuf[500]; /* larger than the %f representation of the largest double */ + assert( argc==1 || argc==2 ); + if( argc==2 ){ + if( SQLITE_NULL==sqlite3_value_type(argv[1]) ) return; + n = sqlite3_value_int(argv[1]); + if( n>30 ) n = 30; + if( n<0 ) n = 0; + } + if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; + r = sqlite3_value_double(argv[0]); + sqlite3_snprintf(sizeof(zBuf),zBuf,"%.*f",n,r); + sqlite3AtoF(zBuf, &r); + sqlite3_result_double(context, r); +} + +/* +** Implementation of the upper() and lower() SQL functions. +*/ +static void upperFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + char *z1; + const char *z2; + int i, n; + if( argc<1 || SQLITE_NULL==sqlite3_value_type(argv[0]) ) return; + z2 = (char*)sqlite3_value_text(argv[0]); + n = sqlite3_value_bytes(argv[0]); + /* Verify that the call to _bytes() does not invalidate the _text() pointer */ + assert( z2==(char*)sqlite3_value_text(argv[0]) ); + if( z2 ){ + z1 = sqlite3_malloc(n+1); + if( z1 ){ + memcpy(z1, z2, n+1); + for(i=0; z1[i]; i++){ + z1[i] = toupper(z1[i]); + } + sqlite3_result_text(context, z1, -1, sqlite3_free); + } + } +} +static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + char *z1; + const char *z2; + int i, n; + if( argc<1 || SQLITE_NULL==sqlite3_value_type(argv[0]) ) return; + z2 = (char*)sqlite3_value_text(argv[0]); + n = sqlite3_value_bytes(argv[0]); + /* Verify that the call to _bytes() does not invalidate the _text() pointer */ + assert( z2==(char*)sqlite3_value_text(argv[0]) ); + if( z2 ){ + z1 = sqlite3_malloc(n+1); + if( z1 ){ + memcpy(z1, z2, n+1); + for(i=0; z1[i]; i++){ + z1[i] = tolower(z1[i]); + } + sqlite3_result_text(context, z1, -1, sqlite3_free); + } + } +} + +/* +** Implementation of the IFNULL(), NVL(), and COALESCE() functions. +** All three do the same thing. They return the first non-NULL +** argument. +*/ +static void ifnullFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + int i; + for(i=0; iSQLITE_MAX_LENGTH ){ + sqlite3_result_error_toobig(context); + return; + } + p = sqliteMalloc(n); + if( p ){ + sqlite3Randomness(n, p); + sqlite3_result_blob(context, (char*)p, n, sqlite3FreeX); + } +} + +/* +** Implementation of the last_insert_rowid() SQL function. The return +** value is the same as the sqlite3_last_insert_rowid() API function. +*/ +static void last_insert_rowid( + sqlite3_context *context, + int arg, + sqlite3_value **argv +){ + sqlite3 *db = sqlite3_user_data(context); + sqlite3_result_int64(context, sqlite3_last_insert_rowid(db)); +} + +/* +** Implementation of the changes() SQL function. The return value is the +** same as the sqlite3_changes() API function. +*/ +static void changes( + sqlite3_context *context, + int arg, + sqlite3_value **argv +){ + sqlite3 *db = sqlite3_user_data(context); + sqlite3_result_int(context, sqlite3_changes(db)); +} + +/* +** Implementation of the total_changes() SQL function. The return value is +** the same as the sqlite3_total_changes() API function. +*/ +static void total_changes( + sqlite3_context *context, + int arg, + sqlite3_value **argv +){ + sqlite3 *db = sqlite3_user_data(context); + sqlite3_result_int(context, sqlite3_total_changes(db)); +} + +/* +** A structure defining how to do GLOB-style comparisons. +*/ +struct compareInfo { + u8 matchAll; + u8 matchOne; + u8 matchSet; + u8 noCase; +}; + +static const struct compareInfo globInfo = { '*', '?', '[', 0 }; +/* The correct SQL-92 behavior is for the LIKE operator to ignore +** case. Thus 'a' LIKE 'A' would be true. */ +static const struct compareInfo likeInfoNorm = { '%', '_', 0, 1 }; +/* If SQLITE_CASE_SENSITIVE_LIKE is defined, then the LIKE operator +** is case sensitive causing 'a' LIKE 'A' to be false */ +static const struct compareInfo likeInfoAlt = { '%', '_', 0, 0 }; + +/* +** Read a single UTF-8 character and return its value. +*/ +u32 sqlite3ReadUtf8(const unsigned char *z){ + u32 c; + SQLITE_READ_UTF8(z, c); + return c; +} + +/* +** Compare two UTF-8 strings for equality where the first string can +** potentially be a "glob" expression. Return true (1) if they +** are the same and false (0) if they are different. +** +** Globbing rules: +** +** '*' Matches any sequence of zero or more characters. +** +** '?' Matches exactly one character. +** +** [...] Matches one character from the enclosed list of +** characters. +** +** [^...] Matches one character not in the enclosed list. +** +** With the [...] and [^...] matching, a ']' character can be included +** in the list by making it the first character after '[' or '^'. A +** range of characters can be specified using '-'. Example: +** "[a-z]" matches any single lower-case letter. To match a '-', make +** it the last character in the list. +** +** This routine is usually quick, but can be N**2 in the worst case. +** +** Hints: to match '*' or '?', put them in "[]". Like this: +** +** abc[*]xyz Matches "abc*xyz" only +*/ +static int patternCompare( + const u8 *zPattern, /* The glob pattern */ + const u8 *zString, /* The string to compare against the glob */ + const struct compareInfo *pInfo, /* Information about how to do the compare */ + const int esc /* The escape character */ +){ + register int c; + int invert; + int seen; + int c2; + u8 matchOne = pInfo->matchOne; + u8 matchAll = pInfo->matchAll; + u8 matchSet = pInfo->matchSet; + u8 noCase = pInfo->noCase; + int prevEscape = 0; /* True if the previous character was 'escape' */ + + while( (c = *zPattern)!=0 ){ + if( !prevEscape && c==matchAll ){ + while( (c=zPattern[1]) == matchAll || c == matchOne ){ + if( c==matchOne ){ + if( *zString==0 ) return 0; + SQLITE_SKIP_UTF8(zString); + } + zPattern++; + } + if( c && esc && sqlite3ReadUtf8(&zPattern[1])==esc ){ + u8 const *zTemp = &zPattern[1]; + SQLITE_SKIP_UTF8(zTemp); + c = *zTemp; + } + if( c==0 ) return 1; + if( c==matchSet ){ + assert( esc==0 ); /* This is GLOB, not LIKE */ + while( *zString && patternCompare(&zPattern[1],zString,pInfo,esc)==0 ){ + SQLITE_SKIP_UTF8(zString); + } + return *zString!=0; + }else{ + while( (c2 = *zString)!=0 ){ + if( noCase ){ + c2 = sqlite3UpperToLower[c2]; + c = sqlite3UpperToLower[c]; + while( c2 != 0 && c2 != c ){ c2 = sqlite3UpperToLower[*++zString]; } + }else{ + while( c2 != 0 && c2 != c ){ c2 = *++zString; } + } + if( c2==0 ) return 0; + if( patternCompare(&zPattern[1],zString,pInfo,esc) ) return 1; + SQLITE_SKIP_UTF8(zString); + } + return 0; + } + }else if( !prevEscape && c==matchOne ){ + if( *zString==0 ) return 0; + SQLITE_SKIP_UTF8(zString); + zPattern++; + }else if( c==matchSet ){ + int prior_c = 0; + assert( esc==0 ); /* This only occurs for GLOB, not LIKE */ + seen = 0; + invert = 0; + c = sqlite3ReadUtf8(zString); + if( c==0 ) return 0; + c2 = *++zPattern; + if( c2=='^' ){ invert = 1; c2 = *++zPattern; } + if( c2==']' ){ + if( c==']' ) seen = 1; + c2 = *++zPattern; + } + while( (c2 = sqlite3ReadUtf8(zPattern))!=0 && c2!=']' ){ + if( c2=='-' && zPattern[1]!=']' && zPattern[1]!=0 && prior_c>0 ){ + zPattern++; + c2 = sqlite3ReadUtf8(zPattern); + if( c>=prior_c && c<=c2 ) seen = 1; + prior_c = 0; + }else if( c==c2 ){ + seen = 1; + prior_c = c2; + }else{ + prior_c = c2; + } + SQLITE_SKIP_UTF8(zPattern); + } + if( c2==0 || (seen ^ invert)==0 ) return 0; + SQLITE_SKIP_UTF8(zString); + zPattern++; + }else if( esc && !prevEscape && sqlite3ReadUtf8(zPattern)==esc){ + prevEscape = 1; + SQLITE_SKIP_UTF8(zPattern); + }else{ + if( noCase ){ + if( sqlite3UpperToLower[c] != sqlite3UpperToLower[*zString] ) return 0; + }else{ + if( c != *zString ) return 0; + } + zPattern++; + zString++; + prevEscape = 0; + } + } + return *zString==0; +} + +/* +** Count the number of times that the LIKE operator (or GLOB which is +** just a variation of LIKE) gets called. This is used for testing +** only. +*/ +#ifdef SQLITE_TEST +int sqlite3_like_count = 0; +#endif + + +/* +** Implementation of the like() SQL function. This function implements +** the build-in LIKE operator. The first argument to the function is the +** pattern and the second argument is the string. So, the SQL statements: +** +** A LIKE B +** +** is implemented as like(B,A). +** +** This same function (with a different compareInfo structure) computes +** the GLOB operator. +*/ +static void likeFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const unsigned char *zA, *zB; + int escape = 0; + + zB = sqlite3_value_text(argv[0]); + zA = sqlite3_value_text(argv[1]); + + /* Limit the length of the LIKE or GLOB pattern to avoid problems + ** of deep recursion and N*N behavior in patternCompare(). + */ + if( sqlite3_value_bytes(argv[0])>SQLITE_MAX_LIKE_PATTERN_LENGTH ){ + sqlite3_result_error(context, "LIKE or GLOB pattern too complex", -1); + return; + } + assert( zB==sqlite3_value_text(argv[0]) ); /* Encoding did not change */ + + if( argc==3 ){ + /* The escape character string must consist of a single UTF-8 character. + ** Otherwise, return an error. + */ + const unsigned char *zEsc = sqlite3_value_text(argv[2]); + if( zEsc==0 ) return; + if( sqlite3Utf8CharLen((char*)zEsc, -1)!=1 ){ + sqlite3_result_error(context, + "ESCAPE expression must be a single character", -1); + return; + } + escape = sqlite3ReadUtf8(zEsc); + } + if( zA && zB ){ + struct compareInfo *pInfo = sqlite3_user_data(context); +#ifdef SQLITE_TEST + sqlite3_like_count++; +#endif + + sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape)); + } +} + +/* +** Implementation of the NULLIF(x,y) function. The result is the first +** argument if the arguments are different. The result is NULL if the +** arguments are equal to each other. +*/ +static void nullifFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + CollSeq *pColl = sqlite3GetFuncCollSeq(context); + if( sqlite3MemCompare(argv[0], argv[1], pColl)!=0 ){ + sqlite3_result_value(context, argv[0]); + } +} + +/* +** Implementation of the VERSION(*) function. The result is the version +** of the SQLite library that is running. +*/ +static void versionFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + sqlite3_result_text(context, sqlite3_version, -1, SQLITE_STATIC); +} + +/* Array for converting from half-bytes (nybbles) into ASCII hex +** digits. */ +static const char hexdigits[] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' +}; + +/* +** EXPERIMENTAL - This is not an official function. The interface may +** change. This function may disappear. Do not write code that depends +** on this function. +** +** Implementation of the QUOTE() function. This function takes a single +** argument. If the argument is numeric, the return value is the same as +** the argument. If the argument is NULL, the return value is the string +** "NULL". Otherwise, the argument is enclosed in single quotes with +** single-quote escapes. +*/ +static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ + if( argc<1 ) return; + switch( sqlite3_value_type(argv[0]) ){ + case SQLITE_NULL: { + sqlite3_result_text(context, "NULL", 4, SQLITE_STATIC); + break; + } + case SQLITE_INTEGER: + case SQLITE_FLOAT: { + sqlite3_result_value(context, argv[0]); + break; + } + case SQLITE_BLOB: { + char *zText = 0; + char const *zBlob = sqlite3_value_blob(argv[0]); + int nBlob = sqlite3_value_bytes(argv[0]); + assert( zBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */ + + if( 2*nBlob+4>SQLITE_MAX_LENGTH ){ + sqlite3_result_error_toobig(context); + return; + } + zText = (char *)sqliteMalloc((2*nBlob)+4); + if( !zText ){ + sqlite3_result_error(context, "out of memory", -1); + }else{ + int i; + for(i=0; i>4)&0x0F]; + zText[(i*2)+3] = hexdigits[(zBlob[i])&0x0F]; + } + zText[(nBlob*2)+2] = '\''; + zText[(nBlob*2)+3] = '\0'; + zText[0] = 'X'; + zText[1] = '\''; + sqlite3_result_text(context, zText, -1, SQLITE_TRANSIENT); + sqliteFree(zText); + } + break; + } + case SQLITE_TEXT: { + int i,j; + u64 n; + const unsigned char *zArg = sqlite3_value_text(argv[0]); + char *z; + + if( zArg==0 ) return; + for(i=0, n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; } + if( i+n+3>SQLITE_MAX_LENGTH ){ + sqlite3_result_error_toobig(context); + return; + } + z = sqliteMalloc( i+n+3 ); + if( z==0 ) return; + z[0] = '\''; + for(i=0, j=1; zArg[i]; i++){ + z[j++] = zArg[i]; + if( zArg[i]=='\'' ){ + z[j++] = '\''; + } + } + z[j++] = '\''; + z[j] = 0; + sqlite3_result_text(context, z, j, SQLITE_TRANSIENT); + sqliteFree(z); + } + } +} + +/* +** The hex() function. Interpret the argument as a blob. Return +** a hexadecimal rendering as text. +*/ +static void hexFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + int i, n; + const unsigned char *pBlob; + char *zHex, *z; + assert( argc==1 ); + pBlob = sqlite3_value_blob(argv[0]); + n = sqlite3_value_bytes(argv[0]); + if( n*2+1>SQLITE_MAX_LENGTH ){ + sqlite3_result_error_toobig(context); + return; + } + assert( pBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */ + z = zHex = sqlite3_malloc(n*2 + 1); + if( zHex==0 ) return; + for(i=0; i>4)&0xf]; + *(z++) = hexdigits[c&0xf]; + } + *z = 0; + sqlite3_result_text(context, zHex, n*2, sqlite3_free); +} + +/* +** The zeroblob(N) function returns a zero-filled blob of size N bytes. +*/ +static void zeroblobFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + i64 n; + assert( argc==1 ); + n = sqlite3_value_int64(argv[0]); + if( n>SQLITE_MAX_LENGTH ){ + sqlite3_result_error_toobig(context); + }else{ + sqlite3_result_zeroblob(context, n); + } +} + +/* +** The replace() function. Three arguments are all strings: call +** them A, B, and C. The result is also a string which is derived +** from A by replacing every occurance of B with C. The match +** must be exact. Collating sequences are not used. +*/ +static void replaceFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const unsigned char *zStr; /* The input string A */ + const unsigned char *zPattern; /* The pattern string B */ + const unsigned char *zRep; /* The replacement string C */ + unsigned char *zOut; /* The output */ + int nStr; /* Size of zStr */ + int nPattern; /* Size of zPattern */ + int nRep; /* Size of zRep */ + i64 nOut; /* Maximum size of zOut */ + int loopLimit; /* Last zStr[] that might match zPattern[] */ + int i, j; /* Loop counters */ + + assert( argc==3 ); + zStr = sqlite3_value_text(argv[0]); + if( zStr==0 ) return; + nStr = sqlite3_value_bytes(argv[0]); + assert( zStr==sqlite3_value_text(argv[0]) ); /* No encoding change */ + zPattern = sqlite3_value_text(argv[1]); + if( zPattern==0 || zPattern[0]==0 ) return; + nPattern = sqlite3_value_bytes(argv[1]); + assert( zPattern==sqlite3_value_text(argv[1]) ); /* No encoding change */ + zRep = sqlite3_value_text(argv[2]); + if( zRep==0 ) return; + nRep = sqlite3_value_bytes(argv[2]); + assert( zRep==sqlite3_value_text(argv[2]) ); + nOut = nStr + 1; + assert( nOut=SQLITE_MAX_LENGTH ){ + sqlite3_result_error_toobig(context); + sqlite3_free(zOut); + return; + } + zOut = sqlite3_realloc(zOut, (int)nOut); + if( zOut==0 ){ + return; + } + memcpy(&zOut[j], zRep, nRep); + j += nRep; + i += nPattern-1; + } + } + assert( j+nStr-i+1==nOut ); + memcpy(&zOut[j], &zStr[i], nStr-i); + j += nStr - i; + assert( j<=nOut ); + zOut[j] = 0; + sqlite3_result_text(context, (char*)zOut, j, sqlite3_free); +} + +/* +** Implementation of the TRIM(), LTRIM(), and RTRIM() functions. +** The userdata is 0x1 for left trim, 0x2 for right trim, 0x3 for both. +*/ +static void trimFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + const unsigned char *zIn; /* Input string */ + const unsigned char *zCharSet; /* Set of characters to trim */ + int nIn; /* Number of bytes in input */ + int flags; /* 1: trimleft 2: trimright 3: trim */ + int i; /* Loop counter */ + unsigned char *aLen; /* Length of each character in zCharSet */ + const unsigned char **azChar; /* Individual characters in zCharSet */ + int nChar; /* Number of characters in zCharSet */ + + if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ + return; + } + zIn = sqlite3_value_text(argv[0]); + if( zIn==0 ) return; + nIn = sqlite3_value_bytes(argv[0]); + assert( zIn==sqlite3_value_text(argv[0]) ); + if( argc==1 ){ + static const unsigned char lenOne[] = { 1 }; + static const unsigned char *azOne[] = { (u8*)" " }; + nChar = 1; + aLen = (u8*)lenOne; + azChar = azOne; + zCharSet = 0; + }else if( (zCharSet = sqlite3_value_text(argv[1]))==0 ){ + return; + }else{ + const unsigned char *z; + for(z=zCharSet, nChar=0; *z; nChar++){ + SQLITE_SKIP_UTF8(z); + } + if( nChar>0 ){ + azChar = sqlite3_malloc( nChar*(sizeof(char*)+1) ); + if( azChar==0 ){ + return; + } + aLen = (unsigned char*)&azChar[nChar]; + for(z=zCharSet, nChar=0; *z; nChar++){ + azChar[nChar] = z; + SQLITE_SKIP_UTF8(z); + aLen[nChar] = z - azChar[nChar]; + } + } + } + if( nChar>0 ){ + flags = (int)sqlite3_user_data(context); + if( flags & 1 ){ + while( nIn>0 ){ + int len; + for(i=0; i=nChar ) break; + zIn += len; + nIn -= len; + } + } + if( flags & 2 ){ + while( nIn>0 ){ + int len; + for(i=0; i=nChar ) break; + nIn -= len; + } + } + if( zCharSet ){ + sqlite3_free(azChar); + } + } + sqlite3_result_text(context, (char*)zIn, nIn, SQLITE_TRANSIENT); +} + +#ifdef SQLITE_SOUNDEX +/* +** Compute the soundex encoding of a word. +*/ +static void soundexFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + char zResult[8]; + const u8 *zIn; + int i, j; + static const unsigned char iCode[] = { + 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, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0, + 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0, + 0, 0, 1, 2, 3, 0, 1, 2, 0, 0, 2, 2, 4, 5, 5, 0, + 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0, + }; + assert( argc==1 ); + zIn = (u8*)sqlite3_value_text(argv[0]); + if( zIn==0 ) zIn = (u8*)""; + for(i=0; zIn[i] && !isalpha(zIn[i]); i++){} + if( zIn[i] ){ + u8 prevcode = iCode[zIn[i]&0x7f]; + zResult[0] = toupper(zIn[i]); + for(j=1; j<4 && zIn[i]; i++){ + int code = iCode[zIn[i]&0x7f]; + if( code>0 ){ + if( code!=prevcode ){ + prevcode = code; + zResult[j++] = code + '0'; + } + }else{ + prevcode = 0; + } + } + while( j<4 ){ + zResult[j++] = '0'; + } + zResult[j] = 0; + sqlite3_result_text(context, zResult, 4, SQLITE_TRANSIENT); + }else{ + sqlite3_result_text(context, "?000", 4, SQLITE_STATIC); + } +} +#endif + +#ifndef SQLITE_OMIT_LOAD_EXTENSION +/* +** A function that loads a shared-library extension then returns NULL. +*/ +static void loadExt(sqlite3_context *context, int argc, sqlite3_value **argv){ + const char *zFile = (const char *)sqlite3_value_text(argv[0]); + const char *zProc; + sqlite3 *db = sqlite3_user_data(context); + char *zErrMsg = 0; + + if( argc==2 ){ + zProc = (const char *)sqlite3_value_text(argv[1]); + }else{ + zProc = 0; + } + if( zFile && sqlite3_load_extension(db, zFile, zProc, &zErrMsg) ){ + sqlite3_result_error(context, zErrMsg, -1); + sqlite3_free(zErrMsg); + } +} +#endif + +#ifdef SQLITE_TEST +/* +** This function generates a string of random characters. Used for +** generating test data. +*/ +static void randStr(sqlite3_context *context, int argc, sqlite3_value **argv){ + static const unsigned char zSrc[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789" + ".-!,:*^+=_|?/<> "; + int iMin, iMax, n, r, i; + unsigned char zBuf[1000]; + if( argc>=1 ){ + iMin = sqlite3_value_int(argv[0]); + if( iMin<0 ) iMin = 0; + if( iMin>=sizeof(zBuf) ) iMin = sizeof(zBuf)-1; + }else{ + iMin = 1; + } + if( argc>=2 ){ + iMax = sqlite3_value_int(argv[1]); + if( iMax=sizeof(zBuf) ) iMax = sizeof(zBuf)-1; + }else{ + iMax = 50; + } + n = iMin; + if( iMax>iMin ){ + sqlite3Randomness(sizeof(r), &r); + r &= 0x7fffffff; + n += r%(iMax + 1 - iMin); + } + assert( ncnt++; + if( type==SQLITE_INTEGER ){ + i64 v = sqlite3_value_int64(argv[0]); + p->rSum += v; + if( (p->approx|p->overflow)==0 ){ + i64 iNewSum = p->iSum + v; + int s1 = p->iSum >> (sizeof(i64)*8-1); + int s2 = v >> (sizeof(i64)*8-1); + int s3 = iNewSum >> (sizeof(i64)*8-1); + p->overflow = (s1&s2&~s3) | (~s1&~s2&s3); + p->iSum = iNewSum; + } + }else{ + p->rSum += sqlite3_value_double(argv[0]); + p->approx = 1; + } + } +} +static void sumFinalize(sqlite3_context *context){ + SumCtx *p; + p = sqlite3_aggregate_context(context, 0); + if( p && p->cnt>0 ){ + if( p->overflow ){ + sqlite3_result_error(context,"integer overflow",-1); + }else if( p->approx ){ + sqlite3_result_double(context, p->rSum); + }else{ + sqlite3_result_int64(context, p->iSum); + } + } +} +static void avgFinalize(sqlite3_context *context){ + SumCtx *p; + p = sqlite3_aggregate_context(context, 0); + if( p && p->cnt>0 ){ + sqlite3_result_double(context, p->rSum/(double)p->cnt); + } +} +static void totalFinalize(sqlite3_context *context){ + SumCtx *p; + p = sqlite3_aggregate_context(context, 0); + sqlite3_result_double(context, p ? p->rSum : 0.0); +} + +/* +** The following structure keeps track of state information for the +** count() aggregate function. +*/ +typedef struct CountCtx CountCtx; +struct CountCtx { + i64 n; +}; + +/* +** Routines to implement the count() aggregate function. +*/ +static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){ + CountCtx *p; + p = sqlite3_aggregate_context(context, sizeof(*p)); + if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0])) && p ){ + p->n++; + } +} +static void countFinalize(sqlite3_context *context){ + CountCtx *p; + p = sqlite3_aggregate_context(context, 0); + sqlite3_result_int64(context, p ? p->n : 0); +} + +/* +** Routines to implement min() and max() aggregate functions. +*/ +static void minmaxStep(sqlite3_context *context, int argc, sqlite3_value **argv){ + Mem *pArg = (Mem *)argv[0]; + Mem *pBest; + + if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; + pBest = (Mem *)sqlite3_aggregate_context(context, sizeof(*pBest)); + if( !pBest ) return; + + if( pBest->flags ){ + int max; + int cmp; + CollSeq *pColl = sqlite3GetFuncCollSeq(context); + /* This step function is used for both the min() and max() aggregates, + ** the only difference between the two being that the sense of the + ** comparison is inverted. For the max() aggregate, the + ** sqlite3_user_data() function returns (void *)-1. For min() it + ** returns (void *)db, where db is the sqlite3* database pointer. + ** Therefore the next statement sets variable 'max' to 1 for the max() + ** aggregate, or 0 for min(). + */ + max = sqlite3_user_data(context)!=0; + cmp = sqlite3MemCompare(pBest, pArg, pColl); + if( (max && cmp<0) || (!max && cmp>0) ){ + sqlite3VdbeMemCopy(pBest, pArg); + } + }else{ + sqlite3VdbeMemCopy(pBest, pArg); + } +} +static void minMaxFinalize(sqlite3_context *context){ + sqlite3_value *pRes; + pRes = (sqlite3_value *)sqlite3_aggregate_context(context, 0); + if( pRes ){ + if( pRes->flags ){ + sqlite3_result_value(context, pRes); + } + sqlite3VdbeMemRelease(pRes); + } +} + + +/* +** This function registered all of the above C functions as SQL +** functions. This should be the only routine in this file with +** external linkage. +*/ +void sqlite3RegisterBuiltinFunctions(sqlite3 *db){ + static const struct { + char *zName; + signed char nArg; + u8 argType; /* ff: db 1: 0, 2: 1, 3: 2,... N: N-1. */ + u8 eTextRep; /* 1: UTF-16. 0: UTF-8 */ + u8 needCollSeq; + void (*xFunc)(sqlite3_context*,int,sqlite3_value **); + } aFuncs[] = { + { "min", -1, 0, SQLITE_UTF8, 1, minmaxFunc }, + { "min", 0, 0, SQLITE_UTF8, 1, 0 }, + { "max", -1, 1, SQLITE_UTF8, 1, minmaxFunc }, + { "max", 0, 1, SQLITE_UTF8, 1, 0 }, + { "typeof", 1, 0, SQLITE_UTF8, 0, typeofFunc }, + { "length", 1, 0, SQLITE_UTF8, 0, lengthFunc }, + { "substr", 3, 0, SQLITE_UTF8, 0, substrFunc }, + { "abs", 1, 0, SQLITE_UTF8, 0, absFunc }, + { "round", 1, 0, SQLITE_UTF8, 0, roundFunc }, + { "round", 2, 0, SQLITE_UTF8, 0, roundFunc }, + { "upper", 1, 0, SQLITE_UTF8, 0, upperFunc }, + { "lower", 1, 0, SQLITE_UTF8, 0, lowerFunc }, + { "coalesce", -1, 0, SQLITE_UTF8, 0, ifnullFunc }, + { "coalesce", 0, 0, SQLITE_UTF8, 0, 0 }, + { "coalesce", 1, 0, SQLITE_UTF8, 0, 0 }, + { "hex", 1, 0, SQLITE_UTF8, 0, hexFunc }, + { "ifnull", 2, 0, SQLITE_UTF8, 1, ifnullFunc }, + { "random", -1, 0, SQLITE_UTF8, 0, randomFunc }, + { "randomblob", 1, 0, SQLITE_UTF8, 0, randomBlob }, + { "nullif", 2, 0, SQLITE_UTF8, 1, nullifFunc }, + { "sqlite_version", 0, 0, SQLITE_UTF8, 0, versionFunc}, + { "quote", 1, 0, SQLITE_UTF8, 0, quoteFunc }, + { "last_insert_rowid", 0, 0xff, SQLITE_UTF8, 0, last_insert_rowid }, + { "changes", 0, 0xff, SQLITE_UTF8, 0, changes }, + { "total_changes", 0, 0xff, SQLITE_UTF8, 0, total_changes }, + { "replace", 3, 0, SQLITE_UTF8, 0, replaceFunc }, + { "ltrim", 1, 1, SQLITE_UTF8, 0, trimFunc }, + { "ltrim", 2, 1, SQLITE_UTF8, 0, trimFunc }, + { "rtrim", 1, 2, SQLITE_UTF8, 0, trimFunc }, + { "rtrim", 2, 2, SQLITE_UTF8, 0, trimFunc }, + { "trim", 1, 3, SQLITE_UTF8, 0, trimFunc }, + { "trim", 2, 3, SQLITE_UTF8, 0, trimFunc }, + { "zeroblob", 1, 0, SQLITE_UTF8, 0, zeroblobFunc }, +#ifdef SQLITE_SOUNDEX + { "soundex", 1, 0, SQLITE_UTF8, 0, soundexFunc}, +#endif +#ifndef SQLITE_OMIT_LOAD_EXTENSION + { "load_extension", 1, 0xff, SQLITE_UTF8, 0, loadExt }, + { "load_extension", 2, 0xff, SQLITE_UTF8, 0, loadExt }, +#endif +#ifdef SQLITE_TEST + { "randstr", 2, 0, SQLITE_UTF8, 0, randStr }, + { "test_destructor", 1, 0xff, SQLITE_UTF8, 0, test_destructor}, + { "test_destructor_count", 0, 0, SQLITE_UTF8, 0, test_destructor_count}, + { "test_auxdata", -1, 0, SQLITE_UTF8, 0, test_auxdata}, + { "test_error", 1, 0, SQLITE_UTF8, 0, test_error}, +#endif + }; + static const struct { + char *zName; + signed char nArg; + u8 argType; + u8 needCollSeq; + void (*xStep)(sqlite3_context*,int,sqlite3_value**); + void (*xFinalize)(sqlite3_context*); + } aAggs[] = { + { "min", 1, 0, 1, minmaxStep, minMaxFinalize }, + { "max", 1, 1, 1, minmaxStep, minMaxFinalize }, + { "sum", 1, 0, 0, sumStep, sumFinalize }, + { "total", 1, 0, 0, sumStep, totalFinalize }, + { "avg", 1, 0, 0, sumStep, avgFinalize }, + { "count", 0, 0, 0, countStep, countFinalize }, + { "count", 1, 0, 0, countStep, countFinalize }, + }; + int i; + + for(i=0; ineedCollSeq = 1; + } + } + } +#ifndef SQLITE_OMIT_ALTERTABLE + sqlite3AlterFunctions(db); +#endif +#ifndef SQLITE_OMIT_PARSER + sqlite3AttachFunctions(db); +#endif + for(i=0; ineedCollSeq = 1; + } + } + } + sqlite3RegisterDateTimeFunctions(db); + if( !sqlite3MallocFailed() ){ + int rc = sqlite3_overload_function(db, "MATCH", 2); + assert( rc==SQLITE_NOMEM || rc==SQLITE_OK ); + if( rc==SQLITE_NOMEM ){ + sqlite3FailedMalloc(); + } + } +#ifdef SQLITE_SSE + (void)sqlite3SseFunctions(db); +#endif +#ifdef SQLITE_CASE_SENSITIVE_LIKE + sqlite3RegisterLikeFunctions(db, 1); +#else + sqlite3RegisterLikeFunctions(db, 0); +#endif +} + +/* +** Set the LIKEOPT flag on the 2-argument function with the given name. +*/ +static void setLikeOptFlag(sqlite3 *db, const char *zName, int flagVal){ + FuncDef *pDef; + pDef = sqlite3FindFunction(db, zName, strlen(zName), 2, SQLITE_UTF8, 0); + if( pDef ){ + pDef->flags = flagVal; + } +} + +/* +** Register the built-in LIKE and GLOB functions. The caseSensitive +** parameter determines whether or not the LIKE operator is case +** sensitive. GLOB is always case sensitive. +*/ +void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){ + struct compareInfo *pInfo; + if( caseSensitive ){ + pInfo = (struct compareInfo*)&likeInfoAlt; + }else{ + pInfo = (struct compareInfo*)&likeInfoNorm; + } + sqlite3CreateFunc(db, "like", 2, SQLITE_UTF8, pInfo, likeFunc, 0, 0); + sqlite3CreateFunc(db, "like", 3, SQLITE_UTF8, pInfo, likeFunc, 0, 0); + sqlite3CreateFunc(db, "glob", 2, SQLITE_UTF8, + (struct compareInfo*)&globInfo, likeFunc, 0,0); + setLikeOptFlag(db, "glob", SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE); + setLikeOptFlag(db, "like", + caseSensitive ? (SQLITE_FUNC_LIKE | SQLITE_FUNC_CASE) : SQLITE_FUNC_LIKE); +} + +/* +** pExpr points to an expression which implements a function. If +** it is appropriate to apply the LIKE optimization to that function +** then set aWc[0] through aWc[2] to the wildcard characters and +** return TRUE. If the function is not a LIKE-style function then +** return FALSE. +*/ +int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){ + FuncDef *pDef; + if( pExpr->op!=TK_FUNCTION || !pExpr->pList ){ + return 0; + } + if( pExpr->pList->nExpr!=2 ){ + return 0; + } + pDef = sqlite3FindFunction(db, (char*)pExpr->token.z, pExpr->token.n, 2, + SQLITE_UTF8, 0); + if( pDef==0 || (pDef->flags & SQLITE_FUNC_LIKE)==0 ){ + return 0; + } + + /* The memcpy() statement assumes that the wildcard characters are + ** the first three statements in the compareInfo structure. The + ** asserts() that follow verify that assumption + */ + memcpy(aWc, pDef->pUserData, 3); + assert( (char*)&likeInfoAlt == (char*)&likeInfoAlt.matchAll ); + assert( &((char*)&likeInfoAlt)[1] == (char*)&likeInfoAlt.matchOne ); + assert( &((char*)&likeInfoAlt)[2] == (char*)&likeInfoAlt.matchSet ); + *pIsNocase = (pDef->flags & SQLITE_FUNC_CASE)==0; + return 1; +} diff --git a/extensions/sqlite/sqlite-source/hash.c b/extensions/sqlite/sqlite-source/hash.c new file mode 100644 index 00000000..8f34caba --- /dev/null +++ b/extensions/sqlite/sqlite-source/hash.c @@ -0,0 +1,397 @@ +/* +** 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$ +*/ +#include "sqliteInt.h" +#include + +/* 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 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 ){ + 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; + if( pH->copyKey ){ + pH->xFree(new_elem->pKey); + } + 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; +} diff --git a/extensions/sqlite/sqlite-source/hash.h b/extensions/sqlite/sqlite-source/hash.h new file mode 100644 index 00000000..47076494 --- /dev/null +++ b/extensions/sqlite/sqlite-source/hash.h @@ -0,0 +1,111 @@ +/* +** 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$ +*/ +#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_ */ diff --git a/extensions/sqlite/sqlite-source/insert.c b/extensions/sqlite/sqlite-source/insert.c new file mode 100644 index 00000000..d99e3fa7 --- /dev/null +++ b/extensions/sqlite/sqlite-source/insert.c @@ -0,0 +1,1604 @@ +/* +** 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 INSERT statements in SQLite. +** +** $Id$ +*/ +#include "sqliteInt.h" + +/* +** Set P3 of the most recently inserted opcode to a column affinity +** string for index pIdx. A column affinity string has one character +** for each column in the table, according to the affinity of the column: +** +** Character Column affinity +** ------------------------------ +** 'a' TEXT +** 'b' NONE +** 'c' NUMERIC +** 'd' INTEGER +** 'e' REAL +*/ +void sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){ + if( !pIdx->zColAff ){ + /* The first time a column affinity string for a particular index is + ** required, it is allocated and populated here. It is then stored as + ** a member of the Index structure for subsequent use. + ** + ** The column affinity string will eventually be deleted by + ** sqliteDeleteIndex() when the Index structure itself is cleaned + ** up. + */ + int n; + Table *pTab = pIdx->pTable; + pIdx->zColAff = (char *)sqliteMalloc(pIdx->nColumn+1); + if( !pIdx->zColAff ){ + return; + } + for(n=0; nnColumn; n++){ + pIdx->zColAff[n] = pTab->aCol[pIdx->aiColumn[n]].affinity; + } + pIdx->zColAff[pIdx->nColumn] = '\0'; + } + + sqlite3VdbeChangeP3(v, -1, pIdx->zColAff, 0); +} + +/* +** Set P3 of the most recently inserted opcode to a column affinity +** string for table pTab. A column affinity string has one character +** for each column indexed by the index, according to the affinity of the +** column: +** +** Character Column affinity +** ------------------------------ +** 'a' TEXT +** 'b' NONE +** 'c' NUMERIC +** 'd' INTEGER +** 'e' REAL +*/ +void sqlite3TableAffinityStr(Vdbe *v, Table *pTab){ + /* The first time a column affinity string for a particular table + ** is required, it is allocated and populated here. It is then + ** stored as a member of the Table structure for subsequent use. + ** + ** The column affinity string will eventually be deleted by + ** sqlite3DeleteTable() when the Table structure itself is cleaned up. + */ + if( !pTab->zColAff ){ + char *zColAff; + int i; + + zColAff = (char *)sqliteMalloc(pTab->nCol+1); + if( !zColAff ){ + return; + } + + for(i=0; inCol; i++){ + zColAff[i] = pTab->aCol[i].affinity; + } + zColAff[pTab->nCol] = '\0'; + + pTab->zColAff = zColAff; + } + + sqlite3VdbeChangeP3(v, -1, pTab->zColAff, 0); +} + +/* +** Return non-zero if SELECT statement p opens the table with rootpage +** iTab in database iDb. This is used to see if a statement of the form +** "INSERT INTO SELECT ..." can run without using temporary +** table for the results of the SELECT. +** +** No checking is done for sub-selects that are part of expressions. +*/ +static int selectReadsTable(Select *p, Schema *pSchema, int iTab){ + int i; + struct SrcList_item *pItem; + if( p->pSrc==0 ) return 0; + for(i=0, pItem=p->pSrc->a; ipSrc->nSrc; i++, pItem++){ + if( pItem->pSelect ){ + if( selectReadsTable(pItem->pSelect, pSchema, iTab) ) return 1; + }else{ + if( pItem->pTab->pSchema==pSchema && pItem->pTab->tnum==iTab ) return 1; + } + } + return 0; +} + +#ifndef SQLITE_OMIT_AUTOINCREMENT +/* +** Write out code to initialize the autoincrement logic. This code +** looks up the current autoincrement value in the sqlite_sequence +** table and stores that value in a memory cell. Code generated by +** autoIncStep() will keep that memory cell holding the largest +** rowid value. Code generated by autoIncEnd() will write the new +** largest value of the counter back into the sqlite_sequence table. +** +** This routine returns the index of the mem[] cell that contains +** the maximum rowid counter. +** +** Two memory cells are allocated. The next memory cell after the +** one returned holds the rowid in sqlite_sequence where we will +** write back the revised maximum rowid. +*/ +static int autoIncBegin( + Parse *pParse, /* Parsing context */ + int iDb, /* Index of the database holding pTab */ + Table *pTab /* The table we are writing to */ +){ + int memId = 0; + if( pTab->autoInc ){ + Vdbe *v = pParse->pVdbe; + Db *pDb = &pParse->db->aDb[iDb]; + int iCur = pParse->nTab; + int addr; + assert( v ); + addr = sqlite3VdbeCurrentAddr(v); + memId = pParse->nMem+1; + pParse->nMem += 2; + sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenRead); + sqlite3VdbeAddOp(v, OP_Rewind, iCur, addr+13); + sqlite3VdbeAddOp(v, OP_Column, iCur, 0); + sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0); + sqlite3VdbeAddOp(v, OP_Ne, 0x100, addr+12); + sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0); + sqlite3VdbeAddOp(v, OP_MemStore, memId-1, 1); + sqlite3VdbeAddOp(v, OP_Column, iCur, 1); + sqlite3VdbeAddOp(v, OP_MemStore, memId, 1); + sqlite3VdbeAddOp(v, OP_Goto, 0, addr+13); + sqlite3VdbeAddOp(v, OP_Next, iCur, addr+4); + sqlite3VdbeAddOp(v, OP_Close, iCur, 0); + } + return memId; +} + +/* +** Update the maximum rowid for an autoincrement calculation. +** +** This routine should be called when the top of the stack holds a +** new rowid that is about to be inserted. If that new rowid is +** larger than the maximum rowid in the memId memory cell, then the +** memory cell is updated. The stack is unchanged. +*/ +static void autoIncStep(Parse *pParse, int memId){ + if( memId>0 ){ + sqlite3VdbeAddOp(pParse->pVdbe, OP_MemMax, memId, 0); + } +} + +/* +** After doing one or more inserts, the maximum rowid is stored +** in mem[memId]. Generate code to write this value back into the +** the sqlite_sequence table. +*/ +static void autoIncEnd( + Parse *pParse, /* The parsing context */ + int iDb, /* Index of the database holding pTab */ + Table *pTab, /* Table we are inserting into */ + int memId /* Memory cell holding the maximum rowid */ +){ + if( pTab->autoInc ){ + int iCur = pParse->nTab; + Vdbe *v = pParse->pVdbe; + Db *pDb = &pParse->db->aDb[iDb]; + int addr; + assert( v ); + addr = sqlite3VdbeCurrentAddr(v); + sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); + sqlite3VdbeAddOp(v, OP_MemLoad, memId-1, 0); + sqlite3VdbeAddOp(v, OP_NotNull, -1, addr+7); + sqlite3VdbeAddOp(v, OP_Pop, 1, 0); + sqlite3VdbeAddOp(v, OP_NewRowid, iCur, 0); + sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0); + sqlite3VdbeAddOp(v, OP_MemLoad, memId, 0); + sqlite3VdbeAddOp(v, OP_MakeRecord, 2, 0); + sqlite3VdbeAddOp(v, OP_Insert, iCur, OPFLAG_APPEND); + sqlite3VdbeAddOp(v, OP_Close, iCur, 0); + } +} +#else +/* +** If SQLITE_OMIT_AUTOINCREMENT is defined, then the three routines +** above are all no-ops +*/ +# define autoIncBegin(A,B,C) (0) +# define autoIncStep(A,B) +# define autoIncEnd(A,B,C,D) +#endif /* SQLITE_OMIT_AUTOINCREMENT */ + + +/* Forward declaration */ +static int xferOptimization( + Parse *pParse, /* Parser context */ + Table *pDest, /* The table we are inserting into */ + Select *pSelect, /* A SELECT statement to use as the data source */ + int onError, /* How to handle constraint errors */ + int iDbDest /* The database of pDest */ +); + +/* +** This routine is call to handle SQL of the following forms: +** +** insert into TABLE (IDLIST) values(EXPRLIST) +** insert into TABLE (IDLIST) select +** +** The IDLIST following the table name is always optional. If omitted, +** then a list of all columns for the table is substituted. The IDLIST +** appears in the pColumn parameter. pColumn is NULL if IDLIST is omitted. +** +** The pList parameter holds EXPRLIST in the first form of the INSERT +** statement above, and pSelect is NULL. For the second form, pList is +** NULL and pSelect is a pointer to the select statement used to generate +** data for the insert. +** +** The code generated follows one of four templates. For a simple +** select with data coming from a VALUES clause, the code executes +** once straight down through. The template looks like this: +** +** open write cursor to and its indices +** puts VALUES clause expressions onto the stack +** write the resulting record into
+** cleanup +** +** The three remaining templates assume the statement is of the form +** +** INSERT INTO
SELECT ... +** +** If the SELECT clause is of the restricted form "SELECT * FROM " - +** in other words if the SELECT pulls all columns from a single table +** and there is no WHERE or LIMIT or GROUP BY or ORDER BY clauses, and +** if and are distinct tables but have identical +** schemas, including all the same indices, then a special optimization +** is invoked that copies raw records from over to . +** See the xferOptimization() function for the implementation of this +** template. This is the second template. +** +** open a write cursor to
+** open read cursor on +** transfer all records in over to
+** close cursors +** foreach index on
+** open a write cursor on the
index +** open a read cursor on the corresponding index +** transfer all records from the read to the write cursors +** close cursors +** end foreach +** +** The third template is for when the second template does not apply +** and the SELECT clause does not read from
at any time. +** The generated code follows this template: +** +** goto B +** A: setup for the SELECT +** loop over the rows in the SELECT +** gosub C +** end loop +** cleanup after the SELECT +** goto D +** B: open write cursor to
and its indices +** goto A +** C: insert the select result into
+** return +** D: cleanup +** +** The fourth template is used if the insert statement takes its +** values from a SELECT but the data is being inserted into a table +** that is also read as part of the SELECT. In the third form, +** we have to use a intermediate table to store the results of +** the select. The template is like this: +** +** goto B +** A: setup for the SELECT +** loop over the tables in the SELECT +** gosub C +** end loop +** cleanup after the SELECT +** goto D +** C: insert the select result into the intermediate table +** return +** B: open a cursor to an intermediate table +** goto A +** D: open write cursor to
and its indices +** loop over the intermediate table +** transfer values form intermediate table into
+** end the loop +** cleanup +*/ +void sqlite3Insert( + Parse *pParse, /* Parser context */ + SrcList *pTabList, /* Name of table into which we are inserting */ + ExprList *pList, /* List of values to be inserted */ + Select *pSelect, /* A SELECT statement to use as the data source */ + IdList *pColumn, /* Column names corresponding to IDLIST. */ + int onError /* How to handle constraint errors */ +){ + Table *pTab; /* The table to insert into */ + char *zTab; /* Name of the table into which we are inserting */ + const char *zDb; /* Name of the database holding this table */ + int i, j, idx; /* Loop counters */ + Vdbe *v; /* Generate code into this virtual machine */ + Index *pIdx; /* For looping over indices of the table */ + int nColumn; /* Number of columns in the data */ + int base = 0; /* VDBE Cursor number for pTab */ + int iCont=0,iBreak=0; /* Beginning and end of the loop over srcTab */ + sqlite3 *db; /* The main database structure */ + int keyColumn = -1; /* Column that is the INTEGER PRIMARY KEY */ + int endOfLoop; /* Label for the end of the insertion loop */ + int useTempTable = 0; /* Store SELECT results in intermediate table */ + int srcTab = 0; /* Data comes from this temporary cursor if >=0 */ + int iSelectLoop = 0; /* Address of code that implements the SELECT */ + int iCleanup = 0; /* Address of the cleanup code */ + int iInsertBlock = 0; /* Address of the subroutine used to insert data */ + int iCntMem = 0; /* Memory cell used for the row counter */ + int newIdx = -1; /* Cursor for the NEW table */ + Db *pDb; /* The database containing table being inserted into */ + int counterMem = 0; /* Memory cell holding AUTOINCREMENT counter */ + int appendFlag = 0; /* True if the insert is likely to be an append */ + int iDb; + + int nHidden = 0; + +#ifndef SQLITE_OMIT_TRIGGER + int isView; /* True if attempting to insert into a view */ + int triggers_exist = 0; /* True if there are FOR EACH ROW triggers */ +#endif + + if( pParse->nErr || sqlite3MallocFailed() ){ + goto insert_cleanup; + } + db = pParse->db; + + /* Locate the table into which we will be inserting new information. + */ + assert( pTabList->nSrc==1 ); + zTab = pTabList->a[0].zName; + if( zTab==0 ) goto insert_cleanup; + pTab = sqlite3SrcListLookup(pParse, pTabList); + if( pTab==0 ){ + goto insert_cleanup; + } + iDb = sqlite3SchemaToIndex(db, pTab->pSchema); + assert( iDbnDb ); + pDb = &db->aDb[iDb]; + zDb = pDb->zName; + if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){ + goto insert_cleanup; + } + + /* Figure out if we have any triggers and if the table being + ** inserted into is a view + */ +#ifndef SQLITE_OMIT_TRIGGER + triggers_exist = sqlite3TriggersExist(pParse, pTab, TK_INSERT, 0); + isView = pTab->pSelect!=0; +#else +# define triggers_exist 0 +# define isView 0 +#endif +#ifdef SQLITE_OMIT_VIEW +# undef isView +# define isView 0 +#endif + + /* Ensure that: + * (a) the table is not read-only, + * (b) that if it is a view then ON INSERT triggers exist + */ + if( sqlite3IsReadOnly(pParse, pTab, triggers_exist) ){ + goto insert_cleanup; + } + assert( pTab!=0 ); + + /* If pTab is really a view, make sure it has been initialized. + ** ViewGetColumnNames() is a no-op if pTab is not a view (or virtual + ** module table). + */ + if( sqlite3ViewGetColumnNames(pParse, pTab) ){ + goto insert_cleanup; + } + + /* Allocate a VDBE + */ + v = sqlite3GetVdbe(pParse); + if( v==0 ) goto insert_cleanup; + if( pParse->nested==0 ) sqlite3VdbeCountChanges(v); + sqlite3BeginWriteOperation(pParse, pSelect || triggers_exist, iDb); + + /* if there are row triggers, allocate a temp table for new.* references. */ + if( triggers_exist ){ + newIdx = pParse->nTab++; + } + +#ifndef SQLITE_OMIT_XFER_OPT + /* If the statement is of the form + ** + ** INSERT INTO SELECT * FROM ; + ** + ** Then special optimizations can be applied that make the transfer + ** very fast and which reduce fragmentation of indices. + */ + if( pColumn==0 && xferOptimization(pParse, pTab, pSelect, onError, iDb) ){ + assert( !triggers_exist ); + assert( pList==0 ); + goto insert_cleanup; + } +#endif /* SQLITE_OMIT_XFER_OPT */ + + /* If this is an AUTOINCREMENT table, look up the sequence number in the + ** sqlite_sequence table and store it in memory cell counterMem. Also + ** remember the rowid of the sqlite_sequence table entry in memory cell + ** counterRowid. + */ + counterMem = autoIncBegin(pParse, iDb, pTab); + + /* Figure out how many columns of data are supplied. If the data + ** is coming from a SELECT statement, then this step also generates + ** all the code to implement the SELECT statement and invoke a subroutine + ** to process each row of the result. (Template 2.) If the SELECT + ** statement uses the the table that is being inserted into, then the + ** subroutine is also coded here. That subroutine stores the SELECT + ** results in a temporary table. (Template 3.) + */ + if( pSelect ){ + /* Data is coming from a SELECT. Generate code to implement that SELECT + */ + int rc, iInitCode; + iInitCode = sqlite3VdbeAddOp(v, OP_Goto, 0, 0); + iSelectLoop = sqlite3VdbeCurrentAddr(v); + iInsertBlock = sqlite3VdbeMakeLabel(v); + + /* Resolve the expressions in the SELECT statement and execute it. */ + rc = sqlite3Select(pParse, pSelect, SRT_Subroutine, iInsertBlock,0,0,0,0); + if( rc || pParse->nErr || sqlite3MallocFailed() ){ + goto insert_cleanup; + } + + iCleanup = sqlite3VdbeMakeLabel(v); + sqlite3VdbeAddOp(v, OP_Goto, 0, iCleanup); + assert( pSelect->pEList ); + nColumn = pSelect->pEList->nExpr; + + /* Set useTempTable to TRUE if the result of the SELECT statement + ** should be written into a temporary table. Set to FALSE if each + ** row of the SELECT can be written directly into the result table. + ** + ** A temp table must be used if the table being updated is also one + ** of the tables being read by the SELECT statement. Also use a + ** temp table in the case of row triggers. + */ + if( triggers_exist || selectReadsTable(pSelect,pTab->pSchema,pTab->tnum) ){ + useTempTable = 1; + } + + if( useTempTable ){ + /* Generate the subroutine that SELECT calls to process each row of + ** the result. Store the result in a temporary table + */ + srcTab = pParse->nTab++; + sqlite3VdbeResolveLabel(v, iInsertBlock); + sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); + sqlite3VdbeAddOp(v, OP_NewRowid, srcTab, 0); + sqlite3VdbeAddOp(v, OP_Pull, 1, 0); + sqlite3VdbeAddOp(v, OP_Insert, srcTab, OPFLAG_APPEND); + sqlite3VdbeAddOp(v, OP_Return, 0, 0); + + /* The following code runs first because the GOTO at the very top + ** of the program jumps to it. Create the temporary table, then jump + ** back up and execute the SELECT code above. + */ + sqlite3VdbeJumpHere(v, iInitCode); + sqlite3VdbeAddOp(v, OP_OpenEphemeral, srcTab, 0); + sqlite3VdbeAddOp(v, OP_SetNumColumns, srcTab, nColumn); + sqlite3VdbeAddOp(v, OP_Goto, 0, iSelectLoop); + sqlite3VdbeResolveLabel(v, iCleanup); + }else{ + sqlite3VdbeJumpHere(v, iInitCode); + } + }else{ + /* This is the case if the data for the INSERT is coming from a VALUES + ** clause + */ + NameContext sNC; + memset(&sNC, 0, sizeof(sNC)); + sNC.pParse = pParse; + srcTab = -1; + useTempTable = 0; + nColumn = pList ? pList->nExpr : 0; + for(i=0; ia[i].pExpr) ){ + goto insert_cleanup; + } + } + } + + /* Make sure the number of columns in the source data matches the number + ** of columns to be inserted into the table. + */ + if( IsVirtual(pTab) ){ + for(i=0; inCol; i++){ + nHidden += (IsHiddenColumn(&pTab->aCol[i]) ? 1 : 0); + } + } + if( pColumn==0 && nColumn && nColumn!=(pTab->nCol-nHidden) ){ + sqlite3ErrorMsg(pParse, + "table %S has %d columns but %d values were supplied", + pTabList, 0, pTab->nCol, nColumn); + goto insert_cleanup; + } + if( pColumn!=0 && nColumn!=pColumn->nId ){ + sqlite3ErrorMsg(pParse, "%d values for %d columns", nColumn, pColumn->nId); + goto insert_cleanup; + } + + /* If the INSERT statement included an IDLIST term, then make sure + ** all elements of the IDLIST really are columns of the table and + ** remember the column indices. + ** + ** If the table has an INTEGER PRIMARY KEY column and that column + ** is named in the IDLIST, then record in the keyColumn variable + ** the index into IDLIST of the primary key column. keyColumn is + ** the index of the primary key as it appears in IDLIST, not as + ** is appears in the original table. (The index of the primary + ** key in the original table is pTab->iPKey.) + */ + if( pColumn ){ + for(i=0; inId; i++){ + pColumn->a[i].idx = -1; + } + for(i=0; inId; i++){ + for(j=0; jnCol; j++){ + if( sqlite3StrICmp(pColumn->a[i].zName, pTab->aCol[j].zName)==0 ){ + pColumn->a[i].idx = j; + if( j==pTab->iPKey ){ + keyColumn = i; + } + break; + } + } + if( j>=pTab->nCol ){ + if( sqlite3IsRowid(pColumn->a[i].zName) ){ + keyColumn = i; + }else{ + sqlite3ErrorMsg(pParse, "table %S has no column named %s", + pTabList, 0, pColumn->a[i].zName); + pParse->nErr++; + goto insert_cleanup; + } + } + } + } + + /* If there is no IDLIST term but the table has an integer primary + ** key, the set the keyColumn variable to the primary key column index + ** in the original table definition. + */ + if( pColumn==0 && nColumn>0 ){ + keyColumn = pTab->iPKey; + } + + /* Open the temp table for FOR EACH ROW triggers + */ + if( triggers_exist ){ + sqlite3VdbeAddOp(v, OP_OpenPseudo, newIdx, 0); + sqlite3VdbeAddOp(v, OP_SetNumColumns, newIdx, pTab->nCol); + } + + /* Initialize the count of rows to be inserted + */ + if( db->flags & SQLITE_CountRows ){ + iCntMem = pParse->nMem++; + sqlite3VdbeAddOp(v, OP_MemInt, 0, iCntMem); + } + + /* Open tables and indices if there are no row triggers */ + if( !triggers_exist ){ + base = pParse->nTab; + sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite); + } + + /* If the data source is a temporary table, then we have to create + ** a loop because there might be multiple rows of data. If the data + ** source is a subroutine call from the SELECT statement, then we need + ** to launch the SELECT statement processing. + */ + if( useTempTable ){ + iBreak = sqlite3VdbeMakeLabel(v); + sqlite3VdbeAddOp(v, OP_Rewind, srcTab, iBreak); + iCont = sqlite3VdbeCurrentAddr(v); + }else if( pSelect ){ + sqlite3VdbeAddOp(v, OP_Goto, 0, iSelectLoop); + sqlite3VdbeResolveLabel(v, iInsertBlock); + } + + /* Run the BEFORE and INSTEAD OF triggers, if there are any + */ + endOfLoop = sqlite3VdbeMakeLabel(v); + if( triggers_exist & TRIGGER_BEFORE ){ + + /* build the NEW.* reference row. Note that if there is an INTEGER + ** PRIMARY KEY into which a NULL is being inserted, that NULL will be + ** translated into a unique ID for the row. But on a BEFORE trigger, + ** we do not know what the unique ID will be (because the insert has + ** not happened yet) so we substitute a rowid of -1 + */ + if( keyColumn<0 ){ + sqlite3VdbeAddOp(v, OP_Integer, -1, 0); + }else if( useTempTable ){ + sqlite3VdbeAddOp(v, OP_Column, srcTab, keyColumn); + }else{ + assert( pSelect==0 ); /* Otherwise useTempTable is true */ + sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr); + sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3); + sqlite3VdbeAddOp(v, OP_Pop, 1, 0); + sqlite3VdbeAddOp(v, OP_Integer, -1, 0); + sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0); + } + + /* Cannot have triggers on a virtual table. If it were possible, + ** this block would have to account for hidden column. + */ + assert(!IsVirtual(pTab)); + + /* Create the new column data + */ + for(i=0; inCol; i++){ + if( pColumn==0 ){ + j = i; + }else{ + for(j=0; jnId; j++){ + if( pColumn->a[j].idx==i ) break; + } + } + if( pColumn && j>=pColumn->nId ){ + sqlite3ExprCode(pParse, pTab->aCol[i].pDflt); + }else if( useTempTable ){ + sqlite3VdbeAddOp(v, OP_Column, srcTab, j); + }else{ + assert( pSelect==0 ); /* Otherwise useTempTable is true */ + sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr); + } + } + sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0); + + /* If this is an INSERT on a view with an INSTEAD OF INSERT trigger, + ** do not attempt any conversions before assembling the record. + ** If this is a real table, attempt conversions as required by the + ** table column affinities. + */ + if( !isView ){ + sqlite3TableAffinityStr(v, pTab); + } + sqlite3VdbeAddOp(v, OP_Insert, newIdx, 0); + + /* Fire BEFORE or INSTEAD OF triggers */ + if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TRIGGER_BEFORE, pTab, + newIdx, -1, onError, endOfLoop) ){ + goto insert_cleanup; + } + } + + /* If any triggers exists, the opening of tables and indices is deferred + ** until now. + */ + if( triggers_exist && !isView ){ + base = pParse->nTab; + sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite); + } + + /* Push the record number for the new entry onto the stack. The + ** record number is a randomly generate integer created by NewRowid + ** except when the table has an INTEGER PRIMARY KEY column, in which + ** case the record number is the same as that column. + */ + if( !isView ){ + if( IsVirtual(pTab) ){ + /* The row that the VUpdate opcode will delete: none */ + sqlite3VdbeAddOp(v, OP_Null, 0, 0); + } + if( keyColumn>=0 ){ + if( useTempTable ){ + sqlite3VdbeAddOp(v, OP_Column, srcTab, keyColumn); + }else if( pSelect ){ + sqlite3VdbeAddOp(v, OP_Dup, nColumn - keyColumn - 1, 1); + }else{ + VdbeOp *pOp; + sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr); + pOp = sqlite3VdbeGetOp(v, sqlite3VdbeCurrentAddr(v) - 1); + if( pOp && pOp->opcode==OP_Null ){ + appendFlag = 1; + pOp->opcode = OP_NewRowid; + pOp->p1 = base; + pOp->p2 = counterMem; + } + } + /* If the PRIMARY KEY expression is NULL, then use OP_NewRowid + ** to generate a unique primary key value. + */ + if( !appendFlag ){ + sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3); + sqlite3VdbeAddOp(v, OP_Pop, 1, 0); + sqlite3VdbeAddOp(v, OP_NewRowid, base, counterMem); + sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0); + } + }else if( IsVirtual(pTab) ){ + sqlite3VdbeAddOp(v, OP_Null, 0, 0); + }else{ + sqlite3VdbeAddOp(v, OP_NewRowid, base, counterMem); + appendFlag = 1; + } + autoIncStep(pParse, counterMem); + + /* Push onto the stack, data for all columns of the new entry, beginning + ** with the first column. + */ + nHidden = 0; + for(i=0; inCol; i++){ + if( i==pTab->iPKey ){ + /* The value of the INTEGER PRIMARY KEY column is always a NULL. + ** Whenever this column is read, the record number will be substituted + ** in its place. So will fill this column with a NULL to avoid + ** taking up data space with information that will never be used. */ + sqlite3VdbeAddOp(v, OP_Null, 0, 0); + continue; + } + if( pColumn==0 ){ + if( IsHiddenColumn(&pTab->aCol[i]) ){ + assert( IsVirtual(pTab) ); + j = -1; + nHidden++; + }else{ + j = i - nHidden; + } + }else{ + for(j=0; jnId; j++){ + if( pColumn->a[j].idx==i ) break; + } + } + if( j<0 || nColumn==0 || (pColumn && j>=pColumn->nId) ){ + sqlite3ExprCode(pParse, pTab->aCol[i].pDflt); + }else if( useTempTable ){ + sqlite3VdbeAddOp(v, OP_Column, srcTab, j); + }else if( pSelect ){ + sqlite3VdbeAddOp(v, OP_Dup, i+nColumn-j+IsVirtual(pTab), 1); + }else{ + sqlite3ExprCode(pParse, pList->a[j].pExpr); + } + } + + /* Generate code to check constraints and generate index keys and + ** do the insertion. + */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( IsVirtual(pTab) ){ + pParse->pVirtualLock = pTab; + sqlite3VdbeOp3(v, OP_VUpdate, 1, pTab->nCol+2, + (const char*)pTab->pVtab, P3_VTAB); + }else +#endif + { + sqlite3GenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0, + 0, onError, endOfLoop); + sqlite3CompleteInsertion(pParse, pTab, base, 0,0,0, + (triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1, + appendFlag); + } + } + + /* Update the count of rows that are inserted + */ + if( (db->flags & SQLITE_CountRows)!=0 ){ + sqlite3VdbeAddOp(v, OP_MemIncr, 1, iCntMem); + } + + if( triggers_exist ){ + /* Close all tables opened */ + if( !isView ){ + sqlite3VdbeAddOp(v, OP_Close, base, 0); + for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){ + sqlite3VdbeAddOp(v, OP_Close, idx+base, 0); + } + } + + /* Code AFTER triggers */ + if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TRIGGER_AFTER, pTab, + newIdx, -1, onError, endOfLoop) ){ + goto insert_cleanup; + } + } + + /* The bottom of the loop, if the data source is a SELECT statement + */ + sqlite3VdbeResolveLabel(v, endOfLoop); + if( useTempTable ){ + sqlite3VdbeAddOp(v, OP_Next, srcTab, iCont); + sqlite3VdbeResolveLabel(v, iBreak); + sqlite3VdbeAddOp(v, OP_Close, srcTab, 0); + }else if( pSelect ){ + sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0); + sqlite3VdbeAddOp(v, OP_Return, 0, 0); + sqlite3VdbeResolveLabel(v, iCleanup); + } + + if( !triggers_exist && !IsVirtual(pTab) ){ + /* Close all tables opened */ + sqlite3VdbeAddOp(v, OP_Close, base, 0); + for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){ + sqlite3VdbeAddOp(v, OP_Close, idx+base, 0); + } + } + + /* Update the sqlite_sequence table by storing the content of the + ** counter value in memory counterMem back into the sqlite_sequence + ** table. + */ + autoIncEnd(pParse, iDb, pTab, counterMem); + + /* + ** Return the number of rows inserted. 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, iCntMem, 0); + sqlite3VdbeAddOp(v, OP_Callback, 1, 0); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows inserted", P3_STATIC); + } + +insert_cleanup: + sqlite3SrcListDelete(pTabList); + sqlite3ExprListDelete(pList); + sqlite3SelectDelete(pSelect); + sqlite3IdListDelete(pColumn); +} + +/* +** Generate code to do a constraint check prior to an INSERT or an UPDATE. +** +** When this routine is called, the stack contains (from bottom to top) +** the following values: +** +** 1. The rowid of the row to be updated before the update. This +** value is omitted unless we are doing an UPDATE that involves a +** change to the record number. +** +** 2. The rowid of the row after the update. +** +** 3. The data in the first column of the entry after the update. +** +** i. Data from middle columns... +** +** N. The data in the last column of the entry after the update. +** +** The old rowid shown as entry (1) above is omitted unless both isUpdate +** and rowidChng are 1. isUpdate is true for UPDATEs and false for +** INSERTs and rowidChng is true if the record number is being changed. +** +** The code generated by this routine pushes additional entries onto +** the stack which are the keys for new index entries for the new record. +** The order of index keys is the same as the order of the indices on +** the pTable->pIndex list. A key is only created for index i if +** aIdxUsed!=0 and aIdxUsed[i]!=0. +** +** This routine also generates code to check constraints. NOT NULL, +** CHECK, and UNIQUE constraints are all checked. If a constraint fails, +** then the appropriate action is performed. There are five possible +** actions: ROLLBACK, ABORT, FAIL, REPLACE, and IGNORE. +** +** Constraint type Action What Happens +** --------------- ---------- ---------------------------------------- +** any ROLLBACK The current transaction is rolled back and +** sqlite3_exec() returns immediately with a +** return code of SQLITE_CONSTRAINT. +** +** any ABORT Back out changes from the current command +** only (do not do a complete rollback) then +** cause sqlite3_exec() to return immediately +** with SQLITE_CONSTRAINT. +** +** any FAIL Sqlite_exec() returns immediately with a +** return code of SQLITE_CONSTRAINT. The +** transaction is not rolled back and any +** prior changes are retained. +** +** any IGNORE The record number and data is popped from +** the stack and there is an immediate jump +** to label ignoreDest. +** +** NOT NULL REPLACE The NULL value is replace by the default +** value for that column. If the default value +** is NULL, the action is the same as ABORT. +** +** UNIQUE REPLACE The other row that conflicts with the row +** being inserted is removed. +** +** CHECK REPLACE Illegal. The results in an exception. +** +** Which action to take is determined by the overrideError parameter. +** Or if overrideError==OE_Default, then the pParse->onError parameter +** is used. Or if pParse->onError==OE_Default then the onError value +** for the constraint is used. +** +** The calling routine must open a read/write cursor for pTab with +** cursor number "base". All indices of pTab must also have open +** read/write cursors with cursor number base+i for the i-th cursor. +** Except, if there is no possibility of a REPLACE action then +** cursors do not need to be open for indices where aIdxUsed[i]==0. +** +** If the isUpdate flag is true, it means that the "base" cursor is +** initially pointing to an entry that is being updated. The isUpdate +** flag causes extra code to be generated so that the "base" cursor +** is still pointing at the same entry after the routine returns. +** Without the isUpdate flag, the "base" cursor might be moved. +*/ +void sqlite3GenerateConstraintChecks( + Parse *pParse, /* The parser context */ + Table *pTab, /* the table into which we are inserting */ + int base, /* Index of a read/write cursor pointing at pTab */ + char *aIdxUsed, /* Which indices are used. NULL means all are used */ + int rowidChng, /* True if the record number will change */ + int isUpdate, /* True for UPDATE, False for INSERT */ + int overrideError, /* Override onError to this if not OE_Default */ + int ignoreDest /* Jump to this label on an OE_Ignore resolution */ +){ + int i; + Vdbe *v; + int nCol; + int onError; + int addr; + int extra; + int iCur; + Index *pIdx; + int seenReplace = 0; + int jumpInst1=0, jumpInst2; + int hasTwoRowids = (isUpdate && rowidChng); + + v = sqlite3GetVdbe(pParse); + assert( v!=0 ); + assert( pTab->pSelect==0 ); /* This table is not a VIEW */ + nCol = pTab->nCol; + + /* Test all NOT NULL constraints. + */ + for(i=0; iiPKey ){ + continue; + } + onError = pTab->aCol[i].notNull; + if( onError==OE_None ) continue; + if( overrideError!=OE_Default ){ + onError = overrideError; + }else if( onError==OE_Default ){ + onError = OE_Abort; + } + if( onError==OE_Replace && pTab->aCol[i].pDflt==0 ){ + onError = OE_Abort; + } + sqlite3VdbeAddOp(v, OP_Dup, nCol-1-i, 1); + addr = sqlite3VdbeAddOp(v, OP_NotNull, 1, 0); + assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail + || onError==OE_Ignore || onError==OE_Replace ); + switch( onError ){ + case OE_Rollback: + case OE_Abort: + case OE_Fail: { + char *zMsg = 0; + sqlite3VdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, onError); + sqlite3SetString(&zMsg, pTab->zName, ".", pTab->aCol[i].zName, + " may not be NULL", (char*)0); + sqlite3VdbeChangeP3(v, -1, zMsg, P3_DYNAMIC); + break; + } + case OE_Ignore: { + sqlite3VdbeAddOp(v, OP_Pop, nCol+1+hasTwoRowids, 0); + sqlite3VdbeAddOp(v, OP_Goto, 0, ignoreDest); + break; + } + case OE_Replace: { + sqlite3ExprCode(pParse, pTab->aCol[i].pDflt); + sqlite3VdbeAddOp(v, OP_Push, nCol-i, 0); + break; + } + } + sqlite3VdbeJumpHere(v, addr); + } + + /* Test all CHECK constraints + */ +#ifndef SQLITE_OMIT_CHECK + if( pTab->pCheck && (pParse->db->flags & SQLITE_IgnoreChecks)==0 ){ + int allOk = sqlite3VdbeMakeLabel(v); + assert( pParse->ckOffset==0 ); + pParse->ckOffset = nCol; + sqlite3ExprIfTrue(pParse, pTab->pCheck, allOk, 1); + assert( pParse->ckOffset==nCol ); + pParse->ckOffset = 0; + onError = overrideError!=OE_Default ? overrideError : OE_Abort; + if( onError==OE_Ignore || onError==OE_Replace ){ + sqlite3VdbeAddOp(v, OP_Pop, nCol+1+hasTwoRowids, 0); + sqlite3VdbeAddOp(v, OP_Goto, 0, ignoreDest); + }else{ + sqlite3VdbeAddOp(v, OP_Halt, SQLITE_CONSTRAINT, onError); + } + sqlite3VdbeResolveLabel(v, allOk); + } +#endif /* !defined(SQLITE_OMIT_CHECK) */ + + /* If we have an INTEGER PRIMARY KEY, make sure the primary key + ** of the new record does not previously exist. Except, if this + ** is an UPDATE and the primary key is not changing, that is OK. + */ + if( rowidChng ){ + onError = pTab->keyConf; + if( overrideError!=OE_Default ){ + onError = overrideError; + }else if( onError==OE_Default ){ + onError = OE_Abort; + } + + if( isUpdate ){ + sqlite3VdbeAddOp(v, OP_Dup, nCol+1, 1); + sqlite3VdbeAddOp(v, OP_Dup, nCol+1, 1); + jumpInst1 = sqlite3VdbeAddOp(v, OP_Eq, 0, 0); + } + sqlite3VdbeAddOp(v, OP_Dup, nCol, 1); + jumpInst2 = sqlite3VdbeAddOp(v, OP_NotExists, base, 0); + switch( onError ){ + default: { + onError = OE_Abort; + /* Fall thru into the next case */ + } + case OE_Rollback: + case OE_Abort: + case OE_Fail: { + sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError, + "PRIMARY KEY must be unique", P3_STATIC); + break; + } + case OE_Replace: { + sqlite3GenerateRowIndexDelete(v, pTab, base, 0); + if( isUpdate ){ + sqlite3VdbeAddOp(v, OP_Dup, nCol+hasTwoRowids, 1); + sqlite3VdbeAddOp(v, OP_MoveGe, base, 0); + } + seenReplace = 1; + break; + } + case OE_Ignore: { + assert( seenReplace==0 ); + sqlite3VdbeAddOp(v, OP_Pop, nCol+1+hasTwoRowids, 0); + sqlite3VdbeAddOp(v, OP_Goto, 0, ignoreDest); + break; + } + } + sqlite3VdbeJumpHere(v, jumpInst2); + if( isUpdate ){ + sqlite3VdbeJumpHere(v, jumpInst1); + sqlite3VdbeAddOp(v, OP_Dup, nCol+1, 1); + sqlite3VdbeAddOp(v, OP_MoveGe, base, 0); + } + } + + /* Test all UNIQUE constraints by creating entries for each UNIQUE + ** index and making sure that duplicate entries do not already exist. + ** Add the new records to the indices as we go. + */ + extra = -1; + for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){ + if( aIdxUsed && aIdxUsed[iCur]==0 ) continue; /* Skip unused indices */ + extra++; + + /* Create a key for accessing the index entry */ + sqlite3VdbeAddOp(v, OP_Dup, nCol+extra, 1); + for(i=0; inColumn; i++){ + int idx = pIdx->aiColumn[i]; + if( idx==pTab->iPKey ){ + sqlite3VdbeAddOp(v, OP_Dup, i+extra+nCol+1, 1); + }else{ + sqlite3VdbeAddOp(v, OP_Dup, i+extra+nCol-idx, 1); + } + } + jumpInst1 = sqlite3VdbeAddOp(v, OP_MakeIdxRec, pIdx->nColumn, 0); + sqlite3IndexAffinityStr(v, pIdx); + + /* Find out what action to take in case there is an indexing conflict */ + onError = pIdx->onError; + if( onError==OE_None ) continue; /* pIdx is not a UNIQUE index */ + if( overrideError!=OE_Default ){ + onError = overrideError; + }else if( onError==OE_Default ){ + onError = OE_Abort; + } + if( seenReplace ){ + if( onError==OE_Ignore ) onError = OE_Replace; + else if( onError==OE_Fail ) onError = OE_Abort; + } + + + /* Check to see if the new index entry will be unique */ + sqlite3VdbeAddOp(v, OP_Dup, extra+nCol+1+hasTwoRowids, 1); + jumpInst2 = sqlite3VdbeAddOp(v, OP_IsUnique, base+iCur+1, 0); + + /* Generate code that executes if the new index entry is not unique */ + assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail + || onError==OE_Ignore || onError==OE_Replace ); + switch( onError ){ + case OE_Rollback: + case OE_Abort: + case OE_Fail: { + int j, n1, n2; + char zErrMsg[200]; + sqlite3_snprintf(sizeof(zErrMsg), zErrMsg, + pIdx->nColumn>1 ? "columns " : "column "); + n1 = strlen(zErrMsg); + for(j=0; jnColumn && n1aCol[pIdx->aiColumn[j]].zName; + n2 = strlen(zCol); + if( j>0 ){ + sqlite3_snprintf(sizeof(zErrMsg)-n1, &zErrMsg[n1], ", "); + n1 += 2; + } + if( n1+n2>sizeof(zErrMsg)-30 ){ + sqlite3_snprintf(sizeof(zErrMsg)-n1, &zErrMsg[n1], "..."); + n1 += 3; + break; + }else{ + sqlite3_snprintf(sizeof(zErrMsg)-n1, &zErrMsg[n1], "%s", zCol); + n1 += n2; + } + } + sqlite3_snprintf(sizeof(zErrMsg)-n1, &zErrMsg[n1], + pIdx->nColumn>1 ? " are not unique" : " is not unique"); + sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError, zErrMsg, 0); + break; + } + case OE_Ignore: { + assert( seenReplace==0 ); + sqlite3VdbeAddOp(v, OP_Pop, nCol+extra+3+hasTwoRowids, 0); + sqlite3VdbeAddOp(v, OP_Goto, 0, ignoreDest); + break; + } + case OE_Replace: { + sqlite3GenerateRowDelete(pParse->db, v, pTab, base, 0); + if( isUpdate ){ + sqlite3VdbeAddOp(v, OP_Dup, nCol+extra+1+hasTwoRowids, 1); + sqlite3VdbeAddOp(v, OP_MoveGe, base, 0); + } + seenReplace = 1; + break; + } + } +#if NULL_DISTINCT_FOR_UNIQUE + sqlite3VdbeJumpHere(v, jumpInst1); +#endif + sqlite3VdbeJumpHere(v, jumpInst2); + } +} + +/* +** This routine generates code to finish the INSERT or UPDATE operation +** that was started by a prior call to sqlite3GenerateConstraintChecks. +** The stack must contain keys for all active indices followed by data +** and the rowid for the new entry. This routine creates the new +** entries in all indices and in the main table. +** +** The arguments to this routine should be the same as the first six +** arguments to sqlite3GenerateConstraintChecks. +*/ +void sqlite3CompleteInsertion( + Parse *pParse, /* The parser context */ + Table *pTab, /* the table into which we are inserting */ + int base, /* Index of a read/write cursor pointing at pTab */ + char *aIdxUsed, /* Which indices are used. NULL means all are used */ + int rowidChng, /* True if the record number will change */ + int isUpdate, /* True for UPDATE, False for INSERT */ + int newIdx, /* Index of NEW table for triggers. -1 if none */ + int appendBias /* True if this is likely to be an append */ +){ + int i; + Vdbe *v; + int nIdx; + Index *pIdx; + int pik_flags; + + v = sqlite3GetVdbe(pParse); + assert( v!=0 ); + assert( pTab->pSelect==0 ); /* This table is not a VIEW */ + for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){} + for(i=nIdx-1; i>=0; i--){ + if( aIdxUsed && aIdxUsed[i]==0 ) continue; + sqlite3VdbeAddOp(v, OP_IdxInsert, base+i+1, 0); + } + sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0); + sqlite3TableAffinityStr(v, pTab); +#ifndef SQLITE_OMIT_TRIGGER + if( newIdx>=0 ){ + sqlite3VdbeAddOp(v, OP_Dup, 1, 0); + sqlite3VdbeAddOp(v, OP_Dup, 1, 0); + sqlite3VdbeAddOp(v, OP_Insert, newIdx, 0); + } +#endif + if( pParse->nested ){ + pik_flags = 0; + }else{ + pik_flags = OPFLAG_NCHANGE; + pik_flags |= (isUpdate?OPFLAG_ISUPDATE:OPFLAG_LASTROWID); + } + if( appendBias ){ + pik_flags |= OPFLAG_APPEND; + } + sqlite3VdbeAddOp(v, OP_Insert, base, pik_flags); + if( !pParse->nested ){ + sqlite3VdbeChangeP3(v, -1, pTab->zName, P3_STATIC); + } + + if( isUpdate && rowidChng ){ + sqlite3VdbeAddOp(v, OP_Pop, 1, 0); + } +} + +/* +** Generate code that will open cursors for a table and for all +** indices of that table. The "base" parameter is the cursor number used +** for the table. Indices are opened on subsequent cursors. +*/ +void sqlite3OpenTableAndIndices( + Parse *pParse, /* Parsing context */ + Table *pTab, /* Table to be opened */ + int base, /* Cursor number assigned to the table */ + int op /* OP_OpenRead or OP_OpenWrite */ +){ + int i; + int iDb; + Index *pIdx; + Vdbe *v; + + if( IsVirtual(pTab) ) return; + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + v = sqlite3GetVdbe(pParse); + assert( v!=0 ); + sqlite3OpenTable(pParse, base, iDb, pTab, op); + for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ + KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); + assert( pIdx->pSchema==pTab->pSchema ); + sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); + VdbeComment((v, "# %s", pIdx->zName)); + sqlite3VdbeOp3(v, op, i+base, pIdx->tnum, (char*)pKey, P3_KEYINFO_HANDOFF); + } + if( pParse->nTab<=base+i ){ + pParse->nTab = base+i; + } +} + + +#ifdef SQLITE_TEST +/* +** The following global variable is incremented whenever the +** transfer optimization is used. This is used for testing +** purposes only - to make sure the transfer optimization really +** is happening when it is suppose to. +*/ +int sqlite3_xferopt_count; +#endif /* SQLITE_TEST */ + + +#ifndef SQLITE_OMIT_XFER_OPT +/* +** Check to collation names to see if they are compatible. +*/ +static int xferCompatibleCollation(const char *z1, const char *z2){ + if( z1==0 ){ + return z2==0; + } + if( z2==0 ){ + return 0; + } + return sqlite3StrICmp(z1, z2)==0; +} + + +/* +** Check to see if index pSrc is compatible as a source of data +** for index pDest in an insert transfer optimization. The rules +** for a compatible index: +** +** * The index is over the same set of columns +** * The same DESC and ASC markings occurs on all columns +** * The same onError processing (OE_Abort, OE_Ignore, etc) +** * The same collating sequence on each column +*/ +static int xferCompatibleIndex(Index *pDest, Index *pSrc){ + int i; + assert( pDest && pSrc ); + assert( pDest->pTable!=pSrc->pTable ); + if( pDest->nColumn!=pSrc->nColumn ){ + return 0; /* Different number of columns */ + } + if( pDest->onError!=pSrc->onError ){ + return 0; /* Different conflict resolution strategies */ + } + for(i=0; inColumn; i++){ + if( pSrc->aiColumn[i]!=pDest->aiColumn[i] ){ + return 0; /* Different columns indexed */ + } + if( pSrc->aSortOrder[i]!=pDest->aSortOrder[i] ){ + return 0; /* Different sort orders */ + } + if( pSrc->azColl[i]!=pDest->azColl[i] ){ + return 0; /* Different sort orders */ + } + } + + /* If no test above fails then the indices must be compatible */ + return 1; +} + +/* +** Attempt the transfer optimization on INSERTs of the form +** +** INSERT INTO tab1 SELECT * FROM tab2; +** +** This optimization is only attempted if +** +** (1) tab1 and tab2 have identical schemas including all the +** same indices and constraints +** +** (2) tab1 and tab2 are different tables +** +** (3) There must be no triggers on tab1 +** +** (4) The result set of the SELECT statement is "*" +** +** (5) The SELECT statement has no WHERE, HAVING, ORDER BY, GROUP BY, +** or LIMIT clause. +** +** (6) The SELECT statement is a simple (not a compound) select that +** contains only tab2 in its FROM clause +** +** This method for implementing the INSERT transfers raw records from +** tab2 over to tab1. The columns are not decoded. Raw records from +** the indices of tab2 are transfered to tab1 as well. In so doing, +** the resulting tab1 has much less fragmentation. +** +** This routine returns TRUE if the optimization is attempted. If any +** of the conditions above fail so that the optimization should not +** be attempted, then this routine returns FALSE. +*/ +static int xferOptimization( + Parse *pParse, /* Parser context */ + Table *pDest, /* The table we are inserting into */ + Select *pSelect, /* A SELECT statement to use as the data source */ + int onError, /* How to handle constraint errors */ + int iDbDest /* The database of pDest */ +){ + ExprList *pEList; /* The result set of the SELECT */ + Table *pSrc; /* The table in the FROM clause of SELECT */ + Index *pSrcIdx, *pDestIdx; /* Source and destination indices */ + struct SrcList_item *pItem; /* An element of pSelect->pSrc */ + int i; /* Loop counter */ + int iDbSrc; /* The database of pSrc */ + int iSrc, iDest; /* Cursors from source and destination */ + int addr1, addr2; /* Loop addresses */ + int emptyDestTest; /* Address of test for empty pDest */ + int emptySrcTest; /* Address of test for empty pSrc */ + Vdbe *v; /* The VDBE we are building */ + KeyInfo *pKey; /* Key information for an index */ + int counterMem; /* Memory register used by AUTOINC */ + int destHasUniqueIdx = 0; /* True if pDest has a UNIQUE index */ + + if( pSelect==0 ){ + return 0; /* Must be of the form INSERT INTO ... SELECT ... */ + } + if( pDest->pTrigger ){ + return 0; /* tab1 must not have triggers */ + } +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( pDest->isVirtual ){ + return 0; /* tab1 must not be a virtual table */ + } +#endif + if( onError==OE_Default ){ + onError = OE_Abort; + } + if( onError!=OE_Abort && onError!=OE_Rollback ){ + return 0; /* Cannot do OR REPLACE or OR IGNORE or OR FAIL */ + } + if( pSelect->pSrc==0 ){ + return 0; /* SELECT must have a FROM clause */ + } + if( pSelect->pSrc->nSrc!=1 ){ + return 0; /* FROM clause must have exactly one term */ + } + if( pSelect->pSrc->a[0].pSelect ){ + return 0; /* FROM clause cannot contain a subquery */ + } + if( pSelect->pWhere ){ + return 0; /* SELECT may not have a WHERE clause */ + } + if( pSelect->pOrderBy ){ + return 0; /* SELECT may not have an ORDER BY clause */ + } + /* Do not need to test for a HAVING clause. If HAVING is present but + ** there is no ORDER BY, we will get an error. */ + if( pSelect->pGroupBy ){ + return 0; /* SELECT may not have a GROUP BY clause */ + } + if( pSelect->pLimit ){ + return 0; /* SELECT may not have a LIMIT clause */ + } + assert( pSelect->pOffset==0 ); /* Must be so if pLimit==0 */ + if( pSelect->pPrior ){ + return 0; /* SELECT may not be a compound query */ + } + if( pSelect->isDistinct ){ + return 0; /* SELECT may not be DISTINCT */ + } + pEList = pSelect->pEList; + assert( pEList!=0 ); + if( pEList->nExpr!=1 ){ + return 0; /* The result set must have exactly one column */ + } + assert( pEList->a[0].pExpr ); + if( pEList->a[0].pExpr->op!=TK_ALL ){ + return 0; /* The result set must be the special operator "*" */ + } + + /* At this point we have established that the statement is of the + ** correct syntactic form to participate in this optimization. Now + ** we have to check the semantics. + */ + pItem = pSelect->pSrc->a; + pSrc = sqlite3LocateTable(pParse, pItem->zName, pItem->zDatabase); + if( pSrc==0 ){ + return 0; /* FROM clause does not contain a real table */ + } + if( pSrc==pDest ){ + return 0; /* tab1 and tab2 may not be the same table */ + } +#ifndef SQLITE_OMIT_VIRTUALTABLE + if( pSrc->isVirtual ){ + return 0; /* tab2 must not be a virtual table */ + } +#endif + if( pSrc->pSelect ){ + return 0; /* tab2 may not be a view */ + } + if( pDest->nCol!=pSrc->nCol ){ + return 0; /* Number of columns must be the same in tab1 and tab2 */ + } + if( pDest->iPKey!=pSrc->iPKey ){ + return 0; /* Both tables must have the same INTEGER PRIMARY KEY */ + } + for(i=0; inCol; i++){ + if( pDest->aCol[i].affinity!=pSrc->aCol[i].affinity ){ + return 0; /* Affinity must be the same on all columns */ + } + if( !xferCompatibleCollation(pDest->aCol[i].zColl, pSrc->aCol[i].zColl) ){ + return 0; /* Collating sequence must be the same on all columns */ + } + if( pDest->aCol[i].notNull && !pSrc->aCol[i].notNull ){ + return 0; /* tab2 must be NOT NULL if tab1 is */ + } + } + for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ + if( pDestIdx->onError!=OE_None ){ + destHasUniqueIdx = 1; + } + for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){ + if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break; + } + if( pSrcIdx==0 ){ + return 0; /* pDestIdx has no corresponding index in pSrc */ + } + } +#ifndef SQLITE_OMIT_CHECK + if( pDest->pCheck && !sqlite3ExprCompare(pSrc->pCheck, pDest->pCheck) ){ + return 0; /* Tables have different CHECK constraints. Ticket #2252 */ + } +#endif + + /* If we get this far, it means either: + ** + ** * We can always do the transfer if the table contains an + ** an integer primary key + ** + ** * We can conditionally do the transfer if the destination + ** table is empty. + */ +#ifdef SQLITE_TEST + sqlite3_xferopt_count++; +#endif + iDbSrc = sqlite3SchemaToIndex(pParse->db, pSrc->pSchema); + v = sqlite3GetVdbe(pParse); + iSrc = pParse->nTab++; + iDest = pParse->nTab++; + counterMem = autoIncBegin(pParse, iDbDest, pDest); + sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite); + if( (pDest->iPKey<0 && pDest->pIndex!=0) || destHasUniqueIdx ){ + /* If tables do not have an INTEGER PRIMARY KEY and there + ** are indices to be copied and the destination is not empty, + ** we have to disallow the transfer optimization because the + ** the rowids might change which will mess up indexing. + ** + ** Or if the destination has a UNIQUE index and is not empty, + ** we also disallow the transfer optimization because we cannot + ** insure that all entries in the union of DEST and SRC will be + ** unique. + */ + addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iDest, 0); + emptyDestTest = sqlite3VdbeAddOp(v, OP_Goto, 0, 0); + sqlite3VdbeJumpHere(v, addr1); + }else{ + emptyDestTest = 0; + } + sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead); + emptySrcTest = sqlite3VdbeAddOp(v, OP_Rewind, iSrc, 0); + if( pDest->iPKey>=0 ){ + addr1 = sqlite3VdbeAddOp(v, OP_Rowid, iSrc, 0); + sqlite3VdbeAddOp(v, OP_Dup, 0, 0); + addr2 = sqlite3VdbeAddOp(v, OP_NotExists, iDest, 0); + sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, onError, + "PRIMARY KEY must be unique", P3_STATIC); + sqlite3VdbeJumpHere(v, addr2); + autoIncStep(pParse, counterMem); + }else if( pDest->pIndex==0 ){ + addr1 = sqlite3VdbeAddOp(v, OP_NewRowid, iDest, 0); + }else{ + addr1 = sqlite3VdbeAddOp(v, OP_Rowid, iSrc, 0); + assert( pDest->autoInc==0 ); + } + sqlite3VdbeAddOp(v, OP_RowData, iSrc, 0); + sqlite3VdbeOp3(v, OP_Insert, iDest, + OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND, + pDest->zName, 0); + sqlite3VdbeAddOp(v, OP_Next, iSrc, addr1); + autoIncEnd(pParse, iDbDest, pDest, counterMem); + for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ + for(pSrcIdx=pSrc->pIndex; pSrcIdx; pSrcIdx=pSrcIdx->pNext){ + if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break; + } + assert( pSrcIdx ); + sqlite3VdbeAddOp(v, OP_Close, iSrc, 0); + sqlite3VdbeAddOp(v, OP_Close, iDest, 0); + sqlite3VdbeAddOp(v, OP_Integer, iDbSrc, 0); + pKey = sqlite3IndexKeyinfo(pParse, pSrcIdx); + VdbeComment((v, "# %s", pSrcIdx->zName)); + sqlite3VdbeOp3(v, OP_OpenRead, iSrc, pSrcIdx->tnum, + (char*)pKey, P3_KEYINFO_HANDOFF); + sqlite3VdbeAddOp(v, OP_Integer, iDbDest, 0); + pKey = sqlite3IndexKeyinfo(pParse, pDestIdx); + VdbeComment((v, "# %s", pDestIdx->zName)); + sqlite3VdbeOp3(v, OP_OpenWrite, iDest, pDestIdx->tnum, + (char*)pKey, P3_KEYINFO_HANDOFF); + addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iSrc, 0); + sqlite3VdbeAddOp(v, OP_RowKey, iSrc, 0); + sqlite3VdbeAddOp(v, OP_IdxInsert, iDest, 1); + sqlite3VdbeAddOp(v, OP_Next, iSrc, addr1+1); + sqlite3VdbeJumpHere(v, addr1); + } + sqlite3VdbeJumpHere(v, emptySrcTest); + sqlite3VdbeAddOp(v, OP_Close, iSrc, 0); + sqlite3VdbeAddOp(v, OP_Close, iDest, 0); + if( emptyDestTest ){ + sqlite3VdbeAddOp(v, OP_Halt, SQLITE_OK, 0); + sqlite3VdbeJumpHere(v, emptyDestTest); + sqlite3VdbeAddOp(v, OP_Close, iDest, 0); + return 0; + }else{ + return 1; + } +} +#endif /* SQLITE_OMIT_XFER_OPT */ diff --git a/extensions/sqlite/sqlite-source/keywordhash.h b/extensions/sqlite/sqlite-source/keywordhash.h new file mode 100644 index 00000000..93872189 --- /dev/null +++ b/extensions/sqlite/sqlite-source/keywordhash.h @@ -0,0 +1,112 @@ +/***** This file contains automatically generated code ****** +** +** The code in this file has been automatically generated by +** +** $Header: /sqlite/sqlite/tool/mkkeywordhash.c,v 1.30 2007/05/04 18:30:41 drh Exp $ +** +** The code in this file implements a function that determines whether +** or not a given identifier is really an SQL keyword. The same thing +** might be implemented more directly using a hand-written hash table. +** But by using this automatically generated code, the size of the code +** is substantially reduced. This is important for embedded applications +** on platforms with limited memory. +*/ +/* Hash score: 165 */ +static int keywordCode(const char *z, int n){ + /* zText[] encodes 775 bytes of keywords in 526 bytes */ + static const char zText[526] = + "BEFOREIGNOREGEXPLAINSTEADDESCAPEACHECKEYCONSTRAINTERSECTABLEFT" + "HENDATABASELECTRANSACTIONATURALTERAISELSEXCEPTRIGGEREFERENCES" + "UNIQUERYATTACHAVINGROUPDATEMPORARYBEGINNEREINDEXCLUSIVEXISTSBETWEEN" + "OTNULLIKECASCADEFERRABLECASECOLLATECREATECURRENT_DATEDELETEDETACH" + "IMMEDIATEJOINSERTMATCHPLANALYZEPRAGMABORTVALUESVIRTUALIMITWHEN" + "WHERENAMEAFTEREPLACEANDEFAULTAUTOINCREMENTCASTCOLUMNCOMMITCONFLICT" + "CROSSCURRENT_TIMESTAMPRIMARYDEFERREDISTINCTDROPFAILFROMFULLGLOB" + "YIFINTOFFSETISNULLORDERESTRICTOUTERIGHTROLLBACKROWUNIONUSINGVACUUM" + "VIEWINITIALLY"; + static const unsigned char aHash[127] = { + 63, 92, 109, 61, 0, 38, 0, 0, 69, 0, 64, 0, 0, + 102, 4, 65, 7, 0, 108, 72, 103, 99, 0, 22, 0, 0, + 113, 0, 111, 106, 0, 18, 80, 0, 1, 0, 0, 56, 57, + 0, 55, 11, 0, 33, 77, 89, 0, 110, 88, 0, 0, 45, + 0, 90, 54, 0, 20, 0, 114, 34, 19, 0, 10, 97, 28, + 83, 0, 0, 116, 93, 47, 115, 41, 12, 44, 0, 78, 0, + 87, 29, 0, 86, 0, 0, 0, 82, 79, 84, 75, 96, 6, + 14, 95, 0, 68, 0, 21, 76, 98, 27, 0, 112, 67, 104, + 49, 40, 71, 0, 0, 81, 100, 0, 107, 0, 15, 0, 0, + 24, 0, 73, 42, 50, 0, 16, 48, 0, 37, + }; + static const unsigned char aNext[116] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, + 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, + 17, 0, 0, 0, 36, 39, 0, 0, 25, 0, 0, 31, 0, + 0, 0, 43, 52, 0, 0, 0, 53, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 51, 0, 0, 0, 0, 26, 0, 8, 46, + 2, 0, 0, 0, 0, 0, 0, 0, 3, 58, 66, 0, 13, + 0, 91, 85, 0, 94, 0, 74, 0, 0, 62, 0, 35, 101, + 0, 0, 105, 23, 30, 60, 70, 0, 0, 59, 0, 0, + }; + static const unsigned char aLen[116] = { + 6, 7, 3, 6, 6, 7, 7, 3, 4, 6, 4, 5, 3, + 10, 9, 5, 4, 4, 3, 8, 2, 6, 11, 2, 7, 5, + 5, 4, 6, 7, 10, 6, 5, 6, 6, 5, 6, 4, 9, + 2, 5, 5, 7, 5, 9, 6, 7, 7, 3, 4, 4, 7, + 3, 10, 4, 7, 6, 12, 6, 6, 9, 4, 6, 5, 4, + 7, 6, 5, 6, 7, 5, 4, 5, 6, 5, 7, 3, 7, + 13, 2, 2, 4, 6, 6, 8, 5, 17, 12, 7, 8, 8, + 2, 4, 4, 4, 4, 4, 2, 2, 4, 6, 2, 3, 6, + 5, 8, 5, 5, 8, 3, 5, 5, 6, 4, 9, 3, + }; + static const unsigned short int aOffset[116] = { + 0, 2, 2, 6, 10, 13, 18, 23, 25, 26, 31, 33, 37, + 40, 47, 55, 58, 61, 63, 65, 70, 71, 76, 85, 86, 91, + 95, 99, 102, 107, 113, 123, 126, 131, 136, 141, 144, 148, 148, + 152, 157, 160, 164, 166, 169, 177, 183, 189, 189, 192, 195, 199, + 200, 204, 214, 218, 225, 231, 243, 249, 255, 264, 266, 272, 277, + 279, 286, 291, 296, 302, 308, 313, 317, 320, 326, 330, 337, 339, + 346, 348, 350, 359, 363, 369, 375, 383, 388, 388, 404, 411, 418, + 419, 426, 430, 434, 438, 442, 445, 447, 449, 452, 452, 455, 458, + 464, 468, 476, 480, 485, 493, 496, 501, 506, 512, 516, 521, + }; + static const unsigned char aCode[116] = { + TK_BEFORE, TK_FOREIGN, TK_FOR, TK_IGNORE, TK_LIKE_KW, + TK_EXPLAIN, TK_INSTEAD, TK_ADD, TK_DESC, TK_ESCAPE, + TK_EACH, TK_CHECK, TK_KEY, TK_CONSTRAINT, TK_INTERSECT, + TK_TABLE, TK_JOIN_KW, TK_THEN, TK_END, TK_DATABASE, + TK_AS, TK_SELECT, TK_TRANSACTION,TK_ON, TK_JOIN_KW, + TK_ALTER, TK_RAISE, TK_ELSE, TK_EXCEPT, TK_TRIGGER, + TK_REFERENCES, TK_UNIQUE, TK_QUERY, TK_ATTACH, TK_HAVING, + TK_GROUP, TK_UPDATE, TK_TEMP, TK_TEMP, TK_OR, + TK_BEGIN, TK_JOIN_KW, TK_REINDEX, TK_INDEX, TK_EXCLUSIVE, + TK_EXISTS, TK_BETWEEN, TK_NOTNULL, TK_NOT, TK_NULL, + TK_LIKE_KW, TK_CASCADE, TK_ASC, TK_DEFERRABLE, TK_CASE, + TK_COLLATE, TK_CREATE, TK_CTIME_KW, TK_DELETE, TK_DETACH, + TK_IMMEDIATE, TK_JOIN, TK_INSERT, TK_MATCH, TK_PLAN, + TK_ANALYZE, TK_PRAGMA, TK_ABORT, TK_VALUES, TK_VIRTUAL, + TK_LIMIT, TK_WHEN, TK_WHERE, TK_RENAME, TK_AFTER, + TK_REPLACE, TK_AND, TK_DEFAULT, TK_AUTOINCR, TK_TO, + TK_IN, TK_CAST, TK_COLUMNKW, TK_COMMIT, TK_CONFLICT, + TK_JOIN_KW, TK_CTIME_KW, TK_CTIME_KW, TK_PRIMARY, TK_DEFERRED, + TK_DISTINCT, TK_IS, TK_DROP, TK_FAIL, TK_FROM, + TK_JOIN_KW, TK_LIKE_KW, TK_BY, TK_IF, TK_INTO, + TK_OFFSET, TK_OF, TK_SET, TK_ISNULL, TK_ORDER, + TK_RESTRICT, TK_JOIN_KW, TK_JOIN_KW, TK_ROLLBACK, TK_ROW, + TK_UNION, TK_USING, TK_VACUUM, TK_VIEW, TK_INITIALLY, + TK_ALL, + }; + 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); +} diff --git a/extensions/sqlite/sqlite-source/legacy.c b/extensions/sqlite/sqlite-source/legacy.c new file mode 100644 index 00000000..4249aa55 --- /dev/null +++ b/extensions/sqlite/sqlite-source/legacy.c @@ -0,0 +1,132 @@ +/* +** 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$ +*/ + +#include "sqliteInt.h" +#include "os.h" +#include + +/* +** 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 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; + } + + 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; ierrMask)==rc ); + return rc; +} diff --git a/extensions/sqlite/sqlite-source/loadext.c b/extensions/sqlite/sqlite-source/loadext.c new file mode 100644 index 00000000..b2f4726c --- /dev/null +++ b/extensions/sqlite/sqlite-source/loadext.c @@ -0,0 +1,440 @@ +/* +** 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 +#include + +/* +** 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_prepare16_v2 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 +# define sqlite3_column_database_name16 0 +# define sqlite3_column_table_name16 0 +# define sqlite3_column_origin_name16 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_create_module_v2 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, + + /* + ** Added after 3.3.13 + */ + sqlite3_prepare_v2, + sqlite3_prepare16_v2, + sqlite3_clear_bindings, + + /* + ** Added for 3.4.1 + */ + sqlite3_create_module_v2, + +}; + +/* +** 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; inExtension; 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 ){ + 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 */ diff --git a/extensions/sqlite/sqlite-source/main.c b/extensions/sqlite/sqlite-source/main.c new file mode 100644 index 00000000..aeb650fa --- /dev/null +++ b/extensions/sqlite/sqlite-source/main.c @@ -0,0 +1,1442 @@ +/* +** 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$ +*/ +#include "sqliteInt.h" +#include "os.h" +#include + +/* +** The version of the library +*/ +const char sqlite3_version[] = SQLITE_VERSION; +const char *sqlite3_libversion(void){ return sqlite3_version; } +int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; } + +/* +** If the following function pointer is not NULL and if +** SQLITE_ENABLE_IOTRACE is enabled, then messages describing +** I/O active are written using this function. These messages +** are intended for debugging activity only. +*/ +void (*sqlite3_io_trace)(const char*, ...) = 0; + +/* +** If the following global variable points to a string which is the +** name of a directory, then that directory will be used to store +** temporary files. +** +** See also the "PRAGMA temp_store_directory" SQL command. +*/ +char *sqlite3_temp_directory = 0; + + +/* +** This is the default collating function named "BINARY" which is always +** available. +*/ +static int binCollFunc( + void *NotUsed, + int nKey1, const void *pKey1, + int nKey2, const void *pKey2 +){ + int rc, n; + n = nKey1lastRowid; +} + +/* +** Return the number of changes in the most recent call to sqlite3_exec(). +*/ +int sqlite3_changes(sqlite3 *db){ + return db->nChange; +} + +/* +** Return the number of changes since the database handle was opened. +*/ +int sqlite3_total_changes(sqlite3 *db){ + return db->nTotalChange; +} + +/* +** Close an existing SQLite database +*/ +int sqlite3_close(sqlite3 *db){ + HashElem *i; + int j; + + if( !db ){ + return SQLITE_OK; + } + if( sqlite3SafetyCheck(db) ){ + return SQLITE_MISUSE; + } + +#ifdef SQLITE_SSE + { + extern void sqlite3SseCleanup(sqlite3*); + sqlite3SseCleanup(db); + } +#endif + + sqlite3ResetInternalSchema(db, 0); + + /* If a transaction is open, the ResetInternalSchema() call above + ** will not have called the xDisconnect() method on any virtual + ** tables in the db->aVTrans[] array. The following sqlite3VtabRollback() + ** call will do so. We need to do this before the check for active + ** SQL statements below, as the v-table implementation may be storing + ** some prepared statements internally. + */ + sqlite3VtabRollback(db); + + /* If there are any outstanding VMs, return SQLITE_BUSY. */ + if( db->pVdbe ){ + sqlite3Error(db, SQLITE_BUSY, + "Unable to close due to unfinalised statements"); + return SQLITE_BUSY; + } + assert( !sqlite3SafetyCheck(db) ); + + /* FIX ME: db->magic may be set to SQLITE_MAGIC_CLOSED if the database + ** cannot be opened for some reason. So this routine needs to run in + ** that case. But maybe there should be an extra magic value for the + ** "failed to open" state. + ** + ** TODO: Coverage tests do not test the case where this condition is + ** true. It's hard to see how to cause it without messing with threads. + */ + if( db->magic!=SQLITE_MAGIC_CLOSED && sqlite3SafetyOn(db) ){ + /* printf("DID NOT CLOSE\n"); fflush(stdout); */ + return SQLITE_ERROR; + } + + for(j=0; jnDb; j++){ + struct Db *pDb = &db->aDb[j]; + if( pDb->pBt ){ + sqlite3BtreeClose(pDb->pBt); + pDb->pBt = 0; + if( j!=1 ){ + pDb->pSchema = 0; + } + } + } + sqlite3ResetInternalSchema(db, 0); + assert( db->nDb<=2 ); + assert( db->aDb==db->aDbStatic ); + for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){ + FuncDef *pFunc, *pNext; + for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){ + pNext = pFunc->pNext; + sqliteFree(pFunc); + } + } + + for(i=sqliteHashFirst(&db->aCollSeq); i; i=sqliteHashNext(i)){ + CollSeq *pColl = (CollSeq *)sqliteHashData(i); + /* Invoke any destructors registered for collation sequence user data. */ + for(j=0; j<3; j++){ + if( pColl[j].xDel ){ + pColl[j].xDel(pColl[j].pUser); + } + } + sqliteFree(pColl); + } + sqlite3HashClear(&db->aCollSeq); +#ifndef SQLITE_OMIT_VIRTUALTABLE + for(i=sqliteHashFirst(&db->aModule); i; i=sqliteHashNext(i)){ + Module *pMod = (Module *)sqliteHashData(i); + if( pMod->xDestroy ){ + pMod->xDestroy(pMod->pAux); + } + sqliteFree(pMod); + } + sqlite3HashClear(&db->aModule); +#endif + + sqlite3HashClear(&db->aFunc); + sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */ + if( db->pErr ){ + sqlite3ValueFree(db->pErr); + } + sqlite3CloseExtensions(db); + + db->magic = SQLITE_MAGIC_ERROR; + + /* The temp-database schema is allocated differently from the other schema + ** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()). + ** So it needs to be freed here. Todo: Why not roll the temp schema into + ** the same sqliteMalloc() as the one that allocates the database + ** structure? + */ + sqliteFree(db->aDb[1].pSchema); + sqliteFree(db); + sqlite3ReleaseThreadData(); + return SQLITE_OK; +} + +/* +** Rollback all database files. +*/ +void sqlite3RollbackAll(sqlite3 *db){ + int i; + int inTrans = 0; + for(i=0; inDb; i++){ + if( db->aDb[i].pBt ){ + if( sqlite3BtreeIsInTrans(db->aDb[i].pBt) ){ + inTrans = 1; + } + sqlite3BtreeRollback(db->aDb[i].pBt); + db->aDb[i].inTrans = 0; + } + } + sqlite3VtabRollback(db); + if( db->flags&SQLITE_InternChanges ){ + sqlite3ResetInternalSchema(db, 0); + } + + /* If one has been configured, invoke the rollback-hook callback */ + if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){ + db->xRollbackCallback(db->pRollbackArg); + } +} + +/* +** Return a static string that describes the kind of error specified in the +** argument. +*/ +const char *sqlite3ErrStr(int rc){ + const char *z; + switch( rc & 0xff ){ + case SQLITE_ROW: + case SQLITE_DONE: + case SQLITE_OK: z = "not an error"; break; + case SQLITE_ERROR: z = "SQL logic error or missing database"; break; + case SQLITE_PERM: z = "access permission denied"; break; + case SQLITE_ABORT: z = "callback requested query abort"; break; + case SQLITE_BUSY: z = "database is locked"; break; + case SQLITE_LOCKED: z = "database table is locked"; break; + case SQLITE_NOMEM: z = "out of memory"; break; + case SQLITE_READONLY: z = "attempt to write a readonly database"; break; + case SQLITE_INTERRUPT: z = "interrupted"; break; + case SQLITE_IOERR: z = "disk I/O error"; break; + case SQLITE_CORRUPT: z = "database disk image is malformed"; break; + case SQLITE_FULL: z = "database or disk is full"; break; + case SQLITE_CANTOPEN: z = "unable to open database file"; break; + case SQLITE_EMPTY: z = "table contains no data"; break; + case SQLITE_SCHEMA: z = "database schema has changed"; break; + case SQLITE_TOOBIG: z = "String or BLOB exceeded size limit"; break; + case SQLITE_CONSTRAINT: z = "constraint failed"; break; + case SQLITE_MISMATCH: z = "datatype mismatch"; break; + case SQLITE_MISUSE: z = "library routine called out of sequence";break; + case SQLITE_NOLFS: z = "kernel lacks large file support"; break; + case SQLITE_AUTH: z = "authorization denied"; break; + case SQLITE_FORMAT: z = "auxiliary database format error"; break; + case SQLITE_RANGE: z = "bind or column index out of range"; break; + case SQLITE_NOTADB: z = "file is encrypted or is not a database";break; + default: z = "unknown error"; break; + } + return z; +} + +/* +** This routine implements a busy callback that sleeps and tries +** again until a timeout value is reached. The timeout value is +** an integer number of milliseconds passed in as the first +** argument. +*/ +static int sqliteDefaultBusyCallback( + void *ptr, /* Database connection */ + int count /* Number of times table has been busy */ +){ +#if OS_WIN || (defined(HAVE_USLEEP) && HAVE_USLEEP) + static const u8 delays[] = + { 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 100 }; + static const u8 totals[] = + { 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228 }; +# define NDELAY (sizeof(delays)/sizeof(delays[0])) + int timeout = ((sqlite3 *)ptr)->busyTimeout; + int delay, prior; + + assert( count>=0 ); + if( count < NDELAY ){ + delay = delays[count]; + prior = totals[count]; + }else{ + delay = delays[NDELAY-1]; + prior = totals[NDELAY-1] + delay*(count-(NDELAY-1)); + } + if( prior + delay > timeout ){ + delay = timeout - prior; + if( delay<=0 ) return 0; + } + sqlite3OsSleep(delay); + return 1; +#else + int timeout = ((sqlite3 *)ptr)->busyTimeout; + if( (count+1)*1000 > timeout ){ + return 0; + } + sqlite3OsSleep(1000); + return 1; +#endif +} + +/* +** Invoke the given busy handler. +** +** This routine is called when an operation failed with a lock. +** If this routine returns non-zero, the lock is retried. If it +** returns 0, the operation aborts with an SQLITE_BUSY error. +*/ +int sqlite3InvokeBusyHandler(BusyHandler *p){ + int rc; + if( p==0 || p->xFunc==0 || p->nBusy<0 ) return 0; + rc = p->xFunc(p->pArg, p->nBusy); + if( rc==0 ){ + p->nBusy = -1; + }else{ + p->nBusy++; + } + return rc; +} + +/* +** This routine sets the busy callback for an Sqlite database to the +** given callback function with the given argument. +*/ +int sqlite3_busy_handler( + sqlite3 *db, + int (*xBusy)(void*,int), + void *pArg +){ + if( sqlite3SafetyCheck(db) ){ + return SQLITE_MISUSE; + } + db->busyHandler.xFunc = xBusy; + db->busyHandler.pArg = pArg; + db->busyHandler.nBusy = 0; + return SQLITE_OK; +} + +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK +/* +** This routine sets the progress callback for an Sqlite database to the +** given callback function with the given argument. The progress callback will +** be invoked every nOps opcodes. +*/ +void sqlite3_progress_handler( + sqlite3 *db, + int nOps, + int (*xProgress)(void*), + void *pArg +){ + if( !sqlite3SafetyCheck(db) ){ + if( nOps>0 ){ + db->xProgress = xProgress; + db->nProgressOps = nOps; + db->pProgressArg = pArg; + }else{ + db->xProgress = 0; + db->nProgressOps = 0; + db->pProgressArg = 0; + } + } +} +#endif + + +/* +** This routine installs a default busy handler that waits for the +** specified number of milliseconds before returning 0. +*/ +int sqlite3_busy_timeout(sqlite3 *db, int ms){ + if( sqlite3SafetyCheck(db) ){ + return SQLITE_MISUSE; + } + if( ms>0 ){ + db->busyTimeout = ms; + sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db); + }else{ + sqlite3_busy_handler(db, 0, 0); + } + return SQLITE_OK; +} + +/* +** Cause any pending operation to stop at its earliest opportunity. +*/ +void sqlite3_interrupt(sqlite3 *db){ + if( db && (db->magic==SQLITE_MAGIC_OPEN || db->magic==SQLITE_MAGIC_BUSY) ){ + db->u1.isInterrupted = 1; + } +} + +/* +** Memory allocation routines that use SQLites internal memory +** memory allocator. Depending on how SQLite is compiled, the +** internal memory allocator might be just an alias for the +** system default malloc/realloc/free. Or the built-in allocator +** might do extra stuff like put sentinals around buffers to +** check for overruns or look for memory leaks. +** +** Use sqlite3_free() to free memory returned by sqlite3_mprintf(). +*/ +void sqlite3_free(void *p){ if( p ) sqlite3OsFree(p); } +void *sqlite3_malloc(int nByte){ return nByte>0 ? sqlite3OsMalloc(nByte) : 0; } +void *sqlite3_realloc(void *pOld, int nByte){ + if( pOld ){ + if( nByte>0 ){ + return sqlite3OsRealloc(pOld, nByte); + }else{ + sqlite3OsFree(pOld); + return 0; + } + }else{ + return sqlite3_malloc(nByte); + } +} + +/* +** This function is exactly the same as sqlite3_create_function(), except +** that it is designed to be called by internal code. The difference is +** that if a malloc() fails in sqlite3_create_function(), an error code +** is returned and the mallocFailed flag cleared. +*/ +int sqlite3CreateFunc( + sqlite3 *db, + const char *zFunctionName, + int nArg, + int enc, + void *pUserData, + void (*xFunc)(sqlite3_context*,int,sqlite3_value **), + void (*xStep)(sqlite3_context*,int,sqlite3_value **), + void (*xFinal)(sqlite3_context*) +){ + FuncDef *p; + int nName; + + if( sqlite3SafetyCheck(db) ){ + return SQLITE_MISUSE; + } + if( zFunctionName==0 || + (xFunc && (xFinal || xStep)) || + (!xFunc && (xFinal && !xStep)) || + (!xFunc && (!xFinal && xStep)) || + (nArg<-1 || nArg>127) || + (255<(nName = strlen(zFunctionName))) ){ + sqlite3Error(db, SQLITE_ERROR, "bad parameters"); + return SQLITE_ERROR; + } + +#ifndef SQLITE_OMIT_UTF16 + /* If SQLITE_UTF16 is specified as the encoding type, transform this + ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the + ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally. + ** + ** If SQLITE_ANY is specified, add three versions of the function + ** to the hash table. + */ + if( enc==SQLITE_UTF16 ){ + enc = SQLITE_UTF16NATIVE; + }else if( enc==SQLITE_ANY ){ + int rc; + rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8, + pUserData, xFunc, xStep, xFinal); + if( rc!=SQLITE_OK ) return rc; + rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE, + pUserData, xFunc, xStep, xFinal); + if( rc!=SQLITE_OK ) return rc; + enc = SQLITE_UTF16BE; + } +#else + enc = SQLITE_UTF8; +#endif + + /* Check if an existing function is being overridden or deleted. If so, + ** and there are active VMs, then return SQLITE_BUSY. If a function + ** is being overridden/deleted but there are no active VMs, allow the + ** operation to continue but invalidate all precompiled statements. + */ + p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 0); + if( p && p->iPrefEnc==enc && p->nArg==nArg ){ + if( db->activeVdbeCnt ){ + sqlite3Error(db, SQLITE_BUSY, + "Unable to delete/modify user-function due to active statements"); + assert( !sqlite3MallocFailed() ); + return SQLITE_BUSY; + }else{ + sqlite3ExpirePreparedStatements(db); + } + } + + p = sqlite3FindFunction(db, zFunctionName, nName, nArg, enc, 1); + if( p ){ + p->flags = 0; + p->xFunc = xFunc; + p->xStep = xStep; + p->xFinalize = xFinal; + p->pUserData = pUserData; + p->nArg = nArg; + } + return SQLITE_OK; +} + +/* +** Create new user functions. +*/ +int sqlite3_create_function( + sqlite3 *db, + const char *zFunctionName, + int nArg, + int enc, + void *p, + void (*xFunc)(sqlite3_context*,int,sqlite3_value **), + void (*xStep)(sqlite3_context*,int,sqlite3_value **), + void (*xFinal)(sqlite3_context*) +){ + int rc; + assert( !sqlite3MallocFailed() ); + rc = sqlite3CreateFunc(db, zFunctionName, nArg, enc, p, xFunc, xStep, xFinal); + + return sqlite3ApiExit(db, rc); +} + +#ifndef SQLITE_OMIT_UTF16 +int sqlite3_create_function16( + sqlite3 *db, + const void *zFunctionName, + int nArg, + int eTextRep, + void *p, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*) +){ + int rc; + char *zFunc8; + assert( !sqlite3MallocFailed() ); + + zFunc8 = sqlite3Utf16to8(zFunctionName, -1); + rc = sqlite3CreateFunc(db, zFunc8, nArg, eTextRep, p, xFunc, xStep, xFinal); + sqliteFree(zFunc8); + + return sqlite3ApiExit(db, rc); +} +#endif + + +/* +** Declare that a function has been overloaded by a virtual table. +** +** If the function already exists as a regular global function, then +** this routine is a no-op. If the function does not exist, then create +** a new one that always throws a run-time error. +** +** When virtual tables intend to provide an overloaded function, they +** should call this routine to make sure the global function exists. +** A global function must exist in order for name resolution to work +** properly. +*/ +int sqlite3_overload_function( + sqlite3 *db, + const char *zName, + int nArg +){ + int nName = strlen(zName); + if( sqlite3FindFunction(db, zName, nName, nArg, SQLITE_UTF8, 0)==0 ){ + sqlite3CreateFunc(db, zName, nArg, SQLITE_UTF8, + 0, sqlite3InvalidFunction, 0, 0); + } + return sqlite3ApiExit(db, SQLITE_OK); +} + +#ifndef SQLITE_OMIT_TRACE +/* +** Register a trace function. The pArg from the previously registered trace +** is returned. +** +** A NULL trace function means that no tracing is executes. A non-NULL +** trace is a pointer to a function that is invoked at the start of each +** SQL statement. +*/ +void *sqlite3_trace(sqlite3 *db, void (*xTrace)(void*,const char*), void *pArg){ + void *pOld = db->pTraceArg; + db->xTrace = xTrace; + db->pTraceArg = pArg; + return pOld; +} +/* +** Register a profile function. The pArg from the previously registered +** profile function is returned. +** +** A NULL profile function means that no profiling is executes. A non-NULL +** profile is a pointer to a function that is invoked at the conclusion of +** each SQL statement that is run. +*/ +void *sqlite3_profile( + sqlite3 *db, + void (*xProfile)(void*,const char*,sqlite_uint64), + void *pArg +){ + void *pOld = db->pProfileArg; + db->xProfile = xProfile; + db->pProfileArg = pArg; + return pOld; +} +#endif /* SQLITE_OMIT_TRACE */ + +/*** EXPERIMENTAL *** +** +** Register a function to be invoked when a transaction comments. +** If the invoked function returns non-zero, then the commit becomes a +** rollback. +*/ +void *sqlite3_commit_hook( + sqlite3 *db, /* Attach the hook to this database */ + int (*xCallback)(void*), /* Function to invoke on each commit */ + void *pArg /* Argument to the function */ +){ + void *pOld = db->pCommitArg; + db->xCommitCallback = xCallback; + db->pCommitArg = pArg; + return pOld; +} + +/* +** Register a callback to be invoked each time a row is updated, +** inserted or deleted using this database connection. +*/ +void *sqlite3_update_hook( + sqlite3 *db, /* Attach the hook to this database */ + void (*xCallback)(void*,int,char const *,char const *,sqlite_int64), + void *pArg /* Argument to the function */ +){ + void *pRet = db->pUpdateArg; + db->xUpdateCallback = xCallback; + db->pUpdateArg = pArg; + return pRet; +} + +/* +** Register a callback to be invoked each time a transaction is rolled +** back by this database connection. +*/ +void *sqlite3_rollback_hook( + sqlite3 *db, /* Attach the hook to this database */ + void (*xCallback)(void*), /* Callback function */ + void *pArg /* Argument to the function */ +){ + void *pRet = db->pRollbackArg; + db->xRollbackCallback = xCallback; + db->pRollbackArg = pArg; + return pRet; +} + +/* +** This routine is called to create a connection to a database BTree +** driver. If zFilename is the name of a file, then that file is +** opened and used. If zFilename is the magic name ":memory:" then +** the database is stored in memory (and is thus forgotten as soon as +** the connection is closed.) If zFilename is NULL then the database +** is a "virtual" database for transient use only and is deleted as +** soon as the connection is closed. +** +** A virtual database can be either a disk file (that is automatically +** deleted when the file is closed) or it an be held entirely in memory, +** depending on the values of the TEMP_STORE compile-time macro and the +** db->temp_store variable, according to the following chart: +** +** TEMP_STORE db->temp_store Location of temporary database +** ---------- -------------- ------------------------------ +** 0 any file +** 1 1 file +** 1 2 memory +** 1 0 file +** 2 1 file +** 2 2 memory +** 2 0 memory +** 3 any memory +*/ +int sqlite3BtreeFactory( + const sqlite3 *db, /* Main database when opening aux otherwise 0 */ + const char *zFilename, /* Name of the file containing the BTree database */ + int omitJournal, /* if TRUE then do not journal this file */ + int nCache, /* How many pages in the page cache */ + Btree **ppBtree /* Pointer to new Btree object written here */ +){ + int btree_flags = 0; + int rc; + + assert( ppBtree != 0); + if( omitJournal ){ + btree_flags |= BTREE_OMIT_JOURNAL; + } + if( db->flags & SQLITE_NoReadlock ){ + btree_flags |= BTREE_NO_READLOCK; + } + if( zFilename==0 ){ +#if TEMP_STORE==0 + /* Do nothing */ +#endif +#ifndef SQLITE_OMIT_MEMORYDB +#if TEMP_STORE==1 + if( db->temp_store==2 ) zFilename = ":memory:"; +#endif +#if TEMP_STORE==2 + if( db->temp_store!=1 ) zFilename = ":memory:"; +#endif +#if TEMP_STORE==3 + zFilename = ":memory:"; +#endif +#endif /* SQLITE_OMIT_MEMORYDB */ + } + + rc = sqlite3BtreeOpen(zFilename, (sqlite3 *)db, ppBtree, btree_flags); + if( rc==SQLITE_OK ){ + sqlite3BtreeSetBusyHandler(*ppBtree, (void*)&db->busyHandler); + sqlite3BtreeSetCacheSize(*ppBtree, nCache); + } + return rc; +} + +/* +** Return UTF-8 encoded English language explanation of the most recent +** error. +*/ +const char *sqlite3_errmsg(sqlite3 *db){ + const char *z; + assert( !sqlite3MallocFailed() ); + if( !db ){ + return sqlite3ErrStr(SQLITE_NOMEM); + } + if( sqlite3SafetyCheck(db) || db->errCode==SQLITE_MISUSE ){ + return sqlite3ErrStr(SQLITE_MISUSE); + } + z = (char*)sqlite3_value_text(db->pErr); + if( z==0 ){ + z = sqlite3ErrStr(db->errCode); + } + return z; +} + +#ifndef SQLITE_OMIT_UTF16 +/* +** Return UTF-16 encoded English language explanation of the most recent +** error. +*/ +const void *sqlite3_errmsg16(sqlite3 *db){ + /* Because all the characters in the string are in the unicode + ** range 0x00-0xFF, if we pad the big-endian string with a + ** zero byte, we can obtain the little-endian string with + ** &big_endian[1]. + */ + static const char outOfMemBe[] = { + 0, 'o', 0, 'u', 0, 't', 0, ' ', + 0, 'o', 0, 'f', 0, ' ', + 0, 'm', 0, 'e', 0, 'm', 0, 'o', 0, 'r', 0, 'y', 0, 0, 0 + }; + static const char misuseBe [] = { + 0, 'l', 0, 'i', 0, 'b', 0, 'r', 0, 'a', 0, 'r', 0, 'y', 0, ' ', + 0, 'r', 0, 'o', 0, 'u', 0, 't', 0, 'i', 0, 'n', 0, 'e', 0, ' ', + 0, 'c', 0, 'a', 0, 'l', 0, 'l', 0, 'e', 0, 'd', 0, ' ', + 0, 'o', 0, 'u', 0, 't', 0, ' ', + 0, 'o', 0, 'f', 0, ' ', + 0, 's', 0, 'e', 0, 'q', 0, 'u', 0, 'e', 0, 'n', 0, 'c', 0, 'e', 0, 0, 0 + }; + + const void *z; + assert( !sqlite3MallocFailed() ); + if( !db ){ + return (void *)(&outOfMemBe[SQLITE_UTF16NATIVE==SQLITE_UTF16LE?1:0]); + } + if( sqlite3SafetyCheck(db) || db->errCode==SQLITE_MISUSE ){ + return (void *)(&misuseBe[SQLITE_UTF16NATIVE==SQLITE_UTF16LE?1:0]); + } + z = sqlite3_value_text16(db->pErr); + if( z==0 ){ + sqlite3ValueSetStr(db->pErr, -1, sqlite3ErrStr(db->errCode), + SQLITE_UTF8, SQLITE_STATIC); + z = sqlite3_value_text16(db->pErr); + } + sqlite3ApiExit(0, 0); + return z; +} +#endif /* SQLITE_OMIT_UTF16 */ + +/* +** Return the most recent error code generated by an SQLite routine. If NULL is +** passed to this function, we assume a malloc() failed during sqlite3_open(). +*/ +int sqlite3_errcode(sqlite3 *db){ + if( !db || sqlite3MallocFailed() ){ + return SQLITE_NOMEM; + } + if( sqlite3SafetyCheck(db) ){ + return SQLITE_MISUSE; + } + return db->errCode & db->errMask; +} + +/* +** Create a new collating function for database "db". The name is zName +** and the encoding is enc. +*/ +static int createCollation( + sqlite3* db, + const char *zName, + int enc, + void* pCtx, + int(*xCompare)(void*,int,const void*,int,const void*), + void(*xDel)(void*) +){ + CollSeq *pColl; + int enc2; + + if( sqlite3SafetyCheck(db) ){ + return SQLITE_MISUSE; + } + + /* If SQLITE_UTF16 is specified as the encoding type, transform this + ** to one of SQLITE_UTF16LE or SQLITE_UTF16BE using the + ** SQLITE_UTF16NATIVE macro. SQLITE_UTF16 is not used internally. + */ + enc2 = enc & ~SQLITE_UTF16_ALIGNED; + if( enc2==SQLITE_UTF16 ){ + enc2 = SQLITE_UTF16NATIVE; + } + + if( (enc2&~3)!=0 ){ + sqlite3Error(db, SQLITE_ERROR, "unknown encoding"); + return SQLITE_ERROR; + } + + /* Check if this call is removing or replacing an existing collation + ** sequence. If so, and there are active VMs, return busy. If there + ** are no active VMs, invalidate any pre-compiled statements. + */ + pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, strlen(zName), 0); + if( pColl && pColl->xCmp ){ + if( db->activeVdbeCnt ){ + sqlite3Error(db, SQLITE_BUSY, + "Unable to delete/modify collation sequence due to active statements"); + return SQLITE_BUSY; + } + sqlite3ExpirePreparedStatements(db); + + /* If collation sequence pColl was created directly by a call to + ** sqlite3_create_collation, and not generated by synthCollSeq(), + ** then any copies made by synthCollSeq() need to be invalidated. + ** Also, collation destructor - CollSeq.xDel() - function may need + ** to be called. + */ + if( (pColl->enc & ~SQLITE_UTF16_ALIGNED)==enc2 ){ + CollSeq *aColl = sqlite3HashFind(&db->aCollSeq, zName, strlen(zName)); + int j; + for(j=0; j<3; j++){ + CollSeq *p = &aColl[j]; + if( p->enc==pColl->enc ){ + if( p->xDel ){ + p->xDel(p->pUser); + } + p->xCmp = 0; + } + } + } + } + + pColl = sqlite3FindCollSeq(db, (u8)enc2, zName, strlen(zName), 1); + if( pColl ){ + pColl->xCmp = xCompare; + pColl->pUser = pCtx; + pColl->xDel = xDel; + pColl->enc = enc2 | (enc & SQLITE_UTF16_ALIGNED); + } + sqlite3Error(db, SQLITE_OK, 0); + return SQLITE_OK; +} + + +/* +** This routine does the work of opening a database on behalf of +** sqlite3_open() and sqlite3_open16(). The database filename "zFilename" +** is UTF-8 encoded. +*/ +static int openDatabase( + const char *zFilename, /* Database filename UTF-8 encoded */ + sqlite3 **ppDb /* OUT: Returned database handle */ +){ + sqlite3 *db; + int rc; + CollSeq *pColl; + + assert( !sqlite3MallocFailed() ); + + /* Allocate the sqlite data structure */ + db = sqliteMalloc( sizeof(sqlite3) ); + if( db==0 ) goto opendb_out; + db->errMask = 0xff; + db->priorNewRowid = 0; + db->magic = SQLITE_MAGIC_BUSY; + db->nDb = 2; + db->aDb = db->aDbStatic; + db->autoCommit = 1; + db->flags |= SQLITE_ShortColNames +#if SQLITE_DEFAULT_FILE_FORMAT<4 + | SQLITE_LegacyFileFmt +#endif +#ifdef SQLITE_ENABLE_LOAD_EXTENSION + | SQLITE_LoadExtension +#endif + ; + sqlite3HashInit(&db->aFunc, SQLITE_HASH_STRING, 0); + sqlite3HashInit(&db->aCollSeq, SQLITE_HASH_STRING, 0); +#ifndef SQLITE_OMIT_VIRTUALTABLE + sqlite3HashInit(&db->aModule, SQLITE_HASH_STRING, 0); +#endif + + /* Add the default collation sequence BINARY. BINARY works for both UTF-8 + ** and UTF-16, so add a version for each to avoid any unnecessary + ** conversions. The only error that can occur here is a malloc() failure. + */ + if( createCollation(db, "BINARY", SQLITE_UTF8, 0, binCollFunc, 0) || + createCollation(db, "BINARY", SQLITE_UTF16BE, 0, binCollFunc, 0) || + createCollation(db, "BINARY", SQLITE_UTF16LE, 0, binCollFunc, 0) || + (db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "BINARY", 6, 0))==0 + ){ + assert( sqlite3MallocFailed() ); + db->magic = SQLITE_MAGIC_CLOSED; + goto opendb_out; + } + + /* Also add a UTF-8 case-insensitive collation sequence. */ + createCollation(db, "NOCASE", SQLITE_UTF8, 0, nocaseCollatingFunc, 0); + + /* Set flags on the built-in collating sequences */ + db->pDfltColl->type = SQLITE_COLL_BINARY; + pColl = sqlite3FindCollSeq(db, SQLITE_UTF8, "NOCASE", 6, 0); + if( pColl ){ + pColl->type = SQLITE_COLL_NOCASE; + } + + /* Open the backend database driver */ + rc = sqlite3BtreeFactory(db, zFilename, 0, SQLITE_DEFAULT_CACHE_SIZE, + &db->aDb[0].pBt); + if( rc!=SQLITE_OK ){ + sqlite3Error(db, rc, 0); + db->magic = SQLITE_MAGIC_CLOSED; + goto opendb_out; + } + db->aDb[0].pSchema = sqlite3SchemaGet(db->aDb[0].pBt); + db->aDb[1].pSchema = sqlite3SchemaGet(0); + + + /* The default safety_level for the main database is 'full'; for the temp + ** database it is 'NONE'. This matches the pager layer defaults. + */ + db->aDb[0].zName = "main"; + db->aDb[0].safety_level = 3; +#ifndef SQLITE_OMIT_TEMPDB + db->aDb[1].zName = "temp"; + db->aDb[1].safety_level = 1; +#endif + + db->magic = SQLITE_MAGIC_OPEN; + if( sqlite3MallocFailed() ){ + goto opendb_out; + } + + /* Register all built-in functions, but do not attempt to read the + ** database schema yet. This is delayed until the first time the database + ** is accessed. + */ + sqlite3Error(db, SQLITE_OK, 0); + sqlite3RegisterBuiltinFunctions(db); + + /* Load automatic extensions - extensions that have been registered + ** using the sqlite3_automatic_extension() API. + */ + (void)sqlite3AutoLoadExtensions(db); + if( sqlite3_errcode(db)!=SQLITE_OK ){ + goto opendb_out; + } + +#ifdef SQLITE_ENABLE_FTS1 + if( !sqlite3MallocFailed() ){ + extern int sqlite3Fts1Init(sqlite3*); + rc = sqlite3Fts1Init(db); + } +#endif + +#ifdef SQLITE_ENABLE_FTS2 + if( !sqlite3MallocFailed() && rc==SQLITE_OK ){ + extern int sqlite3Fts2Init(sqlite3*); + rc = sqlite3Fts2Init(db); + } +#endif + +#ifdef SQLITE_ENABLE_ICU + if( !sqlite3MallocFailed() && rc==SQLITE_OK ){ + extern int sqlite3IcuInit(sqlite3*); + rc = sqlite3IcuInit(db); + } +#endif + sqlite3Error(db, rc, 0); + + /* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking + ** mode. -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking + ** mode. Doing nothing at all also makes NORMAL the default. + */ +#ifdef SQLITE_DEFAULT_LOCKING_MODE + db->dfltLockMode = SQLITE_DEFAULT_LOCKING_MODE; + sqlite3PagerLockingMode(sqlite3BtreePager(db->aDb[0].pBt), + SQLITE_DEFAULT_LOCKING_MODE); +#endif + +opendb_out: + if( SQLITE_NOMEM==(rc = sqlite3_errcode(db)) ){ + sqlite3_close(db); + db = 0; + } + *ppDb = db; + return sqlite3ApiExit(0, rc); +} + +/* +** Open a new database handle. +*/ +int sqlite3_open( + const char *zFilename, + sqlite3 **ppDb +){ + return openDatabase(zFilename, ppDb); +} + +#ifndef SQLITE_OMIT_UTF16 +/* +** Open a new database handle. +*/ +int sqlite3_open16( + const void *zFilename, + sqlite3 **ppDb +){ + char const *zFilename8; /* zFilename encoded in UTF-8 instead of UTF-16 */ + int rc = SQLITE_OK; + sqlite3_value *pVal; + + assert( zFilename ); + assert( ppDb ); + *ppDb = 0; + pVal = sqlite3ValueNew(); + sqlite3ValueSetStr(pVal, -1, zFilename, SQLITE_UTF16NATIVE, SQLITE_STATIC); + zFilename8 = sqlite3ValueText(pVal, SQLITE_UTF8); + if( zFilename8 ){ + rc = openDatabase(zFilename8, ppDb); + if( rc==SQLITE_OK && *ppDb ){ + rc = sqlite3_exec(*ppDb, "PRAGMA encoding = 'UTF-16'", 0, 0, 0); + if( rc!=SQLITE_OK ){ + sqlite3_close(*ppDb); + *ppDb = 0; + } + } + } + sqlite3ValueFree(pVal); + + return sqlite3ApiExit(0, rc); +} +#endif /* SQLITE_OMIT_UTF16 */ + +/* +** The following routine destroys a virtual machine that is created by +** the sqlite3_compile() routine. The integer returned is an SQLITE_ +** success/failure code that describes the result of executing the virtual +** machine. +** +** This routine sets the error code and string returned by +** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16(). +*/ +int sqlite3_finalize(sqlite3_stmt *pStmt){ + int rc; + if( pStmt==0 ){ + rc = SQLITE_OK; + }else{ + rc = sqlite3VdbeFinalize((Vdbe*)pStmt); + } + return rc; +} + +/* +** Terminate the current execution of an SQL statement and reset it +** back to its starting state so that it can be reused. A success code from +** the prior execution is returned. +** +** This routine sets the error code and string returned by +** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16(). +*/ +int sqlite3_reset(sqlite3_stmt *pStmt){ + int rc; + if( pStmt==0 ){ + rc = SQLITE_OK; + }else{ + rc = sqlite3VdbeReset((Vdbe*)pStmt); + sqlite3VdbeMakeReady((Vdbe*)pStmt, -1, 0, 0, 0); + assert( (rc & (sqlite3_db_handle(pStmt)->errMask))==rc ); + } + return rc; +} + +/* +** Register a new collation sequence with the database handle db. +*/ +int sqlite3_create_collation( + sqlite3* db, + const char *zName, + int enc, + void* pCtx, + int(*xCompare)(void*,int,const void*,int,const void*) +){ + int rc; + assert( !sqlite3MallocFailed() ); + rc = createCollation(db, zName, enc, pCtx, xCompare, 0); + return sqlite3ApiExit(db, rc); +} + +/* +** Register a new collation sequence with the database handle db. +*/ +int sqlite3_create_collation_v2( + sqlite3* db, + const char *zName, + int enc, + void* pCtx, + int(*xCompare)(void*,int,const void*,int,const void*), + void(*xDel)(void*) +){ + int rc; + assert( !sqlite3MallocFailed() ); + rc = createCollation(db, zName, enc, pCtx, xCompare, xDel); + return sqlite3ApiExit(db, rc); +} + +#ifndef SQLITE_OMIT_UTF16 +/* +** Register a new collation sequence with the database handle db. +*/ +int sqlite3_create_collation16( + sqlite3* db, + const char *zName, + int enc, + void* pCtx, + int(*xCompare)(void*,int,const void*,int,const void*) +){ + int rc = SQLITE_OK; + char *zName8; + assert( !sqlite3MallocFailed() ); + zName8 = sqlite3Utf16to8(zName, -1); + if( zName8 ){ + rc = createCollation(db, zName8, enc, pCtx, xCompare, 0); + sqliteFree(zName8); + } + return sqlite3ApiExit(db, rc); +} +#endif /* SQLITE_OMIT_UTF16 */ + +/* +** Register a collation sequence factory callback with the database handle +** db. Replace any previously installed collation sequence factory. +*/ +int sqlite3_collation_needed( + sqlite3 *db, + void *pCollNeededArg, + void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*) +){ + if( sqlite3SafetyCheck(db) ){ + return SQLITE_MISUSE; + } + db->xCollNeeded = xCollNeeded; + db->xCollNeeded16 = 0; + db->pCollNeededArg = pCollNeededArg; + return SQLITE_OK; +} + +#ifndef SQLITE_OMIT_UTF16 +/* +** Register a collation sequence factory callback with the database handle +** db. Replace any previously installed collation sequence factory. +*/ +int sqlite3_collation_needed16( + sqlite3 *db, + void *pCollNeededArg, + void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*) +){ + if( sqlite3SafetyCheck(db) ){ + return SQLITE_MISUSE; + } + db->xCollNeeded = 0; + db->xCollNeeded16 = xCollNeeded16; + db->pCollNeededArg = pCollNeededArg; + return SQLITE_OK; +} +#endif /* SQLITE_OMIT_UTF16 */ + +#ifndef SQLITE_OMIT_GLOBALRECOVER +/* +** This function is now an anachronism. It used to be used to recover from a +** malloc() failure, but SQLite now does this automatically. +*/ +int sqlite3_global_recover(){ + return SQLITE_OK; +} +#endif + +/* +** Test to see whether or not the database connection is in autocommit +** mode. Return TRUE if it is and FALSE if not. Autocommit mode is on +** by default. Autocommit is disabled by a BEGIN statement and reenabled +** by the next COMMIT or ROLLBACK. +** +******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ****** +*/ +int sqlite3_get_autocommit(sqlite3 *db){ + return db->autoCommit; +} + +#ifdef SQLITE_DEBUG +/* +** The following routine is subtituted for constant SQLITE_CORRUPT in +** debugging builds. This provides a way to set a breakpoint for when +** corruption is first detected. +*/ +int sqlite3Corrupt(void){ + return SQLITE_CORRUPT; +} +#endif + + +#ifndef SQLITE_OMIT_SHARED_CACHE +/* +** Enable or disable the shared pager and schema features for the +** current thread. +** +** This routine should only be called when there are no open +** database connections. +*/ +int sqlite3_enable_shared_cache(int enable){ + ThreadData *pTd = sqlite3ThreadData(); + if( pTd ){ + /* It is only legal to call sqlite3_enable_shared_cache() when there + ** are no currently open b-trees that were opened by the calling thread. + ** This condition is only easy to detect if the shared-cache were + ** previously enabled (and is being disabled). + */ + if( pTd->pBtree && !enable ){ + assert( pTd->useSharedData ); + return SQLITE_MISUSE; + } + + pTd->useSharedData = enable; + sqlite3ReleaseThreadData(); + } + return sqlite3ApiExit(0, SQLITE_OK); +} +#endif + +/* +** This is a convenience routine that makes sure that all thread-specific +** data for this thread has been deallocated. +*/ +void sqlite3_thread_cleanup(void){ + ThreadData *pTd = sqlite3OsThreadSpecificData(0); + if( pTd ){ + memset(pTd, 0, sizeof(*pTd)); + sqlite3OsThreadSpecificData(-1); + } +} + +/* +** Return meta information about a specific column of a database table. +** See comment in sqlite3.h (sqlite.h.in) for details. +*/ +#ifdef SQLITE_ENABLE_COLUMN_METADATA +int sqlite3_table_column_metadata( + sqlite3 *db, /* Connection handle */ + const char *zDbName, /* Database name or NULL */ + const char *zTableName, /* Table name */ + const char *zColumnName, /* Column name */ + char const **pzDataType, /* OUTPUT: Declared data type */ + char const **pzCollSeq, /* OUTPUT: Collation sequence name */ + int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ + int *pPrimaryKey, /* OUTPUT: True if column part of PK */ + int *pAutoinc /* OUTPUT: True if colums is auto-increment */ +){ + int rc; + char *zErrMsg = 0; + Table *pTab = 0; + Column *pCol = 0; + int iCol; + + char const *zDataType = 0; + char const *zCollSeq = 0; + int notnull = 0; + int primarykey = 0; + int autoinc = 0; + + /* Ensure the database schema has been loaded */ + if( sqlite3SafetyOn(db) ){ + return SQLITE_MISUSE; + } + rc = sqlite3Init(db, &zErrMsg); + if( SQLITE_OK!=rc ){ + goto error_out; + } + + /* Locate the table in question */ + pTab = sqlite3FindTable(db, zTableName, zDbName); + if( !pTab || pTab->pSelect ){ + pTab = 0; + goto error_out; + } + + /* Find the column for which info is requested */ + if( sqlite3IsRowid(zColumnName) ){ + iCol = pTab->iPKey; + if( iCol>=0 ){ + pCol = &pTab->aCol[iCol]; + } + }else{ + for(iCol=0; iColnCol; iCol++){ + pCol = &pTab->aCol[iCol]; + if( 0==sqlite3StrICmp(pCol->zName, zColumnName) ){ + break; + } + } + if( iCol==pTab->nCol ){ + pTab = 0; + goto error_out; + } + } + + /* The following block stores the meta information that will be returned + ** to the caller in local variables zDataType, zCollSeq, notnull, primarykey + ** and autoinc. At this point there are two possibilities: + ** + ** 1. The specified column name was rowid", "oid" or "_rowid_" + ** and there is no explicitly declared IPK column. + ** + ** 2. The table is not a view and the column name identified an + ** explicitly declared column. Copy meta information from *pCol. + */ + if( pCol ){ + zDataType = pCol->zType; + zCollSeq = pCol->zColl; + notnull = (pCol->notNull?1:0); + primarykey = (pCol->isPrimKey?1:0); + autoinc = ((pTab->iPKey==iCol && pTab->autoInc)?1:0); + }else{ + zDataType = "INTEGER"; + primarykey = 1; + } + if( !zCollSeq ){ + zCollSeq = "BINARY"; + } + +error_out: + if( sqlite3SafetyOff(db) ){ + rc = SQLITE_MISUSE; + } + + /* Whether the function call succeeded or failed, set the output parameters + ** to whatever their local counterparts contain. If an error did occur, + ** this has the effect of zeroing all output parameters. + */ + if( pzDataType ) *pzDataType = zDataType; + if( pzCollSeq ) *pzCollSeq = zCollSeq; + if( pNotNull ) *pNotNull = notnull; + if( pPrimaryKey ) *pPrimaryKey = primarykey; + if( pAutoinc ) *pAutoinc = autoinc; + + if( SQLITE_OK==rc && !pTab ){ + sqlite3SetString(&zErrMsg, "no such table column: ", zTableName, ".", + zColumnName, 0); + rc = SQLITE_ERROR; + } + sqlite3Error(db, rc, (zErrMsg?"%s":0), zErrMsg); + sqliteFree(zErrMsg); + return sqlite3ApiExit(db, rc); +} +#endif + +/* +** Set all the parameters in the compiled SQL statement to NULL. +*/ +int sqlite3_clear_bindings(sqlite3_stmt *pStmt){ + int i; + int rc = SQLITE_OK; + for(i=1; rc==SQLITE_OK && i<=sqlite3_bind_parameter_count(pStmt); i++){ + rc = sqlite3_bind_null(pStmt, i); + } + return rc; +} + +/* +** Sleep for a little while. Return the amount of time slept. +*/ +int sqlite3_sleep(int ms){ + return sqlite3OsSleep(ms); +} + +/* +** Enable or disable the extended result codes. +*/ +int sqlite3_extended_result_codes(sqlite3 *db, int onoff){ + db->errMask = onoff ? 0xffffffff : 0xff; + return SQLITE_OK; +} diff --git a/extensions/sqlite/sqlite-source/malloc.c b/extensions/sqlite/sqlite-source/malloc.c new file mode 100644 index 00000000..3716e547 --- /dev/null +++ b/extensions/sqlite/sqlite-source/malloc.c @@ -0,0 +1,835 @@ +/* +** 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. +** +************************************************************************* +** Memory allocation functions used throughout sqlite. +** +** +** $Id$ +*/ +#include "sqliteInt.h" +#include "os.h" +#include +#include + +/* +** MALLOC WRAPPER ARCHITECTURE +** +** The sqlite code accesses dynamic memory allocation/deallocation by invoking +** the following six APIs (which may be implemented as macros). +** +** sqlite3Malloc() +** sqlite3MallocRaw() +** sqlite3Realloc() +** sqlite3ReallocOrFree() +** sqlite3Free() +** sqlite3AllocSize() +** +** The function sqlite3FreeX performs the same task as sqlite3Free and is +** guaranteed to be a real function. The same holds for sqlite3MallocX +** +** The above APIs are implemented in terms of the functions provided in the +** operating-system interface. The OS interface is never accessed directly +** by code outside of this file. +** +** sqlite3OsMalloc() +** sqlite3OsRealloc() +** sqlite3OsFree() +** sqlite3OsAllocationSize() +** +** Functions sqlite3MallocRaw() and sqlite3Realloc() may invoke +** sqlite3_release_memory() if a call to sqlite3OsMalloc() or +** sqlite3OsRealloc() fails (or if the soft-heap-limit for the thread is +** exceeded). Function sqlite3Malloc() usually invokes +** sqlite3MallocRaw(). +** +** MALLOC TEST WRAPPER ARCHITECTURE +** +** The test wrapper provides extra test facilities to ensure the library +** does not leak memory and handles the failure of the underlying OS level +** allocation system correctly. It is only present if the library is +** compiled with the SQLITE_MEMDEBUG macro set. +** +** * Guardposts to detect overwrites. +** * Ability to cause a specific Malloc() or Realloc() to fail. +** * Audit outstanding memory allocations (i.e check for leaks). +*/ + +#define MAX(x,y) ((x)>(y)?(x):(y)) + +#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO) +/* +** Set the soft heap-size limit for the current thread. Passing a negative +** value indicates no limit. +*/ +void sqlite3_soft_heap_limit(int n){ + ThreadData *pTd = sqlite3ThreadData(); + if( pTd ){ + pTd->nSoftHeapLimit = n; + } + sqlite3ReleaseThreadData(); +} + +/* +** Release memory held by SQLite instances created by the current thread. +*/ +int sqlite3_release_memory(int n){ + return sqlite3PagerReleaseMemory(n); +} +#else +/* If SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined, then define a version +** of sqlite3_release_memory() to be used by other code in this file. +** This is done for no better reason than to reduce the number of +** pre-processor #ifndef statements. +*/ +#define sqlite3_release_memory(x) 0 /* 0 == no memory freed */ +#endif + +#ifdef SQLITE_MEMDEBUG +/*-------------------------------------------------------------------------- +** Begin code for memory allocation system test layer. +** +** Memory debugging is turned on by defining the SQLITE_MEMDEBUG macro. +** +** SQLITE_MEMDEBUG==1 -> Fence-posting only (thread safe) +** SQLITE_MEMDEBUG==2 -> Fence-posting + linked list of allocations (not ts) +** SQLITE_MEMDEBUG==3 -> Above + backtraces (not thread safe, req. glibc) +*/ + +/* Figure out whether or not to store backtrace() information for each malloc. +** The backtrace() function is only used if SQLITE_MEMDEBUG is set to 2 or +** greater and glibc is in use. If we don't want to use backtrace(), then just +** define it as an empty macro and set the amount of space reserved to 0. +*/ +#if defined(__GLIBC__) && SQLITE_MEMDEBUG>2 + extern int backtrace(void **, int); + #define TESTALLOC_STACKSIZE 128 + #define TESTALLOC_STACKFRAMES ((TESTALLOC_STACKSIZE-8)/sizeof(void*)) +#else + #define backtrace(x, y) + #define TESTALLOC_STACKSIZE 0 + #define TESTALLOC_STACKFRAMES 0 +#endif + +/* +** Number of 32-bit guard words. This should probably be a multiple of +** 2 since on 64-bit machines we want the value returned by sqliteMalloc() +** to be 8-byte aligned. +*/ +#ifndef TESTALLOC_NGUARD +# define TESTALLOC_NGUARD 2 +#endif + +/* +** Size reserved for storing file-name along with each malloc()ed blob. +*/ +#define TESTALLOC_FILESIZE 64 + +/* +** Size reserved for storing the user string. Each time a Malloc() or Realloc() +** call succeeds, up to TESTALLOC_USERSIZE bytes of the string pointed to by +** sqlite3_malloc_id are stored along with the other test system metadata. +*/ +#define TESTALLOC_USERSIZE 64 +const char *sqlite3_malloc_id = 0; + +/* +** Blocks used by the test layer have the following format: +** +** +** +** +** +** +** <32-bit line number> +** +** +*/ + +#define TESTALLOC_OFFSET_GUARD1(p) (sizeof(void *) * 2) +#define TESTALLOC_OFFSET_DATA(p) ( \ + TESTALLOC_OFFSET_GUARD1(p) + sizeof(u32) * TESTALLOC_NGUARD \ +) +#define TESTALLOC_OFFSET_GUARD2(p) ( \ + TESTALLOC_OFFSET_DATA(p) + sqlite3OsAllocationSize(p) - TESTALLOC_OVERHEAD \ +) +#define TESTALLOC_OFFSET_LINENUMBER(p) ( \ + TESTALLOC_OFFSET_GUARD2(p) + sizeof(u32) * TESTALLOC_NGUARD \ +) +#define TESTALLOC_OFFSET_FILENAME(p) ( \ + TESTALLOC_OFFSET_LINENUMBER(p) + sizeof(u32) \ +) +#define TESTALLOC_OFFSET_USER(p) ( \ + TESTALLOC_OFFSET_FILENAME(p) + TESTALLOC_FILESIZE \ +) +#define TESTALLOC_OFFSET_STACK(p) ( \ + TESTALLOC_OFFSET_USER(p) + TESTALLOC_USERSIZE + 8 - \ + (TESTALLOC_OFFSET_USER(p) % 8) \ +) + +#define TESTALLOC_OVERHEAD ( \ + sizeof(void *)*2 + /* pPrev and pNext pointers */ \ + TESTALLOC_NGUARD*sizeof(u32)*2 + /* Guard words */ \ + sizeof(u32) + TESTALLOC_FILESIZE + /* File and line number */ \ + TESTALLOC_USERSIZE + /* User string */ \ + TESTALLOC_STACKSIZE /* backtrace() stack */ \ +) + + +/* +** For keeping track of the number of mallocs and frees. This +** is used to check for memory leaks. The iMallocFail and iMallocReset +** values are used to simulate malloc() failures during testing in +** order to verify that the library correctly handles an out-of-memory +** condition. +*/ +int sqlite3_nMalloc; /* Number of sqliteMalloc() calls */ +int sqlite3_nFree; /* Number of sqliteFree() calls */ +int sqlite3_memUsed; /* TODO Total memory obtained from malloc */ +int sqlite3_memMax; /* TODO Mem usage high-water mark */ +int sqlite3_iMallocFail; /* Fail sqliteMalloc() after this many calls */ +int sqlite3_iMallocReset = -1; /* When iMallocFail reaches 0, set to this */ + +void *sqlite3_pFirst = 0; /* Pointer to linked list of allocations */ +int sqlite3_nMaxAlloc = 0; /* High water mark of ThreadData.nAlloc */ +int sqlite3_mallocDisallowed = 0; /* assert() in sqlite3Malloc() if set */ +int sqlite3_isFail = 0; /* True if all malloc calls should fail */ +const char *sqlite3_zFile = 0; /* Filename to associate debug info with */ +int sqlite3_iLine = 0; /* Line number for debug info */ +int sqlite3_mallocfail_trace = 0; /* Print a msg on malloc fail if true */ + +/* +** Check for a simulated memory allocation failure. Return true if +** the failure should be simulated. Return false to proceed as normal. +*/ +int sqlite3TestMallocFail(){ + if( sqlite3_isFail ){ + return 1; + } + if( sqlite3_iMallocFail>=0 ){ + sqlite3_iMallocFail--; + if( sqlite3_iMallocFail==0 ){ + sqlite3_iMallocFail = sqlite3_iMallocReset; + sqlite3_isFail = 1; + if( sqlite3_mallocfail_trace ){ + sqlite3DebugPrintf("###_malloc_fails_###\n"); + } + return 1; + } + } + return 0; +} + +/* +** The argument is a pointer returned by sqlite3OsMalloc() or xRealloc(). +** assert() that the first and last (TESTALLOC_NGUARD*4) bytes are set to the +** values set by the applyGuards() function. +*/ +static void checkGuards(u32 *p) +{ + int i; + char *zAlloc = (char *)p; + char *z; + + /* First set of guard words */ + z = &zAlloc[TESTALLOC_OFFSET_GUARD1(p)]; + for(i=0; i1 +/* +** The argument points to an Os level allocation. Link it into the threads list +** of allocations. +*/ +static void linkAlloc(void *p){ + void **pp = (void **)p; + pp[0] = 0; + pp[1] = sqlite3_pFirst; + if( sqlite3_pFirst ){ + ((void **)sqlite3_pFirst)[0] = p; + } + sqlite3_pFirst = p; +} + +/* +** The argument points to an Os level allocation. Unlinke it from the threads +** list of allocations. +*/ +static void unlinkAlloc(void *p) +{ + void **pp = (void **)p; + if( p==sqlite3_pFirst ){ + assert(!pp[0]); + assert(!pp[1] || ((void **)(pp[1]))[0]==p); + sqlite3_pFirst = pp[1]; + if( sqlite3_pFirst ){ + ((void **)sqlite3_pFirst)[0] = 0; + } + }else{ + void **pprev = pp[0]; + void **pnext = pp[1]; + assert(pprev); + assert(pprev[1]==p); + pprev[1] = (void *)pnext; + if( pnext ){ + assert(pnext[0]==p); + pnext[0] = (void *)pprev; + } + } +} + +/* +** Pointer p is a pointer to an OS level allocation that has just been +** realloc()ed. Set the list pointers that point to this entry to it's new +** location. +*/ +static void relinkAlloc(void *p) +{ + void **pp = (void **)p; + if( pp[0] ){ + ((void **)(pp[0]))[1] = p; + }else{ + sqlite3_pFirst = p; + } + if( pp[1] ){ + ((void **)(pp[1]))[0] = p; + } +} +#else +#define linkAlloc(x) +#define relinkAlloc(x) +#define unlinkAlloc(x) +#endif + +/* +** This function sets the result of the Tcl interpreter passed as an argument +** to a list containing an entry for each currently outstanding call made to +** sqliteMalloc and friends by the current thread. Each list entry is itself a +** list, consisting of the following (in order): +** +** * The number of bytes allocated +** * The __FILE__ macro at the time of the sqliteMalloc() call. +** * The __LINE__ macro ... +** * The value of the sqlite3_malloc_id variable ... +** * The output of backtrace() (if available) ... +** +** Todo: We could have a version of this function that outputs to stdout, +** to debug memory leaks when Tcl is not available. +*/ +#if defined(TCLSH) && defined(SQLITE_DEBUG) && SQLITE_MEMDEBUG>1 +#include +int sqlite3OutstandingMallocs(Tcl_Interp *interp){ + void *p; + Tcl_Obj *pRes = Tcl_NewObj(); + Tcl_IncrRefCount(pRes); + + + for(p=sqlite3_pFirst; p; p=((void **)p)[1]){ + Tcl_Obj *pEntry = Tcl_NewObj(); + Tcl_Obj *pStack = Tcl_NewObj(); + char *z; + u32 iLine; + int nBytes = sqlite3OsAllocationSize(p) - TESTALLOC_OVERHEAD; + char *zAlloc = (char *)p; + int i; + + Tcl_ListObjAppendElement(0, pEntry, Tcl_NewIntObj(nBytes)); + + z = &zAlloc[TESTALLOC_OFFSET_FILENAME(p)]; + Tcl_ListObjAppendElement(0, pEntry, Tcl_NewStringObj(z, -1)); + + z = &zAlloc[TESTALLOC_OFFSET_LINENUMBER(p)]; + memcpy(&iLine, z, sizeof(u32)); + Tcl_ListObjAppendElement(0, pEntry, Tcl_NewIntObj(iLine)); + + z = &zAlloc[TESTALLOC_OFFSET_USER(p)]; + Tcl_ListObjAppendElement(0, pEntry, Tcl_NewStringObj(z, -1)); + + z = &zAlloc[TESTALLOC_OFFSET_STACK(p)]; + for(i=0; inAlloc); +#endif + assert( !sqlite3_mallocDisallowed ); + if( !sqlite3TestMallocFail() ){ + u32 *p; + p = (u32 *)sqlite3OsMalloc(n + TESTALLOC_OVERHEAD); + assert(p); + sqlite3_nMalloc++; + applyGuards(p); + linkAlloc(p); + sqlite3OsLeaveMutex(); + return (void *)(&p[TESTALLOC_NGUARD + 2*sizeof(void *)/sizeof(u32)]); + } + sqlite3OsLeaveMutex(); + return 0; +} + +static int OSSIZEOF(void *p){ + if( p ){ + u32 *pOs = (u32 *)getOsPointer(p); + return sqlite3OsAllocationSize(pOs) - TESTALLOC_OVERHEAD; + } + return 0; +} + +/* +** This is the test layer's wrapper around sqlite3OsFree(). The argument is a +** pointer to the space allocated for the application to use. +*/ +static void OSFREE(void *pFree){ + u32 *p; /* Pointer to the OS-layer allocation */ + sqlite3OsEnterMutex(); + p = (u32 *)getOsPointer(pFree); + checkGuards(p); + unlinkAlloc(p); + memset(pFree, 0x55, OSSIZEOF(pFree)); + sqlite3OsFree(p); + sqlite3_nFree++; + sqlite3OsLeaveMutex(); +} + +/* +** This is the test layer's wrapper around sqlite3OsRealloc(). +*/ +static void * OSREALLOC(void *pRealloc, int n){ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + sqlite3_nMaxAlloc = + MAX(sqlite3_nMaxAlloc, sqlite3ThreadDataReadOnly()->nAlloc); +#endif + assert( !sqlite3_mallocDisallowed ); + if( !sqlite3TestMallocFail() ){ + u32 *p = (u32 *)getOsPointer(pRealloc); + checkGuards(p); + p = sqlite3OsRealloc(p, n + TESTALLOC_OVERHEAD); + applyGuards(p); + relinkAlloc(p); + return (void *)(&p[TESTALLOC_NGUARD + 2*sizeof(void *)/sizeof(u32)]); + } + return 0; +} + +static void OSMALLOC_FAILED(){ + sqlite3_isFail = 0; +} + +#else +/* Define macros to call the sqlite3OsXXX interface directly if +** the SQLITE_MEMDEBUG macro is not defined. +*/ +#define OSMALLOC(x) sqlite3OsMalloc(x) +#define OSREALLOC(x,y) sqlite3OsRealloc(x,y) +#define OSFREE(x) sqlite3OsFree(x) +#define OSSIZEOF(x) sqlite3OsAllocationSize(x) +#define OSMALLOC_FAILED() + +#endif /* SQLITE_MEMDEBUG */ +/* +** End code for memory allocation system test layer. +**--------------------------------------------------------------------------*/ + +/* +** This routine is called when we are about to allocate n additional bytes +** of memory. If the new allocation will put is over the soft allocation +** limit, then invoke sqlite3_release_memory() to try to release some +** memory before continuing with the allocation. +** +** This routine also makes sure that the thread-specific-data (TSD) has +** be allocated. If it has not and can not be allocated, then return +** false. The updateMemoryUsedCount() routine below will deallocate +** the TSD if it ought to be. +** +** If SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined, this routine is +** a no-op +*/ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT +static int enforceSoftLimit(int n){ + ThreadData *pTsd = sqlite3ThreadData(); + if( pTsd==0 ){ + return 0; + } + assert( pTsd->nAlloc>=0 ); + if( n>0 && pTsd->nSoftHeapLimit>0 ){ + while( pTsd->nAlloc+n>pTsd->nSoftHeapLimit && sqlite3_release_memory(n) ){} + } + return 1; +} +#else +# define enforceSoftLimit(X) 1 +#endif + +/* +** Update the count of total outstanding memory that is held in +** thread-specific-data (TSD). If after this update the TSD is +** no longer being used, then deallocate it. +** +** If SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined, this routine is +** a no-op +*/ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT +static void updateMemoryUsedCount(int n){ + ThreadData *pTsd = sqlite3ThreadData(); + if( pTsd ){ + pTsd->nAlloc += n; + assert( pTsd->nAlloc>=0 ); + if( pTsd->nAlloc==0 && pTsd->nSoftHeapLimit==0 ){ + sqlite3ReleaseThreadData(); + } + } +} +#else +#define updateMemoryUsedCount(x) /* no-op */ +#endif + +/* +** Allocate and return N bytes of uninitialised memory by calling +** sqlite3OsMalloc(). If the Malloc() call fails, attempt to free memory +** by calling sqlite3_release_memory(). +*/ +void *sqlite3MallocRaw(int n, int doMemManage){ + void *p = 0; + if( n>0 && !sqlite3MallocFailed() && (!doMemManage || enforceSoftLimit(n)) ){ + while( (p = OSMALLOC(n))==0 && sqlite3_release_memory(n) ){} + if( !p ){ + sqlite3FailedMalloc(); + OSMALLOC_FAILED(); + }else if( doMemManage ){ + updateMemoryUsedCount(OSSIZEOF(p)); + } + } + return p; +} + +/* +** Resize the allocation at p to n bytes by calling sqlite3OsRealloc(). The +** pointer to the new allocation is returned. If the Realloc() call fails, +** attempt to free memory by calling sqlite3_release_memory(). +*/ +void *sqlite3Realloc(void *p, int n){ + if( sqlite3MallocFailed() ){ + return 0; + } + + if( !p ){ + return sqlite3Malloc(n, 1); + }else{ + void *np = 0; +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + int origSize = OSSIZEOF(p); +#endif + if( enforceSoftLimit(n - origSize) ){ + while( (np = OSREALLOC(p, n))==0 && sqlite3_release_memory(n) ){} + if( !np ){ + sqlite3FailedMalloc(); + OSMALLOC_FAILED(); + }else{ + updateMemoryUsedCount(OSSIZEOF(np) - origSize); + } + } + return np; + } +} + +/* +** Free the memory pointed to by p. p must be either a NULL pointer or a +** value returned by a previous call to sqlite3Malloc() or sqlite3Realloc(). +*/ +void sqlite3FreeX(void *p){ + if( p ){ + updateMemoryUsedCount(0 - OSSIZEOF(p)); + OSFREE(p); + } +} + +/* +** A version of sqliteMalloc() that is always a function, not a macro. +** Currently, this is used only to alloc to allocate the parser engine. +*/ +void *sqlite3MallocX(int n){ + return sqliteMalloc(n); +} + +/* +** sqlite3Malloc +** sqlite3ReallocOrFree +** +** These two are implemented as wrappers around sqlite3MallocRaw(), +** sqlite3Realloc() and sqlite3Free(). +*/ +void *sqlite3Malloc(int n, int doMemManage){ + void *p = sqlite3MallocRaw(n, doMemManage); + if( p ){ + memset(p, 0, n); + } + return p; +} +void *sqlite3ReallocOrFree(void *p, int n){ + void *pNew; + pNew = sqlite3Realloc(p, n); + if( !pNew ){ + sqlite3FreeX(p); + } + return pNew; +} + +/* +** sqlite3ThreadSafeMalloc() and sqlite3ThreadSafeFree() are used in those +** rare scenarios where sqlite may allocate memory in one thread and free +** it in another. They are exactly the same as sqlite3Malloc() and +** sqlite3Free() except that: +** +** * The allocated memory is not included in any calculations with +** respect to the soft-heap-limit, and +** +** * sqlite3ThreadSafeMalloc() must be matched with ThreadSafeFree(), +** not sqlite3Free(). Calling sqlite3Free() on memory obtained from +** ThreadSafeMalloc() will cause an error somewhere down the line. +*/ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT +void *sqlite3ThreadSafeMalloc(int n){ + (void)ENTER_MALLOC; + return sqlite3Malloc(n, 0); +} +void sqlite3ThreadSafeFree(void *p){ + (void)ENTER_MALLOC; + if( p ){ + OSFREE(p); + } +} +#endif + + +/* +** Return the number of bytes allocated at location p. p must be either +** a NULL pointer (in which case 0 is returned) or a pointer returned by +** sqlite3Malloc(), sqlite3Realloc() or sqlite3ReallocOrFree(). +** +** The number of bytes allocated does not include any overhead inserted by +** any malloc() wrapper functions that may be called. So the value returned +** is the number of bytes that were available to SQLite using pointer p, +** regardless of how much memory was actually allocated. +*/ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT +int sqlite3AllocSize(void *p){ + return OSSIZEOF(p); +} +#endif + +/* +** Make a copy of a string in memory obtained from sqliteMalloc(). These +** functions call sqlite3MallocRaw() directly instead of sqliteMalloc(). This +** is because when memory debugging is turned on, these two functions are +** called via macros that record the current file and line number in the +** ThreadData structure. +*/ +char *sqlite3StrDup(const char *z){ + char *zNew; + int n; + if( z==0 ) return 0; + n = strlen(z)+1; + zNew = sqlite3MallocRaw(n, 1); + if( zNew ) memcpy(zNew, z, n); + return zNew; +} +char *sqlite3StrNDup(const char *z, int n){ + char *zNew; + if( z==0 ) return 0; + zNew = sqlite3MallocRaw(n+1, 1); + if( zNew ){ + memcpy(zNew, z, n); + zNew[n] = 0; + } + return zNew; +} + +/* +** Create a string from the 2nd and subsequent arguments (up to the +** first NULL argument), store the string in memory obtained from +** sqliteMalloc() and make the pointer indicated by the 1st argument +** point to that string. The 1st argument must either be NULL or +** point to memory obtained from sqliteMalloc(). +*/ +void sqlite3SetString(char **pz, ...){ + va_list ap; + int nByte; + const char *z; + char *zResult; + + assert( pz!=0 ); + nByte = 1; + va_start(ap, pz); + while( (z = va_arg(ap, const char*))!=0 ){ + nByte += strlen(z); + } + va_end(ap); + sqliteFree(*pz); + *pz = zResult = sqliteMallocRaw( nByte ); + if( zResult==0 ){ + return; + } + *zResult = 0; + va_start(ap, pz); + while( (z = va_arg(ap, const char*))!=0 ){ + int n = strlen(z); + memcpy(zResult, z, n); + zResult += n; + } + zResult[0] = 0; + va_end(ap); +} + + +/* +** This function must be called before exiting any API function (i.e. +** returning control to the user) that has called sqlite3Malloc or +** sqlite3Realloc. +** +** The returned value is normally a copy of the second argument to this +** function. However, if a malloc() failure has occured since the previous +** invocation SQLITE_NOMEM is returned instead. +** +** If the first argument, db, is not NULL and a malloc() error has occured, +** then the connection error-code (the value returned by sqlite3_errcode()) +** is set to SQLITE_NOMEM. +*/ +int sqlite3_mallocHasFailed = 0; +int sqlite3ApiExit(sqlite3* db, int rc){ + if( sqlite3MallocFailed() ){ + sqlite3_mallocHasFailed = 0; + sqlite3OsLeaveMutex(); + sqlite3Error(db, SQLITE_NOMEM, 0); + rc = SQLITE_NOMEM; + } + return rc & (db ? db->errMask : 0xff); +} + +/* +** Set the "malloc has failed" condition to true for this thread. +*/ +void sqlite3FailedMalloc(){ + if( !sqlite3MallocFailed() ){ + sqlite3OsEnterMutex(); + assert( sqlite3_mallocHasFailed==0 ); + sqlite3_mallocHasFailed = 1; + } +} + +#ifdef SQLITE_MEMDEBUG +/* +** This function sets a flag in the thread-specific-data structure that will +** cause an assert to fail if sqliteMalloc() or sqliteRealloc() is called. +*/ +void sqlite3MallocDisallow(){ + assert( sqlite3_mallocDisallowed>=0 ); + sqlite3_mallocDisallowed++; +} + +/* +** This function clears the flag set in the thread-specific-data structure set +** by sqlite3MallocDisallow(). +*/ +void sqlite3MallocAllow(){ + assert( sqlite3_mallocDisallowed>0 ); + sqlite3_mallocDisallowed--; +} +#endif diff --git a/extensions/sqlite/sqlite-source/opcodes.c b/extensions/sqlite/sqlite-source/opcodes.c new file mode 100644 index 00000000..0b623599 --- /dev/null +++ b/extensions/sqlite/sqlite-source/opcodes.c @@ -0,0 +1,148 @@ +/* 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 */ "VRename", + /* 29 */ "ParseSchema", + /* 30 */ "VOpen", + /* 31 */ "Close", + /* 32 */ "CreateIndex", + /* 33 */ "IsUnique", + /* 34 */ "NotFound", + /* 35 */ "Int64", + /* 36 */ "MustBeInt", + /* 37 */ "Halt", + /* 38 */ "Rowid", + /* 39 */ "IdxLT", + /* 40 */ "AddImm", + /* 41 */ "Statement", + /* 42 */ "RowData", + /* 43 */ "MemMax", + /* 44 */ "Push", + /* 45 */ "NotExists", + /* 46 */ "MemIncr", + /* 47 */ "Gosub", + /* 48 */ "Integer", + /* 49 */ "MemInt", + /* 50 */ "Prev", + /* 51 */ "VColumn", + /* 52 */ "CreateTable", + /* 53 */ "Last", + /* 54 */ "IncrVacuum", + /* 55 */ "IdxRowid", + /* 56 */ "MakeIdxRec", + /* 57 */ "ResetCount", + /* 58 */ "FifoWrite", + /* 59 */ "Callback", + /* 60 */ "Or", + /* 61 */ "And", + /* 62 */ "ContextPush", + /* 63 */ "DropTrigger", + /* 64 */ "DropIndex", + /* 65 */ "IsNull", + /* 66 */ "NotNull", + /* 67 */ "Ne", + /* 68 */ "Eq", + /* 69 */ "Gt", + /* 70 */ "Le", + /* 71 */ "Lt", + /* 72 */ "Ge", + /* 73 */ "IdxGE", + /* 74 */ "BitAnd", + /* 75 */ "BitOr", + /* 76 */ "ShiftLeft", + /* 77 */ "ShiftRight", + /* 78 */ "Add", + /* 79 */ "Subtract", + /* 80 */ "Multiply", + /* 81 */ "Divide", + /* 82 */ "Remainder", + /* 83 */ "Concat", + /* 84 */ "IdxDelete", + /* 85 */ "Negative", + /* 86 */ "Vacuum", + /* 87 */ "BitNot", + /* 88 */ "String8", + /* 89 */ "MoveLe", + /* 90 */ "IfNot", + /* 91 */ "DropTable", + /* 92 */ "MakeRecord", + /* 93 */ "Delete", + /* 94 */ "AggFinal", + /* 95 */ "Dup", + /* 96 */ "Goto", + /* 97 */ "TableLock", + /* 98 */ "FifoRead", + /* 99 */ "Clear", + /* 100 */ "IdxGT", + /* 101 */ "MoveLt", + /* 102 */ "VerifyCookie", + /* 103 */ "AggStep", + /* 104 */ "Pull", + /* 105 */ "SetNumColumns", + /* 106 */ "AbsValue", + /* 107 */ "Transaction", + /* 108 */ "VFilter", + /* 109 */ "VDestroy", + /* 110 */ "ContextPop", + /* 111 */ "Next", + /* 112 */ "IdxInsert", + /* 113 */ "Distinct", + /* 114 */ "Insert", + /* 115 */ "Destroy", + /* 116 */ "ReadCookie", + /* 117 */ "ForceInt", + /* 118 */ "LoadAnalysis", + /* 119 */ "Explain", + /* 120 */ "IfMemZero", + /* 121 */ "OpenPseudo", + /* 122 */ "OpenEphemeral", + /* 123 */ "Null", + /* 124 */ "Blob", + /* 125 */ "Real", + /* 126 */ "HexBlob", + /* 127 */ "MemStore", + /* 128 */ "Rewind", + /* 129 */ "MoveGe", + /* 130 */ "VBegin", + /* 131 */ "VUpdate", + /* 132 */ "VCreate", + /* 133 */ "MemMove", + /* 134 */ "MemNull", + /* 135 */ "Found", + /* 136 */ "NullRow", + /* 137 */ "NotUsed_137", + /* 138 */ "ToText", + /* 139 */ "ToBlob", + /* 140 */ "ToNumeric", + /* 141 */ "ToInt", + /* 142 */ "ToReal", +}; +#endif diff --git a/extensions/sqlite/sqlite-source/opcodes.h b/extensions/sqlite/sqlite-source/opcodes.h new file mode 100644 index 00000000..c4b57608 --- /dev/null +++ b/extensions/sqlite/sqlite-source/opcodes.h @@ -0,0 +1,160 @@ +/* Automatically generated. Do not edit */ +/* See the mkopcodeh.awk script for details */ +#define OP_MemLoad 1 +#define OP_VNext 2 +#define OP_HexBlob 126 /* same as TK_BLOB */ +#define OP_Column 3 +#define OP_SetCookie 4 +#define OP_IfMemPos 5 +#define OP_Real 125 /* same as TK_FLOAT */ +#define OP_Sequence 6 +#define OP_MoveGt 7 +#define OP_Ge 72 /* same as TK_GE */ +#define OP_RowKey 8 +#define OP_Eq 68 /* same as TK_EQ */ +#define OP_OpenWrite 9 +#define OP_NotNull 66 /* same as TK_NOTNULL */ +#define OP_If 10 +#define OP_ToInt 141 /* same as TK_TO_INT */ +#define OP_String8 88 /* 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 69 /* same as TK_GT */ +#define OP_IntegrityCk 18 +#define OP_Sort 19 +#define OP_Function 20 +#define OP_And 61 /* same as TK_AND */ +#define OP_Subtract 79 /* same as TK_MINUS */ +#define OP_Noop 21 +#define OP_Return 22 +#define OP_Remainder 82 /* same as TK_REM */ +#define OP_NewRowid 23 +#define OP_Multiply 80 /* same as TK_STAR */ +#define OP_IfMemNeg 24 +#define OP_Variable 25 +#define OP_String 26 +#define OP_RealAffinity 27 +#define OP_VRename 28 +#define OP_ParseSchema 29 +#define OP_VOpen 30 +#define OP_Close 31 +#define OP_CreateIndex 32 +#define OP_IsUnique 33 +#define OP_NotFound 34 +#define OP_Int64 35 +#define OP_MustBeInt 36 +#define OP_Halt 37 +#define OP_Rowid 38 +#define OP_IdxLT 39 +#define OP_AddImm 40 +#define OP_Statement 41 +#define OP_RowData 42 +#define OP_MemMax 43 +#define OP_Push 44 +#define OP_Or 60 /* same as TK_OR */ +#define OP_NotExists 45 +#define OP_MemIncr 46 +#define OP_Gosub 47 +#define OP_Divide 81 /* same as TK_SLASH */ +#define OP_Integer 48 +#define OP_ToNumeric 140 /* same as TK_TO_NUMERIC*/ +#define OP_MemInt 49 +#define OP_Prev 50 +#define OP_Concat 83 /* same as TK_CONCAT */ +#define OP_BitAnd 74 /* same as TK_BITAND */ +#define OP_VColumn 51 +#define OP_CreateTable 52 +#define OP_Last 53 +#define OP_IsNull 65 /* same as TK_ISNULL */ +#define OP_IncrVacuum 54 +#define OP_IdxRowid 55 +#define OP_MakeIdxRec 56 +#define OP_ShiftRight 77 /* same as TK_RSHIFT */ +#define OP_ResetCount 57 +#define OP_FifoWrite 58 +#define OP_Callback 59 +#define OP_ContextPush 62 +#define OP_DropTrigger 63 +#define OP_DropIndex 64 +#define OP_IdxGE 73 +#define OP_IdxDelete 84 +#define OP_Vacuum 86 +#define OP_MoveLe 89 +#define OP_IfNot 90 +#define OP_DropTable 91 +#define OP_MakeRecord 92 +#define OP_ToBlob 139 /* same as TK_TO_BLOB */ +#define OP_Delete 93 +#define OP_AggFinal 94 +#define OP_ShiftLeft 76 /* same as TK_LSHIFT */ +#define OP_Dup 95 +#define OP_Goto 96 +#define OP_TableLock 97 +#define OP_FifoRead 98 +#define OP_Clear 99 +#define OP_IdxGT 100 +#define OP_MoveLt 101 +#define OP_Le 70 /* same as TK_LE */ +#define OP_VerifyCookie 102 +#define OP_AggStep 103 +#define OP_Pull 104 +#define OP_ToText 138 /* same as TK_TO_TEXT */ +#define OP_Not 16 /* same as TK_NOT */ +#define OP_ToReal 142 /* same as TK_TO_REAL */ +#define OP_SetNumColumns 105 +#define OP_AbsValue 106 +#define OP_Transaction 107 +#define OP_VFilter 108 +#define OP_Negative 85 /* same as TK_UMINUS */ +#define OP_Ne 67 /* same as TK_NE */ +#define OP_VDestroy 109 +#define OP_ContextPop 110 +#define OP_BitOr 75 /* same as TK_BITOR */ +#define OP_Next 111 +#define OP_IdxInsert 112 +#define OP_Distinct 113 +#define OP_Lt 71 /* same as TK_LT */ +#define OP_Insert 114 +#define OP_Destroy 115 +#define OP_ReadCookie 116 +#define OP_ForceInt 117 +#define OP_LoadAnalysis 118 +#define OP_Explain 119 +#define OP_IfMemZero 120 +#define OP_OpenPseudo 121 +#define OP_OpenEphemeral 122 +#define OP_Null 123 +#define OP_Blob 124 +#define OP_Add 78 /* same as TK_PLUS */ +#define OP_MemStore 127 +#define OP_Rewind 128 +#define OP_MoveGe 129 +#define OP_VBegin 130 +#define OP_VUpdate 131 +#define OP_BitNot 87 /* same as TK_BITNOT */ +#define OP_VCreate 132 +#define OP_MemMove 133 +#define OP_MemNull 134 +#define OP_Found 135 +#define OP_NullRow 136 + +/* The following opcode values are never used */ +#define OP_NotUsed_137 137 + +/* 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 0xf96b +#define NOPUSH_MASK_2 0xfbb6 +#define NOPUSH_MASK_3 0xfe64 +#define NOPUSH_MASK_4 0xffff +#define NOPUSH_MASK_5 0x6ef7 +#define NOPUSH_MASK_6 0xfbfb +#define NOPUSH_MASK_7 0x8767 +#define NOPUSH_MASK_8 0x7d9f +#define NOPUSH_MASK_9 0x0000 diff --git a/extensions/sqlite/sqlite-source/os.c b/extensions/sqlite/sqlite-source/os.c new file mode 100644 index 00000000..7cd1ab99 --- /dev/null +++ b/extensions/sqlite/sqlite-source/os.c @@ -0,0 +1,96 @@ +/* +** 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" +#undef _SQLITE_OS_C_ + +/* +** 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); +} +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 sqlite3OsCheckReservedLock(OsFile *id){ + return id->pMethod->xCheckReservedLock(id); +} +int sqlite3OsSectorSize(OsFile *id){ + int (*xSectorSize)(OsFile*) = id->pMethod->xSectorSize; + return xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE; +} + +#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG) + /* These methods are currently only used for testing and debugging. */ + int sqlite3OsFileHandle(OsFile *id){ + return id->pMethod->xFileHandle(id); + } + int sqlite3OsLockState(OsFile *id){ + return id->pMethod->xLockState(id); + } +#endif + +#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 diff --git a/extensions/sqlite/sqlite-source/os.h b/extensions/sqlite/sqlite-source/os.h new file mode 100644 index 00000000..76a9f2c4 --- /dev/null +++ b/extensions/sqlite/sqlite-source/os.h @@ -0,0 +1,548 @@ +/* +** 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_OTHER) +# if OS_OTHER==1 +# undef OS_UNIX +# define OS_UNIX 0 +# undef OS_WIN +# define OS_WIN 0 +# undef OS_OS2 +# define OS_OS2 0 +# else +# undef OS_OTHER +# endif +#endif +#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 +# define SQLITE_TEMPNAME_SIZE (MAX_PATH+50) +#elif OS_OS2 +# if (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 3) && defined(OS2_HIGH_MEMORY) +# include /* has to be included before os2.h for linking to work */ +# endif +# define INCL_DOSDATETIME +# define INCL_DOSFILEMGR +# define INCL_DOSERRORS +# define INCL_DOSMISC +# define INCL_DOSPROCESS +# define INCL_DOSMODULEMGR +# include +# 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 + +/* +** The default size of a disk sector +*/ +#ifndef SQLITE_DEFAULT_SECTOR_SIZE +# define SQLITE_DEFAULT_SECTOR_SIZE 512 +#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); + int (*xSectorSize)(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 sqlite3OsFileSize(OsFile*, i64 *pSize); +int sqlite3OsLock(OsFile*, int); +int sqlite3OsUnlock(OsFile*, int); +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 sqlite3OsSectorSize(OsFile *id); +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 defined(SQLITE_TEST) || defined(SQLITE_DEBUG) + int sqlite3OsFileHandle(OsFile *id); + int sqlite3OsLockState(OsFile *id); +#endif + +/* +** 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 + + +#if defined(_SQLITE_OS_C_) || defined(SQLITE_AMALGAMATION) + /* + ** The os.c file implements the global virtual function table. + ** We have to put this file here because the initializers + ** (ex: sqlite3OsRandomSeed) are macros that are about to be + ** redefined. + */ + 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_ */ diff --git a/extensions/sqlite/sqlite-source/os_common.h b/extensions/sqlite/sqlite-source/os_common.h new file mode 100644 index 00000000..ba52314c --- /dev/null +++ b/extensions/sqlite/sqlite-source/os_common.h @@ -0,0 +1,198 @@ +/* +** 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 +#define OSTRACE1(X) if( sqlite3_os_trace ) sqlite3DebugPrintf(X) +#define OSTRACE2(X,Y) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y) +#define OSTRACE3(X,Y,Z) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z) +#define OSTRACE4(X,Y,Z,A) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z,A) +#define OSTRACE5(X,Y,Z,A,B) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z,A,B) +#define OSTRACE6(X,Y,Z,A,B,C) \ + if(sqlite3_os_trace) sqlite3DebugPrintf(X,Y,Z,A,B,C) +#define OSTRACE7(X,Y,Z,A,B,C,D) \ + if(sqlite3_os_trace) sqlite3DebugPrintf(X,Y,Z,A,B,C,D) +#else +#define OSTRACE1(X) +#define OSTRACE2(X,Y) +#define OSTRACE3(X,Y,Z) +#define OSTRACE4(X,Y,Z,A) +#define OSTRACE5(X,Y,Z,A,B) +#define OSTRACE6(X,Y,Z,A,B,C) +#define OSTRACE7(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_io_error_persist = 0; +int sqlite3_diskfull_pending = 0; +int sqlite3_diskfull = 0; +#define SimulateIOError(CODE) \ + if( sqlite3_io_error_pending || sqlite3_io_error_hit ) \ + if( sqlite3_io_error_pending-- == 1 \ + || (sqlite3_io_error_persist && sqlite3_io_error_hit) ) \ + { local_ioerr(); CODE; } +static void local_ioerr(){ + IOTRACE(("IOERR\n")); + sqlite3_io_error_hit = 1; +} +#define SimulateDiskfullError(CODE) \ + if( sqlite3_diskfull_pending ){ \ + if( sqlite3_diskfull_pending == 1 ){ \ + local_ioerr(); \ + sqlite3_diskfull = 1; \ + sqlite3_io_error_hit = 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 + +/* +** The default size of a disk sector +*/ +#ifndef PAGER_SECTOR_SIZE +# define PAGER_SECTOR_SIZE 512 +#endif diff --git a/extensions/sqlite/sqlite-source/os_unix.c b/extensions/sqlite/sqlite-source/os_unix.c new file mode 100644 index 00000000..cc8449f5 --- /dev/null +++ b/extensions/sqlite/sqlite-source/os_unix.c @@ -0,0 +1,2935 @@ +/* +** 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 code that is specific to Unix systems. +*/ +#include "sqliteInt.h" +#include "os.h" +#if OS_UNIX /* This file is used on unix only */ + +/* #define SQLITE_ENABLE_LOCKING_STYLE 0 */ + +/* +** These #defines should enable >2GB file support on Posix if the +** underlying operating system supports it. If the OS lacks +** large file support, these should be no-ops. +** +** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch +** on the compiler command line. This is necessary if you are compiling +** on a recent machine (ex: RedHat 7.2) but you want your code to work +** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2 +** without this option, LFS is enable. But LFS does not exist in the kernel +** in RedHat 6.0, so the code won't work. Hence, for maximum binary +** portability you should omit LFS. +*/ +#ifndef SQLITE_DISABLE_LFS +# define _LARGE_FILE 1 +# ifndef _FILE_OFFSET_BITS +# define _FILE_OFFSET_BITS 64 +# endif +# define _LARGEFILE_SOURCE 1 +#endif + +/* +** standard include files. +*/ +#include +#include +#include +#include +#include +#include +#include +#ifdef SQLITE_ENABLE_LOCKING_STYLE +#include +#include +#include +#endif /* SQLITE_ENABLE_LOCKING_STYLE */ + +/* +** If we are to be thread-safe, include the pthreads header and define +** the SQLITE_UNIX_THREADS macro. +*/ +#ifndef THREADSAFE +# define THREADSAFE 1 +#endif +#if THREADSAFE +# include +# define SQLITE_UNIX_THREADS 1 +#endif + +/* +** Default permissions when creating a new file +*/ +#ifndef SQLITE_DEFAULT_FILE_PERMISSIONS +# define SQLITE_DEFAULT_FILE_PERMISSIONS 0644 +#endif + + + +/* +** The unixFile structure is subclass of OsFile specific for the unix +** protability layer. +*/ +typedef struct unixFile unixFile; +struct unixFile { + IoMethod const *pMethod; /* Always the first entry */ + struct openCnt *pOpen; /* Info about all open fd's on this inode */ + struct lockInfo *pLock; /* Info about locks on this inode */ +#ifdef SQLITE_ENABLE_LOCKING_STYLE + void *lockingContext; /* Locking style specific state */ +#endif /* SQLITE_ENABLE_LOCKING_STYLE */ + int h; /* The file descriptor */ + unsigned char locktype; /* The type of lock held on this fd */ + unsigned char isOpen; /* True if needs to be closed */ + unsigned char fullSync; /* Use F_FULLSYNC if available */ + int dirfd; /* File descriptor for the directory */ + i64 offset; /* Seek offset */ +#ifdef SQLITE_UNIX_THREADS + pthread_t tid; /* The thread that "owns" this OsFile */ +#endif +}; + +/* +** Provide the ability to override some OS-layer functions during +** testing. This is used to simulate OS crashes to verify that +** commits are atomic even in the event of an OS crash. +*/ +#ifdef SQLITE_CRASH_TEST + extern int sqlite3CrashTestEnable; + extern int sqlite3CrashOpenReadWrite(const char*, OsFile**, int*); + extern int sqlite3CrashOpenExclusive(const char*, OsFile**, int); + extern int sqlite3CrashOpenReadOnly(const char*, OsFile**, int); +# define CRASH_TEST_OVERRIDE(X,A,B,C) \ + if(sqlite3CrashTestEnable){ return X(A,B,C); } +#else +# define CRASH_TEST_OVERRIDE(X,A,B,C) /* no-op */ +#endif + + +/* +** Include code that is common to all os_*.c files +*/ +#include "os_common.h" + +/* +** Do not include any of the File I/O interface procedures if the +** SQLITE_OMIT_DISKIO macro is defined (indicating that the database +** will be in-memory only) +*/ +#ifndef SQLITE_OMIT_DISKIO + + +/* +** Define various macros that are missing from some systems. +*/ +#ifndef O_LARGEFILE +# define O_LARGEFILE 0 +#endif +#ifdef SQLITE_DISABLE_LFS +# undef O_LARGEFILE +# define O_LARGEFILE 0 +#endif +#ifndef O_NOFOLLOW +# define O_NOFOLLOW 0 +#endif +#ifndef O_BINARY +# define O_BINARY 0 +#endif + +/* +** The DJGPP compiler environment looks mostly like Unix, but it +** lacks the fcntl() system call. So redefine fcntl() to be something +** that always succeeds. This means that locking does not occur under +** DJGPP. But it's DOS - what did you expect? +*/ +#ifdef __DJGPP__ +# define fcntl(A,B,C) 0 +#endif + +/* +** The threadid macro resolves to the thread-id or to 0. Used for +** testing and debugging only. +*/ +#ifdef SQLITE_UNIX_THREADS +#define threadid pthread_self() +#else +#define threadid 0 +#endif + +/* +** Set or check the OsFile.tid field. This field is set when an OsFile +** is first opened. All subsequent uses of the OsFile verify that the +** same thread is operating on the OsFile. Some operating systems do +** not allow locks to be overridden by other threads and that restriction +** means that sqlite3* database handles cannot be moved from one thread +** to another. This logic makes sure a user does not try to do that +** by mistake. +** +** Version 3.3.1 (2006-01-15): OsFiles can be moved from one thread to +** another as long as we are running on a system that supports threads +** overriding each others locks (which now the most common behavior) +** or if no locks are held. But the OsFile.pLock field needs to be +** recomputed because its key includes the thread-id. See the +** transferOwnership() function below for additional information +*/ +#if defined(SQLITE_UNIX_THREADS) +# define SET_THREADID(X) (X)->tid = pthread_self() +# define CHECK_THREADID(X) (threadsOverrideEachOthersLocks==0 && \ + !pthread_equal((X)->tid, pthread_self())) +#else +# define SET_THREADID(X) +# define CHECK_THREADID(X) 0 +#endif + +/* +** Here is the dirt on POSIX advisory locks: ANSI STD 1003.1 (1996) +** section 6.5.2.2 lines 483 through 490 specify that when a process +** sets or clears a lock, that operation overrides any prior locks set +** by the same process. It does not explicitly say so, but this implies +** that it overrides locks set by the same process using a different +** file descriptor. Consider this test case: +** +** int fd1 = open("./file1", O_RDWR|O_CREAT, 0644); +** int fd2 = open("./file2", O_RDWR|O_CREAT, 0644); +** +** Suppose ./file1 and ./file2 are really the same file (because +** one is a hard or symbolic link to the other) then if you set +** an exclusive lock on fd1, then try to get an exclusive lock +** on fd2, it works. I would have expected the second lock to +** fail since there was already a lock on the file due to fd1. +** But not so. Since both locks came from the same process, the +** second overrides the first, even though they were on different +** file descriptors opened on different file names. +** +** Bummer. If you ask me, this is broken. Badly broken. It means +** that we cannot use POSIX locks to synchronize file access among +** competing threads of the same process. POSIX locks will work fine +** to synchronize access for threads in separate processes, but not +** threads within the same process. +** +** To work around the problem, SQLite has to manage file locks internally +** on its own. Whenever a new database is opened, we have to find the +** specific inode of the database file (the inode is determined by the +** st_dev and st_ino fields of the stat structure that fstat() fills in) +** and check for locks already existing on that inode. When locks are +** created or removed, we have to look at our own internal record of the +** locks to see if another thread has previously set a lock on that same +** inode. +** +** The OsFile structure for POSIX is no longer just an integer file +** descriptor. It is now a structure that holds the integer file +** descriptor and a pointer to a structure that describes the internal +** locks on the corresponding inode. There is one locking structure +** per inode, so if the same inode is opened twice, both OsFile structures +** point to the same locking structure. The locking structure keeps +** a reference count (so we will know when to delete it) and a "cnt" +** field that tells us its internal lock status. cnt==0 means the +** file is unlocked. cnt==-1 means the file has an exclusive lock. +** cnt>0 means there are cnt shared locks on the file. +** +** Any attempt to lock or unlock a file first checks the locking +** structure. The fcntl() system call is only invoked to set a +** POSIX lock if the internal lock structure transitions between +** a locked and an unlocked state. +** +** 2004-Jan-11: +** More recent discoveries about POSIX advisory locks. (The more +** I discover, the more I realize the a POSIX advisory locks are +** an abomination.) +** +** If you close a file descriptor that points to a file that has locks, +** all locks on that file that are owned by the current process are +** released. To work around this problem, each OsFile structure contains +** a pointer to an openCnt structure. There is one openCnt structure +** per open inode, which means that multiple OsFiles can point to a single +** openCnt. When an attempt is made to close an OsFile, if there are +** other OsFiles open on the same inode that are holding locks, the call +** to close() the file descriptor is deferred until all of the locks clear. +** The openCnt structure keeps a list of file descriptors that need to +** be closed and that list is walked (and cleared) when the last lock +** clears. +** +** First, under Linux threads, because each thread has a separate +** process ID, lock operations in one thread do not override locks +** to the same file in other threads. Linux threads behave like +** separate processes in this respect. But, if you close a file +** descriptor in linux threads, all locks are cleared, even locks +** on other threads and even though the other threads have different +** process IDs. Linux threads is inconsistent in this respect. +** (I'm beginning to think that linux threads is an abomination too.) +** The consequence of this all is that the hash table for the lockInfo +** structure has to include the process id as part of its key because +** locks in different threads are treated as distinct. But the +** openCnt structure should not include the process id in its +** key because close() clears lock on all threads, not just the current +** thread. Were it not for this goofiness in linux threads, we could +** combine the lockInfo and openCnt structures into a single structure. +** +** 2004-Jun-28: +** On some versions of linux, threads can override each others locks. +** On others not. Sometimes you can change the behavior on the same +** system by setting the LD_ASSUME_KERNEL environment variable. The +** POSIX standard is silent as to which behavior is correct, as far +** as I can tell, so other versions of unix might show the same +** inconsistency. There is no little doubt in my mind that posix +** advisory locks and linux threads are profoundly broken. +** +** To work around the inconsistencies, we have to test at runtime +** whether or not threads can override each others locks. This test +** is run once, the first time any lock is attempted. A static +** variable is set to record the results of this test for future +** use. +*/ + +/* +** An instance of the following structure serves as the key used +** to locate a particular lockInfo structure given its inode. +** +** If threads cannot override each others locks, then we set the +** lockKey.tid field to the thread ID. If threads can override +** each others locks then tid is always set to zero. tid is omitted +** if we compile without threading support. +*/ +struct lockKey { + dev_t dev; /* Device number */ + ino_t ino; /* Inode number */ +#ifdef SQLITE_UNIX_THREADS + pthread_t tid; /* Thread ID or zero if threads can override each other */ +#endif +}; + +/* +** An instance of the following structure is allocated for each open +** inode on each thread with a different process ID. (Threads have +** different process IDs on linux, but not on most other unixes.) +** +** A single inode can have multiple file descriptors, so each OsFile +** structure contains a pointer to an instance of this object and this +** object keeps a count of the number of OsFiles pointing to it. +*/ +struct lockInfo { + struct lockKey key; /* The lookup key */ + int cnt; /* Number of SHARED locks held */ + int locktype; /* One of SHARED_LOCK, RESERVED_LOCK etc. */ + int nRef; /* Number of pointers to this structure */ +}; + +/* +** An instance of the following structure serves as the key used +** to locate a particular openCnt structure given its inode. This +** is the same as the lockKey except that the thread ID is omitted. +*/ +struct openKey { + dev_t dev; /* Device number */ + ino_t ino; /* Inode number */ +}; + +/* +** An instance of the following structure is allocated for each open +** inode. This structure keeps track of the number of locks on that +** inode. If a close is attempted against an inode that is holding +** locks, the close is deferred until all locks clear by adding the +** file descriptor to be closed to the pending list. +*/ +struct openCnt { + struct openKey key; /* The lookup key */ + int nRef; /* Number of pointers to this structure */ + int nLock; /* Number of outstanding locks */ + int nPending; /* Number of pending close() operations */ + int *aPending; /* Malloced space holding fd's awaiting a close() */ +}; + +/* +** These hash tables map inodes and file descriptors (really, lockKey and +** openKey structures) into lockInfo and openCnt structures. Access to +** these hash tables must be protected by a mutex. +*/ +static Hash lockHash = {SQLITE_HASH_BINARY, 0, 0, 0, + sqlite3ThreadSafeMalloc, sqlite3ThreadSafeFree, 0, 0}; +static Hash openHash = {SQLITE_HASH_BINARY, 0, 0, 0, + sqlite3ThreadSafeMalloc, sqlite3ThreadSafeFree, 0, 0}; + +#ifdef SQLITE_ENABLE_LOCKING_STYLE +/* +** The locking styles are associated with the different file locking +** capabilities supported by different file systems. +** +** POSIX locking style fully supports shared and exclusive byte-range locks +** ADP locking only supports exclusive byte-range locks +** FLOCK only supports a single file-global exclusive lock +** DOTLOCK isn't a true locking style, it refers to the use of a special +** file named the same as the database file with a '.lock' extension, this +** can be used on file systems that do not offer any reliable file locking +** NO locking means that no locking will be attempted, this is only used for +** read-only file systems currently +** UNSUPPORTED means that no locking will be attempted, this is only used for +** file systems that are known to be unsupported +*/ +typedef enum { + posixLockingStyle = 0, /* standard posix-advisory locks */ + afpLockingStyle, /* use afp locks */ + flockLockingStyle, /* use flock() */ + dotlockLockingStyle, /* use .lock files */ + noLockingStyle, /* useful for read-only file system */ + unsupportedLockingStyle /* indicates unsupported file system */ +} sqlite3LockingStyle; +#endif /* SQLITE_ENABLE_LOCKING_STYLE */ + +#ifdef SQLITE_UNIX_THREADS +/* +** This variable records whether or not threads can override each others +** locks. +** +** 0: No. Threads cannot override each others locks. +** 1: Yes. Threads can override each others locks. +** -1: We don't know yet. +** +** On some systems, we know at compile-time if threads can override each +** others locks. On those systems, the SQLITE_THREAD_OVERRIDE_LOCK macro +** will be set appropriately. On other systems, we have to check at +** runtime. On these latter systems, SQLTIE_THREAD_OVERRIDE_LOCK is +** undefined. +** +** This variable normally has file scope only. But during testing, we make +** it a global so that the test code can change its value in order to verify +** that the right stuff happens in either case. +*/ +#ifndef SQLITE_THREAD_OVERRIDE_LOCK +# define SQLITE_THREAD_OVERRIDE_LOCK -1 +#endif +#ifdef SQLITE_TEST +int threadsOverrideEachOthersLocks = SQLITE_THREAD_OVERRIDE_LOCK; +#else +static int threadsOverrideEachOthersLocks = SQLITE_THREAD_OVERRIDE_LOCK; +#endif + +/* +** This structure holds information passed into individual test +** threads by the testThreadLockingBehavior() routine. +*/ +struct threadTestData { + int fd; /* File to be locked */ + struct flock lock; /* The locking operation */ + int result; /* Result of the locking operation */ +}; + +#ifdef SQLITE_LOCK_TRACE +/* +** Print out information about all locking operations. +** +** This routine is used for troubleshooting locks on multithreaded +** platforms. Enable by compiling with the -DSQLITE_LOCK_TRACE +** command-line option on the compiler. This code is normally +** turned off. +*/ +static int lockTrace(int fd, int op, struct flock *p){ + char *zOpName, *zType; + int s; + int savedErrno; + if( op==F_GETLK ){ + zOpName = "GETLK"; + }else if( op==F_SETLK ){ + zOpName = "SETLK"; + }else{ + s = fcntl(fd, op, p); + sqlite3DebugPrintf("fcntl unknown %d %d %d\n", fd, op, s); + return s; + } + if( p->l_type==F_RDLCK ){ + zType = "RDLCK"; + }else if( p->l_type==F_WRLCK ){ + zType = "WRLCK"; + }else if( p->l_type==F_UNLCK ){ + zType = "UNLCK"; + }else{ + assert( 0 ); + } + assert( p->l_whence==SEEK_SET ); + s = fcntl(fd, op, p); + savedErrno = errno; + sqlite3DebugPrintf("fcntl %d %d %s %s %d %d %d %d\n", + threadid, fd, zOpName, zType, (int)p->l_start, (int)p->l_len, + (int)p->l_pid, s); + if( s==(-1) && op==F_SETLK && (p->l_type==F_RDLCK || p->l_type==F_WRLCK) ){ + struct flock l2; + l2 = *p; + fcntl(fd, F_GETLK, &l2); + if( l2.l_type==F_RDLCK ){ + zType = "RDLCK"; + }else if( l2.l_type==F_WRLCK ){ + zType = "WRLCK"; + }else if( l2.l_type==F_UNLCK ){ + zType = "UNLCK"; + }else{ + assert( 0 ); + } + sqlite3DebugPrintf("fcntl-failure-reason: %s %d %d %d\n", + zType, (int)l2.l_start, (int)l2.l_len, (int)l2.l_pid); + } + errno = savedErrno; + return s; +} +#define fcntl lockTrace +#endif /* SQLITE_LOCK_TRACE */ + +/* +** The testThreadLockingBehavior() routine launches two separate +** threads on this routine. This routine attempts to lock a file +** descriptor then returns. The success or failure of that attempt +** allows the testThreadLockingBehavior() procedure to determine +** whether or not threads can override each others locks. +*/ +static void *threadLockingTest(void *pArg){ + struct threadTestData *pData = (struct threadTestData*)pArg; + pData->result = fcntl(pData->fd, F_SETLK, &pData->lock); + return pArg; +} + +/* +** This procedure attempts to determine whether or not threads +** can override each others locks then sets the +** threadsOverrideEachOthersLocks variable appropriately. +*/ +static void testThreadLockingBehavior(int fd_orig){ + int fd; + struct threadTestData d[2]; + pthread_t t[2]; + + fd = dup(fd_orig); + if( fd<0 ) return; + memset(d, 0, sizeof(d)); + d[0].fd = fd; + d[0].lock.l_type = F_RDLCK; + d[0].lock.l_len = 1; + d[0].lock.l_start = 0; + d[0].lock.l_whence = SEEK_SET; + d[1] = d[0]; + d[1].lock.l_type = F_WRLCK; + pthread_create(&t[0], 0, threadLockingTest, &d[0]); + pthread_create(&t[1], 0, threadLockingTest, &d[1]); + pthread_join(t[0], 0); + pthread_join(t[1], 0); + close(fd); + threadsOverrideEachOthersLocks = d[0].result==0 && d[1].result==0; +} +#endif /* SQLITE_UNIX_THREADS */ + +/* +** Release a lockInfo structure previously allocated by findLockInfo(). +*/ +static void releaseLockInfo(struct lockInfo *pLock){ + assert( sqlite3OsInMutex(1) ); + if (pLock == NULL) + return; + pLock->nRef--; + if( pLock->nRef==0 ){ + sqlite3HashInsert(&lockHash, &pLock->key, sizeof(pLock->key), 0); + sqlite3ThreadSafeFree(pLock); + } +} + +/* +** Release a openCnt structure previously allocated by findLockInfo(). +*/ +static void releaseOpenCnt(struct openCnt *pOpen){ + assert( sqlite3OsInMutex(1) ); + if (pOpen == NULL) + return; + pOpen->nRef--; + if( pOpen->nRef==0 ){ + sqlite3HashInsert(&openHash, &pOpen->key, sizeof(pOpen->key), 0); + free(pOpen->aPending); + sqlite3ThreadSafeFree(pOpen); + } +} + +#ifdef SQLITE_ENABLE_LOCKING_STYLE +/* +** Tests a byte-range locking query to see if byte range locks are +** supported, if not we fall back to dotlockLockingStyle. +*/ +static sqlite3LockingStyle sqlite3TestLockingStyle(const char *filePath, + int fd) { + /* test byte-range lock using fcntl */ + struct flock lockInfo; + + lockInfo.l_len = 1; + lockInfo.l_start = 0; + lockInfo.l_whence = SEEK_SET; + lockInfo.l_type = F_RDLCK; + + if (fcntl(fd, F_GETLK, &lockInfo) != -1) { + return posixLockingStyle; + } + + /* testing for flock can give false positives. So if if the above test + ** fails, then we fall back to using dot-lock style locking. + */ + return dotlockLockingStyle; +} + +/* +** Examines the f_fstypename entry in the statfs structure as returned by +** stat() for the file system hosting the database file, assigns the +** appropriate locking style based on it's value. These values and +** assignments are based on Darwin/OSX behavior and have not been tested on +** other systems. +*/ +static sqlite3LockingStyle sqlite3DetectLockingStyle(const char *filePath, + int fd) { + +#ifdef SQLITE_FIXED_LOCKING_STYLE + return (sqlite3LockingStyle)SQLITE_FIXED_LOCKING_STYLE; +#else + struct statfs fsInfo; + + if (statfs(filePath, &fsInfo) == -1) + return sqlite3TestLockingStyle(filePath, fd); + + if (fsInfo.f_flags & MNT_RDONLY) + return noLockingStyle; + + if( (!strcmp(fsInfo.f_fstypename, "hfs")) || + (!strcmp(fsInfo.f_fstypename, "ufs")) ) + return posixLockingStyle; + + if(!strcmp(fsInfo.f_fstypename, "afpfs")) + return afpLockingStyle; + + if(!strcmp(fsInfo.f_fstypename, "nfs")) + return sqlite3TestLockingStyle(filePath, fd); + + if(!strcmp(fsInfo.f_fstypename, "smbfs")) + return flockLockingStyle; + + if(!strcmp(fsInfo.f_fstypename, "msdos")) + return dotlockLockingStyle; + + if(!strcmp(fsInfo.f_fstypename, "webdav")) + return unsupportedLockingStyle; + + return sqlite3TestLockingStyle(filePath, fd); +#endif /* SQLITE_FIXED_LOCKING_STYLE */ +} + +#endif /* SQLITE_ENABLE_LOCKING_STYLE */ + +/* +** Given a file descriptor, locate lockInfo and openCnt structures that +** describes that file descriptor. Create new ones if necessary. The +** return values might be uninitialized if an error occurs. +** +** Return the number of errors. +*/ +static int findLockInfo( + int fd, /* The file descriptor used in the key */ + struct lockInfo **ppLock, /* Return the lockInfo structure here */ + struct openCnt **ppOpen /* Return the openCnt structure here */ +){ + int rc; + struct lockKey key1; + struct openKey key2; + struct stat statbuf; + struct lockInfo *pLock; + struct openCnt *pOpen; + rc = fstat(fd, &statbuf); + if( rc!=0 ) return 1; + + assert( sqlite3OsInMutex(1) ); + memset(&key1, 0, sizeof(key1)); + key1.dev = statbuf.st_dev; + key1.ino = statbuf.st_ino; +#ifdef SQLITE_UNIX_THREADS + if( threadsOverrideEachOthersLocks<0 ){ + testThreadLockingBehavior(fd); + } + key1.tid = threadsOverrideEachOthersLocks ? 0 : pthread_self(); +#endif + memset(&key2, 0, sizeof(key2)); + key2.dev = statbuf.st_dev; + key2.ino = statbuf.st_ino; + pLock = (struct lockInfo*)sqlite3HashFind(&lockHash, &key1, sizeof(key1)); + if( pLock==0 ){ + struct lockInfo *pOld; + pLock = sqlite3ThreadSafeMalloc( sizeof(*pLock) ); + if( pLock==0 ){ + rc = 1; + goto exit_findlockinfo; + } + pLock->key = key1; + pLock->nRef = 1; + pLock->cnt = 0; + pLock->locktype = 0; + pOld = sqlite3HashInsert(&lockHash, &pLock->key, sizeof(key1), pLock); + if( pOld!=0 ){ + assert( pOld==pLock ); + sqlite3ThreadSafeFree(pLock); + rc = 1; + goto exit_findlockinfo; + } + }else{ + pLock->nRef++; + } + *ppLock = pLock; + if( ppOpen!=0 ){ + pOpen = (struct openCnt*)sqlite3HashFind(&openHash, &key2, sizeof(key2)); + if( pOpen==0 ){ + struct openCnt *pOld; + pOpen = sqlite3ThreadSafeMalloc( sizeof(*pOpen) ); + if( pOpen==0 ){ + releaseLockInfo(pLock); + rc = 1; + goto exit_findlockinfo; + } + pOpen->key = key2; + pOpen->nRef = 1; + pOpen->nLock = 0; + pOpen->nPending = 0; + pOpen->aPending = 0; + pOld = sqlite3HashInsert(&openHash, &pOpen->key, sizeof(key2), pOpen); + if( pOld!=0 ){ + assert( pOld==pOpen ); + sqlite3ThreadSafeFree(pOpen); + releaseLockInfo(pLock); + rc = 1; + goto exit_findlockinfo; + } + }else{ + pOpen->nRef++; + } + *ppOpen = pOpen; + } + +exit_findlockinfo: + return rc; +} + +#ifdef SQLITE_DEBUG +/* +** Helper function for printing out trace information from debugging +** binaries. This returns the string represetation of the supplied +** integer lock-type. +*/ +static const char *locktypeName(int locktype){ + switch( locktype ){ + case NO_LOCK: return "NONE"; + case SHARED_LOCK: return "SHARED"; + case RESERVED_LOCK: return "RESERVED"; + case PENDING_LOCK: return "PENDING"; + case EXCLUSIVE_LOCK: return "EXCLUSIVE"; + } + return "ERROR"; +} +#endif + +/* +** If we are currently in a different thread than the thread that the +** unixFile argument belongs to, then transfer ownership of the unixFile +** over to the current thread. +** +** A unixFile is only owned by a thread on systems where one thread is +** unable to override locks created by a different thread. RedHat9 is +** an example of such a system. +** +** Ownership transfer is only allowed if the unixFile is currently unlocked. +** If the unixFile is locked and an ownership is wrong, then return +** SQLITE_MISUSE. SQLITE_OK is returned if everything works. +*/ +#ifdef SQLITE_UNIX_THREADS +static int transferOwnership(unixFile *pFile){ + int rc; + pthread_t hSelf; + if( threadsOverrideEachOthersLocks ){ + /* Ownership transfers not needed on this system */ + return SQLITE_OK; + } + hSelf = pthread_self(); + if( pthread_equal(pFile->tid, hSelf) ){ + /* We are still in the same thread */ + OSTRACE1("No-transfer, same thread\n"); + return SQLITE_OK; + } + if( pFile->locktype!=NO_LOCK ){ + /* We cannot change ownership while we are holding a lock! */ + return SQLITE_MISUSE; + } + OSTRACE4("Transfer ownership of %d from %d to %d\n", + pFile->h, pFile->tid, hSelf); + pFile->tid = hSelf; + if (pFile->pLock != NULL) { + releaseLockInfo(pFile->pLock); + rc = findLockInfo(pFile->h, &pFile->pLock, 0); + OSTRACE5("LOCK %d is now %s(%s,%d)\n", pFile->h, + locktypeName(pFile->locktype), + locktypeName(pFile->pLock->locktype), pFile->pLock->cnt); + return rc; + } else { + return SQLITE_OK; + } +} +#else + /* On single-threaded builds, ownership transfer is a no-op */ +# define transferOwnership(X) SQLITE_OK +#endif + +/* +** Delete the named file +*/ +int sqlite3UnixDelete(const char *zFilename){ + SimulateIOError(return SQLITE_IOERR_DELETE); + unlink(zFilename); + return SQLITE_OK; +} + +/* +** Return TRUE if the named file exists. +*/ +int sqlite3UnixFileExists(const char *zFilename){ + return access(zFilename, 0)==0; +} + +/* Forward declaration */ +static int allocateUnixFile( + int h, /* File descriptor of the open file */ + OsFile **pId, /* Write the real file descriptor here */ + const char *zFilename, /* Name of the file being opened */ + int delFlag /* If true, make sure the file deletes on close */ +); + +/* +** Attempt to open a file for both reading and writing. If that +** fails, try opening it read-only. If the file does not exist, +** try to create it. +** +** On success, a handle for the open file is written to *id +** and *pReadonly is set to 0 if the file was opened for reading and +** writing or 1 if the file was opened read-only. The function returns +** SQLITE_OK. +** +** On failure, the function returns SQLITE_CANTOPEN and leaves +** *id and *pReadonly unchanged. +*/ +int sqlite3UnixOpenReadWrite( + const char *zFilename, + OsFile **pId, + int *pReadonly +){ + int h; + + CRASH_TEST_OVERRIDE(sqlite3CrashOpenReadWrite, zFilename, pId, pReadonly); + assert( 0==*pId ); + h = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY, + SQLITE_DEFAULT_FILE_PERMISSIONS); + if( h<0 ){ +#ifdef EISDIR + if( errno==EISDIR ){ + return SQLITE_CANTOPEN; + } +#endif + h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY); + if( h<0 ){ + return SQLITE_CANTOPEN; + } + *pReadonly = 1; + }else{ + *pReadonly = 0; + } + return allocateUnixFile(h, pId, zFilename, 0); +} + + +/* +** Attempt to open a new file for exclusive access by this process. +** The file will be opened for both reading and writing. To avoid +** a potential security problem, we do not allow the file to have +** previously existed. Nor do we allow the file to be a symbolic +** link. +** +** If delFlag is true, then make arrangements to automatically delete +** the file when it is closed. +** +** On success, write the file handle into *id and return SQLITE_OK. +** +** On failure, return SQLITE_CANTOPEN. +*/ +int sqlite3UnixOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){ + int h; + + CRASH_TEST_OVERRIDE(sqlite3CrashOpenExclusive, zFilename, pId, delFlag); + assert( 0==*pId ); + h = open(zFilename, + O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY, + delFlag ? 0600 : SQLITE_DEFAULT_FILE_PERMISSIONS); + if( h<0 ){ + return SQLITE_CANTOPEN; + } + return allocateUnixFile(h, pId, zFilename, delFlag); +} + +/* +** Attempt to open a new file for read-only access. +** +** On success, write the file handle into *id and return SQLITE_OK. +** +** On failure, return SQLITE_CANTOPEN. +*/ +int sqlite3UnixOpenReadOnly(const char *zFilename, OsFile **pId){ + int h; + + CRASH_TEST_OVERRIDE(sqlite3CrashOpenReadOnly, zFilename, pId, 0); + assert( 0==*pId ); + h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY); + if( h<0 ){ + return SQLITE_CANTOPEN; + } + return allocateUnixFile(h, pId, zFilename, 0); +} + +/* +** Attempt to open a file descriptor for the directory that contains a +** file. This file descriptor can be used to fsync() the directory +** in order to make sure the creation of a new file is actually written +** to disk. +** +** This routine is only meaningful for Unix. It is a no-op under +** windows since windows does not support hard links. +** +** If FULL_FSYNC is enabled, this function is not longer useful, +** a FULL_FSYNC sync applies to all pending disk operations. +** +** On success, a handle for a previously open file at *id is +** updated with the new directory file descriptor and SQLITE_OK is +** returned. +** +** On failure, the function returns SQLITE_CANTOPEN and leaves +** *id unchanged. +*/ +static int unixOpenDirectory( + OsFile *id, + const char *zDirname +){ + int h; + unixFile *pFile = (unixFile*)id; + assert( pFile!=0 ); + SET_THREADID(pFile); + assert( pFile->dirfd<0 ); + pFile->dirfd = h = open(zDirname, O_RDONLY|O_BINARY, 0); + if( h<0 ){ + return SQLITE_CANTOPEN; + } +#ifdef FD_CLOEXEC + fcntl(h, F_SETFD, fcntl(h, F_GETFD, 0) | FD_CLOEXEC); +#endif + OSTRACE3("OPENDIR %-3d %s\n", h, zDirname); + return SQLITE_OK; +} + +/* +** Create a temporary file name in zBuf. zBuf must be big enough to +** hold at least SQLITE_TEMPNAME_SIZE characters. +*/ +int sqlite3UnixTempFileName(char *zBuf){ + static const char *azDirs[] = { + 0, + "/var/tmp", + "/usr/tmp", + "/tmp", + ".", + }; + static const unsigned char zChars[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789"; + int i, j; + struct stat buf; + const char *zDir = "."; + azDirs[0] = sqlite3_temp_directory; + for(i=0; ioffset then read cnt bytes into pBuf. +** Return the number of bytes actually read. Update the offset. +*/ +static int seekAndRead(unixFile *id, void *pBuf, int cnt){ + int got; + i64 newOffset; + TIMER_START; +#if defined(USE_PREAD) + got = pread(id->h, pBuf, cnt, id->offset); + SimulateIOError( got = -1 ); +#elif defined(USE_PREAD64) + got = pread64(id->h, pBuf, cnt, id->offset); + SimulateIOError( got = -1 ); +#else + newOffset = lseek(id->h, id->offset, SEEK_SET); + SimulateIOError( newOffset-- ); + if( newOffset!=id->offset ){ + return -1; + } + got = read(id->h, pBuf, cnt); +#endif + TIMER_END; + OSTRACE5("READ %-3d %5d %7lld %d\n", id->h, got, id->offset, TIMER_ELAPSED); + if( got>0 ){ + id->offset += got; + } + return got; +} + +/* +** Read data from a file into a buffer. Return SQLITE_OK if all +** bytes were read successfully and SQLITE_IOERR if anything goes +** wrong. +*/ +static int unixRead(OsFile *id, void *pBuf, int amt){ + int got; + assert( id ); + got = seekAndRead((unixFile*)id, pBuf, amt); + if( got==amt ){ + return SQLITE_OK; + }else if( got<0 ){ + return SQLITE_IOERR_READ; + }else{ + memset(&((char*)pBuf)[got], 0, amt-got); + return SQLITE_IOERR_SHORT_READ; + } +} + +/* +** Seek to the offset in id->offset then read cnt bytes into pBuf. +** Return the number of bytes actually read. Update the offset. +*/ +static int seekAndWrite(unixFile *id, const void *pBuf, int cnt){ + int got; + i64 newOffset; + TIMER_START; +#if defined(USE_PREAD) + got = pwrite(id->h, pBuf, cnt, id->offset); +#elif defined(USE_PREAD64) + got = pwrite64(id->h, pBuf, cnt, id->offset); +#else + newOffset = lseek(id->h, id->offset, SEEK_SET); + if( newOffset!=id->offset ){ + return -1; + } + got = write(id->h, pBuf, cnt); +#endif + TIMER_END; + OSTRACE5("WRITE %-3d %5d %7lld %d\n", id->h, got, id->offset, TIMER_ELAPSED); + if( got>0 ){ + id->offset += got; + } + return got; +} + + +/* +** Write data from a buffer into a file. Return SQLITE_OK on success +** or some other error code on failure. +*/ +static int unixWrite(OsFile *id, const void *pBuf, int amt){ + int wrote = 0; + assert( id ); + assert( amt>0 ); + while( amt>0 && (wrote = seekAndWrite((unixFile*)id, pBuf, amt))>0 ){ + amt -= wrote; + pBuf = &((char*)pBuf)[wrote]; + } + SimulateIOError(( wrote=(-1), amt=1 )); + SimulateDiskfullError(( wrote=0, amt=1 )); + if( amt>0 ){ + if( wrote<0 ){ + return SQLITE_IOERR_WRITE; + }else{ + return SQLITE_FULL; + } + } + return SQLITE_OK; +} + +/* +** Move the read/write pointer in a file. +*/ +static int unixSeek(OsFile *id, i64 offset){ + assert( id ); +#ifdef SQLITE_TEST + if( offset ) SimulateDiskfullError(return SQLITE_FULL); +#endif + ((unixFile*)id)->offset = offset; + return SQLITE_OK; +} + +#ifdef SQLITE_TEST +/* +** Count the number of fullsyncs and normal syncs. This is used to test +** that syncs and fullsyncs are occuring at the right times. +*/ +int sqlite3_sync_count = 0; +int sqlite3_fullsync_count = 0; +#endif + +/* +** Use the fdatasync() API only if the HAVE_FDATASYNC macro is defined. +** Otherwise use fsync() in its place. +*/ +#ifndef HAVE_FDATASYNC +# define fdatasync fsync +#endif + +/* +** Define HAVE_FULLFSYNC to 0 or 1 depending on whether or not +** the F_FULLFSYNC macro is defined. F_FULLFSYNC is currently +** only available on Mac OS X. But that could change. +*/ +#ifdef F_FULLFSYNC +# define HAVE_FULLFSYNC 1 +#else +# define HAVE_FULLFSYNC 0 +#endif + + +/* +** The fsync() system call does not work as advertised on many +** unix systems. The following procedure is an attempt to make +** it work better. +** +** The SQLITE_NO_SYNC macro disables all fsync()s. This is useful +** for testing when we want to run through the test suite quickly. +** You are strongly advised *not* to deploy with SQLITE_NO_SYNC +** enabled, however, since with SQLITE_NO_SYNC enabled, an OS crash +** or power failure will likely corrupt the database file. +*/ +static int full_fsync(int fd, int fullSync, int dataOnly){ + int rc; + + /* Record the number of times that we do a normal fsync() and + ** FULLSYNC. This is used during testing to verify that this procedure + ** gets called with the correct arguments. + */ +#ifdef SQLITE_TEST + if( fullSync ) sqlite3_fullsync_count++; + sqlite3_sync_count++; +#endif + + /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a + ** no-op + */ +#ifdef SQLITE_NO_SYNC + rc = SQLITE_OK; +#else + +#if HAVE_FULLFSYNC + if( fullSync ){ + rc = fcntl(fd, F_FULLFSYNC, 0); + }else{ + rc = 1; + } + /* If the FULLFSYNC failed, fall back to attempting an fsync(). + * It shouldn't be possible for fullfsync to fail on the local + * file system (on OSX), so failure indicates that FULLFSYNC + * isn't supported for this file system. So, attempt an fsync + * and (for now) ignore the overhead of a superfluous fcntl call. + * It'd be better to detect fullfsync support once and avoid + * the fcntl call every time sync is called. + */ + if( rc ) rc = fsync(fd); + +#else + if( dataOnly ){ + rc = fdatasync(fd); + }else{ + rc = fsync(fd); + } +#endif /* HAVE_FULLFSYNC */ +#endif /* defined(SQLITE_NO_SYNC) */ + + return rc; +} + +/* +** Make sure all writes to a particular file are committed to disk. +** +** If dataOnly==0 then both the file itself and its metadata (file +** size, access time, etc) are synced. If dataOnly!=0 then only the +** file data is synced. +** +** Under Unix, also make sure that the directory entry for the file +** has been created by fsync-ing the directory that contains the file. +** If we do not do this and we encounter a power failure, the directory +** entry for the journal might not exist after we reboot. The next +** SQLite to access the file will not know that the journal exists (because +** the directory entry for the journal was never created) and the transaction +** will not roll back - possibly leading to database corruption. +*/ +static int unixSync(OsFile *id, int dataOnly){ + int rc; + unixFile *pFile = (unixFile*)id; + assert( pFile ); + OSTRACE2("SYNC %-3d\n", pFile->h); + rc = full_fsync(pFile->h, pFile->fullSync, dataOnly); + SimulateIOError( rc=1 ); + if( rc ){ + return SQLITE_IOERR_FSYNC; + } + if( pFile->dirfd>=0 ){ + OSTRACE4("DIRSYNC %-3d (have_fullfsync=%d fullsync=%d)\n", pFile->dirfd, + HAVE_FULLFSYNC, pFile->fullSync); +#ifndef SQLITE_DISABLE_DIRSYNC + /* The directory sync is only attempted if full_fsync is + ** turned off or unavailable. If a full_fsync occurred above, + ** then the directory sync is superfluous. + */ + if( (!HAVE_FULLFSYNC || !pFile->fullSync) && full_fsync(pFile->dirfd,0,0) ){ + /* + ** We have received multiple reports of fsync() returning + ** errors when applied to directories on certain file systems. + ** A failed directory sync is not a big deal. So it seems + ** better to ignore the error. Ticket #1657 + */ + /* return SQLITE_IOERR; */ + } +#endif + close(pFile->dirfd); /* Only need to sync once, so close the directory */ + pFile->dirfd = -1; /* when we are done. */ + } + return SQLITE_OK; +} + +/* +** Sync the directory zDirname. This is a no-op on operating systems other +** than UNIX. +** +** This is used to make sure the master journal file has truely been deleted +** before making changes to individual journals on a multi-database commit. +** The F_FULLFSYNC option is not needed here. +*/ +int sqlite3UnixSyncDirectory(const char *zDirname){ +#ifdef SQLITE_DISABLE_DIRSYNC + return SQLITE_OK; +#else + int fd; + int r; + fd = open(zDirname, O_RDONLY|O_BINARY, 0); + OSTRACE3("DIRSYNC %-3d (%s)\n", fd, zDirname); + if( fd<0 ){ + return SQLITE_CANTOPEN; + } + r = fsync(fd); + close(fd); + SimulateIOError( r=1 ); + if( r ){ + return SQLITE_IOERR_DIR_FSYNC; + }else{ + return SQLITE_OK; + } +#endif +} + +/* +** Truncate an open file to a specified size +*/ +static int unixTruncate(OsFile *id, i64 nByte){ + int rc; + assert( id ); + rc = ftruncate(((unixFile*)id)->h, (off_t)nByte); + SimulateIOError( rc=1 ); + if( rc ){ + return SQLITE_IOERR_TRUNCATE; + }else{ + return SQLITE_OK; + } +} + +/* +** Determine the current size of a file in bytes +*/ +static int unixFileSize(OsFile *id, i64 *pSize){ + int rc; + struct stat buf; + assert( id ); + rc = fstat(((unixFile*)id)->h, &buf); + SimulateIOError( rc=1 ); + if( rc!=0 ){ + return SQLITE_IOERR_FSTAT; + } + *pSize = buf.st_size; + return SQLITE_OK; +} + +/* +** This routine checks if there is a RESERVED lock held on the specified +** file by this or any other process. If such a lock is held, return +** non-zero. If the file is unlocked or holds only SHARED locks, then +** return zero. +*/ +static int unixCheckReservedLock(OsFile *id){ + int r = 0; + unixFile *pFile = (unixFile*)id; + + assert( pFile ); + sqlite3OsEnterMutex(); /* Because pFile->pLock is shared across threads */ + + /* Check if a thread in this process holds such a lock */ + if( pFile->pLock->locktype>SHARED_LOCK ){ + r = 1; + } + + /* Otherwise see if some other process holds it. + */ + if( !r ){ + struct flock lock; + lock.l_whence = SEEK_SET; + lock.l_start = RESERVED_BYTE; + lock.l_len = 1; + lock.l_type = F_WRLCK; + fcntl(pFile->h, F_GETLK, &lock); + if( lock.l_type!=F_UNLCK ){ + r = 1; + } + } + + sqlite3OsLeaveMutex(); + OSTRACE3("TEST WR-LOCK %d %d\n", pFile->h, r); + + return r; +} + +/* +** Lock the file with the lock specified by parameter locktype - one +** of the following: +** +** (1) SHARED_LOCK +** (2) RESERVED_LOCK +** (3) PENDING_LOCK +** (4) EXCLUSIVE_LOCK +** +** Sometimes when requesting one lock state, additional lock states +** are inserted in between. The locking might fail on one of the later +** transitions leaving the lock state different from what it started but +** still short of its goal. The following chart shows the allowed +** transitions and the inserted intermediate states: +** +** UNLOCKED -> SHARED +** SHARED -> RESERVED +** SHARED -> (PENDING) -> EXCLUSIVE +** RESERVED -> (PENDING) -> EXCLUSIVE +** PENDING -> EXCLUSIVE +** +** This routine will only increase a lock. Use the sqlite3OsUnlock() +** routine to lower a locking level. +*/ +static int unixLock(OsFile *id, int locktype){ + /* The following describes the implementation of the various locks and + ** lock transitions in terms of the POSIX advisory shared and exclusive + ** lock primitives (called read-locks and write-locks below, to avoid + ** confusion with SQLite lock names). The algorithms are complicated + ** slightly in order to be compatible with windows systems simultaneously + ** accessing the same database file, in case that is ever required. + ** + ** Symbols defined in os.h indentify the 'pending byte' and the 'reserved + ** byte', each single bytes at well known offsets, and the 'shared byte + ** range', a range of 510 bytes at a well known offset. + ** + ** To obtain a SHARED lock, a read-lock is obtained on the 'pending + ** byte'. If this is successful, a random byte from the 'shared byte + ** range' is read-locked and the lock on the 'pending byte' released. + ** + ** A process may only obtain a RESERVED lock after it has a SHARED lock. + ** A RESERVED lock is implemented by grabbing a write-lock on the + ** 'reserved byte'. + ** + ** A process may only obtain a PENDING lock after it has obtained a + ** SHARED lock. A PENDING lock is implemented by obtaining a write-lock + ** on the 'pending byte'. This ensures that no new SHARED locks can be + ** obtained, but existing SHARED locks are allowed to persist. A process + ** does not have to obtain a RESERVED lock on the way to a PENDING lock. + ** This property is used by the algorithm for rolling back a journal file + ** after a crash. + ** + ** An EXCLUSIVE lock, obtained after a PENDING lock is held, is + ** implemented by obtaining a write-lock on the entire 'shared byte + ** range'. Since all other locks require a read-lock on one of the bytes + ** within this range, this ensures that no other locks are held on the + ** database. + ** + ** The reason a single byte cannot be used instead of the 'shared byte + ** range' is that some versions of windows do not support read-locks. By + ** locking a random byte from a range, concurrent SHARED locks may exist + ** even if the locking primitive used is always a write-lock. + */ + int rc = SQLITE_OK; + unixFile *pFile = (unixFile*)id; + struct lockInfo *pLock = pFile->pLock; + struct flock lock; + int s; + + assert( pFile ); + OSTRACE7("LOCK %d %s was %s(%s,%d) pid=%d\n", pFile->h, + locktypeName(locktype), locktypeName(pFile->locktype), + locktypeName(pLock->locktype), pLock->cnt , getpid()); + + /* If there is already a lock of this type or more restrictive on the + ** OsFile, do nothing. Don't use the end_lock: exit path, as + ** sqlite3OsEnterMutex() hasn't been called yet. + */ + if( pFile->locktype>=locktype ){ + OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h, + locktypeName(locktype)); + return SQLITE_OK; + } + + /* Make sure the locking sequence is correct + */ + assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); + assert( locktype!=PENDING_LOCK ); + assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); + + /* This mutex is needed because pFile->pLock is shared across threads + */ + sqlite3OsEnterMutex(); + + /* Make sure the current thread owns the pFile. + */ + rc = transferOwnership(pFile); + if( rc!=SQLITE_OK ){ + sqlite3OsLeaveMutex(); + return rc; + } + pLock = pFile->pLock; + + /* If some thread using this PID has a lock via a different OsFile* + ** handle that precludes the requested lock, return BUSY. + */ + if( (pFile->locktype!=pLock->locktype && + (pLock->locktype>=PENDING_LOCK || locktype>SHARED_LOCK)) + ){ + rc = SQLITE_BUSY; + goto end_lock; + } + + /* If a SHARED lock is requested, and some thread using this PID already + ** has a SHARED or RESERVED lock, then increment reference counts and + ** return SQLITE_OK. + */ + if( locktype==SHARED_LOCK && + (pLock->locktype==SHARED_LOCK || pLock->locktype==RESERVED_LOCK) ){ + assert( locktype==SHARED_LOCK ); + assert( pFile->locktype==0 ); + assert( pLock->cnt>0 ); + pFile->locktype = SHARED_LOCK; + pLock->cnt++; + pFile->pOpen->nLock++; + goto end_lock; + } + + lock.l_len = 1L; + + lock.l_whence = SEEK_SET; + + /* A PENDING lock is needed before acquiring a SHARED lock and before + ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will + ** be released. + */ + if( locktype==SHARED_LOCK + || (locktype==EXCLUSIVE_LOCK && pFile->locktypeh, F_SETLK, &lock); + if( s==(-1) ){ + rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; + goto end_lock; + } + } + + + /* If control gets to this point, then actually go ahead and make + ** operating system calls for the specified lock. + */ + if( locktype==SHARED_LOCK ){ + assert( pLock->cnt==0 ); + assert( pLock->locktype==0 ); + + /* Now get the read-lock */ + lock.l_start = SHARED_FIRST; + lock.l_len = SHARED_SIZE; + s = fcntl(pFile->h, F_SETLK, &lock); + + /* Drop the temporary PENDING lock */ + lock.l_start = PENDING_BYTE; + lock.l_len = 1L; + lock.l_type = F_UNLCK; + if( fcntl(pFile->h, F_SETLK, &lock)!=0 ){ + rc = SQLITE_IOERR_UNLOCK; /* This should never happen */ + goto end_lock; + } + if( s==(-1) ){ + rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; + }else{ + pFile->locktype = SHARED_LOCK; + pFile->pOpen->nLock++; + pLock->cnt = 1; + } + }else if( locktype==EXCLUSIVE_LOCK && pLock->cnt>1 ){ + /* We are trying for an exclusive lock but another thread in this + ** same process is still holding a shared lock. */ + rc = SQLITE_BUSY; + }else{ + /* The request was for a RESERVED or EXCLUSIVE lock. It is + ** assumed that there is a SHARED or greater lock on the file + ** already. + */ + assert( 0!=pFile->locktype ); + lock.l_type = F_WRLCK; + switch( locktype ){ + case RESERVED_LOCK: + lock.l_start = RESERVED_BYTE; + break; + case EXCLUSIVE_LOCK: + lock.l_start = SHARED_FIRST; + lock.l_len = SHARED_SIZE; + break; + default: + assert(0); + } + s = fcntl(pFile->h, F_SETLK, &lock); + if( s==(-1) ){ + rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY; + } + } + + if( rc==SQLITE_OK ){ + pFile->locktype = locktype; + pLock->locktype = locktype; + }else if( locktype==EXCLUSIVE_LOCK ){ + pFile->locktype = PENDING_LOCK; + pLock->locktype = PENDING_LOCK; + } + +end_lock: + sqlite3OsLeaveMutex(); + OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype), + rc==SQLITE_OK ? "ok" : "failed"); + return rc; +} + +/* +** Lower the locking level on file descriptor pFile to locktype. locktype +** must be either NO_LOCK or SHARED_LOCK. +** +** If the locking level of the file descriptor is already at or below +** the requested locking level, this routine is a no-op. +*/ +static int unixUnlock(OsFile *id, int locktype){ + struct lockInfo *pLock; + struct flock lock; + int rc = SQLITE_OK; + unixFile *pFile = (unixFile*)id; + + assert( pFile ); + OSTRACE7("UNLOCK %d %d was %d(%d,%d) pid=%d\n", pFile->h, locktype, + pFile->locktype, pFile->pLock->locktype, pFile->pLock->cnt, getpid()); + + assert( locktype<=SHARED_LOCK ); + if( pFile->locktype<=locktype ){ + return SQLITE_OK; + } + if( CHECK_THREADID(pFile) ){ + return SQLITE_MISUSE; + } + sqlite3OsEnterMutex(); + pLock = pFile->pLock; + assert( pLock->cnt!=0 ); + if( pFile->locktype>SHARED_LOCK ){ + assert( pLock->locktype==pFile->locktype ); + if( locktype==SHARED_LOCK ){ + lock.l_type = F_RDLCK; + lock.l_whence = SEEK_SET; + lock.l_start = SHARED_FIRST; + lock.l_len = SHARED_SIZE; + if( fcntl(pFile->h, F_SETLK, &lock)==(-1) ){ + /* This should never happen */ + rc = SQLITE_IOERR_RDLOCK; + } + } + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + lock.l_start = PENDING_BYTE; + lock.l_len = 2L; assert( PENDING_BYTE+1==RESERVED_BYTE ); + if( fcntl(pFile->h, F_SETLK, &lock)!=(-1) ){ + pLock->locktype = SHARED_LOCK; + }else{ + rc = SQLITE_IOERR_UNLOCK; /* This should never happen */ + } + } + if( locktype==NO_LOCK ){ + struct openCnt *pOpen; + + /* Decrement the shared lock counter. Release the lock using an + ** OS call only when all threads in this same process have released + ** the lock. + */ + pLock->cnt--; + if( pLock->cnt==0 ){ + lock.l_type = F_UNLCK; + lock.l_whence = SEEK_SET; + lock.l_start = lock.l_len = 0L; + if( fcntl(pFile->h, F_SETLK, &lock)!=(-1) ){ + pLock->locktype = NO_LOCK; + }else{ + rc = SQLITE_IOERR_UNLOCK; /* This should never happen */ + } + } + + /* Decrement the count of locks against this same file. When the + ** count reaches zero, close any other file descriptors whose close + ** was deferred because of outstanding locks. + */ + pOpen = pFile->pOpen; + pOpen->nLock--; + assert( pOpen->nLock>=0 ); + if( pOpen->nLock==0 && pOpen->nPending>0 ){ + int i; + for(i=0; inPending; i++){ + close(pOpen->aPending[i]); + } + free(pOpen->aPending); + pOpen->nPending = 0; + pOpen->aPending = 0; + } + } + sqlite3OsLeaveMutex(); + pFile->locktype = locktype; + return rc; +} + +/* +** Close a file. +*/ +static int unixClose(OsFile **pId){ + unixFile *id = (unixFile*)*pId; + + if( !id ) return SQLITE_OK; + unixUnlock(*pId, NO_LOCK); + if( id->dirfd>=0 ) close(id->dirfd); + id->dirfd = -1; + sqlite3OsEnterMutex(); + + if( id->pOpen->nLock ){ + /* If there are outstanding locks, do not actually close the file just + ** yet because that would clear those locks. Instead, add the file + ** descriptor to pOpen->aPending. It will be automatically closed when + ** the last lock is cleared. + */ + int *aNew; + struct openCnt *pOpen = id->pOpen; + aNew = realloc( pOpen->aPending, (pOpen->nPending+1)*sizeof(int) ); + if( aNew==0 ){ + /* If a malloc fails, just leak the file descriptor */ + }else{ + pOpen->aPending = aNew; + pOpen->aPending[pOpen->nPending] = id->h; + pOpen->nPending++; + } + }else{ + /* There are no outstanding locks so we can close the file immediately */ + close(id->h); + } + releaseLockInfo(id->pLock); + releaseOpenCnt(id->pOpen); + + sqlite3OsLeaveMutex(); + id->isOpen = 0; + OSTRACE2("CLOSE %-3d\n", id->h); + OpenCounter(-1); + sqlite3ThreadSafeFree(id); + *pId = 0; + return SQLITE_OK; +} + + +#ifdef SQLITE_ENABLE_LOCKING_STYLE +#pragma mark AFP Support + +/* + ** The afpLockingContext structure contains all afp lock specific state + */ +typedef struct afpLockingContext afpLockingContext; +struct afpLockingContext { + unsigned long long sharedLockByte; + char *filePath; +}; + +struct ByteRangeLockPB2 +{ + unsigned long long offset; /* offset to first byte to lock */ + unsigned long long length; /* nbr of bytes to lock */ + unsigned long long retRangeStart; /* nbr of 1st byte locked if successful */ + unsigned char unLockFlag; /* 1 = unlock, 0 = lock */ + unsigned char startEndFlag; /* 1=rel to end of fork, 0=rel to start */ + int fd; /* file desc to assoc this lock with */ +}; + +#define afpfsByteRangeLock2FSCTL _IOWR('z', 23, struct ByteRangeLockPB2) + +/* return 0 on success, 1 on failure. To match the behavior of the + normal posix file locking (used in unixLock for example), we should + provide 'richer' return codes - specifically to differentiate between + 'file busy' and 'file system error' results */ +static int _AFPFSSetLock(const char *path, int fd, unsigned long long offset, + unsigned long long length, int setLockFlag) +{ + struct ByteRangeLockPB2 pb; + int err; + + pb.unLockFlag = setLockFlag ? 0 : 1; + pb.startEndFlag = 0; + pb.offset = offset; + pb.length = length; + pb.fd = fd; + OSTRACE5("AFPLOCK setting lock %s for %d in range %llx:%llx\n", + (setLockFlag?"ON":"OFF"), fd, offset, length); + err = fsctl(path, afpfsByteRangeLock2FSCTL, &pb, 0); + if ( err==-1 ) { + OSTRACE4("AFPLOCK failed to fsctl() '%s' %d %s\n", path, errno, + strerror(errno)); + return 1; /* error */ + } else { + return 0; + } +} + +/* + ** This routine checks if there is a RESERVED lock held on the specified + ** file by this or any other process. If such a lock is held, return + ** non-zero. If the file is unlocked or holds only SHARED locks, then + ** return zero. + */ +static int afpUnixCheckReservedLock(OsFile *id){ + int r = 0; + unixFile *pFile = (unixFile*)id; + + assert( pFile ); + afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; + + /* Check if a thread in this process holds such a lock */ + if( pFile->locktype>SHARED_LOCK ){ + r = 1; + } + + /* Otherwise see if some other process holds it. + */ + if ( !r ) { + /* lock the byte */ + int failed = _AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1,1); + if (failed) { + /* if we failed to get the lock then someone else must have it */ + r = 1; + } else { + /* if we succeeded in taking the reserved lock, unlock it to restore + ** the original state */ + _AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1, 0); + } + } + OSTRACE3("TEST WR-LOCK %d %d\n", pFile->h, r); + + return r; +} + +/* AFP-style locking following the behavior of unixLock, see the unixLock +** function comments for details of lock management. */ +static int afpUnixLock(OsFile *id, int locktype) +{ + int rc = SQLITE_OK; + unixFile *pFile = (unixFile*)id; + afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; + int gotPendingLock = 0; + + assert( pFile ); + OSTRACE5("LOCK %d %s was %s pid=%d\n", pFile->h, + locktypeName(locktype), locktypeName(pFile->locktype), getpid()); + /* If there is already a lock of this type or more restrictive on the + ** OsFile, do nothing. Don't use the afp_end_lock: exit path, as + ** sqlite3OsEnterMutex() hasn't been called yet. + */ + if( pFile->locktype>=locktype ){ + OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h, + locktypeName(locktype)); + return SQLITE_OK; + } + + /* Make sure the locking sequence is correct + */ + assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); + assert( locktype!=PENDING_LOCK ); + assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); + + /* This mutex is needed because pFile->pLock is shared across threads + */ + sqlite3OsEnterMutex(); + + /* Make sure the current thread owns the pFile. + */ + rc = transferOwnership(pFile); + if( rc!=SQLITE_OK ){ + sqlite3OsLeaveMutex(); + return rc; + } + + /* A PENDING lock is needed before acquiring a SHARED lock and before + ** acquiring an EXCLUSIVE lock. For the SHARED lock, the PENDING will + ** be released. + */ + if( locktype==SHARED_LOCK + || (locktype==EXCLUSIVE_LOCK && pFile->locktypefilePath, pFile->h, + PENDING_BYTE, 1, 1); + if (failed) { + rc = SQLITE_BUSY; + goto afp_end_lock; + } + } + + /* If control gets to this point, then actually go ahead and make + ** operating system calls for the specified lock. + */ + if( locktype==SHARED_LOCK ){ + int lk, failed; + int tries = 0; + + /* Now get the read-lock */ + /* note that the quality of the randomness doesn't matter that much */ + lk = random(); + context->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1); + failed = _AFPFSSetLock(context->filePath, pFile->h, + SHARED_FIRST+context->sharedLockByte, 1, 1); + + /* Drop the temporary PENDING lock */ + if (_AFPFSSetLock(context->filePath, pFile->h, PENDING_BYTE, 1, 0)) { + rc = SQLITE_IOERR_UNLOCK; /* This should never happen */ + goto afp_end_lock; + } + + if( failed ){ + rc = SQLITE_BUSY; + } else { + pFile->locktype = SHARED_LOCK; + } + }else{ + /* The request was for a RESERVED or EXCLUSIVE lock. It is + ** assumed that there is a SHARED or greater lock on the file + ** already. + */ + int failed = 0; + assert( 0!=pFile->locktype ); + if (locktype >= RESERVED_LOCK && pFile->locktype < RESERVED_LOCK) { + /* Acquire a RESERVED lock */ + failed = _AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1,1); + } + if (!failed && locktype == EXCLUSIVE_LOCK) { + /* Acquire an EXCLUSIVE lock */ + + /* Remove the shared lock before trying the range. we'll need to + ** reestablish the shared lock if we can't get the afpUnixUnlock + */ + if (!_AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST + + context->sharedLockByte, 1, 0)) { + /* now attemmpt to get the exclusive lock range */ + failed = _AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST, + SHARED_SIZE, 1); + if (failed && _AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST + + context->sharedLockByte, 1, 1)) { + rc = SQLITE_IOERR_RDLOCK; /* this should never happen */ + } + } else { + /* */ + rc = SQLITE_IOERR_UNLOCK; /* this should never happen */ + } + } + if( failed && rc == SQLITE_OK){ + rc = SQLITE_BUSY; + } + } + + if( rc==SQLITE_OK ){ + pFile->locktype = locktype; + }else if( locktype==EXCLUSIVE_LOCK ){ + pFile->locktype = PENDING_LOCK; + } + +afp_end_lock: + sqlite3OsLeaveMutex(); + OSTRACE4("LOCK %d %s %s\n", pFile->h, locktypeName(locktype), + rc==SQLITE_OK ? "ok" : "failed"); + return rc; +} + +/* + ** Lower the locking level on file descriptor pFile to locktype. locktype + ** must be either NO_LOCK or SHARED_LOCK. + ** + ** If the locking level of the file descriptor is already at or below + ** the requested locking level, this routine is a no-op. + */ +static int afpUnixUnlock(OsFile *id, int locktype) { + struct flock lock; + int rc = SQLITE_OK; + unixFile *pFile = (unixFile*)id; + afpLockingContext *context = (afpLockingContext *) pFile->lockingContext; + + assert( pFile ); + OSTRACE5("UNLOCK %d %d was %d pid=%d\n", pFile->h, locktype, + pFile->locktype, getpid()); + + assert( locktype<=SHARED_LOCK ); + if( pFile->locktype<=locktype ){ + return SQLITE_OK; + } + if( CHECK_THREADID(pFile) ){ + return SQLITE_MISUSE; + } + sqlite3OsEnterMutex(); + if( pFile->locktype>SHARED_LOCK ){ + if( locktype==SHARED_LOCK ){ + int failed = 0; + + /* unlock the exclusive range - then re-establish the shared lock */ + if (pFile->locktype==EXCLUSIVE_LOCK) { + failed = _AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST, + SHARED_SIZE, 0); + if (!failed) { + /* successfully removed the exclusive lock */ + if (_AFPFSSetLock(context->filePath, pFile->h, SHARED_FIRST+ + context->sharedLockByte, 1, 1)) { + /* failed to re-establish our shared lock */ + rc = SQLITE_IOERR_RDLOCK; /* This should never happen */ + } + } else { + /* This should never happen - failed to unlock the exclusive range */ + rc = SQLITE_IOERR_UNLOCK; + } + } + } + if (rc == SQLITE_OK && pFile->locktype>=PENDING_LOCK) { + if (_AFPFSSetLock(context->filePath, pFile->h, PENDING_BYTE, 1, 0)){ + /* failed to release the pending lock */ + rc = SQLITE_IOERR_UNLOCK; /* This should never happen */ + } + } + if (rc == SQLITE_OK && pFile->locktype>=RESERVED_LOCK) { + if (_AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1, 0)) { + /* failed to release the reserved lock */ + rc = SQLITE_IOERR_UNLOCK; /* This should never happen */ + } + } + } + if( locktype==NO_LOCK ){ + int failed = _AFPFSSetLock(context->filePath, pFile->h, + SHARED_FIRST + context->sharedLockByte, 1, 0); + if (failed) { + rc = SQLITE_IOERR_UNLOCK; /* This should never happen */ + } + } + if (rc == SQLITE_OK) + pFile->locktype = locktype; + sqlite3OsLeaveMutex(); + return rc; +} + +/* + ** Close a file & cleanup AFP specific locking context + */ +static int afpUnixClose(OsFile **pId) { + unixFile *id = (unixFile*)*pId; + + if( !id ) return SQLITE_OK; + afpUnixUnlock(*pId, NO_LOCK); + /* free the AFP locking structure */ + if (id->lockingContext != NULL) { + if (((afpLockingContext *)id->lockingContext)->filePath != NULL) + sqlite3ThreadSafeFree(((afpLockingContext*)id->lockingContext)->filePath); + sqlite3ThreadSafeFree(id->lockingContext); + } + + if( id->dirfd>=0 ) close(id->dirfd); + id->dirfd = -1; + close(id->h); + id->isOpen = 0; + OSTRACE2("CLOSE %-3d\n", id->h); + OpenCounter(-1); + sqlite3ThreadSafeFree(id); + *pId = 0; + return SQLITE_OK; +} + + +#pragma mark flock() style locking + +/* + ** The flockLockingContext is not used + */ +typedef void flockLockingContext; + +static int flockUnixCheckReservedLock(OsFile *id) { + unixFile *pFile = (unixFile*)id; + + if (pFile->locktype == RESERVED_LOCK) { + return 1; /* already have a reserved lock */ + } else { + /* attempt to get the lock */ + int rc = flock(pFile->h, LOCK_EX | LOCK_NB); + if (!rc) { + /* got the lock, unlock it */ + flock(pFile->h, LOCK_UN); + return 0; /* no one has it reserved */ + } + return 1; /* someone else might have it reserved */ + } +} + +static int flockUnixLock(OsFile *id, int locktype) { + unixFile *pFile = (unixFile*)id; + + /* if we already have a lock, it is exclusive. + ** Just adjust level and punt on outta here. */ + if (pFile->locktype > NO_LOCK) { + pFile->locktype = locktype; + return SQLITE_OK; + } + + /* grab an exclusive lock */ + int rc = flock(pFile->h, LOCK_EX | LOCK_NB); + if (rc) { + /* didn't get, must be busy */ + return SQLITE_BUSY; + } else { + /* got it, set the type and return ok */ + pFile->locktype = locktype; + return SQLITE_OK; + } +} + +static int flockUnixUnlock(OsFile *id, int locktype) { + unixFile *pFile = (unixFile*)id; + + assert( locktype<=SHARED_LOCK ); + + /* no-op if possible */ + if( pFile->locktype==locktype ){ + return SQLITE_OK; + } + + /* shared can just be set because we always have an exclusive */ + if (locktype==SHARED_LOCK) { + pFile->locktype = locktype; + return SQLITE_OK; + } + + /* no, really, unlock. */ + int rc = flock(pFile->h, LOCK_UN); + if (rc) + return SQLITE_IOERR_UNLOCK; + else { + pFile->locktype = NO_LOCK; + return SQLITE_OK; + } +} + +/* + ** Close a file. + */ +static int flockUnixClose(OsFile **pId) { + unixFile *id = (unixFile*)*pId; + + if( !id ) return SQLITE_OK; + flockUnixUnlock(*pId, NO_LOCK); + + if( id->dirfd>=0 ) close(id->dirfd); + id->dirfd = -1; + sqlite3OsEnterMutex(); + + close(id->h); + sqlite3OsLeaveMutex(); + id->isOpen = 0; + OSTRACE2("CLOSE %-3d\n", id->h); + OpenCounter(-1); + sqlite3ThreadSafeFree(id); + *pId = 0; + return SQLITE_OK; +} + +#pragma mark Old-School .lock file based locking + +/* + ** The dotlockLockingContext structure contains all dotlock (.lock) lock + ** specific state + */ +typedef struct dotlockLockingContext dotlockLockingContext; +struct dotlockLockingContext { + char *lockPath; +}; + + +static int dotlockUnixCheckReservedLock(OsFile *id) { + unixFile *pFile = (unixFile*)id; + dotlockLockingContext *context = + (dotlockLockingContext *) pFile->lockingContext; + + if (pFile->locktype == RESERVED_LOCK) { + return 1; /* already have a reserved lock */ + } else { + struct stat statBuf; + if (lstat(context->lockPath,&statBuf) == 0) + /* file exists, someone else has the lock */ + return 1; + else + /* file does not exist, we could have it if we want it */ + return 0; + } +} + +static int dotlockUnixLock(OsFile *id, int locktype) { + unixFile *pFile = (unixFile*)id; + dotlockLockingContext *context = + (dotlockLockingContext *) pFile->lockingContext; + + /* if we already have a lock, it is exclusive. + ** Just adjust level and punt on outta here. */ + if (pFile->locktype > NO_LOCK) { + pFile->locktype = locktype; + + /* Always update the timestamp on the old file */ + utimes(context->lockPath,NULL); + return SQLITE_OK; + } + + /* check to see if lock file already exists */ + struct stat statBuf; + if (lstat(context->lockPath,&statBuf) == 0){ + return SQLITE_BUSY; /* it does, busy */ + } + + /* grab an exclusive lock */ + int fd = open(context->lockPath,O_RDONLY|O_CREAT|O_EXCL,0600); + if (fd < 0) { + /* failed to open/create the file, someone else may have stolen the lock */ + return SQLITE_BUSY; + } + close(fd); + + /* got it, set the type and return ok */ + pFile->locktype = locktype; + return SQLITE_OK; +} + +static int dotlockUnixUnlock(OsFile *id, int locktype) { + unixFile *pFile = (unixFile*)id; + dotlockLockingContext *context = + (dotlockLockingContext *) pFile->lockingContext; + + assert( locktype<=SHARED_LOCK ); + + /* no-op if possible */ + if( pFile->locktype==locktype ){ + return SQLITE_OK; + } + + /* shared can just be set because we always have an exclusive */ + if (locktype==SHARED_LOCK) { + pFile->locktype = locktype; + return SQLITE_OK; + } + + /* no, really, unlock. */ + unlink(context->lockPath); + pFile->locktype = NO_LOCK; + return SQLITE_OK; +} + +/* + ** Close a file. + */ +static int dotlockUnixClose(OsFile **pId) { + unixFile *id = (unixFile*)*pId; + + if( !id ) return SQLITE_OK; + dotlockUnixUnlock(*pId, NO_LOCK); + /* free the dotlock locking structure */ + if (id->lockingContext != NULL) { + if (((dotlockLockingContext *)id->lockingContext)->lockPath != NULL) + sqlite3ThreadSafeFree( ( (dotlockLockingContext *) + id->lockingContext)->lockPath); + sqlite3ThreadSafeFree(id->lockingContext); + } + + if( id->dirfd>=0 ) close(id->dirfd); + id->dirfd = -1; + sqlite3OsEnterMutex(); + + close(id->h); + + sqlite3OsLeaveMutex(); + id->isOpen = 0; + OSTRACE2("CLOSE %-3d\n", id->h); + OpenCounter(-1); + sqlite3ThreadSafeFree(id); + *pId = 0; + return SQLITE_OK; +} + + +#pragma mark No locking + +/* + ** The nolockLockingContext is void + */ +typedef void nolockLockingContext; + +static int nolockUnixCheckReservedLock(OsFile *id) { + return 0; +} + +static int nolockUnixLock(OsFile *id, int locktype) { + return SQLITE_OK; +} + +static int nolockUnixUnlock(OsFile *id, int locktype) { + return SQLITE_OK; +} + +/* + ** Close a file. + */ +static int nolockUnixClose(OsFile **pId) { + unixFile *id = (unixFile*)*pId; + + if( !id ) return SQLITE_OK; + if( id->dirfd>=0 ) close(id->dirfd); + id->dirfd = -1; + sqlite3OsEnterMutex(); + + close(id->h); + + sqlite3OsLeaveMutex(); + id->isOpen = 0; + OSTRACE2("CLOSE %-3d\n", id->h); + OpenCounter(-1); + sqlite3ThreadSafeFree(id); + *pId = 0; + return SQLITE_OK; +} + +#endif /* SQLITE_ENABLE_LOCKING_STYLE */ + +/* +** Turn a relative pathname into a full pathname. Return a pointer +** to the full pathname stored in space obtained from sqliteMalloc(). +** The calling function is responsible for freeing this space once it +** is no longer needed. +*/ +char *sqlite3UnixFullPathname(const char *zRelative){ + char *zFull = 0; + if( zRelative[0]=='/' ){ + sqlite3SetString(&zFull, zRelative, (char*)0); + }else{ + char *zBuf = sqliteMalloc(5000); + if( zBuf==0 ){ + return 0; + } + zBuf[0] = 0; + sqlite3SetString(&zFull, getcwd(zBuf, 5000), "/", zRelative, + (char*)0); + sqliteFree(zBuf); + } + +#if 0 + /* + ** Remove "/./" path elements and convert "/A/./" path elements + ** to just "/". + */ + if( zFull ){ + int i, j; + for(i=j=0; zFull[i]; i++){ + if( zFull[i]=='/' ){ + if( zFull[i+1]=='/' ) continue; + if( zFull[i+1]=='.' && zFull[i+2]=='/' ){ + i += 1; + continue; + } + if( zFull[i+1]=='.' && zFull[i+2]=='.' && zFull[i+3]=='/' ){ + while( j>0 && zFull[j-1]!='/' ){ j--; } + i += 3; + continue; + } + } + zFull[j++] = zFull[i]; + } + zFull[j] = 0; + } +#endif + + return zFull; +} + +/* +** Change the value of the fullsync flag in the given file descriptor. +*/ +static void unixSetFullSync(OsFile *id, int v){ + ((unixFile*)id)->fullSync = v; +} + +/* +** Return the underlying file handle for an OsFile +*/ +static int unixFileHandle(OsFile *id){ + return ((unixFile*)id)->h; +} + +/* +** Return an integer that indices the type of lock currently held +** by this handle. (Used for testing and analysis only.) +*/ +static int unixLockState(OsFile *id){ + return ((unixFile*)id)->locktype; +} + +/* +** Return the sector size in bytes of the underlying block device for +** the specified file. This is almost always 512 bytes, but may be +** larger for some devices. +** +** SQLite code assumes this function cannot fail. It also assumes that +** if two files are created in the same file-system directory (i.e. +** a database and it's journal file) that the sector size will be the +** same for both. +*/ +static int unixSectorSize(OsFile *id){ + return SQLITE_DEFAULT_SECTOR_SIZE; +} + +/* +** This vector defines all the methods that can operate on an OsFile +** for unix. +*/ +static const IoMethod sqlite3UnixIoMethod = { + unixClose, + unixOpenDirectory, + unixRead, + unixWrite, + unixSeek, + unixTruncate, + unixSync, + unixSetFullSync, + unixFileHandle, + unixFileSize, + unixLock, + unixUnlock, + unixLockState, + unixCheckReservedLock, + unixSectorSize, +}; + +#ifdef SQLITE_ENABLE_LOCKING_STYLE +/* + ** This vector defines all the methods that can operate on an OsFile + ** for unix with AFP style file locking. + */ +static const IoMethod sqlite3AFPLockingUnixIoMethod = { + afpUnixClose, + unixOpenDirectory, + unixRead, + unixWrite, + unixSeek, + unixTruncate, + unixSync, + unixSetFullSync, + unixFileHandle, + unixFileSize, + afpUnixLock, + afpUnixUnlock, + unixLockState, + afpUnixCheckReservedLock, + unixSectorSize, +}; + +/* + ** This vector defines all the methods that can operate on an OsFile + ** for unix with flock() style file locking. + */ +static const IoMethod sqlite3FlockLockingUnixIoMethod = { + flockUnixClose, + unixOpenDirectory, + unixRead, + unixWrite, + unixSeek, + unixTruncate, + unixSync, + unixSetFullSync, + unixFileHandle, + unixFileSize, + flockUnixLock, + flockUnixUnlock, + unixLockState, + flockUnixCheckReservedLock, + unixSectorSize, +}; + +/* + ** This vector defines all the methods that can operate on an OsFile + ** for unix with dotlock style file locking. + */ +static const IoMethod sqlite3DotlockLockingUnixIoMethod = { + dotlockUnixClose, + unixOpenDirectory, + unixRead, + unixWrite, + unixSeek, + unixTruncate, + unixSync, + unixSetFullSync, + unixFileHandle, + unixFileSize, + dotlockUnixLock, + dotlockUnixUnlock, + unixLockState, + dotlockUnixCheckReservedLock, + unixSectorSize, +}; + +/* + ** This vector defines all the methods that can operate on an OsFile + ** for unix with dotlock style file locking. + */ +static const IoMethod sqlite3NolockLockingUnixIoMethod = { + nolockUnixClose, + unixOpenDirectory, + unixRead, + unixWrite, + unixSeek, + unixTruncate, + unixSync, + unixSetFullSync, + unixFileHandle, + unixFileSize, + nolockUnixLock, + nolockUnixUnlock, + unixLockState, + nolockUnixCheckReservedLock, + unixSectorSize, +}; + +#endif /* SQLITE_ENABLE_LOCKING_STYLE */ + +/* +** Allocate memory for a new unixFile and initialize that unixFile. +** Write a pointer to the new unixFile into *pId. +** If we run out of memory, close the file and return an error. +*/ +#ifdef SQLITE_ENABLE_LOCKING_STYLE +/* + ** When locking extensions are enabled, the filepath and locking style + ** are needed to determine the unixFile pMethod to use for locking operations. + ** The locking-style specific lockingContext data structure is created + ** and assigned here also. + */ +static int allocateUnixFile( + int h, /* Open file descriptor of file being opened */ + OsFile **pId, /* Write completed initialization here */ + const char *zFilename, /* Name of the file being opened */ + int delFlag /* Delete-on-or-before-close flag */ +){ + sqlite3LockingStyle lockingStyle; + unixFile *pNew; + unixFile f; + int rc; + + memset(&f, 0, sizeof(f)); + lockingStyle = sqlite3DetectLockingStyle(zFilename, h); + if ( lockingStyle == posixLockingStyle ) { + sqlite3OsEnterMutex(); + rc = findLockInfo(h, &f.pLock, &f.pOpen); + sqlite3OsLeaveMutex(); + if( rc ){ + close(h); + unlink(zFilename); + return SQLITE_NOMEM; + } + } else { + /* pLock and pOpen are only used for posix advisory locking */ + f.pLock = NULL; + f.pOpen = NULL; + } + if( delFlag ){ + unlink(zFilename); + } + f.dirfd = -1; + f.h = h; + SET_THREADID(&f); + pNew = sqlite3ThreadSafeMalloc( sizeof(unixFile) ); + if( pNew==0 ){ + close(h); + sqlite3OsEnterMutex(); + releaseLockInfo(f.pLock); + releaseOpenCnt(f.pOpen); + sqlite3OsLeaveMutex(); + *pId = 0; + return SQLITE_NOMEM; + }else{ + *pNew = f; + switch(lockingStyle) { + case afpLockingStyle: { + /* afp locking uses the file path so it needs to be included in + ** the afpLockingContext */ + int nFilename; + pNew->pMethod = &sqlite3AFPLockingUnixIoMethod; + pNew->lockingContext = + sqlite3ThreadSafeMalloc(sizeof(afpLockingContext)); + nFilename = strlen(zFilename)+1; + ((afpLockingContext *)pNew->lockingContext)->filePath = + sqlite3ThreadSafeMalloc(nFilename); + memcpy(((afpLockingContext *)pNew->lockingContext)->filePath, + zFilename, nFilename); + srandomdev(); + break; + } + case flockLockingStyle: + /* flock locking doesn't need additional lockingContext information */ + pNew->pMethod = &sqlite3FlockLockingUnixIoMethod; + break; + case dotlockLockingStyle: { + /* dotlock locking uses the file path so it needs to be included in + ** the dotlockLockingContext */ + int nFilename; + pNew->pMethod = &sqlite3DotlockLockingUnixIoMethod; + pNew->lockingContext = sqlite3ThreadSafeMalloc( + sizeof(dotlockLockingContext)); + nFilename = strlen(zFilename) + 6; + ((dotlockLockingContext *)pNew->lockingContext)->lockPath = + sqlite3ThreadSafeMalloc( nFilename ); + sqlite3_snprintf(nFilename, + ((dotlockLockingContext *)pNew->lockingContext)->lockPath, + "%s.lock", zFilename); + break; + } + case posixLockingStyle: + /* posix locking doesn't need additional lockingContext information */ + pNew->pMethod = &sqlite3UnixIoMethod; + break; + case noLockingStyle: + case unsupportedLockingStyle: + default: + pNew->pMethod = &sqlite3NolockLockingUnixIoMethod; + } + *pId = (OsFile*)pNew; + OpenCounter(+1); + return SQLITE_OK; + } +} +#else /* SQLITE_ENABLE_LOCKING_STYLE */ +static int allocateUnixFile( + int h, /* Open file descriptor on file being opened */ + OsFile **pId, /* Write the resul unixFile structure here */ + const char *zFilename, /* Name of the file being opened */ + int delFlag /* If true, delete the file on or before closing */ +){ + unixFile *pNew; + unixFile f; + int rc; + +#ifdef FD_CLOEXEC + fcntl(h, F_SETFD, fcntl(h, F_GETFD, 0) | FD_CLOEXEC); +#endif + memset(&f, 0, sizeof(f)); + sqlite3OsEnterMutex(); + rc = findLockInfo(h, &f.pLock, &f.pOpen); + sqlite3OsLeaveMutex(); + if( delFlag ){ + unlink(zFilename); + } + if( rc ){ + close(h); + return SQLITE_NOMEM; + } + OSTRACE3("OPEN %-3d %s\n", h, zFilename); + f.dirfd = -1; + f.h = h; + SET_THREADID(&f); + pNew = sqlite3ThreadSafeMalloc( sizeof(unixFile) ); + if( pNew==0 ){ + close(h); + sqlite3OsEnterMutex(); + releaseLockInfo(f.pLock); + releaseOpenCnt(f.pOpen); + sqlite3OsLeaveMutex(); + *pId = 0; + return SQLITE_NOMEM; + }else{ + *pNew = f; + pNew->pMethod = &sqlite3UnixIoMethod; + *pId = (OsFile*)pNew; + OpenCounter(+1); + return SQLITE_OK; + } +} +#endif /* SQLITE_ENABLE_LOCKING_STYLE */ + +#endif /* SQLITE_OMIT_DISKIO */ +/*************************************************************************** +** Everything above deals with file I/O. Everything that follows deals +** with other miscellanous aspects of the operating system interface +****************************************************************************/ + + +#ifndef SQLITE_OMIT_LOAD_EXTENSION +/* +** Interfaces for opening a shared library, finding entry points +** within the shared library, and closing the shared library. +*/ +#include +void *sqlite3UnixDlopen(const char *zFilename){ + return dlopen(zFilename, RTLD_NOW | RTLD_GLOBAL); +} +void *sqlite3UnixDlsym(void *pHandle, const char *zSymbol){ + return dlsym(pHandle, zSymbol); +} +int sqlite3UnixDlclose(void *pHandle){ + return dlclose(pHandle); +} +#endif /* SQLITE_OMIT_LOAD_EXTENSION */ + +/* +** Get information to seed the random number generator. The seed +** is written into the buffer zBuf[256]. The calling function must +** supply a sufficiently large buffer. +*/ +int sqlite3UnixRandomSeed(char *zBuf){ + /* We have to initialize zBuf to prevent valgrind from reporting + ** errors. The reports issued by valgrind are incorrect - we would + ** prefer that the randomness be increased by making use of the + ** uninitialized space in zBuf - but valgrind errors tend to worry + ** some users. Rather than argue, it seems easier just to initialize + ** the whole array and silence valgrind, even if that means less randomness + ** in the random seed. + ** + ** When testing, initializing zBuf[] to zero is all we do. That means + ** that we always use the same random number sequence. This makes the + ** tests repeatable. + */ + memset(zBuf, 0, 256); +#if !defined(SQLITE_TEST) + { + int pid, fd; + fd = open("/dev/urandom", O_RDONLY); + if( fd<0 ){ + time_t t; + time(&t); + memcpy(zBuf, &t, sizeof(t)); + pid = getpid(); + memcpy(&zBuf[sizeof(time_t)], &pid, sizeof(pid)); + }else{ + read(fd, zBuf, 256); + close(fd); + } + } +#endif + return SQLITE_OK; +} + +/* +** Sleep for a little while. Return the amount of time slept. +** The argument is the number of milliseconds we want to sleep. +*/ +int sqlite3UnixSleep(int ms){ +#if defined(HAVE_USLEEP) && HAVE_USLEEP + usleep(ms*1000); + return ms; +#else + sleep((ms+999)/1000); + return 1000*((ms+999)/1000); +#endif +} + +/* +** Static variables used for thread synchronization. +** +** inMutex the nesting depth of the recursive mutex. The thread +** holding mutexMain can read this variable at any time. +** But is must hold mutexAux to change this variable. Other +** threads must hold mutexAux to read the variable and can +** never write. +** +** mutexOwner The thread id of the thread holding mutexMain. Same +** access rules as for inMutex. +** +** mutexOwnerValid True if the value in mutexOwner is valid. The same +** access rules apply as for inMutex. +** +** mutexMain The main mutex. Hold this mutex in order to get exclusive +** access to SQLite data structures. +** +** mutexAux An auxiliary mutex needed to access variables defined above. +** +** Mutexes are always acquired in this order: mutexMain mutexAux. It +** is not necessary to acquire mutexMain in order to get mutexAux - just +** do not attempt to acquire them in the reverse order: mutexAux mutexMain. +** Either get the mutexes with mutexMain first or get mutexAux only. +** +** When running on a platform where the three variables inMutex, mutexOwner, +** and mutexOwnerValid can be set atomically, the mutexAux is not required. +** On many systems, all three are 32-bit integers and writing to a 32-bit +** integer is atomic. I think. But there are no guarantees. So it seems +** safer to protect them using mutexAux. +*/ +static int inMutex = 0; +#ifdef SQLITE_UNIX_THREADS +static pthread_t mutexOwner; /* Thread holding mutexMain */ +static int mutexOwnerValid = 0; /* True if mutexOwner is valid */ +static pthread_mutex_t mutexMain = PTHREAD_MUTEX_INITIALIZER; /* The mutex */ +static pthread_mutex_t mutexAux = PTHREAD_MUTEX_INITIALIZER; /* Aux mutex */ +#endif + +/* +** The following pair of routine implement mutual exclusion for +** multi-threaded processes. Only a single thread is allowed to +** executed code that is surrounded by EnterMutex() and LeaveMutex(). +** +** SQLite uses only a single Mutex. There is not much critical +** code and what little there is executes quickly and without blocking. +** +** As of version 3.3.2, this mutex must be recursive. +*/ +void sqlite3UnixEnterMutex(){ +#ifdef SQLITE_UNIX_THREADS + pthread_mutex_lock(&mutexAux); + if( !mutexOwnerValid || !pthread_equal(mutexOwner, pthread_self()) ){ + pthread_mutex_unlock(&mutexAux); + pthread_mutex_lock(&mutexMain); + assert( inMutex==0 ); + assert( !mutexOwnerValid ); + pthread_mutex_lock(&mutexAux); + mutexOwner = pthread_self(); + mutexOwnerValid = 1; + } + inMutex++; + pthread_mutex_unlock(&mutexAux); +#else + inMutex++; +#endif +} +void sqlite3UnixLeaveMutex(){ + assert( inMutex>0 ); +#ifdef SQLITE_UNIX_THREADS + pthread_mutex_lock(&mutexAux); + inMutex--; + assert( pthread_equal(mutexOwner, pthread_self()) ); + if( inMutex==0 ){ + assert( mutexOwnerValid ); + mutexOwnerValid = 0; + pthread_mutex_unlock(&mutexMain); + } + pthread_mutex_unlock(&mutexAux); +#else + inMutex--; +#endif +} + +/* +** Return TRUE if the mutex is currently held. +** +** If the thisThrd parameter is true, return true only if the +** calling thread holds the mutex. If the parameter is false, return +** true if any thread holds the mutex. +*/ +int sqlite3UnixInMutex(int thisThrd){ +#ifdef SQLITE_UNIX_THREADS + int rc; + pthread_mutex_lock(&mutexAux); + rc = inMutex>0 && (thisThrd==0 || pthread_equal(mutexOwner,pthread_self())); + pthread_mutex_unlock(&mutexAux); + return rc; +#else + return inMutex>0; +#endif +} + +/* +** Remember the number of thread-specific-data blocks allocated. +** Use this to verify that we are not leaking thread-specific-data. +** Ticket #1601 +*/ +#ifdef SQLITE_TEST +int sqlite3_tsd_count = 0; +# ifdef SQLITE_UNIX_THREADS + static pthread_mutex_t tsd_counter_mutex = PTHREAD_MUTEX_INITIALIZER; +# define TSD_COUNTER(N) \ + pthread_mutex_lock(&tsd_counter_mutex); \ + sqlite3_tsd_count += N; \ + pthread_mutex_unlock(&tsd_counter_mutex); +# else +# define TSD_COUNTER(N) sqlite3_tsd_count += N +# endif +#else +# define TSD_COUNTER(N) /* no-op */ +#endif + +/* +** If called with allocateFlag>0, then return a pointer to thread +** specific data for the current thread. Allocate and zero the +** thread-specific data if it does not already exist. +** +** If called with allocateFlag==0, then check the current thread +** specific data. Return it if it exists. If it does not exist, +** then return NULL. +** +** If called with allocateFlag<0, check to see if the thread specific +** data is allocated and is all zero. If it is then deallocate it. +** Return a pointer to the thread specific data or NULL if it is +** unallocated or gets deallocated. +*/ +ThreadData *sqlite3UnixThreadSpecificData(int allocateFlag){ + static const ThreadData zeroData = {0}; /* Initializer to silence warnings + ** from broken compilers */ +#ifdef SQLITE_UNIX_THREADS + static pthread_key_t key; + static int keyInit = 0; + ThreadData *pTsd; + + if( !keyInit ){ + sqlite3OsEnterMutex(); + if( !keyInit ){ + int rc; + rc = pthread_key_create(&key, 0); + if( rc ){ + sqlite3OsLeaveMutex(); + return 0; + } + keyInit = 1; + } + sqlite3OsLeaveMutex(); + } + + pTsd = pthread_getspecific(key); + if( allocateFlag>0 ){ + if( pTsd==0 ){ + if( !sqlite3TestMallocFail() ){ + pTsd = sqlite3OsMalloc(sizeof(zeroData)); + } +#ifdef SQLITE_MEMDEBUG + sqlite3_isFail = 0; +#endif + if( pTsd ){ + *pTsd = zeroData; + pthread_setspecific(key, pTsd); + TSD_COUNTER(+1); + } + } + }else if( pTsd!=0 && allocateFlag<0 + && memcmp(pTsd, &zeroData, sizeof(ThreadData))==0 ){ + sqlite3OsFree(pTsd); + pthread_setspecific(key, 0); + TSD_COUNTER(-1); + pTsd = 0; + } + return pTsd; +#else + static ThreadData *pTsd = 0; + if( allocateFlag>0 ){ + if( pTsd==0 ){ + if( !sqlite3TestMallocFail() ){ + pTsd = sqlite3OsMalloc( sizeof(zeroData) ); + } +#ifdef SQLITE_MEMDEBUG + sqlite3_isFail = 0; +#endif + if( pTsd ){ + *pTsd = zeroData; + TSD_COUNTER(+1); + } + } + }else if( pTsd!=0 && allocateFlag<0 + && memcmp(pTsd, &zeroData, sizeof(ThreadData))==0 ){ + sqlite3OsFree(pTsd); + TSD_COUNTER(-1); + pTsd = 0; + } + return pTsd; +#endif +} + +/* +** The following variable, if set to a non-zero value, becomes the result +** returned from sqlite3OsCurrentTime(). This is used for testing. +*/ +#ifdef SQLITE_TEST +int sqlite3_current_time = 0; +#endif + +/* +** Find the current time (in Universal Coordinated Time). Write the +** current time and date as a Julian Day number into *prNow and +** return 0. Return 1 if the time and date cannot be found. +*/ +int sqlite3UnixCurrentTime(double *prNow){ +#ifdef NO_GETTOD + time_t t; + time(&t); + *prNow = t/86400.0 + 2440587.5; +#else + struct timeval sNow; + gettimeofday(&sNow, 0); + *prNow = 2440587.5 + sNow.tv_sec/86400.0 + sNow.tv_usec/86400000000.0; +#endif +#ifdef SQLITE_TEST + if( sqlite3_current_time ){ + *prNow = sqlite3_current_time/86400.0 + 2440587.5; + } +#endif + return 0; +} + +#endif /* OS_UNIX */ diff --git a/extensions/sqlite/sqlite-source/os_win.c b/extensions/sqlite/sqlite-source/os_win.c new file mode 100644 index 00000000..9ebb9dc3 --- /dev/null +++ b/extensions/sqlite/sqlite-source/os_win.c @@ -0,0 +1,1758 @@ +/* +** 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 code that is specific to windows. +*/ +#include "sqliteInt.h" +#include "os.h" +#if OS_WIN /* This file is used for windows only */ + +#include + +#ifdef __CYGWIN__ +# include +#endif + +/* +** Macros used to determine whether or not to use threads. +*/ +#if defined(THREADSAFE) && THREADSAFE +# define SQLITE_W32_THREADS 1 +#endif + +/* +** Include code that is common to all os_*.c files +*/ +#include "os_common.h" + +/* +** Determine if we are dealing with WindowsCE - which has a much +** reduced API. +*/ +#if defined(_WIN32_WCE) +# define OS_WINCE 1 +# define AreFileApisANSI() 1 +#else +# define OS_WINCE 0 +#endif + +/* +** WinCE lacks native support for file locking so we have to fake it +** with some code of our own. +*/ +#if OS_WINCE +typedef struct winceLock { + int nReaders; /* Number of reader locks obtained */ + BOOL bPending; /* Indicates a pending lock has been obtained */ + BOOL bReserved; /* Indicates a reserved lock has been obtained */ + BOOL bExclusive; /* Indicates an exclusive lock has been obtained */ +} winceLock; +#endif + +/* +** The winFile structure is a subclass of OsFile specific to the win32 +** portability layer. +*/ +typedef struct winFile winFile; +struct winFile { + IoMethod const *pMethod;/* Must be first */ + HANDLE h; /* Handle for accessing the file */ + unsigned char locktype; /* Type of lock currently held on this file */ + short sharedLockByte; /* Randomly chosen byte used as a shared lock */ +#if OS_WINCE + WCHAR *zDeleteOnClose; /* Name of file to delete when closing */ + HANDLE hMutex; /* Mutex used to control access to shared lock */ + HANDLE hShared; /* Shared memory segment used for locking */ + winceLock local; /* Locks obtained by this instance of winFile */ + winceLock *shared; /* Global shared lock memory for the file */ +#endif +}; + + +/* +** Do not include any of the File I/O interface procedures if the +** SQLITE_OMIT_DISKIO macro is defined (indicating that there database +** will be in-memory only) +*/ +#ifndef SQLITE_OMIT_DISKIO + +/* +** The following variable is (normally) set once and never changes +** thereafter. It records whether the operating system is Win95 +** or WinNT. +** +** 0: Operating system unknown. +** 1: Operating system is Win95. +** 2: Operating system is WinNT. +** +** In order to facilitate testing on a WinNT system, the test fixture +** can manually set this value to 1 to emulate Win98 behavior. +*/ +int sqlite3_os_type = 0; + +/* +** Return true (non-zero) if we are running under WinNT, Win2K, WinXP, +** or WinCE. Return false (zero) for Win95, Win98, or WinME. +** +** Here is an interesting observation: Win95, Win98, and WinME lack +** the LockFileEx() API. But we can still statically link against that +** API as long as we don't call it win running Win95/98/ME. A call to +** this routine is used to determine if the host is Win95/98/ME or +** WinNT/2K/XP so that we will know whether or not we can safely call +** the LockFileEx() API. +*/ +#if OS_WINCE +# define isNT() (1) +#else + static int isNT(void){ + if( sqlite3_os_type==0 ){ + OSVERSIONINFO sInfo; + sInfo.dwOSVersionInfoSize = sizeof(sInfo); + GetVersionEx(&sInfo); + sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1; + } + return sqlite3_os_type==2; + } +#endif /* OS_WINCE */ + +/* +** Convert a UTF-8 string to microsoft unicode (UTF-16?). +** +** Space to hold the returned string is obtained from sqliteMalloc. +*/ +static WCHAR *utf8ToUnicode(const char *zFilename){ + int nChar; + WCHAR *zWideFilename; + + nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0); + zWideFilename = sqliteMalloc( nChar*sizeof(zWideFilename[0]) ); + if( zWideFilename==0 ){ + return 0; + } + nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, nChar); + if( nChar==0 ){ + sqliteFree(zWideFilename); + zWideFilename = 0; + } + return zWideFilename; +} + +/* +** Convert microsoft unicode to UTF-8. Space to hold the returned string is +** obtained from sqliteMalloc(). +*/ +static char *unicodeToUtf8(const WCHAR *zWideFilename){ + int nByte; + char *zFilename; + + nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0); + zFilename = sqliteMalloc( nByte ); + if( zFilename==0 ){ + return 0; + } + nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte, + 0, 0); + if( nByte == 0 ){ + sqliteFree(zFilename); + zFilename = 0; + } + return zFilename; +} + +/* +** Convert an ansi string to microsoft unicode, based on the +** current codepage settings for file apis. +** +** Space to hold the returned string is obtained +** from sqliteMalloc. +*/ +static WCHAR *mbcsToUnicode(const char *zFilename){ + int nByte; + WCHAR *zMbcsFilename; + int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; + + nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, NULL,0)*sizeof(WCHAR); + zMbcsFilename = sqliteMalloc( nByte*sizeof(zMbcsFilename[0]) ); + if( zMbcsFilename==0 ){ + return 0; + } + nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, zMbcsFilename, nByte); + if( nByte==0 ){ + sqliteFree(zMbcsFilename); + zMbcsFilename = 0; + } + return zMbcsFilename; +} + +/* +** Convert microsoft unicode to multibyte character string, based on the +** user's Ansi codepage. +** +** Space to hold the returned string is obtained from +** sqliteMalloc(). +*/ +static char *unicodeToMbcs(const WCHAR *zWideFilename){ + int nByte; + char *zFilename; + int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; + + nByte = WideCharToMultiByte(codepage, 0, zWideFilename, -1, 0, 0, 0, 0); + zFilename = sqliteMalloc( nByte ); + if( zFilename==0 ){ + return 0; + } + nByte = WideCharToMultiByte(codepage, 0, zWideFilename, -1, zFilename, nByte, + 0, 0); + if( nByte == 0 ){ + sqliteFree(zFilename); + zFilename = 0; + } + return zFilename; +} + +/* +** Convert multibyte character string to UTF-8. Space to hold the +** returned string is obtained from sqliteMalloc(). +*/ +static char *mbcsToUtf8(const char *zFilename){ + char *zFilenameUtf8; + WCHAR *zTmpWide; + + zTmpWide = mbcsToUnicode(zFilename); + if( zTmpWide==0 ){ + return 0; + } + zFilenameUtf8 = unicodeToUtf8(zTmpWide); + sqliteFree(zTmpWide); + return zFilenameUtf8; +} + +/* +** Convert UTF-8 to multibyte character string. Space to hold the +** returned string is obtained from sqliteMalloc(). +*/ +static char *utf8ToMbcs(const char *zFilename){ + char *zFilenameMbcs; + WCHAR *zTmpWide; + + zTmpWide = utf8ToUnicode(zFilename); + if( zTmpWide==0 ){ + return 0; + } + zFilenameMbcs = unicodeToMbcs(zTmpWide); + sqliteFree(zTmpWide); + return zFilenameMbcs; +} + +#if OS_WINCE +/************************************************************************* +** This section contains code for WinCE only. +*/ +/* +** WindowsCE does not have a localtime() function. So create a +** substitute. +*/ +#include +struct tm *__cdecl localtime(const time_t *t) +{ + static struct tm y; + FILETIME uTm, lTm; + SYSTEMTIME pTm; + i64 t64; + t64 = *t; + t64 = (t64 + 11644473600)*10000000; + uTm.dwLowDateTime = t64 & 0xFFFFFFFF; + uTm.dwHighDateTime= t64 >> 32; + FileTimeToLocalFileTime(&uTm,&lTm); + FileTimeToSystemTime(&lTm,&pTm); + y.tm_year = pTm.wYear - 1900; + y.tm_mon = pTm.wMonth - 1; + y.tm_wday = pTm.wDayOfWeek; + y.tm_mday = pTm.wDay; + y.tm_hour = pTm.wHour; + y.tm_min = pTm.wMinute; + y.tm_sec = pTm.wSecond; + return &y; +} + +/* This will never be called, but defined to make the code compile */ +#define GetTempPathA(a,b) + +#define LockFile(a,b,c,d,e) winceLockFile(&a, b, c, d, e) +#define UnlockFile(a,b,c,d,e) winceUnlockFile(&a, b, c, d, e) +#define LockFileEx(a,b,c,d,e,f) winceLockFileEx(&a, b, c, d, e, f) + +#define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-offsetof(winFile,h)] + +/* +** Acquire a lock on the handle h +*/ +static void winceMutexAcquire(HANDLE h){ + DWORD dwErr; + do { + dwErr = WaitForSingleObject(h, INFINITE); + } while (dwErr != WAIT_OBJECT_0 && dwErr != WAIT_ABANDONED); +} +/* +** Release a lock acquired by winceMutexAcquire() +*/ +#define winceMutexRelease(h) ReleaseMutex(h) + +/* +** Create the mutex and shared memory used for locking in the file +** descriptor pFile +*/ +static BOOL winceCreateLock(const char *zFilename, winFile *pFile){ + WCHAR *zTok; + WCHAR *zName = utf8ToUnicode(zFilename); + BOOL bInit = TRUE; + + /* Initialize the local lockdata */ + ZeroMemory(&pFile->local, sizeof(pFile->local)); + + /* Replace the backslashes from the filename and lowercase it + ** to derive a mutex name. */ + zTok = CharLowerW(zName); + for (;*zTok;zTok++){ + if (*zTok == '\\') *zTok = '_'; + } + + /* Create/open the named mutex */ + pFile->hMutex = CreateMutexW(NULL, FALSE, zName); + if (!pFile->hMutex){ + sqliteFree(zName); + return FALSE; + } + + /* Acquire the mutex before continuing */ + winceMutexAcquire(pFile->hMutex); + + /* Since the names of named mutexes, semaphores, file mappings etc are + ** case-sensitive, take advantage of that by uppercasing the mutex name + ** and using that as the shared filemapping name. + */ + CharUpperW(zName); + pFile->hShared = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, + PAGE_READWRITE, 0, sizeof(winceLock), + zName); + + /* Set a flag that indicates we're the first to create the memory so it + ** must be zero-initialized */ + if (GetLastError() == ERROR_ALREADY_EXISTS){ + bInit = FALSE; + } + + sqliteFree(zName); + + /* If we succeeded in making the shared memory handle, map it. */ + if (pFile->hShared){ + pFile->shared = (winceLock*)MapViewOfFile(pFile->hShared, + FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock)); + /* If mapping failed, close the shared memory handle and erase it */ + if (!pFile->shared){ + CloseHandle(pFile->hShared); + pFile->hShared = NULL; + } + } + + /* If shared memory could not be created, then close the mutex and fail */ + if (pFile->hShared == NULL){ + winceMutexRelease(pFile->hMutex); + CloseHandle(pFile->hMutex); + pFile->hMutex = NULL; + return FALSE; + } + + /* Initialize the shared memory if we're supposed to */ + if (bInit) { + ZeroMemory(pFile->shared, sizeof(winceLock)); + } + + winceMutexRelease(pFile->hMutex); + return TRUE; +} + +/* +** Destroy the part of winFile that deals with wince locks +*/ +static void winceDestroyLock(winFile *pFile){ + if (pFile->hMutex){ + /* Acquire the mutex */ + winceMutexAcquire(pFile->hMutex); + + /* The following blocks should probably assert in debug mode, but they + are to cleanup in case any locks remained open */ + if (pFile->local.nReaders){ + pFile->shared->nReaders --; + } + if (pFile->local.bReserved){ + pFile->shared->bReserved = FALSE; + } + if (pFile->local.bPending){ + pFile->shared->bPending = FALSE; + } + if (pFile->local.bExclusive){ + pFile->shared->bExclusive = FALSE; + } + + /* De-reference and close our copy of the shared memory handle */ + UnmapViewOfFile(pFile->shared); + CloseHandle(pFile->hShared); + + if( pFile->zDeleteOnClose ){ + DeleteFileW(pFile->zDeleteOnClose); + sqliteFree(pFile->zDeleteOnClose); + pFile->zDeleteOnClose = 0; + } + + /* Done with the mutex */ + winceMutexRelease(pFile->hMutex); + CloseHandle(pFile->hMutex); + pFile->hMutex = NULL; + } +} + +/* +** An implementation of the LockFile() API of windows for wince +*/ +static BOOL winceLockFile( + HANDLE *phFile, + DWORD dwFileOffsetLow, + DWORD dwFileOffsetHigh, + DWORD nNumberOfBytesToLockLow, + DWORD nNumberOfBytesToLockHigh +){ + winFile *pFile = HANDLE_TO_WINFILE(phFile); + BOOL bReturn = FALSE; + + if (!pFile->hMutex) return TRUE; + winceMutexAcquire(pFile->hMutex); + + /* Wanting an exclusive lock? */ + if (dwFileOffsetLow == SHARED_FIRST + && nNumberOfBytesToLockLow == SHARED_SIZE){ + if (pFile->shared->nReaders == 0 && pFile->shared->bExclusive == 0){ + pFile->shared->bExclusive = TRUE; + pFile->local.bExclusive = TRUE; + bReturn = TRUE; + } + } + + /* Want a read-only lock? */ + else if ((dwFileOffsetLow >= SHARED_FIRST && + dwFileOffsetLow < SHARED_FIRST + SHARED_SIZE) && + nNumberOfBytesToLockLow == 1){ + if (pFile->shared->bExclusive == 0){ + pFile->local.nReaders ++; + if (pFile->local.nReaders == 1){ + pFile->shared->nReaders ++; + } + bReturn = TRUE; + } + } + + /* Want a pending lock? */ + else if (dwFileOffsetLow == PENDING_BYTE && nNumberOfBytesToLockLow == 1){ + /* If no pending lock has been acquired, then acquire it */ + if (pFile->shared->bPending == 0) { + pFile->shared->bPending = TRUE; + pFile->local.bPending = TRUE; + bReturn = TRUE; + } + } + /* Want a reserved lock? */ + else if (dwFileOffsetLow == RESERVED_BYTE && nNumberOfBytesToLockLow == 1){ + if (pFile->shared->bReserved == 0) { + pFile->shared->bReserved = TRUE; + pFile->local.bReserved = TRUE; + bReturn = TRUE; + } + } + + winceMutexRelease(pFile->hMutex); + return bReturn; +} + +/* +** An implementation of the UnlockFile API of windows for wince +*/ +static BOOL winceUnlockFile( + HANDLE *phFile, + DWORD dwFileOffsetLow, + DWORD dwFileOffsetHigh, + DWORD nNumberOfBytesToUnlockLow, + DWORD nNumberOfBytesToUnlockHigh +){ + winFile *pFile = HANDLE_TO_WINFILE(phFile); + BOOL bReturn = FALSE; + + if (!pFile->hMutex) return TRUE; + winceMutexAcquire(pFile->hMutex); + + /* Releasing a reader lock or an exclusive lock */ + if (dwFileOffsetLow >= SHARED_FIRST && + dwFileOffsetLow < SHARED_FIRST + SHARED_SIZE){ + /* Did we have an exclusive lock? */ + if (pFile->local.bExclusive){ + pFile->local.bExclusive = FALSE; + pFile->shared->bExclusive = FALSE; + bReturn = TRUE; + } + + /* Did we just have a reader lock? */ + else if (pFile->local.nReaders){ + pFile->local.nReaders --; + if (pFile->local.nReaders == 0) + { + pFile->shared->nReaders --; + } + bReturn = TRUE; + } + } + + /* Releasing a pending lock */ + else if (dwFileOffsetLow == PENDING_BYTE && nNumberOfBytesToUnlockLow == 1){ + if (pFile->local.bPending){ + pFile->local.bPending = FALSE; + pFile->shared->bPending = FALSE; + bReturn = TRUE; + } + } + /* Releasing a reserved lock */ + else if (dwFileOffsetLow == RESERVED_BYTE && nNumberOfBytesToUnlockLow == 1){ + if (pFile->local.bReserved) { + pFile->local.bReserved = FALSE; + pFile->shared->bReserved = FALSE; + bReturn = TRUE; + } + } + + winceMutexRelease(pFile->hMutex); + return bReturn; +} + +/* +** An implementation of the LockFileEx() API of windows for wince +*/ +static BOOL winceLockFileEx( + HANDLE *phFile, + DWORD dwFlags, + DWORD dwReserved, + DWORD nNumberOfBytesToLockLow, + DWORD nNumberOfBytesToLockHigh, + LPOVERLAPPED lpOverlapped +){ + /* If the caller wants a shared read lock, forward this call + ** to winceLockFile */ + if (lpOverlapped->Offset == SHARED_FIRST && + dwFlags == 1 && + nNumberOfBytesToLockLow == SHARED_SIZE){ + return winceLockFile(phFile, SHARED_FIRST, 0, 1, 0); + } + return FALSE; +} +/* +** End of the special code for wince +*****************************************************************************/ +#endif /* OS_WINCE */ + +/* +** Convert a UTF-8 filename into whatever form the underlying +** operating system wants filenames in. Space to hold the result +** is obtained from sqliteMalloc and must be freed by the calling +** function. +*/ +static void *convertUtf8Filename(const char *zFilename){ + void *zConverted = 0; + if( isNT() ){ + zConverted = utf8ToUnicode(zFilename); + }else{ + zConverted = utf8ToMbcs(zFilename); + } + /* caller will handle out of memory */ + return zConverted; +} + +/* +** Delete the named file. +** +** Note that windows does not allow a file to be deleted if some other +** process has it open. Sometimes a virus scanner or indexing program +** will open a journal file shortly after it is created in order to do +** whatever it is it does. While this other process is holding the +** file open, we will be unable to delete it. To work around this +** problem, we delay 100 milliseconds and try to delete again. Up +** to MX_DELETION_ATTEMPTs deletion attempts are run before giving +** up and returning an error. +*/ +#define MX_DELETION_ATTEMPTS 3 +int sqlite3WinDelete(const char *zFilename){ + int cnt = 0; + int rc; + void *zConverted = convertUtf8Filename(zFilename); + if( zConverted==0 ){ + return SQLITE_NOMEM; + } + SimulateIOError(return SQLITE_IOERR_DELETE); + if( isNT() ){ + do{ + rc = DeleteFileW(zConverted); + }while( rc==0 && GetFileAttributesW(zConverted)!=0xffffffff + && cnt++ < MX_DELETION_ATTEMPTS && (Sleep(100), 1) ); + }else{ +#if OS_WINCE + return SQLITE_NOMEM; +#else + do{ + rc = DeleteFileA(zConverted); + }while( rc==0 && GetFileAttributesA(zConverted)!=0xffffffff + && cnt++ < MX_DELETION_ATTEMPTS && (Sleep(100), 1) ); +#endif + } + sqliteFree(zConverted); + OSTRACE2("DELETE \"%s\"\n", zFilename); + return rc!=0 ? SQLITE_OK : SQLITE_IOERR; +} + +/* +** Return TRUE if the named file exists. +*/ +int sqlite3WinFileExists(const char *zFilename){ + int exists = 0; + void *zConverted = convertUtf8Filename(zFilename); + if( zConverted==0 ){ + return SQLITE_NOMEM; + } + if( isNT() ){ + exists = GetFileAttributesW((WCHAR*)zConverted) != 0xffffffff; + }else{ +#if OS_WINCE + return SQLITE_NOMEM; +#else + exists = GetFileAttributesA((char*)zConverted) != 0xffffffff; +#endif + } + sqliteFree(zConverted); + return exists; +} + +/* Forward declaration */ +static int allocateWinFile(winFile *pInit, OsFile **pId); + +/* +** Attempt to open a file for both reading and writing. If that +** fails, try opening it read-only. If the file does not exist, +** try to create it. +** +** On success, a handle for the open file is written to *id +** and *pReadonly is set to 0 if the file was opened for reading and +** writing or 1 if the file was opened read-only. The function returns +** SQLITE_OK. +** +** On failure, the function returns SQLITE_CANTOPEN and leaves +** *id and *pReadonly unchanged. +*/ +int sqlite3WinOpenReadWrite( + const char *zFilename, + OsFile **pId, + int *pReadonly +){ + winFile f; + HANDLE h; + void *zConverted = convertUtf8Filename(zFilename); + if( zConverted==0 ){ + return SQLITE_NOMEM; + } + assert( *pId==0 ); + + if( isNT() ){ + h = CreateFileW((WCHAR*)zConverted, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, + NULL + ); + if( h==INVALID_HANDLE_VALUE ){ + h = CreateFileW((WCHAR*)zConverted, + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, + NULL + ); + if( h==INVALID_HANDLE_VALUE ){ + sqliteFree(zConverted); + return SQLITE_CANTOPEN; + } + *pReadonly = 1; + }else{ + *pReadonly = 0; + } +#if OS_WINCE + if (!winceCreateLock(zFilename, &f)){ + CloseHandle(h); + sqliteFree(zConverted); + return SQLITE_CANTOPEN; + } +#endif + }else{ +#if OS_WINCE + return SQLITE_NOMEM; +#else + h = CreateFileA((char*)zConverted, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, + NULL + ); + if( h==INVALID_HANDLE_VALUE ){ + h = CreateFileA((char*)zConverted, + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, + NULL + ); + if( h==INVALID_HANDLE_VALUE ){ + sqliteFree(zConverted); + return SQLITE_CANTOPEN; + } + *pReadonly = 1; + }else{ + *pReadonly = 0; + } +#endif /* OS_WINCE */ + } + + sqliteFree(zConverted); + + f.h = h; +#if OS_WINCE + f.zDeleteOnClose = 0; +#endif + OSTRACE3("OPEN R/W %d \"%s\"\n", h, zFilename); + return allocateWinFile(&f, pId); +} + + +/* +** Attempt to open a new file for exclusive access by this process. +** The file will be opened for both reading and writing. To avoid +** a potential security problem, we do not allow the file to have +** previously existed. Nor do we allow the file to be a symbolic +** link. +** +** If delFlag is true, then make arrangements to automatically delete +** the file when it is closed. +** +** On success, write the file handle into *id and return SQLITE_OK. +** +** On failure, return SQLITE_CANTOPEN. +** +** Sometimes if we have just deleted a prior journal file, windows +** will fail to open a new one because there is a "pending delete". +** To work around this bug, we pause for 100 milliseconds and attempt +** a second open after the first one fails. The whole operation only +** fails if both open attempts are unsuccessful. +*/ +int sqlite3WinOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){ + winFile f; + HANDLE h; + DWORD fileflags; + void *zConverted = convertUtf8Filename(zFilename); + if( zConverted==0 ){ + return SQLITE_NOMEM; + } + assert( *pId == 0 ); + fileflags = FILE_FLAG_RANDOM_ACCESS; +#if !OS_WINCE + if( delFlag ){ + fileflags |= FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE; + } +#endif + if( isNT() ){ + int cnt = 0; + do{ + h = CreateFileW((WCHAR*)zConverted, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + fileflags, + NULL + ); + }while( h==INVALID_HANDLE_VALUE && cnt++ < 2 && (Sleep(100), 1) ); + }else{ +#if OS_WINCE + return SQLITE_NOMEM; +#else + int cnt = 0; + do{ + h = CreateFileA((char*)zConverted, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + fileflags, + NULL + ); + }while( h==INVALID_HANDLE_VALUE && cnt++ < 2 && (Sleep(100), 1) ); +#endif /* OS_WINCE */ + } +#if OS_WINCE + if( delFlag && h!=INVALID_HANDLE_VALUE ){ + f.zDeleteOnClose = zConverted; + zConverted = 0; + } + f.hMutex = NULL; +#endif + sqliteFree(zConverted); + if( h==INVALID_HANDLE_VALUE ){ + return SQLITE_CANTOPEN; + } + f.h = h; + OSTRACE3("OPEN EX %d \"%s\"\n", h, zFilename); + return allocateWinFile(&f, pId); +} + +/* +** Attempt to open a new file for read-only access. +** +** On success, write the file handle into *id and return SQLITE_OK. +** +** On failure, return SQLITE_CANTOPEN. +*/ +int sqlite3WinOpenReadOnly(const char *zFilename, OsFile **pId){ + winFile f; + HANDLE h; + void *zConverted = convertUtf8Filename(zFilename); + if( zConverted==0 ){ + return SQLITE_NOMEM; + } + assert( *pId==0 ); + if( isNT() ){ + h = CreateFileW((WCHAR*)zConverted, + GENERIC_READ, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, + NULL + ); + }else{ +#if OS_WINCE + return SQLITE_NOMEM; +#else + h = CreateFileA((char*)zConverted, + GENERIC_READ, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, + NULL + ); +#endif + } + sqliteFree(zConverted); + if( h==INVALID_HANDLE_VALUE ){ + return SQLITE_CANTOPEN; + } + f.h = h; +#if OS_WINCE + f.zDeleteOnClose = 0; + f.hMutex = NULL; +#endif + OSTRACE3("OPEN RO %d \"%s\"\n", h, zFilename); + return allocateWinFile(&f, pId); +} + +/* +** Attempt to open a file descriptor for the directory that contains a +** file. This file descriptor can be used to fsync() the directory +** in order to make sure the creation of a new file is actually written +** to disk. +** +** This routine is only meaningful for Unix. It is a no-op under +** windows since windows does not support hard links. +** +** On success, a handle for a previously open file is at *id is +** updated with the new directory file descriptor and SQLITE_OK is +** returned. +** +** On failure, the function returns SQLITE_CANTOPEN and leaves +** *id unchanged. +*/ +static int winOpenDirectory( + OsFile *id, + const char *zDirname +){ + return SQLITE_OK; +} + +/* +** Create a temporary file name in zBuf. zBuf must be big enough to +** hold at least SQLITE_TEMPNAME_SIZE characters. +*/ +int sqlite3WinTempFileName(char *zBuf){ + static char zChars[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789"; + int i, j; + char zTempPath[SQLITE_TEMPNAME_SIZE]; + if( sqlite3_temp_directory ){ + strncpy(zTempPath, sqlite3_temp_directory, SQLITE_TEMPNAME_SIZE-30); + zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0; + }else if( isNT() ){ + char *zMulti; + WCHAR zWidePath[SQLITE_TEMPNAME_SIZE]; + GetTempPathW(SQLITE_TEMPNAME_SIZE-30, zWidePath); + zMulti = unicodeToUtf8(zWidePath); + if( zMulti ){ + strncpy(zTempPath, zMulti, SQLITE_TEMPNAME_SIZE-30); + zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0; + sqliteFree(zMulti); + }else{ + return SQLITE_NOMEM; + } + }else{ + char *zUtf8; + char zMbcsPath[SQLITE_TEMPNAME_SIZE]; + GetTempPathA(SQLITE_TEMPNAME_SIZE-30, zMbcsPath); + zUtf8 = mbcsToUtf8(zMbcsPath); + if( zUtf8 ){ + strncpy(zTempPath, zUtf8, SQLITE_TEMPNAME_SIZE-30); + zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0; + sqliteFree(zUtf8); + }else{ + return SQLITE_NOMEM; + } + } + for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){} + zTempPath[i] = 0; + for(;;){ + sqlite3_snprintf(SQLITE_TEMPNAME_SIZE, zBuf, + "%s\\"TEMP_FILE_PREFIX, zTempPath); + j = strlen(zBuf); + sqlite3Randomness(15, &zBuf[j]); + for(i=0; i<15; i++, j++){ + zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; + } + zBuf[j] = 0; + if( !sqlite3OsFileExists(zBuf) ) break; + } + OSTRACE2("TEMP FILENAME: %s\n", zBuf); + return SQLITE_OK; +} + +/* +** Close a file. +** +** It is reported that an attempt to close a handle might sometimes +** fail. This is a very unreasonable result, but windows is notorious +** for being unreasonable so I do not doubt that it might happen. If +** the close fails, we pause for 100 milliseconds and try again. As +** many as MX_CLOSE_ATTEMPT attempts to close the handle are made before +** giving up and returning an error. +*/ +#define MX_CLOSE_ATTEMPT 3 +static int winClose(OsFile **pId){ + winFile *pFile; + int rc = 1; + if( pId && (pFile = (winFile*)*pId)!=0 ){ + int rc, cnt = 0; + OSTRACE2("CLOSE %d\n", pFile->h); + do{ + rc = CloseHandle(pFile->h); + }while( rc==0 && cnt++ < MX_CLOSE_ATTEMPT && (Sleep(100), 1) ); +#if OS_WINCE + winceDestroyLock(pFile); +#endif + OpenCounter(-1); + sqliteFree(pFile); + *pId = 0; + } + return rc ? SQLITE_OK : SQLITE_IOERR; +} + +/* +** Read data from a file into a buffer. Return SQLITE_OK if all +** bytes were read successfully and SQLITE_IOERR if anything goes +** wrong. +*/ +static int winRead(OsFile *id, void *pBuf, int amt){ + DWORD got; + assert( id!=0 ); + SimulateIOError(return SQLITE_IOERR_READ); + OSTRACE3("READ %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype); + if( !ReadFile(((winFile*)id)->h, pBuf, amt, &got, 0) ){ + return SQLITE_IOERR_READ; + } + if( got==(DWORD)amt ){ + return SQLITE_OK; + }else{ + memset(&((char*)pBuf)[got], 0, amt-got); + return SQLITE_IOERR_SHORT_READ; + } +} + +/* +** Write data from a buffer into a file. Return SQLITE_OK on success +** or some other error code on failure. +*/ +static int winWrite(OsFile *id, const void *pBuf, int amt){ + int rc = 0; + DWORD wrote; + assert( id!=0 ); + SimulateIOError(return SQLITE_IOERR_READ); + SimulateDiskfullError(return SQLITE_FULL); + OSTRACE3("WRITE %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype); + assert( amt>0 ); + while( amt>0 && (rc = WriteFile(((winFile*)id)->h, pBuf, amt, &wrote, 0))!=0 + && wrote>0 ){ + amt -= wrote; + pBuf = &((char*)pBuf)[wrote]; + } + if( !rc || amt>(int)wrote ){ + return SQLITE_FULL; + } + return SQLITE_OK; +} + +/* +** Some microsoft compilers lack this definition. +*/ +#ifndef INVALID_SET_FILE_POINTER +# define INVALID_SET_FILE_POINTER ((DWORD)-1) +#endif + +/* +** Move the read/write pointer in a file. +*/ +static int winSeek(OsFile *id, i64 offset){ + LONG upperBits = offset>>32; + LONG lowerBits = offset & 0xffffffff; + DWORD rc; + assert( id!=0 ); +#ifdef SQLITE_TEST + if( offset ) SimulateDiskfullError(return SQLITE_FULL); +#endif + rc = SetFilePointer(((winFile*)id)->h, lowerBits, &upperBits, FILE_BEGIN); + OSTRACE3("SEEK %d %lld\n", ((winFile*)id)->h, offset); + if( rc==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR ){ + return SQLITE_FULL; + } + return SQLITE_OK; +} + +/* +** Make sure all writes to a particular file are committed to disk. +*/ +static int winSync(OsFile *id, int dataOnly){ + assert( id!=0 ); + OSTRACE3("SYNC %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype); + if( FlushFileBuffers(((winFile*)id)->h) ){ + return SQLITE_OK; + }else{ + return SQLITE_IOERR; + } +} + +/* +** Sync the directory zDirname. This is a no-op on operating systems other +** than UNIX. +*/ +int sqlite3WinSyncDirectory(const char *zDirname){ + SimulateIOError(return SQLITE_IOERR_READ); + return SQLITE_OK; +} + +/* +** Truncate an open file to a specified size +*/ +static int winTruncate(OsFile *id, i64 nByte){ + LONG upperBits = nByte>>32; + assert( id!=0 ); + OSTRACE3("TRUNCATE %d %lld\n", ((winFile*)id)->h, nByte); + SimulateIOError(return SQLITE_IOERR_TRUNCATE); + SetFilePointer(((winFile*)id)->h, nByte, &upperBits, FILE_BEGIN); + SetEndOfFile(((winFile*)id)->h); + return SQLITE_OK; +} + +/* +** Determine the current size of a file in bytes +*/ +static int winFileSize(OsFile *id, i64 *pSize){ + DWORD upperBits, lowerBits; + assert( id!=0 ); + SimulateIOError(return SQLITE_IOERR_FSTAT); + lowerBits = GetFileSize(((winFile*)id)->h, &upperBits); + *pSize = (((i64)upperBits)<<32) + lowerBits; + return SQLITE_OK; +} + +/* +** LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems. +*/ +#ifndef LOCKFILE_FAIL_IMMEDIATELY +# define LOCKFILE_FAIL_IMMEDIATELY 1 +#endif + +/* +** Acquire a reader lock. +** Different API routines are called depending on whether or not this +** is Win95 or WinNT. +*/ +static int getReadLock(winFile *id){ + int res; + if( isNT() ){ + OVERLAPPED ovlp; + ovlp.Offset = SHARED_FIRST; + ovlp.OffsetHigh = 0; + ovlp.hEvent = 0; + res = LockFileEx(id->h, LOCKFILE_FAIL_IMMEDIATELY, 0, SHARED_SIZE,0,&ovlp); + }else{ + int lk; + sqlite3Randomness(sizeof(lk), &lk); + id->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1); + res = LockFile(id->h, SHARED_FIRST+id->sharedLockByte, 0, 1, 0); + } + return res; +} + +/* +** Undo a readlock +*/ +static int unlockReadLock(winFile *pFile){ + int res; + if( isNT() ){ + res = UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); + }else{ + res = UnlockFile(pFile->h, SHARED_FIRST + pFile->sharedLockByte, 0, 1, 0); + } + return res; +} + +#ifndef SQLITE_OMIT_PAGER_PRAGMAS +/* +** Check that a given pathname is a directory and is writable +** +*/ +int sqlite3WinIsDirWritable(char *zDirname){ + int fileAttr; + void *zConverted; + if( zDirname==0 ) return 0; + if( !isNT() && strlen(zDirname)>MAX_PATH ) return 0; + + zConverted = convertUtf8Filename(zDirname); + if( zConverted==0 ){ + return SQLITE_NOMEM; + } + if( isNT() ){ + fileAttr = GetFileAttributesW((WCHAR*)zConverted); + }else{ +#if OS_WINCE + return 0; +#else + fileAttr = GetFileAttributesA((char*)zConverted); +#endif + } + sqliteFree(zConverted); + if( fileAttr == 0xffffffff ) return 0; + if( (fileAttr & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY ){ + return 0; + } + return 1; +} +#endif /* SQLITE_OMIT_PAGER_PRAGMAS */ + +/* +** Lock the file with the lock specified by parameter locktype - one +** of the following: +** +** (1) SHARED_LOCK +** (2) RESERVED_LOCK +** (3) PENDING_LOCK +** (4) EXCLUSIVE_LOCK +** +** Sometimes when requesting one lock state, additional lock states +** are inserted in between. The locking might fail on one of the later +** transitions leaving the lock state different from what it started but +** still short of its goal. The following chart shows the allowed +** transitions and the inserted intermediate states: +** +** UNLOCKED -> SHARED +** SHARED -> RESERVED +** SHARED -> (PENDING) -> EXCLUSIVE +** RESERVED -> (PENDING) -> EXCLUSIVE +** PENDING -> EXCLUSIVE +** +** This routine will only increase a lock. The winUnlock() routine +** erases all locks at once and returns us immediately to locking level 0. +** It is not possible to lower the locking level one step at a time. You +** must go straight to locking level 0. +*/ +static int winLock(OsFile *id, int locktype){ + int rc = SQLITE_OK; /* Return code from subroutines */ + int res = 1; /* Result of a windows lock call */ + int newLocktype; /* Set id->locktype to this value before exiting */ + int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */ + winFile *pFile = (winFile*)id; + + assert( pFile!=0 ); + OSTRACE5("LOCK %d %d was %d(%d)\n", + pFile->h, locktype, pFile->locktype, pFile->sharedLockByte); + + /* If there is already a lock of this type or more restrictive on the + ** OsFile, do nothing. Don't use the end_lock: exit path, as + ** sqlite3OsEnterMutex() hasn't been called yet. + */ + if( pFile->locktype>=locktype ){ + return SQLITE_OK; + } + + /* Make sure the locking sequence is correct + */ + assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); + assert( locktype!=PENDING_LOCK ); + assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); + + /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or + ** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of + ** the PENDING_LOCK byte is temporary. + */ + newLocktype = pFile->locktype; + if( pFile->locktype==NO_LOCK + || (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK) + ){ + int cnt = 3; + while( cnt-->0 && (res = LockFile(pFile->h, PENDING_BYTE, 0, 1, 0))==0 ){ + /* Try 3 times to get the pending lock. The pending lock might be + ** held by another reader process who will release it momentarily. + */ + OSTRACE2("could not get a PENDING lock. cnt=%d\n", cnt); + Sleep(1); + } + gotPendingLock = res; + } + + /* Acquire a shared lock + */ + if( locktype==SHARED_LOCK && res ){ + assert( pFile->locktype==NO_LOCK ); + res = getReadLock(pFile); + if( res ){ + newLocktype = SHARED_LOCK; + } + } + + /* Acquire a RESERVED lock + */ + if( locktype==RESERVED_LOCK && res ){ + assert( pFile->locktype==SHARED_LOCK ); + res = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); + if( res ){ + newLocktype = RESERVED_LOCK; + } + } + + /* Acquire a PENDING lock + */ + if( locktype==EXCLUSIVE_LOCK && res ){ + newLocktype = PENDING_LOCK; + gotPendingLock = 0; + } + + /* Acquire an EXCLUSIVE lock + */ + if( locktype==EXCLUSIVE_LOCK && res ){ + assert( pFile->locktype>=SHARED_LOCK ); + res = unlockReadLock(pFile); + OSTRACE2("unreadlock = %d\n", res); + res = LockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); + if( res ){ + newLocktype = EXCLUSIVE_LOCK; + }else{ + OSTRACE2("error-code = %d\n", GetLastError()); + getReadLock(pFile); + } + } + + /* If we are holding a PENDING lock that ought to be released, then + ** release it now. + */ + if( gotPendingLock && locktype==SHARED_LOCK ){ + UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0); + } + + /* Update the state of the lock has held in the file descriptor then + ** return the appropriate result code. + */ + if( res ){ + rc = SQLITE_OK; + }else{ + OSTRACE4("LOCK FAILED %d trying for %d but got %d\n", pFile->h, + locktype, newLocktype); + rc = SQLITE_BUSY; + } + pFile->locktype = newLocktype; + return rc; +} + +/* +** This routine checks if there is a RESERVED lock held on the specified +** file by this or any other process. If such a lock is held, return +** non-zero, otherwise zero. +*/ +static int winCheckReservedLock(OsFile *id){ + int rc; + winFile *pFile = (winFile*)id; + assert( pFile!=0 ); + if( pFile->locktype>=RESERVED_LOCK ){ + rc = 1; + OSTRACE3("TEST WR-LOCK %d %d (local)\n", pFile->h, rc); + }else{ + rc = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); + if( rc ){ + UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); + } + rc = !rc; + OSTRACE3("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc); + } + return rc; +} + +/* +** Lower the locking level on file descriptor id to locktype. locktype +** must be either NO_LOCK or SHARED_LOCK. +** +** If the locking level of the file descriptor is already at or below +** the requested locking level, this routine is a no-op. +** +** It is not possible for this routine to fail if the second argument +** is NO_LOCK. If the second argument is SHARED_LOCK then this routine +** might return SQLITE_IOERR; +*/ +static int winUnlock(OsFile *id, int locktype){ + int type; + int rc = SQLITE_OK; + winFile *pFile = (winFile*)id; + assert( pFile!=0 ); + assert( locktype<=SHARED_LOCK ); + OSTRACE5("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype, + pFile->locktype, pFile->sharedLockByte); + type = pFile->locktype; + if( type>=EXCLUSIVE_LOCK ){ + UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); + if( locktype==SHARED_LOCK && !getReadLock(pFile) ){ + /* This should never happen. We should always be able to + ** reacquire the read lock */ + rc = SQLITE_IOERR_UNLOCK; + } + } + if( type>=RESERVED_LOCK ){ + UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); + } + if( locktype==NO_LOCK && type>=SHARED_LOCK ){ + unlockReadLock(pFile); + } + if( type>=PENDING_LOCK ){ + UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0); + } + pFile->locktype = locktype; + return rc; +} + +/* +** Turn a relative pathname into a full pathname. Return a pointer +** to the full pathname stored in space obtained from sqliteMalloc(). +** The calling function is responsible for freeing this space once it +** is no longer needed. +*/ +char *sqlite3WinFullPathname(const char *zRelative){ + char *zFull; +#if defined(__CYGWIN__) + int nByte; + nByte = strlen(zRelative) + MAX_PATH + 1001; + zFull = sqliteMalloc( nByte ); + if( zFull==0 ) return 0; + if( cygwin_conv_to_full_win32_path(zRelative, zFull) ) return 0; +#elif OS_WINCE + /* WinCE has no concept of a relative pathname, or so I am told. */ + zFull = sqliteStrDup(zRelative); +#else + int nByte; + void *zConverted; + zConverted = convertUtf8Filename(zRelative); + if( isNT() ){ + WCHAR *zTemp; + nByte = GetFullPathNameW((WCHAR*)zConverted, 0, 0, 0) + 3; + zTemp = sqliteMalloc( nByte*sizeof(zTemp[0]) ); + if( zTemp==0 ){ + sqliteFree(zConverted); + return 0; + } + GetFullPathNameW((WCHAR*)zConverted, nByte, zTemp, 0); + sqliteFree(zConverted); + zFull = unicodeToUtf8(zTemp); + sqliteFree(zTemp); + }else{ + char *zTemp; + nByte = GetFullPathNameA((char*)zConverted, 0, 0, 0) + 3; + zTemp = sqliteMalloc( nByte*sizeof(zTemp[0]) ); + if( zTemp==0 ){ + sqliteFree(zConverted); + return 0; + } + GetFullPathNameA((char*)zConverted, nByte, zTemp, 0); + sqliteFree(zConverted); + zFull = mbcsToUtf8(zTemp); + sqliteFree(zTemp); + } +#endif + return zFull; +} + +/* +** The fullSync option is meaningless on windows. This is a no-op. +*/ +static void winSetFullSync(OsFile *id, int v){ + return; +} + +/* +** Return the underlying file handle for an OsFile +*/ +static int winFileHandle(OsFile *id){ + return (int)((winFile*)id)->h; +} + +/* +** Return an integer that indices the type of lock currently held +** by this handle. (Used for testing and analysis only.) +*/ +static int winLockState(OsFile *id){ + return ((winFile*)id)->locktype; +} + +/* +** Return the sector size in bytes of the underlying block device for +** the specified file. This is almost always 512 bytes, but may be +** larger for some devices. +** +** SQLite code assumes this function cannot fail. It also assumes that +** if two files are created in the same file-system directory (i.e. +** a database and it's journal file) that the sector size will be the +** same for both. +*/ +static int winSectorSize(OsFile *id){ + return SQLITE_DEFAULT_SECTOR_SIZE; +} + +/* +** This vector defines all the methods that can operate on an OsFile +** for win32. +*/ +static const IoMethod sqlite3WinIoMethod = { + winClose, + winOpenDirectory, + winRead, + winWrite, + winSeek, + winTruncate, + winSync, + winSetFullSync, + winFileHandle, + winFileSize, + winLock, + winUnlock, + winLockState, + winCheckReservedLock, + winSectorSize, +}; + +/* +** Allocate memory for an OsFile. Initialize the new OsFile +** to the value given in pInit and return a pointer to the new +** OsFile. If we run out of memory, close the file and return NULL. +*/ +static int allocateWinFile(winFile *pInit, OsFile **pId){ + winFile *pNew; + pNew = sqliteMalloc( sizeof(*pNew) ); + if( pNew==0 ){ + CloseHandle(pInit->h); +#if OS_WINCE + sqliteFree(pInit->zDeleteOnClose); +#endif + *pId = 0; + return SQLITE_NOMEM; + }else{ + *pNew = *pInit; + pNew->pMethod = &sqlite3WinIoMethod; + pNew->locktype = NO_LOCK; + pNew->sharedLockByte = 0; + *pId = (OsFile*)pNew; + OpenCounter(+1); + return SQLITE_OK; + } +} + + +#endif /* SQLITE_OMIT_DISKIO */ +/*************************************************************************** +** Everything above deals with file I/O. Everything that follows deals +** with other miscellanous aspects of the operating system interface +****************************************************************************/ + +#if !defined(SQLITE_OMIT_LOAD_EXTENSION) +/* +** Interfaces for opening a shared library, finding entry points +** within the shared library, and closing the shared library. +*/ +void *sqlite3WinDlopen(const char *zFilename){ + HANDLE h; + void *zConverted = convertUtf8Filename(zFilename); + if( zConverted==0 ){ + return 0; + } + if( isNT() ){ + h = LoadLibraryW((WCHAR*)zConverted); + }else{ +#if OS_WINCE + return 0; +#else + h = LoadLibraryA((char*)zConverted); +#endif + } + sqliteFree(zConverted); + return (void*)h; + +} +void *sqlite3WinDlsym(void *pHandle, const char *zSymbol){ +#if OS_WINCE + /* The GetProcAddressA() routine is only available on wince. */ + return GetProcAddressA((HANDLE)pHandle, zSymbol); +#else + /* All other windows platforms expect GetProcAddress() to take + ** an Ansi string regardless of the _UNICODE setting */ + return GetProcAddress((HANDLE)pHandle, zSymbol); +#endif +} +int sqlite3WinDlclose(void *pHandle){ + return FreeLibrary((HANDLE)pHandle); +} +#endif /* !SQLITE_OMIT_LOAD_EXTENSION */ + +/* +** Get information to seed the random number generator. The seed +** is written into the buffer zBuf[256]. The calling function must +** supply a sufficiently large buffer. +*/ +int sqlite3WinRandomSeed(char *zBuf){ + /* We have to initialize zBuf to prevent valgrind from reporting + ** errors. The reports issued by valgrind are incorrect - we would + ** prefer that the randomness be increased by making use of the + ** uninitialized space in zBuf - but valgrind errors tend to worry + ** some users. Rather than argue, it seems easier just to initialize + ** the whole array and silence valgrind, even if that means less randomness + ** in the random seed. + ** + ** When testing, initializing zBuf[] to zero is all we do. That means + ** that we always use the same random number sequence.* This makes the + ** tests repeatable. + */ + memset(zBuf, 0, 256); + GetSystemTime((LPSYSTEMTIME)zBuf); + return SQLITE_OK; +} + +/* +** Sleep for a little while. Return the amount of time slept. +*/ +int sqlite3WinSleep(int ms){ + Sleep(ms); + return ms; +} + +/* +** Static variables used for thread synchronization +*/ +static int inMutex = 0; +#ifdef SQLITE_W32_THREADS + static DWORD mutexOwner; + static CRITICAL_SECTION cs; +#endif + +/* +** The following pair of routines implement mutual exclusion for +** multi-threaded processes. Only a single thread is allowed to +** executed code that is surrounded by EnterMutex() and LeaveMutex(). +** +** SQLite uses only a single Mutex. There is not much critical +** code and what little there is executes quickly and without blocking. +** +** Version 3.3.1 and earlier used a simple mutex. Beginning with +** version 3.3.2, a recursive mutex is required. +*/ +void sqlite3WinEnterMutex(){ +#ifdef SQLITE_W32_THREADS + static int isInit = 0; + while( !isInit ){ + static long lock = 0; + if( InterlockedIncrement(&lock)==1 ){ + InitializeCriticalSection(&cs); + isInit = 1; + }else{ + Sleep(1); + } + } + EnterCriticalSection(&cs); + mutexOwner = GetCurrentThreadId(); +#endif + inMutex++; +} +void sqlite3WinLeaveMutex(){ + assert( inMutex ); + inMutex--; +#ifdef SQLITE_W32_THREADS + assert( mutexOwner==GetCurrentThreadId() ); + LeaveCriticalSection(&cs); +#endif +} + +/* +** Return TRUE if the mutex is currently held. +** +** If the thisThreadOnly parameter is true, return true if and only if the +** calling thread holds the mutex. If the parameter is false, return +** true if any thread holds the mutex. +*/ +int sqlite3WinInMutex(int thisThreadOnly){ +#ifdef SQLITE_W32_THREADS + return inMutex>0 && (thisThreadOnly==0 || mutexOwner==GetCurrentThreadId()); +#else + return inMutex>0; +#endif +} + + +/* +** The following variable, if set to a non-zero value, becomes the result +** returned from sqlite3OsCurrentTime(). This is used for testing. +*/ +#ifdef SQLITE_TEST +int sqlite3_current_time = 0; +#endif + +/* +** Find the current time (in Universal Coordinated Time). Write the +** current time and date as a Julian Day number into *prNow and +** return 0. Return 1 if the time and date cannot be found. +*/ +int sqlite3WinCurrentTime(double *prNow){ + FILETIME ft; + /* FILETIME structure is a 64-bit value representing the number of + 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5). + */ + double now; +#if OS_WINCE + SYSTEMTIME time; + GetSystemTime(&time); + SystemTimeToFileTime(&time,&ft); +#else + GetSystemTimeAsFileTime( &ft ); +#endif + now = ((double)ft.dwHighDateTime) * 4294967296.0; + *prNow = (now + ft.dwLowDateTime)/864000000000.0 + 2305813.5; +#ifdef SQLITE_TEST + if( sqlite3_current_time ){ + *prNow = sqlite3_current_time/86400.0 + 2440587.5; + } +#endif + return 0; +} + +/* +** Remember the number of thread-specific-data blocks allocated. +** Use this to verify that we are not leaking thread-specific-data. +** Ticket #1601 +*/ +#ifdef SQLITE_TEST +int sqlite3_tsd_count = 0; +# define TSD_COUNTER_INCR InterlockedIncrement(&sqlite3_tsd_count) +# define TSD_COUNTER_DECR InterlockedDecrement(&sqlite3_tsd_count) +#else +# define TSD_COUNTER_INCR /* no-op */ +# define TSD_COUNTER_DECR /* no-op */ +#endif + + + +/* +** If called with allocateFlag>1, then return a pointer to thread +** specific data for the current thread. Allocate and zero the +** thread-specific data if it does not already exist necessary. +** +** If called with allocateFlag==0, then check the current thread +** specific data. Return it if it exists. If it does not exist, +** then return NULL. +** +** If called with allocateFlag<0, check to see if the thread specific +** data is allocated and is all zero. If it is then deallocate it. +** Return a pointer to the thread specific data or NULL if it is +** unallocated or gets deallocated. +*/ +ThreadData *sqlite3WinThreadSpecificData(int allocateFlag){ + static int key; + static int keyInit = 0; + static const ThreadData zeroData = {0}; + ThreadData *pTsd; + + if( !keyInit ){ + sqlite3OsEnterMutex(); + if( !keyInit ){ + key = TlsAlloc(); + if( key==0xffffffff ){ + sqlite3OsLeaveMutex(); + return 0; + } + keyInit = 1; + } + sqlite3OsLeaveMutex(); + } + pTsd = TlsGetValue(key); + if( allocateFlag>0 ){ + if( !pTsd ){ + pTsd = sqlite3OsMalloc( sizeof(zeroData) ); + if( pTsd ){ + *pTsd = zeroData; + TlsSetValue(key, pTsd); + TSD_COUNTER_INCR; + } + } + }else if( pTsd!=0 && allocateFlag<0 + && memcmp(pTsd, &zeroData, sizeof(ThreadData))==0 ){ + sqlite3OsFree(pTsd); + TlsSetValue(key, 0); + TSD_COUNTER_DECR; + pTsd = 0; + } + return pTsd; +} +#endif /* OS_WIN */ diff --git a/extensions/sqlite/sqlite-source/pager.c b/extensions/sqlite/sqlite-source/pager.c new file mode 100644 index 00000000..a57e2a6b --- /dev/null +++ b/extensions/sqlite/sqlite-source/pager.c @@ -0,0 +1,4469 @@ +/* +** 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 is the implementation of the page cache subsystem or "pager". +** +** The pager is used to access a database disk file. It implements +** atomic commit and rollback through the use of a journal file that +** is separate from the database file. The pager also implements file +** locking to prevent two processes from writing the same database +** file simultaneously, or one process from reading the database while +** another is writing. +** +** @(#) $Id$ +*/ +#ifndef SQLITE_OMIT_DISKIO +#include "sqliteInt.h" +#include "os.h" +#include "pager.h" +#include +#include + +/* +** Macros for troubleshooting. Normally turned off +*/ +#if 0 +#define sqlite3DebugPrintf printf +#define PAGERTRACE1(X) sqlite3DebugPrintf(X) +#define PAGERTRACE2(X,Y) sqlite3DebugPrintf(X,Y) +#define PAGERTRACE3(X,Y,Z) sqlite3DebugPrintf(X,Y,Z) +#define PAGERTRACE4(X,Y,Z,W) sqlite3DebugPrintf(X,Y,Z,W) +#define PAGERTRACE5(X,Y,Z,W,V) sqlite3DebugPrintf(X,Y,Z,W,V) +#else +#define PAGERTRACE1(X) +#define PAGERTRACE2(X,Y) +#define PAGERTRACE3(X,Y,Z) +#define PAGERTRACE4(X,Y,Z,W) +#define PAGERTRACE5(X,Y,Z,W,V) +#endif + +/* +** The following two macros are used within the PAGERTRACEX() macros above +** to print out file-descriptors. +** +** PAGERID() takes a pointer to a Pager struct as it's argument. The +** associated file-descriptor is returned. FILEHANDLEID() takes an OsFile +** struct as it's argument. +*/ +#define PAGERID(p) ((int)(p->fd)) +#define FILEHANDLEID(fd) ((int)fd) + +/* +** The page cache as a whole is always in one of the following +** states: +** +** PAGER_UNLOCK The page cache is not currently reading or +** writing the database file. There is no +** data held in memory. This is the initial +** state. +** +** PAGER_SHARED The page cache is reading the database. +** Writing is not permitted. There can be +** multiple readers accessing the same database +** file at the same time. +** +** PAGER_RESERVED This process has reserved the database for writing +** but has not yet made any changes. Only one process +** at a time can reserve the database. The original +** database file has not been modified so other +** processes may still be reading the on-disk +** database file. +** +** PAGER_EXCLUSIVE The page cache is writing the database. +** Access is exclusive. No other processes or +** threads can be reading or writing while one +** process is writing. +** +** PAGER_SYNCED The pager moves to this state from PAGER_EXCLUSIVE +** after all dirty pages have been written to the +** database file and the file has been synced to +** disk. All that remains to do is to remove or +** truncate the journal file and the transaction +** will be committed. +** +** The page cache comes up in PAGER_UNLOCK. The first time a +** sqlite3PagerGet() occurs, the state transitions to PAGER_SHARED. +** After all pages have been released using sqlite_page_unref(), +** the state transitions back to PAGER_UNLOCK. The first time +** that sqlite3PagerWrite() is called, the state transitions to +** PAGER_RESERVED. (Note that sqlite3PagerWrite() can only be +** called on an outstanding page which means that the pager must +** be in PAGER_SHARED before it transitions to PAGER_RESERVED.) +** PAGER_RESERVED means that there is an open rollback journal. +** The transition to PAGER_EXCLUSIVE occurs before any changes +** are made to the database file, though writes to the rollback +** journal occurs with just PAGER_RESERVED. After an sqlite3PagerRollback() +** or sqlite3PagerCommitPhaseTwo(), the state can go back to PAGER_SHARED, +** or it can stay at PAGER_EXCLUSIVE if we are in exclusive access mode. +*/ +#define PAGER_UNLOCK 0 +#define PAGER_SHARED 1 /* same as SHARED_LOCK */ +#define PAGER_RESERVED 2 /* same as RESERVED_LOCK */ +#define PAGER_EXCLUSIVE 4 /* same as EXCLUSIVE_LOCK */ +#define PAGER_SYNCED 5 + +/* +** If the SQLITE_BUSY_RESERVED_LOCK macro is set to true at compile-time, +** then failed attempts to get a reserved lock will invoke the busy callback. +** This is off by default. To see why, consider the following scenario: +** +** Suppose thread A already has a shared lock and wants a reserved lock. +** Thread B already has a reserved lock and wants an exclusive lock. If +** both threads are using their busy callbacks, it might be a long time +** be for one of the threads give up and allows the other to proceed. +** But if the thread trying to get the reserved lock gives up quickly +** (if it never invokes its busy callback) then the contention will be +** resolved quickly. +*/ +#ifndef SQLITE_BUSY_RESERVED_LOCK +# define SQLITE_BUSY_RESERVED_LOCK 0 +#endif + +/* +** This macro rounds values up so that if the value is an address it +** is guaranteed to be an address that is aligned to an 8-byte boundary. +*/ +#define FORCE_ALIGNMENT(X) (((X)+7)&~7) + +/* +** Each in-memory image of a page begins with the following header. +** This header is only visible to this pager module. The client +** code that calls pager sees only the data that follows the header. +** +** Client code should call sqlite3PagerWrite() on a page prior to making +** any modifications to that page. The first time sqlite3PagerWrite() +** is called, the original page contents are written into the rollback +** journal and PgHdr.inJournal and PgHdr.needSync are set. Later, once +** the journal page has made it onto the disk surface, PgHdr.needSync +** is cleared. The modified page cannot be written back into the original +** database file until the journal pages has been synced to disk and the +** PgHdr.needSync has been cleared. +** +** The PgHdr.dirty flag is set when sqlite3PagerWrite() is called and +** is cleared again when the page content is written back to the original +** database file. +** +** Details of important structure elements: +** +** needSync +** +** If this is true, this means that it is not safe to write the page +** content to the database because the original content needed +** for rollback has not by synced to the main rollback journal. +** The original content may have been written to the rollback journal +** but it has not yet been synced. So we cannot write to the database +** file because power failure might cause the page in the journal file +** to never reach the disk. It is as if the write to the journal file +** does not occur until the journal file is synced. +** +** This flag is false if the page content exactly matches what +** currently exists in the database file. The needSync flag is also +** false if the original content has been written to the main rollback +** journal and synced. If the page represents a new page that has +** been added onto the end of the database during the current +** transaction, the needSync flag is true until the original database +** size in the journal header has been synced to disk. +** +** inJournal +** +** This is true if the original page has been written into the main +** rollback journal. This is always false for new pages added to +** the end of the database file during the current transaction. +** And this flag says nothing about whether or not the journal +** has been synced to disk. For pages that are in the original +** database file, the following expression should always be true: +** +** inJournal = (pPager->aInJournal[(pgno-1)/8] & (1<<((pgno-1)%8))!=0 +** +** The pPager->aInJournal[] array is only valid for the original +** pages of the database, not new pages that are added to the end +** of the database, so obviously the above expression cannot be +** valid for new pages. For new pages inJournal is always 0. +** +** dirty +** +** When true, this means that the content of the page has been +** modified and needs to be written back to the database file. +** If false, it means that either the content of the page is +** unchanged or else the content is unimportant and we do not +** care whether or not it is preserved. +** +** alwaysRollback +** +** This means that the sqlite3PagerDontRollback() API should be +** ignored for this page. The DontRollback() API attempts to say +** that the content of the page on disk is unimportant (it is an +** unused page on the freelist) so that it is unnecessary to +** rollback changes to this page because the content of the page +** can change without changing the meaning of the database. This +** flag overrides any DontRollback() attempt. This flag is set +** when a page that originally contained valid data is added to +** the freelist. Later in the same transaction, this page might +** be pulled from the freelist and reused for something different +** and at that point the DontRollback() API will be called because +** pages taken from the freelist do not need to be protected by +** the rollback journal. But this flag says that the page was +** not originally part of the freelist so that it still needs to +** be rolled back in spite of any subsequent DontRollback() calls. +** +** needRead +** +** This flag means (when true) that the content of the page has +** not yet been loaded from disk. The in-memory content is just +** garbage. (Actually, we zero the content, but you should not +** make any assumptions about the content nevertheless.) If the +** content is needed in the future, it should be read from the +** original database file. +*/ +typedef struct PgHdr PgHdr; +struct PgHdr { + Pager *pPager; /* The pager to which this page belongs */ + Pgno pgno; /* The page number for this page */ + PgHdr *pNextHash, *pPrevHash; /* Hash collision chain for PgHdr.pgno */ + PgHdr *pNextFree, *pPrevFree; /* Freelist of pages where nRef==0 */ + PgHdr *pNextAll; /* A list of all pages */ + u8 inJournal; /* TRUE if has been written to journal */ + u8 dirty; /* TRUE if we need to write back changes */ + u8 needSync; /* Sync journal before writing this page */ + u8 alwaysRollback; /* Disable DontRollback() for this page */ + u8 needRead; /* Read content if PagerWrite() is called */ + short int nRef; /* Number of users of this page */ + PgHdr *pDirty, *pPrevDirty; /* Dirty pages */ + u32 notUsed; /* Buffer space */ +#ifdef SQLITE_CHECK_PAGES + u32 pageHash; +#endif + /* pPager->pageSize bytes of page data follow this header */ + /* Pager.nExtra bytes of local data follow the page data */ +}; + +/* +** For an in-memory only database, some extra information is recorded about +** each page so that changes can be rolled back. (Journal files are not +** used for in-memory databases.) The following information is added to +** the end of every EXTRA block for in-memory databases. +** +** This information could have been added directly to the PgHdr structure. +** But then it would take up an extra 8 bytes of storage on every PgHdr +** even for disk-based databases. Splitting it out saves 8 bytes. This +** is only a savings of 0.8% but those percentages add up. +*/ +typedef struct PgHistory PgHistory; +struct PgHistory { + u8 *pOrig; /* Original page text. Restore to this on a full rollback */ + u8 *pStmt; /* Text as it was at the beginning of the current statement */ + PgHdr *pNextStmt, *pPrevStmt; /* List of pages in the statement journal */ + u8 inStmt; /* TRUE if in the statement subjournal */ +}; + +/* +** A macro used for invoking the codec if there is one +*/ +#ifdef SQLITE_HAS_CODEC +# define CODEC1(P,D,N,X) if( P->xCodec!=0 ){ P->xCodec(P->pCodecArg,D,N,X); } +# define CODEC2(P,D,N,X) ((char*)(P->xCodec!=0?P->xCodec(P->pCodecArg,D,N,X):D)) +#else +# define CODEC1(P,D,N,X) /* NO-OP */ +# define CODEC2(P,D,N,X) ((char*)D) +#endif + +/* +** Convert a pointer to a PgHdr into a pointer to its data +** and back again. +*/ +#define PGHDR_TO_DATA(P) ((void*)(&(P)[1])) +#define DATA_TO_PGHDR(D) (&((PgHdr*)(D))[-1]) +#define PGHDR_TO_EXTRA(G,P) ((void*)&((char*)(&(G)[1]))[(P)->pageSize]) +#define PGHDR_TO_HIST(P,PGR) \ + ((PgHistory*)&((char*)(&(P)[1]))[(PGR)->pageSize+(PGR)->nExtra]) + +/* +** A open page cache is an instance of the following structure. +** +** Pager.errCode may be set to SQLITE_IOERR, SQLITE_CORRUPT, or +** or SQLITE_FULL. Once one of the first three errors occurs, it persists +** and is returned as the result of every major pager API call. The +** SQLITE_FULL return code is slightly different. It persists only until the +** next successful rollback is performed on the pager cache. Also, +** SQLITE_FULL does not affect the sqlite3PagerGet() and sqlite3PagerLookup() +** APIs, they may still be used successfully. +*/ +struct Pager { + u8 journalOpen; /* True if journal file descriptors is valid */ + u8 journalStarted; /* True if header of journal is synced */ + u8 useJournal; /* Use a rollback journal on this file */ + u8 noReadlock; /* Do not bother to obtain readlocks */ + u8 stmtOpen; /* True if the statement subjournal is open */ + u8 stmtInUse; /* True we are in a statement subtransaction */ + u8 stmtAutoopen; /* Open stmt journal when main journal is opened*/ + u8 noSync; /* Do not sync the journal if true */ + u8 fullSync; /* Do extra syncs of the journal for robustness */ + u8 full_fsync; /* Use F_FULLFSYNC when available */ + u8 state; /* PAGER_UNLOCK, _SHARED, _RESERVED, etc. */ + u8 tempFile; /* zFilename is a temporary file */ + u8 readOnly; /* True for a read-only database */ + u8 needSync; /* True if an fsync() is needed on the journal */ + u8 dirtyCache; /* True if cached pages have changed */ + u8 alwaysRollback; /* Disable DontRollback() for all pages */ + u8 memDb; /* True to inhibit all file I/O */ + u8 setMaster; /* True if a m-j name has been written to jrnl */ + u8 doNotSync; /* Boolean. While true, do not spill the cache */ + u8 exclusiveMode; /* Boolean. True if locking_mode==EXCLUSIVE */ + u8 changeCountDone; /* Set after incrementing the change-counter */ + int errCode; /* One of several kinds of errors */ + int dbSize; /* Number of pages in the file */ + int origDbSize; /* dbSize before the current change */ + int stmtSize; /* Size of database (in pages) at stmt_begin() */ + int nRec; /* Number of pages written to the journal */ + u32 cksumInit; /* Quasi-random value added to every checksum */ + int stmtNRec; /* Number of records in stmt subjournal */ + int nExtra; /* Add this many bytes to each in-memory page */ + int pageSize; /* Number of bytes in a page */ + int nPage; /* Total number of in-memory pages */ + int nRef; /* Number of in-memory pages with PgHdr.nRef>0 */ + int mxPage; /* Maximum number of pages to hold in cache */ + Pgno mxPgno; /* Maximum allowed size of the database */ + u8 *aInJournal; /* One bit for each page in the database file */ + u8 *aInStmt; /* One bit for each page in the database */ + char *zFilename; /* Name of the database file */ + char *zJournal; /* Name of the journal file */ + char *zDirectory; /* Directory hold database and journal files */ + OsFile *fd, *jfd; /* File descriptors for database and journal */ + OsFile *stfd; /* File descriptor for the statement subjournal*/ + BusyHandler *pBusyHandler; /* Pointer to sqlite.busyHandler */ + PgHdr *pFirst, *pLast; /* List of free pages */ + PgHdr *pFirstSynced; /* First free page with PgHdr.needSync==0 */ + PgHdr *pAll; /* List of all pages */ + PgHdr *pStmt; /* List of pages in the statement subjournal */ + PgHdr *pDirty; /* List of all dirty pages */ + i64 journalOff; /* Current byte offset in the journal file */ + i64 journalHdr; /* Byte offset to previous journal header */ + i64 stmtHdrOff; /* First journal header written this statement */ + i64 stmtCksum; /* cksumInit when statement was started */ + i64 stmtJSize; /* Size of journal at stmt_begin() */ + int sectorSize; /* Assumed sector size during rollback */ +#ifdef SQLITE_TEST + int nHit, nMiss; /* Cache hits and missing */ + int nRead, nWrite; /* Database pages read/written */ +#endif + void (*xDestructor)(DbPage*,int); /* Call this routine when freeing pages */ + void (*xReiniter)(DbPage*,int); /* Call this routine when reloading pages */ +#ifdef SQLITE_HAS_CODEC + void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */ + void *pCodecArg; /* First argument to xCodec() */ +#endif + int nHash; /* Size of the pager hash table */ + PgHdr **aHash; /* Hash table to map page number to PgHdr */ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + Pager *pNext; /* Linked list of pagers in this thread */ +#endif + char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */ + char dbFileVers[16]; /* Changes whenever database file changes */ +}; + +/* +** The following global variables hold counters used for +** testing purposes only. These variables do not exist in +** a non-testing build. These variables are not thread-safe. +*/ +#ifdef SQLITE_TEST +int sqlite3_pager_readdb_count = 0; /* Number of full pages read from DB */ +int sqlite3_pager_writedb_count = 0; /* Number of full pages written to DB */ +int sqlite3_pager_writej_count = 0; /* Number of pages written to journal */ +int sqlite3_pager_pgfree_count = 0; /* Number of cache pages freed */ +# define PAGER_INCR(v) v++ +#else +# define PAGER_INCR(v) +#endif + + + +/* +** Journal files begin with the following magic string. The data +** was obtained from /dev/random. It is used only as a sanity check. +** +** Since version 2.8.0, the journal format contains additional sanity +** checking information. If the power fails while the journal is begin +** written, semi-random garbage data might appear in the journal +** file after power is restored. If an attempt is then made +** to roll the journal back, the database could be corrupted. The additional +** sanity checking data is an attempt to discover the garbage in the +** journal and ignore it. +** +** The sanity checking information for the new journal format consists +** of a 32-bit checksum on each page of data. The checksum covers both +** the page number and the pPager->pageSize bytes of data for the page. +** This cksum is initialized to a 32-bit random value that appears in the +** journal file right after the header. The random initializer is important, +** because garbage data that appears at the end of a journal is likely +** data that was once in other files that have now been deleted. If the +** garbage data came from an obsolete journal file, the checksums might +** be correct. But by initializing the checksum to random value which +** is different for every journal, we minimize that risk. +*/ +static const unsigned char aJournalMagic[] = { + 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd7, +}; + +/* +** The size of the header and of each page in the journal is determined +** by the following macros. +*/ +#define JOURNAL_PG_SZ(pPager) ((pPager->pageSize) + 8) + +/* +** The journal header size for this pager. In the future, this could be +** set to some value read from the disk controller. The important +** characteristic is that it is the same size as a disk sector. +*/ +#define JOURNAL_HDR_SZ(pPager) (pPager->sectorSize) + +/* +** The macro MEMDB is true if we are dealing with an in-memory database. +** We do this as a macro so that if the SQLITE_OMIT_MEMORYDB macro is set, +** the value of MEMDB will be a constant and the compiler will optimize +** out code that would never execute. +*/ +#ifdef SQLITE_OMIT_MEMORYDB +# define MEMDB 0 +#else +# define MEMDB pPager->memDb +#endif + +/* +** Page number PAGER_MJ_PGNO is never used in an SQLite database (it is +** reserved for working around a windows/posix incompatibility). It is +** used in the journal to signify that the remainder of the journal file +** is devoted to storing a master journal name - there are no more pages to +** roll back. See comments for function writeMasterJournal() for details. +*/ +/* #define PAGER_MJ_PGNO(x) (PENDING_BYTE/((x)->pageSize)) */ +#define PAGER_MJ_PGNO(x) ((PENDING_BYTE/((x)->pageSize))+1) + +/* +** The maximum legal page number is (2^31 - 1). +*/ +#define PAGER_MAX_PGNO 2147483647 + +/* +** Enable reference count tracking (for debugging) here: +*/ +#ifdef SQLITE_DEBUG + int pager3_refinfo_enable = 0; + static void pager_refinfo(PgHdr *p){ + static int cnt = 0; + if( !pager3_refinfo_enable ) return; + sqlite3DebugPrintf( + "REFCNT: %4d addr=%p nRef=%-3d total=%d\n", + p->pgno, PGHDR_TO_DATA(p), p->nRef, p->pPager->nRef + ); + cnt++; /* Something to set a breakpoint on */ + } +# define REFINFO(X) pager_refinfo(X) +#else +# define REFINFO(X) +#endif + +/* +** Return true if page *pPg has already been written to the statement +** journal (or statement snapshot has been created, if *pPg is part +** of an in-memory database). +*/ +static int pageInStatement(PgHdr *pPg){ + Pager *pPager = pPg->pPager; + if( MEMDB ){ + return PGHDR_TO_HIST(pPg, pPager)->inStmt; + }else{ + Pgno pgno = pPg->pgno; + u8 *a = pPager->aInStmt; + return (a && (int)pgno<=pPager->stmtSize && (a[pgno/8] & (1<<(pgno&7)))); + } +} + +/* +** Change the size of the pager hash table to N. N must be a power +** of two. +*/ +static void pager_resize_hash_table(Pager *pPager, int N){ + PgHdr **aHash, *pPg; + assert( N>0 && (N&(N-1))==0 ); + aHash = sqliteMalloc( sizeof(aHash[0])*N ); + if( aHash==0 ){ + /* Failure to rehash is not an error. It is only a performance hit. */ + return; + } + sqliteFree(pPager->aHash); + pPager->nHash = N; + pPager->aHash = aHash; + for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ + int h; + if( pPg->pgno==0 ){ + assert( pPg->pNextHash==0 && pPg->pPrevHash==0 ); + continue; + } + h = pPg->pgno & (N-1); + pPg->pNextHash = aHash[h]; + if( aHash[h] ){ + aHash[h]->pPrevHash = pPg; + } + aHash[h] = pPg; + pPg->pPrevHash = 0; + } +} + +/* +** Read a 32-bit integer from the given file descriptor. Store the integer +** that is read in *pRes. Return SQLITE_OK if everything worked, or an +** error code is something goes wrong. +** +** All values are stored on disk as big-endian. +*/ +static int read32bits(OsFile *fd, u32 *pRes){ + unsigned char ac[4]; + int rc = sqlite3OsRead(fd, ac, sizeof(ac)); + if( rc==SQLITE_OK ){ + *pRes = sqlite3Get4byte(ac); + } + return rc; +} + +/* +** Write a 32-bit integer into a string buffer in big-endian byte order. +*/ +#define put32bits(A,B) sqlite3Put4byte((u8*)A,B) + +/* +** Write a 32-bit integer into the given file descriptor. Return SQLITE_OK +** on success or an error code is something goes wrong. +*/ +static int write32bits(OsFile *fd, u32 val){ + char ac[4]; + put32bits(ac, val); + return sqlite3OsWrite(fd, ac, 4); +} + +/* +** This function should be called when an error occurs within the pager +** code. The first argument is a pointer to the pager structure, the +** second the error-code about to be returned by a pager API function. +** The value returned is a copy of the second argument to this function. +** +** If the second argument is SQLITE_IOERR, SQLITE_CORRUPT, or SQLITE_FULL +** the error becomes persistent. All subsequent API calls on this Pager +** will immediately return the same error code. +*/ +static int pager_error(Pager *pPager, int rc){ + int rc2 = rc & 0xff; + assert( pPager->errCode==SQLITE_FULL || pPager->errCode==SQLITE_OK ); + if( + rc2==SQLITE_FULL || + rc2==SQLITE_IOERR || + rc2==SQLITE_CORRUPT + ){ + pPager->errCode = rc; + } + return rc; +} + +/* +** If SQLITE_CHECK_PAGES is defined then we do some sanity checking +** on the cache using a hash function. This is used for testing +** and debugging only. +*/ +#ifdef SQLITE_CHECK_PAGES +/* +** Return a 32-bit hash of the page data for pPage. +*/ +static u32 pager_datahash(int nByte, unsigned char *pData){ + u32 hash = 0; + int i; + for(i=0; ipPager->pageSize, + (unsigned char *)PGHDR_TO_DATA(pPage)); +} + +/* +** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES +** is defined, and NDEBUG is not defined, an assert() statement checks +** that the page is either dirty or still matches the calculated page-hash. +*/ +#define CHECK_PAGE(x) checkPage(x) +static void checkPage(PgHdr *pPg){ + Pager *pPager = pPg->pPager; + assert( !pPg->pageHash || pPager->errCode || MEMDB || pPg->dirty || + pPg->pageHash==pager_pagehash(pPg) ); +} + +#else +#define pager_datahash(X,Y) 0 +#define pager_pagehash(X) 0 +#define CHECK_PAGE(x) +#endif + +/* +** When this is called the journal file for pager pPager must be open. +** The master journal file name is read from the end of the file and +** written into memory obtained from sqliteMalloc(). *pzMaster is +** set to point at the memory and SQLITE_OK returned. The caller must +** sqliteFree() *pzMaster. +** +** If no master journal file name is present *pzMaster is set to 0 and +** SQLITE_OK returned. +*/ +static int readMasterJournal(OsFile *pJrnl, char **pzMaster){ + int rc; + u32 len; + i64 szJ; + u32 cksum; + int i; + unsigned char aMagic[8]; /* A buffer to hold the magic header */ + + *pzMaster = 0; + + rc = sqlite3OsFileSize(pJrnl, &szJ); + if( rc!=SQLITE_OK || szJ<16 ) return rc; + + rc = sqlite3OsSeek(pJrnl, szJ-16); + if( rc!=SQLITE_OK ) return rc; + + rc = read32bits(pJrnl, &len); + if( rc!=SQLITE_OK ) return rc; + + rc = read32bits(pJrnl, &cksum); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3OsRead(pJrnl, aMagic, 8); + if( rc!=SQLITE_OK || memcmp(aMagic, aJournalMagic, 8) ) return rc; + + rc = sqlite3OsSeek(pJrnl, szJ-16-len); + if( rc!=SQLITE_OK ) return rc; + + *pzMaster = (char *)sqliteMalloc(len+1); + if( !*pzMaster ){ + return SQLITE_NOMEM; + } + rc = sqlite3OsRead(pJrnl, *pzMaster, len); + if( rc!=SQLITE_OK ){ + sqliteFree(*pzMaster); + *pzMaster = 0; + return rc; + } + + /* See if the checksum matches the master journal name */ + for(i=0; ijournalOff; + if( c ){ + offset = ((c-1)/JOURNAL_HDR_SZ(pPager) + 1) * JOURNAL_HDR_SZ(pPager); + } + assert( offset%JOURNAL_HDR_SZ(pPager)==0 ); + assert( offset>=c ); + assert( (offset-c)journalOff = offset; + return sqlite3OsSeek(pPager->jfd, pPager->journalOff); +} + +/* +** The journal file must be open when this routine is called. A journal +** header (JOURNAL_HDR_SZ bytes) is written into the journal file at the +** current location. +** +** The format for the journal header is as follows: +** - 8 bytes: Magic identifying journal format. +** - 4 bytes: Number of records in journal, or -1 no-sync mode is on. +** - 4 bytes: Random number used for page hash. +** - 4 bytes: Initial database page count. +** - 4 bytes: Sector size used by the process that wrote this journal. +** +** Followed by (JOURNAL_HDR_SZ - 24) bytes of unused space. +*/ +static int writeJournalHdr(Pager *pPager){ + char zHeader[sizeof(aJournalMagic)+16]; + int rc; + + if( pPager->stmtHdrOff==0 ){ + pPager->stmtHdrOff = pPager->journalOff; + } + + rc = seekJournalHdr(pPager); + if( rc ) return rc; + + pPager->journalHdr = pPager->journalOff; + pPager->journalOff += JOURNAL_HDR_SZ(pPager); + + /* FIX ME: + ** + ** Possibly for a pager not in no-sync mode, the journal magic should not + ** be written until nRec is filled in as part of next syncJournal(). + ** + ** Actually maybe the whole journal header should be delayed until that + ** point. Think about this. + */ + memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic)); + /* The nRec Field. 0xFFFFFFFF for no-sync journals. */ + put32bits(&zHeader[sizeof(aJournalMagic)], pPager->noSync ? 0xffffffff : 0); + /* The random check-hash initialiser */ + sqlite3Randomness(sizeof(pPager->cksumInit), &pPager->cksumInit); + put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit); + /* The initial database size */ + put32bits(&zHeader[sizeof(aJournalMagic)+8], pPager->dbSize); + /* The assumed sector size for this process */ + put32bits(&zHeader[sizeof(aJournalMagic)+12], pPager->sectorSize); + IOTRACE(("JHDR %p %lld %d\n", pPager, pPager->journalHdr, sizeof(zHeader))) + rc = sqlite3OsWrite(pPager->jfd, zHeader, sizeof(zHeader)); + + /* The journal header has been written successfully. Seek the journal + ** file descriptor to the end of the journal header sector. + */ + if( rc==SQLITE_OK ){ + IOTRACE(("JTAIL %p %lld\n", pPager, pPager->journalOff-1)) + rc = sqlite3OsSeek(pPager->jfd, pPager->journalOff-1); + if( rc==SQLITE_OK ){ + rc = sqlite3OsWrite(pPager->jfd, "\000", 1); + } + } + return rc; +} + +/* +** The journal file must be open when this is called. A journal header file +** (JOURNAL_HDR_SZ bytes) is read from the current location in the journal +** file. See comments above function writeJournalHdr() for a description of +** the journal header format. +** +** If the header is read successfully, *nRec is set to the number of +** page records following this header and *dbSize is set to the size of the +** database before the transaction began, in pages. Also, pPager->cksumInit +** is set to the value read from the journal header. SQLITE_OK is returned +** in this case. +** +** If the journal header file appears to be corrupted, SQLITE_DONE is +** returned and *nRec and *dbSize are not set. If JOURNAL_HDR_SZ bytes +** cannot be read from the journal file an error code is returned. +*/ +static int readJournalHdr( + Pager *pPager, + i64 journalSize, + u32 *pNRec, + u32 *pDbSize +){ + int rc; + unsigned char aMagic[8]; /* A buffer to hold the magic header */ + + rc = seekJournalHdr(pPager); + if( rc ) return rc; + + if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){ + return SQLITE_DONE; + } + + rc = sqlite3OsRead(pPager->jfd, aMagic, sizeof(aMagic)); + if( rc ) return rc; + + if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){ + return SQLITE_DONE; + } + + rc = read32bits(pPager->jfd, pNRec); + if( rc ) return rc; + + rc = read32bits(pPager->jfd, &pPager->cksumInit); + if( rc ) return rc; + + rc = read32bits(pPager->jfd, pDbSize); + if( rc ) return rc; + + /* Update the assumed sector-size to match the value used by + ** the process that created this journal. If this journal was + ** created by a process other than this one, then this routine + ** is being called from within pager_playback(). The local value + ** of Pager.sectorSize is restored at the end of that routine. + */ + rc = read32bits(pPager->jfd, (u32 *)&pPager->sectorSize); + if( rc ) return rc; + + pPager->journalOff += JOURNAL_HDR_SZ(pPager); + rc = sqlite3OsSeek(pPager->jfd, pPager->journalOff); + return rc; +} + + +/* +** Write the supplied master journal name into the journal file for pager +** pPager at the current location. The master journal name must be the last +** thing written to a journal file. If the pager is in full-sync mode, the +** journal file descriptor is advanced to the next sector boundary before +** anything is written. The format is: +** +** + 4 bytes: PAGER_MJ_PGNO. +** + N bytes: length of master journal name. +** + 4 bytes: N +** + 4 bytes: Master journal name checksum. +** + 8 bytes: aJournalMagic[]. +** +** The master journal page checksum is the sum of the bytes in the master +** journal name. +** +** If zMaster is a NULL pointer (occurs for a single database transaction), +** this call is a no-op. +*/ +static int writeMasterJournal(Pager *pPager, const char *zMaster){ + int rc; + int len; + int i; + u32 cksum = 0; + char zBuf[sizeof(aJournalMagic)+2*4]; + + if( !zMaster || pPager->setMaster) return SQLITE_OK; + pPager->setMaster = 1; + + len = strlen(zMaster); + for(i=0; ifullSync ){ + rc = seekJournalHdr(pPager); + if( rc!=SQLITE_OK ) return rc; + } + pPager->journalOff += (len+20); + + rc = write32bits(pPager->jfd, PAGER_MJ_PGNO(pPager)); + if( rc!=SQLITE_OK ) return rc; + + rc = sqlite3OsWrite(pPager->jfd, zMaster, len); + if( rc!=SQLITE_OK ) return rc; + + put32bits(zBuf, len); + put32bits(&zBuf[4], cksum); + memcpy(&zBuf[8], aJournalMagic, sizeof(aJournalMagic)); + rc = sqlite3OsWrite(pPager->jfd, zBuf, 8+sizeof(aJournalMagic)); + pPager->needSync = !pPager->noSync; + return rc; +} + +/* +** Add or remove a page from the list of all pages that are in the +** statement journal. +** +** The Pager keeps a separate list of pages that are currently in +** the statement journal. This helps the sqlite3PagerStmtCommit() +** routine run MUCH faster for the common case where there are many +** pages in memory but only a few are in the statement journal. +*/ +static void page_add_to_stmt_list(PgHdr *pPg){ + Pager *pPager = pPg->pPager; + PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); + assert( MEMDB ); + if( !pHist->inStmt ){ + assert( pHist->pPrevStmt==0 && pHist->pNextStmt==0 ); + if( pPager->pStmt ){ + PGHDR_TO_HIST(pPager->pStmt, pPager)->pPrevStmt = pPg; + } + pHist->pNextStmt = pPager->pStmt; + pPager->pStmt = pPg; + pHist->inStmt = 1; + } +} + +/* +** Find a page in the hash table given its page number. Return +** a pointer to the page or NULL if not found. +*/ +static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){ + PgHdr *p; + if( pPager->aHash==0 ) return 0; + p = pPager->aHash[pgno & (pPager->nHash-1)]; + while( p && p->pgno!=pgno ){ + p = p->pNextHash; + } + return p; +} + +/* +** Unlock the database file. +*/ +static void pager_unlock(Pager *pPager){ + if( !pPager->exclusiveMode ){ + if( !MEMDB ){ + sqlite3OsUnlock(pPager->fd, NO_LOCK); + pPager->dbSize = -1; + IOTRACE(("UNLOCK %p\n", pPager)) + } + pPager->state = PAGER_UNLOCK; + pPager->changeCountDone = 0; + } +} + +/* +** Execute a rollback if a transaction is active and unlock the +** database file. This is a no-op if the pager has already entered +** the error-state. +*/ +static void pagerUnlockAndRollback(Pager *p){ + if( p->errCode ) return; + assert( p->state>=PAGER_RESERVED || p->journalOpen==0 ); + if( p->state>=PAGER_RESERVED ){ + sqlite3PagerRollback(p); + } + pager_unlock(p); + assert( p->errCode || !p->journalOpen || (p->exclusiveMode&&!p->journalOff) ); + assert( p->errCode || !p->stmtOpen || p->exclusiveMode ); +} + + +/* +** Clear the in-memory cache. This routine +** sets the state of the pager back to what it was when it was first +** opened. Any outstanding pages are invalidated and subsequent attempts +** to access those pages will likely result in a coredump. +*/ +static void pager_reset(Pager *pPager){ + PgHdr *pPg, *pNext; + if( pPager->errCode ) return; + for(pPg=pPager->pAll; pPg; pPg=pNext){ + IOTRACE(("PGFREE %p %d\n", pPager, pPg->pgno)); + PAGER_INCR(sqlite3_pager_pgfree_count); + pNext = pPg->pNextAll; + sqliteFree(pPg); + } + pPager->pStmt = 0; + pPager->pFirst = 0; + pPager->pFirstSynced = 0; + pPager->pLast = 0; + pPager->pAll = 0; + pPager->nHash = 0; + sqliteFree(pPager->aHash); + pPager->nPage = 0; + pPager->aHash = 0; + pPager->nRef = 0; +} + +/* +** This routine ends a transaction. A transaction is ended by either +** a COMMIT or a ROLLBACK. +** +** When this routine is called, the pager has the journal file open and +** a RESERVED or EXCLUSIVE lock on the database. This routine will release +** the database lock and acquires a SHARED lock in its place if that is +** the appropriate thing to do. Release locks usually is appropriate, +** unless we are in exclusive access mode or unless this is a +** COMMIT AND BEGIN or ROLLBACK AND BEGIN operation. +** +** The journal file is either deleted or truncated. +** +** TODO: Consider keeping the journal file open for temporary databases. +** This might give a performance improvement on windows where opening +** a file is an expensive operation. +*/ +static int pager_end_transaction(Pager *pPager){ + PgHdr *pPg; + int rc = SQLITE_OK; + int rc2 = SQLITE_OK; + assert( !MEMDB ); + if( pPager->statestmtOpen && !pPager->exclusiveMode ){ + sqlite3OsClose(&pPager->stfd); + pPager->stmtOpen = 0; + } + if( pPager->journalOpen ){ + if( pPager->exclusiveMode + && (rc = sqlite3OsTruncate(pPager->jfd, 0))==SQLITE_OK ){; + sqlite3OsSeek(pPager->jfd, 0); + pPager->journalOff = 0; + pPager->journalStarted = 0; + }else{ + sqlite3OsClose(&pPager->jfd); + pPager->journalOpen = 0; + if( rc==SQLITE_OK ){ + rc = sqlite3OsDelete(pPager->zJournal); + } + } + sqliteFree( pPager->aInJournal ); + pPager->aInJournal = 0; + for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ + pPg->inJournal = 0; + pPg->dirty = 0; + pPg->needSync = 0; + pPg->alwaysRollback = 0; +#ifdef SQLITE_CHECK_PAGES + pPg->pageHash = pager_pagehash(pPg); +#endif + } + pPager->pDirty = 0; + pPager->dirtyCache = 0; + pPager->nRec = 0; + }else{ + assert( pPager->aInJournal==0 ); + assert( pPager->dirtyCache==0 || pPager->useJournal==0 ); + } + + if( !pPager->exclusiveMode ){ + rc2 = sqlite3OsUnlock(pPager->fd, SHARED_LOCK); + pPager->state = PAGER_SHARED; + }else if( pPager->state==PAGER_SYNCED ){ + pPager->state = PAGER_EXCLUSIVE; + } + pPager->origDbSize = 0; + pPager->setMaster = 0; + pPager->needSync = 0; + pPager->pFirstSynced = pPager->pFirst; + pPager->dbSize = -1; + + return (rc==SQLITE_OK?rc2:rc); +} + +/* +** Compute and return a checksum for the page of data. +** +** This is not a real checksum. It is really just the sum of the +** random initial value and the page number. We experimented with +** a checksum of the entire data, but that was found to be too slow. +** +** Note that the page number is stored at the beginning of data and +** the checksum is stored at the end. This is important. If journal +** corruption occurs due to a power failure, the most likely scenario +** is that one end or the other of the record will be changed. It is +** much less likely that the two ends of the journal record will be +** correct and the middle be corrupt. Thus, this "checksum" scheme, +** though fast and simple, catches the mostly likely kind of corruption. +** +** FIX ME: Consider adding every 200th (or so) byte of the data to the +** checksum. That way if a single page spans 3 or more disk sectors and +** only the middle sector is corrupt, we will still have a reasonable +** chance of failing the checksum and thus detecting the problem. +*/ +static u32 pager_cksum(Pager *pPager, const u8 *aData){ + u32 cksum = pPager->cksumInit; + int i = pPager->pageSize-200; + while( i>0 ){ + cksum += aData[i]; + i -= 200; + } + return cksum; +} + +/* Forward declaration */ +static void makeClean(PgHdr*); + +/* +** Read a single page from the journal file opened on file descriptor +** jfd. Playback this one page. +** +** If useCksum==0 it means this journal does not use checksums. Checksums +** are not used in statement journals because statement journals do not +** need to survive power failures. +*/ +static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){ + int rc; + PgHdr *pPg; /* An existing page in the cache */ + Pgno pgno; /* The page number of a page in journal */ + u32 cksum; /* Checksum used for sanity checking */ + u8 *aData = (u8 *)pPager->pTmpSpace; /* Temp storage for a page */ + + /* useCksum should be true for the main journal and false for + ** statement journals. Verify that this is always the case + */ + assert( jfd == (useCksum ? pPager->jfd : pPager->stfd) ); + assert( aData ); + + rc = read32bits(jfd, &pgno); + if( rc!=SQLITE_OK ) return rc; + rc = sqlite3OsRead(jfd, aData, pPager->pageSize); + if( rc!=SQLITE_OK ) return rc; + pPager->journalOff += pPager->pageSize + 4; + + /* Sanity checking on the page. This is more important that I originally + ** thought. If a power failure occurs while the journal is being written, + ** it could cause invalid data to be written into the journal. We need to + ** detect this invalid data (with high probability) and ignore it. + */ + if( pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){ + return SQLITE_DONE; + } + if( pgno>(unsigned)pPager->dbSize ){ + return SQLITE_OK; + } + if( useCksum ){ + rc = read32bits(jfd, &cksum); + if( rc ) return rc; + pPager->journalOff += 4; + if( pager_cksum(pPager, aData)!=cksum ){ + return SQLITE_DONE; + } + } + + assert( pPager->state==PAGER_RESERVED || pPager->state>=PAGER_EXCLUSIVE ); + + /* If the pager is in RESERVED state, then there must be a copy of this + ** page in the pager cache. In this case just update the pager cache, + ** not the database file. The page is left marked dirty in this case. + ** + ** An exception to the above rule: If the database is in no-sync mode + ** and a page is moved during an incremental vacuum then the page may + ** not be in the pager cache. Later: if a malloc() or IO error occurs + ** during a Movepage() call, then the page may not be in the cache + ** either. So the condition described in the above paragraph is not + ** assert()able. + ** + ** If in EXCLUSIVE state, then we update the pager cache if it exists + ** and the main file. The page is then marked not dirty. + ** + ** Ticket #1171: The statement journal might contain page content that is + ** different from the page content at the start of the transaction. + ** This occurs when a page is changed prior to the start of a statement + ** then changed again within the statement. When rolling back such a + ** statement we must not write to the original database unless we know + ** for certain that original page contents are synced into the main rollback + ** journal. Otherwise, a power loss might leave modified data in the + ** database file without an entry in the rollback journal that can + ** restore the database to its original form. Two conditions must be + ** met before writing to the database files. (1) the database must be + ** locked. (2) we know that the original page content is fully synced + ** in the main journal either because the page is not in cache or else + ** the page is marked as needSync==0. + */ + pPg = pager_lookup(pPager, pgno); + PAGERTRACE4("PLAYBACK %d page %d hash(%08x)\n", + PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, aData)); + if( pPager->state>=PAGER_EXCLUSIVE && (pPg==0 || pPg->needSync==0) ){ + rc = sqlite3OsSeek(pPager->fd, (pgno-1)*(i64)pPager->pageSize); + if( rc==SQLITE_OK ){ + rc = sqlite3OsWrite(pPager->fd, aData, pPager->pageSize); + } + if( pPg ){ + makeClean(pPg); + } + } + if( pPg ){ + /* No page should ever be explicitly rolled back that is in use, except + ** for page 1 which is held in use in order to keep the lock on the + ** database active. However such a page may be rolled back as a result + ** of an internal error resulting in an automatic call to + ** sqlite3PagerRollback(). + */ + void *pData; + /* assert( pPg->nRef==0 || pPg->pgno==1 ); */ + pData = PGHDR_TO_DATA(pPg); + memcpy(pData, aData, pPager->pageSize); + if( pPager->xReiniter ){ + pPager->xReiniter(pPg, pPager->pageSize); + } +#ifdef SQLITE_CHECK_PAGES + pPg->pageHash = pager_pagehash(pPg); +#endif + /* If this was page 1, then restore the value of Pager.dbFileVers. + ** Do this before any decoding. */ + if( pgno==1 ){ + memcpy(&pPager->dbFileVers, &((u8*)pData)[24],sizeof(pPager->dbFileVers)); + } + + /* Decode the page just read from disk */ + CODEC1(pPager, pData, pPg->pgno, 3); + } + return rc; +} + +/* +** Parameter zMaster is the name of a master journal file. A single journal +** file that referred to the master journal file has just been rolled back. +** This routine checks if it is possible to delete the master journal file, +** and does so if it is. +** +** The master journal file contains the names of all child journals. +** To tell if a master journal can be deleted, check to each of the +** children. If all children are either missing or do not refer to +** a different master journal, then this master journal can be deleted. +*/ +static int pager_delmaster(const char *zMaster){ + int rc; + int master_open = 0; + OsFile *master = 0; + char *zMasterJournal = 0; /* Contents of master journal file */ + i64 nMasterJournal; /* Size of master journal file */ + + /* Open the master journal file exclusively in case some other process + ** is running this routine also. Not that it makes too much difference. + */ + rc = sqlite3OsOpenReadOnly(zMaster, &master); + assert( rc!=SQLITE_OK || master ); + if( rc!=SQLITE_OK ) goto delmaster_out; + master_open = 1; + rc = sqlite3OsFileSize(master, &nMasterJournal); + if( rc!=SQLITE_OK ) goto delmaster_out; + + if( nMasterJournal>0 ){ + char *zJournal; + char *zMasterPtr = 0; + + /* Load the entire master journal file into space obtained from + ** sqliteMalloc() and pointed to by zMasterJournal. + */ + zMasterJournal = (char *)sqliteMalloc(nMasterJournal); + if( !zMasterJournal ){ + rc = SQLITE_NOMEM; + goto delmaster_out; + } + rc = sqlite3OsRead(master, zMasterJournal, nMasterJournal); + if( rc!=SQLITE_OK ) goto delmaster_out; + + zJournal = zMasterJournal; + while( (zJournal-zMasterJournal)state>=PAGER_EXCLUSIVE ){ + rc = sqlite3OsTruncate(pPager->fd, pPager->pageSize*(i64)nPage); + } + if( rc==SQLITE_OK ){ + pPager->dbSize = nPage; + pager_truncate_cache(pPager); + } + return rc; +} + +/* +** Set the sectorSize for the given pager. +** +** The sector size is the larger of the sector size reported +** by sqlite3OsSectorSize() and the pageSize. +*/ +static void setSectorSize(Pager *pPager){ + pPager->sectorSize = sqlite3OsSectorSize(pPager->fd); + if( pPager->sectorSizepageSize ){ + pPager->sectorSize = pPager->pageSize; + } +} + +/* +** Playback the journal and thus restore the database file to +** the state it was in before we started making changes. +** +** The journal file format is as follows: +** +** (1) 8 byte prefix. A copy of aJournalMagic[]. +** (2) 4 byte big-endian integer which is the number of valid page records +** in the journal. If this value is 0xffffffff, then compute the +** number of page records from the journal size. +** (3) 4 byte big-endian integer which is the initial value for the +** sanity checksum. +** (4) 4 byte integer which is the number of pages to truncate the +** database to during a rollback. +** (5) 4 byte integer which is the number of bytes in the master journal +** name. The value may be zero (indicate that there is no master +** journal.) +** (6) N bytes of the master journal name. The name will be nul-terminated +** and might be shorter than the value read from (5). If the first byte +** of the name is \000 then there is no master journal. The master +** journal name is stored in UTF-8. +** (7) Zero or more pages instances, each as follows: +** + 4 byte page number. +** + pPager->pageSize bytes of data. +** + 4 byte checksum +** +** When we speak of the journal header, we mean the first 6 items above. +** Each entry in the journal is an instance of the 7th item. +** +** Call the value from the second bullet "nRec". nRec is the number of +** valid page entries in the journal. In most cases, you can compute the +** value of nRec from the size of the journal file. But if a power +** failure occurred while the journal was being written, it could be the +** case that the size of the journal file had already been increased but +** the extra entries had not yet made it safely to disk. In such a case, +** the value of nRec computed from the file size would be too large. For +** that reason, we always use the nRec value in the header. +** +** If the nRec value is 0xffffffff it means that nRec should be computed +** from the file size. This value is used when the user selects the +** no-sync option for the journal. A power failure could lead to corruption +** in this case. But for things like temporary table (which will be +** deleted when the power is restored) we don't care. +** +** If the file opened as the journal file is not a well-formed +** journal file then all pages up to the first corrupted page are rolled +** back (or no pages if the journal header is corrupted). The journal file +** is then deleted and SQLITE_OK returned, just as if no corruption had +** been encountered. +** +** If an I/O or malloc() error occurs, the journal-file is not deleted +** and an error code is returned. +*/ +static int pager_playback(Pager *pPager, int isHot){ + i64 szJ; /* Size of the journal file in bytes */ + u32 nRec; /* Number of Records in the journal */ + int i; /* Loop counter */ + Pgno mxPg = 0; /* Size of the original file in pages */ + int rc; /* Result code of a subroutine */ + char *zMaster = 0; /* Name of master journal file if any */ + + /* Figure out how many records are in the journal. Abort early if + ** the journal is empty. + */ + assert( pPager->journalOpen ); + rc = sqlite3OsFileSize(pPager->jfd, &szJ); + if( rc!=SQLITE_OK || szJ==0 ){ + goto end_playback; + } + + /* Read the master journal name from the journal, if it is present. + ** If a master journal file name is specified, but the file is not + ** present on disk, then the journal is not hot and does not need to be + ** played back. + */ + rc = readMasterJournal(pPager->jfd, &zMaster); + assert( rc!=SQLITE_DONE ); + if( rc!=SQLITE_OK || (zMaster && !sqlite3OsFileExists(zMaster)) ){ + sqliteFree(zMaster); + zMaster = 0; + if( rc==SQLITE_DONE ) rc = SQLITE_OK; + goto end_playback; + } + sqlite3OsSeek(pPager->jfd, 0); + pPager->journalOff = 0; + + /* This loop terminates either when the readJournalHdr() call returns + ** SQLITE_DONE or an IO error occurs. */ + while( 1 ){ + + /* Read the next journal header from the journal file. If there are + ** not enough bytes left in the journal file for a complete header, or + ** it is corrupted, then a process must of failed while writing it. + ** This indicates nothing more needs to be rolled back. + */ + rc = readJournalHdr(pPager, szJ, &nRec, &mxPg); + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_DONE ){ + rc = SQLITE_OK; + } + goto end_playback; + } + + /* If nRec is 0xffffffff, then this journal was created by a process + ** working in no-sync mode. This means that the rest of the journal + ** file consists of pages, there are no more journal headers. Compute + ** the value of nRec based on this assumption. + */ + if( nRec==0xffffffff ){ + assert( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ); + nRec = (szJ - JOURNAL_HDR_SZ(pPager))/JOURNAL_PG_SZ(pPager); + } + + /* If nRec is 0 and this rollback is of a transaction created by this + ** process. In this case the rest of the journal file consists of + ** journalled copies of pages that need to be read back into the cache. + */ + if( nRec==0 && !isHot ){ + nRec = (szJ - pPager->journalOff) / JOURNAL_PG_SZ(pPager); + } + + /* If this is the first header read from the journal, truncate the + ** database file back to it's original size. + */ + if( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){ + rc = pager_truncate(pPager, mxPg); + if( rc!=SQLITE_OK ){ + goto end_playback; + } + } + + /* Copy original pages out of the journal and back into the database file. + */ + for(i=0; ijfd, 1); + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_DONE ){ + rc = SQLITE_OK; + pPager->journalOff = szJ; + break; + }else{ + goto end_playback; + } + } + } + } + /*NOTREACHED*/ + assert( 0 ); + +end_playback: + if( rc==SQLITE_OK ){ + rc = pager_end_transaction(pPager); + } + if( zMaster ){ + /* If there was a master journal and this routine will return success, + ** see if it is possible to delete the master journal. + */ + if( rc==SQLITE_OK ){ + rc = pager_delmaster(zMaster); + } + sqliteFree(zMaster); + } + + /* The Pager.sectorSize variable may have been updated while rolling + ** back a journal created by a process with a different sector size + ** value. Reset it to the correct value for this process. + */ + setSectorSize(pPager); + return rc; +} + +/* +** Playback the statement journal. +** +** This is similar to playing back the transaction journal but with +** a few extra twists. +** +** (1) The number of pages in the database file at the start of +** the statement is stored in pPager->stmtSize, not in the +** journal file itself. +** +** (2) In addition to playing back the statement journal, also +** playback all pages of the transaction journal beginning +** at offset pPager->stmtJSize. +*/ +static int pager_stmt_playback(Pager *pPager){ + i64 szJ; /* Size of the full journal */ + i64 hdrOff; + int nRec; /* Number of Records */ + int i; /* Loop counter */ + int rc; + + szJ = pPager->journalOff; +#ifndef NDEBUG + { + i64 os_szJ; + rc = sqlite3OsFileSize(pPager->jfd, &os_szJ); + if( rc!=SQLITE_OK ) return rc; + assert( szJ==os_szJ ); + } +#endif + + /* Set hdrOff to be the offset just after the end of the last journal + ** page written before the first journal-header for this statement + ** transaction was written, or the end of the file if no journal + ** header was written. + */ + hdrOff = pPager->stmtHdrOff; + assert( pPager->fullSync || !hdrOff ); + if( !hdrOff ){ + hdrOff = szJ; + } + + /* Truncate the database back to its original size. + */ + rc = pager_truncate(pPager, pPager->stmtSize); + assert( pPager->state>=PAGER_SHARED ); + + /* Figure out how many records are in the statement journal. + */ + assert( pPager->stmtInUse && pPager->journalOpen ); + sqlite3OsSeek(pPager->stfd, 0); + nRec = pPager->stmtNRec; + + /* Copy original pages out of the statement journal and back into the + ** database file. Note that the statement journal omits checksums from + ** each record since power-failure recovery is not important to statement + ** journals. + */ + for(i=nRec-1; i>=0; i--){ + rc = pager_playback_one_page(pPager, pPager->stfd, 0); + assert( rc!=SQLITE_DONE ); + if( rc!=SQLITE_OK ) goto end_stmt_playback; + } + + /* Now roll some pages back from the transaction journal. Pager.stmtJSize + ** was the size of the journal file when this statement was started, so + ** everything after that needs to be rolled back, either into the + ** database, the memory cache, or both. + ** + ** If it is not zero, then Pager.stmtHdrOff is the offset to the start + ** of the first journal header written during this statement transaction. + */ + rc = sqlite3OsSeek(pPager->jfd, pPager->stmtJSize); + if( rc!=SQLITE_OK ){ + goto end_stmt_playback; + } + pPager->journalOff = pPager->stmtJSize; + pPager->cksumInit = pPager->stmtCksum; + while( pPager->journalOff < hdrOff ){ + rc = pager_playback_one_page(pPager, pPager->jfd, 1); + assert( rc!=SQLITE_DONE ); + if( rc!=SQLITE_OK ) goto end_stmt_playback; + } + + while( pPager->journalOff < szJ ){ + u32 nJRec; /* Number of Journal Records */ + u32 dummy; + rc = readJournalHdr(pPager, szJ, &nJRec, &dummy); + if( rc!=SQLITE_OK ){ + assert( rc!=SQLITE_DONE ); + goto end_stmt_playback; + } + if( nJRec==0 ){ + nJRec = (szJ - pPager->journalOff) / (pPager->pageSize+8); + } + for(i=nJRec-1; i>=0 && pPager->journalOff < szJ; i--){ + rc = pager_playback_one_page(pPager, pPager->jfd, 1); + assert( rc!=SQLITE_DONE ); + if( rc!=SQLITE_OK ) goto end_stmt_playback; + } + } + + pPager->journalOff = szJ; + +end_stmt_playback: + if( rc==SQLITE_OK) { + pPager->journalOff = szJ; + /* pager_reload_cache(pPager); */ + } + return rc; +} + +/* +** Change the maximum number of in-memory pages that are allowed. +*/ +void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){ + if( mxPage>10 ){ + pPager->mxPage = mxPage; + }else{ + pPager->mxPage = 10; + } +} + +/* +** Adjust the robustness of the database to damage due to OS crashes +** or power failures by changing the number of syncs()s when writing +** the rollback journal. There are three levels: +** +** OFF sqlite3OsSync() is never called. This is the default +** for temporary and transient files. +** +** NORMAL The journal is synced once before writes begin on the +** database. This is normally adequate protection, but +** it is theoretically possible, though very unlikely, +** that an inopertune power failure could leave the journal +** in a state which would cause damage to the database +** when it is rolled back. +** +** FULL The journal is synced twice before writes begin on the +** database (with some additional information - the nRec field +** of the journal header - being written in between the two +** syncs). If we assume that writing a +** single disk sector is atomic, then this mode provides +** assurance that the journal will not be corrupted to the +** point of causing damage to the database during rollback. +** +** Numeric values associated with these states are OFF==1, NORMAL=2, +** and FULL=3. +*/ +#ifndef SQLITE_OMIT_PAGER_PRAGMAS +void sqlite3PagerSetSafetyLevel(Pager *pPager, int level, int full_fsync){ + pPager->noSync = level==1 || pPager->tempFile; + pPager->fullSync = level==3 && !pPager->tempFile; + pPager->full_fsync = full_fsync; + if( pPager->noSync ) pPager->needSync = 0; +} +#endif + +/* +** The following global variable is incremented whenever the library +** attempts to open a temporary file. This information is used for +** testing and analysis only. +*/ +#ifdef SQLITE_TEST +int sqlite3_opentemp_count = 0; +#endif + +/* +** Open a temporary file. +** +** Write the file descriptor into *fd. Return SQLITE_OK on success or some +** other error code if we fail. +** +** The OS will automatically delete the temporary file when it is +** closed. +*/ +static int sqlite3PagerOpentemp(OsFile **pFd){ + int cnt = 8; + int rc; + char zFile[SQLITE_TEMPNAME_SIZE]; + +#ifdef SQLITE_TEST + sqlite3_opentemp_count++; /* Used for testing and analysis only */ +#endif + do{ + cnt--; + sqlite3OsTempFileName(zFile); + rc = sqlite3OsOpenExclusive(zFile, pFd, 1); + assert( rc!=SQLITE_OK || *pFd ); + }while( cnt>0 && rc!=SQLITE_OK && rc!=SQLITE_NOMEM ); + return rc; +} + +/* +** Create a new page cache and put a pointer to the page cache in *ppPager. +** The file to be cached need not exist. The file is not locked until +** the first call to sqlite3PagerGet() and is only held open until the +** last page is released using sqlite3PagerUnref(). +** +** If zFilename is NULL then a randomly-named temporary file is created +** and used as the file to be cached. The file will be deleted +** automatically when it is closed. +** +** If zFilename is ":memory:" then all information is held in cache. +** It is never written to disk. This can be used to implement an +** in-memory database. +*/ +int sqlite3PagerOpen( + Pager **ppPager, /* Return the Pager structure here */ + const char *zFilename, /* Name of the database file to open */ + int nExtra, /* Extra bytes append to each in-memory page */ + int flags /* flags controlling this file */ +){ + Pager *pPager = 0; + char *zFullPathname = 0; + int nameLen; /* Compiler is wrong. This is always initialized before use */ + OsFile *fd = 0; + int rc = SQLITE_OK; + int i; + int tempFile = 0; + int memDb = 0; + int readOnly = 0; + int useJournal = (flags & PAGER_OMIT_JOURNAL)==0; + int noReadlock = (flags & PAGER_NO_READLOCK)!=0; + char zTemp[SQLITE_TEMPNAME_SIZE]; +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + /* A malloc() cannot fail in sqlite3ThreadData() as one or more calls to + ** malloc() must have already been made by this thread before it gets + ** to this point. This means the ThreadData must have been allocated already + ** so that ThreadData.nAlloc can be set. It would be nice to assert + ** that ThreadData.nAlloc is non-zero, but alas this breaks test cases + ** written to invoke the pager directly. + */ + ThreadData *pTsd = sqlite3ThreadData(); + assert( pTsd ); +#endif + + /* We used to test if malloc() had already failed before proceeding. + ** But the way this function is used in SQLite means that can never + ** happen. Furthermore, if the malloc-failed flag is already set, + ** either the call to sqliteStrDup() or sqliteMalloc() below will + ** fail shortly and SQLITE_NOMEM returned anyway. + */ + *ppPager = 0; + + /* Open the pager file and set zFullPathname to point at malloc()ed + ** memory containing the complete filename (i.e. including the directory). + */ + if( zFilename && zFilename[0] ){ +#ifndef SQLITE_OMIT_MEMORYDB + if( strcmp(zFilename,":memory:")==0 ){ + memDb = 1; + zFullPathname = sqliteStrDup(""); + }else +#endif + { + zFullPathname = sqlite3OsFullPathname(zFilename); + if( zFullPathname ){ + rc = sqlite3OsOpenReadWrite(zFullPathname, &fd, &readOnly); + assert( rc!=SQLITE_OK || fd ); + } + } + }else{ + rc = sqlite3PagerOpentemp(&fd); + sqlite3OsTempFileName(zTemp); + zFilename = zTemp; + zFullPathname = sqlite3OsFullPathname(zFilename); + if( rc==SQLITE_OK ){ + tempFile = 1; + } + } + + /* Allocate the Pager structure. As part of the same allocation, allocate + ** space for the full paths of the file, directory and journal + ** (Pager.zFilename, Pager.zDirectory and Pager.zJournal). + */ + if( zFullPathname ){ + nameLen = strlen(zFullPathname); + pPager = sqliteMalloc( sizeof(*pPager) + nameLen*3 + 30 ); + if( pPager && rc==SQLITE_OK ){ + pPager->pTmpSpace = (char *)sqliteMallocRaw(SQLITE_DEFAULT_PAGE_SIZE); + } + } + + + /* If an error occured in either of the blocks above, free the memory + ** pointed to by zFullPathname, free the Pager structure and close the + ** file. Since the pager is not allocated there is no need to set + ** any Pager.errMask variables. + */ + if( !pPager || !zFullPathname || !pPager->pTmpSpace || rc!=SQLITE_OK ){ + sqlite3OsClose(&fd); + sqliteFree(zFullPathname); + sqliteFree(pPager); + return ((rc==SQLITE_OK)?SQLITE_NOMEM:rc); + } + + PAGERTRACE3("OPEN %d %s\n", FILEHANDLEID(fd), zFullPathname); + IOTRACE(("OPEN %p %s\n", pPager, zFullPathname)) + pPager->zFilename = (char*)&pPager[1]; + pPager->zDirectory = &pPager->zFilename[nameLen+1]; + pPager->zJournal = &pPager->zDirectory[nameLen+1]; + memcpy(pPager->zFilename, zFullPathname, nameLen+1); + memcpy(pPager->zDirectory, zFullPathname, nameLen+1); + + for(i=nameLen; i>0 && pPager->zDirectory[i-1]!='/'; i--){} + if( i>0 ) pPager->zDirectory[i-1] = 0; + memcpy(pPager->zJournal, zFullPathname,nameLen); + sqliteFree(zFullPathname); + memcpy(&pPager->zJournal[nameLen], "-journal",sizeof("-journal")); + pPager->fd = fd; + /* pPager->journalOpen = 0; */ + pPager->useJournal = useJournal && !memDb; + pPager->noReadlock = noReadlock && readOnly; + /* pPager->stmtOpen = 0; */ + /* pPager->stmtInUse = 0; */ + /* pPager->nRef = 0; */ + pPager->dbSize = memDb-1; + pPager->pageSize = SQLITE_DEFAULT_PAGE_SIZE; + /* pPager->stmtSize = 0; */ + /* pPager->stmtJSize = 0; */ + /* pPager->nPage = 0; */ + pPager->mxPage = 100; + pPager->mxPgno = SQLITE_MAX_PAGE_COUNT; + assert( PAGER_UNLOCK==0 ); + /* pPager->state = PAGER_UNLOCK; */ + /* pPager->errMask = 0; */ + pPager->tempFile = tempFile; + assert( tempFile==PAGER_LOCKINGMODE_NORMAL + || tempFile==PAGER_LOCKINGMODE_EXCLUSIVE ); + assert( PAGER_LOCKINGMODE_EXCLUSIVE==1 ); + pPager->exclusiveMode = tempFile; + pPager->memDb = memDb; + pPager->readOnly = readOnly; + /* pPager->needSync = 0; */ + pPager->noSync = pPager->tempFile || !useJournal; + pPager->fullSync = (pPager->noSync?0:1); + /* pPager->pFirst = 0; */ + /* pPager->pFirstSynced = 0; */ + /* pPager->pLast = 0; */ + pPager->nExtra = FORCE_ALIGNMENT(nExtra); + assert(fd||memDb); + if( !memDb ){ + setSectorSize(pPager); + } + /* pPager->pBusyHandler = 0; */ + /* memset(pPager->aHash, 0, sizeof(pPager->aHash)); */ + *ppPager = pPager; +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + pPager->pNext = pTsd->pPager; + pTsd->pPager = pPager; +#endif + return SQLITE_OK; +} + +/* +** Set the busy handler function. +*/ +void sqlite3PagerSetBusyhandler(Pager *pPager, BusyHandler *pBusyHandler){ + pPager->pBusyHandler = pBusyHandler; +} + +/* +** Set the destructor for this pager. If not NULL, the destructor is called +** when the reference count on each page reaches zero. The destructor can +** be used to clean up information in the extra segment appended to each page. +** +** The destructor is not called as a result sqlite3PagerClose(). +** Destructors are only called by sqlite3PagerUnref(). +*/ +void sqlite3PagerSetDestructor(Pager *pPager, void (*xDesc)(DbPage*,int)){ + pPager->xDestructor = xDesc; +} + +/* +** Set the reinitializer for this pager. If not NULL, the reinitializer +** is called when the content of a page in cache is restored to its original +** value as a result of a rollback. The callback gives higher-level code +** an opportunity to restore the EXTRA section to agree with the restored +** page data. +*/ +void sqlite3PagerSetReiniter(Pager *pPager, void (*xReinit)(DbPage*,int)){ + pPager->xReiniter = xReinit; +} + +/* +** Set the page size. Return the new size. If the suggest new page +** size is inappropriate, then an alternative page size is selected +** and returned. +*/ +int sqlite3PagerSetPagesize(Pager *pPager, int pageSize){ + assert( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE ); + if( !pPager->memDb && pPager->nRef==0 ){ + pager_reset(pPager); + pPager->pageSize = pageSize; + pPager->pTmpSpace = sqlite3ReallocOrFree(pPager->pTmpSpace, pageSize); + } + return pPager->pageSize; +} + +/* +** Attempt to set the maximum database page count if mxPage is positive. +** Make no changes if mxPage is zero or negative. And never reduce the +** maximum page count below the current size of the database. +** +** Regardless of mxPage, return the current maximum page count. +*/ +int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){ + if( mxPage>0 ){ + pPager->mxPgno = mxPage; + } + sqlite3PagerPagecount(pPager); + return pPager->mxPgno; +} + +/* +** The following set of routines are used to disable the simulated +** I/O error mechanism. These routines are used to avoid simulated +** errors in places where we do not care about errors. +** +** Unless -DSQLITE_TEST=1 is used, these routines are all no-ops +** and generate no code. +*/ +#ifdef SQLITE_TEST +extern int sqlite3_io_error_pending; +extern int sqlite3_io_error_hit; +static int saved_cnt; +void disable_simulated_io_errors(void){ + saved_cnt = sqlite3_io_error_pending; + sqlite3_io_error_pending = -1; +} +void enable_simulated_io_errors(void){ + sqlite3_io_error_pending = saved_cnt; +} +#else +# define disable_simulated_io_errors() +# define enable_simulated_io_errors() +#endif + +/* +** Read the first N bytes from the beginning of the file into memory +** that pDest points to. +** +** No error checking is done. The rational for this is that this function +** may be called even if the file does not exist or contain a header. In +** these cases sqlite3OsRead() will return an error, to which the correct +** response is to zero the memory at pDest and continue. A real IO error +** will presumably recur and be picked up later (Todo: Think about this). +*/ +int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned char *pDest){ + int rc = SQLITE_OK; + memset(pDest, 0, N); + if( MEMDB==0 ){ + disable_simulated_io_errors(); + sqlite3OsSeek(pPager->fd, 0); + enable_simulated_io_errors(); + IOTRACE(("DBHDR %p 0 %d\n", pPager, N)) + rc = sqlite3OsRead(pPager->fd, pDest, N); + if( rc==SQLITE_IOERR_SHORT_READ ){ + rc = SQLITE_OK; + } + } + return rc; +} + +/* +** Return the total number of pages in the disk file associated with +** pPager. +** +** If the PENDING_BYTE lies on the page directly after the end of the +** file, then consider this page part of the file too. For example, if +** PENDING_BYTE is byte 4096 (the first byte of page 5) and the size of the +** file is 4096 bytes, 5 is returned instead of 4. +*/ +int sqlite3PagerPagecount(Pager *pPager){ + i64 n; + int rc; + assert( pPager!=0 ); + if( pPager->errCode ){ + return 0; + } + if( pPager->dbSize>=0 ){ + n = pPager->dbSize; + } else { + if( (rc = sqlite3OsFileSize(pPager->fd, &n))!=SQLITE_OK ){ + pager_error(pPager, rc); + return 0; + } + if( n>0 && npageSize ){ + n = 1; + }else{ + n /= pPager->pageSize; + } + if( pPager->state!=PAGER_UNLOCK ){ + pPager->dbSize = n; + } + } + if( n==(PENDING_BYTE/pPager->pageSize) ){ + n++; + } + if( n>pPager->mxPgno ){ + pPager->mxPgno = n; + } + return n; +} + + +#ifndef SQLITE_OMIT_MEMORYDB +/* +** Clear a PgHistory block +*/ +static void clearHistory(PgHistory *pHist){ + sqliteFree(pHist->pOrig); + sqliteFree(pHist->pStmt); + pHist->pOrig = 0; + pHist->pStmt = 0; +} +#else +#define clearHistory(x) +#endif + +/* +** Forward declaration +*/ +static int syncJournal(Pager*); + +/* +** Unlink pPg from it's hash chain. Also set the page number to 0 to indicate +** that the page is not part of any hash chain. This is required because the +** sqlite3PagerMovepage() routine can leave a page in the +** pNextFree/pPrevFree list that is not a part of any hash-chain. +*/ +static void unlinkHashChain(Pager *pPager, PgHdr *pPg){ + if( pPg->pgno==0 ){ + assert( pPg->pNextHash==0 && pPg->pPrevHash==0 ); + return; + } + if( pPg->pNextHash ){ + pPg->pNextHash->pPrevHash = pPg->pPrevHash; + } + if( pPg->pPrevHash ){ + assert( pPager->aHash[pPg->pgno & (pPager->nHash-1)]!=pPg ); + pPg->pPrevHash->pNextHash = pPg->pNextHash; + }else{ + int h = pPg->pgno & (pPager->nHash-1); + pPager->aHash[h] = pPg->pNextHash; + } + if( MEMDB ){ + clearHistory(PGHDR_TO_HIST(pPg, pPager)); + } + pPg->pgno = 0; + pPg->pNextHash = pPg->pPrevHash = 0; +} + +/* +** Unlink a page from the free list (the list of all pages where nRef==0) +** and from its hash collision chain. +*/ +static void unlinkPage(PgHdr *pPg){ + Pager *pPager = pPg->pPager; + + /* Keep the pFirstSynced pointer pointing at the first synchronized page */ + if( pPg==pPager->pFirstSynced ){ + PgHdr *p = pPg->pNextFree; + while( p && p->needSync ){ p = p->pNextFree; } + pPager->pFirstSynced = p; + } + + /* Unlink from the freelist */ + if( pPg->pPrevFree ){ + pPg->pPrevFree->pNextFree = pPg->pNextFree; + }else{ + assert( pPager->pFirst==pPg ); + pPager->pFirst = pPg->pNextFree; + } + if( pPg->pNextFree ){ + pPg->pNextFree->pPrevFree = pPg->pPrevFree; + }else{ + assert( pPager->pLast==pPg ); + pPager->pLast = pPg->pPrevFree; + } + pPg->pNextFree = pPg->pPrevFree = 0; + + /* Unlink from the pgno hash table */ + unlinkHashChain(pPager, pPg); +} + +/* +** This routine is used to truncate the cache when a database +** is truncated. Drop from the cache all pages whose pgno is +** larger than pPager->dbSize and is unreferenced. +** +** Referenced pages larger than pPager->dbSize are zeroed. +** +** Actually, at the point this routine is called, it would be +** an error to have a referenced page. But rather than delete +** that page and guarantee a subsequent segfault, it seems better +** to zero it and hope that we error out sanely. +*/ +static void pager_truncate_cache(Pager *pPager){ + PgHdr *pPg; + PgHdr **ppPg; + int dbSize = pPager->dbSize; + + ppPg = &pPager->pAll; + while( (pPg = *ppPg)!=0 ){ + if( pPg->pgno<=dbSize ){ + ppPg = &pPg->pNextAll; + }else if( pPg->nRef>0 ){ + memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize); + ppPg = &pPg->pNextAll; + }else{ + *ppPg = pPg->pNextAll; + IOTRACE(("PGFREE %p %d\n", pPager, pPg->pgno)); + PAGER_INCR(sqlite3_pager_pgfree_count); + unlinkPage(pPg); + makeClean(pPg); + sqliteFree(pPg); + pPager->nPage--; + } + } +} + +/* +** Try to obtain a lock on a file. Invoke the busy callback if the lock +** is currently not available. Repeat until the busy callback returns +** false or until the lock succeeds. +** +** Return SQLITE_OK on success and an error code if we cannot obtain +** the lock. +*/ +static int pager_wait_on_lock(Pager *pPager, int locktype){ + int rc; + + /* The OS lock values must be the same as the Pager lock values */ + assert( PAGER_SHARED==SHARED_LOCK ); + assert( PAGER_RESERVED==RESERVED_LOCK ); + assert( PAGER_EXCLUSIVE==EXCLUSIVE_LOCK ); + + /* If the file is currently unlocked then the size must be unknown */ + assert( pPager->state>=PAGER_SHARED || pPager->dbSize<0 || MEMDB ); + + if( pPager->state>=locktype ){ + rc = SQLITE_OK; + }else{ + do { + rc = sqlite3OsLock(pPager->fd, locktype); + }while( rc==SQLITE_BUSY && sqlite3InvokeBusyHandler(pPager->pBusyHandler) ); + if( rc==SQLITE_OK ){ + pPager->state = locktype; + IOTRACE(("LOCK %p %d\n", pPager, locktype)) + } + } + return rc; +} + +/* +** Truncate the file to the number of pages specified. +*/ +int sqlite3PagerTruncate(Pager *pPager, Pgno nPage){ + int rc; + assert( pPager->state>=PAGER_SHARED || MEMDB ); + sqlite3PagerPagecount(pPager); + if( pPager->errCode ){ + rc = pPager->errCode; + return rc; + } + if( nPage>=(unsigned)pPager->dbSize ){ + return SQLITE_OK; + } + if( MEMDB ){ + pPager->dbSize = nPage; + pager_truncate_cache(pPager); + return SQLITE_OK; + } + rc = syncJournal(pPager); + if( rc!=SQLITE_OK ){ + return rc; + } + + /* Get an exclusive lock on the database before truncating. */ + rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); + if( rc!=SQLITE_OK ){ + return rc; + } + + rc = pager_truncate(pPager, nPage); + return rc; +} + +/* +** Shutdown the page cache. Free all memory and close all files. +** +** If a transaction was in progress when this routine is called, that +** transaction is rolled back. All outstanding pages are invalidated +** and their memory is freed. Any attempt to use a page associated +** with this page cache after this function returns will likely +** result in a coredump. +** +** This function always succeeds. If a transaction is active an attempt +** is made to roll it back. If an error occurs during the rollback +** a hot journal may be left in the filesystem but no error is returned +** to the caller. +*/ +int sqlite3PagerClose(Pager *pPager){ +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + /* A malloc() cannot fail in sqlite3ThreadData() as one or more calls to + ** malloc() must have already been made by this thread before it gets + ** to this point. This means the ThreadData must have been allocated already + ** so that ThreadData.nAlloc can be set. + */ + ThreadData *pTsd = sqlite3ThreadData(); + assert( pPager ); + assert( pTsd && pTsd->nAlloc ); +#endif + + disable_simulated_io_errors(); + pPager->errCode = 0; + pPager->exclusiveMode = 0; + pager_reset(pPager); + pagerUnlockAndRollback(pPager); + enable_simulated_io_errors(); + PAGERTRACE2("CLOSE %d\n", PAGERID(pPager)); + IOTRACE(("CLOSE %p\n", pPager)) + assert( pPager->errCode || (pPager->journalOpen==0 && pPager->stmtOpen==0) ); + if( pPager->journalOpen ){ + sqlite3OsClose(&pPager->jfd); + } + sqliteFree(pPager->aInJournal); + if( pPager->stmtOpen ){ + sqlite3OsClose(&pPager->stfd); + } + sqlite3OsClose(&pPager->fd); + /* Temp files are automatically deleted by the OS + ** if( pPager->tempFile ){ + ** sqlite3OsDelete(pPager->zFilename); + ** } + */ + +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + /* Remove the pager from the linked list of pagers starting at + ** ThreadData.pPager if memory-management is enabled. + */ + if( pPager==pTsd->pPager ){ + pTsd->pPager = pPager->pNext; + }else{ + Pager *pTmp; + for(pTmp = pTsd->pPager; pTmp->pNext!=pPager; pTmp=pTmp->pNext){} + pTmp->pNext = pPager->pNext; + } +#endif + sqliteFree(pPager->aHash); + sqliteFree(pPager->pTmpSpace); + sqliteFree(pPager); + return SQLITE_OK; +} + +#if !defined(NDEBUG) || defined(SQLITE_TEST) +/* +** Return the page number for the given page data. +*/ +Pgno sqlite3PagerPagenumber(DbPage *p){ + return p->pgno; +} +#endif + +/* +** The page_ref() function increments the reference count for a page. +** If the page is currently on the freelist (the reference count is zero) then +** remove it from the freelist. +** +** For non-test systems, page_ref() is a macro that calls _page_ref() +** online of the reference count is zero. For test systems, page_ref() +** is a real function so that we can set breakpoints and trace it. +*/ +static void _page_ref(PgHdr *pPg){ + if( pPg->nRef==0 ){ + /* The page is currently on the freelist. Remove it. */ + if( pPg==pPg->pPager->pFirstSynced ){ + PgHdr *p = pPg->pNextFree; + while( p && p->needSync ){ p = p->pNextFree; } + pPg->pPager->pFirstSynced = p; + } + if( pPg->pPrevFree ){ + pPg->pPrevFree->pNextFree = pPg->pNextFree; + }else{ + pPg->pPager->pFirst = pPg->pNextFree; + } + if( pPg->pNextFree ){ + pPg->pNextFree->pPrevFree = pPg->pPrevFree; + }else{ + pPg->pPager->pLast = pPg->pPrevFree; + } + pPg->pPager->nRef++; + } + pPg->nRef++; + REFINFO(pPg); +} +#ifdef SQLITE_DEBUG + static void page_ref(PgHdr *pPg){ + if( pPg->nRef==0 ){ + _page_ref(pPg); + }else{ + pPg->nRef++; + REFINFO(pPg); + } + } +#else +# define page_ref(P) ((P)->nRef==0?_page_ref(P):(void)(P)->nRef++) +#endif + +/* +** Increment the reference count for a page. The input pointer is +** a reference to the page data. +*/ +int sqlite3PagerRef(DbPage *pPg){ + page_ref(pPg); + return SQLITE_OK; +} + +/* +** Sync the journal. In other words, make sure all the pages that have +** been written to the journal have actually reached the surface of the +** disk. It is not safe to modify the original database file until after +** the journal has been synced. If the original database is modified before +** the journal is synced and a power failure occurs, the unsynced journal +** data would be lost and we would be unable to completely rollback the +** database changes. Database corruption would occur. +** +** This routine also updates the nRec field in the header of the journal. +** (See comments on the pager_playback() routine for additional information.) +** If the sync mode is FULL, two syncs will occur. First the whole journal +** is synced, then the nRec field is updated, then a second sync occurs. +** +** For temporary databases, we do not care if we are able to rollback +** after a power failure, so sync occurs. +** +** This routine clears the needSync field of every page current held in +** memory. +*/ +static int syncJournal(Pager *pPager){ + PgHdr *pPg; + int rc = SQLITE_OK; + + /* Sync the journal before modifying the main database + ** (assuming there is a journal and it needs to be synced.) + */ + if( pPager->needSync ){ + if( !pPager->tempFile ){ + assert( pPager->journalOpen ); + /* assert( !pPager->noSync ); // noSync might be set if synchronous + ** was turned off after the transaction was started. Ticket #615 */ +#ifndef NDEBUG + { + /* Make sure the pPager->nRec counter we are keeping agrees + ** with the nRec computed from the size of the journal file. + */ + i64 jSz; + rc = sqlite3OsFileSize(pPager->jfd, &jSz); + if( rc!=0 ) return rc; + assert( pPager->journalOff==jSz ); + } +#endif + { + /* Write the nRec value into the journal file header. If in + ** full-synchronous mode, sync the journal first. This ensures that + ** all data has really hit the disk before nRec is updated to mark + ** it as a candidate for rollback. + */ + if( pPager->fullSync ){ + PAGERTRACE2("SYNC journal of %d\n", PAGERID(pPager)); + IOTRACE(("JSYNC %p\n", pPager)) + rc = sqlite3OsSync(pPager->jfd, 0); + if( rc!=0 ) return rc; + } + rc = sqlite3OsSeek(pPager->jfd, + pPager->journalHdr + sizeof(aJournalMagic)); + if( rc ) return rc; + IOTRACE(("JHDR %p %lld %d\n", pPager, + pPager->journalHdr + sizeof(aJournalMagic), 4)) + rc = write32bits(pPager->jfd, pPager->nRec); + if( rc ) return rc; + + rc = sqlite3OsSeek(pPager->jfd, pPager->journalOff); + if( rc ) return rc; + } + PAGERTRACE2("SYNC journal of %d\n", PAGERID(pPager)); + IOTRACE(("JSYNC %p\n", pPager)) + rc = sqlite3OsSync(pPager->jfd, pPager->full_fsync); + if( rc!=0 ) return rc; + pPager->journalStarted = 1; + } + pPager->needSync = 0; + + /* Erase the needSync flag from every page. + */ + for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ + pPg->needSync = 0; + } + pPager->pFirstSynced = pPager->pFirst; + } + +#ifndef NDEBUG + /* If the Pager.needSync flag is clear then the PgHdr.needSync + ** flag must also be clear for all pages. Verify that this + ** invariant is true. + */ + else{ + for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ + assert( pPg->needSync==0 ); + } + assert( pPager->pFirstSynced==pPager->pFirst ); + } +#endif + + return rc; +} + +/* +** Merge two lists of pages connected by pDirty and in pgno order. +** Do not both fixing the pPrevDirty pointers. +*/ +static PgHdr *merge_pagelist(PgHdr *pA, PgHdr *pB){ + PgHdr result, *pTail; + pTail = &result; + while( pA && pB ){ + if( pA->pgnopgno ){ + pTail->pDirty = pA; + pTail = pA; + pA = pA->pDirty; + }else{ + pTail->pDirty = pB; + pTail = pB; + pB = pB->pDirty; + } + } + if( pA ){ + pTail->pDirty = pA; + }else if( pB ){ + pTail->pDirty = pB; + }else{ + pTail->pDirty = 0; + } + return result.pDirty; +} + +/* +** Sort the list of pages in accending order by pgno. Pages are +** connected by pDirty pointers. The pPrevDirty pointers are +** corrupted by this sort. +*/ +#define N_SORT_BUCKET_ALLOC 25 +#define N_SORT_BUCKET 25 +#ifdef SQLITE_TEST + int sqlite3_pager_n_sort_bucket = 0; + #undef N_SORT_BUCKET + #define N_SORT_BUCKET \ + (sqlite3_pager_n_sort_bucket?sqlite3_pager_n_sort_bucket:N_SORT_BUCKET_ALLOC) +#endif +static PgHdr *sort_pagelist(PgHdr *pIn){ + PgHdr *a[N_SORT_BUCKET_ALLOC], *p; + int i; + memset(a, 0, sizeof(a)); + while( pIn ){ + p = pIn; + pIn = p->pDirty; + p->pDirty = 0; + for(i=0; ipPager; + + /* At this point there may be either a RESERVED or EXCLUSIVE lock on the + ** database file. If there is already an EXCLUSIVE lock, the following + ** calls to sqlite3OsLock() are no-ops. + ** + ** Moving the lock from RESERVED to EXCLUSIVE actually involves going + ** through an intermediate state PENDING. A PENDING lock prevents new + ** readers from attaching to the database but is unsufficient for us to + ** write. The idea of a PENDING lock is to prevent new readers from + ** coming in while we wait for existing readers to clear. + ** + ** While the pager is in the RESERVED state, the original database file + ** is unchanged and we can rollback without having to playback the + ** journal into the original database file. Once we transition to + ** EXCLUSIVE, it means the database file has been changed and any rollback + ** will require a journal playback. + */ + rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); + if( rc!=SQLITE_OK ){ + return rc; + } + + pList = sort_pagelist(pList); + while( pList ){ + assert( pList->dirty ); + rc = sqlite3OsSeek(pPager->fd, (pList->pgno-1)*(i64)pPager->pageSize); + if( rc ) return rc; + /* If there are dirty pages in the page cache with page numbers greater + ** than Pager.dbSize, this means sqlite3PagerTruncate() was called to + ** make the file smaller (presumably by auto-vacuum code). Do not write + ** any such pages to the file. + */ + if( pList->pgno<=pPager->dbSize ){ + char *pData = CODEC2(pPager, PGHDR_TO_DATA(pList), pList->pgno, 6); + PAGERTRACE4("STORE %d page %d hash(%08x)\n", + PAGERID(pPager), pList->pgno, pager_pagehash(pList)); + IOTRACE(("PGOUT %p %d\n", pPager, pList->pgno)); + rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize); + PAGER_INCR(sqlite3_pager_writedb_count); + PAGER_INCR(pPager->nWrite); + if( pList->pgno==1 ){ + memcpy(&pPager->dbFileVers, &pData[24], sizeof(pPager->dbFileVers)); + } + } +#ifndef NDEBUG + else{ + PAGERTRACE3("NOSTORE %d page %d\n", PAGERID(pPager), pList->pgno); + } +#endif + if( rc ) return rc; + pList->dirty = 0; +#ifdef SQLITE_CHECK_PAGES + pList->pageHash = pager_pagehash(pList); +#endif + pList = pList->pDirty; + } + return SQLITE_OK; +} + +/* +** Collect every dirty page into a dirty list and +** return a pointer to the head of that list. All pages are +** collected even if they are still in use. +*/ +static PgHdr *pager_get_all_dirty_pages(Pager *pPager){ + return pPager->pDirty; +} + +/* +** Return TRUE if there is a hot journal on the given pager. +** A hot journal is one that needs to be played back. +** +** If the current size of the database file is 0 but a journal file +** exists, that is probably an old journal left over from a prior +** database with the same name. Just delete the journal. +*/ +static int hasHotJournal(Pager *pPager){ + if( !pPager->useJournal ) return 0; + if( !sqlite3OsFileExists(pPager->zJournal) ){ + return 0; + } + if( sqlite3OsCheckReservedLock(pPager->fd) ){ + return 0; + } + if( sqlite3PagerPagecount(pPager)==0 ){ + sqlite3OsDelete(pPager->zJournal); + return 0; + }else{ + return 1; + } +} + +/* +** Try to find a page in the cache that can be recycled. +** +** This routine may return SQLITE_IOERR, SQLITE_FULL or SQLITE_OK. It +** does not set the pPager->errCode variable. +*/ +static int pager_recycle(Pager *pPager, int syncOk, PgHdr **ppPg){ + PgHdr *pPg; + *ppPg = 0; + + assert(!MEMDB); + + /* Find a page to recycle. Try to locate a page that does not + ** require us to do an fsync() on the journal. + */ + pPg = pPager->pFirstSynced; + + /* If we could not find a page that does not require an fsync() + ** on the journal file then fsync the journal file. This is a + ** very slow operation, so we work hard to avoid it. But sometimes + ** it can't be helped. + */ + if( pPg==0 && pPager->pFirst && syncOk && !MEMDB){ + int rc = syncJournal(pPager); + if( rc!=0 ){ + return rc; + } + if( pPager->fullSync ){ + /* If in full-sync mode, write a new journal header into the + ** journal file. This is done to avoid ever modifying a journal + ** header that is involved in the rollback of pages that have + ** already been written to the database (in case the header is + ** trashed when the nRec field is updated). + */ + pPager->nRec = 0; + assert( pPager->journalOff > 0 ); + assert( pPager->doNotSync==0 ); + rc = writeJournalHdr(pPager); + if( rc!=0 ){ + return rc; + } + } + pPg = pPager->pFirst; + } + if( pPg==0 ){ + return SQLITE_OK; + } + + assert( pPg->nRef==0 ); + + /* Write the page to the database file if it is dirty. + */ + if( pPg->dirty ){ + int rc; + assert( pPg->needSync==0 ); + makeClean(pPg); + pPg->dirty = 1; + pPg->pDirty = 0; + rc = pager_write_pagelist( pPg ); + if( rc!=SQLITE_OK ){ + return rc; + } + } + assert( pPg->dirty==0 ); + + /* If the page we are recycling is marked as alwaysRollback, then + ** set the global alwaysRollback flag, thus disabling the + ** sqlite3PagerDontRollback() optimization for the rest of this transaction. + ** It is necessary to do this because the page marked alwaysRollback + ** might be reloaded at a later time but at that point we won't remember + ** that is was marked alwaysRollback. This means that all pages must + ** be marked as alwaysRollback from here on out. + */ + if( pPg->alwaysRollback ){ + IOTRACE(("ALWAYS_ROLLBACK %p\n", pPager)) + pPager->alwaysRollback = 1; + } + + /* Unlink the old page from the free list and the hash table + */ + unlinkPage(pPg); + assert( pPg->pgno==0 ); + + *ppPg = pPg; + return SQLITE_OK; +} + +/* +** This function is called to free superfluous dynamically allocated memory +** held by the pager system. Memory in use by any SQLite pager allocated +** by the current thread may be sqliteFree()ed. +** +** nReq is the number of bytes of memory required. Once this much has +** been released, the function returns. A negative value for nReq means +** free as much memory as possible. The return value is the total number +** of bytes of memory released. +*/ +#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO) +int sqlite3PagerReleaseMemory(int nReq){ + const ThreadData *pTsdro = sqlite3ThreadDataReadOnly(); + int nReleased = 0; + int i; + + /* If the the global mutex is held, this subroutine becomes a + ** o-op; zero bytes of memory are freed. This is because + ** some of the code invoked by this function may also + ** try to obtain the mutex, resulting in a deadlock. + */ + if( sqlite3OsInMutex(0) ){ + return 0; + } + + /* Outermost loop runs for at most two iterations. First iteration we + ** try to find memory that can be released without calling fsync(). Second + ** iteration (which only runs if the first failed to free nReq bytes of + ** memory) is permitted to call fsync(). This is of course much more + ** expensive. + */ + for(i=0; i<=1; i++){ + + /* Loop through all the SQLite pagers opened by the current thread. */ + Pager *pPager = pTsdro->pPager; + for( ; pPager && (nReq<0 || nReleasedpNext){ + PgHdr *pPg; + int rc; + + if( MEMDB ){ + continue; + } + + /* For each pager, try to free as many pages as possible (without + ** calling fsync() if this is the first iteration of the outermost + ** loop). + */ + while( SQLITE_OK==(rc = pager_recycle(pPager, i, &pPg)) && pPg) { + /* We've found a page to free. At this point the page has been + ** removed from the page hash-table, free-list and synced-list + ** (pFirstSynced). It is still in the all pages (pAll) list. + ** Remove it from this list before freeing. + ** + ** Todo: Check the Pager.pStmt list to make sure this is Ok. It + ** probably is though. + */ + PgHdr *pTmp; + assert( pPg ); + if( pPg==pPager->pAll ){ + pPager->pAll = pPg->pNextAll; + }else{ + for( pTmp=pPager->pAll; pTmp->pNextAll!=pPg; pTmp=pTmp->pNextAll ){} + pTmp->pNextAll = pPg->pNextAll; + } + nReleased += sqliteAllocSize(pPg); + IOTRACE(("PGFREE %p %d\n", pPager, pPg->pgno)); + PAGER_INCR(sqlite3_pager_pgfree_count); + sqliteFree(pPg); + } + + if( rc!=SQLITE_OK ){ + /* An error occured whilst writing to the database file or + ** journal in pager_recycle(). The error is not returned to the + ** caller of this function. Instead, set the Pager.errCode variable. + ** The error will be returned to the user (or users, in the case + ** of a shared pager cache) of the pager for which the error occured. + */ + assert( (rc&0xff)==SQLITE_IOERR || rc==SQLITE_FULL ); + assert( pPager->state>=PAGER_RESERVED ); + pager_error(pPager, rc); + } + } + } + + return nReleased; +} +#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT && !SQLITE_OMIT_DISKIO */ + +/* +** Read the content of page pPg out of the database file. +*/ +static int readDbPage(Pager *pPager, PgHdr *pPg, Pgno pgno){ + int rc; + assert( MEMDB==0 ); + rc = sqlite3OsSeek(pPager->fd, (pgno-1)*(i64)pPager->pageSize); + if( rc==SQLITE_OK ){ + rc = sqlite3OsRead(pPager->fd, PGHDR_TO_DATA(pPg), + pPager->pageSize); + } + PAGER_INCR(sqlite3_pager_readdb_count); + PAGER_INCR(pPager->nRead); + IOTRACE(("PGIN %p %d\n", pPager, pgno)); + if( pgno==1 ){ + memcpy(&pPager->dbFileVers, &((u8*)PGHDR_TO_DATA(pPg))[24], + sizeof(pPager->dbFileVers)); + } + CODEC1(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3); + PAGERTRACE4("FETCH %d page %d hash(%08x)\n", + PAGERID(pPager), pPg->pgno, pager_pagehash(pPg)); + return rc; +} + + +/* +** This function is called to obtain the shared lock required before +** data may be read from the pager cache. If the shared lock has already +** been obtained, this function is a no-op. +** +** Immediately after obtaining the shared lock (if required), this function +** checks for a hot-journal file. If one is found, an emergency rollback +** is performed immediately. +*/ +static int pagerSharedLock(Pager *pPager){ + int rc = SQLITE_OK; + + if( pPager->state==PAGER_UNLOCK ){ + if( !MEMDB ){ + assert( pPager->nRef==0 ); + if( !pPager->noReadlock ){ + rc = pager_wait_on_lock(pPager, SHARED_LOCK); + if( rc!=SQLITE_OK ){ + return pager_error(pPager, rc); + } + assert( pPager->state>=SHARED_LOCK ); + } + + /* If a journal file exists, and there is no RESERVED lock on the + ** database file, then it either needs to be played back or deleted. + */ + if( hasHotJournal(pPager) ){ + /* Get an EXCLUSIVE lock on the database file. At this point it is + ** important that a RESERVED lock is not obtained on the way to the + ** EXCLUSIVE lock. If it were, another process might open the + ** database file, detect the RESERVED lock, and conclude that the + ** database is safe to read while this process is still rolling it + ** back. + ** + ** Because the intermediate RESERVED lock is not requested, the + ** second process will get to this point in the code and fail to + ** obtain it's own EXCLUSIVE lock on the database file. + */ + rc = sqlite3OsLock(pPager->fd, EXCLUSIVE_LOCK); + if( rc!=SQLITE_OK ){ + pager_unlock(pPager); + return pager_error(pPager, rc); + } + pPager->state = PAGER_EXCLUSIVE; + + /* Open the journal for reading only. Return SQLITE_BUSY if + ** we are unable to open the journal file. + ** + ** The journal file does not need to be locked itself. The + ** journal file is never open unless the main database file holds + ** a write lock, so there is never any chance of two or more + ** processes opening the journal at the same time. + ** + ** Open the journal for read/write access. This is because in + ** exclusive-access mode the file descriptor will be kept open and + ** possibly used for a transaction later on. On some systems, the + ** OsTruncate() call used in exclusive-access mode also requires + ** a read/write file handle. + */ + rc = SQLITE_BUSY; + if( sqlite3OsFileExists(pPager->zJournal) ){ + int ro; + assert( !pPager->tempFile ); + rc = sqlite3OsOpenReadWrite(pPager->zJournal, &pPager->jfd, &ro); + assert( rc!=SQLITE_OK || pPager->jfd ); + if( ro ){ + rc = SQLITE_BUSY; + sqlite3OsClose(&pPager->jfd); + } + } + if( rc!=SQLITE_OK ){ + pager_unlock(pPager); + return SQLITE_BUSY; + } + pPager->journalOpen = 1; + pPager->journalStarted = 0; + pPager->journalOff = 0; + pPager->setMaster = 0; + pPager->journalHdr = 0; + + /* Playback and delete the journal. Drop the database write + ** lock and reacquire the read lock. + */ + rc = pager_playback(pPager, 1); + if( rc!=SQLITE_OK ){ + return pager_error(pPager, rc); + } + assert(pPager->state==PAGER_SHARED || + (pPager->exclusiveMode && pPager->state>PAGER_SHARED) + ); + } + + if( pPager->pAll ){ + /* The shared-lock has just been acquired on the database file + ** and there are already pages in the cache (from a previous + ** read or write transaction). Check to see if the database + ** has been modified. If the database has changed, flush the + ** cache. + ** + ** Database changes is detected by looking at 15 bytes beginning + ** at offset 24 into the file. The first 4 of these 16 bytes are + ** a 32-bit counter that is incremented with each change. The + ** other bytes change randomly with each file change when + ** a codec is in use. + ** + ** There is a vanishingly small chance that a change will not be + ** detected. The chance of an undetected change is so small that + ** it can be neglected. + */ + char dbFileVers[sizeof(pPager->dbFileVers)]; + sqlite3PagerPagecount(pPager); + + if( pPager->errCode ){ + return pPager->errCode; + } + + if( pPager->dbSize>0 ){ + IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers))); + rc = sqlite3OsSeek(pPager->fd, 24); + if( rc!=SQLITE_OK ){ + return rc; + } + rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers)); + if( rc!=SQLITE_OK ){ + return rc; + } + }else{ + memset(dbFileVers, 0, sizeof(dbFileVers)); + } + + if( memcmp(pPager->dbFileVers, dbFileVers, sizeof(dbFileVers))!=0 ){ + pager_reset(pPager); + } + } + } + assert( pPager->exclusiveMode || pPager->state<=PAGER_SHARED ); + if( pPager->state==PAGER_UNLOCK ){ + pPager->state = PAGER_SHARED; + } + } + + return rc; +} + +/* +** Allocate a PgHdr object. Either create a new one or reuse +** an existing one that is not otherwise in use. +** +** A new PgHdr structure is created if any of the following are +** true: +** +** (1) We have not exceeded our maximum allocated cache size +** as set by the "PRAGMA cache_size" command. +** +** (2) There are no unused PgHdr objects available at this time. +** +** (3) This is an in-memory database. +** +** (4) There are no PgHdr objects that do not require a journal +** file sync and a sync of the journal file is currently +** prohibited. +** +** Otherwise, reuse an existing PgHdr. In other words, reuse an +** existing PgHdr if all of the following are true: +** +** (1) We have reached or exceeded the maximum cache size +** allowed by "PRAGMA cache_size". +** +** (2) There is a PgHdr available with PgHdr->nRef==0 +** +** (3) We are not in an in-memory database +** +** (4) Either there is an available PgHdr that does not need +** to be synced to disk or else disk syncing is currently +** allowed. +*/ +static int pagerAllocatePage(Pager *pPager, PgHdr **ppPg){ + int rc = SQLITE_OK; + PgHdr *pPg; + + /* Create a new PgHdr if any of the four conditions defined + ** above is met: */ + if( pPager->nPagemxPage + || pPager->pFirst==0 + || MEMDB + || (pPager->pFirstSynced==0 && pPager->doNotSync) + ){ + if( pPager->nPage>=pPager->nHash ){ + pager_resize_hash_table(pPager, + pPager->nHash<256 ? 256 : pPager->nHash*2); + if( pPager->nHash==0 ){ + rc = SQLITE_NOMEM; + goto pager_allocate_out; + } + } + pPg = sqliteMallocRaw( sizeof(*pPg) + pPager->pageSize + + sizeof(u32) + pPager->nExtra + + MEMDB*sizeof(PgHistory) ); + if( pPg==0 ){ + rc = SQLITE_NOMEM; + goto pager_allocate_out; + } + memset(pPg, 0, sizeof(*pPg)); + if( MEMDB ){ + memset(PGHDR_TO_HIST(pPg, pPager), 0, sizeof(PgHistory)); + } + pPg->pPager = pPager; + pPg->pNextAll = pPager->pAll; + pPager->pAll = pPg; + pPager->nPage++; + }else{ + /* Recycle an existing page with a zero ref-count. */ + rc = pager_recycle(pPager, 1, &pPg); + if( rc==SQLITE_BUSY ){ + rc = SQLITE_IOERR_BLOCKED; + } + if( rc!=SQLITE_OK ){ + goto pager_allocate_out; + } + assert( pPager->state>=SHARED_LOCK ); + assert(pPg); + } + *ppPg = pPg; + +pager_allocate_out: + return rc; +} + +/* +** Make sure we have the content for a page. If the page was +** previously acquired with noContent==1, then the content was +** just initialized to zeros instead of being read from disk. +** But now we need the real data off of disk. So make sure we +** have it. Read it in if we do not have it already. +*/ +static int pager_get_content(PgHdr *pPg){ + if( pPg->needRead ){ + int rc = readDbPage(pPg->pPager, pPg, pPg->pgno); + if( rc==SQLITE_OK ){ + pPg->needRead = 0; + }else{ + return rc; + } + } + return SQLITE_OK; +} + +/* +** Acquire a page. +** +** A read lock on the disk file is obtained when the first page is acquired. +** This read lock is dropped when the last page is released. +** +** This routine works for any page number greater than 0. If the database +** file is smaller than the requested page, then no actual disk +** read occurs and the memory image of the page is initialized to +** all zeros. The extra data appended to a page is always initialized +** to zeros the first time a page is loaded into memory. +** +** The acquisition might fail for several reasons. In all cases, +** an appropriate error code is returned and *ppPage is set to NULL. +** +** See also sqlite3PagerLookup(). Both this routine and Lookup() attempt +** to find a page in the in-memory cache first. If the page is not already +** in memory, this routine goes to disk to read it in whereas Lookup() +** just returns 0. This routine acquires a read-lock the first time it +** has to go to disk, and could also playback an old journal if necessary. +** Since Lookup() never goes to disk, it never has to deal with locks +** or journal files. +** +** If noContent is false, the page contents are actually read from disk. +** If noContent is true, it means that we do not care about the contents +** of the page at this time, so do not do a disk read. Just fill in the +** page content with zeros. But mark the fact that we have not read the +** content by setting the PgHdr.needRead flag. Later on, if +** sqlite3PagerWrite() is called on this page or if this routine is +** called again with noContent==0, that means that the content is needed +** and the disk read should occur at that point. +*/ +int sqlite3PagerAcquire( + Pager *pPager, /* The pager open on the database file */ + Pgno pgno, /* Page number to fetch */ + DbPage **ppPage, /* Write a pointer to the page here */ + int noContent /* Do not bother reading content from disk if true */ +){ + PgHdr *pPg; + int rc; + + assert( pPager->state==PAGER_UNLOCK || pPager->nRef>0 || pgno==1 ); + + /* The maximum page number is 2^31. Return SQLITE_CORRUPT if a page + ** number greater than this, or zero, is requested. + */ + if( pgno>PAGER_MAX_PGNO || pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){ + return SQLITE_CORRUPT_BKPT; + } + + /* Make sure we have not hit any critical errors. + */ + assert( pPager!=0 ); + *ppPage = 0; + if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ + return pPager->errCode; + } + + /* If this is the first page accessed, then get a SHARED lock + ** on the database file. pagerSharedLock() is a no-op if + ** a database lock is already held. + */ + rc = pagerSharedLock(pPager); + if( rc!=SQLITE_OK ){ + return rc; + } + assert( pPager->state!=PAGER_UNLOCK ); + + pPg = pager_lookup(pPager, pgno); + if( pPg==0 ){ + /* The requested page is not in the page cache. */ + int nMax; + int h; + PAGER_INCR(pPager->nMiss); + rc = pagerAllocatePage(pPager, &pPg); + if( rc!=SQLITE_OK ){ + return rc; + } + + pPg->pgno = pgno; + assert( !MEMDB || pgno>pPager->stmtSize ); + if( pPager->aInJournal && (int)pgno<=pPager->origDbSize ){ + sqlite3CheckMemory(pPager->aInJournal, pgno/8); + assert( pPager->journalOpen ); + pPg->inJournal = (pPager->aInJournal[pgno/8] & (1<<(pgno&7)))!=0; + pPg->needSync = 0; + }else{ + pPg->inJournal = 0; + pPg->needSync = 0; + } + + makeClean(pPg); + pPg->nRef = 1; + REFINFO(pPg); + + pPager->nRef++; + if( pPager->nExtra>0 ){ + memset(PGHDR_TO_EXTRA(pPg, pPager), 0, pPager->nExtra); + } + nMax = sqlite3PagerPagecount(pPager); + if( pPager->errCode ){ + sqlite3PagerUnref(pPg); + rc = pPager->errCode; + return rc; + } + + /* Populate the page with data, either by reading from the database + ** file, or by setting the entire page to zero. + */ + if( nMax<(int)pgno || MEMDB || (noContent && !pPager->alwaysRollback) ){ + if( pgno>pPager->mxPgno ){ + sqlite3PagerUnref(pPg); + return SQLITE_FULL; + } + memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize); + pPg->needRead = noContent && !pPager->alwaysRollback; + IOTRACE(("ZERO %p %d\n", pPager, pgno)); + }else{ + rc = readDbPage(pPager, pPg, pgno); + if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){ + pPg->pgno = 0; + sqlite3PagerUnref(pPg); + return rc; + } + pPg->needRead = 0; + } + + /* Link the page into the page hash table */ + h = pgno & (pPager->nHash-1); + assert( pgno!=0 ); + pPg->pNextHash = pPager->aHash[h]; + pPager->aHash[h] = pPg; + if( pPg->pNextHash ){ + assert( pPg->pNextHash->pPrevHash==0 ); + pPg->pNextHash->pPrevHash = pPg; + } + +#ifdef SQLITE_CHECK_PAGES + pPg->pageHash = pager_pagehash(pPg); +#endif + }else{ + /* The requested page is in the page cache. */ + assert(pPager->nRef>0 || pgno==1); + PAGER_INCR(pPager->nHit); + if( !noContent ){ + rc = pager_get_content(pPg); + if( rc ){ + return rc; + } + } + page_ref(pPg); + } + *ppPage = pPg; + return SQLITE_OK; +} + +/* +** Acquire a page if it is already in the in-memory cache. Do +** not read the page from disk. Return a pointer to the page, +** or 0 if the page is not in cache. +** +** See also sqlite3PagerGet(). The difference between this routine +** and sqlite3PagerGet() is that _get() will go to the disk and read +** in the page if the page is not already in cache. This routine +** returns NULL if the page is not in cache or if a disk I/O error +** has ever happened. +*/ +DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno){ + PgHdr *pPg; + + assert( pPager!=0 ); + assert( pgno!=0 ); + + if( pPager->state==PAGER_UNLOCK ){ + assert( !pPager->pAll || pPager->exclusiveMode ); + return 0; + } + if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ + return 0; + } + pPg = pager_lookup(pPager, pgno); + if( pPg==0 ) return 0; + page_ref(pPg); + return pPg; +} + +/* +** Release a page. +** +** If the number of references to the page drop to zero, then the +** page is added to the LRU list. When all references to all pages +** are released, a rollback occurs and the lock on the database is +** removed. +*/ +int sqlite3PagerUnref(DbPage *pPg){ + + /* Decrement the reference count for this page + */ + assert( pPg->nRef>0 ); + pPg->nRef--; + REFINFO(pPg); + + CHECK_PAGE(pPg); + + /* When the number of references to a page reach 0, call the + ** destructor and add the page to the freelist. + */ + if( pPg->nRef==0 ){ + Pager *pPager; + pPager = pPg->pPager; + pPg->pNextFree = 0; + pPg->pPrevFree = pPager->pLast; + pPager->pLast = pPg; + if( pPg->pPrevFree ){ + pPg->pPrevFree->pNextFree = pPg; + }else{ + pPager->pFirst = pPg; + } + if( pPg->needSync==0 && pPager->pFirstSynced==0 ){ + pPager->pFirstSynced = pPg; + } + if( pPager->xDestructor ){ + pPager->xDestructor(pPg, pPager->pageSize); + } + + /* When all pages reach the freelist, drop the read lock from + ** the database file. + */ + pPager->nRef--; + assert( pPager->nRef>=0 ); + if( pPager->nRef==0 && (!pPager->exclusiveMode || pPager->journalOff>0) ){ + pagerUnlockAndRollback(pPager); + } + } + return SQLITE_OK; +} + +/* +** Create a journal file for pPager. There should already be a RESERVED +** or EXCLUSIVE lock on the database file when this routine is called. +** +** Return SQLITE_OK if everything. Return an error code and release the +** write lock if anything goes wrong. +*/ +static int pager_open_journal(Pager *pPager){ + int rc; + assert( !MEMDB ); + assert( pPager->state>=PAGER_RESERVED ); + assert( pPager->journalOpen==0 ); + assert( pPager->useJournal ); + assert( pPager->aInJournal==0 ); + sqlite3PagerPagecount(pPager); + pPager->aInJournal = sqliteMalloc( pPager->dbSize/8 + 1 ); + if( pPager->aInJournal==0 ){ + rc = SQLITE_NOMEM; + goto failed_to_open_journal; + } + rc = sqlite3OsOpenExclusive(pPager->zJournal, &pPager->jfd, + pPager->tempFile); + assert( rc!=SQLITE_OK || pPager->jfd ); + pPager->journalOff = 0; + pPager->setMaster = 0; + pPager->journalHdr = 0; + if( rc!=SQLITE_OK ){ + if( rc==SQLITE_NOMEM ){ + sqlite3OsDelete(pPager->zJournal); + } + goto failed_to_open_journal; + } + sqlite3OsSetFullSync(pPager->jfd, pPager->full_fsync); + sqlite3OsSetFullSync(pPager->fd, pPager->full_fsync); + sqlite3OsOpenDirectory(pPager->jfd, pPager->zDirectory); + pPager->journalOpen = 1; + pPager->journalStarted = 0; + pPager->needSync = 0; + pPager->alwaysRollback = 0; + pPager->nRec = 0; + if( pPager->errCode ){ + rc = pPager->errCode; + goto failed_to_open_journal; + } + pPager->origDbSize = pPager->dbSize; + + rc = writeJournalHdr(pPager); + + if( pPager->stmtAutoopen && rc==SQLITE_OK ){ + rc = sqlite3PagerStmtBegin(pPager); + } + if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){ + rc = pager_end_transaction(pPager); + if( rc==SQLITE_OK ){ + rc = SQLITE_FULL; + } + } + return rc; + +failed_to_open_journal: + sqliteFree(pPager->aInJournal); + pPager->aInJournal = 0; + return rc; +} + +/* +** Acquire a write-lock on the database. The lock is removed when +** the any of the following happen: +** +** * sqlite3PagerCommitPhaseTwo() is called. +** * sqlite3PagerRollback() is called. +** * sqlite3PagerClose() is called. +** * sqlite3PagerUnref() is called to on every outstanding page. +** +** The first parameter to this routine is a pointer to any open page of the +** database file. Nothing changes about the page - it is used merely to +** acquire a pointer to the Pager structure and as proof that there is +** already a read-lock on the database. +** +** The second parameter indicates how much space in bytes to reserve for a +** master journal file-name at the start of the journal when it is created. +** +** A journal file is opened if this is not a temporary file. For temporary +** files, the opening of the journal file is deferred until there is an +** actual need to write to the journal. +** +** If the database is already reserved for writing, this routine is a no-op. +** +** If exFlag is true, go ahead and get an EXCLUSIVE lock on the file +** immediately instead of waiting until we try to flush the cache. The +** exFlag is ignored if a transaction is already active. +*/ +int sqlite3PagerBegin(DbPage *pPg, int exFlag){ + Pager *pPager = pPg->pPager; + int rc = SQLITE_OK; + assert( pPg->nRef>0 ); + assert( pPager->state!=PAGER_UNLOCK ); + if( pPager->state==PAGER_SHARED ){ + assert( pPager->aInJournal==0 ); + if( MEMDB ){ + pPager->state = PAGER_EXCLUSIVE; + pPager->origDbSize = pPager->dbSize; + }else{ + rc = sqlite3OsLock(pPager->fd, RESERVED_LOCK); + if( rc==SQLITE_OK ){ + pPager->state = PAGER_RESERVED; + if( exFlag ){ + rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); + } + } + if( rc!=SQLITE_OK ){ + return rc; + } + pPager->dirtyCache = 0; + PAGERTRACE2("TRANSACTION %d\n", PAGERID(pPager)); + if( pPager->useJournal && !pPager->tempFile ){ + rc = pager_open_journal(pPager); + } + } + }else if( pPager->journalOpen && pPager->journalOff==0 ){ + /* This happens when the pager was in exclusive-access mode last + ** time a (read or write) transaction was successfully concluded + ** by this connection. Instead of deleting the journal file it was + ** kept open and truncated to 0 bytes. + */ + assert( pPager->nRec==0 ); + assert( pPager->origDbSize==0 ); + assert( pPager->aInJournal==0 ); + sqlite3PagerPagecount(pPager); + pPager->aInJournal = sqliteMalloc( pPager->dbSize/8 + 1 ); + if( !pPager->aInJournal ){ + rc = SQLITE_NOMEM; + }else{ + pPager->origDbSize = pPager->dbSize; + rc = writeJournalHdr(pPager); + } + } + assert( !pPager->journalOpen || pPager->journalOff>0 || rc!=SQLITE_OK ); + return rc; +} + +/* +** Make a page dirty. Set its dirty flag and add it to the dirty +** page list. +*/ +static void makeDirty(PgHdr *pPg){ + if( pPg->dirty==0 ){ + Pager *pPager = pPg->pPager; + pPg->dirty = 1; + pPg->pDirty = pPager->pDirty; + if( pPager->pDirty ){ + pPager->pDirty->pPrevDirty = pPg; + } + pPg->pPrevDirty = 0; + pPager->pDirty = pPg; + } +} + +/* +** Make a page clean. Clear its dirty bit and remove it from the +** dirty page list. +*/ +static void makeClean(PgHdr *pPg){ + if( pPg->dirty ){ + pPg->dirty = 0; + if( pPg->pDirty ){ + pPg->pDirty->pPrevDirty = pPg->pPrevDirty; + } + if( pPg->pPrevDirty ){ + pPg->pPrevDirty->pDirty = pPg->pDirty; + }else{ + pPg->pPager->pDirty = pPg->pDirty; + } + } +} + + +/* +** Mark a data page as writeable. The page is written into the journal +** if it is not there already. This routine must be called before making +** changes to a page. +** +** The first time this routine is called, the pager creates a new +** journal and acquires a RESERVED lock on the database. If the RESERVED +** lock could not be acquired, this routine returns SQLITE_BUSY. The +** calling routine must check for that return value and be careful not to +** change any page data until this routine returns SQLITE_OK. +** +** If the journal file could not be written because the disk is full, +** then this routine returns SQLITE_FULL and does an immediate rollback. +** All subsequent write attempts also return SQLITE_FULL until there +** is a call to sqlite3PagerCommit() or sqlite3PagerRollback() to +** reset. +*/ +static int pager_write(PgHdr *pPg){ + void *pData = PGHDR_TO_DATA(pPg); + Pager *pPager = pPg->pPager; + int rc = SQLITE_OK; + + /* Check for errors + */ + if( pPager->errCode ){ + return pPager->errCode; + } + if( pPager->readOnly ){ + return SQLITE_PERM; + } + + assert( !pPager->setMaster ); + + CHECK_PAGE(pPg); + + /* If this page was previously acquired with noContent==1, that means + ** we didn't really read in the content of the page. This can happen + ** (for example) when the page is being moved to the freelist. But + ** now we are (perhaps) moving the page off of the freelist for + ** reuse and we need to know its original content so that content + ** can be stored in the rollback journal. So do the read at this + ** time. + */ + rc = pager_get_content(pPg); + if( rc ){ + return rc; + } + + /* Mark the page as dirty. If the page has already been written + ** to the journal then we can return right away. + */ + makeDirty(pPg); + if( pPg->inJournal && (pageInStatement(pPg) || pPager->stmtInUse==0) ){ + pPager->dirtyCache = 1; + }else{ + + /* If we get this far, it means that the page needs to be + ** written to the transaction journal or the ckeckpoint journal + ** or both. + ** + ** First check to see that the transaction journal exists and + ** create it if it does not. + */ + assert( pPager->state!=PAGER_UNLOCK ); + rc = sqlite3PagerBegin(pPg, 0); + if( rc!=SQLITE_OK ){ + return rc; + } + assert( pPager->state>=PAGER_RESERVED ); + if( !pPager->journalOpen && pPager->useJournal ){ + rc = pager_open_journal(pPager); + if( rc!=SQLITE_OK ) return rc; + } + assert( pPager->journalOpen || !pPager->useJournal ); + pPager->dirtyCache = 1; + + /* The transaction journal now exists and we have a RESERVED or an + ** EXCLUSIVE lock on the main database file. Write the current page to + ** the transaction journal if it is not there already. + */ + if( !pPg->inJournal && (pPager->useJournal || MEMDB) ){ + if( (int)pPg->pgno <= pPager->origDbSize ){ + int szPg; + if( MEMDB ){ + PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); + PAGERTRACE3("JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); + assert( pHist->pOrig==0 ); + pHist->pOrig = sqliteMallocRaw( pPager->pageSize ); + if( pHist->pOrig ){ + memcpy(pHist->pOrig, PGHDR_TO_DATA(pPg), pPager->pageSize); + } + }else{ + u32 cksum, saved; + char *pData2, *pEnd; + /* We should never write to the journal file the page that + ** contains the database locks. The following assert verifies + ** that we do not. */ + assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) ); + pData2 = CODEC2(pPager, pData, pPg->pgno, 7); + cksum = pager_cksum(pPager, (u8*)pData2); + pEnd = pData2 + pPager->pageSize; + pData2 -= 4; + saved = *(u32*)pEnd; + put32bits(pEnd, cksum); + szPg = pPager->pageSize+8; + put32bits(pData2, pPg->pgno); + rc = sqlite3OsWrite(pPager->jfd, pData2, szPg); + IOTRACE(("JOUT %p %d %lld %d\n", pPager, pPg->pgno, + pPager->journalOff, szPg)); + PAGER_INCR(sqlite3_pager_writej_count); + pPager->journalOff += szPg; + PAGERTRACE5("JOURNAL %d page %d needSync=%d hash(%08x)\n", + PAGERID(pPager), pPg->pgno, pPg->needSync, pager_pagehash(pPg)); + *(u32*)pEnd = saved; + + /* An error has occured writing to the journal file. The + ** transaction will be rolled back by the layer above. + */ + if( rc!=SQLITE_OK ){ + return rc; + } + + pPager->nRec++; + assert( pPager->aInJournal!=0 ); + pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7); + pPg->needSync = !pPager->noSync; + if( pPager->stmtInUse ){ + pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7); + } + } + }else{ + pPg->needSync = !pPager->journalStarted && !pPager->noSync; + PAGERTRACE4("APPEND %d page %d needSync=%d\n", + PAGERID(pPager), pPg->pgno, pPg->needSync); + } + if( pPg->needSync ){ + pPager->needSync = 1; + } + pPg->inJournal = 1; + } + + /* If the statement journal is open and the page is not in it, + ** then write the current page to the statement journal. Note that + ** the statement journal format differs from the standard journal format + ** in that it omits the checksums and the header. + */ + if( pPager->stmtInUse + && !pageInStatement(pPg) + && (int)pPg->pgno<=pPager->stmtSize + ){ + assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize ); + if( MEMDB ){ + PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); + assert( pHist->pStmt==0 ); + pHist->pStmt = sqliteMallocRaw( pPager->pageSize ); + if( pHist->pStmt ){ + memcpy(pHist->pStmt, PGHDR_TO_DATA(pPg), pPager->pageSize); + } + PAGERTRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); + page_add_to_stmt_list(pPg); + }else{ + char *pData2 = CODEC2(pPager, pData, pPg->pgno, 7)-4; + put32bits(pData2, pPg->pgno); + rc = sqlite3OsWrite(pPager->stfd, pData2, pPager->pageSize+4); + PAGERTRACE3("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno); + if( rc!=SQLITE_OK ){ + return rc; + } + pPager->stmtNRec++; + assert( pPager->aInStmt!=0 ); + pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7); + } + } + } + + /* Update the database size and return. + */ + assert( pPager->state>=PAGER_SHARED ); + if( pPager->dbSize<(int)pPg->pgno ){ + pPager->dbSize = pPg->pgno; + if( !MEMDB && pPager->dbSize==PENDING_BYTE/pPager->pageSize ){ + pPager->dbSize++; + } + } + return rc; +} + +/* +** This function is used to mark a data-page as writable. It uses +** pager_write() to open a journal file (if it is not already open) +** and write the page *pData to the journal. +** +** The difference between this function and pager_write() is that this +** function also deals with the special case where 2 or more pages +** fit on a single disk sector. In this case all co-resident pages +** must have been written to the journal file before returning. +*/ +int sqlite3PagerWrite(DbPage *pDbPage){ + int rc = SQLITE_OK; + + PgHdr *pPg = pDbPage; + Pager *pPager = pPg->pPager; + Pgno nPagePerSector = (pPager->sectorSize/pPager->pageSize); + + if( !MEMDB && nPagePerSector>1 ){ + Pgno nPageCount; /* Total number of pages in database file */ + Pgno pg1; /* First page of the sector pPg is located on. */ + int nPage; /* Number of pages starting at pg1 to journal */ + int ii; + + /* Set the doNotSync flag to 1. This is because we cannot allow a journal + ** header to be written between the pages journaled by this function. + */ + assert( pPager->doNotSync==0 ); + pPager->doNotSync = 1; + + /* This trick assumes that both the page-size and sector-size are + ** an integer power of 2. It sets variable pg1 to the identifier + ** of the first page of the sector pPg is located on. + */ + pg1 = ((pPg->pgno-1) & ~(nPagePerSector-1)) + 1; + + nPageCount = sqlite3PagerPagecount(pPager); + if( pPg->pgno>nPageCount ){ + nPage = (pPg->pgno - pg1)+1; + }else if( (pg1+nPagePerSector-1)>nPageCount ){ + nPage = nPageCount+1-pg1; + }else{ + nPage = nPagePerSector; + } + assert(nPage>0); + assert(pg1<=pPg->pgno); + assert((pg1+nPage)>pPg->pgno); + + for(ii=0; iiaInJournal || pg==pPg->pgno || + pg>pPager->origDbSize || !(pPager->aInJournal[pg/8]&(1<<(pg&7))) + ) { + if( pg!=PAGER_MJ_PGNO(pPager) ){ + PgHdr *pPage; + rc = sqlite3PagerGet(pPager, pg, &pPage); + if( rc==SQLITE_OK ){ + rc = pager_write(pPage); + sqlite3PagerUnref(pPage); + } + } + } + } + + assert( pPager->doNotSync==1 ); + pPager->doNotSync = 0; + }else{ + rc = pager_write(pDbPage); + } + return rc; +} + +/* +** Return TRUE if the page given in the argument was previously passed +** to sqlite3PagerWrite(). In other words, return TRUE if it is ok +** to change the content of the page. +*/ +#ifndef NDEBUG +int sqlite3PagerIswriteable(DbPage *pPg){ + return pPg->dirty; +} +#endif + +#ifndef SQLITE_OMIT_VACUUM +/* +** Replace the content of a single page with the information in the third +** argument. +*/ +int sqlite3PagerOverwrite(Pager *pPager, Pgno pgno, void *pData){ + PgHdr *pPg; + int rc; + + rc = sqlite3PagerGet(pPager, pgno, &pPg); + if( rc==SQLITE_OK ){ + rc = sqlite3PagerWrite(pPg); + if( rc==SQLITE_OK ){ + memcpy(sqlite3PagerGetData(pPg), pData, pPager->pageSize); + } + sqlite3PagerUnref(pPg); + } + return rc; +} +#endif + +/* +** A call to this routine tells the pager that it is not necessary to +** write the information on page pPg back to the disk, even though +** that page might be marked as dirty. +** +** The overlying software layer calls this routine when all of the data +** on the given page is unused. The pager marks the page as clean so +** that it does not get written to disk. +** +** Tests show that this optimization, together with the +** sqlite3PagerDontRollback() below, more than double the speed +** of large INSERT operations and quadruple the speed of large DELETEs. +** +** When this routine is called, set the alwaysRollback flag to true. +** Subsequent calls to sqlite3PagerDontRollback() for the same page +** will thereafter be ignored. This is necessary to avoid a problem +** where a page with data is added to the freelist during one part of +** a transaction then removed from the freelist during a later part +** of the same transaction and reused for some other purpose. When it +** is first added to the freelist, this routine is called. When reused, +** the sqlite3PagerDontRollback() routine is called. But because the +** page contains critical data, we still need to be sure it gets +** rolled back in spite of the sqlite3PagerDontRollback() call. +*/ +void sqlite3PagerDontWrite(DbPage *pDbPage){ + PgHdr *pPg = pDbPage; + Pager *pPager = pPg->pPager; + + if( MEMDB ) return; + pPg->alwaysRollback = 1; + if( pPg->dirty && !pPager->stmtInUse ){ + assert( pPager->state>=PAGER_SHARED ); + if( pPager->dbSize==(int)pPg->pgno && pPager->origDbSizedbSize ){ + /* If this pages is the last page in the file and the file has grown + ** during the current transaction, then do NOT mark the page as clean. + ** When the database file grows, we must make sure that the last page + ** gets written at least once so that the disk file will be the correct + ** size. If you do not write this page and the size of the file + ** on the disk ends up being too small, that can lead to database + ** corruption during the next transaction. + */ + }else{ + PAGERTRACE3("DONT_WRITE page %d of %d\n", pPg->pgno, PAGERID(pPager)); + IOTRACE(("CLEAN %p %d\n", pPager, pPg->pgno)) + makeClean(pPg); +#ifdef SQLITE_CHECK_PAGES + pPg->pageHash = pager_pagehash(pPg); +#endif + } + } +} + +/* +** A call to this routine tells the pager that if a rollback occurs, +** it is not necessary to restore the data on the given page. This +** means that the pager does not have to record the given page in the +** rollback journal. +** +** If we have not yet actually read the content of this page (if +** the PgHdr.needRead flag is set) then this routine acts as a promise +** that we will never need to read the page content in the future. +** so the needRead flag can be cleared at this point. +*/ +void sqlite3PagerDontRollback(DbPage *pPg){ + Pager *pPager = pPg->pPager; + + assert( pPager->state>=PAGER_RESERVED ); + if( pPager->journalOpen==0 ) return; + if( pPg->alwaysRollback || pPager->alwaysRollback || MEMDB ) return; + if( !pPg->inJournal && (int)pPg->pgno <= pPager->origDbSize ){ + assert( pPager->aInJournal!=0 ); + pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7); + pPg->inJournal = 1; + pPg->needRead = 0; + if( pPager->stmtInUse ){ + pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7); + } + PAGERTRACE3("DONT_ROLLBACK page %d of %d\n", pPg->pgno, PAGERID(pPager)); + IOTRACE(("GARBAGE %p %d\n", pPager, pPg->pgno)) + } + if( pPager->stmtInUse + && !pageInStatement(pPg) + && (int)pPg->pgno<=pPager->stmtSize + ){ + assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize ); + assert( pPager->aInStmt!=0 ); + pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7); + } +} + + +/* +** This routine is called to increment the database file change-counter, +** stored at byte 24 of the pager file. +*/ +static int pager_incr_changecounter(Pager *pPager){ + PgHdr *pPgHdr; + u32 change_counter; + int rc; + + if( !pPager->changeCountDone ){ + /* Open page 1 of the file for writing. */ + rc = sqlite3PagerGet(pPager, 1, &pPgHdr); + if( rc!=SQLITE_OK ) return rc; + rc = sqlite3PagerWrite(pPgHdr); + if( rc!=SQLITE_OK ) return rc; + + /* Increment the value just read and write it back to byte 24. */ + change_counter = sqlite3Get4byte((u8*)pPager->dbFileVers); + change_counter++; + put32bits(((char*)PGHDR_TO_DATA(pPgHdr))+24, change_counter); + /* Release the page reference. */ + sqlite3PagerUnref(pPgHdr); + pPager->changeCountDone = 1; + } + return SQLITE_OK; +} + +/* +** Sync the database file for the pager pPager. zMaster points to the name +** of a master journal file that should be written into the individual +** journal file. zMaster may be NULL, which is interpreted as no master +** journal (a single database transaction). +** +** This routine ensures that the journal is synced, all dirty pages written +** to the database file and the database file synced. The only thing that +** remains to commit the transaction is to delete the journal file (or +** master journal file if specified). +** +** Note that if zMaster==NULL, this does not overwrite a previous value +** passed to an sqlite3PagerCommitPhaseOne() call. +** +** If parameter nTrunc is non-zero, then the pager file is truncated to +** nTrunc pages (this is used by auto-vacuum databases). +*/ +int sqlite3PagerCommitPhaseOne(Pager *pPager, const char *zMaster, Pgno nTrunc){ + int rc = SQLITE_OK; + + PAGERTRACE4("DATABASE SYNC: File=%s zMaster=%s nTrunc=%d\n", + pPager->zFilename, zMaster, nTrunc); + + /* If this is an in-memory db, or no pages have been written to, or this + ** function has already been called, it is a no-op. + */ + if( pPager->state!=PAGER_SYNCED && !MEMDB && pPager->dirtyCache ){ + PgHdr *pPg; + assert( pPager->journalOpen ); + + /* If a master journal file name has already been written to the + ** journal file, then no sync is required. This happens when it is + ** written, then the process fails to upgrade from a RESERVED to an + ** EXCLUSIVE lock. The next time the process tries to commit the + ** transaction the m-j name will have already been written. + */ + if( !pPager->setMaster ){ + rc = pager_incr_changecounter(pPager); + if( rc!=SQLITE_OK ) goto sync_exit; +#ifndef SQLITE_OMIT_AUTOVACUUM + if( nTrunc!=0 ){ + /* If this transaction has made the database smaller, then all pages + ** being discarded by the truncation must be written to the journal + ** file. + */ + Pgno i; + int iSkip = PAGER_MJ_PGNO(pPager); + for( i=nTrunc+1; i<=pPager->origDbSize; i++ ){ + if( !(pPager->aInJournal[i/8] & (1<<(i&7))) && i!=iSkip ){ + rc = sqlite3PagerGet(pPager, i, &pPg); + if( rc!=SQLITE_OK ) goto sync_exit; + rc = sqlite3PagerWrite(pPg); + sqlite3PagerUnref(pPg); + if( rc!=SQLITE_OK ) goto sync_exit; + } + } + } +#endif + rc = writeMasterJournal(pPager, zMaster); + if( rc!=SQLITE_OK ) goto sync_exit; + rc = syncJournal(pPager); + if( rc!=SQLITE_OK ) goto sync_exit; + } + +#ifndef SQLITE_OMIT_AUTOVACUUM + if( nTrunc!=0 ){ + rc = sqlite3PagerTruncate(pPager, nTrunc); + if( rc!=SQLITE_OK ) goto sync_exit; + } +#endif + + /* Write all dirty pages to the database file */ + pPg = pager_get_all_dirty_pages(pPager); + rc = pager_write_pagelist(pPg); + if( rc!=SQLITE_OK ) goto sync_exit; + pPager->pDirty = 0; + + /* Sync the database file. */ + if( !pPager->noSync ){ + rc = sqlite3OsSync(pPager->fd, 0); + } + IOTRACE(("DBSYNC %p\n", pPager)) + + pPager->state = PAGER_SYNCED; + }else if( MEMDB && nTrunc!=0 ){ + rc = sqlite3PagerTruncate(pPager, nTrunc); + } + +sync_exit: + if( rc==SQLITE_IOERR_BLOCKED ){ + /* pager_incr_changecounter() may attempt to obtain an exclusive + * lock to spill the cache and return IOERR_BLOCKED. But since + * there is no chance the cache is inconsistent, it's + * better to return SQLITE_BUSY. + */ + rc = SQLITE_BUSY; + } + return rc; +} + + +/* +** Commit all changes to the database and release the write lock. +** +** If the commit fails for any reason, a rollback attempt is made +** and an error code is returned. If the commit worked, SQLITE_OK +** is returned. +*/ +int sqlite3PagerCommitPhaseTwo(Pager *pPager){ + int rc; + PgHdr *pPg; + + if( pPager->errCode ){ + return pPager->errCode; + } + if( pPager->statedirty = 0; + pPg->inJournal = 0; + pHist->inStmt = 0; + pPg->needSync = 0; + pHist->pPrevStmt = pHist->pNextStmt = 0; + pPg = pPg->pDirty; + } + pPager->pDirty = 0; +#ifndef NDEBUG + for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ + PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); + assert( !pPg->alwaysRollback ); + assert( !pHist->pOrig ); + assert( !pHist->pStmt ); + } +#endif + pPager->pStmt = 0; + pPager->state = PAGER_SHARED; + return SQLITE_OK; + } + assert( pPager->journalOpen || !pPager->dirtyCache ); + assert( pPager->state==PAGER_SYNCED || !pPager->dirtyCache ); + rc = pager_end_transaction(pPager); + return pager_error(pPager, rc); +} + +/* +** Rollback all changes. The database falls back to PAGER_SHARED mode. +** All in-memory cache pages revert to their original data contents. +** The journal is deleted. +** +** This routine cannot fail unless some other process is not following +** the correct locking protocol or unless some other +** process is writing trash into the journal file (SQLITE_CORRUPT) or +** unless a prior malloc() failed (SQLITE_NOMEM). Appropriate error +** codes are returned for all these occasions. Otherwise, +** SQLITE_OK is returned. +*/ +int sqlite3PagerRollback(Pager *pPager){ + int rc; + PAGERTRACE2("ROLLBACK %d\n", PAGERID(pPager)); + if( MEMDB ){ + PgHdr *p; + for(p=pPager->pAll; p; p=p->pNextAll){ + PgHistory *pHist; + assert( !p->alwaysRollback ); + if( !p->dirty ){ + assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pOrig ); + assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pStmt ); + continue; + } + + pHist = PGHDR_TO_HIST(p, pPager); + if( pHist->pOrig ){ + memcpy(PGHDR_TO_DATA(p), pHist->pOrig, pPager->pageSize); + PAGERTRACE3("ROLLBACK-PAGE %d of %d\n", p->pgno, PAGERID(pPager)); + }else{ + PAGERTRACE3("PAGE %d is clean on %d\n", p->pgno, PAGERID(pPager)); + } + clearHistory(pHist); + p->dirty = 0; + p->inJournal = 0; + pHist->inStmt = 0; + pHist->pPrevStmt = pHist->pNextStmt = 0; + if( pPager->xReiniter ){ + pPager->xReiniter(p, pPager->pageSize); + } + } + pPager->pDirty = 0; + pPager->pStmt = 0; + pPager->dbSize = pPager->origDbSize; + pager_truncate_cache(pPager); + pPager->stmtInUse = 0; + pPager->state = PAGER_SHARED; + return SQLITE_OK; + } + + if( !pPager->dirtyCache || !pPager->journalOpen ){ + rc = pager_end_transaction(pPager); + return rc; + } + + if( pPager->errCode && pPager->errCode!=SQLITE_FULL ){ + if( pPager->state>=PAGER_EXCLUSIVE ){ + pager_playback(pPager, 0); + } + return pPager->errCode; + } + if( pPager->state==PAGER_RESERVED ){ + int rc2; + rc = pager_playback(pPager, 0); + rc2 = pager_end_transaction(pPager); + if( rc==SQLITE_OK ){ + rc = rc2; + } + }else{ + rc = pager_playback(pPager, 0); + } + /* pager_reset(pPager); */ + pPager->dbSize = -1; + + /* If an error occurs during a ROLLBACK, we can no longer trust the pager + ** cache. So call pager_error() on the way out to make any error + ** persistent. + */ + return pager_error(pPager, rc); +} + +/* +** Return TRUE if the database file is opened read-only. Return FALSE +** if the database is (in theory) writable. +*/ +int sqlite3PagerIsreadonly(Pager *pPager){ + return pPager->readOnly; +} + +/* +** Return the number of references to the pager. +*/ +int sqlite3PagerRefcount(Pager *pPager){ + return pPager->nRef; +} + +#ifdef SQLITE_TEST +/* +** This routine is used for testing and analysis only. +*/ +int *sqlite3PagerStats(Pager *pPager){ + static int a[11]; + a[0] = pPager->nRef; + a[1] = pPager->nPage; + a[2] = pPager->mxPage; + a[3] = pPager->dbSize; + a[4] = pPager->state; + a[5] = pPager->errCode; + a[6] = pPager->nHit; + a[7] = pPager->nMiss; + a[8] = 0; /* Used to be pPager->nOvfl */ + a[9] = pPager->nRead; + a[10] = pPager->nWrite; + return a; +} +#endif + +/* +** Set the statement rollback point. +** +** This routine should be called with the transaction journal already +** open. A new statement journal is created that can be used to rollback +** changes of a single SQL command within a larger transaction. +*/ +int sqlite3PagerStmtBegin(Pager *pPager){ + int rc; + assert( !pPager->stmtInUse ); + assert( pPager->state>=PAGER_SHARED ); + assert( pPager->dbSize>=0 ); + PAGERTRACE2("STMT-BEGIN %d\n", PAGERID(pPager)); + if( MEMDB ){ + pPager->stmtInUse = 1; + pPager->stmtSize = pPager->dbSize; + return SQLITE_OK; + } + if( !pPager->journalOpen ){ + pPager->stmtAutoopen = 1; + return SQLITE_OK; + } + assert( pPager->journalOpen ); + pPager->aInStmt = sqliteMalloc( pPager->dbSize/8 + 1 ); + if( pPager->aInStmt==0 ){ + /* sqlite3OsLock(pPager->fd, SHARED_LOCK); */ + return SQLITE_NOMEM; + } +#ifndef NDEBUG + rc = sqlite3OsFileSize(pPager->jfd, &pPager->stmtJSize); + if( rc ) goto stmt_begin_failed; + assert( pPager->stmtJSize == pPager->journalOff ); +#endif + pPager->stmtJSize = pPager->journalOff; + pPager->stmtSize = pPager->dbSize; + pPager->stmtHdrOff = 0; + pPager->stmtCksum = pPager->cksumInit; + if( !pPager->stmtOpen ){ + rc = sqlite3PagerOpentemp(&pPager->stfd); + if( rc ) goto stmt_begin_failed; + pPager->stmtOpen = 1; + pPager->stmtNRec = 0; + } + pPager->stmtInUse = 1; + return SQLITE_OK; + +stmt_begin_failed: + if( pPager->aInStmt ){ + sqliteFree(pPager->aInStmt); + pPager->aInStmt = 0; + } + return rc; +} + +/* +** Commit a statement. +*/ +int sqlite3PagerStmtCommit(Pager *pPager){ + if( pPager->stmtInUse ){ + PgHdr *pPg, *pNext; + PAGERTRACE2("STMT-COMMIT %d\n", PAGERID(pPager)); + if( !MEMDB ){ + sqlite3OsSeek(pPager->stfd, 0); + /* sqlite3OsTruncate(pPager->stfd, 0); */ + sqliteFree( pPager->aInStmt ); + pPager->aInStmt = 0; + }else{ + for(pPg=pPager->pStmt; pPg; pPg=pNext){ + PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); + pNext = pHist->pNextStmt; + assert( pHist->inStmt ); + pHist->inStmt = 0; + pHist->pPrevStmt = pHist->pNextStmt = 0; + sqliteFree(pHist->pStmt); + pHist->pStmt = 0; + } + } + pPager->stmtNRec = 0; + pPager->stmtInUse = 0; + pPager->pStmt = 0; + } + pPager->stmtAutoopen = 0; + return SQLITE_OK; +} + +/* +** Rollback a statement. +*/ +int sqlite3PagerStmtRollback(Pager *pPager){ + int rc; + if( pPager->stmtInUse ){ + PAGERTRACE2("STMT-ROLLBACK %d\n", PAGERID(pPager)); + if( MEMDB ){ + PgHdr *pPg; + PgHistory *pHist; + for(pPg=pPager->pStmt; pPg; pPg=pHist->pNextStmt){ + pHist = PGHDR_TO_HIST(pPg, pPager); + if( pHist->pStmt ){ + memcpy(PGHDR_TO_DATA(pPg), pHist->pStmt, pPager->pageSize); + sqliteFree(pHist->pStmt); + pHist->pStmt = 0; + } + } + pPager->dbSize = pPager->stmtSize; + pager_truncate_cache(pPager); + rc = SQLITE_OK; + }else{ + rc = pager_stmt_playback(pPager); + } + sqlite3PagerStmtCommit(pPager); + }else{ + rc = SQLITE_OK; + } + pPager->stmtAutoopen = 0; + return rc; +} + +/* +** Return the full pathname of the database file. +*/ +const char *sqlite3PagerFilename(Pager *pPager){ + return pPager->zFilename; +} + +/* +** Return the directory of the database file. +*/ +const char *sqlite3PagerDirname(Pager *pPager){ + return pPager->zDirectory; +} + +/* +** Return the full pathname of the journal file. +*/ +const char *sqlite3PagerJournalname(Pager *pPager){ + return pPager->zJournal; +} + +/* +** Return true if fsync() calls are disabled for this pager. Return FALSE +** if fsync()s are executed normally. +*/ +int sqlite3PagerNosync(Pager *pPager){ + return pPager->noSync; +} + +#ifdef SQLITE_HAS_CODEC +/* +** Set the codec for this pager +*/ +void sqlite3PagerSetCodec( + Pager *pPager, + void *(*xCodec)(void*,void*,Pgno,int), + void *pCodecArg +){ + pPager->xCodec = xCodec; + pPager->pCodecArg = pCodecArg; +} +#endif + +#ifndef SQLITE_OMIT_AUTOVACUUM +/* +** Move the page pPg to location pgno in the file. +** +** There must be no references to the page previously located at +** pgno (which we call pPgOld) though that page is allowed to be +** in cache. If the page previous located at pgno is not already +** in the rollback journal, it is not put there by by this routine. +** +** References to the page pPg remain valid. Updating any +** meta-data associated with pPg (i.e. data stored in the nExtra bytes +** allocated along with the page) is the responsibility of the caller. +** +** A transaction must be active when this routine is called. It used to be +** required that a statement transaction was not active, but this restriction +** has been removed (CREATE INDEX needs to move a page when a statement +** transaction is active). +*/ +int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno){ + PgHdr *pPgOld; /* The page being overwritten. */ + int h; + Pgno needSyncPgno = 0; + + assert( pPg->nRef>0 ); + + PAGERTRACE5("MOVE %d page %d (needSync=%d) moves to %d\n", + PAGERID(pPager), pPg->pgno, pPg->needSync, pgno); + IOTRACE(("MOVE %p %d %d\n", pPager, pPg->pgno, pgno)) + + pager_get_content(pPg); + if( pPg->needSync ){ + needSyncPgno = pPg->pgno; + assert( pPg->inJournal || (int)pgno>pPager->origDbSize ); + assert( pPg->dirty ); + assert( pPager->needSync ); + } + + /* Unlink pPg from it's hash-chain */ + unlinkHashChain(pPager, pPg); + + /* If the cache contains a page with page-number pgno, remove it + ** from it's hash chain. Also, if the PgHdr.needSync was set for + ** page pgno before the 'move' operation, it needs to be retained + ** for the page moved there. + */ + pPg->needSync = 0; + pPgOld = pager_lookup(pPager, pgno); + if( pPgOld ){ + assert( pPgOld->nRef==0 ); + unlinkHashChain(pPager, pPgOld); + makeClean(pPgOld); + pPg->needSync = pPgOld->needSync; + }else{ + pPg->needSync = 0; + } + if( pPager->aInJournal && (int)pgno<=pPager->origDbSize ){ + pPg->inJournal = (pPager->aInJournal[pgno/8] & (1<<(pgno&7)))!=0; + }else{ + pPg->inJournal = 0; + assert( pPg->needSync==0 || (int)pgno>pPager->origDbSize ); + } + + /* Change the page number for pPg and insert it into the new hash-chain. */ + assert( pgno!=0 ); + pPg->pgno = pgno; + h = pgno & (pPager->nHash-1); + if( pPager->aHash[h] ){ + assert( pPager->aHash[h]->pPrevHash==0 ); + pPager->aHash[h]->pPrevHash = pPg; + } + pPg->pNextHash = pPager->aHash[h]; + pPager->aHash[h] = pPg; + pPg->pPrevHash = 0; + + makeDirty(pPg); + pPager->dirtyCache = 1; + + if( needSyncPgno ){ + /* If needSyncPgno is non-zero, then the journal file needs to be + ** sync()ed before any data is written to database file page needSyncPgno. + ** Currently, no such page exists in the page-cache and the + ** Pager.aInJournal bit has been set. This needs to be remedied by loading + ** the page into the pager-cache and setting the PgHdr.needSync flag. + ** + ** The sqlite3PagerGet() call may cause the journal to sync. So make + ** sure the Pager.needSync flag is set too. + */ + int rc; + PgHdr *pPgHdr; + assert( pPager->needSync ); + rc = sqlite3PagerGet(pPager, needSyncPgno, &pPgHdr); + if( rc!=SQLITE_OK ) return rc; + pPager->needSync = 1; + pPgHdr->needSync = 1; + pPgHdr->inJournal = 1; + makeDirty(pPgHdr); + sqlite3PagerUnref(pPgHdr); + } + + return SQLITE_OK; +} +#endif + +/* +** Return a pointer to the data for the specified page. +*/ +void *sqlite3PagerGetData(DbPage *pPg){ + return PGHDR_TO_DATA(pPg); +} + +/* +** Return a pointer to the Pager.nExtra bytes of "extra" space +** allocated along with the specified page. +*/ +void *sqlite3PagerGetExtra(DbPage *pPg){ + Pager *pPager = pPg->pPager; + return (pPager?PGHDR_TO_EXTRA(pPg, pPager):0); +} + +/* +** Get/set the locking-mode for this pager. Parameter eMode must be one +** of PAGER_LOCKINGMODE_QUERY, PAGER_LOCKINGMODE_NORMAL or +** PAGER_LOCKINGMODE_EXCLUSIVE. If the parameter is not _QUERY, then +** the locking-mode is set to the value specified. +** +** The returned value is either PAGER_LOCKINGMODE_NORMAL or +** PAGER_LOCKINGMODE_EXCLUSIVE, indicating the current (possibly updated) +** locking-mode. +*/ +int sqlite3PagerLockingMode(Pager *pPager, int eMode){ + assert( eMode==PAGER_LOCKINGMODE_QUERY + || eMode==PAGER_LOCKINGMODE_NORMAL + || eMode==PAGER_LOCKINGMODE_EXCLUSIVE ); + assert( PAGER_LOCKINGMODE_QUERY<0 ); + assert( PAGER_LOCKINGMODE_NORMAL>=0 && PAGER_LOCKINGMODE_EXCLUSIVE>=0 ); + if( eMode>=0 && !pPager->tempFile ){ + pPager->exclusiveMode = eMode; + } + return (int)pPager->exclusiveMode; +} + +#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) +/* +** Return the current state of the file lock for the given pager. +** The return value is one of NO_LOCK, SHARED_LOCK, RESERVED_LOCK, +** PENDING_LOCK, or EXCLUSIVE_LOCK. +*/ +int sqlite3PagerLockstate(Pager *pPager){ + return sqlite3OsLockState(pPager->fd); +} +#endif + +#ifdef SQLITE_DEBUG +/* +** Print a listing of all referenced pages and their ref count. +*/ +void sqlite3PagerRefdump(Pager *pPager){ + PgHdr *pPg; + for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ + if( pPg->nRef<=0 ) continue; + sqlite3DebugPrintf("PAGE %3d addr=%p nRef=%d\n", + pPg->pgno, PGHDR_TO_DATA(pPg), pPg->nRef); + } +} +#endif + +#endif /* SQLITE_OMIT_DISKIO */ diff --git a/extensions/sqlite/sqlite-source/pager.h b/extensions/sqlite/sqlite-source/pager.h new file mode 100644 index 00000000..f3c82c29 --- /dev/null +++ b/extensions/sqlite/sqlite-source/pager.h @@ -0,0 +1,128 @@ +/* +** 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$ +*/ + +#ifndef _PAGER_H_ +#define _PAGER_H_ + +/* +** 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; + +/* +** Handle type for pages. +*/ +typedef struct PgHdr DbPage; + +/* +** Allowed values for the flags parameter to sqlite3PagerOpen(). +** +** 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 */ + +/* +** Valid values for the second argument to sqlite3PagerLockingMode(). +*/ +#define PAGER_LOCKINGMODE_QUERY -1 +#define PAGER_LOCKINGMODE_NORMAL 0 +#define PAGER_LOCKINGMODE_EXCLUSIVE 1 + +/* +** See source code comments for a detailed description of the following +** routines: +*/ +int sqlite3PagerOpen(Pager **ppPager, const char *zFilename, + int nExtra, int flags); +void sqlite3PagerSetBusyhandler(Pager*, BusyHandler *pBusyHandler); +void sqlite3PagerSetDestructor(Pager*, void(*)(DbPage*,int)); +void sqlite3PagerSetReiniter(Pager*, void(*)(DbPage*,int)); +int sqlite3PagerSetPagesize(Pager*, int); +int sqlite3PagerMaxPageCount(Pager*, int); +int sqlite3PagerReadFileheader(Pager*, int, unsigned char*); +void sqlite3PagerSetCachesize(Pager*, int); +int sqlite3PagerClose(Pager *pPager); +int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag); +#define sqlite3PagerGet(A,B,C) sqlite3PagerAcquire(A,B,C,0) +DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno); +int sqlite3PagerRef(DbPage*); +int sqlite3PagerUnref(DbPage*); +int sqlite3PagerWrite(DbPage*); +int sqlite3PagerOverwrite(Pager *pPager, Pgno pgno, void*); +int sqlite3PagerPagecount(Pager*); +int sqlite3PagerTruncate(Pager*,Pgno); +int sqlite3PagerBegin(DbPage*, int exFlag); +int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, Pgno); +int sqlite3PagerCommitPhaseTwo(Pager*); +int sqlite3PagerRollback(Pager*); +int sqlite3PagerIsreadonly(Pager*); +int sqlite3PagerStmtBegin(Pager*); +int sqlite3PagerStmtCommit(Pager*); +int sqlite3PagerStmtRollback(Pager*); +void sqlite3PagerDontRollback(DbPage*); +void sqlite3PagerDontWrite(DbPage*); +int sqlite3PagerRefcount(Pager*); +void sqlite3PagerSetSafetyLevel(Pager*,int,int); +const char *sqlite3PagerFilename(Pager*); +const char *sqlite3PagerDirname(Pager*); +const char *sqlite3PagerJournalname(Pager*); +int sqlite3PagerNosync(Pager*); +int sqlite3PagerMovepage(Pager*,DbPage*,Pgno); +void *sqlite3PagerGetData(DbPage *); +void *sqlite3PagerGetExtra(DbPage *); +int sqlite3PagerLockingMode(Pager *, int); + +#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO) + int sqlite3PagerReleaseMemory(int); +#endif + +#ifdef SQLITE_HAS_CODEC + void sqlite3PagerSetCodec(Pager*,void*(*)(void*,void*,Pgno,int),void*); +#endif + +#if !defined(NDEBUG) || defined(SQLITE_TEST) + Pgno sqlite3PagerPagenumber(DbPage*); + int sqlite3PagerIswriteable(DbPage*); +#endif + +#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) + int sqlite3PagerLockstate(Pager*); +#endif + +#ifdef SQLITE_TEST + int *sqlite3PagerStats(Pager*); + void sqlite3PagerRefdump(Pager*); + int pager3_refinfo_enable; +#endif + +#ifdef SQLITE_TEST +void disable_simulated_io_errors(void); +void enable_simulated_io_errors(void); +#else +# define disable_simulated_io_errors() +# define enable_simulated_io_errors() +#endif + +#endif /* _PAGER_H_ */ diff --git a/extensions/sqlite/sqlite-source/parse.c b/extensions/sqlite/sqlite-source/parse.c new file mode 100644 index 00000000..508d5bd5 --- /dev/null +++ b/extensions/sqlite/sqlite-source/parse.c @@ -0,0 +1,3503 @@ +/* Driver template for the LEMON parser generator. +** The author disclaims copyright to this source code. +*/ +/* First off, code is include which follows the "include" declaration +** in the input file. */ +#include +#line 56 "parse.y" + +#include "sqliteInt.h" +#include "parse.h" + +/* +** An instance of this structure holds information about the +** LIMIT clause of a SELECT statement. +*/ +struct LimitVal { + Expr *pLimit; /* The LIMIT expression. NULL if there is no limit */ + Expr *pOffset; /* The OFFSET expression. NULL if there is none */ +}; + +/* +** An instance of this structure is used to store the LIKE, +** GLOB, NOT LIKE, and NOT GLOB operators. +*/ +struct LikeOp { + Token eOperator; /* "like" or "glob" or "regexp" */ + int not; /* True if the NOT keyword is present */ +}; + +/* +** An instance of the following structure describes the event of a +** TRIGGER. "a" is the event type, one of TK_UPDATE, TK_INSERT, +** TK_DELETE, or TK_INSTEAD. If the event is of the form +** +** UPDATE ON (a,b,c) +** +** Then the "b" IdList records the list "a,b,c". +*/ +struct TrigEvent { int a; IdList * b; }; + +/* +** An instance of this structure holds the ATTACH key and the key type. +*/ +struct AttachKey { int type; Token key; }; + +#line 48 "parse.c" +/* Next is all token values, in a form suitable for use by makeheaders. +** This section will be null unless lemon is run with the -m switch. +*/ +/* +** These constants (all generated automatically by the parser generator) +** specify the various kinds of tokens (terminals) that the parser +** understands. +** +** Each symbol here is a terminal symbol in the grammar. +*/ +/* Make sure the INTERFACE macro is defined. +*/ +#ifndef INTERFACE +# define INTERFACE 1 +#endif +/* The next thing included is series of defines which control +** various aspects of the generated parser. +** YYCODETYPE is the data type used for storing terminal +** and nonterminal numbers. "unsigned char" is +** used if there are fewer than 250 terminals +** and nonterminals. "int" is used otherwise. +** YYNOCODE is a number of type YYCODETYPE which corresponds +** to no legal terminal or nonterminal number. This +** number is used to fill in empty slots of the hash +** table. +** YYFALLBACK If defined, this indicates that one or more tokens +** have fall-back values which should be used if the +** original value of the token will not parse. +** YYACTIONTYPE is the data type used for storing terminal +** and nonterminal numbers. "unsigned char" is +** used if there are fewer than 250 rules and +** states combined. "int" is used otherwise. +** sqlite3ParserTOKENTYPE is the data type used for minor tokens given +** directly to the parser from the tokenizer. +** YYMINORTYPE is the data type used for all minor tokens. +** This is typically a union of many types, one of +** which is sqlite3ParserTOKENTYPE. The entry in the union +** for base tokens is called "yy0". +** YYSTACKDEPTH is the maximum depth of the parser's stack. If +** zero the stack is dynamically sized using realloc() +** sqlite3ParserARG_SDECL A static variable declaration for the %extra_argument +** sqlite3ParserARG_PDECL A parameter declaration for the %extra_argument +** sqlite3ParserARG_STORE Code to store %extra_argument into yypParser +** sqlite3ParserARG_FETCH Code to extract %extra_argument from yypParser +** YYNSTATE the combined number of states. +** YYNRULE the number of rules in the grammar +** YYERRORSYMBOL is the code number of the error symbol. If not +** defined, then do no error processing. +*/ +#define YYCODETYPE unsigned char +#define YYNOCODE 248 +#define YYACTIONTYPE unsigned short int +#define YYWILDCARD 59 +#define sqlite3ParserTOKENTYPE Token +typedef union { + sqlite3ParserTOKENTYPE yy0; + int yy46; + struct LikeOp yy72; + Expr* yy172; + ExprList* yy174; + Select* yy219; + struct LimitVal yy234; + TriggerStep* yy243; + struct TrigEvent yy370; + SrcList* yy373; + Expr * yy386; + struct {int value; int mask;} yy405; + Token yy410; + IdList* yy432; + int yy495; +} YYMINORTYPE; +#ifndef YYSTACKDEPTH +#define YYSTACKDEPTH 100 +#endif +#define sqlite3ParserARG_SDECL Parse *pParse; +#define sqlite3ParserARG_PDECL ,Parse *pParse +#define sqlite3ParserARG_FETCH Parse *pParse = yypParser->pParse +#define sqlite3ParserARG_STORE yypParser->pParse = pParse +#define YYNSTATE 586 +#define YYNRULE 311 +#define YYERRORSYMBOL 138 +#define YYERRSYMDT yy495 +#define YYFALLBACK 1 +#define YY_NO_ACTION (YYNSTATE+YYNRULE+2) +#define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1) +#define YY_ERROR_ACTION (YYNSTATE+YYNRULE) + +/* Next are that tables used to determine what action to take based on the +** current state and lookahead token. These tables are used to implement +** functions that take a state number and lookahead value and return an +** action integer. +** +** Suppose the action integer is N. Then the action is determined as +** follows +** +** 0 <= N < YYNSTATE Shift N. That is, push the lookahead +** token onto the stack and goto state N. +** +** YYNSTATE <= N < YYNSTATE+YYNRULE Reduce by rule N-YYNSTATE. +** +** N == YYNSTATE+YYNRULE A syntax error has occurred. +** +** N == YYNSTATE+YYNRULE+1 The parser accepts its input. +** +** N == YYNSTATE+YYNRULE+2 No such action. Denotes unused +** slots in the yy_action[] table. +** +** The action table is constructed as a single large table named yy_action[]. +** Given state S and lookahead X, the action is computed as +** +** yy_action[ yy_shift_ofst[S] + X ] +** +** If the index value yy_shift_ofst[S]+X is out of range or if the value +** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S] +** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table +** and that yy_default[S] should be used instead. +** +** The formula above is for computing the action when the lookahead is +** a terminal symbol. If the lookahead is a non-terminal (as occurs after +** a reduce action) then the yy_reduce_ofst[] array is used in place of +** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of +** YY_SHIFT_USE_DFLT. +** +** The following are the tables generated in this section: +** +** yy_action[] A single table containing all actions. +** yy_lookahead[] A table containing the lookahead for each entry in +** yy_action. Used to detect hash collisions. +** yy_shift_ofst[] For each state, the offset into yy_action for +** shifting terminals. +** yy_reduce_ofst[] For each state, the offset into yy_action for +** shifting non-terminals after a reduce. +** yy_default[] Default action for each state. +*/ +static const YYACTIONTYPE yy_action[] = { + /* 0 */ 290, 898, 122, 585, 407, 170, 2, 437, 61, 61, + /* 10 */ 61, 61, 517, 63, 63, 63, 63, 64, 64, 65, + /* 20 */ 65, 65, 66, 231, 445, 209, 422, 428, 68, 63, + /* 30 */ 63, 63, 63, 64, 64, 65, 65, 65, 66, 231, + /* 40 */ 389, 386, 394, 449, 60, 59, 295, 432, 433, 429, + /* 50 */ 429, 62, 62, 61, 61, 61, 61, 261, 63, 63, + /* 60 */ 63, 63, 64, 64, 65, 65, 65, 66, 231, 290, + /* 70 */ 491, 492, 437, 487, 206, 81, 67, 417, 69, 152, + /* 80 */ 63, 63, 63, 63, 64, 64, 65, 65, 65, 66, + /* 90 */ 231, 67, 460, 69, 152, 422, 428, 571, 262, 58, + /* 100 */ 64, 64, 65, 65, 65, 66, 231, 395, 396, 419, + /* 110 */ 419, 419, 290, 60, 59, 295, 432, 433, 429, 429, + /* 120 */ 62, 62, 61, 61, 61, 61, 315, 63, 63, 63, + /* 130 */ 63, 64, 64, 65, 65, 65, 66, 231, 422, 428, + /* 140 */ 93, 65, 65, 65, 66, 231, 394, 231, 412, 34, + /* 150 */ 56, 296, 440, 441, 408, 486, 60, 59, 295, 432, + /* 160 */ 433, 429, 429, 62, 62, 61, 61, 61, 61, 488, + /* 170 */ 63, 63, 63, 63, 64, 64, 65, 65, 65, 66, + /* 180 */ 231, 290, 255, 522, 293, 569, 112, 406, 520, 449, + /* 190 */ 329, 315, 405, 20, 437, 338, 517, 394, 530, 529, + /* 200 */ 503, 445, 209, 568, 567, 206, 528, 422, 428, 147, + /* 210 */ 148, 395, 396, 412, 41, 208, 149, 531, 370, 487, + /* 220 */ 259, 566, 257, 417, 290, 60, 59, 295, 432, 433, + /* 230 */ 429, 429, 62, 62, 61, 61, 61, 61, 315, 63, + /* 240 */ 63, 63, 63, 64, 64, 65, 65, 65, 66, 231, + /* 250 */ 422, 428, 445, 331, 212, 419, 419, 419, 361, 437, + /* 260 */ 412, 41, 395, 396, 364, 565, 208, 290, 60, 59, + /* 270 */ 295, 432, 433, 429, 429, 62, 62, 61, 61, 61, + /* 280 */ 61, 394, 63, 63, 63, 63, 64, 64, 65, 65, + /* 290 */ 65, 66, 231, 422, 428, 489, 298, 522, 472, 66, + /* 300 */ 231, 211, 472, 224, 409, 284, 532, 20, 447, 521, + /* 310 */ 166, 60, 59, 295, 432, 433, 429, 429, 62, 62, + /* 320 */ 61, 61, 61, 61, 472, 63, 63, 63, 63, 64, + /* 330 */ 64, 65, 65, 65, 66, 231, 207, 478, 315, 76, + /* 340 */ 290, 235, 298, 55, 482, 225, 395, 396, 179, 545, + /* 350 */ 492, 343, 346, 347, 67, 150, 69, 152, 337, 522, + /* 360 */ 412, 35, 348, 237, 249, 368, 422, 428, 576, 20, + /* 370 */ 162, 116, 239, 341, 244, 342, 174, 320, 440, 441, + /* 380 */ 412, 3, 79, 250, 60, 59, 295, 432, 433, 429, + /* 390 */ 429, 62, 62, 61, 61, 61, 61, 172, 63, 63, + /* 400 */ 63, 63, 64, 64, 65, 65, 65, 66, 231, 290, + /* 410 */ 249, 548, 232, 485, 508, 351, 315, 116, 239, 341, + /* 420 */ 244, 342, 174, 179, 315, 523, 343, 346, 347, 250, + /* 430 */ 218, 413, 153, 462, 509, 422, 428, 348, 412, 34, + /* 440 */ 463, 208, 175, 173, 158, 233, 412, 34, 336, 547, + /* 450 */ 447, 321, 166, 60, 59, 295, 432, 433, 429, 429, + /* 460 */ 62, 62, 61, 61, 61, 61, 413, 63, 63, 63, + /* 470 */ 63, 64, 64, 65, 65, 65, 66, 231, 290, 540, + /* 480 */ 333, 515, 502, 539, 454, 569, 300, 19, 329, 142, + /* 490 */ 315, 388, 315, 328, 2, 360, 455, 292, 481, 371, + /* 500 */ 267, 266, 250, 568, 422, 428, 586, 389, 386, 456, + /* 510 */ 206, 493, 412, 49, 412, 49, 301, 583, 889, 157, + /* 520 */ 889, 494, 60, 59, 295, 432, 433, 429, 429, 62, + /* 530 */ 62, 61, 61, 61, 61, 199, 63, 63, 63, 63, + /* 540 */ 64, 64, 65, 65, 65, 66, 231, 290, 315, 179, + /* 550 */ 436, 253, 343, 346, 347, 368, 151, 580, 306, 248, + /* 560 */ 307, 450, 75, 348, 77, 380, 208, 423, 424, 413, + /* 570 */ 412, 27, 317, 422, 428, 438, 1, 22, 583, 888, + /* 580 */ 394, 888, 542, 476, 318, 261, 435, 435, 426, 427, + /* 590 */ 413, 60, 59, 295, 432, 433, 429, 429, 62, 62, + /* 600 */ 61, 61, 61, 61, 326, 63, 63, 63, 63, 64, + /* 610 */ 64, 65, 65, 65, 66, 231, 290, 425, 580, 372, + /* 620 */ 219, 92, 515, 9, 334, 394, 555, 394, 454, 67, + /* 630 */ 394, 69, 152, 397, 398, 399, 318, 234, 435, 435, + /* 640 */ 455, 316, 422, 428, 297, 395, 396, 318, 430, 435, + /* 650 */ 435, 579, 289, 456, 220, 325, 5, 217, 544, 290, + /* 660 */ 60, 59, 295, 432, 433, 429, 429, 62, 62, 61, + /* 670 */ 61, 61, 61, 393, 63, 63, 63, 63, 64, 64, + /* 680 */ 65, 65, 65, 66, 231, 422, 428, 480, 311, 390, + /* 690 */ 395, 396, 395, 396, 205, 395, 396, 821, 271, 515, + /* 700 */ 248, 198, 290, 60, 59, 295, 432, 433, 429, 429, + /* 710 */ 62, 62, 61, 61, 61, 61, 468, 63, 63, 63, + /* 720 */ 63, 64, 64, 65, 65, 65, 66, 231, 422, 428, + /* 730 */ 169, 158, 261, 261, 302, 413, 274, 117, 272, 261, + /* 740 */ 515, 515, 261, 515, 190, 290, 60, 70, 295, 432, + /* 750 */ 433, 429, 429, 62, 62, 61, 61, 61, 61, 377, + /* 760 */ 63, 63, 63, 63, 64, 64, 65, 65, 65, 66, + /* 770 */ 231, 422, 428, 382, 557, 303, 304, 248, 413, 318, + /* 780 */ 558, 435, 435, 559, 538, 358, 538, 385, 290, 194, + /* 790 */ 59, 295, 432, 433, 429, 429, 62, 62, 61, 61, + /* 800 */ 61, 61, 369, 63, 63, 63, 63, 64, 64, 65, + /* 810 */ 65, 65, 66, 231, 422, 428, 394, 273, 248, 248, + /* 820 */ 170, 246, 437, 413, 384, 365, 176, 177, 178, 467, + /* 830 */ 309, 121, 154, 126, 295, 432, 433, 429, 429, 62, + /* 840 */ 62, 61, 61, 61, 61, 315, 63, 63, 63, 63, + /* 850 */ 64, 64, 65, 65, 65, 66, 231, 72, 322, 175, + /* 860 */ 4, 315, 261, 315, 294, 261, 413, 412, 28, 315, + /* 870 */ 261, 315, 319, 72, 322, 315, 4, 418, 443, 443, + /* 880 */ 294, 395, 396, 412, 23, 412, 32, 437, 319, 324, + /* 890 */ 327, 412, 53, 412, 52, 315, 156, 412, 97, 449, + /* 900 */ 315, 192, 315, 275, 315, 324, 376, 469, 500, 315, + /* 910 */ 476, 277, 476, 163, 292, 449, 315, 412, 95, 74, + /* 920 */ 73, 467, 412, 100, 412, 101, 412, 111, 72, 313, + /* 930 */ 314, 412, 113, 417, 446, 74, 73, 479, 412, 16, + /* 940 */ 379, 315, 181, 465, 72, 313, 314, 72, 322, 417, + /* 950 */ 4, 206, 315, 184, 294, 315, 497, 498, 474, 206, + /* 960 */ 171, 339, 319, 412, 98, 419, 419, 419, 420, 421, + /* 970 */ 11, 359, 378, 305, 412, 33, 413, 412, 96, 324, + /* 980 */ 458, 419, 419, 419, 420, 421, 11, 413, 411, 449, + /* 990 */ 411, 160, 410, 315, 410, 466, 221, 222, 223, 103, + /* 1000 */ 83, 471, 315, 507, 506, 315, 620, 475, 315, 74, + /* 1010 */ 73, 245, 203, 21, 279, 412, 24, 437, 72, 313, + /* 1020 */ 314, 280, 315, 417, 412, 54, 505, 412, 114, 315, + /* 1030 */ 412, 115, 504, 201, 145, 547, 240, 510, 524, 200, + /* 1040 */ 315, 511, 202, 315, 412, 25, 315, 241, 315, 18, + /* 1050 */ 315, 412, 36, 315, 254, 419, 419, 419, 420, 421, + /* 1060 */ 11, 256, 412, 37, 258, 412, 26, 315, 412, 38, + /* 1070 */ 412, 39, 412, 40, 260, 412, 42, 315, 512, 315, + /* 1080 */ 126, 315, 437, 315, 187, 375, 276, 266, 265, 412, + /* 1090 */ 43, 291, 315, 252, 315, 126, 206, 581, 8, 412, + /* 1100 */ 44, 412, 29, 412, 30, 412, 45, 350, 363, 126, + /* 1110 */ 315, 543, 315, 126, 412, 46, 412, 47, 315, 355, + /* 1120 */ 381, 551, 315, 171, 552, 315, 90, 562, 578, 90, + /* 1130 */ 288, 366, 412, 48, 412, 31, 582, 367, 268, 269, + /* 1140 */ 412, 10, 270, 554, 412, 50, 564, 412, 51, 278, + /* 1150 */ 281, 282, 575, 144, 442, 403, 323, 226, 444, 461, + /* 1160 */ 464, 242, 503, 550, 561, 513, 161, 392, 400, 516, + /* 1170 */ 401, 345, 402, 7, 312, 83, 227, 332, 228, 82, + /* 1180 */ 330, 57, 408, 416, 168, 78, 459, 123, 210, 414, + /* 1190 */ 84, 335, 340, 299, 496, 500, 490, 229, 495, 243, + /* 1200 */ 104, 247, 499, 501, 230, 285, 415, 215, 514, 518, + /* 1210 */ 525, 526, 519, 236, 527, 473, 238, 352, 477, 286, + /* 1220 */ 182, 356, 533, 354, 119, 183, 185, 87, 546, 130, + /* 1230 */ 186, 535, 188, 140, 362, 191, 553, 216, 373, 374, + /* 1240 */ 131, 560, 308, 132, 133, 572, 577, 136, 263, 134, + /* 1250 */ 139, 536, 573, 391, 91, 94, 404, 574, 99, 214, + /* 1260 */ 102, 621, 622, 431, 164, 434, 165, 71, 141, 17, + /* 1270 */ 439, 448, 451, 155, 6, 452, 470, 110, 167, 453, + /* 1280 */ 457, 124, 13, 213, 120, 80, 12, 125, 159, 483, + /* 1290 */ 484, 85, 310, 105, 180, 251, 106, 118, 86, 107, + /* 1300 */ 241, 344, 349, 353, 143, 534, 127, 357, 171, 189, + /* 1310 */ 264, 108, 287, 128, 549, 129, 193, 537, 541, 14, + /* 1320 */ 195, 88, 196, 556, 197, 137, 138, 135, 15, 563, + /* 1330 */ 570, 109, 283, 146, 204, 383, 387, 899, 584, 899, + /* 1340 */ 899, 899, 899, 899, 89, +}; +static const YYCODETYPE yy_lookahead[] = { + /* 0 */ 16, 139, 140, 141, 168, 21, 144, 23, 69, 70, + /* 10 */ 71, 72, 176, 74, 75, 76, 77, 78, 79, 80, + /* 20 */ 81, 82, 83, 84, 78, 79, 42, 43, 73, 74, + /* 30 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + /* 40 */ 1, 2, 23, 58, 60, 61, 62, 63, 64, 65, + /* 50 */ 66, 67, 68, 69, 70, 71, 72, 147, 74, 75, + /* 60 */ 76, 77, 78, 79, 80, 81, 82, 83, 84, 16, + /* 70 */ 185, 186, 88, 88, 110, 22, 217, 92, 219, 220, + /* 80 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, + /* 90 */ 84, 217, 218, 219, 220, 42, 43, 238, 188, 46, + /* 100 */ 78, 79, 80, 81, 82, 83, 84, 88, 89, 124, + /* 110 */ 125, 126, 16, 60, 61, 62, 63, 64, 65, 66, + /* 120 */ 67, 68, 69, 70, 71, 72, 147, 74, 75, 76, + /* 130 */ 77, 78, 79, 80, 81, 82, 83, 84, 42, 43, + /* 140 */ 44, 80, 81, 82, 83, 84, 23, 84, 169, 170, + /* 150 */ 19, 164, 165, 166, 23, 169, 60, 61, 62, 63, + /* 160 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 169, + /* 170 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, + /* 180 */ 84, 16, 14, 147, 150, 147, 21, 167, 168, 58, + /* 190 */ 211, 147, 156, 157, 23, 216, 176, 23, 181, 176, + /* 200 */ 177, 78, 79, 165, 166, 110, 183, 42, 43, 78, + /* 210 */ 79, 88, 89, 169, 170, 228, 180, 181, 123, 88, + /* 220 */ 52, 98, 54, 92, 16, 60, 61, 62, 63, 64, + /* 230 */ 65, 66, 67, 68, 69, 70, 71, 72, 147, 74, + /* 240 */ 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + /* 250 */ 42, 43, 78, 209, 210, 124, 125, 126, 224, 88, + /* 260 */ 169, 170, 88, 89, 230, 227, 228, 16, 60, 61, + /* 270 */ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + /* 280 */ 72, 23, 74, 75, 76, 77, 78, 79, 80, 81, + /* 290 */ 82, 83, 84, 42, 43, 160, 16, 147, 161, 83, + /* 300 */ 84, 210, 161, 153, 169, 158, 156, 157, 161, 162, + /* 310 */ 163, 60, 61, 62, 63, 64, 65, 66, 67, 68, + /* 320 */ 69, 70, 71, 72, 161, 74, 75, 76, 77, 78, + /* 330 */ 79, 80, 81, 82, 83, 84, 192, 200, 147, 131, + /* 340 */ 16, 200, 16, 199, 20, 190, 88, 89, 90, 185, + /* 350 */ 186, 93, 94, 95, 217, 22, 219, 220, 147, 147, + /* 360 */ 169, 170, 104, 200, 84, 147, 42, 43, 156, 157, + /* 370 */ 90, 91, 92, 93, 94, 95, 96, 164, 165, 166, + /* 380 */ 169, 170, 131, 103, 60, 61, 62, 63, 64, 65, + /* 390 */ 66, 67, 68, 69, 70, 71, 72, 155, 74, 75, + /* 400 */ 76, 77, 78, 79, 80, 81, 82, 83, 84, 16, + /* 410 */ 84, 11, 221, 20, 30, 16, 147, 91, 92, 93, + /* 420 */ 94, 95, 96, 90, 147, 181, 93, 94, 95, 103, + /* 430 */ 212, 189, 155, 27, 50, 42, 43, 104, 169, 170, + /* 440 */ 34, 228, 43, 201, 202, 147, 169, 170, 206, 49, + /* 450 */ 161, 162, 163, 60, 61, 62, 63, 64, 65, 66, + /* 460 */ 67, 68, 69, 70, 71, 72, 189, 74, 75, 76, + /* 470 */ 77, 78, 79, 80, 81, 82, 83, 84, 16, 25, + /* 480 */ 211, 147, 20, 29, 12, 147, 102, 19, 211, 21, + /* 490 */ 147, 141, 147, 216, 144, 41, 24, 98, 20, 99, + /* 500 */ 100, 101, 103, 165, 42, 43, 0, 1, 2, 37, + /* 510 */ 110, 39, 169, 170, 169, 170, 182, 19, 20, 147, + /* 520 */ 22, 49, 60, 61, 62, 63, 64, 65, 66, 67, + /* 530 */ 68, 69, 70, 71, 72, 155, 74, 75, 76, 77, + /* 540 */ 78, 79, 80, 81, 82, 83, 84, 16, 147, 90, + /* 550 */ 20, 20, 93, 94, 95, 147, 155, 59, 215, 225, + /* 560 */ 215, 20, 130, 104, 132, 227, 228, 42, 43, 189, + /* 570 */ 169, 170, 16, 42, 43, 20, 19, 22, 19, 20, + /* 580 */ 23, 22, 18, 147, 106, 147, 108, 109, 63, 64, + /* 590 */ 189, 60, 61, 62, 63, 64, 65, 66, 67, 68, + /* 600 */ 69, 70, 71, 72, 186, 74, 75, 76, 77, 78, + /* 610 */ 79, 80, 81, 82, 83, 84, 16, 92, 59, 55, + /* 620 */ 212, 21, 147, 19, 147, 23, 188, 23, 12, 217, + /* 630 */ 23, 219, 220, 7, 8, 9, 106, 147, 108, 109, + /* 640 */ 24, 147, 42, 43, 208, 88, 89, 106, 92, 108, + /* 650 */ 109, 244, 245, 37, 145, 39, 191, 182, 94, 16, + /* 660 */ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + /* 670 */ 70, 71, 72, 147, 74, 75, 76, 77, 78, 79, + /* 680 */ 80, 81, 82, 83, 84, 42, 43, 80, 142, 143, + /* 690 */ 88, 89, 88, 89, 148, 88, 89, 133, 14, 147, + /* 700 */ 225, 155, 16, 60, 61, 62, 63, 64, 65, 66, + /* 710 */ 67, 68, 69, 70, 71, 72, 114, 74, 75, 76, + /* 720 */ 77, 78, 79, 80, 81, 82, 83, 84, 42, 43, + /* 730 */ 201, 202, 147, 147, 182, 189, 52, 147, 54, 147, + /* 740 */ 147, 147, 147, 147, 155, 16, 60, 61, 62, 63, + /* 750 */ 64, 65, 66, 67, 68, 69, 70, 71, 72, 213, + /* 760 */ 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, + /* 770 */ 84, 42, 43, 188, 188, 182, 182, 225, 189, 106, + /* 780 */ 188, 108, 109, 188, 99, 100, 101, 241, 16, 155, + /* 790 */ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + /* 800 */ 71, 72, 213, 74, 75, 76, 77, 78, 79, 80, + /* 810 */ 81, 82, 83, 84, 42, 43, 23, 133, 225, 225, + /* 820 */ 21, 225, 23, 189, 239, 236, 99, 100, 101, 22, + /* 830 */ 242, 243, 155, 22, 62, 63, 64, 65, 66, 67, + /* 840 */ 68, 69, 70, 71, 72, 147, 74, 75, 76, 77, + /* 850 */ 78, 79, 80, 81, 82, 83, 84, 16, 17, 43, + /* 860 */ 19, 147, 147, 147, 23, 147, 189, 169, 170, 147, + /* 870 */ 147, 147, 31, 16, 17, 147, 19, 147, 124, 125, + /* 880 */ 23, 88, 89, 169, 170, 169, 170, 88, 31, 48, + /* 890 */ 147, 169, 170, 169, 170, 147, 89, 169, 170, 58, + /* 900 */ 147, 22, 147, 188, 147, 48, 188, 114, 97, 147, + /* 910 */ 147, 188, 147, 19, 98, 58, 147, 169, 170, 78, + /* 920 */ 79, 114, 169, 170, 169, 170, 169, 170, 87, 88, + /* 930 */ 89, 169, 170, 92, 161, 78, 79, 80, 169, 170, + /* 940 */ 91, 147, 155, 22, 87, 88, 89, 16, 17, 92, + /* 950 */ 19, 110, 147, 155, 23, 147, 7, 8, 20, 110, + /* 960 */ 22, 80, 31, 169, 170, 124, 125, 126, 127, 128, + /* 970 */ 129, 208, 123, 208, 169, 170, 189, 169, 170, 48, + /* 980 */ 147, 124, 125, 126, 127, 128, 129, 189, 107, 58, + /* 990 */ 107, 5, 111, 147, 111, 203, 10, 11, 12, 13, + /* 1000 */ 121, 147, 147, 91, 92, 147, 112, 147, 147, 78, + /* 1010 */ 79, 147, 26, 19, 28, 169, 170, 23, 87, 88, + /* 1020 */ 89, 35, 147, 92, 169, 170, 178, 169, 170, 147, + /* 1030 */ 169, 170, 147, 47, 113, 49, 92, 178, 147, 53, + /* 1040 */ 147, 178, 56, 147, 169, 170, 147, 103, 147, 19, + /* 1050 */ 147, 169, 170, 147, 147, 124, 125, 126, 127, 128, + /* 1060 */ 129, 147, 169, 170, 147, 169, 170, 147, 169, 170, + /* 1070 */ 169, 170, 169, 170, 147, 169, 170, 147, 20, 147, + /* 1080 */ 22, 147, 88, 147, 232, 99, 100, 101, 147, 169, + /* 1090 */ 170, 105, 147, 20, 147, 22, 110, 20, 68, 169, + /* 1100 */ 170, 169, 170, 169, 170, 169, 170, 20, 147, 22, + /* 1110 */ 147, 20, 147, 22, 169, 170, 169, 170, 147, 233, + /* 1120 */ 134, 20, 147, 22, 20, 147, 22, 20, 20, 22, + /* 1130 */ 22, 147, 169, 170, 169, 170, 59, 147, 147, 147, + /* 1140 */ 169, 170, 147, 147, 169, 170, 147, 169, 170, 147, + /* 1150 */ 147, 147, 147, 191, 229, 149, 223, 193, 229, 172, + /* 1160 */ 172, 172, 177, 194, 194, 172, 6, 146, 146, 172, + /* 1170 */ 146, 173, 146, 22, 154, 121, 194, 118, 195, 119, + /* 1180 */ 116, 120, 23, 160, 112, 130, 152, 152, 222, 189, + /* 1190 */ 98, 115, 98, 40, 179, 97, 171, 196, 171, 171, + /* 1200 */ 19, 84, 173, 171, 197, 174, 198, 226, 160, 160, + /* 1210 */ 171, 171, 179, 204, 171, 205, 204, 15, 205, 174, + /* 1220 */ 151, 38, 152, 152, 60, 151, 151, 130, 184, 19, + /* 1230 */ 152, 152, 151, 214, 152, 184, 194, 226, 152, 15, + /* 1240 */ 187, 194, 152, 187, 187, 33, 137, 184, 234, 187, + /* 1250 */ 214, 235, 152, 1, 237, 237, 20, 152, 159, 175, + /* 1260 */ 175, 112, 112, 92, 112, 107, 112, 19, 19, 231, + /* 1270 */ 20, 20, 11, 19, 117, 20, 114, 240, 22, 20, + /* 1280 */ 20, 19, 117, 44, 243, 22, 22, 20, 112, 20, + /* 1290 */ 20, 19, 246, 19, 96, 20, 19, 32, 19, 19, + /* 1300 */ 103, 44, 44, 16, 21, 17, 98, 36, 22, 98, + /* 1310 */ 133, 19, 5, 45, 1, 102, 122, 51, 45, 19, + /* 1320 */ 113, 68, 14, 17, 115, 102, 122, 113, 19, 123, + /* 1330 */ 20, 14, 136, 19, 135, 57, 3, 247, 4, 247, + /* 1340 */ 247, 247, 247, 247, 68, +}; +#define YY_SHIFT_USE_DFLT (-62) +#define YY_SHIFT_MAX 387 +static const short yy_shift_ofst[] = { + /* 0 */ 39, 841, 986, -16, 841, 931, 931, 258, 123, -36, + /* 10 */ 96, 931, 931, 931, 931, 931, -45, 400, 174, 19, + /* 20 */ 171, -54, -54, 53, 165, 208, 251, 324, 393, 462, + /* 30 */ 531, 600, 643, 686, 643, 643, 643, 643, 643, 643, + /* 40 */ 643, 643, 643, 643, 643, 643, 643, 643, 643, 643, + /* 50 */ 643, 643, 729, 772, 772, 857, 931, 931, 931, 931, + /* 60 */ 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, + /* 70 */ 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, + /* 80 */ 931, 931, 931, 931, 931, 931, 931, 931, 931, 931, + /* 90 */ 931, 931, 931, 931, 931, -61, -61, 6, 6, 280, + /* 100 */ 22, 61, 399, 564, 19, 19, 19, 19, 19, 19, + /* 110 */ 19, 216, 171, 63, -62, -62, 131, 326, 472, 472, + /* 120 */ 498, 559, 506, 799, 19, 799, 19, 19, 19, 19, + /* 130 */ 19, 19, 19, 19, 19, 19, 19, 19, 19, 849, + /* 140 */ 95, -36, -36, -36, -62, -62, -62, -15, -15, 333, + /* 150 */ 459, 478, 557, 530, 541, 616, 602, 793, 604, 607, + /* 160 */ 626, 19, 19, 881, 19, 19, 994, 19, 19, 807, + /* 170 */ 19, 19, 673, 807, 19, 19, 384, 384, 384, 19, + /* 180 */ 19, 673, 19, 19, 673, 19, 454, 685, 19, 19, + /* 190 */ 673, 19, 19, 19, 673, 19, 19, 19, 673, 673, + /* 200 */ 19, 19, 19, 19, 19, 468, 883, 921, 754, 754, + /* 210 */ 432, 406, 406, 406, 816, 406, 406, 811, 879, 879, + /* 220 */ 1160, 1160, 1160, 1160, 1151, -36, 1054, 1059, 1060, 1064, + /* 230 */ 1061, 1159, 1055, 1072, 1072, 1092, 1076, 1092, 1076, 1094, + /* 240 */ 1094, 1153, 1094, 1098, 1094, 1181, 1117, 1159, 1117, 1159, + /* 250 */ 1153, 1094, 1094, 1094, 1181, 1202, 1072, 1202, 1072, 1202, + /* 260 */ 1072, 1072, 1183, 1097, 1202, 1072, 1164, 1164, 1210, 1054, + /* 270 */ 1072, 1224, 1224, 1224, 1224, 1054, 1164, 1210, 1072, 1212, + /* 280 */ 1212, 1072, 1072, 1109, -62, -62, -62, -62, -62, -62, + /* 290 */ 525, 684, 727, 168, 894, 556, 555, 938, 944, 949, + /* 300 */ 912, 1058, 1073, 1087, 1091, 1101, 1104, 1107, 1030, 1108, + /* 310 */ 1077, 1252, 1236, 1149, 1150, 1152, 1154, 1171, 1158, 1248, + /* 320 */ 1250, 1251, 1249, 1261, 1254, 1255, 1256, 1259, 1260, 1263, + /* 330 */ 1157, 1264, 1165, 1263, 1162, 1262, 1267, 1176, 1269, 1270, + /* 340 */ 1265, 1239, 1272, 1257, 1274, 1275, 1277, 1279, 1258, 1280, + /* 350 */ 1198, 1197, 1287, 1288, 1283, 1208, 1271, 1266, 1268, 1286, + /* 360 */ 1273, 1177, 1211, 1292, 1307, 1313, 1213, 1253, 1276, 1194, + /* 370 */ 1300, 1207, 1308, 1209, 1306, 1214, 1223, 1204, 1309, 1206, + /* 380 */ 1310, 1317, 1278, 1199, 1196, 1314, 1333, 1334, +}; +#define YY_REDUCE_USE_DFLT (-165) +#define YY_REDUCE_MAX 289 +static const short yy_reduce_ofst[] = { + /* 0 */ -138, 277, 546, 137, 401, -21, 44, 36, 38, 242, + /* 10 */ -141, 191, 91, 269, 343, 345, -126, 589, 338, 150, + /* 20 */ 147, -13, 213, 412, 412, 412, 412, 412, 412, 412, + /* 30 */ 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + /* 40 */ 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, + /* 50 */ 412, 412, 412, 412, 412, 211, 698, 714, 716, 722, + /* 60 */ 724, 728, 748, 753, 755, 757, 762, 769, 794, 805, + /* 70 */ 808, 846, 855, 858, 861, 875, 882, 893, 896, 899, + /* 80 */ 901, 903, 906, 920, 930, 932, 934, 936, 945, 947, + /* 90 */ 963, 965, 971, 975, 978, 412, 412, 412, 412, 20, + /* 100 */ 412, 412, 23, 34, 334, 475, 552, 593, 594, 585, + /* 110 */ 212, 412, 289, 412, 412, 412, 135, -164, -115, 164, + /* 120 */ 407, 407, 350, 141, 436, 163, 596, -90, 763, 218, + /* 130 */ 765, 438, 586, 592, 595, 715, 718, 408, 723, 380, + /* 140 */ 634, 677, 787, 798, 144, 529, 588, -14, 0, 17, + /* 150 */ 244, 155, 298, 155, 155, 418, 372, 477, 490, 494, + /* 160 */ 509, 526, 590, 465, 494, 730, 773, 743, 833, 792, + /* 170 */ 854, 860, 155, 792, 864, 885, 848, 859, 863, 891, + /* 180 */ 907, 155, 914, 917, 155, 927, 852, 886, 941, 961, + /* 190 */ 155, 984, 990, 991, 155, 992, 995, 996, 155, 155, + /* 200 */ 999, 1002, 1003, 1004, 1005, 1006, 962, 964, 925, 929, + /* 210 */ 933, 987, 988, 989, 985, 993, 997, 998, 969, 970, + /* 220 */ 1021, 1022, 1024, 1026, 1020, 1000, 982, 983, 1001, 1007, + /* 230 */ 1008, 1023, 966, 1034, 1035, 1009, 1010, 1012, 1013, 1025, + /* 240 */ 1027, 1015, 1028, 1029, 1032, 1031, 981, 1048, 1011, 1049, + /* 250 */ 1033, 1039, 1040, 1043, 1045, 1069, 1070, 1074, 1071, 1075, + /* 260 */ 1078, 1079, 1014, 1016, 1081, 1082, 1044, 1051, 1019, 1042, + /* 270 */ 1086, 1053, 1056, 1057, 1062, 1047, 1063, 1036, 1090, 1017, + /* 280 */ 1018, 1100, 1105, 1037, 1099, 1084, 1085, 1038, 1041, 1046, +}; +static const YYACTIONTYPE yy_default[] = { + /* 0 */ 592, 816, 897, 707, 897, 816, 897, 897, 843, 711, + /* 10 */ 872, 814, 897, 897, 897, 897, 789, 897, 843, 897, + /* 20 */ 623, 843, 843, 740, 897, 897, 897, 897, 897, 897, + /* 30 */ 897, 897, 741, 897, 818, 813, 809, 811, 810, 817, + /* 40 */ 742, 731, 738, 745, 723, 856, 747, 748, 754, 755, + /* 50 */ 873, 871, 777, 776, 795, 897, 897, 897, 897, 897, + /* 60 */ 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, + /* 70 */ 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, + /* 80 */ 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, + /* 90 */ 897, 897, 897, 897, 897, 779, 800, 778, 788, 616, + /* 100 */ 780, 781, 676, 611, 897, 897, 897, 897, 897, 897, + /* 110 */ 897, 782, 897, 783, 796, 797, 897, 897, 897, 897, + /* 120 */ 897, 897, 592, 707, 897, 707, 897, 897, 897, 897, + /* 130 */ 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, + /* 140 */ 897, 897, 897, 897, 701, 711, 890, 897, 897, 667, + /* 150 */ 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, + /* 160 */ 599, 597, 897, 699, 897, 897, 625, 897, 897, 709, + /* 170 */ 897, 897, 714, 715, 897, 897, 897, 897, 897, 897, + /* 180 */ 897, 613, 897, 897, 688, 897, 849, 897, 897, 897, + /* 190 */ 863, 897, 897, 897, 861, 897, 897, 897, 690, 750, + /* 200 */ 830, 897, 876, 878, 897, 897, 699, 708, 897, 897, + /* 210 */ 812, 734, 734, 734, 646, 734, 734, 649, 744, 744, + /* 220 */ 596, 596, 596, 596, 666, 897, 744, 735, 737, 727, + /* 230 */ 739, 897, 897, 716, 716, 724, 726, 724, 726, 678, + /* 240 */ 678, 663, 678, 649, 678, 822, 827, 897, 827, 897, + /* 250 */ 663, 678, 678, 678, 822, 608, 716, 608, 716, 608, + /* 260 */ 716, 716, 853, 855, 608, 716, 680, 680, 756, 744, + /* 270 */ 716, 687, 687, 687, 687, 744, 680, 756, 716, 875, + /* 280 */ 875, 716, 716, 883, 633, 651, 651, 858, 890, 895, + /* 290 */ 897, 897, 897, 897, 763, 897, 897, 897, 897, 897, + /* 300 */ 897, 897, 897, 897, 897, 897, 897, 897, 836, 897, + /* 310 */ 897, 897, 897, 768, 764, 897, 765, 897, 693, 897, + /* 320 */ 897, 897, 897, 897, 897, 897, 897, 897, 897, 815, + /* 330 */ 897, 728, 897, 736, 897, 897, 897, 897, 897, 897, + /* 340 */ 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, + /* 350 */ 897, 897, 897, 897, 897, 897, 897, 897, 851, 852, + /* 360 */ 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, + /* 370 */ 897, 897, 897, 897, 897, 897, 897, 897, 897, 897, + /* 380 */ 897, 897, 882, 897, 897, 885, 593, 897, 587, 590, + /* 390 */ 589, 591, 595, 598, 620, 621, 622, 600, 601, 602, + /* 400 */ 603, 604, 605, 606, 612, 614, 632, 634, 618, 636, + /* 410 */ 697, 698, 760, 691, 692, 696, 771, 762, 766, 767, + /* 420 */ 769, 770, 784, 785, 787, 793, 799, 802, 786, 791, + /* 430 */ 792, 794, 798, 801, 694, 695, 805, 619, 626, 627, + /* 440 */ 630, 631, 839, 841, 840, 842, 629, 628, 772, 775, + /* 450 */ 807, 808, 864, 865, 866, 867, 868, 803, 717, 806, + /* 460 */ 790, 729, 732, 733, 730, 700, 710, 719, 720, 721, + /* 470 */ 722, 705, 706, 712, 725, 758, 759, 713, 702, 703, + /* 480 */ 704, 804, 761, 773, 774, 637, 638, 768, 639, 640, + /* 490 */ 641, 679, 682, 683, 684, 642, 661, 664, 665, 643, + /* 500 */ 650, 644, 645, 652, 653, 654, 657, 658, 659, 660, + /* 510 */ 655, 656, 823, 824, 828, 826, 825, 647, 648, 662, + /* 520 */ 635, 624, 617, 668, 671, 672, 673, 674, 675, 677, + /* 530 */ 669, 670, 615, 607, 609, 718, 845, 854, 850, 846, + /* 540 */ 847, 848, 610, 819, 820, 681, 752, 753, 844, 857, + /* 550 */ 859, 757, 860, 862, 887, 685, 686, 689, 829, 869, + /* 560 */ 743, 746, 749, 751, 831, 832, 833, 834, 837, 838, + /* 570 */ 835, 870, 874, 877, 879, 880, 881, 884, 886, 891, + /* 580 */ 892, 893, 896, 894, 594, 588, +}; +#define YY_SZ_ACTTAB (int)(sizeof(yy_action)/sizeof(yy_action[0])) + +/* The next table maps tokens into fallback tokens. If a construct +** like the following: +** +** %fallback ID X Y Z. +** +** appears in the grammer, then ID becomes a fallback token for X, Y, +** and Z. Whenever one of the tokens X, Y, or Z is input to the parser +** but it does not parse, the type of the token is changed to ID and +** the parse is retried before an error is thrown. +*/ +#ifdef YYFALLBACK +static const YYCODETYPE yyFallback[] = { + 0, /* $ => nothing */ + 0, /* SEMI => nothing */ + 23, /* EXPLAIN => ID */ + 23, /* QUERY => ID */ + 23, /* PLAN => ID */ + 23, /* BEGIN => ID */ + 0, /* TRANSACTION => nothing */ + 23, /* DEFERRED => ID */ + 23, /* IMMEDIATE => ID */ + 23, /* EXCLUSIVE => ID */ + 0, /* COMMIT => nothing */ + 23, /* END => ID */ + 0, /* ROLLBACK => nothing */ + 0, /* CREATE => nothing */ + 0, /* TABLE => nothing */ + 23, /* IF => ID */ + 0, /* NOT => nothing */ + 0, /* EXISTS => nothing */ + 23, /* TEMP => ID */ + 0, /* LP => nothing */ + 0, /* RP => nothing */ + 0, /* AS => nothing */ + 0, /* COMMA => nothing */ + 0, /* ID => nothing */ + 23, /* ABORT => ID */ + 23, /* AFTER => ID */ + 23, /* ANALYZE => ID */ + 23, /* ASC => ID */ + 23, /* ATTACH => ID */ + 23, /* BEFORE => ID */ + 23, /* CASCADE => ID */ + 23, /* CAST => ID */ + 23, /* CONFLICT => ID */ + 23, /* DATABASE => ID */ + 23, /* DESC => ID */ + 23, /* DETACH => ID */ + 23, /* EACH => ID */ + 23, /* FAIL => ID */ + 23, /* FOR => ID */ + 23, /* IGNORE => ID */ + 23, /* INITIALLY => ID */ + 23, /* INSTEAD => ID */ + 23, /* LIKE_KW => ID */ + 23, /* MATCH => ID */ + 23, /* KEY => ID */ + 23, /* OF => ID */ + 23, /* OFFSET => ID */ + 23, /* PRAGMA => ID */ + 23, /* RAISE => ID */ + 23, /* REPLACE => ID */ + 23, /* RESTRICT => ID */ + 23, /* ROW => ID */ + 23, /* TRIGGER => ID */ + 23, /* VACUUM => ID */ + 23, /* VIEW => ID */ + 23, /* VIRTUAL => ID */ + 23, /* REINDEX => ID */ + 23, /* RENAME => ID */ + 23, /* CTIME_KW => ID */ + 0, /* ANY => nothing */ + 0, /* OR => nothing */ + 0, /* AND => nothing */ + 0, /* IS => nothing */ + 0, /* BETWEEN => nothing */ + 0, /* IN => nothing */ + 0, /* ISNULL => nothing */ + 0, /* NOTNULL => nothing */ + 0, /* NE => nothing */ + 0, /* EQ => nothing */ + 0, /* GT => nothing */ + 0, /* LE => nothing */ + 0, /* LT => nothing */ + 0, /* GE => nothing */ + 0, /* ESCAPE => nothing */ + 0, /* BITAND => nothing */ + 0, /* BITOR => nothing */ + 0, /* LSHIFT => nothing */ + 0, /* RSHIFT => nothing */ + 0, /* PLUS => nothing */ + 0, /* MINUS => nothing */ + 0, /* STAR => nothing */ + 0, /* SLASH => nothing */ + 0, /* REM => nothing */ + 0, /* CONCAT => nothing */ + 0, /* COLLATE => nothing */ + 0, /* UMINUS => nothing */ + 0, /* UPLUS => nothing */ + 0, /* BITNOT => nothing */ + 0, /* STRING => nothing */ + 0, /* JOIN_KW => nothing */ + 0, /* CONSTRAINT => nothing */ + 0, /* DEFAULT => nothing */ + 0, /* NULL => nothing */ + 0, /* PRIMARY => nothing */ + 0, /* UNIQUE => nothing */ + 0, /* CHECK => nothing */ + 0, /* REFERENCES => nothing */ + 0, /* AUTOINCR => nothing */ + 0, /* ON => nothing */ + 0, /* DELETE => nothing */ + 0, /* UPDATE => nothing */ + 0, /* INSERT => nothing */ + 0, /* SET => nothing */ + 0, /* DEFERRABLE => nothing */ + 0, /* FOREIGN => nothing */ + 0, /* DROP => nothing */ + 0, /* UNION => nothing */ + 0, /* ALL => nothing */ + 0, /* EXCEPT => nothing */ + 0, /* INTERSECT => nothing */ + 0, /* SELECT => nothing */ + 0, /* DISTINCT => nothing */ + 0, /* DOT => nothing */ + 0, /* FROM => nothing */ + 0, /* JOIN => nothing */ + 0, /* USING => nothing */ + 0, /* ORDER => nothing */ + 0, /* BY => nothing */ + 0, /* GROUP => nothing */ + 0, /* HAVING => nothing */ + 0, /* LIMIT => nothing */ + 0, /* WHERE => nothing */ + 0, /* INTO => nothing */ + 0, /* VALUES => nothing */ + 0, /* INTEGER => nothing */ + 0, /* FLOAT => nothing */ + 0, /* BLOB => nothing */ + 0, /* REGISTER => nothing */ + 0, /* VARIABLE => nothing */ + 0, /* CASE => nothing */ + 0, /* WHEN => nothing */ + 0, /* THEN => nothing */ + 0, /* ELSE => nothing */ + 0, /* INDEX => nothing */ + 0, /* ALTER => nothing */ + 0, /* TO => nothing */ + 0, /* ADD => nothing */ + 0, /* COLUMNKW => nothing */ +}; +#endif /* YYFALLBACK */ + +/* The following structure represents a single element of the +** parser's stack. Information stored includes: +** +** + The state number for the parser at this level of the stack. +** +** + The value of the token stored at this level of the stack. +** (In other words, the "major" token.) +** +** + The semantic value stored at this level of the stack. This is +** the information used by the action routines in the grammar. +** It is sometimes called the "minor" token. +*/ +struct yyStackEntry { + int stateno; /* The state-number */ + int major; /* The major token value. This is the code + ** number for the token at this stack level */ + YYMINORTYPE minor; /* The user-supplied minor token value. This + ** is the value of the token */ +}; +typedef struct yyStackEntry yyStackEntry; + +/* The state of the parser is completely contained in an instance of +** the following structure */ +struct yyParser { + int yyidx; /* Index of top element in stack */ + int yyerrcnt; /* Shifts left before out of the error */ + sqlite3ParserARG_SDECL /* A place to hold %extra_argument */ +#if YYSTACKDEPTH<=0 + int yystksz; /* Current side of the stack */ + yyStackEntry *yystack; /* The parser's stack */ +#else + yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */ +#endif +}; +typedef struct yyParser yyParser; + +#ifndef NDEBUG +#include +static FILE *yyTraceFILE = 0; +static char *yyTracePrompt = 0; +#endif /* NDEBUG */ + +#ifndef NDEBUG +/* +** Turn parser tracing on by giving a stream to which to write the trace +** and a prompt to preface each trace message. Tracing is turned off +** by making either argument NULL +** +** Inputs: +**
    +**
  • A FILE* to which trace output should be written. +** If NULL, then tracing is turned off. +**
  • A prefix string written at the beginning of every +** line of trace output. If NULL, then tracing is +** turned off. +**
+** +** Outputs: +** None. +*/ +void sqlite3ParserTrace(FILE *TraceFILE, char *zTracePrompt){ + yyTraceFILE = TraceFILE; + yyTracePrompt = zTracePrompt; + if( yyTraceFILE==0 ) yyTracePrompt = 0; + else if( yyTracePrompt==0 ) yyTraceFILE = 0; +} +#endif /* NDEBUG */ + +#ifndef NDEBUG +/* For tracing shifts, the names of all terminals and nonterminals +** are required. The following table supplies these names */ +static const char *const yyTokenName[] = { + "$", "SEMI", "EXPLAIN", "QUERY", + "PLAN", "BEGIN", "TRANSACTION", "DEFERRED", + "IMMEDIATE", "EXCLUSIVE", "COMMIT", "END", + "ROLLBACK", "CREATE", "TABLE", "IF", + "NOT", "EXISTS", "TEMP", "LP", + "RP", "AS", "COMMA", "ID", + "ABORT", "AFTER", "ANALYZE", "ASC", + "ATTACH", "BEFORE", "CASCADE", "CAST", + "CONFLICT", "DATABASE", "DESC", "DETACH", + "EACH", "FAIL", "FOR", "IGNORE", + "INITIALLY", "INSTEAD", "LIKE_KW", "MATCH", + "KEY", "OF", "OFFSET", "PRAGMA", + "RAISE", "REPLACE", "RESTRICT", "ROW", + "TRIGGER", "VACUUM", "VIEW", "VIRTUAL", + "REINDEX", "RENAME", "CTIME_KW", "ANY", + "OR", "AND", "IS", "BETWEEN", + "IN", "ISNULL", "NOTNULL", "NE", + "EQ", "GT", "LE", "LT", + "GE", "ESCAPE", "BITAND", "BITOR", + "LSHIFT", "RSHIFT", "PLUS", "MINUS", + "STAR", "SLASH", "REM", "CONCAT", + "COLLATE", "UMINUS", "UPLUS", "BITNOT", + "STRING", "JOIN_KW", "CONSTRAINT", "DEFAULT", + "NULL", "PRIMARY", "UNIQUE", "CHECK", + "REFERENCES", "AUTOINCR", "ON", "DELETE", + "UPDATE", "INSERT", "SET", "DEFERRABLE", + "FOREIGN", "DROP", "UNION", "ALL", + "EXCEPT", "INTERSECT", "SELECT", "DISTINCT", + "DOT", "FROM", "JOIN", "USING", + "ORDER", "BY", "GROUP", "HAVING", + "LIMIT", "WHERE", "INTO", "VALUES", + "INTEGER", "FLOAT", "BLOB", "REGISTER", + "VARIABLE", "CASE", "WHEN", "THEN", + "ELSE", "INDEX", "ALTER", "TO", + "ADD", "COLUMNKW", "error", "input", + "cmdlist", "ecmd", "cmdx", "cmd", + "explain", "transtype", "trans_opt", "nm", + "create_table", "create_table_args", "temp", "ifnotexists", + "dbnm", "columnlist", "conslist_opt", "select", + "column", "columnid", "type", "carglist", + "id", "ids", "typetoken", "typename", + "signed", "plus_num", "minus_num", "carg", + "ccons", "term", "expr", "onconf", + "sortorder", "autoinc", "idxlist_opt", "refargs", + "defer_subclause", "refarg", "refact", "init_deferred_pred_opt", + "conslist", "tcons", "idxlist", "defer_subclause_opt", + "orconf", "resolvetype", "raisetype", "ifexists", + "fullname", "oneselect", "multiselect_op", "distinct", + "selcollist", "from", "where_opt", "groupby_opt", + "having_opt", "orderby_opt", "limit_opt", "sclp", + "as", "seltablist", "stl_prefix", "joinop", + "on_opt", "using_opt", "seltablist_paren", "joinop2", + "inscollist", "sortlist", "sortitem", "nexprlist", + "setlist", "insert_cmd", "inscollist_opt", "itemlist", + "exprlist", "likeop", "escape", "between_op", + "in_op", "case_operand", "case_exprlist", "case_else", + "uniqueflag", "idxitem", "collate", "nmnum", + "plus_opt", "number", "trigger_decl", "trigger_cmd_list", + "trigger_time", "trigger_event", "foreach_clause", "when_clause", + "trigger_cmd", "database_kw_opt", "key_opt", "add_column_fullname", + "kwcolumn_opt", "create_vtab", "vtabarglist", "vtabarg", + "vtabargtoken", "lp", "anylist", +}; +#endif /* NDEBUG */ + +#ifndef NDEBUG +/* For tracing reduce actions, the names of all rules are required. +*/ +static const char *const yyRuleName[] = { + /* 0 */ "input ::= cmdlist", + /* 1 */ "cmdlist ::= cmdlist ecmd", + /* 2 */ "cmdlist ::= ecmd", + /* 3 */ "cmdx ::= cmd", + /* 4 */ "ecmd ::= SEMI", + /* 5 */ "ecmd ::= explain cmdx SEMI", + /* 6 */ "explain ::=", + /* 7 */ "explain ::= EXPLAIN", + /* 8 */ "explain ::= EXPLAIN QUERY PLAN", + /* 9 */ "cmd ::= BEGIN transtype trans_opt", + /* 10 */ "trans_opt ::=", + /* 11 */ "trans_opt ::= TRANSACTION", + /* 12 */ "trans_opt ::= TRANSACTION nm", + /* 13 */ "transtype ::=", + /* 14 */ "transtype ::= DEFERRED", + /* 15 */ "transtype ::= IMMEDIATE", + /* 16 */ "transtype ::= EXCLUSIVE", + /* 17 */ "cmd ::= COMMIT trans_opt", + /* 18 */ "cmd ::= END trans_opt", + /* 19 */ "cmd ::= ROLLBACK trans_opt", + /* 20 */ "cmd ::= create_table create_table_args", + /* 21 */ "create_table ::= CREATE temp TABLE ifnotexists nm dbnm", + /* 22 */ "ifnotexists ::=", + /* 23 */ "ifnotexists ::= IF NOT EXISTS", + /* 24 */ "temp ::= TEMP", + /* 25 */ "temp ::=", + /* 26 */ "create_table_args ::= LP columnlist conslist_opt RP", + /* 27 */ "create_table_args ::= AS select", + /* 28 */ "columnlist ::= columnlist COMMA column", + /* 29 */ "columnlist ::= column", + /* 30 */ "column ::= columnid type carglist", + /* 31 */ "columnid ::= nm", + /* 32 */ "id ::= ID", + /* 33 */ "ids ::= ID|STRING", + /* 34 */ "nm ::= ID", + /* 35 */ "nm ::= STRING", + /* 36 */ "nm ::= JOIN_KW", + /* 37 */ "type ::=", + /* 38 */ "type ::= typetoken", + /* 39 */ "typetoken ::= typename", + /* 40 */ "typetoken ::= typename LP signed RP", + /* 41 */ "typetoken ::= typename LP signed COMMA signed RP", + /* 42 */ "typename ::= ids", + /* 43 */ "typename ::= typename ids", + /* 44 */ "signed ::= plus_num", + /* 45 */ "signed ::= minus_num", + /* 46 */ "carglist ::= carglist carg", + /* 47 */ "carglist ::=", + /* 48 */ "carg ::= CONSTRAINT nm ccons", + /* 49 */ "carg ::= ccons", + /* 50 */ "ccons ::= DEFAULT term", + /* 51 */ "ccons ::= DEFAULT LP expr RP", + /* 52 */ "ccons ::= DEFAULT PLUS term", + /* 53 */ "ccons ::= DEFAULT MINUS term", + /* 54 */ "ccons ::= DEFAULT id", + /* 55 */ "ccons ::= NULL onconf", + /* 56 */ "ccons ::= NOT NULL onconf", + /* 57 */ "ccons ::= PRIMARY KEY sortorder onconf autoinc", + /* 58 */ "ccons ::= UNIQUE onconf", + /* 59 */ "ccons ::= CHECK LP expr RP", + /* 60 */ "ccons ::= REFERENCES nm idxlist_opt refargs", + /* 61 */ "ccons ::= defer_subclause", + /* 62 */ "ccons ::= COLLATE id", + /* 63 */ "autoinc ::=", + /* 64 */ "autoinc ::= AUTOINCR", + /* 65 */ "refargs ::=", + /* 66 */ "refargs ::= refargs refarg", + /* 67 */ "refarg ::= MATCH nm", + /* 68 */ "refarg ::= ON DELETE refact", + /* 69 */ "refarg ::= ON UPDATE refact", + /* 70 */ "refarg ::= ON INSERT refact", + /* 71 */ "refact ::= SET NULL", + /* 72 */ "refact ::= SET DEFAULT", + /* 73 */ "refact ::= CASCADE", + /* 74 */ "refact ::= RESTRICT", + /* 75 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt", + /* 76 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt", + /* 77 */ "init_deferred_pred_opt ::=", + /* 78 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED", + /* 79 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE", + /* 80 */ "conslist_opt ::=", + /* 81 */ "conslist_opt ::= COMMA conslist", + /* 82 */ "conslist ::= conslist COMMA tcons", + /* 83 */ "conslist ::= conslist tcons", + /* 84 */ "conslist ::= tcons", + /* 85 */ "tcons ::= CONSTRAINT nm", + /* 86 */ "tcons ::= PRIMARY KEY LP idxlist autoinc RP onconf", + /* 87 */ "tcons ::= UNIQUE LP idxlist RP onconf", + /* 88 */ "tcons ::= CHECK LP expr RP onconf", + /* 89 */ "tcons ::= FOREIGN KEY LP idxlist RP REFERENCES nm idxlist_opt refargs defer_subclause_opt", + /* 90 */ "defer_subclause_opt ::=", + /* 91 */ "defer_subclause_opt ::= defer_subclause", + /* 92 */ "onconf ::=", + /* 93 */ "onconf ::= ON CONFLICT resolvetype", + /* 94 */ "orconf ::=", + /* 95 */ "orconf ::= OR resolvetype", + /* 96 */ "resolvetype ::= raisetype", + /* 97 */ "resolvetype ::= IGNORE", + /* 98 */ "resolvetype ::= REPLACE", + /* 99 */ "cmd ::= DROP TABLE ifexists fullname", + /* 100 */ "ifexists ::= IF EXISTS", + /* 101 */ "ifexists ::=", + /* 102 */ "cmd ::= CREATE temp VIEW ifnotexists nm dbnm AS select", + /* 103 */ "cmd ::= DROP VIEW ifexists fullname", + /* 104 */ "cmd ::= select", + /* 105 */ "select ::= oneselect", + /* 106 */ "select ::= select multiselect_op oneselect", + /* 107 */ "multiselect_op ::= UNION", + /* 108 */ "multiselect_op ::= UNION ALL", + /* 109 */ "multiselect_op ::= EXCEPT|INTERSECT", + /* 110 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt", + /* 111 */ "distinct ::= DISTINCT", + /* 112 */ "distinct ::= ALL", + /* 113 */ "distinct ::=", + /* 114 */ "sclp ::= selcollist COMMA", + /* 115 */ "sclp ::=", + /* 116 */ "selcollist ::= sclp expr as", + /* 117 */ "selcollist ::= sclp STAR", + /* 118 */ "selcollist ::= sclp nm DOT STAR", + /* 119 */ "as ::= AS nm", + /* 120 */ "as ::= ids", + /* 121 */ "as ::=", + /* 122 */ "from ::=", + /* 123 */ "from ::= FROM seltablist", + /* 124 */ "stl_prefix ::= seltablist joinop", + /* 125 */ "stl_prefix ::=", + /* 126 */ "seltablist ::= stl_prefix nm dbnm as on_opt using_opt", + /* 127 */ "seltablist ::= stl_prefix LP seltablist_paren RP as on_opt using_opt", + /* 128 */ "seltablist_paren ::= select", + /* 129 */ "seltablist_paren ::= seltablist", + /* 130 */ "dbnm ::=", + /* 131 */ "dbnm ::= DOT nm", + /* 132 */ "fullname ::= nm dbnm", + /* 133 */ "joinop ::= COMMA|JOIN", + /* 134 */ "joinop ::= JOIN_KW JOIN", + /* 135 */ "joinop ::= JOIN_KW nm JOIN", + /* 136 */ "joinop ::= JOIN_KW nm nm JOIN", + /* 137 */ "on_opt ::= ON expr", + /* 138 */ "on_opt ::=", + /* 139 */ "using_opt ::= USING LP inscollist RP", + /* 140 */ "using_opt ::=", + /* 141 */ "orderby_opt ::=", + /* 142 */ "orderby_opt ::= ORDER BY sortlist", + /* 143 */ "sortlist ::= sortlist COMMA sortitem sortorder", + /* 144 */ "sortlist ::= sortitem sortorder", + /* 145 */ "sortitem ::= expr", + /* 146 */ "sortorder ::= ASC", + /* 147 */ "sortorder ::= DESC", + /* 148 */ "sortorder ::=", + /* 149 */ "groupby_opt ::=", + /* 150 */ "groupby_opt ::= GROUP BY nexprlist", + /* 151 */ "having_opt ::=", + /* 152 */ "having_opt ::= HAVING expr", + /* 153 */ "limit_opt ::=", + /* 154 */ "limit_opt ::= LIMIT expr", + /* 155 */ "limit_opt ::= LIMIT expr OFFSET expr", + /* 156 */ "limit_opt ::= LIMIT expr COMMA expr", + /* 157 */ "cmd ::= DELETE FROM fullname where_opt", + /* 158 */ "where_opt ::=", + /* 159 */ "where_opt ::= WHERE expr", + /* 160 */ "cmd ::= UPDATE orconf fullname SET setlist where_opt", + /* 161 */ "setlist ::= setlist COMMA nm EQ expr", + /* 162 */ "setlist ::= nm EQ expr", + /* 163 */ "cmd ::= insert_cmd INTO fullname inscollist_opt VALUES LP itemlist RP", + /* 164 */ "cmd ::= insert_cmd INTO fullname inscollist_opt select", + /* 165 */ "cmd ::= insert_cmd INTO fullname inscollist_opt DEFAULT VALUES", + /* 166 */ "insert_cmd ::= INSERT orconf", + /* 167 */ "insert_cmd ::= REPLACE", + /* 168 */ "itemlist ::= itemlist COMMA expr", + /* 169 */ "itemlist ::= expr", + /* 170 */ "inscollist_opt ::=", + /* 171 */ "inscollist_opt ::= LP inscollist RP", + /* 172 */ "inscollist ::= inscollist COMMA nm", + /* 173 */ "inscollist ::= nm", + /* 174 */ "expr ::= term", + /* 175 */ "expr ::= LP expr RP", + /* 176 */ "term ::= NULL", + /* 177 */ "expr ::= ID", + /* 178 */ "expr ::= JOIN_KW", + /* 179 */ "expr ::= nm DOT nm", + /* 180 */ "expr ::= nm DOT nm DOT nm", + /* 181 */ "term ::= INTEGER|FLOAT|BLOB", + /* 182 */ "term ::= STRING", + /* 183 */ "expr ::= REGISTER", + /* 184 */ "expr ::= VARIABLE", + /* 185 */ "expr ::= expr COLLATE id", + /* 186 */ "expr ::= CAST LP expr AS typetoken RP", + /* 187 */ "expr ::= ID LP distinct exprlist RP", + /* 188 */ "expr ::= ID LP STAR RP", + /* 189 */ "term ::= CTIME_KW", + /* 190 */ "expr ::= expr AND expr", + /* 191 */ "expr ::= expr OR expr", + /* 192 */ "expr ::= expr LT|GT|GE|LE expr", + /* 193 */ "expr ::= expr EQ|NE expr", + /* 194 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr", + /* 195 */ "expr ::= expr PLUS|MINUS expr", + /* 196 */ "expr ::= expr STAR|SLASH|REM expr", + /* 197 */ "expr ::= expr CONCAT expr", + /* 198 */ "likeop ::= LIKE_KW", + /* 199 */ "likeop ::= NOT LIKE_KW", + /* 200 */ "likeop ::= MATCH", + /* 201 */ "likeop ::= NOT MATCH", + /* 202 */ "escape ::= ESCAPE expr", + /* 203 */ "escape ::=", + /* 204 */ "expr ::= expr likeop expr escape", + /* 205 */ "expr ::= expr ISNULL|NOTNULL", + /* 206 */ "expr ::= expr IS NULL", + /* 207 */ "expr ::= expr NOT NULL", + /* 208 */ "expr ::= expr IS NOT NULL", + /* 209 */ "expr ::= NOT|BITNOT expr", + /* 210 */ "expr ::= MINUS expr", + /* 211 */ "expr ::= PLUS expr", + /* 212 */ "between_op ::= BETWEEN", + /* 213 */ "between_op ::= NOT BETWEEN", + /* 214 */ "expr ::= expr between_op expr AND expr", + /* 215 */ "in_op ::= IN", + /* 216 */ "in_op ::= NOT IN", + /* 217 */ "expr ::= expr in_op LP exprlist RP", + /* 218 */ "expr ::= LP select RP", + /* 219 */ "expr ::= expr in_op LP select RP", + /* 220 */ "expr ::= expr in_op nm dbnm", + /* 221 */ "expr ::= EXISTS LP select RP", + /* 222 */ "expr ::= CASE case_operand case_exprlist case_else END", + /* 223 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr", + /* 224 */ "case_exprlist ::= WHEN expr THEN expr", + /* 225 */ "case_else ::= ELSE expr", + /* 226 */ "case_else ::=", + /* 227 */ "case_operand ::= expr", + /* 228 */ "case_operand ::=", + /* 229 */ "exprlist ::= nexprlist", + /* 230 */ "exprlist ::=", + /* 231 */ "nexprlist ::= nexprlist COMMA expr", + /* 232 */ "nexprlist ::= expr", + /* 233 */ "cmd ::= CREATE uniqueflag INDEX ifnotexists nm dbnm ON nm LP idxlist RP", + /* 234 */ "uniqueflag ::= UNIQUE", + /* 235 */ "uniqueflag ::=", + /* 236 */ "idxlist_opt ::=", + /* 237 */ "idxlist_opt ::= LP idxlist RP", + /* 238 */ "idxlist ::= idxlist COMMA idxitem collate sortorder", + /* 239 */ "idxlist ::= idxitem collate sortorder", + /* 240 */ "idxitem ::= nm", + /* 241 */ "collate ::=", + /* 242 */ "collate ::= COLLATE id", + /* 243 */ "cmd ::= DROP INDEX ifexists fullname", + /* 244 */ "cmd ::= VACUUM", + /* 245 */ "cmd ::= VACUUM nm", + /* 246 */ "cmd ::= PRAGMA nm dbnm EQ nmnum", + /* 247 */ "cmd ::= PRAGMA nm dbnm EQ ON", + /* 248 */ "cmd ::= PRAGMA nm dbnm EQ minus_num", + /* 249 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP", + /* 250 */ "cmd ::= PRAGMA nm dbnm", + /* 251 */ "nmnum ::= plus_num", + /* 252 */ "nmnum ::= nm", + /* 253 */ "plus_num ::= plus_opt number", + /* 254 */ "minus_num ::= MINUS number", + /* 255 */ "number ::= INTEGER|FLOAT", + /* 256 */ "plus_opt ::= PLUS", + /* 257 */ "plus_opt ::=", + /* 258 */ "cmd ::= CREATE trigger_decl BEGIN trigger_cmd_list END", + /* 259 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause", + /* 260 */ "trigger_time ::= BEFORE", + /* 261 */ "trigger_time ::= AFTER", + /* 262 */ "trigger_time ::= INSTEAD OF", + /* 263 */ "trigger_time ::=", + /* 264 */ "trigger_event ::= DELETE|INSERT", + /* 265 */ "trigger_event ::= UPDATE", + /* 266 */ "trigger_event ::= UPDATE OF inscollist", + /* 267 */ "foreach_clause ::=", + /* 268 */ "foreach_clause ::= FOR EACH ROW", + /* 269 */ "when_clause ::=", + /* 270 */ "when_clause ::= WHEN expr", + /* 271 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI", + /* 272 */ "trigger_cmd_list ::=", + /* 273 */ "trigger_cmd ::= UPDATE orconf nm SET setlist where_opt", + /* 274 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt VALUES LP itemlist RP", + /* 275 */ "trigger_cmd ::= insert_cmd INTO nm inscollist_opt select", + /* 276 */ "trigger_cmd ::= DELETE FROM nm where_opt", + /* 277 */ "trigger_cmd ::= select", + /* 278 */ "expr ::= RAISE LP IGNORE RP", + /* 279 */ "expr ::= RAISE LP raisetype COMMA nm RP", + /* 280 */ "raisetype ::= ROLLBACK", + /* 281 */ "raisetype ::= ABORT", + /* 282 */ "raisetype ::= FAIL", + /* 283 */ "cmd ::= DROP TRIGGER ifexists fullname", + /* 284 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt", + /* 285 */ "cmd ::= DETACH database_kw_opt expr", + /* 286 */ "key_opt ::=", + /* 287 */ "key_opt ::= KEY expr", + /* 288 */ "database_kw_opt ::= DATABASE", + /* 289 */ "database_kw_opt ::=", + /* 290 */ "cmd ::= REINDEX", + /* 291 */ "cmd ::= REINDEX nm dbnm", + /* 292 */ "cmd ::= ANALYZE", + /* 293 */ "cmd ::= ANALYZE nm dbnm", + /* 294 */ "cmd ::= ALTER TABLE fullname RENAME TO nm", + /* 295 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt column", + /* 296 */ "add_column_fullname ::= fullname", + /* 297 */ "kwcolumn_opt ::=", + /* 298 */ "kwcolumn_opt ::= COLUMNKW", + /* 299 */ "cmd ::= create_vtab", + /* 300 */ "cmd ::= create_vtab LP vtabarglist RP", + /* 301 */ "create_vtab ::= CREATE VIRTUAL TABLE nm dbnm USING nm", + /* 302 */ "vtabarglist ::= vtabarg", + /* 303 */ "vtabarglist ::= vtabarglist COMMA vtabarg", + /* 304 */ "vtabarg ::=", + /* 305 */ "vtabarg ::= vtabarg vtabargtoken", + /* 306 */ "vtabargtoken ::= ANY", + /* 307 */ "vtabargtoken ::= lp anylist RP", + /* 308 */ "lp ::= LP", + /* 309 */ "anylist ::=", + /* 310 */ "anylist ::= anylist ANY", +}; +#endif /* NDEBUG */ + + +#if YYSTACKDEPTH<=0 +/* +** Try to increase the size of the parser stack. +*/ +static void yyGrowStack(yyParser *p){ + int newSize; + yyStackEntry *pNew; + + newSize = p->yystksz*2 + 100; + pNew = realloc(p->yystack, newSize*sizeof(pNew[0])); + if( pNew ){ + p->yystack = pNew; + p->yystksz = newSize; +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sStack grows to %d entries!\n", + yyTracePrompt, p->yystksz); + } +#endif + } +} +#endif + +/* +** This function allocates a new parser. +** The only argument is a pointer to a function which works like +** malloc. +** +** Inputs: +** A pointer to the function used to allocate memory. +** +** Outputs: +** A pointer to a parser. This pointer is used in subsequent calls +** to sqlite3Parser and sqlite3ParserFree. +*/ +void *sqlite3ParserAlloc(void *(*mallocProc)(size_t)){ + yyParser *pParser; + pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) ); + if( pParser ){ + pParser->yyidx = -1; +#if YYSTACKDEPTH<=0 + yyGrowStack(pParser); +#endif + } + return pParser; +} + +/* The following function deletes the value associated with a +** symbol. The symbol can be either a terminal or nonterminal. +** "yymajor" is the symbol code, and "yypminor" is a pointer to +** the value. +*/ +static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){ + switch( yymajor ){ + /* Here is inserted the actions which take place when a + ** terminal or non-terminal is destroyed. This can happen + ** when the symbol is popped from the stack during a + ** reduce or during error processing or when a parser is + ** being destroyed before it is finished parsing. + ** + ** Note: during a reduce, the only symbols destroyed are those + ** which appear on the RHS of the rule, but which are not used + ** inside the C code. + */ + case 155: + case 189: + case 206: +#line 374 "parse.y" +{sqlite3SelectDelete((yypminor->yy219));} +#line 1274 "parse.c" + break; + case 169: + case 170: + case 194: + case 196: + case 204: + case 210: + case 218: + case 221: + case 223: + case 235: +#line 627 "parse.y" +{sqlite3ExprDelete((yypminor->yy172));} +#line 1288 "parse.c" + break; + case 174: + case 182: + case 192: + case 195: + case 197: + case 199: + case 209: + case 211: + case 212: + case 215: + case 216: + case 222: +#line 876 "parse.y" +{sqlite3ExprListDelete((yypminor->yy174));} +#line 1304 "parse.c" + break; + case 188: + case 193: + case 201: + case 202: +#line 489 "parse.y" +{sqlite3SrcListDelete((yypminor->yy373));} +#line 1312 "parse.c" + break; + case 205: + case 208: + case 214: +#line 506 "parse.y" +{sqlite3IdListDelete((yypminor->yy432));} +#line 1319 "parse.c" + break; + case 231: + case 236: +#line 979 "parse.y" +{sqlite3DeleteTriggerStep((yypminor->yy243));} +#line 1325 "parse.c" + break; + case 233: +#line 965 "parse.y" +{sqlite3IdListDelete((yypminor->yy370).b);} +#line 1330 "parse.c" + break; + case 238: +#line 1052 "parse.y" +{sqlite3ExprDelete((yypminor->yy386));} +#line 1335 "parse.c" + break; + default: break; /* If no destructor action specified: do nothing */ + } +} + +/* +** Pop the parser's stack once. +** +** If there is a destructor routine associated with the token which +** is popped from the stack, then call it. +** +** Return the major token number for the symbol popped. +*/ +static int yy_pop_parser_stack(yyParser *pParser){ + YYCODETYPE yymajor; + yyStackEntry *yytos = &pParser->yystack[pParser->yyidx]; + + if( pParser->yyidx<0 ) return 0; +#ifndef NDEBUG + if( yyTraceFILE && pParser->yyidx>=0 ){ + fprintf(yyTraceFILE,"%sPopping %s\n", + yyTracePrompt, + yyTokenName[yytos->major]); + } +#endif + yymajor = yytos->major; + yy_destructor( yymajor, &yytos->minor); + pParser->yyidx--; + return yymajor; +} + +/* +** Deallocate and destroy a parser. Destructors are all called for +** all stack elements before shutting the parser down. +** +** Inputs: +**
    +**
  • A pointer to the parser. This should be a pointer +** obtained from sqlite3ParserAlloc. +**
  • A pointer to a function used to reclaim memory obtained +** from malloc. +**
+*/ +void sqlite3ParserFree( + void *p, /* The parser to be deleted */ + void (*freeProc)(void*) /* Function used to reclaim memory */ +){ + yyParser *pParser = (yyParser*)p; + if( pParser==0 ) return; + while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser); +#if YYSTACKDEPTH<=0 + free(pParser->yystack); +#endif + (*freeProc)((void*)pParser); +} + +/* +** Find the appropriate action for a parser given the terminal +** look-ahead token iLookAhead. +** +** If the look-ahead token is YYNOCODE, then check to see if the action is +** independent of the look-ahead. If it is, return the action, otherwise +** return YY_NO_ACTION. +*/ +static int yy_find_shift_action( + yyParser *pParser, /* The parser */ + YYCODETYPE iLookAhead /* The look-ahead token */ +){ + int i; + int stateno = pParser->yystack[pParser->yyidx].stateno; + + if( stateno>YY_SHIFT_MAX || (i = yy_shift_ofst[stateno])==YY_SHIFT_USE_DFLT ){ + return yy_default[stateno]; + } + if( iLookAhead==YYNOCODE ){ + return YY_NO_ACTION; + } + i += iLookAhead; + if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){ + if( iLookAhead>0 ){ +#ifdef YYFALLBACK + int iFallback; /* Fallback token */ + if( iLookAhead %s\n", + yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); + } +#endif + return yy_find_shift_action(pParser, iFallback); + } +#endif +#ifdef YYWILDCARD + { + int j = i - iLookAhead + YYWILDCARD; + if( j>=0 && j %s\n", + yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[YYWILDCARD]); + } +#endif /* NDEBUG */ + return yy_action[j]; + } + } +#endif /* YYWILDCARD */ + } + return yy_default[stateno]; + }else{ + return yy_action[i]; + } +} + +/* +** Find the appropriate action for a parser given the non-terminal +** look-ahead token iLookAhead. +** +** If the look-ahead token is YYNOCODE, then check to see if the action is +** independent of the look-ahead. If it is, return the action, otherwise +** return YY_NO_ACTION. +*/ +static int yy_find_reduce_action( + int stateno, /* Current state number */ + YYCODETYPE iLookAhead /* The look-ahead token */ +){ + int i; + /* int stateno = pParser->yystack[pParser->yyidx].stateno; */ + + if( stateno>YY_REDUCE_MAX || + (i = yy_reduce_ofst[stateno])==YY_REDUCE_USE_DFLT ){ + return yy_default[stateno]; + } + if( iLookAhead==YYNOCODE ){ + return YY_NO_ACTION; + } + i += iLookAhead; + if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){ + return yy_default[stateno]; + }else{ + return yy_action[i]; + } +} + +/* +** The following routine is called if the stack overflows. +*/ +static void yyStackOverflow(yyParser *yypParser, YYMINORTYPE *yypMinor){ + sqlite3ParserARG_FETCH; + yypParser->yyidx--; +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt); + } +#endif + while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); + /* Here code is inserted which will execute if the parser + ** stack every overflows */ +#line 44 "parse.y" + + sqlite3ErrorMsg(pParse, "parser stack overflow"); + pParse->parseError = 1; +#line 1499 "parse.c" + sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument var */ +} + +/* +** Perform a shift action. +*/ +static void yy_shift( + yyParser *yypParser, /* The parser to be shifted */ + int yyNewState, /* The new state to shift in */ + int yyMajor, /* The major token to shift in */ + YYMINORTYPE *yypMinor /* Pointer ot the minor token to shift in */ +){ + yyStackEntry *yytos; + yypParser->yyidx++; +#if YYSTACKDEPTH>0 + if( yypParser->yyidx>=YYSTACKDEPTH ){ + yyStackOverflow(yypParser, yypMinor); + return; + } +#else + if( yypParser->yyidx>=yypParser->yystksz ){ + yyGrowStack(yypParser); + if( yypParser->yyidx>=yypParser->yystksz ){ + yyStackOverflow(yypParser, yypMinor); + return; + } + } +#endif + yytos = &yypParser->yystack[yypParser->yyidx]; + yytos->stateno = yyNewState; + yytos->major = yyMajor; + yytos->minor = *yypMinor; +#ifndef NDEBUG + if( yyTraceFILE && yypParser->yyidx>0 ){ + int i; + fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState); + fprintf(yyTraceFILE,"%sStack:",yyTracePrompt); + for(i=1; i<=yypParser->yyidx; i++) + fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]); + fprintf(yyTraceFILE,"\n"); + } +#endif +} + +/* The following table contains information about every rule that +** is used during the reduce. +*/ +static const struct { + YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ + unsigned char nrhs; /* Number of right-hand side symbols in the rule */ +} yyRuleInfo[] = { + { 139, 1 }, + { 140, 2 }, + { 140, 1 }, + { 142, 1 }, + { 141, 1 }, + { 141, 3 }, + { 144, 0 }, + { 144, 1 }, + { 144, 3 }, + { 143, 3 }, + { 146, 0 }, + { 146, 1 }, + { 146, 2 }, + { 145, 0 }, + { 145, 1 }, + { 145, 1 }, + { 145, 1 }, + { 143, 2 }, + { 143, 2 }, + { 143, 2 }, + { 143, 2 }, + { 148, 6 }, + { 151, 0 }, + { 151, 3 }, + { 150, 1 }, + { 150, 0 }, + { 149, 4 }, + { 149, 2 }, + { 153, 3 }, + { 153, 1 }, + { 156, 3 }, + { 157, 1 }, + { 160, 1 }, + { 161, 1 }, + { 147, 1 }, + { 147, 1 }, + { 147, 1 }, + { 158, 0 }, + { 158, 1 }, + { 162, 1 }, + { 162, 4 }, + { 162, 6 }, + { 163, 1 }, + { 163, 2 }, + { 164, 1 }, + { 164, 1 }, + { 159, 2 }, + { 159, 0 }, + { 167, 3 }, + { 167, 1 }, + { 168, 2 }, + { 168, 4 }, + { 168, 3 }, + { 168, 3 }, + { 168, 2 }, + { 168, 2 }, + { 168, 3 }, + { 168, 5 }, + { 168, 2 }, + { 168, 4 }, + { 168, 4 }, + { 168, 1 }, + { 168, 2 }, + { 173, 0 }, + { 173, 1 }, + { 175, 0 }, + { 175, 2 }, + { 177, 2 }, + { 177, 3 }, + { 177, 3 }, + { 177, 3 }, + { 178, 2 }, + { 178, 2 }, + { 178, 1 }, + { 178, 1 }, + { 176, 3 }, + { 176, 2 }, + { 179, 0 }, + { 179, 2 }, + { 179, 2 }, + { 154, 0 }, + { 154, 2 }, + { 180, 3 }, + { 180, 2 }, + { 180, 1 }, + { 181, 2 }, + { 181, 7 }, + { 181, 5 }, + { 181, 5 }, + { 181, 10 }, + { 183, 0 }, + { 183, 1 }, + { 171, 0 }, + { 171, 3 }, + { 184, 0 }, + { 184, 2 }, + { 185, 1 }, + { 185, 1 }, + { 185, 1 }, + { 143, 4 }, + { 187, 2 }, + { 187, 0 }, + { 143, 8 }, + { 143, 4 }, + { 143, 1 }, + { 155, 1 }, + { 155, 3 }, + { 190, 1 }, + { 190, 2 }, + { 190, 1 }, + { 189, 9 }, + { 191, 1 }, + { 191, 1 }, + { 191, 0 }, + { 199, 2 }, + { 199, 0 }, + { 192, 3 }, + { 192, 2 }, + { 192, 4 }, + { 200, 2 }, + { 200, 1 }, + { 200, 0 }, + { 193, 0 }, + { 193, 2 }, + { 202, 2 }, + { 202, 0 }, + { 201, 6 }, + { 201, 7 }, + { 206, 1 }, + { 206, 1 }, + { 152, 0 }, + { 152, 2 }, + { 188, 2 }, + { 203, 1 }, + { 203, 2 }, + { 203, 3 }, + { 203, 4 }, + { 204, 2 }, + { 204, 0 }, + { 205, 4 }, + { 205, 0 }, + { 197, 0 }, + { 197, 3 }, + { 209, 4 }, + { 209, 2 }, + { 210, 1 }, + { 172, 1 }, + { 172, 1 }, + { 172, 0 }, + { 195, 0 }, + { 195, 3 }, + { 196, 0 }, + { 196, 2 }, + { 198, 0 }, + { 198, 2 }, + { 198, 4 }, + { 198, 4 }, + { 143, 4 }, + { 194, 0 }, + { 194, 2 }, + { 143, 6 }, + { 212, 5 }, + { 212, 3 }, + { 143, 8 }, + { 143, 5 }, + { 143, 6 }, + { 213, 2 }, + { 213, 1 }, + { 215, 3 }, + { 215, 1 }, + { 214, 0 }, + { 214, 3 }, + { 208, 3 }, + { 208, 1 }, + { 170, 1 }, + { 170, 3 }, + { 169, 1 }, + { 170, 1 }, + { 170, 1 }, + { 170, 3 }, + { 170, 5 }, + { 169, 1 }, + { 169, 1 }, + { 170, 1 }, + { 170, 1 }, + { 170, 3 }, + { 170, 6 }, + { 170, 5 }, + { 170, 4 }, + { 169, 1 }, + { 170, 3 }, + { 170, 3 }, + { 170, 3 }, + { 170, 3 }, + { 170, 3 }, + { 170, 3 }, + { 170, 3 }, + { 170, 3 }, + { 217, 1 }, + { 217, 2 }, + { 217, 1 }, + { 217, 2 }, + { 218, 2 }, + { 218, 0 }, + { 170, 4 }, + { 170, 2 }, + { 170, 3 }, + { 170, 3 }, + { 170, 4 }, + { 170, 2 }, + { 170, 2 }, + { 170, 2 }, + { 219, 1 }, + { 219, 2 }, + { 170, 5 }, + { 220, 1 }, + { 220, 2 }, + { 170, 5 }, + { 170, 3 }, + { 170, 5 }, + { 170, 4 }, + { 170, 4 }, + { 170, 5 }, + { 222, 5 }, + { 222, 4 }, + { 223, 2 }, + { 223, 0 }, + { 221, 1 }, + { 221, 0 }, + { 216, 1 }, + { 216, 0 }, + { 211, 3 }, + { 211, 1 }, + { 143, 11 }, + { 224, 1 }, + { 224, 0 }, + { 174, 0 }, + { 174, 3 }, + { 182, 5 }, + { 182, 3 }, + { 225, 1 }, + { 226, 0 }, + { 226, 2 }, + { 143, 4 }, + { 143, 1 }, + { 143, 2 }, + { 143, 5 }, + { 143, 5 }, + { 143, 5 }, + { 143, 6 }, + { 143, 3 }, + { 227, 1 }, + { 227, 1 }, + { 165, 2 }, + { 166, 2 }, + { 229, 1 }, + { 228, 1 }, + { 228, 0 }, + { 143, 5 }, + { 230, 11 }, + { 232, 1 }, + { 232, 1 }, + { 232, 2 }, + { 232, 0 }, + { 233, 1 }, + { 233, 1 }, + { 233, 3 }, + { 234, 0 }, + { 234, 3 }, + { 235, 0 }, + { 235, 2 }, + { 231, 3 }, + { 231, 0 }, + { 236, 6 }, + { 236, 8 }, + { 236, 5 }, + { 236, 4 }, + { 236, 1 }, + { 170, 4 }, + { 170, 6 }, + { 186, 1 }, + { 186, 1 }, + { 186, 1 }, + { 143, 4 }, + { 143, 6 }, + { 143, 3 }, + { 238, 0 }, + { 238, 2 }, + { 237, 1 }, + { 237, 0 }, + { 143, 1 }, + { 143, 3 }, + { 143, 1 }, + { 143, 3 }, + { 143, 6 }, + { 143, 6 }, + { 239, 1 }, + { 240, 0 }, + { 240, 1 }, + { 143, 1 }, + { 143, 4 }, + { 241, 7 }, + { 242, 1 }, + { 242, 3 }, + { 243, 0 }, + { 243, 2 }, + { 244, 1 }, + { 244, 3 }, + { 245, 1 }, + { 246, 0 }, + { 246, 2 }, +}; + +static void yy_accept(yyParser*); /* Forward Declaration */ + +/* +** Perform a reduce action and the shift that must immediately +** follow the reduce. +*/ +static void yy_reduce( + yyParser *yypParser, /* The parser */ + int yyruleno /* Number of the rule by which to reduce */ +){ + int yygoto; /* The next state */ + int yyact; /* The next action */ + YYMINORTYPE yygotominor; /* The LHS of the rule reduced */ + yyStackEntry *yymsp; /* The top of the parser's stack */ + int yysize; /* Amount to pop the stack */ + sqlite3ParserARG_FETCH; + yymsp = &yypParser->yystack[yypParser->yyidx]; +#ifndef NDEBUG + if( yyTraceFILE && yyruleno>=0 + && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ + fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt, + yyRuleName[yyruleno]); + } +#endif /* NDEBUG */ + + /* Silence complaints from purify about yygotominor being uninitialized + ** in some cases when it is copied into the stack after the following + ** switch. yygotominor is uninitialized when a rule reduces that does + ** not set the value of its left-hand side nonterminal. Leaving the + ** value of the nonterminal uninitialized is utterly harmless as long + ** as the value is never used. So really the only thing this code + ** accomplishes is to quieten purify. + ** + ** 2007-01-16: The wireshark project (www.wireshark.org) reports that + ** without this code, their parser segfaults. I'm not sure what there + ** parser is doing to make this happen. This is the second bug report + ** from wireshark this week. Clearly they are stressing Lemon in ways + ** that it has not been previously stressed... (SQLite ticket #2172) + */ + memset(&yygotominor, 0, sizeof(yygotominor)); + + + switch( yyruleno ){ + /* Beginning here are the reduction cases. A typical example + ** follows: + ** case 0: + ** #line + ** { ... } // User supplied code + ** #line + ** break; + */ + case 0: + case 1: + case 2: + case 4: + case 5: + case 10: + case 11: + case 12: + case 20: + case 28: + case 29: + case 37: + case 44: + case 45: + case 46: + case 47: + case 48: + case 49: + case 55: + case 82: + case 83: + case 84: + case 85: + case 256: + case 257: + case 267: + case 268: + case 288: + case 289: + case 297: + case 298: + case 302: + case 303: + case 305: + case 309: +#line 97 "parse.y" +{ +} +#line 1953 "parse.c" + break; + case 3: +#line 100 "parse.y" +{ sqlite3FinishCoding(pParse); } +#line 1958 "parse.c" + break; + case 6: +#line 103 "parse.y" +{ sqlite3BeginParse(pParse, 0); } +#line 1963 "parse.c" + break; + case 7: +#line 105 "parse.y" +{ sqlite3BeginParse(pParse, 1); } +#line 1968 "parse.c" + break; + case 8: +#line 106 "parse.y" +{ sqlite3BeginParse(pParse, 2); } +#line 1973 "parse.c" + break; + case 9: +#line 112 "parse.y" +{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy46);} +#line 1978 "parse.c" + break; + case 13: +#line 117 "parse.y" +{yygotominor.yy46 = TK_DEFERRED;} +#line 1983 "parse.c" + break; + case 14: + case 15: + case 16: + case 107: + case 109: +#line 118 "parse.y" +{yygotominor.yy46 = yymsp[0].major;} +#line 1992 "parse.c" + break; + case 17: + case 18: +#line 121 "parse.y" +{sqlite3CommitTransaction(pParse);} +#line 1998 "parse.c" + break; + case 19: +#line 123 "parse.y" +{sqlite3RollbackTransaction(pParse);} +#line 2003 "parse.c" + break; + case 21: +#line 128 "parse.y" +{ + sqlite3StartTable(pParse,&yymsp[-1].minor.yy410,&yymsp[0].minor.yy410,yymsp[-4].minor.yy46,0,0,yymsp[-2].minor.yy46); +} +#line 2010 "parse.c" + break; + case 22: + case 25: + case 63: + case 77: + case 79: + case 90: + case 101: + case 112: + case 113: + case 212: + case 215: +#line 132 "parse.y" +{yygotominor.yy46 = 0;} +#line 2025 "parse.c" + break; + case 23: + case 24: + case 64: + case 78: + case 100: + case 111: + case 213: + case 216: +#line 133 "parse.y" +{yygotominor.yy46 = 1;} +#line 2037 "parse.c" + break; + case 26: +#line 139 "parse.y" +{ + sqlite3EndTable(pParse,&yymsp[-1].minor.yy410,&yymsp[0].minor.yy0,0); +} +#line 2044 "parse.c" + break; + case 27: +#line 142 "parse.y" +{ + sqlite3EndTable(pParse,0,0,yymsp[0].minor.yy219); + sqlite3SelectDelete(yymsp[0].minor.yy219); +} +#line 2052 "parse.c" + break; + case 30: +#line 154 "parse.y" +{ + yygotominor.yy410.z = yymsp[-2].minor.yy410.z; + yygotominor.yy410.n = (pParse->sLastToken.z-yymsp[-2].minor.yy410.z) + pParse->sLastToken.n; +} +#line 2060 "parse.c" + break; + case 31: +#line 158 "parse.y" +{ + sqlite3AddColumn(pParse,&yymsp[0].minor.yy410); + yygotominor.yy410 = yymsp[0].minor.yy410; +} +#line 2068 "parse.c" + break; + case 32: + case 33: + case 34: + case 35: + case 36: + case 255: +#line 168 "parse.y" +{yygotominor.yy410 = yymsp[0].minor.yy0;} +#line 2078 "parse.c" + break; + case 38: +#line 229 "parse.y" +{sqlite3AddColumnType(pParse,&yymsp[0].minor.yy410);} +#line 2083 "parse.c" + break; + case 39: + case 42: + case 119: + case 120: + case 131: + case 240: + case 242: + case 251: + case 252: + case 253: + case 254: +#line 230 "parse.y" +{yygotominor.yy410 = yymsp[0].minor.yy410;} +#line 2098 "parse.c" + break; + case 40: +#line 231 "parse.y" +{ + yygotominor.yy410.z = yymsp[-3].minor.yy410.z; + yygotominor.yy410.n = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-3].minor.yy410.z; +} +#line 2106 "parse.c" + break; + case 41: +#line 235 "parse.y" +{ + yygotominor.yy410.z = yymsp[-5].minor.yy410.z; + yygotominor.yy410.n = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n] - yymsp[-5].minor.yy410.z; +} +#line 2114 "parse.c" + break; + case 43: +#line 241 "parse.y" +{yygotominor.yy410.z=yymsp[-1].minor.yy410.z; yygotominor.yy410.n=yymsp[0].minor.yy410.n+(yymsp[0].minor.yy410.z-yymsp[-1].minor.yy410.z);} +#line 2119 "parse.c" + break; + case 50: + case 52: +#line 252 "parse.y" +{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy172);} +#line 2125 "parse.c" + break; + case 51: +#line 253 "parse.y" +{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy172);} +#line 2130 "parse.c" + break; + case 53: +#line 255 "parse.y" +{ + Expr *p = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy172, 0, 0); + sqlite3AddDefaultValue(pParse,p); +} +#line 2138 "parse.c" + break; + case 54: +#line 259 "parse.y" +{ + Expr *p = sqlite3Expr(TK_STRING, 0, 0, &yymsp[0].minor.yy410); + sqlite3AddDefaultValue(pParse,p); +} +#line 2146 "parse.c" + break; + case 56: +#line 268 "parse.y" +{sqlite3AddNotNull(pParse, yymsp[0].minor.yy46);} +#line 2151 "parse.c" + break; + case 57: +#line 270 "parse.y" +{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy46,yymsp[0].minor.yy46,yymsp[-2].minor.yy46);} +#line 2156 "parse.c" + break; + case 58: +#line 271 "parse.y" +{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy46,0,0,0,0);} +#line 2161 "parse.c" + break; + case 59: +#line 272 "parse.y" +{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy172);} +#line 2166 "parse.c" + break; + case 60: +#line 274 "parse.y" +{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy410,yymsp[-1].minor.yy174,yymsp[0].minor.yy46);} +#line 2171 "parse.c" + break; + case 61: +#line 275 "parse.y" +{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy46);} +#line 2176 "parse.c" + break; + case 62: +#line 276 "parse.y" +{sqlite3AddCollateType(pParse, (char*)yymsp[0].minor.yy410.z, yymsp[0].minor.yy410.n);} +#line 2181 "parse.c" + break; + case 65: +#line 289 "parse.y" +{ yygotominor.yy46 = OE_Restrict * 0x010101; } +#line 2186 "parse.c" + break; + case 66: +#line 290 "parse.y" +{ yygotominor.yy46 = (yymsp[-1].minor.yy46 & yymsp[0].minor.yy405.mask) | yymsp[0].minor.yy405.value; } +#line 2191 "parse.c" + break; + case 67: +#line 292 "parse.y" +{ yygotominor.yy405.value = 0; yygotominor.yy405.mask = 0x000000; } +#line 2196 "parse.c" + break; + case 68: +#line 293 "parse.y" +{ yygotominor.yy405.value = yymsp[0].minor.yy46; yygotominor.yy405.mask = 0x0000ff; } +#line 2201 "parse.c" + break; + case 69: +#line 294 "parse.y" +{ yygotominor.yy405.value = yymsp[0].minor.yy46<<8; yygotominor.yy405.mask = 0x00ff00; } +#line 2206 "parse.c" + break; + case 70: +#line 295 "parse.y" +{ yygotominor.yy405.value = yymsp[0].minor.yy46<<16; yygotominor.yy405.mask = 0xff0000; } +#line 2211 "parse.c" + break; + case 71: +#line 297 "parse.y" +{ yygotominor.yy46 = OE_SetNull; } +#line 2216 "parse.c" + break; + case 72: +#line 298 "parse.y" +{ yygotominor.yy46 = OE_SetDflt; } +#line 2221 "parse.c" + break; + case 73: +#line 299 "parse.y" +{ yygotominor.yy46 = OE_Cascade; } +#line 2226 "parse.c" + break; + case 74: +#line 300 "parse.y" +{ yygotominor.yy46 = OE_Restrict; } +#line 2231 "parse.c" + break; + case 75: + case 76: + case 91: + case 93: + case 95: + case 96: + case 166: +#line 302 "parse.y" +{yygotominor.yy46 = yymsp[0].minor.yy46;} +#line 2242 "parse.c" + break; + case 80: +#line 312 "parse.y" +{yygotominor.yy410.n = 0; yygotominor.yy410.z = 0;} +#line 2247 "parse.c" + break; + case 81: +#line 313 "parse.y" +{yygotominor.yy410 = yymsp[-1].minor.yy0;} +#line 2252 "parse.c" + break; + case 86: +#line 319 "parse.y" +{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy174,yymsp[0].minor.yy46,yymsp[-2].minor.yy46,0);} +#line 2257 "parse.c" + break; + case 87: +#line 321 "parse.y" +{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy174,yymsp[0].minor.yy46,0,0,0,0);} +#line 2262 "parse.c" + break; + case 88: +#line 322 "parse.y" +{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy172);} +#line 2267 "parse.c" + break; + case 89: +#line 324 "parse.y" +{ + sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy174, &yymsp[-3].minor.yy410, yymsp[-2].minor.yy174, yymsp[-1].minor.yy46); + sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy46); +} +#line 2275 "parse.c" + break; + case 92: + case 94: +#line 338 "parse.y" +{yygotominor.yy46 = OE_Default;} +#line 2281 "parse.c" + break; + case 97: +#line 343 "parse.y" +{yygotominor.yy46 = OE_Ignore;} +#line 2286 "parse.c" + break; + case 98: + case 167: +#line 344 "parse.y" +{yygotominor.yy46 = OE_Replace;} +#line 2292 "parse.c" + break; + case 99: +#line 348 "parse.y" +{ + sqlite3DropTable(pParse, yymsp[0].minor.yy373, 0, yymsp[-1].minor.yy46); +} +#line 2299 "parse.c" + break; + case 102: +#line 358 "parse.y" +{ + sqlite3CreateView(pParse, &yymsp[-7].minor.yy0, &yymsp[-3].minor.yy410, &yymsp[-2].minor.yy410, yymsp[0].minor.yy219, yymsp[-6].minor.yy46, yymsp[-4].minor.yy46); +} +#line 2306 "parse.c" + break; + case 103: +#line 361 "parse.y" +{ + sqlite3DropTable(pParse, yymsp[0].minor.yy373, 1, yymsp[-1].minor.yy46); +} +#line 2313 "parse.c" + break; + case 104: +#line 368 "parse.y" +{ + sqlite3Select(pParse, yymsp[0].minor.yy219, SRT_Callback, 0, 0, 0, 0, 0); + sqlite3SelectDelete(yymsp[0].minor.yy219); +} +#line 2321 "parse.c" + break; + case 105: + case 128: +#line 378 "parse.y" +{yygotominor.yy219 = yymsp[0].minor.yy219;} +#line 2327 "parse.c" + break; + case 106: +#line 380 "parse.y" +{ + if( yymsp[0].minor.yy219 ){ + yymsp[0].minor.yy219->op = yymsp[-1].minor.yy46; + yymsp[0].minor.yy219->pPrior = yymsp[-2].minor.yy219; + }else{ + sqlite3SelectDelete(yymsp[-2].minor.yy219); + } + yygotominor.yy219 = yymsp[0].minor.yy219; +} +#line 2340 "parse.c" + break; + case 108: +#line 391 "parse.y" +{yygotominor.yy46 = TK_ALL;} +#line 2345 "parse.c" + break; + case 110: +#line 395 "parse.y" +{ + yygotominor.yy219 = sqlite3SelectNew(yymsp[-6].minor.yy174,yymsp[-5].minor.yy373,yymsp[-4].minor.yy172,yymsp[-3].minor.yy174,yymsp[-2].minor.yy172,yymsp[-1].minor.yy174,yymsp[-7].minor.yy46,yymsp[0].minor.yy234.pLimit,yymsp[0].minor.yy234.pOffset); +} +#line 2352 "parse.c" + break; + case 114: + case 237: +#line 416 "parse.y" +{yygotominor.yy174 = yymsp[-1].minor.yy174;} +#line 2358 "parse.c" + break; + case 115: + case 141: + case 149: + case 230: + case 236: +#line 417 "parse.y" +{yygotominor.yy174 = 0;} +#line 2367 "parse.c" + break; + case 116: +#line 418 "parse.y" +{ + yygotominor.yy174 = sqlite3ExprListAppend(yymsp[-2].minor.yy174,yymsp[-1].minor.yy172,yymsp[0].minor.yy410.n?&yymsp[0].minor.yy410:0); +} +#line 2374 "parse.c" + break; + case 117: +#line 421 "parse.y" +{ + yygotominor.yy174 = sqlite3ExprListAppend(yymsp[-1].minor.yy174, sqlite3Expr(TK_ALL, 0, 0, 0), 0); +} +#line 2381 "parse.c" + break; + case 118: +#line 424 "parse.y" +{ + Expr *pRight = sqlite3Expr(TK_ALL, 0, 0, 0); + Expr *pLeft = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy410); + yygotominor.yy174 = sqlite3ExprListAppend(yymsp[-3].minor.yy174, sqlite3Expr(TK_DOT, pLeft, pRight, 0), 0); +} +#line 2390 "parse.c" + break; + case 121: +#line 436 "parse.y" +{yygotominor.yy410.n = 0;} +#line 2395 "parse.c" + break; + case 122: +#line 448 "parse.y" +{yygotominor.yy373 = sqliteMalloc(sizeof(*yygotominor.yy373));} +#line 2400 "parse.c" + break; + case 123: +#line 449 "parse.y" +{ + yygotominor.yy373 = yymsp[0].minor.yy373; + sqlite3SrcListShiftJoinType(yygotominor.yy373); +} +#line 2408 "parse.c" + break; + case 124: +#line 457 "parse.y" +{ + yygotominor.yy373 = yymsp[-1].minor.yy373; + if( yygotominor.yy373 && yygotominor.yy373->nSrc>0 ) yygotominor.yy373->a[yygotominor.yy373->nSrc-1].jointype = yymsp[0].minor.yy46; +} +#line 2416 "parse.c" + break; + case 125: +#line 461 "parse.y" +{yygotominor.yy373 = 0;} +#line 2421 "parse.c" + break; + case 126: +#line 462 "parse.y" +{ + yygotominor.yy373 = sqlite3SrcListAppendFromTerm(yymsp[-5].minor.yy373,&yymsp[-4].minor.yy410,&yymsp[-3].minor.yy410,&yymsp[-2].minor.yy410,0,yymsp[-1].minor.yy172,yymsp[0].minor.yy432); +} +#line 2428 "parse.c" + break; + case 127: +#line 467 "parse.y" +{ + yygotominor.yy373 = sqlite3SrcListAppendFromTerm(yymsp[-6].minor.yy373,0,0,&yymsp[-2].minor.yy410,yymsp[-4].minor.yy219,yymsp[-1].minor.yy172,yymsp[0].minor.yy432); + } +#line 2435 "parse.c" + break; + case 129: +#line 478 "parse.y" +{ + sqlite3SrcListShiftJoinType(yymsp[0].minor.yy373); + yygotominor.yy219 = sqlite3SelectNew(0,yymsp[0].minor.yy373,0,0,0,0,0,0,0); + } +#line 2443 "parse.c" + break; + case 130: +#line 485 "parse.y" +{yygotominor.yy410.z=0; yygotominor.yy410.n=0;} +#line 2448 "parse.c" + break; + case 132: +#line 490 "parse.y" +{yygotominor.yy373 = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy410,&yymsp[0].minor.yy410);} +#line 2453 "parse.c" + break; + case 133: +#line 494 "parse.y" +{ yygotominor.yy46 = JT_INNER; } +#line 2458 "parse.c" + break; + case 134: +#line 495 "parse.y" +{ yygotominor.yy46 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); } +#line 2463 "parse.c" + break; + case 135: +#line 496 "parse.y" +{ yygotominor.yy46 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy410,0); } +#line 2468 "parse.c" + break; + case 136: +#line 498 "parse.y" +{ yygotominor.yy46 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy410,&yymsp[-1].minor.yy410); } +#line 2473 "parse.c" + break; + case 137: + case 145: + case 152: + case 159: + case 174: + case 202: + case 225: + case 227: +#line 502 "parse.y" +{yygotominor.yy172 = yymsp[0].minor.yy172;} +#line 2485 "parse.c" + break; + case 138: + case 151: + case 158: + case 203: + case 226: + case 228: +#line 503 "parse.y" +{yygotominor.yy172 = 0;} +#line 2495 "parse.c" + break; + case 139: + case 171: +#line 507 "parse.y" +{yygotominor.yy432 = yymsp[-1].minor.yy432;} +#line 2501 "parse.c" + break; + case 140: + case 170: +#line 508 "parse.y" +{yygotominor.yy432 = 0;} +#line 2507 "parse.c" + break; + case 142: + case 150: + case 229: +#line 519 "parse.y" +{yygotominor.yy174 = yymsp[0].minor.yy174;} +#line 2514 "parse.c" + break; + case 143: +#line 520 "parse.y" +{ + yygotominor.yy174 = sqlite3ExprListAppend(yymsp[-3].minor.yy174,yymsp[-1].minor.yy172,0); + if( yygotominor.yy174 ) yygotominor.yy174->a[yygotominor.yy174->nExpr-1].sortOrder = yymsp[0].minor.yy46; +} +#line 2522 "parse.c" + break; + case 144: +#line 524 "parse.y" +{ + yygotominor.yy174 = sqlite3ExprListAppend(0,yymsp[-1].minor.yy172,0); + if( yygotominor.yy174 && yygotominor.yy174->a ) yygotominor.yy174->a[0].sortOrder = yymsp[0].minor.yy46; +} +#line 2530 "parse.c" + break; + case 146: + case 148: +#line 532 "parse.y" +{yygotominor.yy46 = SQLITE_SO_ASC;} +#line 2536 "parse.c" + break; + case 147: +#line 533 "parse.y" +{yygotominor.yy46 = SQLITE_SO_DESC;} +#line 2541 "parse.c" + break; + case 153: +#line 559 "parse.y" +{yygotominor.yy234.pLimit = 0; yygotominor.yy234.pOffset = 0;} +#line 2546 "parse.c" + break; + case 154: +#line 560 "parse.y" +{yygotominor.yy234.pLimit = yymsp[0].minor.yy172; yygotominor.yy234.pOffset = 0;} +#line 2551 "parse.c" + break; + case 155: +#line 562 "parse.y" +{yygotominor.yy234.pLimit = yymsp[-2].minor.yy172; yygotominor.yy234.pOffset = yymsp[0].minor.yy172;} +#line 2556 "parse.c" + break; + case 156: +#line 564 "parse.y" +{yygotominor.yy234.pOffset = yymsp[-2].minor.yy172; yygotominor.yy234.pLimit = yymsp[0].minor.yy172;} +#line 2561 "parse.c" + break; + case 157: +#line 568 "parse.y" +{sqlite3DeleteFrom(pParse,yymsp[-1].minor.yy373,yymsp[0].minor.yy172);} +#line 2566 "parse.c" + break; + case 160: +#line 578 "parse.y" +{ + sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy174,SQLITE_MAX_COLUMN,"set list"); + sqlite3Update(pParse,yymsp[-3].minor.yy373,yymsp[-1].minor.yy174,yymsp[0].minor.yy172,yymsp[-4].minor.yy46); +} +#line 2574 "parse.c" + break; + case 161: +#line 587 "parse.y" +{yygotominor.yy174 = sqlite3ExprListAppend(yymsp[-4].minor.yy174,yymsp[0].minor.yy172,&yymsp[-2].minor.yy410);} +#line 2579 "parse.c" + break; + case 162: +#line 588 "parse.y" +{yygotominor.yy174 = sqlite3ExprListAppend(0,yymsp[0].minor.yy172,&yymsp[-2].minor.yy410);} +#line 2584 "parse.c" + break; + case 163: +#line 594 "parse.y" +{sqlite3Insert(pParse, yymsp[-5].minor.yy373, yymsp[-1].minor.yy174, 0, yymsp[-4].minor.yy432, yymsp[-7].minor.yy46);} +#line 2589 "parse.c" + break; + case 164: +#line 596 "parse.y" +{sqlite3Insert(pParse, yymsp[-2].minor.yy373, 0, yymsp[0].minor.yy219, yymsp[-1].minor.yy432, yymsp[-4].minor.yy46);} +#line 2594 "parse.c" + break; + case 165: +#line 598 "parse.y" +{sqlite3Insert(pParse, yymsp[-3].minor.yy373, 0, 0, yymsp[-2].minor.yy432, yymsp[-5].minor.yy46);} +#line 2599 "parse.c" + break; + case 168: + case 231: +#line 608 "parse.y" +{yygotominor.yy174 = sqlite3ExprListAppend(yymsp[-2].minor.yy174,yymsp[0].minor.yy172,0);} +#line 2605 "parse.c" + break; + case 169: + case 232: +#line 609 "parse.y" +{yygotominor.yy174 = sqlite3ExprListAppend(0,yymsp[0].minor.yy172,0);} +#line 2611 "parse.c" + break; + case 172: +#line 618 "parse.y" +{yygotominor.yy432 = sqlite3IdListAppend(yymsp[-2].minor.yy432,&yymsp[0].minor.yy410);} +#line 2616 "parse.c" + break; + case 173: +#line 619 "parse.y" +{yygotominor.yy432 = sqlite3IdListAppend(0,&yymsp[0].minor.yy410);} +#line 2621 "parse.c" + break; + case 175: +#line 630 "parse.y" +{yygotominor.yy172 = yymsp[-1].minor.yy172; sqlite3ExprSpan(yygotominor.yy172,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); } +#line 2626 "parse.c" + break; + case 176: + case 181: + case 182: +#line 631 "parse.y" +{yygotominor.yy172 = sqlite3Expr(yymsp[0].major, 0, 0, &yymsp[0].minor.yy0);} +#line 2633 "parse.c" + break; + case 177: + case 178: +#line 632 "parse.y" +{yygotominor.yy172 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy0);} +#line 2639 "parse.c" + break; + case 179: +#line 634 "parse.y" +{ + Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy410); + Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy410); + yygotominor.yy172 = sqlite3Expr(TK_DOT, temp1, temp2, 0); +} +#line 2648 "parse.c" + break; + case 180: +#line 639 "parse.y" +{ + Expr *temp1 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-4].minor.yy410); + Expr *temp2 = sqlite3Expr(TK_ID, 0, 0, &yymsp[-2].minor.yy410); + Expr *temp3 = sqlite3Expr(TK_ID, 0, 0, &yymsp[0].minor.yy410); + Expr *temp4 = sqlite3Expr(TK_DOT, temp2, temp3, 0); + yygotominor.yy172 = sqlite3Expr(TK_DOT, temp1, temp4, 0); +} +#line 2659 "parse.c" + break; + case 183: +#line 648 "parse.y" +{yygotominor.yy172 = sqlite3RegisterExpr(pParse, &yymsp[0].minor.yy0);} +#line 2664 "parse.c" + break; + case 184: +#line 649 "parse.y" +{ + Token *pToken = &yymsp[0].minor.yy0; + Expr *pExpr = yygotominor.yy172 = sqlite3Expr(TK_VARIABLE, 0, 0, pToken); + sqlite3ExprAssignVarNumber(pParse, pExpr); +} +#line 2673 "parse.c" + break; + case 185: +#line 654 "parse.y" +{ + yygotominor.yy172 = sqlite3ExprSetColl(pParse, yymsp[-2].minor.yy172, &yymsp[0].minor.yy410); +} +#line 2680 "parse.c" + break; + case 186: +#line 658 "parse.y" +{ + yygotominor.yy172 = sqlite3Expr(TK_CAST, yymsp[-3].minor.yy172, 0, &yymsp[-1].minor.yy410); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-5].minor.yy0,&yymsp[0].minor.yy0); +} +#line 2688 "parse.c" + break; + case 187: +#line 663 "parse.y" +{ + if( yymsp[-1].minor.yy174 && yymsp[-1].minor.yy174->nExpr>SQLITE_MAX_FUNCTION_ARG ){ + sqlite3ErrorMsg(pParse, "too many arguments on function %T", &yymsp[-4].minor.yy0); + } + yygotominor.yy172 = sqlite3ExprFunction(yymsp[-1].minor.yy174, &yymsp[-4].minor.yy0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0); + if( yymsp[-2].minor.yy46 && yygotominor.yy172 ){ + yygotominor.yy172->flags |= EP_Distinct; + } +} +#line 2702 "parse.c" + break; + case 188: +#line 673 "parse.y" +{ + yygotominor.yy172 = sqlite3ExprFunction(0, &yymsp[-3].minor.yy0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); +} +#line 2710 "parse.c" + break; + case 189: +#line 677 "parse.y" +{ + /* The CURRENT_TIME, CURRENT_DATE, and CURRENT_TIMESTAMP values are + ** treated as functions that return constants */ + yygotominor.yy172 = sqlite3ExprFunction(0,&yymsp[0].minor.yy0); + if( yygotominor.yy172 ){ + yygotominor.yy172->op = TK_CONST_FUNC; + yygotominor.yy172->span = yymsp[0].minor.yy0; + } +} +#line 2723 "parse.c" + break; + case 190: + case 191: + case 192: + case 193: + case 194: + case 195: + case 196: + case 197: +#line 686 "parse.y" +{yygotominor.yy172 = sqlite3Expr(yymsp[-1].major, yymsp[-2].minor.yy172, yymsp[0].minor.yy172, 0);} +#line 2735 "parse.c" + break; + case 198: + case 200: +#line 696 "parse.y" +{yygotominor.yy72.eOperator = yymsp[0].minor.yy0; yygotominor.yy72.not = 0;} +#line 2741 "parse.c" + break; + case 199: + case 201: +#line 697 "parse.y" +{yygotominor.yy72.eOperator = yymsp[0].minor.yy0; yygotominor.yy72.not = 1;} +#line 2747 "parse.c" + break; + case 204: +#line 704 "parse.y" +{ + ExprList *pList; + pList = sqlite3ExprListAppend(0, yymsp[-1].minor.yy172, 0); + pList = sqlite3ExprListAppend(pList, yymsp[-3].minor.yy172, 0); + if( yymsp[0].minor.yy172 ){ + pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy172, 0); + } + yygotominor.yy172 = sqlite3ExprFunction(pList, &yymsp[-2].minor.yy72.eOperator); + if( yymsp[-2].minor.yy72.not ) yygotominor.yy172 = sqlite3Expr(TK_NOT, yygotominor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172, &yymsp[-3].minor.yy172->span, &yymsp[-1].minor.yy172->span); + if( yygotominor.yy172 ) yygotominor.yy172->flags |= EP_InfixFunc; +} +#line 2763 "parse.c" + break; + case 205: +#line 717 "parse.y" +{ + yygotominor.yy172 = sqlite3Expr(yymsp[0].major, yymsp[-1].minor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-1].minor.yy172->span,&yymsp[0].minor.yy0); +} +#line 2771 "parse.c" + break; + case 206: +#line 721 "parse.y" +{ + yygotominor.yy172 = sqlite3Expr(TK_ISNULL, yymsp[-2].minor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-2].minor.yy172->span,&yymsp[0].minor.yy0); +} +#line 2779 "parse.c" + break; + case 207: +#line 725 "parse.y" +{ + yygotominor.yy172 = sqlite3Expr(TK_NOTNULL, yymsp[-2].minor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-2].minor.yy172->span,&yymsp[0].minor.yy0); +} +#line 2787 "parse.c" + break; + case 208: +#line 729 "parse.y" +{ + yygotominor.yy172 = sqlite3Expr(TK_NOTNULL, yymsp[-3].minor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-3].minor.yy172->span,&yymsp[0].minor.yy0); +} +#line 2795 "parse.c" + break; + case 209: +#line 733 "parse.y" +{ + yygotominor.yy172 = sqlite3Expr(yymsp[-1].major, yymsp[0].minor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy172->span); +} +#line 2803 "parse.c" + break; + case 210: +#line 737 "parse.y" +{ + yygotominor.yy172 = sqlite3Expr(TK_UMINUS, yymsp[0].minor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy172->span); +} +#line 2811 "parse.c" + break; + case 211: +#line 741 "parse.y" +{ + yygotominor.yy172 = sqlite3Expr(TK_UPLUS, yymsp[0].minor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy172->span); +} +#line 2819 "parse.c" + break; + case 214: +#line 748 "parse.y" +{ + ExprList *pList = sqlite3ExprListAppend(0, yymsp[-2].minor.yy172, 0); + pList = sqlite3ExprListAppend(pList, yymsp[0].minor.yy172, 0); + yygotominor.yy172 = sqlite3Expr(TK_BETWEEN, yymsp[-4].minor.yy172, 0, 0); + if( yygotominor.yy172 ){ + yygotominor.yy172->pList = pList; + }else{ + sqlite3ExprListDelete(pList); + } + if( yymsp[-3].minor.yy46 ) yygotominor.yy172 = sqlite3Expr(TK_NOT, yygotominor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-4].minor.yy172->span,&yymsp[0].minor.yy172->span); +} +#line 2835 "parse.c" + break; + case 217: +#line 764 "parse.y" +{ + yygotominor.yy172 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy172, 0, 0); + if( yygotominor.yy172 ){ + yygotominor.yy172->pList = yymsp[-1].minor.yy174; + sqlite3ExprSetHeight(yygotominor.yy172); + }else{ + sqlite3ExprListDelete(yymsp[-1].minor.yy174); + } + if( yymsp[-3].minor.yy46 ) yygotominor.yy172 = sqlite3Expr(TK_NOT, yygotominor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-4].minor.yy172->span,&yymsp[0].minor.yy0); + } +#line 2850 "parse.c" + break; + case 218: +#line 775 "parse.y" +{ + yygotominor.yy172 = sqlite3Expr(TK_SELECT, 0, 0, 0); + if( yygotominor.yy172 ){ + yygotominor.yy172->pSelect = yymsp[-1].minor.yy219; + sqlite3ExprSetHeight(yygotominor.yy172); + }else{ + sqlite3SelectDelete(yymsp[-1].minor.yy219); + } + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); + } +#line 2864 "parse.c" + break; + case 219: +#line 785 "parse.y" +{ + yygotominor.yy172 = sqlite3Expr(TK_IN, yymsp[-4].minor.yy172, 0, 0); + if( yygotominor.yy172 ){ + yygotominor.yy172->pSelect = yymsp[-1].minor.yy219; + sqlite3ExprSetHeight(yygotominor.yy172); + }else{ + sqlite3SelectDelete(yymsp[-1].minor.yy219); + } + if( yymsp[-3].minor.yy46 ) yygotominor.yy172 = sqlite3Expr(TK_NOT, yygotominor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-4].minor.yy172->span,&yymsp[0].minor.yy0); + } +#line 2879 "parse.c" + break; + case 220: +#line 796 "parse.y" +{ + SrcList *pSrc = sqlite3SrcListAppend(0,&yymsp[-1].minor.yy410,&yymsp[0].minor.yy410); + yygotominor.yy172 = sqlite3Expr(TK_IN, yymsp[-3].minor.yy172, 0, 0); + if( yygotominor.yy172 ){ + yygotominor.yy172->pSelect = sqlite3SelectNew(0,pSrc,0,0,0,0,0,0,0); + sqlite3ExprSetHeight(yygotominor.yy172); + }else{ + sqlite3SrcListDelete(pSrc); + } + if( yymsp[-2].minor.yy46 ) yygotominor.yy172 = sqlite3Expr(TK_NOT, yygotominor.yy172, 0, 0); + sqlite3ExprSpan(yygotominor.yy172,&yymsp[-3].minor.yy172->span,yymsp[0].minor.yy410.z?&yymsp[0].minor.yy410:&yymsp[-1].minor.yy410); + } +#line 2895 "parse.c" + break; + case 221: +#line 808 "parse.y" +{ + Expr *p = yygotominor.yy172 = sqlite3Expr(TK_EXISTS, 0, 0, 0); + if( p ){ + p->pSelect = yymsp[-1].minor.yy219; + sqlite3ExprSpan(p,&yymsp[-3].minor.yy0,&yymsp[0].minor.yy0); + sqlite3ExprSetHeight(yygotominor.yy172); + }else{ + sqlite3SelectDelete(yymsp[-1].minor.yy219); + } + } +#line 2909 "parse.c" + break; + case 222: +#line 821 "parse.y" +{ + yygotominor.yy172 = sqlite3Expr(TK_CASE, yymsp[-3].minor.yy172, yymsp[-1].minor.yy172, 0); + if( yygotominor.yy172 ){ + yygotominor.yy172->pList = yymsp[-2].minor.yy174; + sqlite3ExprSetHeight(yygotominor.yy172); + }else{ + sqlite3ExprListDelete(yymsp[-2].minor.yy174); + } + sqlite3ExprSpan(yygotominor.yy172, &yymsp[-4].minor.yy0, &yymsp[0].minor.yy0); +} +#line 2923 "parse.c" + break; + case 223: +#line 833 "parse.y" +{ + yygotominor.yy174 = sqlite3ExprListAppend(yymsp[-4].minor.yy174, yymsp[-2].minor.yy172, 0); + yygotominor.yy174 = sqlite3ExprListAppend(yygotominor.yy174, yymsp[0].minor.yy172, 0); +} +#line 2931 "parse.c" + break; + case 224: +#line 837 "parse.y" +{ + yygotominor.yy174 = sqlite3ExprListAppend(0, yymsp[-2].minor.yy172, 0); + yygotominor.yy174 = sqlite3ExprListAppend(yygotominor.yy174, yymsp[0].minor.yy172, 0); +} +#line 2939 "parse.c" + break; + case 233: +#line 864 "parse.y" +{ + sqlite3CreateIndex(pParse, &yymsp[-6].minor.yy410, &yymsp[-5].minor.yy410, sqlite3SrcListAppend(0,&yymsp[-3].minor.yy410,0), yymsp[-1].minor.yy174, yymsp[-9].minor.yy46, + &yymsp[-10].minor.yy0, &yymsp[0].minor.yy0, SQLITE_SO_ASC, yymsp[-7].minor.yy46); +} +#line 2947 "parse.c" + break; + case 234: + case 281: +#line 870 "parse.y" +{yygotominor.yy46 = OE_Abort;} +#line 2953 "parse.c" + break; + case 235: +#line 871 "parse.y" +{yygotominor.yy46 = OE_None;} +#line 2958 "parse.c" + break; + case 238: +#line 881 "parse.y" +{ + Expr *p = 0; + if( yymsp[-1].minor.yy410.n>0 ){ + p = sqlite3Expr(TK_COLUMN, 0, 0, 0); + if( p ) p->pColl = sqlite3LocateCollSeq(pParse, (char*)yymsp[-1].minor.yy410.z, yymsp[-1].minor.yy410.n); + } + yygotominor.yy174 = sqlite3ExprListAppend(yymsp[-4].minor.yy174, p, &yymsp[-2].minor.yy410); + sqlite3ExprListCheckLength(pParse, yygotominor.yy174, SQLITE_MAX_COLUMN, "index"); + if( yygotominor.yy174 ) yygotominor.yy174->a[yygotominor.yy174->nExpr-1].sortOrder = yymsp[0].minor.yy46; +} +#line 2972 "parse.c" + break; + case 239: +#line 891 "parse.y" +{ + Expr *p = 0; + if( yymsp[-1].minor.yy410.n>0 ){ + p = sqlite3Expr(TK_COLUMN, 0, 0, 0); + if( p ) p->pColl = sqlite3LocateCollSeq(pParse, (char*)yymsp[-1].minor.yy410.z, yymsp[-1].minor.yy410.n); + } + yygotominor.yy174 = sqlite3ExprListAppend(0, p, &yymsp[-2].minor.yy410); + sqlite3ExprListCheckLength(pParse, yygotominor.yy174, SQLITE_MAX_COLUMN, "index"); + if( yygotominor.yy174 ) yygotominor.yy174->a[yygotominor.yy174->nExpr-1].sortOrder = yymsp[0].minor.yy46; +} +#line 2986 "parse.c" + break; + case 241: +#line 904 "parse.y" +{yygotominor.yy410.z = 0; yygotominor.yy410.n = 0;} +#line 2991 "parse.c" + break; + case 243: +#line 910 "parse.y" +{sqlite3DropIndex(pParse, yymsp[0].minor.yy373, yymsp[-1].minor.yy46);} +#line 2996 "parse.c" + break; + case 244: + case 245: +#line 916 "parse.y" +{sqlite3Vacuum(pParse);} +#line 3002 "parse.c" + break; + case 246: +#line 924 "parse.y" +{sqlite3Pragma(pParse,&yymsp[-3].minor.yy410,&yymsp[-2].minor.yy410,&yymsp[0].minor.yy410,0);} +#line 3007 "parse.c" + break; + case 247: +#line 925 "parse.y" +{sqlite3Pragma(pParse,&yymsp[-3].minor.yy410,&yymsp[-2].minor.yy410,&yymsp[0].minor.yy0,0);} +#line 3012 "parse.c" + break; + case 248: +#line 926 "parse.y" +{ + sqlite3Pragma(pParse,&yymsp[-3].minor.yy410,&yymsp[-2].minor.yy410,&yymsp[0].minor.yy410,1); +} +#line 3019 "parse.c" + break; + case 249: +#line 929 "parse.y" +{sqlite3Pragma(pParse,&yymsp[-4].minor.yy410,&yymsp[-3].minor.yy410,&yymsp[-1].minor.yy410,0);} +#line 3024 "parse.c" + break; + case 250: +#line 930 "parse.y" +{sqlite3Pragma(pParse,&yymsp[-1].minor.yy410,&yymsp[0].minor.yy410,0,0);} +#line 3029 "parse.c" + break; + case 258: +#line 944 "parse.y" +{ + Token all; + all.z = yymsp[-3].minor.yy410.z; + all.n = (yymsp[0].minor.yy0.z - yymsp[-3].minor.yy410.z) + yymsp[0].minor.yy0.n; + sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy243, &all); +} +#line 3039 "parse.c" + break; + case 259: +#line 953 "parse.y" +{ + sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy410, &yymsp[-6].minor.yy410, yymsp[-5].minor.yy46, yymsp[-4].minor.yy370.a, yymsp[-4].minor.yy370.b, yymsp[-2].minor.yy373, yymsp[0].minor.yy172, yymsp[-10].minor.yy46, yymsp[-8].minor.yy46); + yygotominor.yy410 = (yymsp[-6].minor.yy410.n==0?yymsp[-7].minor.yy410:yymsp[-6].minor.yy410); +} +#line 3047 "parse.c" + break; + case 260: + case 263: +#line 959 "parse.y" +{ yygotominor.yy46 = TK_BEFORE; } +#line 3053 "parse.c" + break; + case 261: +#line 960 "parse.y" +{ yygotominor.yy46 = TK_AFTER; } +#line 3058 "parse.c" + break; + case 262: +#line 961 "parse.y" +{ yygotominor.yy46 = TK_INSTEAD;} +#line 3063 "parse.c" + break; + case 264: + case 265: +#line 966 "parse.y" +{yygotominor.yy370.a = yymsp[0].major; yygotominor.yy370.b = 0;} +#line 3069 "parse.c" + break; + case 266: +#line 968 "parse.y" +{yygotominor.yy370.a = TK_UPDATE; yygotominor.yy370.b = yymsp[0].minor.yy432;} +#line 3074 "parse.c" + break; + case 269: +#line 975 "parse.y" +{ yygotominor.yy172 = 0; } +#line 3079 "parse.c" + break; + case 270: +#line 976 "parse.y" +{ yygotominor.yy172 = yymsp[0].minor.yy172; } +#line 3084 "parse.c" + break; + case 271: +#line 980 "parse.y" +{ + if( yymsp[-2].minor.yy243 ){ + yymsp[-2].minor.yy243->pLast->pNext = yymsp[-1].minor.yy243; + }else{ + yymsp[-2].minor.yy243 = yymsp[-1].minor.yy243; + } + yymsp[-2].minor.yy243->pLast = yymsp[-1].minor.yy243; + yygotominor.yy243 = yymsp[-2].minor.yy243; +} +#line 3097 "parse.c" + break; + case 272: +#line 989 "parse.y" +{ yygotominor.yy243 = 0; } +#line 3102 "parse.c" + break; + case 273: +#line 995 "parse.y" +{ yygotominor.yy243 = sqlite3TriggerUpdateStep(&yymsp[-3].minor.yy410, yymsp[-1].minor.yy174, yymsp[0].minor.yy172, yymsp[-4].minor.yy46); } +#line 3107 "parse.c" + break; + case 274: +#line 1000 "parse.y" +{yygotominor.yy243 = sqlite3TriggerInsertStep(&yymsp[-5].minor.yy410, yymsp[-4].minor.yy432, yymsp[-1].minor.yy174, 0, yymsp[-7].minor.yy46);} +#line 3112 "parse.c" + break; + case 275: +#line 1003 "parse.y" +{yygotominor.yy243 = sqlite3TriggerInsertStep(&yymsp[-2].minor.yy410, yymsp[-1].minor.yy432, 0, yymsp[0].minor.yy219, yymsp[-4].minor.yy46);} +#line 3117 "parse.c" + break; + case 276: +#line 1007 "parse.y" +{yygotominor.yy243 = sqlite3TriggerDeleteStep(&yymsp[-1].minor.yy410, yymsp[0].minor.yy172);} +#line 3122 "parse.c" + break; + case 277: +#line 1010 "parse.y" +{yygotominor.yy243 = sqlite3TriggerSelectStep(yymsp[0].minor.yy219); } +#line 3127 "parse.c" + break; + case 278: +#line 1013 "parse.y" +{ + yygotominor.yy172 = sqlite3Expr(TK_RAISE, 0, 0, 0); + if( yygotominor.yy172 ){ + yygotominor.yy172->iColumn = OE_Ignore; + sqlite3ExprSpan(yygotominor.yy172, &yymsp[-3].minor.yy0, &yymsp[0].minor.yy0); + } +} +#line 3138 "parse.c" + break; + case 279: +#line 1020 "parse.y" +{ + yygotominor.yy172 = sqlite3Expr(TK_RAISE, 0, 0, &yymsp[-1].minor.yy410); + if( yygotominor.yy172 ) { + yygotominor.yy172->iColumn = yymsp[-3].minor.yy46; + sqlite3ExprSpan(yygotominor.yy172, &yymsp[-5].minor.yy0, &yymsp[0].minor.yy0); + } +} +#line 3149 "parse.c" + break; + case 280: +#line 1030 "parse.y" +{yygotominor.yy46 = OE_Rollback;} +#line 3154 "parse.c" + break; + case 282: +#line 1032 "parse.y" +{yygotominor.yy46 = OE_Fail;} +#line 3159 "parse.c" + break; + case 283: +#line 1037 "parse.y" +{ + sqlite3DropTrigger(pParse,yymsp[0].minor.yy373,yymsp[-1].minor.yy46); +} +#line 3166 "parse.c" + break; + case 284: +#line 1044 "parse.y" +{ + sqlite3Attach(pParse, yymsp[-3].minor.yy172, yymsp[-1].minor.yy172, yymsp[0].minor.yy386); +} +#line 3173 "parse.c" + break; + case 285: +#line 1047 "parse.y" +{ + sqlite3Detach(pParse, yymsp[0].minor.yy172); +} +#line 3180 "parse.c" + break; + case 286: +#line 1053 "parse.y" +{ yygotominor.yy386 = 0; } +#line 3185 "parse.c" + break; + case 287: +#line 1054 "parse.y" +{ yygotominor.yy386 = yymsp[0].minor.yy172; } +#line 3190 "parse.c" + break; + case 290: +#line 1062 "parse.y" +{sqlite3Reindex(pParse, 0, 0);} +#line 3195 "parse.c" + break; + case 291: +#line 1063 "parse.y" +{sqlite3Reindex(pParse, &yymsp[-1].minor.yy410, &yymsp[0].minor.yy410);} +#line 3200 "parse.c" + break; + case 292: +#line 1068 "parse.y" +{sqlite3Analyze(pParse, 0, 0);} +#line 3205 "parse.c" + break; + case 293: +#line 1069 "parse.y" +{sqlite3Analyze(pParse, &yymsp[-1].minor.yy410, &yymsp[0].minor.yy410);} +#line 3210 "parse.c" + break; + case 294: +#line 1074 "parse.y" +{ + sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy373,&yymsp[0].minor.yy410); +} +#line 3217 "parse.c" + break; + case 295: +#line 1077 "parse.y" +{ + sqlite3AlterFinishAddColumn(pParse, &yymsp[0].minor.yy410); +} +#line 3224 "parse.c" + break; + case 296: +#line 1080 "parse.y" +{ + sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy373); +} +#line 3231 "parse.c" + break; + case 299: +#line 1089 "parse.y" +{sqlite3VtabFinishParse(pParse,0);} +#line 3236 "parse.c" + break; + case 300: +#line 1090 "parse.y" +{sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);} +#line 3241 "parse.c" + break; + case 301: +#line 1091 "parse.y" +{ + sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy410, &yymsp[-2].minor.yy410, &yymsp[0].minor.yy410); +} +#line 3248 "parse.c" + break; + case 304: +#line 1096 "parse.y" +{sqlite3VtabArgInit(pParse);} +#line 3253 "parse.c" + break; + case 306: + case 307: + case 308: + case 310: +#line 1098 "parse.y" +{sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);} +#line 3261 "parse.c" + break; + }; + yygoto = yyRuleInfo[yyruleno].lhs; + yysize = yyRuleInfo[yyruleno].nrhs; + yypParser->yyidx -= yysize; + yyact = yy_find_reduce_action(yymsp[-yysize].stateno,yygoto); + if( yyact < YYNSTATE ){ +#ifdef NDEBUG + /* If we are not debugging and the reduce action popped at least + ** one element off the stack, then we can push the new element back + ** onto the stack here, and skip the stack overflow test in yy_shift(). + ** That gives a significant speed improvement. */ + if( yysize ){ + yypParser->yyidx++; + yymsp -= yysize-1; + yymsp->stateno = yyact; + yymsp->major = yygoto; + yymsp->minor = yygotominor; + }else +#endif + { + yy_shift(yypParser,yyact,yygoto,&yygotominor); + } + }else if( yyact == YYNSTATE + YYNRULE + 1 ){ + yy_accept(yypParser); + } +} + +/* +** The following code executes when the parse fails +*/ +static void yy_parse_failed( + yyParser *yypParser /* The parser */ +){ + sqlite3ParserARG_FETCH; +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt); + } +#endif + while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); + /* Here code is inserted which will be executed whenever the + ** parser fails */ + sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ +} + +/* +** The following code executes when a syntax error first occurs. +*/ +static void yy_syntax_error( + yyParser *yypParser, /* The parser */ + int yymajor, /* The major type of the error token */ + YYMINORTYPE yyminor /* The minor type of the error token */ +){ + sqlite3ParserARG_FETCH; +#define TOKEN (yyminor.yy0) +#line 34 "parse.y" + + if( !pParse->parseError ){ + if( TOKEN.z[0] ){ + sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &TOKEN); + }else{ + sqlite3ErrorMsg(pParse, "incomplete SQL statement"); + } + pParse->parseError = 1; + } +#line 3329 "parse.c" + sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ +} + +/* +** The following is executed when the parser accepts +*/ +static void yy_accept( + yyParser *yypParser /* The parser */ +){ + sqlite3ParserARG_FETCH; +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt); + } +#endif + while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser); + /* Here code is inserted which will be executed whenever the + ** parser accepts */ + sqlite3ParserARG_STORE; /* Suppress warning about unused %extra_argument variable */ +} + +/* The main parser program. +** The first argument is a pointer to a structure obtained from +** "sqlite3ParserAlloc" which describes the current state of the parser. +** The second argument is the major token number. The third is +** the minor token. The fourth optional argument is whatever the +** user wants (and specified in the grammar) and is available for +** use by the action routines. +** +** Inputs: +**
    +**
  • A pointer to the parser (an opaque structure.) +**
  • The major token number. +**
  • The minor token number. +**
  • An option argument of a grammar-specified type. +**
+** +** Outputs: +** None. +*/ +void sqlite3Parser( + void *yyp, /* The parser */ + int yymajor, /* The major token code number */ + sqlite3ParserTOKENTYPE yyminor /* The value for the token */ + sqlite3ParserARG_PDECL /* Optional %extra_argument parameter */ +){ + YYMINORTYPE yyminorunion; + int yyact; /* The parser action. */ + int yyendofinput; /* True if we are at the end of input */ + int yyerrorhit = 0; /* True if yymajor has invoked an error */ + yyParser *yypParser; /* The parser */ + + /* (re)initialize the parser, if necessary */ + yypParser = (yyParser*)yyp; + if( yypParser->yyidx<0 ){ +#if YYSTACKDEPTH<=0 + if( yypParser->yystksz <=0 ){ + memset(&yyminorunion, 0, sizeof(yyminorunion)); + yyStackOverflow(yypParser, &yyminorunion); + return; + } +#endif + yypParser->yyidx = 0; + yypParser->yyerrcnt = -1; + yypParser->yystack[0].stateno = 0; + yypParser->yystack[0].major = 0; + } + yyminorunion.yy0 = yyminor; + yyendofinput = (yymajor==0); + sqlite3ParserARG_STORE; + +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]); + } +#endif + + do{ + yyact = yy_find_shift_action(yypParser,yymajor); + if( yyactyyerrcnt--; + if( yyendofinput && yypParser->yyidx>=0 ){ + yymajor = 0; + }else{ + yymajor = YYNOCODE; + } + }else if( yyact < YYNSTATE + YYNRULE ){ + yy_reduce(yypParser,yyact-YYNSTATE); + }else if( yyact == YY_ERROR_ACTION ){ + int yymx; +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt); + } +#endif +#ifdef YYERRORSYMBOL + /* A syntax error has occurred. + ** The response to an error depends upon whether or not the + ** grammar defines an error token "ERROR". + ** + ** This is what we do if the grammar does define ERROR: + ** + ** * Call the %syntax_error function. + ** + ** * Begin popping the stack until we enter a state where + ** it is legal to shift the error symbol, then shift + ** the error symbol. + ** + ** * Set the error count to three. + ** + ** * Begin accepting and shifting new tokens. No new error + ** processing will occur until three tokens have been + ** shifted successfully. + ** + */ + if( yypParser->yyerrcnt<0 ){ + yy_syntax_error(yypParser,yymajor,yyminorunion); + } + yymx = yypParser->yystack[yypParser->yyidx].major; + if( yymx==YYERRORSYMBOL || yyerrorhit ){ +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sDiscard input token %s\n", + yyTracePrompt,yyTokenName[yymajor]); + } +#endif + yy_destructor(yymajor,&yyminorunion); + yymajor = YYNOCODE; + }else{ + while( + yypParser->yyidx >= 0 && + yymx != YYERRORSYMBOL && + (yyact = yy_find_reduce_action( + yypParser->yystack[yypParser->yyidx].stateno, + YYERRORSYMBOL)) >= YYNSTATE + ){ + yy_pop_parser_stack(yypParser); + } + if( yypParser->yyidx < 0 || yymajor==0 ){ + yy_destructor(yymajor,&yyminorunion); + yy_parse_failed(yypParser); + yymajor = YYNOCODE; + }else if( yymx!=YYERRORSYMBOL ){ + YYMINORTYPE u2; + u2.YYERRSYMDT = 0; + yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2); + } + } + yypParser->yyerrcnt = 3; + yyerrorhit = 1; +#else /* YYERRORSYMBOL is not defined */ + /* This is what we do if the grammar does not define ERROR: + ** + ** * Report an error message, and throw away the input token. + ** + ** * If the input token is $, then fail the parse. + ** + ** As before, subsequent error messages are suppressed until + ** three input tokens have been successfully shifted. + */ + if( yypParser->yyerrcnt<=0 ){ + yy_syntax_error(yypParser,yymajor,yyminorunion); + } + yypParser->yyerrcnt = 3; + yy_destructor(yymajor,&yyminorunion); + if( yyendofinput ){ + yy_parse_failed(yypParser); + } + yymajor = YYNOCODE; +#endif + }else{ + yy_accept(yypParser); + yymajor = YYNOCODE; + } + }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 ); + return; +} diff --git a/extensions/sqlite/sqlite-source/parse.h b/extensions/sqlite/sqlite-source/parse.h new file mode 100644 index 00000000..ed848ec5 --- /dev/null +++ b/extensions/sqlite/sqlite-source/parse.h @@ -0,0 +1,152 @@ +#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_TRIGGER 52 +#define TK_VACUUM 53 +#define TK_VIEW 54 +#define TK_VIRTUAL 55 +#define TK_REINDEX 56 +#define TK_RENAME 57 +#define TK_CTIME_KW 58 +#define TK_ANY 59 +#define TK_OR 60 +#define TK_AND 61 +#define TK_IS 62 +#define TK_BETWEEN 63 +#define TK_IN 64 +#define TK_ISNULL 65 +#define TK_NOTNULL 66 +#define TK_NE 67 +#define TK_EQ 68 +#define TK_GT 69 +#define TK_LE 70 +#define TK_LT 71 +#define TK_GE 72 +#define TK_ESCAPE 73 +#define TK_BITAND 74 +#define TK_BITOR 75 +#define TK_LSHIFT 76 +#define TK_RSHIFT 77 +#define TK_PLUS 78 +#define TK_MINUS 79 +#define TK_STAR 80 +#define TK_SLASH 81 +#define TK_REM 82 +#define TK_CONCAT 83 +#define TK_COLLATE 84 +#define TK_UMINUS 85 +#define TK_UPLUS 86 +#define TK_BITNOT 87 +#define TK_STRING 88 +#define TK_JOIN_KW 89 +#define TK_CONSTRAINT 90 +#define TK_DEFAULT 91 +#define TK_NULL 92 +#define TK_PRIMARY 93 +#define TK_UNIQUE 94 +#define TK_CHECK 95 +#define TK_REFERENCES 96 +#define TK_AUTOINCR 97 +#define TK_ON 98 +#define TK_DELETE 99 +#define TK_UPDATE 100 +#define TK_INSERT 101 +#define TK_SET 102 +#define TK_DEFERRABLE 103 +#define TK_FOREIGN 104 +#define TK_DROP 105 +#define TK_UNION 106 +#define TK_ALL 107 +#define TK_EXCEPT 108 +#define TK_INTERSECT 109 +#define TK_SELECT 110 +#define TK_DISTINCT 111 +#define TK_DOT 112 +#define TK_FROM 113 +#define TK_JOIN 114 +#define TK_USING 115 +#define TK_ORDER 116 +#define TK_BY 117 +#define TK_GROUP 118 +#define TK_HAVING 119 +#define TK_LIMIT 120 +#define TK_WHERE 121 +#define TK_INTO 122 +#define TK_VALUES 123 +#define TK_INTEGER 124 +#define TK_FLOAT 125 +#define TK_BLOB 126 +#define TK_REGISTER 127 +#define TK_VARIABLE 128 +#define TK_CASE 129 +#define TK_WHEN 130 +#define TK_THEN 131 +#define TK_ELSE 132 +#define TK_INDEX 133 +#define TK_ALTER 134 +#define TK_TO 135 +#define TK_ADD 136 +#define TK_COLUMNKW 137 +#define TK_TO_TEXT 138 +#define TK_TO_BLOB 139 +#define TK_TO_NUMERIC 140 +#define TK_TO_INT 141 +#define TK_TO_REAL 142 +#define TK_END_OF_FILE 143 +#define TK_ILLEGAL 144 +#define TK_SPACE 145 +#define TK_UNCLOSED_STRING 146 +#define TK_COMMENT 147 +#define TK_FUNCTION 148 +#define TK_COLUMN 149 +#define TK_AGG_FUNCTION 150 +#define TK_AGG_COLUMN 151 +#define TK_CONST_FUNC 152 diff --git a/extensions/sqlite/sqlite-source/pragma.c b/extensions/sqlite/sqlite-source/pragma.c new file mode 100644 index 00000000..6844c249 --- /dev/null +++ b/extensions/sqlite/sqlite-source/pragma.c @@ -0,0 +1,1180 @@ +/* +** 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 PRAGMA command. +** +** $Id$ +*/ +#include "sqliteInt.h" +#include "os.h" +#include + +/* Ignore this whole file if pragmas are disabled +*/ +#if !defined(SQLITE_OMIT_PRAGMA) && !defined(SQLITE_OMIT_PARSER) + +#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) +# include "pager.h" +# include "btree.h" +#endif + +/* +** Interpret the given string as a safety level. Return 0 for OFF, +** 1 for ON or NORMAL and 2 for FULL. Return 1 for an empty or +** unrecognized string argument. +** +** Note that the values returned are one less that the values that +** should be passed into sqlite3BtreeSetSafetyLevel(). The is done +** to support legacy SQL code. The safety level used to be boolean +** and older scripts may have used numbers 0 for OFF and 1 for ON. +*/ +static int getSafetyLevel(const char *z){ + /* 123456789 123456789 */ + static const char zText[] = "onoffalseyestruefull"; + static const u8 iOffset[] = {0, 1, 2, 4, 9, 12, 16}; + static const u8 iLength[] = {2, 2, 3, 5, 3, 4, 4}; + static const u8 iValue[] = {1, 0, 0, 0, 1, 1, 2}; + int i, n; + if( isdigit(*z) ){ + return atoi(z); + } + n = strlen(z); + for(i=0; i=0&&i<=2)?i:0); +} +#endif /* ifndef SQLITE_OMIT_AUTOVACUUM */ + +#ifndef SQLITE_OMIT_PAGER_PRAGMAS +/* +** Interpret the given string as a temp db location. Return 1 for file +** backed temporary databases, 2 for the Red-Black tree in memory database +** and 0 to use the compile-time default. +*/ +static int getTempStore(const char *z){ + if( z[0]>='0' && z[0]<='2' ){ + return z[0] - '0'; + }else if( sqlite3StrICmp(z, "file")==0 ){ + return 1; + }else if( sqlite3StrICmp(z, "memory")==0 ){ + return 2; + }else{ + return 0; + } +} +#endif /* SQLITE_PAGER_PRAGMAS */ + +#ifndef SQLITE_OMIT_PAGER_PRAGMAS +/* +** Invalidate temp storage, either when the temp storage is changed +** from default, or when 'file' and the temp_store_directory has changed +*/ +static int invalidateTempStorage(Parse *pParse){ + sqlite3 *db = pParse->db; + if( db->aDb[1].pBt!=0 ){ + if( !db->autoCommit ){ + sqlite3ErrorMsg(pParse, "temporary storage cannot be changed " + "from within a transaction"); + return SQLITE_ERROR; + } + sqlite3BtreeClose(db->aDb[1].pBt); + db->aDb[1].pBt = 0; + sqlite3ResetInternalSchema(db, 0); + } + return SQLITE_OK; +} +#endif /* SQLITE_PAGER_PRAGMAS */ + +#ifndef SQLITE_OMIT_PAGER_PRAGMAS +/* +** If the TEMP database is open, close it and mark the database schema +** as needing reloading. This must be done when using the TEMP_STORE +** or DEFAULT_TEMP_STORE pragmas. +*/ +static int changeTempStorage(Parse *pParse, const char *zStorageType){ + int ts = getTempStore(zStorageType); + sqlite3 *db = pParse->db; + if( db->temp_store==ts ) return SQLITE_OK; + if( invalidateTempStorage( pParse ) != SQLITE_OK ){ + return SQLITE_ERROR; + } + db->temp_store = ts; + return SQLITE_OK; +} +#endif /* SQLITE_PAGER_PRAGMAS */ + +/* +** Generate code to return a single integer value. +*/ +static void returnSingleInt(Parse *pParse, const char *zLabel, int value){ + Vdbe *v = sqlite3GetVdbe(pParse); + sqlite3VdbeAddOp(v, OP_Integer, value, 0); + if( pParse->explain==0 ){ + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, P3_STATIC); + } + sqlite3VdbeAddOp(v, OP_Callback, 1, 0); +} + +#ifndef SQLITE_OMIT_FLAG_PRAGMAS +/* +** Check to see if zRight and zLeft refer to a pragma that queries +** or changes one of the flags in db->flags. Return 1 if so and 0 if not. +** Also, implement the pragma. +*/ +static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){ + static const struct sPragmaType { + const char *zName; /* Name of the pragma */ + int mask; /* Mask for the db->flags value */ + } aPragma[] = { + { "full_column_names", SQLITE_FullColNames }, + { "short_column_names", SQLITE_ShortColNames }, + { "count_changes", SQLITE_CountRows }, + { "empty_result_callbacks", SQLITE_NullCallback }, + { "legacy_file_format", SQLITE_LegacyFileFmt }, + { "fullfsync", SQLITE_FullFSync }, +#ifdef SQLITE_DEBUG + { "sql_trace", SQLITE_SqlTrace }, + { "vdbe_listing", SQLITE_VdbeListing }, + { "vdbe_trace", SQLITE_VdbeTrace }, +#endif +#ifndef SQLITE_OMIT_CHECK + { "ignore_check_constraints", SQLITE_IgnoreChecks }, +#endif + /* The following is VERY experimental */ + { "writable_schema", SQLITE_WriteSchema|SQLITE_RecoveryMode }, + { "omit_readlock", SQLITE_NoReadlock }, + + /* TODO: Maybe it shouldn't be possible to change the ReadUncommitted + ** flag if there are any active statements. */ + { "read_uncommitted", SQLITE_ReadUncommitted }, + }; + int i; + const struct sPragmaType *p; + for(i=0, p=aPragma; izName)==0 ){ + sqlite3 *db = pParse->db; + Vdbe *v; + v = sqlite3GetVdbe(pParse); + if( v ){ + if( zRight==0 ){ + returnSingleInt(pParse, p->zName, (db->flags & p->mask)!=0 ); + }else{ + if( getBoolean(zRight) ){ + db->flags |= p->mask; + }else{ + db->flags &= ~p->mask; + } + } + } + return 1; + } + } + return 0; +} +#endif /* SQLITE_OMIT_FLAG_PRAGMAS */ + +/* +** Process a pragma statement. +** +** Pragmas are of this form: +** +** PRAGMA [database.]id [= value] +** +** The identifier might also be a string. The value is a string, and +** identifier, or a number. If minusFlag is true, then the value is +** a number that was preceded by a minus sign. +** +** If the left side is "database.id" then pId1 is the database name +** and pId2 is the id. If the left side is just "id" then pId1 is the +** id and pId2 is any empty string. +*/ +void sqlite3Pragma( + Parse *pParse, + Token *pId1, /* First part of [database.]id field */ + Token *pId2, /* Second part of [database.]id field, or NULL */ + Token *pValue, /* Token for , or NULL */ + int minusFlag /* True if a '-' sign preceded */ +){ + char *zLeft = 0; /* Nul-terminated UTF-8 string */ + char *zRight = 0; /* Nul-terminated UTF-8 string , or NULL */ + const char *zDb = 0; /* The database name */ + Token *pId; /* Pointer to token */ + int iDb; /* Database index for */ + sqlite3 *db = pParse->db; + Db *pDb; + Vdbe *v = sqlite3GetVdbe(pParse); + if( v==0 ) return; + + /* Interpret the [database.] part of the pragma statement. iDb is the + ** index of the database this pragma is being applied to in db.aDb[]. */ + iDb = sqlite3TwoPartName(pParse, pId1, pId2, &pId); + if( iDb<0 ) return; + pDb = &db->aDb[iDb]; + + /* If the temp database has been explicitly named as part of the + ** pragma, make sure it is open. + */ + if( iDb==1 && sqlite3OpenTempDatabase(pParse) ){ + return; + } + + zLeft = sqlite3NameFromToken(pId); + if( !zLeft ) return; + if( minusFlag ){ + zRight = sqlite3MPrintf("-%T", pValue); + }else{ + zRight = sqlite3NameFromToken(pValue); + } + + zDb = ((iDb>0)?pDb->zName:0); + if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, zDb) ){ + goto pragma_out; + } + +#ifndef SQLITE_OMIT_PAGER_PRAGMAS + /* + ** PRAGMA [database.]default_cache_size + ** PRAGMA [database.]default_cache_size=N + ** + ** The first form reports the current persistent setting for the + ** page cache size. The value returned is the maximum number of + ** pages in the page cache. The second form sets both the current + ** page cache size value and the persistent page cache size value + ** stored in the database file. + ** + ** The default cache size is stored in meta-value 2 of page 1 of the + ** database file. The cache size is actually the absolute value of + ** this memory location. The sign of meta-value 2 determines the + ** synchronous setting. A negative value means synchronous is off + ** and a positive value means synchronous is on. + */ + if( sqlite3StrICmp(zLeft,"default_cache_size")==0 ){ + static const VdbeOpList getCacheSize[] = { + { OP_ReadCookie, 0, 2, 0}, /* 0 */ + { OP_AbsValue, 0, 0, 0}, + { OP_Dup, 0, 0, 0}, + { OP_Integer, 0, 0, 0}, + { OP_Ne, 0, 6, 0}, + { OP_Integer, 0, 0, 0}, /* 5 */ + { OP_Callback, 1, 0, 0}, + }; + int addr; + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + if( !zRight ){ + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", P3_STATIC); + addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize); + sqlite3VdbeChangeP1(v, addr, iDb); + sqlite3VdbeChangeP1(v, addr+5, SQLITE_DEFAULT_CACHE_SIZE); + }else{ + int size = atoi(zRight); + if( size<0 ) size = -size; + sqlite3BeginWriteOperation(pParse, 0, iDb); + sqlite3VdbeAddOp(v, OP_Integer, size, 0); + sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 2); + addr = sqlite3VdbeAddOp(v, OP_Integer, 0, 0); + sqlite3VdbeAddOp(v, OP_Ge, 0, addr+3); + sqlite3VdbeAddOp(v, OP_Negative, 0, 0); + sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 2); + pDb->pSchema->cache_size = size; + sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); + } + }else + + /* + ** PRAGMA [database.]page_size + ** PRAGMA [database.]page_size=N + ** + ** The first form reports the current setting for the + ** database page size in bytes. The second form sets the + ** database page size value. The value can only be set if + ** the database has not yet been created. + */ + if( sqlite3StrICmp(zLeft,"page_size")==0 ){ + Btree *pBt = pDb->pBt; + if( !zRight ){ + int size = pBt ? sqlite3BtreeGetPageSize(pBt) : 0; + returnSingleInt(pParse, "page_size", size); + }else{ + sqlite3BtreeSetPageSize(pBt, atoi(zRight), -1); + } + }else + + /* + ** PRAGMA [database.]max_page_count + ** PRAGMA [database.]max_page_count=N + ** + ** The first form reports the current setting for the + ** maximum number of pages in the database file. The + ** second form attempts to change this setting. Both + ** forms return the current setting. + */ + if( sqlite3StrICmp(zLeft,"max_page_count")==0 ){ + Btree *pBt = pDb->pBt; + int newMax = 0; + if( zRight ){ + newMax = atoi(zRight); + } + if( pBt ){ + newMax = sqlite3BtreeMaxPageCount(pBt, newMax); + } + returnSingleInt(pParse, "max_page_count", newMax); + }else + + /* + ** PRAGMA [database.]locking_mode + ** PRAGMA [database.]locking_mode = (normal|exclusive) + */ + if( sqlite3StrICmp(zLeft,"locking_mode")==0 ){ + const char *zRet = "normal"; + int eMode = getLockingMode(zRight); + + if( pId2->n==0 && eMode==PAGER_LOCKINGMODE_QUERY ){ + /* Simple "PRAGMA locking_mode;" statement. This is a query for + ** the current default locking mode (which may be different to + ** the locking-mode of the main database). + */ + eMode = db->dfltLockMode; + }else{ + Pager *pPager; + if( pId2->n==0 ){ + /* This indicates that no database name was specified as part + ** of the PRAGMA command. In this case the locking-mode must be + ** set on all attached databases, as well as the main db file. + ** + ** Also, the sqlite3.dfltLockMode variable is set so that + ** any subsequently attached databases also use the specified + ** locking mode. + */ + int ii; + assert(pDb==&db->aDb[0]); + for(ii=2; iinDb; ii++){ + pPager = sqlite3BtreePager(db->aDb[ii].pBt); + sqlite3PagerLockingMode(pPager, eMode); + } + db->dfltLockMode = eMode; + } + pPager = sqlite3BtreePager(pDb->pBt); + eMode = sqlite3PagerLockingMode(pPager, eMode); + } + + assert(eMode==PAGER_LOCKINGMODE_NORMAL||eMode==PAGER_LOCKINGMODE_EXCLUSIVE); + if( eMode==PAGER_LOCKINGMODE_EXCLUSIVE ){ + zRet = "exclusive"; + } + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "locking_mode", P3_STATIC); + sqlite3VdbeOp3(v, OP_String8, 0, 0, zRet, 0); + sqlite3VdbeAddOp(v, OP_Callback, 1, 0); + }else +#endif /* SQLITE_OMIT_PAGER_PRAGMAS */ + + /* + ** PRAGMA [database.]auto_vacuum + ** PRAGMA [database.]auto_vacuum=N + ** + ** Get or set the (boolean) value of the database 'auto-vacuum' parameter. + */ +#ifndef SQLITE_OMIT_AUTOVACUUM + if( sqlite3StrICmp(zLeft,"auto_vacuum")==0 ){ + Btree *pBt = pDb->pBt; + if( sqlite3ReadSchema(pParse) ){ + goto pragma_out; + } + if( !zRight ){ + int auto_vacuum = + pBt ? sqlite3BtreeGetAutoVacuum(pBt) : SQLITE_DEFAULT_AUTOVACUUM; + returnSingleInt(pParse, "auto_vacuum", auto_vacuum); + }else{ + int eAuto = getAutoVacuum(zRight); + if( eAuto>=0 ){ + /* Call SetAutoVacuum() to set initialize the internal auto and + ** incr-vacuum flags. This is required in case this connection + ** creates the database file. It is important that it is created + ** as an auto-vacuum capable db. + */ + int rc = sqlite3BtreeSetAutoVacuum(pBt, eAuto); + if( rc==SQLITE_OK && (eAuto==1 || eAuto==2) ){ + /* When setting the auto_vacuum mode to either "full" or + ** "incremental", write the value of meta[6] in the database + ** file. Before writing to meta[6], check that meta[3] indicates + ** that this really is an auto-vacuum capable database. + */ + static const VdbeOpList setMeta6[] = { + { OP_Transaction, 0, 1, 0}, /* 0 */ + { OP_ReadCookie, 0, 3, 0}, /* 1 */ + { OP_If, 0, 0, 0}, /* 2 */ + { OP_Halt, SQLITE_OK, OE_Abort, 0}, /* 3 */ + { OP_Integer, 0, 0, 0}, /* 4 */ + { OP_SetCookie, 0, 6, 0}, /* 5 */ + }; + int iAddr; + iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6); + sqlite3VdbeChangeP1(v, iAddr, iDb); + sqlite3VdbeChangeP1(v, iAddr+1, iDb); + sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4); + sqlite3VdbeChangeP1(v, iAddr+4, eAuto-1); + sqlite3VdbeChangeP1(v, iAddr+5, iDb); + } + } + } + }else +#endif + + /* + ** PRAGMA [database.]incremental_vacuum(N) + ** + ** Do N steps of incremental vacuuming on a database. + */ +#ifndef SQLITE_OMIT_AUTOVACUUM + if( sqlite3StrICmp(zLeft,"incremental_vacuum")==0 ){ + int iLimit, addr; + if( sqlite3ReadSchema(pParse) ){ + goto pragma_out; + } + if( zRight==0 || !sqlite3GetInt32(zRight, &iLimit) || iLimit<=0 ){ + iLimit = 0x7fffffff; + } + sqlite3BeginWriteOperation(pParse, 0, iDb); + sqlite3VdbeAddOp(v, OP_MemInt, iLimit, 0); + addr = sqlite3VdbeAddOp(v, OP_IncrVacuum, iDb, 0); + sqlite3VdbeAddOp(v, OP_Callback, 0, 0); + sqlite3VdbeAddOp(v, OP_MemIncr, -1, 0); + sqlite3VdbeAddOp(v, OP_IfMemPos, 0, addr); + sqlite3VdbeJumpHere(v, addr); + }else +#endif + +#ifndef SQLITE_OMIT_PAGER_PRAGMAS + /* + ** PRAGMA [database.]cache_size + ** PRAGMA [database.]cache_size=N + ** + ** The first form reports the current local setting for the + ** page cache size. The local setting can be different from + ** the persistent cache size value that is stored in the database + ** file itself. The value returned is the maximum number of + ** pages in the page cache. The second form sets the local + ** page cache size value. It does not change the persistent + ** cache size stored on the disk so the cache size will revert + ** to its default value when the database is closed and reopened. + ** N should be a positive integer. + */ + if( sqlite3StrICmp(zLeft,"cache_size")==0 ){ + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + if( !zRight ){ + returnSingleInt(pParse, "cache_size", pDb->pSchema->cache_size); + }else{ + int size = atoi(zRight); + if( size<0 ) size = -size; + pDb->pSchema->cache_size = size; + sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size); + } + }else + + /* + ** PRAGMA temp_store + ** PRAGMA temp_store = "default"|"memory"|"file" + ** + ** Return or set the local value of the temp_store flag. Changing + ** the local value does not make changes to the disk file and the default + ** value will be restored the next time the database is opened. + ** + ** Note that it is possible for the library compile-time options to + ** override this setting + */ + if( sqlite3StrICmp(zLeft, "temp_store")==0 ){ + if( !zRight ){ + returnSingleInt(pParse, "temp_store", db->temp_store); + }else{ + changeTempStorage(pParse, zRight); + } + }else + + /* + ** PRAGMA temp_store_directory + ** PRAGMA temp_store_directory = ""|"directory_name" + ** + ** Return or set the local value of the temp_store_directory flag. Changing + ** the value sets a specific directory to be used for temporary files. + ** Setting to a null string reverts to the default temporary directory search. + ** If temporary directory is changed, then invalidateTempStorage. + ** + */ + if( sqlite3StrICmp(zLeft, "temp_store_directory")==0 ){ + if( !zRight ){ + if( sqlite3_temp_directory ){ + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, + "temp_store_directory", P3_STATIC); + sqlite3VdbeOp3(v, OP_String8, 0, 0, sqlite3_temp_directory, 0); + sqlite3VdbeAddOp(v, OP_Callback, 1, 0); + } + }else{ + if( zRight[0] && !sqlite3OsIsDirWritable(zRight) ){ + sqlite3ErrorMsg(pParse, "not a writable directory"); + goto pragma_out; + } + if( TEMP_STORE==0 + || (TEMP_STORE==1 && db->temp_store<=1) + || (TEMP_STORE==2 && db->temp_store==1) + ){ + invalidateTempStorage(pParse); + } + sqliteFree(sqlite3_temp_directory); + if( zRight[0] ){ + sqlite3_temp_directory = zRight; + zRight = 0; + }else{ + sqlite3_temp_directory = 0; + } + } + }else + + /* + ** PRAGMA [database.]synchronous + ** PRAGMA [database.]synchronous=OFF|ON|NORMAL|FULL + ** + ** Return or set the local value of the synchronous flag. Changing + ** the local value does not make changes to the disk file and the + ** default value will be restored the next time the database is + ** opened. + */ + if( sqlite3StrICmp(zLeft,"synchronous")==0 ){ + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + if( !zRight ){ + returnSingleInt(pParse, "synchronous", pDb->safety_level-1); + }else{ + if( !db->autoCommit ){ + sqlite3ErrorMsg(pParse, + "Safety level may not be changed inside a transaction"); + }else{ + pDb->safety_level = getSafetyLevel(zRight)+1; + } + } + }else +#endif /* SQLITE_OMIT_PAGER_PRAGMAS */ + +#ifndef SQLITE_OMIT_FLAG_PRAGMAS + if( flagPragma(pParse, zLeft, zRight) ){ + /* The flagPragma() subroutine also generates any necessary code + ** there is nothing more to do here */ + }else +#endif /* SQLITE_OMIT_FLAG_PRAGMAS */ + +#ifndef SQLITE_OMIT_SCHEMA_PRAGMAS + /* + ** PRAGMA table_info(
) + ** + ** Return a single row for each column of the named table. The columns of + ** the returned data set are: + ** + ** cid: Column id (numbered from left to right, starting at 0) + ** name: Column name + ** type: Column declaration type. + ** notnull: True if 'NOT NULL' is part of column declaration + ** dflt_value: The default value for the column, if any. + */ + if( sqlite3StrICmp(zLeft, "table_info")==0 && zRight ){ + Table *pTab; + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + pTab = sqlite3FindTable(db, zRight, zDb); + if( pTab ){ + int i; + int nHidden = 0; + Column *pCol; + sqlite3VdbeSetNumCols(v, 6); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", P3_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P3_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", P3_STATIC); + sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "notnull", P3_STATIC); + sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "dflt_value", P3_STATIC); + sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "pk", P3_STATIC); + sqlite3ViewGetColumnNames(pParse, pTab); + for(i=0, pCol=pTab->aCol; inCol; i++, pCol++){ + const Token *pDflt; + if( IsHiddenColumn(pCol) ){ + nHidden++; + continue; + } + sqlite3VdbeAddOp(v, OP_Integer, i-nHidden, 0); + sqlite3VdbeOp3(v, OP_String8, 0, 0, pCol->zName, 0); + sqlite3VdbeOp3(v, OP_String8, 0, 0, + pCol->zType ? pCol->zType : "", 0); + sqlite3VdbeAddOp(v, OP_Integer, pCol->notNull, 0); + if( pCol->pDflt && (pDflt = &pCol->pDflt->span)->z ){ + sqlite3VdbeOp3(v, OP_String8, 0, 0, (char*)pDflt->z, pDflt->n); + }else{ + sqlite3VdbeAddOp(v, OP_Null, 0, 0); + } + sqlite3VdbeAddOp(v, OP_Integer, pCol->isPrimKey, 0); + sqlite3VdbeAddOp(v, OP_Callback, 6, 0); + } + } + }else + + if( sqlite3StrICmp(zLeft, "index_info")==0 && zRight ){ + Index *pIdx; + Table *pTab; + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + pIdx = sqlite3FindIndex(db, zRight, zDb); + if( pIdx ){ + int i; + pTab = pIdx->pTable; + sqlite3VdbeSetNumCols(v, 3); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", P3_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", P3_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", P3_STATIC); + for(i=0; inColumn; i++){ + int cnum = pIdx->aiColumn[i]; + sqlite3VdbeAddOp(v, OP_Integer, i, 0); + sqlite3VdbeAddOp(v, OP_Integer, cnum, 0); + assert( pTab->nCol>cnum ); + sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->aCol[cnum].zName, 0); + sqlite3VdbeAddOp(v, OP_Callback, 3, 0); + } + } + }else + + if( sqlite3StrICmp(zLeft, "index_list")==0 && zRight ){ + Index *pIdx; + Table *pTab; + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + pTab = sqlite3FindTable(db, zRight, zDb); + if( pTab ){ + v = sqlite3GetVdbe(pParse); + pIdx = pTab->pIndex; + if( pIdx ){ + int i = 0; + sqlite3VdbeSetNumCols(v, 3); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P3_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P3_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", P3_STATIC); + while(pIdx){ + sqlite3VdbeAddOp(v, OP_Integer, i, 0); + sqlite3VdbeOp3(v, OP_String8, 0, 0, pIdx->zName, 0); + sqlite3VdbeAddOp(v, OP_Integer, pIdx->onError!=OE_None, 0); + sqlite3VdbeAddOp(v, OP_Callback, 3, 0); + ++i; + pIdx = pIdx->pNext; + } + } + } + }else + + if( sqlite3StrICmp(zLeft, "database_list")==0 ){ + int i; + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + sqlite3VdbeSetNumCols(v, 3); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P3_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P3_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "file", P3_STATIC); + for(i=0; inDb; i++){ + if( db->aDb[i].pBt==0 ) continue; + assert( db->aDb[i].zName!=0 ); + sqlite3VdbeAddOp(v, OP_Integer, i, 0); + sqlite3VdbeOp3(v, OP_String8, 0, 0, db->aDb[i].zName, 0); + sqlite3VdbeOp3(v, OP_String8, 0, 0, + sqlite3BtreeGetFilename(db->aDb[i].pBt), 0); + sqlite3VdbeAddOp(v, OP_Callback, 3, 0); + } + }else + + if( sqlite3StrICmp(zLeft, "collation_list")==0 ){ + int i = 0; + HashElem *p; + sqlite3VdbeSetNumCols(v, 2); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", P3_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", P3_STATIC); + for(p=sqliteHashFirst(&db->aCollSeq); p; p=sqliteHashNext(p)){ + CollSeq *pColl = (CollSeq *)sqliteHashData(p); + sqlite3VdbeAddOp(v, OP_Integer, i++, 0); + sqlite3VdbeOp3(v, OP_String8, 0, 0, pColl->zName, 0); + sqlite3VdbeAddOp(v, OP_Callback, 2, 0); + } + }else +#endif /* SQLITE_OMIT_SCHEMA_PRAGMAS */ + +#ifndef SQLITE_OMIT_FOREIGN_KEY + if( sqlite3StrICmp(zLeft, "foreign_key_list")==0 && zRight ){ + FKey *pFK; + Table *pTab; + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + pTab = sqlite3FindTable(db, zRight, zDb); + if( pTab ){ + v = sqlite3GetVdbe(pParse); + pFK = pTab->pFKey; + if( pFK ){ + int i = 0; + sqlite3VdbeSetNumCols(v, 5); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "id", P3_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "seq", P3_STATIC); + sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "table", P3_STATIC); + sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "from", P3_STATIC); + sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "to", P3_STATIC); + while(pFK){ + int j; + for(j=0; jnCol; j++){ + char *zCol = pFK->aCol[j].zCol; + sqlite3VdbeAddOp(v, OP_Integer, i, 0); + sqlite3VdbeAddOp(v, OP_Integer, j, 0); + sqlite3VdbeOp3(v, OP_String8, 0, 0, pFK->zTo, 0); + sqlite3VdbeOp3(v, OP_String8, 0, 0, + pTab->aCol[pFK->aCol[j].iFrom].zName, 0); + sqlite3VdbeOp3(v, zCol ? OP_String8 : OP_Null, 0, 0, zCol, 0); + sqlite3VdbeAddOp(v, OP_Callback, 5, 0); + } + ++i; + pFK = pFK->pNextFrom; + } + } + } + }else +#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ + +#ifndef NDEBUG + if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){ + if( zRight ){ + if( getBoolean(zRight) ){ + sqlite3ParserTrace(stderr, "parser: "); + }else{ + sqlite3ParserTrace(0, 0); + } + } + }else +#endif + + /* Reinstall the LIKE and GLOB functions. The variant of LIKE + ** used will be case sensitive or not depending on the RHS. + */ + if( sqlite3StrICmp(zLeft, "case_sensitive_like")==0 ){ + if( zRight ){ + sqlite3RegisterLikeFunctions(db, getBoolean(zRight)); + } + }else + +#ifndef SQLITE_INTEGRITY_CHECK_ERROR_MAX +# define SQLITE_INTEGRITY_CHECK_ERROR_MAX 100 +#endif + +#ifndef SQLITE_OMIT_INTEGRITY_CHECK + if( sqlite3StrICmp(zLeft, "integrity_check")==0 ){ + int i, j, addr, mxErr; + + /* Code that appears at the end of the integrity check. If no error + ** messages have been generated, output OK. Otherwise output the + ** error message + */ + static const VdbeOpList endCode[] = { + { OP_MemLoad, 0, 0, 0}, + { OP_Integer, 0, 0, 0}, + { OP_Ne, 0, 0, 0}, /* 2 */ + { OP_String8, 0, 0, "ok"}, + { OP_Callback, 1, 0, 0}, + }; + + /* Initialize the VDBE program */ + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", P3_STATIC); + + /* Set the maximum error count */ + mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; + if( zRight ){ + mxErr = atoi(zRight); + if( mxErr<=0 ){ + mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX; + } + } + sqlite3VdbeAddOp(v, OP_MemInt, mxErr, 0); + + /* Do an integrity check on each database file */ + for(i=0; inDb; i++){ + HashElem *x; + Hash *pTbls; + int cnt = 0; + + if( OMIT_TEMPDB && i==1 ) continue; + + sqlite3CodeVerifySchema(pParse, i); + addr = sqlite3VdbeAddOp(v, OP_IfMemPos, 0, 0); + sqlite3VdbeAddOp(v, OP_Halt, 0, 0); + sqlite3VdbeJumpHere(v, addr); + + /* Do an integrity check of the B-Tree + */ + pTbls = &db->aDb[i].pSchema->tblHash; + for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ + Table *pTab = sqliteHashData(x); + Index *pIdx; + sqlite3VdbeAddOp(v, OP_Integer, pTab->tnum, 0); + cnt++; + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + sqlite3VdbeAddOp(v, OP_Integer, pIdx->tnum, 0); + cnt++; + } + } + if( cnt==0 ) continue; + sqlite3VdbeAddOp(v, OP_IntegrityCk, 0, i); + addr = sqlite3VdbeAddOp(v, OP_IsNull, -1, 0); + sqlite3VdbeOp3(v, OP_String8, 0, 0, + sqlite3MPrintf("*** in database %s ***\n", db->aDb[i].zName), + P3_DYNAMIC); + sqlite3VdbeAddOp(v, OP_Pull, 1, 0); + sqlite3VdbeAddOp(v, OP_Concat, 0, 0); + sqlite3VdbeAddOp(v, OP_Callback, 1, 0); + sqlite3VdbeJumpHere(v, addr); + + /* Make sure all the indices are constructed correctly. + */ + for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){ + Table *pTab = sqliteHashData(x); + Index *pIdx; + int loopTop; + + if( pTab->pIndex==0 ) continue; + addr = sqlite3VdbeAddOp(v, OP_IfMemPos, 0, 0); + sqlite3VdbeAddOp(v, OP_Halt, 0, 0); + sqlite3VdbeJumpHere(v, addr); + sqlite3OpenTableAndIndices(pParse, pTab, 1, OP_OpenRead); + sqlite3VdbeAddOp(v, OP_MemInt, 0, 1); + loopTop = sqlite3VdbeAddOp(v, OP_Rewind, 1, 0); + sqlite3VdbeAddOp(v, OP_MemIncr, 1, 1); + for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ + int jmp2; + static const VdbeOpList idxErr[] = { + { OP_MemIncr, -1, 0, 0}, + { OP_String8, 0, 0, "rowid "}, + { OP_Rowid, 1, 0, 0}, + { OP_String8, 0, 0, " missing from index "}, + { OP_String8, 0, 0, 0}, /* 4 */ + { OP_Concat, 2, 0, 0}, + { OP_Callback, 1, 0, 0}, + }; + sqlite3GenerateIndexKey(v, pIdx, 1); + jmp2 = sqlite3VdbeAddOp(v, OP_Found, j+2, 0); + addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr); + sqlite3VdbeChangeP3(v, addr+4, pIdx->zName, P3_STATIC); + sqlite3VdbeJumpHere(v, jmp2); + } + sqlite3VdbeAddOp(v, OP_Next, 1, loopTop+1); + sqlite3VdbeJumpHere(v, loopTop); + for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ + static const VdbeOpList cntIdx[] = { + { OP_MemInt, 0, 2, 0}, + { OP_Rewind, 0, 0, 0}, /* 1 */ + { OP_MemIncr, 1, 2, 0}, + { OP_Next, 0, 0, 0}, /* 3 */ + { OP_MemLoad, 1, 0, 0}, + { OP_MemLoad, 2, 0, 0}, + { OP_Eq, 0, 0, 0}, /* 6 */ + { OP_MemIncr, -1, 0, 0}, + { OP_String8, 0, 0, "wrong # of entries in index "}, + { OP_String8, 0, 0, 0}, /* 9 */ + { OP_Concat, 0, 0, 0}, + { OP_Callback, 1, 0, 0}, + }; + if( pIdx->tnum==0 ) continue; + addr = sqlite3VdbeAddOp(v, OP_IfMemPos, 0, 0); + sqlite3VdbeAddOp(v, OP_Halt, 0, 0); + sqlite3VdbeJumpHere(v, addr); + addr = sqlite3VdbeAddOpList(v, ArraySize(cntIdx), cntIdx); + sqlite3VdbeChangeP1(v, addr+1, j+2); + sqlite3VdbeChangeP2(v, addr+1, addr+4); + sqlite3VdbeChangeP1(v, addr+3, j+2); + sqlite3VdbeChangeP2(v, addr+3, addr+2); + sqlite3VdbeJumpHere(v, addr+6); + sqlite3VdbeChangeP3(v, addr+9, pIdx->zName, P3_STATIC); + } + } + } + addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode); + sqlite3VdbeChangeP1(v, addr+1, mxErr); + sqlite3VdbeJumpHere(v, addr+2); + }else +#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ + +#ifndef SQLITE_OMIT_UTF16 + /* + ** PRAGMA encoding + ** PRAGMA encoding = "utf-8"|"utf-16"|"utf-16le"|"utf-16be" + ** + ** In it's first form, this pragma returns the encoding of the main + ** database. If the database is not initialized, it is initialized now. + ** + ** The second form of this pragma is a no-op if the main database file + ** has not already been initialized. In this case it sets the default + ** encoding that will be used for the main database file if a new file + ** is created. If an existing main database file is opened, then the + ** default text encoding for the existing database is used. + ** + ** In all cases new databases created using the ATTACH command are + ** created to use the same default text encoding as the main database. If + ** the main database has not been initialized and/or created when ATTACH + ** is executed, this is done before the ATTACH operation. + ** + ** In the second form this pragma sets the text encoding to be used in + ** new database files created using this database handle. It is only + ** useful if invoked immediately after the main database i + */ + if( sqlite3StrICmp(zLeft, "encoding")==0 ){ + static const struct EncName { + char *zName; + u8 enc; + } encnames[] = { + { "UTF-8", SQLITE_UTF8 }, + { "UTF8", SQLITE_UTF8 }, + { "UTF-16le", SQLITE_UTF16LE }, + { "UTF16le", SQLITE_UTF16LE }, + { "UTF-16be", SQLITE_UTF16BE }, + { "UTF16be", SQLITE_UTF16BE }, + { "UTF-16", 0 }, /* SQLITE_UTF16NATIVE */ + { "UTF16", 0 }, /* SQLITE_UTF16NATIVE */ + { 0, 0 } + }; + const struct EncName *pEnc; + if( !zRight ){ /* "PRAGMA encoding" */ + if( sqlite3ReadSchema(pParse) ) goto pragma_out; + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "encoding", P3_STATIC); + sqlite3VdbeAddOp(v, OP_String8, 0, 0); + for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ + if( pEnc->enc==ENC(pParse->db) ){ + sqlite3VdbeChangeP3(v, -1, pEnc->zName, P3_STATIC); + break; + } + } + sqlite3VdbeAddOp(v, OP_Callback, 1, 0); + }else{ /* "PRAGMA encoding = XXX" */ + /* Only change the value of sqlite.enc if the database handle is not + ** initialized. If the main database exists, the new sqlite.enc value + ** will be overwritten when the schema is next loaded. If it does not + ** already exists, it will be created to use the new encoding value. + */ + if( + !(DbHasProperty(db, 0, DB_SchemaLoaded)) || + DbHasProperty(db, 0, DB_Empty) + ){ + for(pEnc=&encnames[0]; pEnc->zName; pEnc++){ + if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){ + ENC(pParse->db) = pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE; + break; + } + } + if( !pEnc->zName ){ + sqlite3ErrorMsg(pParse, "unsupported encoding: %s", zRight); + } + } + } + }else +#endif /* SQLITE_OMIT_UTF16 */ + +#ifndef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS + /* + ** PRAGMA [database.]schema_version + ** PRAGMA [database.]schema_version = + ** + ** PRAGMA [database.]user_version + ** PRAGMA [database.]user_version = + ** + ** The pragma's schema_version and user_version are used to set or get + ** the value of the schema-version and user-version, respectively. Both + ** the schema-version and the user-version are 32-bit signed integers + ** stored in the database header. + ** + ** The schema-cookie is usually only manipulated internally by SQLite. It + ** is incremented by SQLite whenever the database schema is modified (by + ** creating or dropping a table or index). The schema version is used by + ** SQLite each time a query is executed to ensure that the internal cache + ** of the schema used when compiling the SQL query matches the schema of + ** the database against which the compiled query is actually executed. + ** Subverting this mechanism by using "PRAGMA schema_version" to modify + ** the schema-version is potentially dangerous and may lead to program + ** crashes or database corruption. Use with caution! + ** + ** The user-version is not used internally by SQLite. It may be used by + ** applications for any purpose. + */ + if( sqlite3StrICmp(zLeft, "schema_version")==0 + || sqlite3StrICmp(zLeft, "user_version")==0 + || sqlite3StrICmp(zLeft, "freelist_count")==0 + ){ + + int iCookie; /* Cookie index. 0 for schema-cookie, 6 for user-cookie. */ + switch( zLeft[0] ){ + case 's': case 'S': + iCookie = 0; + break; + case 'f': case 'F': + iCookie = 1; + iDb = (-1*(iDb+1)); + assert(iDb<=0); + break; + default: + iCookie = 5; + break; + } + + if( zRight && iDb>=0 ){ + /* Write the specified cookie value */ + static const VdbeOpList setCookie[] = { + { OP_Transaction, 0, 1, 0}, /* 0 */ + { OP_Integer, 0, 0, 0}, /* 1 */ + { OP_SetCookie, 0, 0, 0}, /* 2 */ + }; + int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie); + sqlite3VdbeChangeP1(v, addr, iDb); + sqlite3VdbeChangeP1(v, addr+1, atoi(zRight)); + sqlite3VdbeChangeP1(v, addr+2, iDb); + sqlite3VdbeChangeP2(v, addr+2, iCookie); + }else{ + /* Read the specified cookie value */ + static const VdbeOpList readCookie[] = { + { OP_ReadCookie, 0, 0, 0}, /* 0 */ + { OP_Callback, 1, 0, 0} + }; + int addr = sqlite3VdbeAddOpList(v, ArraySize(readCookie), readCookie); + sqlite3VdbeChangeP1(v, addr, iDb); + sqlite3VdbeChangeP2(v, addr, iCookie); + sqlite3VdbeSetNumCols(v, 1); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, P3_TRANSIENT); + } + }else +#endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */ + +#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) + /* + ** Report the current state of file logs for all databases + */ + if( sqlite3StrICmp(zLeft, "lock_status")==0 ){ + static const char *const azLockName[] = { + "unlocked", "shared", "reserved", "pending", "exclusive" + }; + int i; + Vdbe *v = sqlite3GetVdbe(pParse); + sqlite3VdbeSetNumCols(v, 2); + sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "database", P3_STATIC); + sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "status", P3_STATIC); + for(i=0; inDb; i++){ + Btree *pBt; + Pager *pPager; + if( db->aDb[i].zName==0 ) continue; + sqlite3VdbeOp3(v, OP_String8, 0, 0, db->aDb[i].zName, P3_STATIC); + pBt = db->aDb[i].pBt; + if( pBt==0 || (pPager = sqlite3BtreePager(pBt))==0 ){ + sqlite3VdbeOp3(v, OP_String8, 0, 0, "closed", P3_STATIC); + }else{ + int j = sqlite3PagerLockstate(pPager); + sqlite3VdbeOp3(v, OP_String8, 0, 0, + (j>=0 && j<=4) ? azLockName[j] : "unknown", P3_STATIC); + } + sqlite3VdbeAddOp(v, OP_Callback, 2, 0); + } + }else +#endif + +#ifdef SQLITE_SSE + /* + ** Check to see if the sqlite_statements table exists. Create it + ** if it does not. + */ + if( sqlite3StrICmp(zLeft, "create_sqlite_statement_table")==0 ){ + extern int sqlite3CreateStatementsTable(Parse*); + sqlite3CreateStatementsTable(pParse); + }else +#endif + +#if SQLITE_HAS_CODEC + if( sqlite3StrICmp(zLeft, "key")==0 ){ + sqlite3_key(db, zRight, strlen(zRight)); + }else +#endif +#if SQLITE_HAS_CODEC || defined(SQLITE_ENABLE_CEROD) + if( sqlite3StrICmp(zLeft, "activate_extensions")==0 ){ +#if SQLITE_HAS_CODEC + if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){ + extern void sqlite3_activate_see(const char*); + sqlite3_activate_see(&zRight[4]); + } +#endif +#ifdef SQLITE_ENABLE_CEROD + if( sqlite3StrNICmp(zRight, "cerod-", 6)==0 ){ + extern void sqlite3_activate_cerod(const char*); + sqlite3_activate_cerod(&zRight[6]); + } +#endif + } +#endif + + {} + + if( v ){ + /* Code an OP_Expire at the end of each PRAGMA program to cause + ** the VDBE implementing the pragma to expire. Most (all?) pragmas + ** are only valid for a single execution. + */ + sqlite3VdbeAddOp(v, OP_Expire, 1, 0); + + /* + ** Reset the safety level, in case the fullfsync flag or synchronous + ** setting changed. + */ +#ifndef SQLITE_OMIT_PAGER_PRAGMAS + if( db->autoCommit ){ + sqlite3BtreeSetSafetyLevel(pDb->pBt, pDb->safety_level, + (db->flags&SQLITE_FullFSync)!=0); + } +#endif + } +pragma_out: + sqliteFree(zLeft); + sqliteFree(zRight); +} + +#endif /* SQLITE_OMIT_PRAGMA || SQLITE_OMIT_PARSER */ diff --git a/extensions/sqlite/sqlite-source/prepare.c b/extensions/sqlite/sqlite-source/prepare.c new file mode 100644 index 00000000..8cf17b7b --- /dev/null +++ b/extensions/sqlite/sqlite-source/prepare.c @@ -0,0 +1,697 @@ +/* +** 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$ +*/ +#include "sqliteInt.h" +#include "os.h" +#include + +/* +** 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 && iDbnDb ); + 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 && iDbnDb ); + 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] Incremental-vacuum flag. + ** 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 && ipBt, 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 = SQLITE_DEFAULT_CACHE_SIZE; } + 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 || (db->flags&SQLITE_RecoveryMode)){ + /* Black magic: If the SQLITE_RecoveryMode flag is set, then consider + ** the schema loaded, even if errors occured. In this situation the + ** current sqlite3_prepare() operation will fail, but the following one + ** will attempt to compile the supplied statement against whatever subset + ** of the schema was loaded before the error occured. The primary + ** purpose of this is to allow access to the sqlite_master table + ** even when it's contents have been corrupted. + */ + DbSetProperty(db, iDb, DB_SchemaLoaded); + rc = SQLITE_OK; + } + 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 && inDb; 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 && iDbnDb; 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; inDb; i++){ + if( db->aDb[i].pSchema==pSchema ){ + break; + } + } + assert( i>=0 &&i>=0 && inDb ); + } + 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; inDb; 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; + if( nBytes>SQLITE_MAX_SQL_LENGTH ){ + return SQLITE_TOOBIG; + } + zSqlCopy = sqlite3StrNDup(zSql, nBytes); + if( zSqlCopy ){ + sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg); + sqliteFree(zSqlCopy); + } + sParse.zTail = &zSql[nBytes]; + }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( saveSqlFlag ){ + sqlite3VdbeSetSql(sParse.pVdbe, zSql, sParse.zTail - zSql); + } + if( rc!=SQLITE_OK || sqlite3MallocFailed() ){ + sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe); + assert(!(*ppStmt)); + }else{ + *ppStmt = (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; + sqlite3_stmt *pNew; + const char *zSql; + sqlite3 *db; + + zSql = sqlite3VdbeGetSql(p); + if( zSql==0 ){ + return 0; + } + db = sqlite3VdbeDb(p); + rc = sqlite3Prepare(db, zSql, -1, 0, &pNew, 0); + if( rc ){ + assert( pNew==0 ); + return 0; + }else{ + assert( pNew!=0 ); + } + sqlite3VdbeSwap((Vdbe*)pNew, p); + sqlite3_transfer_bindings(pNew, (sqlite3_stmt*)p); + sqlite3VdbeResetStepResult((Vdbe*)pNew); + sqlite3VdbeFinalize((Vdbe*)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 */ diff --git a/extensions/sqlite/sqlite-source/printf.c b/extensions/sqlite/sqlite-source/printf.c new file mode 100644 index 00000000..01ed7a1e --- /dev/null +++ b/extensions/sqlite/sqlite-source/printf.c @@ -0,0 +1,885 @@ +/* +** 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" +#include + +/* +** 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 */ +#define etSQLESCAPE3 16 /* %w -> Strings with '\"' doubled */ + + +/* +** 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 }, + { 'w', 0, 4, etSQLESCAPE3, 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; idxflags & 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 && precisioncharset]; + 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( sqlite3_isnan(realvalue) ){ + bufpt = "NaN"; + length = 3; + break; + } + 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 ){ + if( prefix=='-' ){ + bufpt = "-Inf"; + }else if( prefix=='+' ){ + bufpt = "+Inf"; + }else{ + bufpt = "Inf"; + } + length = strlen(bufpt); + 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=0 && precisionetBUFSIZE ){ + bufpt = zExtra = sqliteMalloc( n ); + if( bufpt==0 ) return -1; + }else{ + bufpt = buf; + } + j = 0; + if( needQuote ) bufpt[j++] = q; + for(i=0; (ch=escarg[i])!=0; i++){ + bufpt[j++] = ch; + if( ch==q ) bufpt[j++] = ch; + } + if( needQuote ) bufpt[j++] = q; + bufpt[j] = 0; + length = j; + /* The precision is ignored on %q and %Q */ + /* if( precision>=0 && precisionz ){ + (*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 && knSrc ); + 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{ + int nAlloc = pM->nChar + nNewChar*2 + 1; + if( pM->zText==pM->zBase ){ + pM->zText = pM->xRealloc(0, nAlloc); + if( pM->zText && pM->nChar ){ + memcpy(pM->zText, pM->zBase, pM->nChar); + } + }else{ + char *zNew; + zNew = pM->xRealloc(pM->zText, nAlloc); + if( zNew ){ + pM->zText = zNew; + }else{ + return; + } + } + pM->nAlloc = nAlloc; + } + } + 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; + va_start(ap, zFormat); + z = sqlite3_vmprintf(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; + + if( n<=0 ){ + return zBuf; + } + zBuf[0] = 0; + 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) || defined(SQLITE_MEMDEBUG) +/* +** 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 diff --git a/extensions/sqlite/sqlite-source/random.c b/extensions/sqlite/sqlite-source/random.c new file mode 100644 index 00000000..5adc84aa --- /dev/null +++ b/extensions/sqlite/sqlite-source/random.c @@ -0,0 +1,100 @@ +/* +** 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$ +*/ +#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(); +} diff --git a/extensions/sqlite/sqlite-source/select.c b/extensions/sqlite/sqlite-source/select.c new file mode 100644 index 00000000..6840d41b --- /dev/null +++ b/extensions/sqlite/sqlite-source/select.c @@ -0,0 +1,3505 @@ +/* +** 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 SELECT statements in SQLite. +** +** $Id$ +*/ +#include "sqliteInt.h" + + +/* +** Delete all the content of a Select structure but do not deallocate +** the select structure itself. +*/ +static void clearSelect(Select *p){ + sqlite3ExprListDelete(p->pEList); + sqlite3SrcListDelete(p->pSrc); + sqlite3ExprDelete(p->pWhere); + sqlite3ExprListDelete(p->pGroupBy); + sqlite3ExprDelete(p->pHaving); + sqlite3ExprListDelete(p->pOrderBy); + sqlite3SelectDelete(p->pPrior); + sqlite3ExprDelete(p->pLimit); + sqlite3ExprDelete(p->pOffset); +} + + +/* +** Allocate a new Select structure and return a pointer to that +** structure. +*/ +Select *sqlite3SelectNew( + ExprList *pEList, /* which columns to include in the result */ + SrcList *pSrc, /* the FROM clause -- which tables to scan */ + Expr *pWhere, /* the WHERE clause */ + ExprList *pGroupBy, /* the GROUP BY clause */ + Expr *pHaving, /* the HAVING clause */ + ExprList *pOrderBy, /* the ORDER BY clause */ + int isDistinct, /* true if the DISTINCT keyword is present */ + Expr *pLimit, /* LIMIT value. NULL means not used */ + Expr *pOffset /* OFFSET value. NULL means no offset */ +){ + Select *pNew; + Select standin; + pNew = sqliteMalloc( sizeof(*pNew) ); + assert( !pOffset || pLimit ); /* Can't have OFFSET without LIMIT. */ + if( pNew==0 ){ + pNew = &standin; + memset(pNew, 0, sizeof(*pNew)); + } + if( pEList==0 ){ + pEList = sqlite3ExprListAppend(0, sqlite3Expr(TK_ALL,0,0,0), 0); + } + pNew->pEList = pEList; + pNew->pSrc = pSrc; + pNew->pWhere = pWhere; + pNew->pGroupBy = pGroupBy; + pNew->pHaving = pHaving; + pNew->pOrderBy = pOrderBy; + pNew->isDistinct = isDistinct; + pNew->op = TK_SELECT; + assert( pOffset==0 || pLimit!=0 ); + pNew->pLimit = pLimit; + pNew->pOffset = pOffset; + pNew->iLimit = -1; + pNew->iOffset = -1; + pNew->addrOpenEphm[0] = -1; + pNew->addrOpenEphm[1] = -1; + pNew->addrOpenEphm[2] = -1; + if( pNew==&standin) { + clearSelect(pNew); + pNew = 0; + } + return pNew; +} + +/* +** Delete the given Select structure and all of its substructures. +*/ +void sqlite3SelectDelete(Select *p){ + if( p ){ + clearSelect(p); + sqliteFree(p); + } +} + +/* +** Given 1 to 3 identifiers preceeding the JOIN keyword, determine the +** type of join. Return an integer constant that expresses that type +** in terms of the following bit values: +** +** JT_INNER +** JT_CROSS +** JT_OUTER +** JT_NATURAL +** JT_LEFT +** JT_RIGHT +** +** A full outer join is the combination of JT_LEFT and JT_RIGHT. +** +** If an illegal or unsupported join type is seen, then still return +** a join type, but put an error in the pParse structure. +*/ +int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){ + int jointype = 0; + Token *apAll[3]; + Token *p; + static const struct { + const char zKeyword[8]; + u8 nChar; + u8 code; + } keywords[] = { + { "natural", 7, JT_NATURAL }, + { "left", 4, JT_LEFT|JT_OUTER }, + { "right", 5, JT_RIGHT|JT_OUTER }, + { "full", 4, JT_LEFT|JT_RIGHT|JT_OUTER }, + { "outer", 5, JT_OUTER }, + { "inner", 5, JT_INNER }, + { "cross", 5, JT_INNER|JT_CROSS }, + }; + int i, j; + apAll[0] = pA; + apAll[1] = pB; + apAll[2] = pC; + for(i=0; i<3 && apAll[i]; i++){ + p = apAll[i]; + for(j=0; jn==keywords[j].nChar + && sqlite3StrNICmp((char*)p->z, keywords[j].zKeyword, p->n)==0 ){ + jointype |= keywords[j].code; + break; + } + } + if( j>=sizeof(keywords)/sizeof(keywords[0]) ){ + jointype |= JT_ERROR; + break; + } + } + if( + (jointype & (JT_INNER|JT_OUTER))==(JT_INNER|JT_OUTER) || + (jointype & JT_ERROR)!=0 + ){ + const char *zSp1 = " "; + const char *zSp2 = " "; + if( pB==0 ){ zSp1++; } + if( pC==0 ){ zSp2++; } + sqlite3ErrorMsg(pParse, "unknown or unsupported join type: " + "%T%s%T%s%T", pA, zSp1, pB, zSp2, pC); + jointype = JT_INNER; + }else if( jointype & JT_RIGHT ){ + sqlite3ErrorMsg(pParse, + "RIGHT and FULL OUTER JOINs are not currently supported"); + jointype = JT_INNER; + } + return jointype; +} + +/* +** Return the index of a column in a table. Return -1 if the column +** is not contained in the table. +*/ +static int columnIndex(Table *pTab, const char *zCol){ + int i; + for(i=0; inCol; i++){ + if( sqlite3StrICmp(pTab->aCol[i].zName, zCol)==0 ) return i; + } + return -1; +} + +/* +** Set the value of a token to a '\000'-terminated string. +*/ +static void setToken(Token *p, const char *z){ + p->z = (u8*)z; + p->n = z ? strlen(z) : 0; + p->dyn = 0; +} + +/* +** Set the token to the double-quoted and escaped version of the string pointed +** to by z. For example; +** +** {a"bc} -> {"a""bc"} +*/ +static void setQuotedToken(Token *p, const char *z){ + p->z = (u8 *)sqlite3MPrintf("\"%w\"", z); + p->dyn = 1; + if( p->z ){ + p->n = strlen((char *)p->z); + } +} + +/* +** Create an expression node for an identifier with the name of zName +*/ +Expr *sqlite3CreateIdExpr(const char *zName){ + Token dummy; + setToken(&dummy, zName); + return sqlite3Expr(TK_ID, 0, 0, &dummy); +} + + +/* +** Add a term to the WHERE expression in *ppExpr that requires the +** zCol column to be equal in the two tables pTab1 and pTab2. +*/ +static void addWhereTerm( + const char *zCol, /* Name of the column */ + const Table *pTab1, /* First table */ + const char *zAlias1, /* Alias for first table. May be NULL */ + const Table *pTab2, /* Second table */ + const char *zAlias2, /* Alias for second table. May be NULL */ + int iRightJoinTable, /* VDBE cursor for the right table */ + Expr **ppExpr /* Add the equality term to this expression */ +){ + Expr *pE1a, *pE1b, *pE1c; + Expr *pE2a, *pE2b, *pE2c; + Expr *pE; + + pE1a = sqlite3CreateIdExpr(zCol); + pE2a = sqlite3CreateIdExpr(zCol); + if( zAlias1==0 ){ + zAlias1 = pTab1->zName; + } + pE1b = sqlite3CreateIdExpr(zAlias1); + if( zAlias2==0 ){ + zAlias2 = pTab2->zName; + } + pE2b = sqlite3CreateIdExpr(zAlias2); + pE1c = sqlite3ExprOrFree(TK_DOT, pE1b, pE1a, 0); + pE2c = sqlite3ExprOrFree(TK_DOT, pE2b, pE2a, 0); + pE = sqlite3ExprOrFree(TK_EQ, pE1c, pE2c, 0); + if( pE ){ + ExprSetProperty(pE, EP_FromJoin); + pE->iRightJoinTable = iRightJoinTable; + } + pE = sqlite3ExprAnd(*ppExpr, pE); + if( pE ){ + *ppExpr = pE; + } +} + +/* +** Set the EP_FromJoin property on all terms of the given expression. +** And set the Expr.iRightJoinTable to iTable for every term in the +** expression. +** +** The EP_FromJoin property is used on terms of an expression to tell +** the LEFT OUTER JOIN processing logic that this term is part of the +** join restriction specified in the ON or USING clause and not a part +** of the more general WHERE clause. These terms are moved over to the +** WHERE clause during join processing but we need to remember that they +** originated in the ON or USING clause. +** +** The Expr.iRightJoinTable tells the WHERE clause processing that the +** expression depends on table iRightJoinTable even if that table is not +** explicitly mentioned in the expression. That information is needed +** for cases like this: +** +** SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.b AND t1.x=5 +** +** The where clause needs to defer the handling of the t1.x=5 +** term until after the t2 loop of the join. In that way, a +** NULL t2 row will be inserted whenever t1.x!=5. If we do not +** defer the handling of t1.x=5, it will be processed immediately +** after the t1 loop and rows with t1.x!=5 will never appear in +** the output, which is incorrect. +*/ +static void setJoinExpr(Expr *p, int iTable){ + while( p ){ + ExprSetProperty(p, EP_FromJoin); + p->iRightJoinTable = iTable; + setJoinExpr(p->pLeft, iTable); + p = p->pRight; + } +} + +/* +** This routine processes the join information for a SELECT statement. +** ON and USING clauses are converted into extra terms of the WHERE clause. +** NATURAL joins also create extra WHERE clause terms. +** +** The terms of a FROM clause are contained in the Select.pSrc structure. +** The left most table is the first entry in Select.pSrc. The right-most +** table is the last entry. The join operator is held in the entry to +** the left. Thus entry 0 contains the join operator for the join between +** entries 0 and 1. Any ON or USING clauses associated with the join are +** also attached to the left entry. +** +** This routine returns the number of errors encountered. +*/ +static int sqliteProcessJoin(Parse *pParse, Select *p){ + SrcList *pSrc; /* All tables in the FROM clause */ + int i, j; /* Loop counters */ + struct SrcList_item *pLeft; /* Left table being joined */ + struct SrcList_item *pRight; /* Right table being joined */ + + pSrc = p->pSrc; + pLeft = &pSrc->a[0]; + pRight = &pLeft[1]; + for(i=0; inSrc-1; i++, pRight++, pLeft++){ + Table *pLeftTab = pLeft->pTab; + Table *pRightTab = pRight->pTab; + + if( pLeftTab==0 || pRightTab==0 ) continue; + + /* When the NATURAL keyword is present, add WHERE clause terms for + ** every column that the two tables have in common. + */ + if( pRight->jointype & JT_NATURAL ){ + if( pRight->pOn || pRight->pUsing ){ + sqlite3ErrorMsg(pParse, "a NATURAL join may not have " + "an ON or USING clause", 0); + return 1; + } + for(j=0; jnCol; j++){ + char *zName = pLeftTab->aCol[j].zName; + if( columnIndex(pRightTab, zName)>=0 ){ + addWhereTerm(zName, pLeftTab, pLeft->zAlias, + pRightTab, pRight->zAlias, + pRight->iCursor, &p->pWhere); + + } + } + } + + /* Disallow both ON and USING clauses in the same join + */ + if( pRight->pOn && pRight->pUsing ){ + sqlite3ErrorMsg(pParse, "cannot have both ON and USING " + "clauses in the same join"); + return 1; + } + + /* Add the ON clause to the end of the WHERE clause, connected by + ** an AND operator. + */ + if( pRight->pOn ){ + setJoinExpr(pRight->pOn, pRight->iCursor); + p->pWhere = sqlite3ExprAnd(p->pWhere, pRight->pOn); + pRight->pOn = 0; + } + + /* Create extra terms on the WHERE clause for each column named + ** in the USING clause. Example: If the two tables to be joined are + ** A and B and the USING clause names X, Y, and Z, then add this + ** to the WHERE clause: A.X=B.X AND A.Y=B.Y AND A.Z=B.Z + ** Report an error if any column mentioned in the USING clause is + ** not contained in both tables to be joined. + */ + if( pRight->pUsing ){ + IdList *pList = pRight->pUsing; + for(j=0; jnId; j++){ + char *zName = pList->a[j].zName; + if( columnIndex(pLeftTab, zName)<0 || columnIndex(pRightTab, zName)<0 ){ + sqlite3ErrorMsg(pParse, "cannot join using column %s - column " + "not present in both tables", zName); + return 1; + } + addWhereTerm(zName, pLeftTab, pLeft->zAlias, + pRightTab, pRight->zAlias, + pRight->iCursor, &p->pWhere); + } + } + } + return 0; +} + +/* +** Insert code into "v" that will push the record on the top of the +** stack into the sorter. +*/ +static void pushOntoSorter( + Parse *pParse, /* Parser context */ + ExprList *pOrderBy, /* The ORDER BY clause */ + Select *pSelect /* The whole SELECT statement */ +){ + Vdbe *v = pParse->pVdbe; + sqlite3ExprCodeExprList(pParse, pOrderBy); + sqlite3VdbeAddOp(v, OP_Sequence, pOrderBy->iECursor, 0); + sqlite3VdbeAddOp(v, OP_Pull, pOrderBy->nExpr + 1, 0); + sqlite3VdbeAddOp(v, OP_MakeRecord, pOrderBy->nExpr + 2, 0); + sqlite3VdbeAddOp(v, OP_IdxInsert, pOrderBy->iECursor, 0); + if( pSelect->iLimit>=0 ){ + int addr1, addr2; + addr1 = sqlite3VdbeAddOp(v, OP_IfMemZero, pSelect->iLimit+1, 0); + sqlite3VdbeAddOp(v, OP_MemIncr, -1, pSelect->iLimit+1); + addr2 = sqlite3VdbeAddOp(v, OP_Goto, 0, 0); + sqlite3VdbeJumpHere(v, addr1); + sqlite3VdbeAddOp(v, OP_Last, pOrderBy->iECursor, 0); + sqlite3VdbeAddOp(v, OP_Delete, pOrderBy->iECursor, 0); + sqlite3VdbeJumpHere(v, addr2); + pSelect->iLimit = -1; + } +} + +/* +** Add code to implement the OFFSET +*/ +static void codeOffset( + Vdbe *v, /* Generate code into this VM */ + Select *p, /* The SELECT statement being coded */ + int iContinue, /* Jump here to skip the current record */ + int nPop /* Number of times to pop stack when jumping */ +){ + if( p->iOffset>=0 && iContinue!=0 ){ + int addr; + sqlite3VdbeAddOp(v, OP_MemIncr, -1, p->iOffset); + addr = sqlite3VdbeAddOp(v, OP_IfMemNeg, p->iOffset, 0); + if( nPop>0 ){ + sqlite3VdbeAddOp(v, OP_Pop, nPop, 0); + } + sqlite3VdbeAddOp(v, OP_Goto, 0, iContinue); + VdbeComment((v, "# skip OFFSET records")); + sqlite3VdbeJumpHere(v, addr); + } +} + +/* +** Add code that will check to make sure the top N elements of the +** stack are distinct. iTab is a sorting index that holds previously +** seen combinations of the N values. A new entry is made in iTab +** if the current N values are new. +** +** A jump to addrRepeat is made and the N+1 values are popped from the +** stack if the top N elements are not distinct. +*/ +static void codeDistinct( + Vdbe *v, /* Generate code into this VM */ + int iTab, /* A sorting index used to test for distinctness */ + int addrRepeat, /* Jump to here if not distinct */ + int N /* The top N elements of the stack must be distinct */ +){ + sqlite3VdbeAddOp(v, OP_MakeRecord, -N, 0); + sqlite3VdbeAddOp(v, OP_Distinct, iTab, sqlite3VdbeCurrentAddr(v)+3); + sqlite3VdbeAddOp(v, OP_Pop, N+1, 0); + sqlite3VdbeAddOp(v, OP_Goto, 0, addrRepeat); + VdbeComment((v, "# skip indistinct records")); + sqlite3VdbeAddOp(v, OP_IdxInsert, iTab, 0); +} + +/* +** Generate an error message when a SELECT is used within a subexpression +** (example: "a IN (SELECT * FROM table)") but it has more than 1 result +** column. We do this in a subroutine because the error occurs in multiple +** places. +*/ +static int checkForMultiColumnSelectError(Parse *pParse, int eDest, int nExpr){ + if( nExpr>1 && (eDest==SRT_Mem || eDest==SRT_Set) ){ + sqlite3ErrorMsg(pParse, "only a single result allowed for " + "a SELECT that is part of an expression"); + return 1; + }else{ + return 0; + } +} + +/* +** This routine generates the code for the inside of the inner loop +** of a SELECT. +** +** If srcTab and nColumn are both zero, then the pEList expressions +** are evaluated in order to get the data for this row. If nColumn>0 +** then data is pulled from srcTab and pEList is used only to get the +** datatypes for each column. +*/ +static int selectInnerLoop( + Parse *pParse, /* The parser context */ + Select *p, /* The complete select statement being coded */ + ExprList *pEList, /* List of values being extracted */ + int srcTab, /* Pull data from this table */ + int nColumn, /* Number of columns in the source table */ + ExprList *pOrderBy, /* If not NULL, sort results using this key */ + int distinct, /* If >=0, make sure results are distinct */ + int eDest, /* How to dispose of the results */ + int iParm, /* An argument to the disposal method */ + int iContinue, /* Jump here to continue with next row */ + int iBreak, /* Jump here to break out of the inner loop */ + char *aff /* affinity string if eDest is SRT_Union */ +){ + Vdbe *v = pParse->pVdbe; + int i; + int hasDistinct; /* True if the DISTINCT keyword is present */ + + if( v==0 ) return 0; + assert( pEList!=0 ); + + /* If there was a LIMIT clause on the SELECT statement, then do the check + ** to see if this row should be output. + */ + hasDistinct = distinct>=0 && pEList->nExpr>0; + if( pOrderBy==0 && !hasDistinct ){ + codeOffset(v, p, iContinue, 0); + } + + /* Pull the requested columns. + */ + if( nColumn>0 ){ + for(i=0; inExpr; + sqlite3ExprCodeExprList(pParse, pEList); + } + + /* If the DISTINCT keyword was present on the SELECT statement + ** and this row has been seen before, then do not make this row + ** part of the result. + */ + if( hasDistinct ){ + assert( pEList!=0 ); + assert( pEList->nExpr==nColumn ); + codeDistinct(v, distinct, iContinue, nColumn); + if( pOrderBy==0 ){ + codeOffset(v, p, iContinue, nColumn); + } + } + + if( checkForMultiColumnSelectError(pParse, eDest, pEList->nExpr) ){ + return 0; + } + + switch( eDest ){ + /* In this mode, write each query result to the key of the temporary + ** table iParm. + */ +#ifndef SQLITE_OMIT_COMPOUND_SELECT + case SRT_Union: { + sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); + if( aff ){ + sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC); + } + sqlite3VdbeAddOp(v, OP_IdxInsert, iParm, 0); + break; + } + + /* Construct a record from the query result, but instead of + ** saving that record, use it as a key to delete elements from + ** the temporary table iParm. + */ + case SRT_Except: { + int addr; + addr = sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); + sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC); + sqlite3VdbeAddOp(v, OP_NotFound, iParm, addr+3); + sqlite3VdbeAddOp(v, OP_Delete, iParm, 0); + break; + } +#endif + + /* Store the result as data using a unique key. + */ + case SRT_Table: + case SRT_EphemTab: { + sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); + if( pOrderBy ){ + pushOntoSorter(pParse, pOrderBy, p); + }else{ + sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0); + sqlite3VdbeAddOp(v, OP_Pull, 1, 0); + sqlite3VdbeAddOp(v, OP_Insert, iParm, OPFLAG_APPEND); + } + break; + } + +#ifndef SQLITE_OMIT_SUBQUERY + /* If we are creating a set for an "expr IN (SELECT ...)" construct, + ** then there should be a single item on the stack. Write this + ** item into the set table with bogus data. + */ + case SRT_Set: { + int addr1 = sqlite3VdbeCurrentAddr(v); + int addr2; + + assert( nColumn==1 ); + sqlite3VdbeAddOp(v, OP_NotNull, -1, addr1+3); + sqlite3VdbeAddOp(v, OP_Pop, 1, 0); + addr2 = sqlite3VdbeAddOp(v, OP_Goto, 0, 0); + p->affinity = sqlite3CompareAffinity(pEList->a[0].pExpr,(iParm>>16)&0xff); + if( pOrderBy ){ + /* At first glance you would think we could optimize out the + ** ORDER BY in this case since the order of entries in the set + ** does not matter. But there might be a LIMIT clause, in which + ** case the order does matter */ + pushOntoSorter(pParse, pOrderBy, p); + }else{ + sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &p->affinity, 1); + sqlite3VdbeAddOp(v, OP_IdxInsert, (iParm&0x0000FFFF), 0); + } + sqlite3VdbeJumpHere(v, addr2); + break; + } + + /* If any row exist in the result set, record that fact and abort. + */ + case SRT_Exists: { + sqlite3VdbeAddOp(v, OP_MemInt, 1, iParm); + sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0); + /* The LIMIT clause will terminate the loop for us */ + break; + } + + /* If this is a scalar select that is part of an expression, then + ** store the results in the appropriate memory cell and break out + ** of the scan loop. + */ + case SRT_Mem: { + assert( nColumn==1 ); + if( pOrderBy ){ + pushOntoSorter(pParse, pOrderBy, p); + }else{ + sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1); + /* The LIMIT clause will jump out of the loop for us */ + } + break; + } +#endif /* #ifndef SQLITE_OMIT_SUBQUERY */ + + /* Send the data to the callback function or to a subroutine. In the + ** case of a subroutine, the subroutine itself is responsible for + ** popping the data from the stack. + */ + case SRT_Subroutine: + case SRT_Callback: { + if( pOrderBy ){ + sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); + pushOntoSorter(pParse, pOrderBy, p); + }else if( eDest==SRT_Subroutine ){ + sqlite3VdbeAddOp(v, OP_Gosub, 0, iParm); + }else{ + sqlite3VdbeAddOp(v, OP_Callback, nColumn, 0); + } + break; + } + +#if !defined(SQLITE_OMIT_TRIGGER) + /* Discard the results. This is used for SELECT statements inside + ** the body of a TRIGGER. The purpose of such selects is to call + ** user-defined functions that have side effects. We do not care + ** about the actual results of the select. + */ + default: { + assert( eDest==SRT_Discard ); + sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0); + break; + } +#endif + } + + /* Jump to the end of the loop if the LIMIT is reached. + */ + if( p->iLimit>=0 && pOrderBy==0 ){ + sqlite3VdbeAddOp(v, OP_MemIncr, -1, p->iLimit); + sqlite3VdbeAddOp(v, OP_IfMemZero, p->iLimit, iBreak); + } + return 0; +} + +/* +** Given an expression list, generate a KeyInfo structure that records +** the collating sequence for each expression in that expression list. +** +** If the ExprList is an ORDER BY or GROUP BY clause then the resulting +** KeyInfo structure is appropriate for initializing a virtual index to +** implement that clause. If the ExprList is the result set of a SELECT +** then the KeyInfo structure is appropriate for initializing a virtual +** index to implement a DISTINCT test. +** +** Space to hold the KeyInfo structure is obtain from malloc. The calling +** function is responsible for seeing that this structure is eventually +** freed. Add the KeyInfo structure to the P3 field of an opcode using +** P3_KEYINFO_HANDOFF is the usual way of dealing with this. +*/ +static KeyInfo *keyInfoFromExprList(Parse *pParse, ExprList *pList){ + sqlite3 *db = pParse->db; + int nExpr; + KeyInfo *pInfo; + struct ExprList_item *pItem; + int i; + + nExpr = pList->nExpr; + pInfo = sqliteMalloc( sizeof(*pInfo) + nExpr*(sizeof(CollSeq*)+1) ); + if( pInfo ){ + pInfo->aSortOrder = (u8*)&pInfo->aColl[nExpr]; + pInfo->nField = nExpr; + pInfo->enc = ENC(db); + for(i=0, pItem=pList->a; ipExpr); + if( !pColl ){ + pColl = db->pDfltColl; + } + pInfo->aColl[i] = pColl; + pInfo->aSortOrder[i] = pItem->sortOrder; + } + } + return pInfo; +} + + +/* +** If the inner loop was generated using a non-null pOrderBy argument, +** then the results were placed in a sorter. After the loop is terminated +** we need to run the sorter and output the results. The following +** routine generates the code needed to do that. +*/ +static void generateSortTail( + Parse *pParse, /* Parsing context */ + Select *p, /* The SELECT statement */ + Vdbe *v, /* Generate code into this VDBE */ + int nColumn, /* Number of columns of data */ + int eDest, /* Write the sorted results here */ + int iParm /* Optional parameter associated with eDest */ +){ + int brk = sqlite3VdbeMakeLabel(v); + int cont = sqlite3VdbeMakeLabel(v); + int addr; + int iTab; + int pseudoTab = 0; + ExprList *pOrderBy = p->pOrderBy; + + iTab = pOrderBy->iECursor; + if( eDest==SRT_Callback || eDest==SRT_Subroutine ){ + pseudoTab = pParse->nTab++; + sqlite3VdbeAddOp(v, OP_OpenPseudo, pseudoTab, 0); + sqlite3VdbeAddOp(v, OP_SetNumColumns, pseudoTab, nColumn); + } + addr = 1 + sqlite3VdbeAddOp(v, OP_Sort, iTab, brk); + codeOffset(v, p, cont, 0); + if( eDest==SRT_Callback || eDest==SRT_Subroutine ){ + sqlite3VdbeAddOp(v, OP_Integer, 1, 0); + } + sqlite3VdbeAddOp(v, OP_Column, iTab, pOrderBy->nExpr + 1); + switch( eDest ){ + case SRT_Table: + case SRT_EphemTab: { + sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0); + sqlite3VdbeAddOp(v, OP_Pull, 1, 0); + sqlite3VdbeAddOp(v, OP_Insert, iParm, OPFLAG_APPEND); + break; + } +#ifndef SQLITE_OMIT_SUBQUERY + case SRT_Set: { + assert( nColumn==1 ); + sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3); + sqlite3VdbeAddOp(v, OP_Pop, 1, 0); + sqlite3VdbeAddOp(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+3); + sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &p->affinity, 1); + sqlite3VdbeAddOp(v, OP_IdxInsert, (iParm&0x0000FFFF), 0); + break; + } + case SRT_Mem: { + assert( nColumn==1 ); + sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1); + /* The LIMIT clause will terminate the loop for us */ + break; + } +#endif + case SRT_Callback: + case SRT_Subroutine: { + int i; + sqlite3VdbeAddOp(v, OP_Insert, pseudoTab, 0); + for(i=0; iiLimit>=0 ){ + sqlite3VdbeAddOp(v, OP_MemIncr, -1, p->iLimit); + sqlite3VdbeAddOp(v, OP_IfMemZero, p->iLimit, brk); + } + + /* The bottom of the loop + */ + sqlite3VdbeResolveLabel(v, cont); + sqlite3VdbeAddOp(v, OP_Next, iTab, addr); + sqlite3VdbeResolveLabel(v, brk); + if( eDest==SRT_Callback || eDest==SRT_Subroutine ){ + sqlite3VdbeAddOp(v, OP_Close, pseudoTab, 0); + } + +} + +/* +** Return a pointer to a string containing the 'declaration type' of the +** expression pExpr. The string may be treated as static by the caller. +** +** The declaration type is the exact datatype definition extracted from the +** original CREATE TABLE statement if the expression is a column. The +** declaration type for a ROWID field is INTEGER. Exactly when an expression +** is considered a column can be complex in the presence of subqueries. The +** result-set expression in all of the following SELECT statements is +** considered a column by this function. +** +** SELECT col FROM tbl; +** SELECT (SELECT col FROM tbl; +** SELECT (SELECT col FROM tbl); +** SELECT abc FROM (SELECT col AS abc FROM tbl); +** +** The declaration type for any expression other than a column is NULL. +*/ +static const char *columnType( + NameContext *pNC, + Expr *pExpr, + const char **pzOriginDb, + const char **pzOriginTab, + const char **pzOriginCol +){ + char const *zType = 0; + char const *zOriginDb = 0; + char const *zOriginTab = 0; + char const *zOriginCol = 0; + int j; + if( pExpr==0 || pNC->pSrcList==0 ) return 0; + + switch( pExpr->op ){ + case TK_AGG_COLUMN: + case TK_COLUMN: { + /* The expression is a column. Locate the table the column is being + ** extracted from in NameContext.pSrcList. This table may be real + ** database table or a subquery. + */ + Table *pTab = 0; /* Table structure column is extracted from */ + Select *pS = 0; /* Select the column is extracted from */ + int iCol = pExpr->iColumn; /* Index of column in pTab */ + while( pNC && !pTab ){ + SrcList *pTabList = pNC->pSrcList; + for(j=0;jnSrc && pTabList->a[j].iCursor!=pExpr->iTable;j++); + if( jnSrc ){ + pTab = pTabList->a[j].pTab; + pS = pTabList->a[j].pSelect; + }else{ + pNC = pNC->pNext; + } + } + + if( pTab==0 ){ + /* FIX ME: + ** This can occurs if you have something like "SELECT new.x;" inside + ** a trigger. In other words, if you reference the special "new" + ** table in the result set of a select. We do not have a good way + ** to find the actual table type, so call it "TEXT". This is really + ** something of a bug, but I do not know how to fix it. + ** + ** This code does not produce the correct answer - it just prevents + ** a segfault. See ticket #1229. + */ + zType = "TEXT"; + break; + } + + assert( pTab ); + if( pS ){ + /* The "table" is actually a sub-select or a view in the FROM clause + ** of the SELECT statement. Return the declaration type and origin + ** data for the result-set column of the sub-select. + */ + if( iCol>=0 && iColpEList->nExpr ){ + /* If iCol is less than zero, then the expression requests the + ** rowid of the sub-select or view. This expression is legal (see + ** test case misc2.2.2) - it always evaluates to NULL. + */ + NameContext sNC; + Expr *p = pS->pEList->a[iCol].pExpr; + sNC.pSrcList = pS->pSrc; + sNC.pNext = 0; + sNC.pParse = pNC->pParse; + zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol); + } + }else if( pTab->pSchema ){ + /* A real table */ + assert( !pS ); + if( iCol<0 ) iCol = pTab->iPKey; + assert( iCol==-1 || (iCol>=0 && iColnCol) ); + if( iCol<0 ){ + zType = "INTEGER"; + zOriginCol = "rowid"; + }else{ + zType = pTab->aCol[iCol].zType; + zOriginCol = pTab->aCol[iCol].zName; + } + zOriginTab = pTab->zName; + if( pNC->pParse ){ + int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema); + zOriginDb = pNC->pParse->db->aDb[iDb].zName; + } + } + break; + } +#ifndef SQLITE_OMIT_SUBQUERY + case TK_SELECT: { + /* The expression is a sub-select. Return the declaration type and + ** origin info for the single column in the result set of the SELECT + ** statement. + */ + NameContext sNC; + Select *pS = pExpr->pSelect; + Expr *p = pS->pEList->a[0].pExpr; + sNC.pSrcList = pS->pSrc; + sNC.pNext = pNC; + sNC.pParse = pNC->pParse; + zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol); + break; + } +#endif + } + + if( pzOriginDb ){ + assert( pzOriginTab && pzOriginCol ); + *pzOriginDb = zOriginDb; + *pzOriginTab = zOriginTab; + *pzOriginCol = zOriginCol; + } + return zType; +} + +/* +** Generate code that will tell the VDBE the declaration types of columns +** in the result set. +*/ +static void generateColumnTypes( + Parse *pParse, /* Parser context */ + SrcList *pTabList, /* List of tables */ + ExprList *pEList /* Expressions defining the result set */ +){ + Vdbe *v = pParse->pVdbe; + int i; + NameContext sNC; + sNC.pSrcList = pTabList; + sNC.pParse = pParse; + for(i=0; inExpr; i++){ + Expr *p = pEList->a[i].pExpr; + const char *zOrigDb = 0; + const char *zOrigTab = 0; + const char *zOrigCol = 0; + const char *zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol); + + /* The vdbe must make it's own copy of the column-type and other + ** column specific strings, in case the schema is reset before this + ** virtual machine is deleted. + */ + sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, P3_TRANSIENT); + sqlite3VdbeSetColName(v, i, COLNAME_DATABASE, zOrigDb, P3_TRANSIENT); + sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, P3_TRANSIENT); + sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, P3_TRANSIENT); + } +} + +/* +** Generate code that will tell the VDBE the names of columns +** in the result set. This information is used to provide the +** azCol[] values in the callback. +*/ +static void generateColumnNames( + Parse *pParse, /* Parser context */ + SrcList *pTabList, /* List of tables */ + ExprList *pEList /* Expressions defining the result set */ +){ + Vdbe *v = pParse->pVdbe; + int i, j; + sqlite3 *db = pParse->db; + int fullNames, shortNames; + +#ifndef SQLITE_OMIT_EXPLAIN + /* If this is an EXPLAIN, skip this step */ + if( pParse->explain ){ + return; + } +#endif + + assert( v!=0 ); + if( pParse->colNamesSet || v==0 || sqlite3MallocFailed() ) return; + pParse->colNamesSet = 1; + fullNames = (db->flags & SQLITE_FullColNames)!=0; + shortNames = (db->flags & SQLITE_ShortColNames)!=0; + sqlite3VdbeSetNumCols(v, pEList->nExpr); + for(i=0; inExpr; i++){ + Expr *p; + p = pEList->a[i].pExpr; + if( p==0 ) continue; + if( pEList->a[i].zName ){ + char *zName = pEList->a[i].zName; + sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, strlen(zName)); + continue; + } + if( p->op==TK_COLUMN && pTabList ){ + Table *pTab; + char *zCol; + int iCol = p->iColumn; + for(j=0; jnSrc && pTabList->a[j].iCursor!=p->iTable; j++){} + assert( jnSrc ); + pTab = pTabList->a[j].pTab; + if( iCol<0 ) iCol = pTab->iPKey; + assert( iCol==-1 || (iCol>=0 && iColnCol) ); + if( iCol<0 ){ + zCol = "rowid"; + }else{ + zCol = pTab->aCol[iCol].zName; + } + if( !shortNames && !fullNames && p->span.z && p->span.z[0] ){ + sqlite3VdbeSetColName(v, i, COLNAME_NAME, (char*)p->span.z, p->span.n); + }else if( fullNames || (!shortNames && pTabList->nSrc>1) ){ + char *zName = 0; + char *zTab; + + zTab = pTabList->a[j].zAlias; + if( fullNames || zTab==0 ) zTab = pTab->zName; + sqlite3SetString(&zName, zTab, ".", zCol, (char*)0); + sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, P3_DYNAMIC); + }else{ + sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, strlen(zCol)); + } + }else if( p->span.z && p->span.z[0] ){ + sqlite3VdbeSetColName(v, i, COLNAME_NAME, (char*)p->span.z, p->span.n); + /* sqlite3VdbeCompressSpace(v, addr); */ + }else{ + char zName[30]; + assert( p->op!=TK_COLUMN || pTabList==0 ); + sqlite3_snprintf(sizeof(zName), zName, "column%d", i+1); + sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, 0); + } + } + generateColumnTypes(pParse, pTabList, pEList); +} + +#ifndef SQLITE_OMIT_COMPOUND_SELECT +/* +** Name of the connection operator, used for error messages. +*/ +static const char *selectOpName(int id){ + char *z; + switch( id ){ + case TK_ALL: z = "UNION ALL"; break; + case TK_INTERSECT: z = "INTERSECT"; break; + case TK_EXCEPT: z = "EXCEPT"; break; + default: z = "UNION"; break; + } + return z; +} +#endif /* SQLITE_OMIT_COMPOUND_SELECT */ + +/* +** Forward declaration +*/ +static int prepSelectStmt(Parse*, Select*); + +/* +** Given a SELECT statement, generate a Table structure that describes +** the result set of that SELECT. +*/ +Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){ + Table *pTab; + int i, j; + ExprList *pEList; + Column *aCol, *pCol; + + while( pSelect->pPrior ) pSelect = pSelect->pPrior; + if( prepSelectStmt(pParse, pSelect) ){ + return 0; + } + if( sqlite3SelectResolve(pParse, pSelect, 0) ){ + return 0; + } + pTab = sqliteMalloc( sizeof(Table) ); + if( pTab==0 ){ + return 0; + } + pTab->nRef = 1; + pTab->zName = zTabName ? sqliteStrDup(zTabName) : 0; + pEList = pSelect->pEList; + pTab->nCol = pEList->nExpr; + assert( pTab->nCol>0 ); + pTab->aCol = aCol = sqliteMalloc( sizeof(pTab->aCol[0])*pTab->nCol ); + for(i=0, pCol=aCol; inCol; i++, pCol++){ + Expr *p, *pR; + char *zType; + char *zName; + int nName; + CollSeq *pColl; + int cnt; + NameContext sNC; + + /* Get an appropriate name for the column + */ + p = pEList->a[i].pExpr; + assert( p->pRight==0 || p->pRight->token.z==0 || p->pRight->token.z[0]!=0 ); + if( (zName = pEList->a[i].zName)!=0 ){ + /* If the column contains an "AS " phrase, use as the name */ + zName = sqliteStrDup(zName); + }else if( p->op==TK_DOT + && (pR=p->pRight)!=0 && pR->token.z && pR->token.z[0] ){ + /* For columns of the from A.B use B as the name */ + zName = sqlite3MPrintf("%T", &pR->token); + }else if( p->span.z && p->span.z[0] ){ + /* Use the original text of the column expression as its name */ + zName = sqlite3MPrintf("%T", &p->span); + }else{ + /* If all else fails, make up a name */ + zName = sqlite3MPrintf("column%d", i+1); + } + sqlite3Dequote(zName); + if( sqlite3MallocFailed() ){ + sqliteFree(zName); + sqlite3DeleteTable(pTab); + return 0; + } + + /* Make sure the column name is unique. If the name is not unique, + ** append a integer to the name so that it becomes unique. + */ + nName = strlen(zName); + for(j=cnt=0; jzName = zName; + + /* Get the typename, type affinity, and collating sequence for the + ** column. + */ + memset(&sNC, 0, sizeof(sNC)); + sNC.pSrcList = pSelect->pSrc; + zType = sqliteStrDup(columnType(&sNC, p, 0, 0, 0)); + pCol->zType = zType; + pCol->affinity = sqlite3ExprAffinity(p); + pColl = sqlite3ExprCollSeq(pParse, p); + if( pColl ){ + pCol->zColl = sqliteStrDup(pColl->zName); + } + } + pTab->iPKey = -1; + return pTab; +} + +/* +** Prepare a SELECT statement for processing by doing the following +** things: +** +** (1) Make sure VDBE cursor numbers have been assigned to every +** element of the FROM clause. +** +** (2) Fill in the pTabList->a[].pTab fields in the SrcList that +** defines FROM clause. When views appear in the FROM clause, +** fill pTabList->a[].pSelect with a copy of the SELECT statement +** that implements the view. A copy is made of the view's SELECT +** statement so that we can freely modify or delete that statement +** without worrying about messing up the presistent representation +** of the view. +** +** (3) Add terms to the WHERE clause to accomodate the NATURAL keyword +** on joins and the ON and USING clause of joins. +** +** (4) Scan the list of columns in the result set (pEList) looking +** for instances of the "*" operator or the TABLE.* operator. +** If found, expand each "*" to be every column in every table +** and TABLE.* to be every column in TABLE. +** +** Return 0 on success. If there are problems, leave an error message +** in pParse and return non-zero. +*/ +static int prepSelectStmt(Parse *pParse, Select *p){ + int i, j, k, rc; + SrcList *pTabList; + ExprList *pEList; + struct SrcList_item *pFrom; + + if( p==0 || p->pSrc==0 || sqlite3MallocFailed() ){ + return 1; + } + pTabList = p->pSrc; + pEList = p->pEList; + + /* Make sure cursor numbers have been assigned to all entries in + ** the FROM clause of the SELECT statement. + */ + sqlite3SrcListAssignCursors(pParse, p->pSrc); + + /* Look up every table named in the FROM clause of the select. If + ** an entry of the FROM clause is a subquery instead of a table or view, + ** then create a transient table structure to describe the subquery. + */ + for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ + Table *pTab; + if( pFrom->pTab!=0 ){ + /* This statement has already been prepared. There is no need + ** to go further. */ + assert( i==0 ); + return 0; + } + if( pFrom->zName==0 ){ +#ifndef SQLITE_OMIT_SUBQUERY + /* A sub-query in the FROM clause of a SELECT */ + assert( pFrom->pSelect!=0 ); + if( pFrom->zAlias==0 ){ + pFrom->zAlias = + sqlite3MPrintf("sqlite_subquery_%p_", (void*)pFrom->pSelect); + } + assert( pFrom->pTab==0 ); + pFrom->pTab = pTab = + sqlite3ResultSetOfSelect(pParse, pFrom->zAlias, pFrom->pSelect); + if( pTab==0 ){ + return 1; + } + /* The isEphem flag indicates that the Table structure has been + ** dynamically allocated and may be freed at any time. In other words, + ** pTab is not pointing to a persistent table structure that defines + ** part of the schema. */ + pTab->isEphem = 1; +#endif + }else{ + /* An ordinary table or view name in the FROM clause */ + assert( pFrom->pTab==0 ); + pFrom->pTab = pTab = + sqlite3LocateTable(pParse,pFrom->zName,pFrom->zDatabase); + if( pTab==0 ){ + return 1; + } + pTab->nRef++; +#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE) + if( pTab->pSelect || IsVirtual(pTab) ){ + /* We reach here if the named table is a really a view */ + if( sqlite3ViewGetColumnNames(pParse, pTab) ){ + return 1; + } + /* If pFrom->pSelect!=0 it means we are dealing with a + ** view within a view. The SELECT structure has already been + ** copied by the outer view so we can skip the copy step here + ** in the inner view. + */ + if( pFrom->pSelect==0 ){ + pFrom->pSelect = sqlite3SelectDup(pTab->pSelect); + } + } +#endif + } + } + + /* Process NATURAL keywords, and ON and USING clauses of joins. + */ + if( sqliteProcessJoin(pParse, p) ) return 1; + + /* For every "*" that occurs in the column list, insert the names of + ** all columns in all tables. And for every TABLE.* insert the names + ** of all columns in TABLE. The parser inserted a special expression + ** with the TK_ALL operator for each "*" that it found in the column list. + ** The following code just has to locate the TK_ALL expressions and expand + ** each one to the list of all columns in all tables. + ** + ** The first loop just checks to see if there are any "*" operators + ** that need expanding. + */ + for(k=0; knExpr; k++){ + Expr *pE = pEList->a[k].pExpr; + if( pE->op==TK_ALL ) break; + if( pE->op==TK_DOT && pE->pRight && pE->pRight->op==TK_ALL + && pE->pLeft && pE->pLeft->op==TK_ID ) break; + } + rc = 0; + if( knExpr ){ + /* + ** If we get here it means the result set contains one or more "*" + ** operators that need to be expanded. Loop through each expression + ** in the result set and expand them one by one. + */ + struct ExprList_item *a = pEList->a; + ExprList *pNew = 0; + int flags = pParse->db->flags; + int longNames = (flags & SQLITE_FullColNames)!=0 && + (flags & SQLITE_ShortColNames)==0; + + for(k=0; knExpr; k++){ + Expr *pE = a[k].pExpr; + if( pE->op!=TK_ALL && + (pE->op!=TK_DOT || pE->pRight==0 || pE->pRight->op!=TK_ALL) ){ + /* This particular expression does not need to be expanded. + */ + pNew = sqlite3ExprListAppend(pNew, a[k].pExpr, 0); + if( pNew ){ + pNew->a[pNew->nExpr-1].zName = a[k].zName; + }else{ + rc = 1; + } + a[k].pExpr = 0; + a[k].zName = 0; + }else{ + /* This expression is a "*" or a "TABLE.*" and needs to be + ** expanded. */ + int tableSeen = 0; /* Set to 1 when TABLE matches */ + char *zTName; /* text of name of TABLE */ + if( pE->op==TK_DOT && pE->pLeft ){ + zTName = sqlite3NameFromToken(&pE->pLeft->token); + }else{ + zTName = 0; + } + for(i=0, pFrom=pTabList->a; inSrc; i++, pFrom++){ + Table *pTab = pFrom->pTab; + char *zTabName = pFrom->zAlias; + if( zTabName==0 || zTabName[0]==0 ){ + zTabName = pTab->zName; + } + if( zTName && (zTabName==0 || zTabName[0]==0 || + sqlite3StrICmp(zTName, zTabName)!=0) ){ + continue; + } + tableSeen = 1; + for(j=0; jnCol; j++){ + Expr *pExpr, *pRight; + char *zName = pTab->aCol[j].zName; + + /* If a column is marked as 'hidden' (currently only possible + ** for virtual tables), do not include it in the expanded + ** result-set list. + */ + if( IsHiddenColumn(&pTab->aCol[j]) ){ + assert(IsVirtual(pTab)); + continue; + } + + if( i>0 ){ + struct SrcList_item *pLeft = &pTabList->a[i-1]; + if( (pLeft[1].jointype & JT_NATURAL)!=0 && + columnIndex(pLeft->pTab, zName)>=0 ){ + /* In a NATURAL join, omit the join columns from the + ** table on the right */ + continue; + } + if( sqlite3IdListIndex(pLeft[1].pUsing, zName)>=0 ){ + /* In a join with a USING clause, omit columns in the + ** using clause from the table on the right. */ + continue; + } + } + pRight = sqlite3Expr(TK_ID, 0, 0, 0); + if( pRight==0 ) break; + setQuotedToken(&pRight->token, zName); + if( zTabName && (longNames || pTabList->nSrc>1) ){ + Expr *pLeft = sqlite3Expr(TK_ID, 0, 0, 0); + pExpr = sqlite3Expr(TK_DOT, pLeft, pRight, 0); + if( pExpr==0 ) break; + setQuotedToken(&pLeft->token, zTabName); + setToken(&pExpr->span, sqlite3MPrintf("%s.%s", zTabName, zName)); + pExpr->span.dyn = 1; + pExpr->token.z = 0; + pExpr->token.n = 0; + pExpr->token.dyn = 0; + }else{ + pExpr = pRight; + pExpr->span = pExpr->token; + pExpr->span.dyn = 0; + } + if( longNames ){ + pNew = sqlite3ExprListAppend(pNew, pExpr, &pExpr->span); + }else{ + pNew = sqlite3ExprListAppend(pNew, pExpr, &pRight->token); + } + } + } + if( !tableSeen ){ + if( zTName ){ + sqlite3ErrorMsg(pParse, "no such table: %s", zTName); + }else{ + sqlite3ErrorMsg(pParse, "no tables specified"); + } + rc = 1; + } + sqliteFree(zTName); + } + } + sqlite3ExprListDelete(pEList); + p->pEList = pNew; + } + if( p->pEList && p->pEList->nExpr>SQLITE_MAX_COLUMN ){ + sqlite3ErrorMsg(pParse, "too many columns in result set"); + rc = SQLITE_ERROR; + } + if( sqlite3MallocFailed() ){ + rc = SQLITE_NOMEM; + } + return rc; +} + +#ifndef SQLITE_OMIT_COMPOUND_SELECT +/* +** This routine associates entries in an ORDER BY expression list with +** columns in a result. For each ORDER BY expression, the opcode of +** the top-level node is changed to TK_COLUMN and the iColumn value of +** the top-level node is filled in with column number and the iTable +** value of the top-level node is filled with iTable parameter. +** +** If there are prior SELECT clauses, they are processed first. A match +** in an earlier SELECT takes precedence over a later SELECT. +** +** Any entry that does not match is flagged as an error. The number +** of errors is returned. +*/ +static int matchOrderbyToColumn( + Parse *pParse, /* A place to leave error messages */ + Select *pSelect, /* Match to result columns of this SELECT */ + ExprList *pOrderBy, /* The ORDER BY values to match against columns */ + int iTable, /* Insert this value in iTable */ + int mustComplete /* If TRUE all ORDER BYs must match */ +){ + int nErr = 0; + int i, j; + ExprList *pEList; + + if( pSelect==0 || pOrderBy==0 ) return 1; + if( mustComplete ){ + for(i=0; inExpr; i++){ pOrderBy->a[i].done = 0; } + } + if( prepSelectStmt(pParse, pSelect) ){ + return 1; + } + if( pSelect->pPrior ){ + if( matchOrderbyToColumn(pParse, pSelect->pPrior, pOrderBy, iTable, 0) ){ + return 1; + } + } + pEList = pSelect->pEList; + for(i=0; inExpr; i++){ + struct ExprList_item *pItem; + Expr *pE = pOrderBy->a[i].pExpr; + int iCol = -1; + char *zLabel; + + if( pOrderBy->a[i].done ) continue; + if( sqlite3ExprIsInteger(pE, &iCol) ){ + if( iCol<=0 || iCol>pEList->nExpr ){ + sqlite3ErrorMsg(pParse, + "ORDER BY position %d should be between 1 and %d", + iCol, pEList->nExpr); + nErr++; + break; + } + if( !mustComplete ) continue; + iCol--; + } + if( iCol<0 && (zLabel = sqlite3NameFromToken(&pE->token))!=0 ){ + for(j=0, pItem=pEList->a; jnExpr; j++, pItem++){ + char *zName; + int isMatch; + if( pItem->zName ){ + zName = sqlite3StrDup(pItem->zName); + }else{ + zName = sqlite3NameFromToken(&pItem->pExpr->token); + } + isMatch = zName && sqlite3StrICmp(zName, zLabel)==0; + sqliteFree(zName); + if( isMatch ){ + iCol = j; + break; + } + } + sqliteFree(zLabel); + } + if( iCol>=0 ){ + pE->op = TK_COLUMN; + pE->iColumn = iCol; + pE->iTable = iTable; + pE->iAgg = -1; + pOrderBy->a[i].done = 1; + }else if( mustComplete ){ + sqlite3ErrorMsg(pParse, + "ORDER BY term number %d does not match any result column", i+1); + nErr++; + break; + } + } + return nErr; +} +#endif /* #ifndef SQLITE_OMIT_COMPOUND_SELECT */ + +/* +** Get a VDBE for the given parser context. Create a new one if necessary. +** If an error occurs, return NULL and leave a message in pParse. +*/ +Vdbe *sqlite3GetVdbe(Parse *pParse){ + Vdbe *v = pParse->pVdbe; + if( v==0 ){ + v = pParse->pVdbe = sqlite3VdbeCreate(pParse->db); + } + return v; +} + + +/* +** Compute the iLimit and iOffset fields of the SELECT based on the +** pLimit and pOffset expressions. pLimit and pOffset hold the expressions +** that appear in the original SQL statement after the LIMIT and OFFSET +** keywords. Or NULL if those keywords are omitted. iLimit and iOffset +** are the integer memory register numbers for counters used to compute +** the limit and offset. If there is no limit and/or offset, then +** iLimit and iOffset are negative. +** +** This routine changes the values of iLimit and iOffset only if +** a limit or offset is defined by pLimit and pOffset. iLimit and +** iOffset should have been preset to appropriate default values +** (usually but not always -1) prior to calling this routine. +** Only if pLimit!=0 or pOffset!=0 do the limit registers get +** redefined. The UNION ALL operator uses this property to force +** the reuse of the same limit and offset registers across multiple +** SELECT statements. +*/ +static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ + Vdbe *v = 0; + int iLimit = 0; + int iOffset; + int addr1, addr2; + + /* + ** "LIMIT -1" always shows all rows. There is some + ** contraversy about what the correct behavior should be. + ** The current implementation interprets "LIMIT 0" to mean + ** no rows. + */ + if( p->pLimit ){ + p->iLimit = iLimit = pParse->nMem; + pParse->nMem += 2; + v = sqlite3GetVdbe(pParse); + if( v==0 ) return; + sqlite3ExprCode(pParse, p->pLimit); + sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0); + sqlite3VdbeAddOp(v, OP_MemStore, iLimit, 1); + VdbeComment((v, "# LIMIT counter")); + sqlite3VdbeAddOp(v, OP_IfMemZero, iLimit, iBreak); + sqlite3VdbeAddOp(v, OP_MemLoad, iLimit, 0); + } + if( p->pOffset ){ + p->iOffset = iOffset = pParse->nMem++; + v = sqlite3GetVdbe(pParse); + if( v==0 ) return; + sqlite3ExprCode(pParse, p->pOffset); + sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0); + sqlite3VdbeAddOp(v, OP_MemStore, iOffset, p->pLimit==0); + VdbeComment((v, "# OFFSET counter")); + addr1 = sqlite3VdbeAddOp(v, OP_IfMemPos, iOffset, 0); + sqlite3VdbeAddOp(v, OP_Pop, 1, 0); + sqlite3VdbeAddOp(v, OP_Integer, 0, 0); + sqlite3VdbeJumpHere(v, addr1); + if( p->pLimit ){ + sqlite3VdbeAddOp(v, OP_Add, 0, 0); + } + } + if( p->pLimit ){ + addr1 = sqlite3VdbeAddOp(v, OP_IfMemPos, iLimit, 0); + sqlite3VdbeAddOp(v, OP_Pop, 1, 0); + sqlite3VdbeAddOp(v, OP_MemInt, -1, iLimit+1); + addr2 = sqlite3VdbeAddOp(v, OP_Goto, 0, 0); + sqlite3VdbeJumpHere(v, addr1); + sqlite3VdbeAddOp(v, OP_MemStore, iLimit+1, 1); + VdbeComment((v, "# LIMIT+OFFSET")); + sqlite3VdbeJumpHere(v, addr2); + } +} + +/* +** Allocate a virtual index to use for sorting. +*/ +static void createSortingIndex(Parse *pParse, Select *p, ExprList *pOrderBy){ + if( pOrderBy ){ + int addr; + assert( pOrderBy->iECursor==0 ); + pOrderBy->iECursor = pParse->nTab++; + addr = sqlite3VdbeAddOp(pParse->pVdbe, OP_OpenEphemeral, + pOrderBy->iECursor, pOrderBy->nExpr+1); + assert( p->addrOpenEphm[2] == -1 ); + p->addrOpenEphm[2] = addr; + } +} + +#ifndef SQLITE_OMIT_COMPOUND_SELECT +/* +** Return the appropriate collating sequence for the iCol-th column of +** the result set for the compound-select statement "p". Return NULL if +** the column has no default collating sequence. +** +** The collating sequence for the compound select is taken from the +** left-most term of the select that has a collating sequence. +*/ +static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){ + CollSeq *pRet; + if( p->pPrior ){ + pRet = multiSelectCollSeq(pParse, p->pPrior, iCol); + }else{ + pRet = 0; + } + if( pRet==0 ){ + pRet = sqlite3ExprCollSeq(pParse, p->pEList->a[iCol].pExpr); + } + return pRet; +} +#endif /* SQLITE_OMIT_COMPOUND_SELECT */ + +#ifndef SQLITE_OMIT_COMPOUND_SELECT +/* +** This routine is called to process a query that is really the union +** or intersection of two or more separate queries. +** +** "p" points to the right-most of the two queries. the query on the +** left is p->pPrior. The left query could also be a compound query +** in which case this routine will be called recursively. +** +** The results of the total query are to be written into a destination +** of type eDest with parameter iParm. +** +** Example 1: Consider a three-way compound SQL statement. +** +** SELECT a FROM t1 UNION SELECT b FROM t2 UNION SELECT c FROM t3 +** +** This statement is parsed up as follows: +** +** SELECT c FROM t3 +** | +** `-----> SELECT b FROM t2 +** | +** `------> SELECT a FROM t1 +** +** The arrows in the diagram above represent the Select.pPrior pointer. +** So if this routine is called with p equal to the t3 query, then +** pPrior will be the t2 query. p->op will be TK_UNION in this case. +** +** Notice that because of the way SQLite parses compound SELECTs, the +** individual selects always group from left to right. +*/ +static int multiSelect( + Parse *pParse, /* Parsing context */ + Select *p, /* The right-most of SELECTs to be coded */ + int eDest, /* \___ Store query results as specified */ + int iParm, /* / by these two parameters. */ + char *aff /* If eDest is SRT_Union, the affinity string */ +){ + int rc = SQLITE_OK; /* Success code from a subroutine */ + Select *pPrior; /* Another SELECT immediately to our left */ + Vdbe *v; /* Generate code to this VDBE */ + int nCol; /* Number of columns in the result set */ + ExprList *pOrderBy; /* The ORDER BY clause on p */ + int aSetP2[2]; /* Set P2 value of these op to number of columns */ + int nSetP2 = 0; /* Number of slots in aSetP2[] used */ + + /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs. Only + ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT. + */ + if( p==0 || p->pPrior==0 ){ + rc = 1; + goto multi_select_end; + } + pPrior = p->pPrior; + assert( pPrior->pRightmost!=pPrior ); + assert( pPrior->pRightmost==p->pRightmost ); + if( pPrior->pOrderBy ){ + sqlite3ErrorMsg(pParse,"ORDER BY clause should come after %s not before", + selectOpName(p->op)); + rc = 1; + goto multi_select_end; + } + if( pPrior->pLimit ){ + sqlite3ErrorMsg(pParse,"LIMIT clause should come after %s not before", + selectOpName(p->op)); + rc = 1; + goto multi_select_end; + } + + /* Make sure we have a valid query engine. If not, create a new one. + */ + v = sqlite3GetVdbe(pParse); + if( v==0 ){ + rc = 1; + goto multi_select_end; + } + + /* Create the destination temporary table if necessary + */ + if( eDest==SRT_EphemTab ){ + assert( p->pEList ); + assert( nSetP2pOrderBy; + switch( p->op ){ + case TK_ALL: { + if( pOrderBy==0 ){ + int addr = 0; + assert( !pPrior->pLimit ); + pPrior->pLimit = p->pLimit; + pPrior->pOffset = p->pOffset; + rc = sqlite3Select(pParse, pPrior, eDest, iParm, 0, 0, 0, aff); + p->pLimit = 0; + p->pOffset = 0; + if( rc ){ + goto multi_select_end; + } + p->pPrior = 0; + p->iLimit = pPrior->iLimit; + p->iOffset = pPrior->iOffset; + if( p->iLimit>=0 ){ + addr = sqlite3VdbeAddOp(v, OP_IfMemZero, p->iLimit, 0); + VdbeComment((v, "# Jump ahead if LIMIT reached")); + } + rc = sqlite3Select(pParse, p, eDest, iParm, 0, 0, 0, aff); + p->pPrior = pPrior; + if( rc ){ + goto multi_select_end; + } + if( addr ){ + sqlite3VdbeJumpHere(v, addr); + } + break; + } + /* For UNION ALL ... ORDER BY fall through to the next case */ + } + case TK_EXCEPT: + case TK_UNION: { + int unionTab; /* Cursor number of the temporary table holding result */ + int op = 0; /* One of the SRT_ operations to apply to self */ + int priorOp; /* The SRT_ operation to apply to prior selects */ + Expr *pLimit, *pOffset; /* Saved values of p->nLimit and p->nOffset */ + int addr; + + priorOp = p->op==TK_ALL ? SRT_Table : SRT_Union; + if( eDest==priorOp && pOrderBy==0 && !p->pLimit && !p->pOffset ){ + /* We can reuse a temporary table generated by a SELECT to our + ** right. + */ + unionTab = iParm; + }else{ + /* We will need to create our own temporary table to hold the + ** intermediate results. + */ + unionTab = pParse->nTab++; + if( pOrderBy && matchOrderbyToColumn(pParse, p, pOrderBy, unionTab,1) ){ + rc = 1; + goto multi_select_end; + } + addr = sqlite3VdbeAddOp(v, OP_OpenEphemeral, unionTab, 0); + if( priorOp==SRT_Table ){ + assert( nSetP2addrOpenEphm[0] == -1 ); + p->addrOpenEphm[0] = addr; + p->pRightmost->usesEphm = 1; + } + createSortingIndex(pParse, p, pOrderBy); + assert( p->pEList ); + } + + /* Code the SELECT statements to our left + */ + assert( !pPrior->pOrderBy ); + rc = sqlite3Select(pParse, pPrior, priorOp, unionTab, 0, 0, 0, aff); + if( rc ){ + goto multi_select_end; + } + + /* Code the current SELECT statement + */ + switch( p->op ){ + case TK_EXCEPT: op = SRT_Except; break; + case TK_UNION: op = SRT_Union; break; + case TK_ALL: op = SRT_Table; break; + } + p->pPrior = 0; + p->pOrderBy = 0; + p->disallowOrderBy = pOrderBy!=0; + pLimit = p->pLimit; + p->pLimit = 0; + pOffset = p->pOffset; + p->pOffset = 0; + rc = sqlite3Select(pParse, p, op, unionTab, 0, 0, 0, aff); + /* Query flattening in sqlite3Select() might refill p->pOrderBy. + ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */ + sqlite3ExprListDelete(p->pOrderBy); + p->pPrior = pPrior; + p->pOrderBy = pOrderBy; + sqlite3ExprDelete(p->pLimit); + p->pLimit = pLimit; + p->pOffset = pOffset; + p->iLimit = -1; + p->iOffset = -1; + if( rc ){ + goto multi_select_end; + } + + + /* Convert the data in the temporary table into whatever form + ** it is that we currently need. + */ + if( eDest!=priorOp || unionTab!=iParm ){ + int iCont, iBreak, iStart; + assert( p->pEList ); + if( eDest==SRT_Callback ){ + Select *pFirst = p; + while( pFirst->pPrior ) pFirst = pFirst->pPrior; + generateColumnNames(pParse, 0, pFirst->pEList); + } + iBreak = sqlite3VdbeMakeLabel(v); + iCont = sqlite3VdbeMakeLabel(v); + computeLimitRegisters(pParse, p, iBreak); + sqlite3VdbeAddOp(v, OP_Rewind, unionTab, iBreak); + iStart = sqlite3VdbeCurrentAddr(v); + rc = selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr, + pOrderBy, -1, eDest, iParm, + iCont, iBreak, 0); + if( rc ){ + rc = 1; + goto multi_select_end; + } + sqlite3VdbeResolveLabel(v, iCont); + sqlite3VdbeAddOp(v, OP_Next, unionTab, iStart); + sqlite3VdbeResolveLabel(v, iBreak); + sqlite3VdbeAddOp(v, OP_Close, unionTab, 0); + } + break; + } + case TK_INTERSECT: { + int tab1, tab2; + int iCont, iBreak, iStart; + Expr *pLimit, *pOffset; + int addr; + + /* INTERSECT is different from the others since it requires + ** two temporary tables. Hence it has its own case. Begin + ** by allocating the tables we will need. + */ + tab1 = pParse->nTab++; + tab2 = pParse->nTab++; + if( pOrderBy && matchOrderbyToColumn(pParse,p,pOrderBy,tab1,1) ){ + rc = 1; + goto multi_select_end; + } + createSortingIndex(pParse, p, pOrderBy); + + addr = sqlite3VdbeAddOp(v, OP_OpenEphemeral, tab1, 0); + assert( p->addrOpenEphm[0] == -1 ); + p->addrOpenEphm[0] = addr; + p->pRightmost->usesEphm = 1; + assert( p->pEList ); + + /* Code the SELECTs to our left into temporary table "tab1". + */ + rc = sqlite3Select(pParse, pPrior, SRT_Union, tab1, 0, 0, 0, aff); + if( rc ){ + goto multi_select_end; + } + + /* Code the current SELECT into temporary table "tab2" + */ + addr = sqlite3VdbeAddOp(v, OP_OpenEphemeral, tab2, 0); + assert( p->addrOpenEphm[1] == -1 ); + p->addrOpenEphm[1] = addr; + p->pPrior = 0; + pLimit = p->pLimit; + p->pLimit = 0; + pOffset = p->pOffset; + p->pOffset = 0; + rc = sqlite3Select(pParse, p, SRT_Union, tab2, 0, 0, 0, aff); + p->pPrior = pPrior; + sqlite3ExprDelete(p->pLimit); + p->pLimit = pLimit; + p->pOffset = pOffset; + if( rc ){ + goto multi_select_end; + } + + /* Generate code to take the intersection of the two temporary + ** tables. + */ + assert( p->pEList ); + if( eDest==SRT_Callback ){ + Select *pFirst = p; + while( pFirst->pPrior ) pFirst = pFirst->pPrior; + generateColumnNames(pParse, 0, pFirst->pEList); + } + iBreak = sqlite3VdbeMakeLabel(v); + iCont = sqlite3VdbeMakeLabel(v); + computeLimitRegisters(pParse, p, iBreak); + sqlite3VdbeAddOp(v, OP_Rewind, tab1, iBreak); + iStart = sqlite3VdbeAddOp(v, OP_RowKey, tab1, 0); + sqlite3VdbeAddOp(v, OP_NotFound, tab2, iCont); + rc = selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr, + pOrderBy, -1, eDest, iParm, + iCont, iBreak, 0); + if( rc ){ + rc = 1; + goto multi_select_end; + } + sqlite3VdbeResolveLabel(v, iCont); + sqlite3VdbeAddOp(v, OP_Next, tab1, iStart); + sqlite3VdbeResolveLabel(v, iBreak); + sqlite3VdbeAddOp(v, OP_Close, tab2, 0); + sqlite3VdbeAddOp(v, OP_Close, tab1, 0); + break; + } + } + + /* Make sure all SELECTs in the statement have the same number of elements + ** in their result sets. + */ + assert( p->pEList && pPrior->pEList ); + if( p->pEList->nExpr!=pPrior->pEList->nExpr ){ + sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s" + " do not have the same number of result columns", selectOpName(p->op)); + rc = 1; + goto multi_select_end; + } + + /* Set the number of columns in temporary tables + */ + nCol = p->pEList->nExpr; + while( nSetP2 ){ + sqlite3VdbeChangeP2(v, aSetP2[--nSetP2], nCol); + } + + /* Compute collating sequences used by either the ORDER BY clause or + ** by any temporary tables needed to implement the compound select. + ** Attach the KeyInfo structure to all temporary tables. Invoke the + ** ORDER BY processing if there is an ORDER BY clause. + ** + ** This section is run by the right-most SELECT statement only. + ** SELECT statements to the left always skip this part. The right-most + ** SELECT might also skip this part if it has no ORDER BY clause and + ** no temp tables are required. + */ + if( pOrderBy || p->usesEphm ){ + int i; /* Loop counter */ + KeyInfo *pKeyInfo; /* Collating sequence for the result set */ + Select *pLoop; /* For looping through SELECT statements */ + int nKeyCol; /* Number of entries in pKeyInfo->aCol[] */ + CollSeq **apColl; /* For looping through pKeyInfo->aColl[] */ + CollSeq **aCopy; /* A copy of pKeyInfo->aColl[] */ + + assert( p->pRightmost==p ); + nKeyCol = nCol + (pOrderBy ? pOrderBy->nExpr : 0); + pKeyInfo = sqliteMalloc(sizeof(*pKeyInfo)+nKeyCol*(sizeof(CollSeq*) + 1)); + if( !pKeyInfo ){ + rc = SQLITE_NOMEM; + goto multi_select_end; + } + + pKeyInfo->enc = ENC(pParse->db); + pKeyInfo->nField = nCol; + + for(i=0, apColl=pKeyInfo->aColl; idb->pDfltColl; + } + } + + for(pLoop=p; pLoop; pLoop=pLoop->pPrior){ + for(i=0; i<2; i++){ + int addr = pLoop->addrOpenEphm[i]; + if( addr<0 ){ + /* If [0] is unused then [1] is also unused. So we can + ** always safely abort as soon as the first unused slot is found */ + assert( pLoop->addrOpenEphm[1]<0 ); + break; + } + sqlite3VdbeChangeP2(v, addr, nCol); + sqlite3VdbeChangeP3(v, addr, (char*)pKeyInfo, P3_KEYINFO); + pLoop->addrOpenEphm[i] = -1; + } + } + + if( pOrderBy ){ + struct ExprList_item *pOTerm = pOrderBy->a; + int nOrderByExpr = pOrderBy->nExpr; + int addr; + u8 *pSortOrder; + + /* Reuse the same pKeyInfo for the ORDER BY as was used above for + ** the compound select statements. Except we have to change out the + ** pKeyInfo->aColl[] values. Some of the aColl[] values will be + ** reused when constructing the pKeyInfo for the ORDER BY, so make + ** a copy. Sufficient space to hold both the nCol entries for + ** the compound select and the nOrderbyExpr entries for the ORDER BY + ** was allocated above. But we need to move the compound select + ** entries out of the way before constructing the ORDER BY entries. + ** Move the compound select entries into aCopy[] where they can be + ** accessed and reused when constructing the ORDER BY entries. + ** Because nCol might be greater than or less than nOrderByExpr + ** we have to use memmove() when doing the copy. + */ + aCopy = &pKeyInfo->aColl[nOrderByExpr]; + pSortOrder = pKeyInfo->aSortOrder = (u8*)&aCopy[nCol]; + memmove(aCopy, pKeyInfo->aColl, nCol*sizeof(CollSeq*)); + + apColl = pKeyInfo->aColl; + for(i=0; ipExpr; + if( (pExpr->flags & EP_ExpCollate) ){ + assert( pExpr->pColl!=0 ); + *apColl = pExpr->pColl; + }else{ + *apColl = aCopy[pExpr->iColumn]; + } + *pSortOrder = pOTerm->sortOrder; + } + assert( p->pRightmost==p ); + assert( p->addrOpenEphm[2]>=0 ); + addr = p->addrOpenEphm[2]; + sqlite3VdbeChangeP2(v, addr, p->pOrderBy->nExpr+2); + pKeyInfo->nField = nOrderByExpr; + sqlite3VdbeChangeP3(v, addr, (char*)pKeyInfo, P3_KEYINFO_HANDOFF); + pKeyInfo = 0; + generateSortTail(pParse, p, v, p->pEList->nExpr, eDest, iParm); + } + + sqliteFree(pKeyInfo); + } + +multi_select_end: + return rc; +} +#endif /* SQLITE_OMIT_COMPOUND_SELECT */ + +#ifndef SQLITE_OMIT_VIEW +/* +** Scan through the expression pExpr. Replace every reference to +** a column in table number iTable with a copy of the iColumn-th +** entry in pEList. (But leave references to the ROWID column +** unchanged.) +** +** This routine is part of the flattening procedure. A subquery +** whose result set is defined by pEList appears as entry in the +** FROM clause of a SELECT such that the VDBE cursor assigned to that +** FORM clause entry is iTable. This routine make the necessary +** changes to pExpr so that it refers directly to the source table +** of the subquery rather the result set of the subquery. +*/ +static void substExprList(ExprList*,int,ExprList*); /* Forward Decl */ +static void substSelect(Select *, int, ExprList *); /* Forward Decl */ +static void substExpr(Expr *pExpr, int iTable, ExprList *pEList){ + if( pExpr==0 ) return; + if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable ){ + if( pExpr->iColumn<0 ){ + pExpr->op = TK_NULL; + }else{ + Expr *pNew; + assert( pEList!=0 && pExpr->iColumnnExpr ); + assert( pExpr->pLeft==0 && pExpr->pRight==0 && pExpr->pList==0 ); + pNew = pEList->a[pExpr->iColumn].pExpr; + assert( pNew!=0 ); + pExpr->op = pNew->op; + assert( pExpr->pLeft==0 ); + pExpr->pLeft = sqlite3ExprDup(pNew->pLeft); + assert( pExpr->pRight==0 ); + pExpr->pRight = sqlite3ExprDup(pNew->pRight); + assert( pExpr->pList==0 ); + pExpr->pList = sqlite3ExprListDup(pNew->pList); + pExpr->iTable = pNew->iTable; + pExpr->pTab = pNew->pTab; + pExpr->iColumn = pNew->iColumn; + pExpr->iAgg = pNew->iAgg; + sqlite3TokenCopy(&pExpr->token, &pNew->token); + sqlite3TokenCopy(&pExpr->span, &pNew->span); + pExpr->pSelect = sqlite3SelectDup(pNew->pSelect); + pExpr->flags = pNew->flags; + } + }else{ + substExpr(pExpr->pLeft, iTable, pEList); + substExpr(pExpr->pRight, iTable, pEList); + substSelect(pExpr->pSelect, iTable, pEList); + substExprList(pExpr->pList, iTable, pEList); + } +} +static void substExprList(ExprList *pList, int iTable, ExprList *pEList){ + int i; + if( pList==0 ) return; + for(i=0; inExpr; i++){ + substExpr(pList->a[i].pExpr, iTable, pEList); + } +} +static void substSelect(Select *p, int iTable, ExprList *pEList){ + if( !p ) return; + substExprList(p->pEList, iTable, pEList); + substExprList(p->pGroupBy, iTable, pEList); + substExprList(p->pOrderBy, iTable, pEList); + substExpr(p->pHaving, iTable, pEList); + substExpr(p->pWhere, iTable, pEList); + substSelect(p->pPrior, iTable, pEList); +} +#endif /* !defined(SQLITE_OMIT_VIEW) */ + +#ifndef SQLITE_OMIT_VIEW +/* +** This routine attempts to flatten subqueries in order to speed +** execution. It returns 1 if it makes changes and 0 if no flattening +** occurs. +** +** To understand the concept of flattening, consider the following +** query: +** +** SELECT a FROM (SELECT x+y AS a FROM t1 WHERE z<100) WHERE a>5 +** +** The default way of implementing this query is to execute the +** subquery first and store the results in a temporary table, then +** run the outer query on that temporary table. This requires two +** passes over the data. Furthermore, because the temporary table +** has no indices, the WHERE clause on the outer query cannot be +** optimized. +** +** This routine attempts to rewrite queries such as the above into +** a single flat select, like this: +** +** SELECT x+y AS a FROM t1 WHERE z<100 AND a>5 +** +** The code generated for this simpification gives the same result +** but only has to scan the data once. And because indices might +** exist on the table t1, a complete scan of the data might be +** avoided. +** +** Flattening is only attempted if all of the following are true: +** +** (1) The subquery and the outer query do not both use aggregates. +** +** (2) The subquery is not an aggregate or the outer query is not a join. +** +** (3) The subquery is not the right operand of a left outer join, or +** the subquery is not itself a join. (Ticket #306) +** +** (4) The subquery is not DISTINCT or the outer query is not a join. +** +** (5) The subquery is not DISTINCT or the outer query does not use +** aggregates. +** +** (6) The subquery does not use aggregates or the outer query is not +** DISTINCT. +** +** (7) The subquery has a FROM clause. +** +** (8) The subquery does not use LIMIT or the outer query is not a join. +** +** (9) The subquery does not use LIMIT or the outer query does not use +** aggregates. +** +** (10) The subquery does not use aggregates or the outer query does not +** use LIMIT. +** +** (11) The subquery and the outer query do not both have ORDER BY clauses. +** +** (12) The subquery is not the right term of a LEFT OUTER JOIN or the +** subquery has no WHERE clause. (added by ticket #350) +** +** (13) The subquery and outer query do not both use LIMIT +** +** (14) The subquery does not use OFFSET +** +** (15) The outer query is not part of a compound select or the +** subquery does not have both an ORDER BY and a LIMIT clause. +** (See ticket #2339) +** +** In this routine, the "p" parameter is a pointer to the outer query. +** The subquery is p->pSrc->a[iFrom]. isAgg is true if the outer query +** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates. +** +** If flattening is not attempted, this routine is a no-op and returns 0. +** If flattening is attempted this routine returns 1. +** +** All of the expression analysis must occur on both the outer query and +** the subquery before this routine runs. +*/ +static int flattenSubquery( + Select *p, /* The parent or outer SELECT statement */ + int iFrom, /* Index in p->pSrc->a[] of the inner subquery */ + int isAgg, /* True if outer SELECT uses aggregate functions */ + int subqueryIsAgg /* True if the subquery uses aggregate functions */ +){ + Select *pSub; /* The inner query or "subquery" */ + SrcList *pSrc; /* The FROM clause of the outer query */ + SrcList *pSubSrc; /* The FROM clause of the subquery */ + ExprList *pList; /* The result set of the outer query */ + int iParent; /* VDBE cursor number of the pSub result set temp table */ + int i; /* Loop counter */ + Expr *pWhere; /* The WHERE clause */ + struct SrcList_item *pSubitem; /* The subquery */ + + /* Check to see if flattening is permitted. Return 0 if not. + */ + if( p==0 ) return 0; + pSrc = p->pSrc; + assert( pSrc && iFrom>=0 && iFromnSrc ); + pSubitem = &pSrc->a[iFrom]; + pSub = pSubitem->pSelect; + assert( pSub!=0 ); + if( isAgg && subqueryIsAgg ) return 0; /* Restriction (1) */ + if( subqueryIsAgg && pSrc->nSrc>1 ) return 0; /* Restriction (2) */ + pSubSrc = pSub->pSrc; + assert( pSubSrc ); + /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants, + ** not arbitrary expresssions, we allowed some combining of LIMIT and OFFSET + ** because they could be computed at compile-time. But when LIMIT and OFFSET + ** became arbitrary expressions, we were forced to add restrictions (13) + ** and (14). */ + if( pSub->pLimit && p->pLimit ) return 0; /* Restriction (13) */ + if( pSub->pOffset ) return 0; /* Restriction (14) */ + if( p->pRightmost && pSub->pLimit && pSub->pOrderBy ){ + return 0; /* Restriction (15) */ + } + if( pSubSrc->nSrc==0 ) return 0; /* Restriction (7) */ + if( (pSub->isDistinct || pSub->pLimit) + && (pSrc->nSrc>1 || isAgg) ){ /* Restrictions (4)(5)(8)(9) */ + return 0; + } + if( p->isDistinct && subqueryIsAgg ) return 0; /* Restriction (6) */ + if( (p->disallowOrderBy || p->pOrderBy) && pSub->pOrderBy ){ + return 0; /* Restriction (11) */ + } + + /* Restriction 3: If the subquery is a join, make sure the subquery is + ** not used as the right operand of an outer join. Examples of why this + ** is not allowed: + ** + ** t1 LEFT OUTER JOIN (t2 JOIN t3) + ** + ** If we flatten the above, we would get + ** + ** (t1 LEFT OUTER JOIN t2) JOIN t3 + ** + ** which is not at all the same thing. + */ + if( pSubSrc->nSrc>1 && (pSubitem->jointype & JT_OUTER)!=0 ){ + return 0; + } + + /* Restriction 12: If the subquery is the right operand of a left outer + ** join, make sure the subquery has no WHERE clause. + ** An examples of why this is not allowed: + ** + ** t1 LEFT OUTER JOIN (SELECT * FROM t2 WHERE t2.x>0) + ** + ** If we flatten the above, we would get + ** + ** (t1 LEFT OUTER JOIN t2) WHERE t2.x>0 + ** + ** But the t2.x>0 test will always fail on a NULL row of t2, which + ** effectively converts the OUTER JOIN into an INNER JOIN. + */ + if( (pSubitem->jointype & JT_OUTER)!=0 && pSub->pWhere!=0 ){ + return 0; + } + + /* If we reach this point, it means flattening is permitted for the + ** iFrom-th entry of the FROM clause in the outer query. + */ + + /* Move all of the FROM elements of the subquery into the + ** the FROM clause of the outer query. Before doing this, remember + ** the cursor number for the original outer query FROM element in + ** iParent. The iParent cursor will never be used. Subsequent code + ** will scan expressions looking for iParent references and replace + ** those references with expressions that resolve to the subquery FROM + ** elements we are now copying in. + */ + iParent = pSubitem->iCursor; + { + int nSubSrc = pSubSrc->nSrc; + int jointype = pSubitem->jointype; + + sqlite3DeleteTable(pSubitem->pTab); + sqliteFree(pSubitem->zDatabase); + sqliteFree(pSubitem->zName); + sqliteFree(pSubitem->zAlias); + if( nSubSrc>1 ){ + int extra = nSubSrc - 1; + for(i=1; ipSrc = pSrc; + for(i=pSrc->nSrc-1; i-extra>=iFrom; i--){ + pSrc->a[i] = pSrc->a[i-extra]; + } + } + for(i=0; ia[i+iFrom] = pSubSrc->a[i]; + memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i])); + } + pSrc->a[iFrom].jointype = jointype; + } + + /* Now begin substituting subquery result set expressions for + ** references to the iParent in the outer query. + ** + ** Example: + ** + ** SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b; + ** \ \_____________ subquery __________/ / + ** \_____________________ outer query ______________________________/ + ** + ** We look at every expression in the outer query and every place we see + ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10". + */ + pList = p->pEList; + for(i=0; inExpr; i++){ + Expr *pExpr; + if( pList->a[i].zName==0 && (pExpr = pList->a[i].pExpr)->span.z!=0 ){ + pList->a[i].zName = sqliteStrNDup((char*)pExpr->span.z, pExpr->span.n); + } + } + substExprList(p->pEList, iParent, pSub->pEList); + if( isAgg ){ + substExprList(p->pGroupBy, iParent, pSub->pEList); + substExpr(p->pHaving, iParent, pSub->pEList); + } + if( pSub->pOrderBy ){ + assert( p->pOrderBy==0 ); + p->pOrderBy = pSub->pOrderBy; + pSub->pOrderBy = 0; + }else if( p->pOrderBy ){ + substExprList(p->pOrderBy, iParent, pSub->pEList); + } + if( pSub->pWhere ){ + pWhere = sqlite3ExprDup(pSub->pWhere); + }else{ + pWhere = 0; + } + if( subqueryIsAgg ){ + assert( p->pHaving==0 ); + p->pHaving = p->pWhere; + p->pWhere = pWhere; + substExpr(p->pHaving, iParent, pSub->pEList); + p->pHaving = sqlite3ExprAnd(p->pHaving, sqlite3ExprDup(pSub->pHaving)); + assert( p->pGroupBy==0 ); + p->pGroupBy = sqlite3ExprListDup(pSub->pGroupBy); + }else{ + substExpr(p->pWhere, iParent, pSub->pEList); + p->pWhere = sqlite3ExprAnd(p->pWhere, pWhere); + } + + /* The flattened query is distinct if either the inner or the + ** outer query is distinct. + */ + p->isDistinct = p->isDistinct || pSub->isDistinct; + + /* + ** SELECT ... FROM (SELECT ... LIMIT a OFFSET b) LIMIT x OFFSET y; + ** + ** One is tempted to try to add a and b to combine the limits. But this + ** does not work if either limit is negative. + */ + if( pSub->pLimit ){ + p->pLimit = pSub->pLimit; + pSub->pLimit = 0; + } + + /* Finially, delete what is left of the subquery and return + ** success. + */ + sqlite3SelectDelete(pSub); + return 1; +} +#endif /* SQLITE_OMIT_VIEW */ + +/* +** Analyze the SELECT statement passed in as an argument to see if it +** is a simple min() or max() query. If it is and this query can be +** satisfied using a single seek to the beginning or end of an index, +** then generate the code for this SELECT and return 1. If this is not a +** simple min() or max() query, then return 0; +** +** A simply min() or max() query looks like this: +** +** SELECT min(a) FROM table; +** SELECT max(a) FROM table; +** +** The query may have only a single table in its FROM argument. There +** can be no GROUP BY or HAVING or WHERE clauses. The result set must +** be the min() or max() of a single column of the table. The column +** in the min() or max() function must be indexed. +** +** The parameters to this routine are the same as for sqlite3Select(). +** See the header comment on that routine for additional information. +*/ +static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){ + Expr *pExpr; + int iCol; + Table *pTab; + Index *pIdx; + int base; + Vdbe *v; + int seekOp; + ExprList *pEList, *pList, eList; + struct ExprList_item eListItem; + SrcList *pSrc; + int brk; + int iDb; + + /* Check to see if this query is a simple min() or max() query. Return + ** zero if it is not. + */ + if( p->pGroupBy || p->pHaving || p->pWhere ) return 0; + pSrc = p->pSrc; + if( pSrc->nSrc!=1 ) return 0; + pEList = p->pEList; + if( pEList->nExpr!=1 ) return 0; + pExpr = pEList->a[0].pExpr; + if( pExpr->op!=TK_AGG_FUNCTION ) return 0; + pList = pExpr->pList; + if( pList==0 || pList->nExpr!=1 ) return 0; + if( pExpr->token.n!=3 ) return 0; + if( sqlite3StrNICmp((char*)pExpr->token.z,"min",3)==0 ){ + seekOp = OP_Rewind; + }else if( sqlite3StrNICmp((char*)pExpr->token.z,"max",3)==0 ){ + seekOp = OP_Last; + }else{ + return 0; + } + pExpr = pList->a[0].pExpr; + if( pExpr->op!=TK_COLUMN ) return 0; + iCol = pExpr->iColumn; + pTab = pSrc->a[0].pTab; + + /* This optimization cannot be used with virtual tables. */ + if( IsVirtual(pTab) ) return 0; + + /* If we get to here, it means the query is of the correct form. + ** Check to make sure we have an index and make pIdx point to the + ** appropriate index. If the min() or max() is on an INTEGER PRIMARY + ** key column, no index is necessary so set pIdx to NULL. If no + ** usable index is found, return 0. + */ + if( iCol<0 ){ + pIdx = 0; + }else{ + CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr); + if( pColl==0 ) return 0; + for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ + assert( pIdx->nColumn>=1 ); + if( pIdx->aiColumn[0]==iCol && + 0==sqlite3StrICmp(pIdx->azColl[0], pColl->zName) ){ + break; + } + } + if( pIdx==0 ) return 0; + } + + /* Identify column types if we will be using the callback. This + ** step is skipped if the output is going to a table or a memory cell. + ** The column names have already been generated in the calling function. + */ + v = sqlite3GetVdbe(pParse); + if( v==0 ) return 0; + + /* If the output is destined for a temporary table, open that table. + */ + if( eDest==SRT_EphemTab ){ + sqlite3VdbeAddOp(v, OP_OpenEphemeral, iParm, 1); + } + + /* Generating code to find the min or the max. Basically all we have + ** to do is find the first or the last entry in the chosen index. If + ** the min() or max() is on the INTEGER PRIMARY KEY, then find the first + ** or last entry in the main table. + */ + iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); + assert( iDb>=0 || pTab->isEphem ); + sqlite3CodeVerifySchema(pParse, iDb); + sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); + base = pSrc->a[0].iCursor; + brk = sqlite3VdbeMakeLabel(v); + computeLimitRegisters(pParse, p, brk); + if( pSrc->a[0].pSelect==0 ){ + sqlite3OpenTable(pParse, base, iDb, pTab, OP_OpenRead); + } + if( pIdx==0 ){ + sqlite3VdbeAddOp(v, seekOp, base, 0); + }else{ + /* Even though the cursor used to open the index here is closed + ** as soon as a single value has been read from it, allocate it + ** using (pParse->nTab++) to prevent the cursor id from being + ** reused. This is important for statements of the form + ** "INSERT INTO x SELECT max() FROM x". + */ + int iIdx; + KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); + iIdx = pParse->nTab++; + assert( pIdx->pSchema==pTab->pSchema ); + sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); + sqlite3VdbeOp3(v, OP_OpenRead, iIdx, pIdx->tnum, + (char*)pKey, P3_KEYINFO_HANDOFF); + if( seekOp==OP_Rewind ){ + sqlite3VdbeAddOp(v, OP_Null, 0, 0); + sqlite3VdbeAddOp(v, OP_MakeRecord, 1, 0); + seekOp = OP_MoveGt; + } + if( pIdx->aSortOrder[0]==SQLITE_SO_DESC ){ + /* Ticket #2514: invert the seek operator if we are using + ** a descending index. */ + if( seekOp==OP_Last ){ + seekOp = OP_Rewind; + }else{ + assert( seekOp==OP_MoveGt ); + seekOp = OP_MoveLt; + } + } + sqlite3VdbeAddOp(v, seekOp, iIdx, 0); + sqlite3VdbeAddOp(v, OP_IdxRowid, iIdx, 0); + sqlite3VdbeAddOp(v, OP_Close, iIdx, 0); + sqlite3VdbeAddOp(v, OP_MoveGe, base, 0); + } + eList.nExpr = 1; + memset(&eListItem, 0, sizeof(eListItem)); + eList.a = &eListItem; + eList.a[0].pExpr = pExpr; + selectInnerLoop(pParse, p, &eList, 0, 0, 0, -1, eDest, iParm, brk, brk, 0); + sqlite3VdbeResolveLabel(v, brk); + sqlite3VdbeAddOp(v, OP_Close, base, 0); + + return 1; +} + +/* +** Analyze and ORDER BY or GROUP BY clause in a SELECT statement. Return +** the number of errors seen. +** +** An ORDER BY or GROUP BY is a list of expressions. If any expression +** is an integer constant, then that expression is replaced by the +** corresponding entry in the result set. +*/ +static int processOrderGroupBy( + NameContext *pNC, /* Name context of the SELECT statement. */ + ExprList *pOrderBy, /* The ORDER BY or GROUP BY clause to be processed */ + const char *zType /* Either "ORDER" or "GROUP", as appropriate */ +){ + int i; + ExprList *pEList = pNC->pEList; /* The result set of the SELECT */ + Parse *pParse = pNC->pParse; /* The result set of the SELECT */ + assert( pEList ); + + if( pOrderBy==0 ) return 0; + if( pOrderBy->nExpr>SQLITE_MAX_COLUMN ){ + sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType); + return 1; + } + for(i=0; inExpr; i++){ + int iCol; + Expr *pE = pOrderBy->a[i].pExpr; + if( sqlite3ExprIsInteger(pE, &iCol) ){ + if( iCol>0 && iCol<=pEList->nExpr ){ + CollSeq *pColl = pE->pColl; + int flags = pE->flags & EP_ExpCollate; + sqlite3ExprDelete(pE); + pE = pOrderBy->a[i].pExpr = sqlite3ExprDup(pEList->a[iCol-1].pExpr); + if( pColl && flags ){ + pE->pColl = pColl; + pE->flags |= flags; + } + }else{ + sqlite3ErrorMsg(pParse, + "%s BY column number %d out of range - should be " + "between 1 and %d", zType, iCol, pEList->nExpr); + return 1; + } + } + if( sqlite3ExprResolveNames(pNC, pE) ){ + return 1; + } + } + return 0; +} + +/* +** This routine resolves any names used in the result set of the +** supplied SELECT statement. If the SELECT statement being resolved +** is a sub-select, then pOuterNC is a pointer to the NameContext +** of the parent SELECT. +*/ +int sqlite3SelectResolve( + Parse *pParse, /* The parser context */ + Select *p, /* The SELECT statement being coded. */ + NameContext *pOuterNC /* The outer name context. May be NULL. */ +){ + ExprList *pEList; /* Result set. */ + int i; /* For-loop variable used in multiple places */ + NameContext sNC; /* Local name-context */ + ExprList *pGroupBy; /* The group by clause */ + + /* If this routine has run before, return immediately. */ + if( p->isResolved ){ + assert( !pOuterNC ); + return SQLITE_OK; + } + p->isResolved = 1; + + /* If there have already been errors, do nothing. */ + if( pParse->nErr>0 ){ + return SQLITE_ERROR; + } + + /* Prepare the select statement. This call will allocate all cursors + ** required to handle the tables and subqueries in the FROM clause. + */ + if( prepSelectStmt(pParse, p) ){ + return SQLITE_ERROR; + } + + /* Resolve the expressions in the LIMIT and OFFSET clauses. These + ** are not allowed to refer to any names, so pass an empty NameContext. + */ + memset(&sNC, 0, sizeof(sNC)); + sNC.pParse = pParse; + if( sqlite3ExprResolveNames(&sNC, p->pLimit) || + sqlite3ExprResolveNames(&sNC, p->pOffset) ){ + return SQLITE_ERROR; + } + + /* Set up the local name-context to pass to ExprResolveNames() to + ** resolve the expression-list. + */ + sNC.allowAgg = 1; + sNC.pSrcList = p->pSrc; + sNC.pNext = pOuterNC; + + /* Resolve names in the result set. */ + pEList = p->pEList; + if( !pEList ) return SQLITE_ERROR; + for(i=0; inExpr; i++){ + Expr *pX = pEList->a[i].pExpr; + if( sqlite3ExprResolveNames(&sNC, pX) ){ + return SQLITE_ERROR; + } + } + + /* If there are no aggregate functions in the result-set, and no GROUP BY + ** expression, do not allow aggregates in any of the other expressions. + */ + assert( !p->isAgg ); + pGroupBy = p->pGroupBy; + if( pGroupBy || sNC.hasAgg ){ + p->isAgg = 1; + }else{ + sNC.allowAgg = 0; + } + + /* If a HAVING clause is present, then there must be a GROUP BY clause. + */ + if( p->pHaving && !pGroupBy ){ + sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING"); + return SQLITE_ERROR; + } + + /* Add the expression list to the name-context before parsing the + ** other expressions in the SELECT statement. This is so that + ** expressions in the WHERE clause (etc.) can refer to expressions by + ** aliases in the result set. + ** + ** Minor point: If this is the case, then the expression will be + ** re-evaluated for each reference to it. + */ + sNC.pEList = p->pEList; + if( sqlite3ExprResolveNames(&sNC, p->pWhere) || + sqlite3ExprResolveNames(&sNC, p->pHaving) ){ + return SQLITE_ERROR; + } + if( p->pPrior==0 ){ + if( processOrderGroupBy(&sNC, p->pOrderBy, "ORDER") || + processOrderGroupBy(&sNC, pGroupBy, "GROUP") ){ + return SQLITE_ERROR; + } + } + + if( sqlite3MallocFailed() ){ + return SQLITE_NOMEM; + } + + /* Make sure the GROUP BY clause does not contain aggregate functions. + */ + if( pGroupBy ){ + struct ExprList_item *pItem; + + for(i=0, pItem=pGroupBy->a; inExpr; i++, pItem++){ + if( ExprHasProperty(pItem->pExpr, EP_Agg) ){ + sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in " + "the GROUP BY clause"); + return SQLITE_ERROR; + } + } + } + + /* If this is one SELECT of a compound, be sure to resolve names + ** in the other SELECTs. + */ + if( p->pPrior ){ + return sqlite3SelectResolve(pParse, p->pPrior, pOuterNC); + }else{ + return SQLITE_OK; + } +} + +/* +** Reset the aggregate accumulator. +** +** The aggregate accumulator is a set of memory cells that hold +** intermediate results while calculating an aggregate. This +** routine simply stores NULLs in all of those memory cells. +*/ +static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){ + Vdbe *v = pParse->pVdbe; + int i; + struct AggInfo_func *pFunc; + if( pAggInfo->nFunc+pAggInfo->nColumn==0 ){ + return; + } + for(i=0; inColumn; i++){ + sqlite3VdbeAddOp(v, OP_MemNull, pAggInfo->aCol[i].iMem, 0); + } + for(pFunc=pAggInfo->aFunc, i=0; inFunc; i++, pFunc++){ + sqlite3VdbeAddOp(v, OP_MemNull, pFunc->iMem, 0); + if( pFunc->iDistinct>=0 ){ + Expr *pE = pFunc->pExpr; + if( pE->pList==0 || pE->pList->nExpr!=1 ){ + sqlite3ErrorMsg(pParse, "DISTINCT in aggregate must be followed " + "by an expression"); + pFunc->iDistinct = -1; + }else{ + KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->pList); + sqlite3VdbeOp3(v, OP_OpenEphemeral, pFunc->iDistinct, 0, + (char*)pKeyInfo, P3_KEYINFO_HANDOFF); + } + } + } +} + +/* +** Invoke the OP_AggFinalize opcode for every aggregate function +** in the AggInfo structure. +*/ +static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){ + Vdbe *v = pParse->pVdbe; + int i; + struct AggInfo_func *pF; + for(i=0, pF=pAggInfo->aFunc; inFunc; i++, pF++){ + ExprList *pList = pF->pExpr->pList; + sqlite3VdbeOp3(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0, + (void*)pF->pFunc, P3_FUNCDEF); + } +} + +/* +** Update the accumulator memory cells for an aggregate based on +** the current cursor position. +*/ +static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ + Vdbe *v = pParse->pVdbe; + int i; + struct AggInfo_func *pF; + struct AggInfo_col *pC; + + pAggInfo->directMode = 1; + for(i=0, pF=pAggInfo->aFunc; inFunc; i++, pF++){ + int nArg; + int addrNext = 0; + ExprList *pList = pF->pExpr->pList; + if( pList ){ + nArg = pList->nExpr; + sqlite3ExprCodeExprList(pParse, pList); + }else{ + nArg = 0; + } + if( pF->iDistinct>=0 ){ + addrNext = sqlite3VdbeMakeLabel(v); + assert( nArg==1 ); + codeDistinct(v, pF->iDistinct, addrNext, 1); + } + if( pF->pFunc->needCollSeq ){ + CollSeq *pColl = 0; + struct ExprList_item *pItem; + int j; + assert( pList!=0 ); /* pList!=0 if pF->pFunc->needCollSeq is true */ + for(j=0, pItem=pList->a; !pColl && jpExpr); + } + if( !pColl ){ + pColl = pParse->db->pDfltColl; + } + sqlite3VdbeOp3(v, OP_CollSeq, 0, 0, (char *)pColl, P3_COLLSEQ); + } + sqlite3VdbeOp3(v, OP_AggStep, pF->iMem, nArg, (void*)pF->pFunc, P3_FUNCDEF); + if( addrNext ){ + sqlite3VdbeResolveLabel(v, addrNext); + } + } + for(i=0, pC=pAggInfo->aCol; inAccumulator; i++, pC++){ + sqlite3ExprCode(pParse, pC->pExpr); + sqlite3VdbeAddOp(v, OP_MemStore, pC->iMem, 1); + } + pAggInfo->directMode = 0; +} + + +/* +** Generate code for the given SELECT statement. +** +** The results are distributed in various ways depending on the +** value of eDest and iParm. +** +** eDest Value Result +** ------------ ------------------------------------------- +** SRT_Callback Invoke the callback for each row of the result. +** +** SRT_Mem Store first result in memory cell iParm +** +** SRT_Set Store results as keys of table iParm. +** +** SRT_Union Store results as a key in a temporary table iParm +** +** SRT_Except Remove results from the temporary table iParm. +** +** SRT_Table Store results in temporary table iParm +** +** The table above is incomplete. Additional eDist value have be added +** since this comment was written. See the selectInnerLoop() function for +** a complete listing of the allowed values of eDest and their meanings. +** +** This routine returns the number of errors. If any errors are +** encountered, then an appropriate error message is left in +** pParse->zErrMsg. +** +** This routine does NOT free the Select structure passed in. The +** calling function needs to do that. +** +** The pParent, parentTab, and *pParentAgg fields are filled in if this +** SELECT is a subquery. This routine may try to combine this SELECT +** with its parent to form a single flat query. In so doing, it might +** change the parent query from a non-aggregate to an aggregate query. +** For that reason, the pParentAgg flag is passed as a pointer, so it +** can be changed. +** +** Example 1: The meaning of the pParent parameter. +** +** SELECT * FROM t1 JOIN (SELECT x, count(*) FROM t2) JOIN t3; +** \ \_______ subquery _______/ / +** \ / +** \____________________ outer query ___________________/ +** +** This routine is called for the outer query first. For that call, +** pParent will be NULL. During the processing of the outer query, this +** routine is called recursively to handle the subquery. For the recursive +** call, pParent will point to the outer query. Because the subquery is +** the second element in a three-way join, the parentTab parameter will +** be 1 (the 2nd value of a 0-indexed array.) +*/ +int sqlite3Select( + Parse *pParse, /* The parser context */ + Select *p, /* The SELECT statement being coded. */ + int eDest, /* How to dispose of the results */ + int iParm, /* A parameter used by the eDest disposal method */ + Select *pParent, /* Another SELECT for which this is a sub-query */ + int parentTab, /* Index in pParent->pSrc of this query */ + int *pParentAgg, /* True if pParent uses aggregate functions */ + char *aff /* If eDest is SRT_Union, the affinity string */ +){ + int i, j; /* Loop counters */ + WhereInfo *pWInfo; /* Return from sqlite3WhereBegin() */ + Vdbe *v; /* The virtual machine under construction */ + int isAgg; /* True for select lists like "count(*)" */ + ExprList *pEList; /* List of columns to extract. */ + SrcList *pTabList; /* List of tables to select from */ + Expr *pWhere; /* The WHERE clause. May be NULL */ + ExprList *pOrderBy; /* The ORDER BY clause. May be NULL */ + ExprList *pGroupBy; /* The GROUP BY clause. May be NULL */ + Expr *pHaving; /* The HAVING clause. May be NULL */ + int isDistinct; /* True if the DISTINCT keyword is present */ + int distinct; /* Table to use for the distinct set */ + int rc = 1; /* Value to return from this function */ + int addrSortIndex; /* Address of an OP_OpenEphemeral instruction */ + AggInfo sAggInfo; /* Information used by aggregate queries */ + int iEnd; /* Address of the end of the query */ + + if( p==0 || sqlite3MallocFailed() || pParse->nErr ){ + return 1; + } + if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; + memset(&sAggInfo, 0, sizeof(sAggInfo)); + +#ifndef SQLITE_OMIT_COMPOUND_SELECT + /* If there is are a sequence of queries, do the earlier ones first. + */ + if( p->pPrior ){ + if( p->pRightmost==0 ){ + Select *pLoop; + int cnt = 0; + for(pLoop=p; pLoop; pLoop=pLoop->pPrior, cnt++){ + pLoop->pRightmost = p; + } + if( SQLITE_MAX_COMPOUND_SELECT>0 && cnt>SQLITE_MAX_COMPOUND_SELECT ){ + sqlite3ErrorMsg(pParse, "too many terms in compound SELECT"); + return 1; + } + } + return multiSelect(pParse, p, eDest, iParm, aff); + } +#endif + + pOrderBy = p->pOrderBy; + if( IgnorableOrderby(eDest) ){ + p->pOrderBy = 0; + } + if( sqlite3SelectResolve(pParse, p, 0) ){ + goto select_end; + } + p->pOrderBy = pOrderBy; + + /* Make local copies of the parameters for this query. + */ + pTabList = p->pSrc; + pWhere = p->pWhere; + pGroupBy = p->pGroupBy; + pHaving = p->pHaving; + isAgg = p->isAgg; + isDistinct = p->isDistinct; + pEList = p->pEList; + if( pEList==0 ) goto select_end; + + /* + ** Do not even attempt to generate any code if we have already seen + ** errors before this routine starts. + */ + if( pParse->nErr>0 ) goto select_end; + + /* If writing to memory or generating a set + ** only a single column may be output. + */ +#ifndef SQLITE_OMIT_SUBQUERY + if( checkForMultiColumnSelectError(pParse, eDest, pEList->nExpr) ){ + goto select_end; + } +#endif + + /* ORDER BY is ignored for some destinations. + */ + if( IgnorableOrderby(eDest) ){ + pOrderBy = 0; + } + + /* Begin generating code. + */ + v = sqlite3GetVdbe(pParse); + if( v==0 ) goto select_end; + + /* Generate code for all sub-queries in the FROM clause + */ +#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) + for(i=0; inSrc; i++){ + const char *zSavedAuthContext = 0; + int needRestoreContext; + struct SrcList_item *pItem = &pTabList->a[i]; + + if( pItem->pSelect==0 || pItem->isPopulated ) continue; + if( pItem->zName!=0 ){ + zSavedAuthContext = pParse->zAuthContext; + pParse->zAuthContext = pItem->zName; + needRestoreContext = 1; + }else{ + needRestoreContext = 0; + } +#if SQLITE_MAX_EXPR_DEPTH>0 + /* Increment Parse.nHeight by the height of the largest expression + ** tree refered to by this, the parent select. The child select + ** may contain expression trees of at most + ** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit + ** more conservative than necessary, but much easier than enforcing + ** an exact limit. + */ + pParse->nHeight += sqlite3SelectExprHeight(p); +#endif + sqlite3Select(pParse, pItem->pSelect, SRT_EphemTab, + pItem->iCursor, p, i, &isAgg, 0); +#if SQLITE_MAX_EXPR_DEPTH>0 + pParse->nHeight -= sqlite3SelectExprHeight(p); +#endif + if( needRestoreContext ){ + pParse->zAuthContext = zSavedAuthContext; + } + pTabList = p->pSrc; + pWhere = p->pWhere; + if( !IgnorableOrderby(eDest) ){ + pOrderBy = p->pOrderBy; + } + pGroupBy = p->pGroupBy; + pHaving = p->pHaving; + isDistinct = p->isDistinct; + } +#endif + + /* Check for the special case of a min() or max() function by itself + ** in the result set. + */ + if( simpleMinMaxQuery(pParse, p, eDest, iParm) ){ + rc = 0; + goto select_end; + } + + /* Check to see if this is a subquery that can be "flattened" into its parent. + ** If flattening is a possiblity, do so and return immediately. + */ +#ifndef SQLITE_OMIT_VIEW + if( pParent && pParentAgg && + flattenSubquery(pParent, parentTab, *pParentAgg, isAgg) ){ + if( isAgg ) *pParentAgg = 1; + goto select_end; + } +#endif + + /* If there is an ORDER BY clause, then this sorting + ** index might end up being unused if the data can be + ** extracted in pre-sorted order. If that is the case, then the + ** OP_OpenEphemeral instruction will be changed to an OP_Noop once + ** we figure out that the sorting index is not needed. The addrSortIndex + ** variable is used to facilitate that change. + */ + if( pOrderBy ){ + KeyInfo *pKeyInfo; + if( pParse->nErr ){ + goto select_end; + } + pKeyInfo = keyInfoFromExprList(pParse, pOrderBy); + pOrderBy->iECursor = pParse->nTab++; + p->addrOpenEphm[2] = addrSortIndex = + sqlite3VdbeOp3(v, OP_OpenEphemeral, pOrderBy->iECursor, pOrderBy->nExpr+2, (char*)pKeyInfo, P3_KEYINFO_HANDOFF); + }else{ + addrSortIndex = -1; + } + + /* If the output is destined for a temporary table, open that table. + */ + if( eDest==SRT_EphemTab ){ + sqlite3VdbeAddOp(v, OP_OpenEphemeral, iParm, pEList->nExpr); + } + + /* Set the limiter. + */ + iEnd = sqlite3VdbeMakeLabel(v); + computeLimitRegisters(pParse, p, iEnd); + + /* Open a virtual index to use for the distinct set. + */ + if( isDistinct ){ + KeyInfo *pKeyInfo; + distinct = pParse->nTab++; + pKeyInfo = keyInfoFromExprList(pParse, p->pEList); + sqlite3VdbeOp3(v, OP_OpenEphemeral, distinct, 0, + (char*)pKeyInfo, P3_KEYINFO_HANDOFF); + }else{ + distinct = -1; + } + + /* Aggregate and non-aggregate queries are handled differently */ + if( !isAgg && pGroupBy==0 ){ + /* This case is for non-aggregate queries + ** Begin the database scan + */ + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy); + if( pWInfo==0 ) goto select_end; + + /* If sorting index that was created by a prior OP_OpenEphemeral + ** instruction ended up not being needed, then change the OP_OpenEphemeral + ** into an OP_Noop. + */ + if( addrSortIndex>=0 && pOrderBy==0 ){ + sqlite3VdbeChangeToNoop(v, addrSortIndex, 1); + p->addrOpenEphm[2] = -1; + } + + /* Use the standard inner loop + */ + if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, eDest, + iParm, pWInfo->iContinue, pWInfo->iBreak, aff) ){ + goto select_end; + } + + /* End the database scan loop. + */ + sqlite3WhereEnd(pWInfo); + }else{ + /* This is the processing for aggregate queries */ + NameContext sNC; /* Name context for processing aggregate information */ + int iAMem; /* First Mem address for storing current GROUP BY */ + int iBMem; /* First Mem address for previous GROUP BY */ + int iUseFlag; /* Mem address holding flag indicating that at least + ** one row of the input to the aggregator has been + ** processed */ + int iAbortFlag; /* Mem address which causes query abort if positive */ + int groupBySort; /* Rows come from source in GROUP BY order */ + + + /* The following variables hold addresses or labels for parts of the + ** virtual machine program we are putting together */ + int addrOutputRow; /* Start of subroutine that outputs a result row */ + int addrSetAbort; /* Set the abort flag and return */ + int addrInitializeLoop; /* Start of code that initializes the input loop */ + int addrTopOfLoop; /* Top of the input loop */ + int addrGroupByChange; /* Code that runs when any GROUP BY term changes */ + int addrProcessRow; /* Code to process a single input row */ + int addrEnd; /* End of all processing */ + int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */ + int addrReset; /* Subroutine for resetting the accumulator */ + + addrEnd = sqlite3VdbeMakeLabel(v); + + /* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in + ** sAggInfo for all TK_AGG_FUNCTION nodes in expressions of the + ** SELECT statement. + */ + memset(&sNC, 0, sizeof(sNC)); + sNC.pParse = pParse; + sNC.pSrcList = pTabList; + sNC.pAggInfo = &sAggInfo; + sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr+1 : 0; + sAggInfo.pGroupBy = pGroupBy; + if( sqlite3ExprAnalyzeAggList(&sNC, pEList) ){ + goto select_end; + } + if( sqlite3ExprAnalyzeAggList(&sNC, pOrderBy) ){ + goto select_end; + } + if( pHaving && sqlite3ExprAnalyzeAggregates(&sNC, pHaving) ){ + goto select_end; + } + sAggInfo.nAccumulator = sAggInfo.nColumn; + for(i=0; ipList) ){ + goto select_end; + } + } + if( sqlite3MallocFailed() ) goto select_end; + + /* Processing for aggregates with GROUP BY is very different and + ** much more complex tha aggregates without a GROUP BY. + */ + if( pGroupBy ){ + KeyInfo *pKeyInfo; /* Keying information for the group by clause */ + + /* Create labels that we will be needing + */ + + addrInitializeLoop = sqlite3VdbeMakeLabel(v); + addrGroupByChange = sqlite3VdbeMakeLabel(v); + addrProcessRow = sqlite3VdbeMakeLabel(v); + + /* If there is a GROUP BY clause we might need a sorting index to + ** implement it. Allocate that sorting index now. If it turns out + ** that we do not need it after all, the OpenEphemeral instruction + ** will be converted into a Noop. + */ + sAggInfo.sortingIdx = pParse->nTab++; + pKeyInfo = keyInfoFromExprList(pParse, pGroupBy); + addrSortingIdx = + sqlite3VdbeOp3(v, OP_OpenEphemeral, sAggInfo.sortingIdx, + sAggInfo.nSortingColumn, + (char*)pKeyInfo, P3_KEYINFO_HANDOFF); + + /* Initialize memory locations used by GROUP BY aggregate processing + */ + iUseFlag = pParse->nMem++; + iAbortFlag = pParse->nMem++; + iAMem = pParse->nMem; + pParse->nMem += pGroupBy->nExpr; + iBMem = pParse->nMem; + pParse->nMem += pGroupBy->nExpr; + sqlite3VdbeAddOp(v, OP_MemInt, 0, iAbortFlag); + VdbeComment((v, "# clear abort flag")); + sqlite3VdbeAddOp(v, OP_MemInt, 0, iUseFlag); + VdbeComment((v, "# indicate accumulator empty")); + sqlite3VdbeAddOp(v, OP_Goto, 0, addrInitializeLoop); + + /* Generate a subroutine that outputs a single row of the result + ** set. This subroutine first looks at the iUseFlag. If iUseFlag + ** is less than or equal to zero, the subroutine is a no-op. If + ** the processing calls for the query to abort, this subroutine + ** increments the iAbortFlag memory location before returning in + ** order to signal the caller to abort. + */ + addrSetAbort = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeAddOp(v, OP_MemInt, 1, iAbortFlag); + VdbeComment((v, "# set abort flag")); + sqlite3VdbeAddOp(v, OP_Return, 0, 0); + addrOutputRow = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeAddOp(v, OP_IfMemPos, iUseFlag, addrOutputRow+2); + VdbeComment((v, "# Groupby result generator entry point")); + sqlite3VdbeAddOp(v, OP_Return, 0, 0); + finalizeAggFunctions(pParse, &sAggInfo); + if( pHaving ){ + sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, 1); + } + rc = selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy, + distinct, eDest, iParm, + addrOutputRow+1, addrSetAbort, aff); + if( rc ){ + goto select_end; + } + sqlite3VdbeAddOp(v, OP_Return, 0, 0); + VdbeComment((v, "# end groupby result generator")); + + /* Generate a subroutine that will reset the group-by accumulator + */ + addrReset = sqlite3VdbeCurrentAddr(v); + resetAccumulator(pParse, &sAggInfo); + sqlite3VdbeAddOp(v, OP_Return, 0, 0); + + /* Begin a loop that will extract all source rows in GROUP BY order. + ** This might involve two separate loops with an OP_Sort in between, or + ** it might be a single loop that uses an index to extract information + ** in the right order to begin with. + */ + sqlite3VdbeResolveLabel(v, addrInitializeLoop); + sqlite3VdbeAddOp(v, OP_Gosub, 0, addrReset); + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy); + if( pWInfo==0 ) goto select_end; + if( pGroupBy==0 ){ + /* The optimizer is able to deliver rows in group by order so + ** we do not have to sort. The OP_OpenEphemeral table will be + ** cancelled later because we still need to use the pKeyInfo + */ + pGroupBy = p->pGroupBy; + groupBySort = 0; + }else{ + /* Rows are coming out in undetermined order. We have to push + ** each row into a sorting index, terminate the first loop, + ** then loop over the sorting index in order to get the output + ** in sorted order + */ + groupBySort = 1; + sqlite3ExprCodeExprList(pParse, pGroupBy); + sqlite3VdbeAddOp(v, OP_Sequence, sAggInfo.sortingIdx, 0); + j = pGroupBy->nExpr+1; + for(i=0; iiSorterColumnpTab, pCol->iColumn, pCol->iTable); + j++; + } + sqlite3VdbeAddOp(v, OP_MakeRecord, j, 0); + sqlite3VdbeAddOp(v, OP_IdxInsert, sAggInfo.sortingIdx, 0); + sqlite3WhereEnd(pWInfo); + sqlite3VdbeAddOp(v, OP_Sort, sAggInfo.sortingIdx, addrEnd); + VdbeComment((v, "# GROUP BY sort")); + sAggInfo.useSortingIdx = 1; + } + + /* Evaluate the current GROUP BY terms and store in b0, b1, b2... + ** (b0 is memory location iBMem+0, b1 is iBMem+1, and so forth) + ** Then compare the current GROUP BY terms against the GROUP BY terms + ** from the previous row currently stored in a0, a1, a2... + */ + addrTopOfLoop = sqlite3VdbeCurrentAddr(v); + for(j=0; jnExpr; j++){ + if( groupBySort ){ + sqlite3VdbeAddOp(v, OP_Column, sAggInfo.sortingIdx, j); + }else{ + sAggInfo.directMode = 1; + sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr); + } + sqlite3VdbeAddOp(v, OP_MemStore, iBMem+j, jnExpr-1); + } + for(j=pGroupBy->nExpr-1; j>=0; j--){ + if( jnExpr-1 ){ + sqlite3VdbeAddOp(v, OP_MemLoad, iBMem+j, 0); + } + sqlite3VdbeAddOp(v, OP_MemLoad, iAMem+j, 0); + if( j==0 ){ + sqlite3VdbeAddOp(v, OP_Eq, 0x200, addrProcessRow); + }else{ + sqlite3VdbeAddOp(v, OP_Ne, 0x200, addrGroupByChange); + } + sqlite3VdbeChangeP3(v, -1, (void*)pKeyInfo->aColl[j], P3_COLLSEQ); + } + + /* Generate code that runs whenever the GROUP BY changes. + ** Change in the GROUP BY are detected by the previous code + ** block. If there were no changes, this block is skipped. + ** + ** This code copies current group by terms in b0,b1,b2,... + ** over to a0,a1,a2. It then calls the output subroutine + ** and resets the aggregate accumulator registers in preparation + ** for the next GROUP BY batch. + */ + sqlite3VdbeResolveLabel(v, addrGroupByChange); + for(j=0; jnExpr; j++){ + sqlite3VdbeAddOp(v, OP_MemMove, iAMem+j, iBMem+j); + } + sqlite3VdbeAddOp(v, OP_Gosub, 0, addrOutputRow); + VdbeComment((v, "# output one row")); + sqlite3VdbeAddOp(v, OP_IfMemPos, iAbortFlag, addrEnd); + VdbeComment((v, "# check abort flag")); + sqlite3VdbeAddOp(v, OP_Gosub, 0, addrReset); + VdbeComment((v, "# reset accumulator")); + + /* Update the aggregate accumulators based on the content of + ** the current row + */ + sqlite3VdbeResolveLabel(v, addrProcessRow); + updateAccumulator(pParse, &sAggInfo); + sqlite3VdbeAddOp(v, OP_MemInt, 1, iUseFlag); + VdbeComment((v, "# indicate data in accumulator")); + + /* End of the loop + */ + if( groupBySort ){ + sqlite3VdbeAddOp(v, OP_Next, sAggInfo.sortingIdx, addrTopOfLoop); + }else{ + sqlite3WhereEnd(pWInfo); + sqlite3VdbeChangeToNoop(v, addrSortingIdx, 1); + } + + /* Output the final row of result + */ + sqlite3VdbeAddOp(v, OP_Gosub, 0, addrOutputRow); + VdbeComment((v, "# output final row")); + + } /* endif pGroupBy */ + else { + /* This case runs if the aggregate has no GROUP BY clause. The + ** processing is much simpler since there is only a single row + ** of output. + */ + resetAccumulator(pParse, &sAggInfo); + pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0); + if( pWInfo==0 ) goto select_end; + updateAccumulator(pParse, &sAggInfo); + sqlite3WhereEnd(pWInfo); + finalizeAggFunctions(pParse, &sAggInfo); + pOrderBy = 0; + if( pHaving ){ + sqlite3ExprIfFalse(pParse, pHaving, addrEnd, 1); + } + selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, -1, + eDest, iParm, addrEnd, addrEnd, aff); + } + sqlite3VdbeResolveLabel(v, addrEnd); + + } /* endif aggregate query */ + + /* If there is an ORDER BY clause, then we need to sort the results + ** and send them to the callback one by one. + */ + if( pOrderBy ){ + generateSortTail(pParse, p, v, pEList->nExpr, eDest, iParm); + } + +#ifndef SQLITE_OMIT_SUBQUERY + /* If this was a subquery, we have now converted the subquery into a + ** temporary table. So set the SrcList_item.isPopulated flag to prevent + ** this subquery from being evaluated again and to force the use of + ** the temporary table. + */ + if( pParent ){ + assert( pParent->pSrc->nSrc>parentTab ); + assert( pParent->pSrc->a[parentTab].pSelect==p ); + pParent->pSrc->a[parentTab].isPopulated = 1; + } +#endif + + /* Jump here to skip this query + */ + sqlite3VdbeResolveLabel(v, iEnd); + + /* The SELECT was successfully coded. Set the return code to 0 + ** to indicate no errors. + */ + rc = 0; + + /* Control jumps to here if an error is encountered above, or upon + ** successful coding of the SELECT. + */ +select_end: + + /* Identify column names if we will be using them in a callback. This + ** step is skipped if the output is going to some other destination. + */ + if( rc==SQLITE_OK && eDest==SRT_Callback ){ + generateColumnNames(pParse, pTabList, pEList); + } + + sqliteFree(sAggInfo.aCol); + sqliteFree(sAggInfo.aFunc); + return rc; +} + +#if defined(SQLITE_DEBUG) +/* +******************************************************************************* +** The following code is used for testing and debugging only. The code +** that follows does not appear in normal builds. +** +** These routines are used to print out the content of all or part of a +** parse structures such as Select or Expr. Such printouts are useful +** for helping to understand what is happening inside the code generator +** during the execution of complex SELECT statements. +** +** These routine are not called anywhere from within the normal +** code base. Then are intended to be called from within the debugger +** or from temporary "printf" statements inserted for debugging. +*/ +void sqlite3PrintExpr(Expr *p){ + if( p->token.z && p->token.n>0 ){ + sqlite3DebugPrintf("(%.*s", p->token.n, p->token.z); + }else{ + sqlite3DebugPrintf("(%d", p->op); + } + if( p->pLeft ){ + sqlite3DebugPrintf(" "); + sqlite3PrintExpr(p->pLeft); + } + if( p->pRight ){ + sqlite3DebugPrintf(" "); + sqlite3PrintExpr(p->pRight); + } + sqlite3DebugPrintf(")"); +} +void sqlite3PrintExprList(ExprList *pList){ + int i; + for(i=0; inExpr; i++){ + sqlite3PrintExpr(pList->a[i].pExpr); + if( inExpr-1 ){ + sqlite3DebugPrintf(", "); + } + } +} +void sqlite3PrintSelect(Select *p, int indent){ + sqlite3DebugPrintf("%*sSELECT(%p) ", indent, "", p); + sqlite3PrintExprList(p->pEList); + sqlite3DebugPrintf("\n"); + if( p->pSrc ){ + char *zPrefix; + int i; + zPrefix = "FROM"; + for(i=0; ipSrc->nSrc; i++){ + struct SrcList_item *pItem = &p->pSrc->a[i]; + sqlite3DebugPrintf("%*s ", indent+6, zPrefix); + zPrefix = ""; + if( pItem->pSelect ){ + sqlite3DebugPrintf("(\n"); + sqlite3PrintSelect(pItem->pSelect, indent+10); + sqlite3DebugPrintf("%*s)", indent+8, ""); + }else if( pItem->zName ){ + sqlite3DebugPrintf("%s", pItem->zName); + } + if( pItem->pTab ){ + sqlite3DebugPrintf("(table: %s)", pItem->pTab->zName); + } + if( pItem->zAlias ){ + sqlite3DebugPrintf(" AS %s", pItem->zAlias); + } + if( ipSrc->nSrc-1 ){ + sqlite3DebugPrintf(","); + } + sqlite3DebugPrintf("\n"); + } + } + if( p->pWhere ){ + sqlite3DebugPrintf("%*s WHERE ", indent, ""); + sqlite3PrintExpr(p->pWhere); + sqlite3DebugPrintf("\n"); + } + if( p->pGroupBy ){ + sqlite3DebugPrintf("%*s GROUP BY ", indent, ""); + sqlite3PrintExprList(p->pGroupBy); + sqlite3DebugPrintf("\n"); + } + if( p->pHaving ){ + sqlite3DebugPrintf("%*s HAVING ", indent, ""); + sqlite3PrintExpr(p->pHaving); + sqlite3DebugPrintf("\n"); + } + if( p->pOrderBy ){ + sqlite3DebugPrintf("%*s ORDER BY ", indent, ""); + sqlite3PrintExprList(p->pOrderBy); + sqlite3DebugPrintf("\n"); + } +} +/* End of the structure debug printing code +*****************************************************************************/ +#endif /* defined(SQLITE_TEST) || defined(SQLITE_DEBUG) */ diff --git a/extensions/sqlite/sqlite-source/sqlite3.h b/extensions/sqlite/sqlite-source/sqlite3.h new file mode 100644 index 00000000..d569b24c --- /dev/null +++ b/extensions/sqlite/sqlite-source/sqlite3.h @@ -0,0 +1,2702 @@ +/* +** 2001 September 15 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This header file defines the interface that the SQLite library +** presents to client programs. If a C-function, structure, datatype, +** or constant definition does not appear in this file, then it is +** not a published API of SQLite, is subject to change without +** notice, and should not be referenced by programs that use SQLite. +** +** Some of the definitions that are in this file are marked as +** "experimental". Experimental interfaces are normally new +** features recently added to SQLite. We do not anticipate changes +** to experimental interfaces but reserve to make minor changes if +** experience from use "in the wild" suggest such changes are prudent. +** +** The official C-language API documentation for SQLite is derived +** from comments in this file. This file is the authoritative source +** on how SQLite interfaces are suppose to operate. +** +** The name of this file under configuration management is "sqlite.h.in". +** The makefile makes some minor changes to this file (such as inserting +** the version number) and changes its name to "sqlite3.h" as +** part of the build process. +** +** @(#) $Id$ +*/ +#ifndef _SQLITE3_H_ +#define _SQLITE3_H_ +#include /* Needed for the definition of va_list */ + +/* +** Make sure we can call this stuff from C++. +*/ +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Make sure these symbols where not defined by some previous header +** file. +*/ +#ifdef SQLITE_VERSION +# undef SQLITE_VERSION +#endif +#ifdef SQLITE_VERSION_NUMBER +# undef SQLITE_VERSION_NUMBER +#endif + +/* +** CAPI3REF: Compile-Time Library Version Numbers +** +** The version of the SQLite library is contained in the sqlite3.h +** header file in a #define named SQLITE_VERSION. The SQLITE_VERSION +** macro resolves to a string constant. +** +** The format of the version string is "X.Y.Z", where +** X is the major version number, Y is the minor version number and Z +** is the release number. The X.Y.Z might be followed by "alpha" or "beta". +** For example "3.1.1beta". +** +** The X value is always 3 in SQLite. The X value only changes when +** backwards compatibility is broken and we intend to never break +** backwards compatibility. The Y value only changes when +** there are major feature enhancements that are forwards compatible +** but not backwards compatible. The Z value is incremented with +** each release but resets back to 0 when Y is incremented. +** +** The SQLITE_VERSION_NUMBER is an integer with the value +** (X*1000000 + Y*1000 + Z). For example, for version "3.1.1beta", +** SQLITE_VERSION_NUMBER is set to 3001001. To detect if they are using +** version 3.1.1 or greater at compile time, programs may use the test +** (SQLITE_VERSION_NUMBER>=3001001). +** +** See also: [sqlite3_libversion()] and [sqlite3_libversion_number()]. +*/ +#define SQLITE_VERSION "3.4.1" +#define SQLITE_VERSION_NUMBER 3004001 + +/* +** CAPI3REF: Run-Time Library Version Numbers +** +** These routines return values equivalent to the header constants +** [SQLITE_VERSION] and [SQLITE_VERSION_NUMBER]. The values returned +** by this routines should only be different from the header values +** if you compile your program using an sqlite3.h header from a +** different version of SQLite that the version of the library you +** link against. +** +** The sqlite3_version[] string constant contains the text of the +** [SQLITE_VERSION] string. The sqlite3_libversion() function returns +** a poiner to the sqlite3_version[] string constant. The function +** is provided for DLL users who can only access functions and not +** constants within the DLL. +*/ +extern const char sqlite3_version[]; +const char *sqlite3_libversion(void); +int sqlite3_libversion_number(void); + +/* +** CAPI3REF: Database Connection Handle +** +** Each open SQLite database is represented by pointer to an instance of the +** opaque structure named "sqlite3". It is useful to think of an sqlite3 +** pointer as an object. The [sqlite3_open] interface is its constructor +** and [sqlite3_close] is its destructor. There are many other interfaces +** (such as [sqlite3_prepare_v2], [sqlite3_create_function], and +** [sqlite3_busy_timeout] to name but three) that are methods on this +** object. +*/ +typedef struct sqlite3 sqlite3; + + +/* +** CAPI3REF: 64-Bit Integer Types +** +** Some compilers do not support the "long long" datatype. So we have +** to do compiler-specific typedefs for 64-bit signed and unsigned integers. +** +** Many SQLite interface functions require a 64-bit integer arguments. +** Those interfaces are declared using this typedef. +*/ +#ifdef SQLITE_INT64_TYPE + typedef SQLITE_INT64_TYPE sqlite_int64; + typedef unsigned SQLITE_INT64_TYPE sqlite_uint64; +#elif defined(_MSC_VER) || defined(__BORLANDC__) + typedef __int64 sqlite_int64; + typedef unsigned __int64 sqlite_uint64; +#else + typedef long long int sqlite_int64; + typedef unsigned long long int sqlite_uint64; +#endif + +/* +** If compiling for a processor that lacks floating point support, +** substitute integer for floating-point +*/ +#ifdef SQLITE_OMIT_FLOATING_POINT +# define double sqlite_int64 +#endif + +/* +** CAPI3REF: Closing A Database Connection +** +** Call this function with a pointer to a structure that was previously +** returned from [sqlite3_open()] and the corresponding database will by +** closed. +** +** All SQL statements prepared using [sqlite3_prepare_v2()] or +** [sqlite3_prepare16_v2()] must be destroyed using [sqlite3_finalize()] +** before this routine is called. Otherwise, SQLITE_BUSY is returned and the +** database connection remains open. +*/ +int sqlite3_close(sqlite3 *); + +/* +** The type for a callback function. +** This is legacy and deprecated. It is included for historical +** compatibility and is not documented. +*/ +typedef int (*sqlite3_callback)(void*,int,char**, char**); + +/* +** CAPI3REF: One-Step Query Execution Interface +** +** This interface is used to do a one-time evaluatation of zero +** or more SQL statements. UTF-8 text of the SQL statements to +** be evaluted is passed in as the second parameter. The statements +** are prepared one by one using [sqlite3_prepare()], evaluated +** using [sqlite3_step()], then destroyed using [sqlite3_finalize()]. +** +** If one or more of the SQL statements are queries, then +** the callback function specified by the 3rd parameter is +** invoked once for each row of the query result. This callback +** should normally return 0. If the callback returns a non-zero +** value then the query is aborted, all subsequent SQL statements +** are skipped and the sqlite3_exec() function returns the SQLITE_ABORT. +** +** The 4th parameter to this interface is an arbitrary pointer that is +** passed through to the callback function as its first parameter. +** +** The 2nd parameter to the callback function is the number of +** columns in the query result. The 3rd parameter to the callback +** is an array of strings holding the values for each column +** as extracted using [sqlite3_column_text()]. +** The 4th parameter to the callback is an array of strings +** obtained using [sqlite3_column_name()] and holding +** the names of each column. +** +** The callback function may be NULL, even for queries. A NULL +** callback is not an error. It just means that no callback +** will be invoked. +** +** If an error occurs while parsing or evaluating the SQL (but +** not while executing the callback) then an appropriate error +** message is written into memory obtained from [sqlite3_malloc()] and +** *errmsg is made to point to that message. The calling function +** is responsible for freeing the memory that holds the error +** message. Use [sqlite3_free()] for this. If errmsg==NULL, +** then no error message is ever written. +** +** The return value is is SQLITE_OK if there are no errors and +** some other [SQLITE_OK | return code] if there is an error. +** The particular return value depends on the type of error. +** +*/ +int sqlite3_exec( + sqlite3*, /* An open database */ + const char *sql, /* SQL to be evaluted */ + int (*callback)(void*,int,char**,char**), /* Callback function */ + void *, /* 1st argument to callback */ + char **errmsg /* Error msg written here */ +); + +/* +** CAPI3REF: Result Codes +** KEYWORDS: SQLITE_OK +** +** Many SQLite functions return an integer result code from the set shown +** above in order to indicates success or failure. +** +** The result codes above are the only ones returned by SQLite in its +** default configuration. However, the [sqlite3_extended_result_codes()] +** API can be used to set a database connectoin to return more detailed +** result codes. +** +** See also: [SQLITE_IOERR_READ | extended result codes] +** +*/ +#define SQLITE_OK 0 /* Successful result */ +/* beginning-of-error-codes */ +#define SQLITE_ERROR 1 /* SQL error or missing database */ +#define SQLITE_INTERNAL 2 /* NOT USED. Internal logic error in SQLite */ +#define SQLITE_PERM 3 /* Access permission denied */ +#define SQLITE_ABORT 4 /* Callback routine requested an abort */ +#define SQLITE_BUSY 5 /* The database file is locked */ +#define SQLITE_LOCKED 6 /* A table in the database is locked */ +#define SQLITE_NOMEM 7 /* A malloc() failed */ +#define SQLITE_READONLY 8 /* Attempt to write a readonly database */ +#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/ +#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */ +#define SQLITE_CORRUPT 11 /* The database disk image is malformed */ +#define SQLITE_NOTFOUND 12 /* NOT USED. Table or record not found */ +#define SQLITE_FULL 13 /* Insertion failed because database is full */ +#define SQLITE_CANTOPEN 14 /* Unable to open the database file */ +#define SQLITE_PROTOCOL 15 /* NOT USED. Database lock protocol error */ +#define SQLITE_EMPTY 16 /* Database is empty */ +#define SQLITE_SCHEMA 17 /* The database schema changed */ +#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */ +#define SQLITE_CONSTRAINT 19 /* Abort due to contraint violation */ +#define SQLITE_MISMATCH 20 /* Data type mismatch */ +#define SQLITE_MISUSE 21 /* Library used incorrectly */ +#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ +#define SQLITE_AUTH 23 /* Authorization denied */ +#define SQLITE_FORMAT 24 /* Auxiliary database format error */ +#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */ +#define SQLITE_NOTADB 26 /* File opened that is not a database file */ +#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */ +#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */ +/* end-of-error-codes */ + +/* +** CAPI3REF: Extended Result Codes +** +** In its default configuration, SQLite API routines return one of 26 integer +** result codes described at result-codes. However, experience has shown that +** many of these result codes are too course-grained. They do not provide as +** much information about problems as users might like. In an effort to +** address this, newer versions of SQLite (version 3.3.8 and later) include +** support for additional result codes that provide more detailed information +** about errors. The extended result codes are enabled (or disabled) for +** each database +** connection using the [sqlite3_extended_result_codes()] API. +** +** Some of the available extended result codes are listed above. +** We expect the number of extended result codes will be expand +** over time. Software that uses extended result codes should expect +** to see new result codes in future releases of SQLite. +** +** The symbolic name for an extended result code always contains a related +** primary result code as a prefix. Primary result codes contain a single +** "_" character. Extended result codes contain two or more "_" characters. +** The numeric value of an extended result code can be converted to its +** corresponding primary result code by masking off the lower 8 bytes. +** +** The SQLITE_OK result code will never be extended. It will always +** be exactly zero. +*/ +#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8)) +#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8)) +#define SQLITE_IOERR_WRITE (SQLITE_IOERR | (3<<8)) +#define SQLITE_IOERR_FSYNC (SQLITE_IOERR | (4<<8)) +#define SQLITE_IOERR_DIR_FSYNC (SQLITE_IOERR | (5<<8)) +#define SQLITE_IOERR_TRUNCATE (SQLITE_IOERR | (6<<8)) +#define SQLITE_IOERR_FSTAT (SQLITE_IOERR | (7<<8)) +#define SQLITE_IOERR_UNLOCK (SQLITE_IOERR | (8<<8)) +#define SQLITE_IOERR_RDLOCK (SQLITE_IOERR | (9<<8)) +#define SQLITE_IOERR_DELETE (SQLITE_IOERR | (10<<8)) +#define SQLITE_IOERR_BLOCKED (SQLITE_IOERR | (11<<8)) + +/* +** CAPI3REF: Enable Or Disable Extended Result Codes +** +** This routine enables or disables the +** [SQLITE_IOERR_READ | extended result codes] feature. +** By default, SQLite API routines return one of only 26 integer +** [SQLITE_OK | result codes]. When extended result codes +** are enabled by this routine, the repetoire of result codes can be +** much larger and can (hopefully) provide more detailed information +** about the cause of an error. +** +** The second argument is a boolean value that turns extended result +** codes on and off. Extended result codes are off by default for +** backwards compatibility with older versions of SQLite. +*/ +int sqlite3_extended_result_codes(sqlite3*, int onoff); + +/* +** CAPI3REF: Last Insert Rowid +** +** Each entry in an SQLite table has a unique 64-bit signed integer key +** called the "rowid". The rowid is always available as an undeclared +** column named ROWID, OID, or _ROWID_. If the table has a column of +** type INTEGER PRIMARY KEY then that column is another an alias for the +** rowid. +** +** This routine returns the rowid of the most recent INSERT into +** the database from the database connection given in the first +** argument. If no inserts have ever occurred on this database +** connection, zero is returned. +** +** If an INSERT occurs within a trigger, then the rowid of the +** inserted row is returned by this routine as long as the trigger +** is running. But once the trigger terminates, the value returned +** by this routine reverts to the last value inserted before the +** trigger fired. +*/ +sqlite_int64 sqlite3_last_insert_rowid(sqlite3*); + +/* +** CAPI3REF: Count The Number Of Rows Modified +** +** This function returns the number of database rows that were changed +** (or inserted or deleted) by the most recent SQL statement. Only +** changes that are directly specified by the INSERT, UPDATE, or +** DELETE statement are counted. Auxiliary changes caused by +** triggers are not counted. Use the [sqlite3_total_changes()] function +** to find the total number of changes including changes caused by triggers. +** +** Within the body of a trigger, the sqlite3_changes() interface can be +** called to find the number of +** changes in the most recently completed INSERT, UPDATE, or DELETE +** statement within the body of the trigger. +** +** All changes are counted, even if they were later undone by a +** ROLLBACK or ABORT. Except, changes associated with creating and +** dropping tables are not counted. +** +** If a callback invokes [sqlite3_exec()] or [sqlite3_step()] recursively, +** then the changes in the inner, recursive call are counted together +** with the changes in the outer call. +** +** SQLite implements the command "DELETE FROM table" without a WHERE clause +** by dropping and recreating the table. (This is much faster than going +** through and deleting individual elements from the table.) Because of +** this optimization, the change count for "DELETE FROM table" will be +** zero regardless of the number of elements that were originally in the +** table. To get an accurate count of the number of rows deleted, use +** "DELETE FROM table WHERE 1" instead. +*/ +int sqlite3_changes(sqlite3*); + +/* +** CAPI3REF: Total Number Of Rows Modified +*** +** This function returns the number of database rows that have been +** modified by INSERT, UPDATE or DELETE statements since the database handle +** was opened. This includes UPDATE, INSERT and DELETE statements executed +** as part of trigger programs. All changes are counted as soon as the +** statement that makes them is completed (when the statement handle is +** passed to [sqlite3_reset()] or [sqlite_finalise()]). +** +** See also the [sqlite3_change()] interface. +** +** SQLite implements the command "DELETE FROM table" without a WHERE clause +** by dropping and recreating the table. (This is much faster than going +** through and deleting individual elements form the table.) Because of +** this optimization, the change count for "DELETE FROM table" will be +** zero regardless of the number of elements that were originally in the +** table. To get an accurate count of the number of rows deleted, use +** "DELETE FROM table WHERE 1" instead. +*/ +int sqlite3_total_changes(sqlite3*); + +/* +** CAPI3REF: Interrupt A Long-Running Query +** +** This function causes any pending database operation to abort and +** return at its earliest opportunity. This routine is typically +** called in response to a user action such as pressing "Cancel" +** or Ctrl-C where the user wants a long query operation to halt +** immediately. +** +** It is safe to call this routine from a thread different from the +** thread that is currently running the database operation. +** +** The SQL operation that is interrupted will return [SQLITE_INTERRUPT]. +** If an interrupted operation was an update that is inside an +** explicit transaction, then the entire transaction will be rolled +** back automatically. +*/ +void sqlite3_interrupt(sqlite3*); + +/* +** CAPI3REF: Determine If An SQL Statement Is Complete +** +** These functions return true if the given input string comprises +** one or more complete SQL statements. For the sqlite3_complete() call, +** the parameter must be a nul-terminated UTF-8 string. For +** sqlite3_complete16(), a nul-terminated machine byte order UTF-16 string +** is required. +** +** These routines are useful for command-line input to determine if the +** currently entered text forms one or more complete SQL statements or +** if additional input is needed before sending the statements into +** SQLite for parsing. The algorithm is simple. If the +** last token other than spaces and comments is a semicolon, then return +** true. Actually, the algorithm is a little more complicated than that +** in order to deal with triggers, but the basic idea is the same: the +** statement is not complete unless it ends in a semicolon. +*/ +int sqlite3_complete(const char *sql); +int sqlite3_complete16(const void *sql); + +/* +** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors +** +** This routine identifies a callback function that might be invoked +** whenever an attempt is made to open a database table +** that another thread or process has locked. +** If the busy callback is NULL, then [SQLITE_BUSY] +** (or sometimes [SQLITE_IOERR_BLOCKED]) +** is returned immediately upon encountering the lock. +** If the busy callback is not NULL, then the +** callback will be invoked with two arguments. The +** first argument to the handler is a copy of the void* pointer which +** is the third argument to this routine. The second argument to +** the handler is the number of times that the busy handler has +** been invoked for this locking event. If the +** busy callback returns 0, then no additional attempts are made to +** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned. +** If the callback returns non-zero, then another attempt is made to open the +** database for reading and the cycle repeats. +** +** The presence of a busy handler does not guarantee that +** it will be invoked when there is lock contention. +** If SQLite determines that invoking the busy handler could result in +** a deadlock, it will return [SQLITE_BUSY] instead. +** Consider a scenario where one process is holding a read lock that +** it is trying to promote to a reserved lock and +** a second process is holding a reserved lock that it is trying +** to promote to an exclusive lock. The first process cannot proceed +** because it is blocked by the second and the second process cannot +** proceed because it is blocked by the first. If both processes +** invoke the busy handlers, neither will make any progress. Therefore, +** SQLite returns [SQLITE_BUSY] for the first process, hoping that this +** will induce the first process to release its read lock and allow +** the second process to proceed. +** +** The default busy callback is NULL. +** +** The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED] when +** SQLite is in the middle of a large transaction where all the +** changes will not fit into the in-memory cache. SQLite will +** already hold a RESERVED lock on the database file, but it needs +** to promote this lock to EXCLUSIVE so that it can spill cache +** pages into the database file without harm to concurrent +** readers. If it is unable to promote the lock, then the in-memory +** cache will be left in an inconsistent state and so the error +** code is promoted from the relatively benign [SQLITE_BUSY] to +** the more severe [SQLITE_IOERR_BLOCKED]. This error code promotion +** forces an automatic rollback of the changes. See the +** +** CorruptionFollowingBusyError wiki page for a discussion of why +** this is important. +** +** Sqlite is re-entrant, so the busy handler may start a new query. +** (It is not clear why anyone would every want to do this, but it +** is allowed, in theory.) But the busy handler may not close the +** database. Closing the database from a busy handler will delete +** data structures out from under the executing query and will +** probably result in a segmentation fault or other runtime error. +** +** There can only be a single busy handler defined for each database +** connection. Setting a new busy handler clears any previous one. +** Note that calling [sqlite3_busy_timeout()] will also set or clear +** the busy handler. +*/ +int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); + +/* +** CAPI3REF: Set A Busy Timeout +** +** This routine sets a busy handler that sleeps for a while when a +** table is locked. The handler will sleep multiple times until +** at least "ms" milliseconds of sleeping have been done. After +** "ms" milliseconds of sleeping, the handler returns 0 which +** causes [sqlite3_step()] to return [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]. +** +** Calling this routine with an argument less than or equal to zero +** turns off all busy handlers. +** +** There can only be a single busy handler for a particular database +** connection. If another busy handler was defined +** (using [sqlite3_busy_handler()]) prior to calling +** this routine, that other busy handler is cleared. +*/ +int sqlite3_busy_timeout(sqlite3*, int ms); + +/* +** CAPI3REF: Convenience Routines For Running Queries +** +** This next routine is a convenience wrapper around [sqlite3_exec()]. +** Instead of invoking a user-supplied callback for each row of the +** result, this routine remembers each row of the result in memory +** obtained from [sqlite3_malloc()], then returns all of the result after the +** query has finished. +** +** As an example, suppose the query result where this table: +** +**
+**        Name        | Age
+**        -----------------------
+**        Alice       | 43
+**        Bob         | 28
+**        Cindy       | 21
+** 
+** +** If the 3rd argument were &azResult then after the function returns +** azResult will contain the following data: +** +**
+**        azResult[0] = "Name";
+**        azResult[1] = "Age";
+**        azResult[2] = "Alice";
+**        azResult[3] = "43";
+**        azResult[4] = "Bob";
+**        azResult[5] = "28";
+**        azResult[6] = "Cindy";
+**        azResult[7] = "21";
+** 
+** +** Notice that there is an extra row of data containing the column +** headers. But the *nrow return value is still 3. *ncolumn is +** set to 2. In general, the number of values inserted into azResult +** will be ((*nrow) + 1)*(*ncolumn). +** +** After the calling function has finished using the result, it should +** pass the result data pointer to sqlite3_free_table() in order to +** release the memory that was malloc-ed. Because of the way the +** [sqlite3_malloc()] happens, the calling function must not try to call +** [sqlite3_free()] directly. Only [sqlite3_free_table()] is able to release +** the memory properly and safely. +** +** The return value of this routine is the same as from [sqlite3_exec()]. +*/ +int sqlite3_get_table( + sqlite3*, /* An open database */ + const char *sql, /* SQL to be executed */ + char ***resultp, /* Result written to a char *[] that this points to */ + int *nrow, /* Number of result rows written here */ + int *ncolumn, /* Number of result columns written here */ + char **errmsg /* Error msg written here */ +); +void sqlite3_free_table(char **result); + +/* +** CAPI3REF: Formatted String Printing Functions +** +** These routines are workalikes of the "printf()" family of functions +** from the standard C library. +** +** The sqlite3_mprintf() and sqlite3_vmprintf() routines write their +** results into memory obtained from [sqlite_malloc()]. +** The strings returned by these two routines should be +** released by [sqlite3_free()]. Both routines return a +** NULL pointer if [sqlite3_malloc()] is unable to allocate enough +** memory to hold the resulting string. +** +** In sqlite3_snprintf() routine is similar to "snprintf()" from +** the standard C library. The result is written into the +** buffer supplied as the second parameter whose size is given by +** the first parameter. Note that the order of the +** first two parameters is reversed from snprintf(). This is an +** historical accident that cannot be fixed without breaking +** backwards compatibility. Note also that sqlite3_snprintf() +** returns a pointer to its buffer instead of the number of +** characters actually written into the buffer. We admit that +** the number of characters written would be a more useful return +** value but we cannot change the implementation of sqlite3_snprintf() +** now without breaking compatibility. +** +** As long as the buffer size is greater than zero, sqlite3_snprintf() +** guarantees that the buffer is always zero-terminated. The first +** parameter "n" is the total size of the buffer, including space for +** the zero terminator. So the longest string that can be completely +** written will be n-1 characters. +** +** These routines all implement some additional formatting +** options that are useful for constructing SQL statements. +** All of the usual printf formatting options apply. In addition, there +** is are "%q" and "%Q" options. +** +** The %q option works like %s in that it substitutes a null-terminated +** string from the argument list. But %q also doubles every '\'' character. +** %q is designed for use inside a string literal. By doubling each '\'' +** character it escapes that character and allows it to be inserted into +** the string. +** +** For example, so some string variable contains text as follows: +** +**
+**  char *zText = "It's a happy day!";
+** 
+** +** One can use this text in an SQL statement as follows: +** +**
+**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES('%q')", zText);
+**  sqlite3_exec(db, zSQL, 0, 0, 0);
+**  sqlite3_free(zSQL);
+** 
+** +** Because the %q format string is used, the '\'' character in zText +** is escaped and the SQL generated is as follows: +** +**
+**  INSERT INTO table1 VALUES('It''s a happy day!')
+** 
+** +** This is correct. Had we used %s instead of %q, the generated SQL +** would have looked like this: +** +**
+**  INSERT INTO table1 VALUES('It's a happy day!');
+** 
+** +** This second example is an SQL syntax error. As a general rule you +** should always use %q instead of %s when inserting text into a string +** literal. +** +** The %Q option works like %q except it also adds single quotes around +** the outside of the total string. Or if the parameter in the argument +** list is a NULL pointer, %Q substitutes the text "NULL" (without single +** quotes) in place of the %Q option. So, for example, one could say: +** +**
+**  char *zSQL = sqlite3_mprintf("INSERT INTO table VALUES(%Q)", zText);
+**  sqlite3_exec(db, zSQL, 0, 0, 0);
+**  sqlite3_free(zSQL);
+** 
+** +** The code above will render a correct SQL statement in the zSQL +** variable even if the zText variable is a NULL pointer. +*/ +char *sqlite3_mprintf(const char*,...); +char *sqlite3_vmprintf(const char*, va_list); +char *sqlite3_snprintf(int,char*,const char*, ...); + +/* +** CAPI3REF: Memory Allocation Functions +** +** SQLite uses its own memory allocator. On some installations, this +** memory allocator is identical to the standard malloc()/realloc()/free() +** and can be used interchangable. On others, the implementations are +** different. For maximum portability, it is best not to mix calls +** to the standard malloc/realloc/free with the sqlite versions. +*/ +void *sqlite3_malloc(int); +void *sqlite3_realloc(void*, int); +void sqlite3_free(void*); + +/* +** CAPI3REF: Compile-Time Authorization Callbacks +*** +** This routine registers a authorizer callback with the SQLite library. +** The authorizer callback is invoked as SQL statements are being compiled +** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()], +** [sqlite3_prepare16()] and [sqlite3_prepare16_v2()]. At various +** points during the compilation process, as logic is being created +** to perform various actions, the authorizer callback is invoked to +** see if those actions are allowed. The authorizer callback should +** return SQLITE_OK to allow the action, [SQLITE_IGNORE] to disallow the +** specific action but allow the SQL statement to continue to be +** compiled, or [SQLITE_DENY] to cause the entire SQL statement to be +** rejected with an error. +** +** Depending on the action, the [SQLITE_IGNORE] and [SQLITE_DENY] return +** codes might mean something different or they might mean the same +** thing. If the action is, for example, to perform a delete opertion, +** then [SQLITE_IGNORE] and [SQLITE_DENY] both cause the statement compilation +** to fail with an error. But if the action is to read a specific column +** from a specific table, then [SQLITE_DENY] will cause the entire +** statement to fail but [SQLITE_IGNORE] will cause a NULL value to be +** read instead of the actual column value. +** +** The first parameter to the authorizer callback is a copy of +** the third parameter to the sqlite3_set_authorizer() interface. +** The second parameter to the callback is an integer +** [SQLITE_COPY | action code] that specifies the particular action +** to be authorized. The available action codes are +** [SQLITE_COPY | documented separately]. The third through sixth +** parameters to the callback are strings that contain additional +** details about the action to be authorized. +** +** An authorizer is used when preparing SQL statements from an untrusted +** source, to ensure that the SQL statements do not try to access data +** that they are not allowed to see, or that they do not try to +** execute malicious statements that damage the database. For +** example, an application may allow a user to enter arbitrary +** SQL queries for evaluation by a database. But the application does +** not want the user to be able to make arbitrary changes to the +** database. An authorizer could then be put in place while the +** user-entered SQL is being prepared that disallows everything +** except SELECT statements. +** +** Only a single authorizer can be in place on a database connection +** at a time. Each call to sqlite3_set_authorizer overrides the +** previous call. A NULL authorizer means that no authorization +** callback is invoked. The default authorizer is NULL. +** +** Note that the authorizer callback is invoked only during +** [sqlite3_prepare()] or its variants. Authorization is not +** performed during statement evaluation in [sqlite3_step()]. +*/ +int sqlite3_set_authorizer( + sqlite3*, + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*), + void *pUserData +); + +/* +** CAPI3REF: Authorizer Return Codes +** +** The [sqlite3_set_authorizer | authorizer callback function] must +** return either [SQLITE_OK] or one of these two constants in order +** to signal SQLite whether or not the action is permitted. See the +** [sqlite3_set_authorizer | authorizer documentation] for additional +** information. +*/ +#define SQLITE_DENY 1 /* Abort the SQL statement with an error */ +#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */ + +/* +** CAPI3REF: Authorizer Action Codes +** +** The [sqlite3_set_authorizer()] interface registers a callback function +** that is invoked to authorizer certain SQL statement actions. The +** second parameter to the callback is an integer code that specifies +** what action is being authorized. These are the integer action codes that +** the authorizer callback may be passed. +** +** These action code values signify what kind of operation is to be +** authorized. The 3rd and 4th parameters to the authorization callback +** function will be parameters or NULL depending on which of these +** codes is used as the second parameter. The 5th parameter to the +** authorizer callback is the name of the database ("main", "temp", +** etc.) if applicable. The 6th parameter to the authorizer callback +** is the name of the inner-most trigger or view that is responsible for +** the access attempt or NULL if this access attempt is directly from +** top-level SQL code. +*/ +/******************************************* 3rd ************ 4th ***********/ +#define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */ +#define SQLITE_CREATE_TABLE 2 /* Table Name NULL */ +#define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */ +#define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */ +#define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */ +#define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */ +#define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */ +#define SQLITE_CREATE_VIEW 8 /* View Name NULL */ +#define SQLITE_DELETE 9 /* Table Name NULL */ +#define SQLITE_DROP_INDEX 10 /* Index Name Table Name */ +#define SQLITE_DROP_TABLE 11 /* Table Name NULL */ +#define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */ +#define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */ +#define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */ +#define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */ +#define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */ +#define SQLITE_DROP_VIEW 17 /* View Name NULL */ +#define SQLITE_INSERT 18 /* Table Name NULL */ +#define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */ +#define SQLITE_READ 20 /* Table Name Column Name */ +#define SQLITE_SELECT 21 /* NULL NULL */ +#define SQLITE_TRANSACTION 22 /* NULL NULL */ +#define SQLITE_UPDATE 23 /* Table Name Column Name */ +#define SQLITE_ATTACH 24 /* Filename NULL */ +#define SQLITE_DETACH 25 /* Database Name NULL */ +#define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */ +#define SQLITE_REINDEX 27 /* Index Name NULL */ +#define SQLITE_ANALYZE 28 /* Table Name NULL */ +#define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */ +#define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */ +#define SQLITE_FUNCTION 31 /* Function Name NULL */ +#define SQLITE_COPY 0 /* No longer used */ + +/* +** CAPI3REF: Tracing And Profiling Functions +** +** These routines register callback functions that can be used for +** tracing and profiling the execution of SQL statements. +** The callback function registered by sqlite3_trace() is invoked +** at the first [sqlite3_step()] for the evaluation of an SQL statement. +** The callback function registered by sqlite3_profile() is invoked +** as each SQL statement finishes and includes +** information on how long that statement ran. +** +** The sqlite3_profile() API is currently considered experimental and +** is subject to change. +*/ +void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*); +void *sqlite3_profile(sqlite3*, + void(*xProfile)(void*,const char*,sqlite_uint64), void*); + +/* +** CAPI3REF: Query Progress Callbacks +** +** This routine configures a callback function - the progress callback - that +** is invoked periodically during long running calls to [sqlite3_exec()], +** [sqlite3_step()] and [sqlite3_get_table()]. An example use for this +** interface is to keep a GUI updated during a large query. +** +** The progress callback is invoked once for every N virtual machine opcodes, +** where N is the second argument to this function. The progress callback +** itself is identified by the third argument to this function. The fourth +** argument to this function is a void pointer passed to the progress callback +** function each time it is invoked. +** +** If a call to [sqlite3_exec()], [sqlite3_step()], or [sqlite3_get_table()] +** results in fewer than N opcodes being executed, then the progress +** callback is never invoked. +** +** Only a single progress callback function may be registered for each +** open database connection. Every call to sqlite3_progress_handler() +** overwrites the results of the previous call. +** To remove the progress callback altogether, pass NULL as the third +** argument to this function. +** +** If the progress callback returns a result other than 0, then the current +** query is immediately terminated and any database changes rolled back. +** The containing [sqlite3_exec()], [sqlite3_step()], or +** [sqlite3_get_table()] call returns SQLITE_INTERRUPT. This feature +** can be used, for example, to implement the "Cancel" button on a +** progress dialog box in a GUI. +*/ +void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*); + +/* +** CAPI3REF: Opening A New Database Connection +** +** Open the sqlite database file "filename". The "filename" is UTF-8 +** encoded for sqlite3_open() and UTF-16 encoded in the native byte order +** for sqlite3_open16(). An [sqlite3*] handle is returned in *ppDb, even +** if an error occurs. If the database is opened (or created) successfully, +** then SQLITE_OK is returned. Otherwise an error code is returned. The +** sqlite3_errmsg() or sqlite3_errmsg16() routines can be used to obtain +** an English language description of the error. +** +** If the database file does not exist, then a new database will be created +** as needed. The default encoding for the database will be UTF-8 if +** sqlite3_open() is called and UTF-16 if sqlite3_open16 is used. +** +** Whether or not an error occurs when it is opened, resources associated +** with the [sqlite3*] handle should be released by passing it to +** sqlite3_close() when it is no longer required. +** +** Note to windows users: The encoding used for the filename argument +** of sqlite3_open() must be UTF-8, not whatever codepage is currently +** defined. Filenames containing international characters must be converted +** to UTF-8 prior to passing them into sqlite3_open(). +*/ +int sqlite3_open( + const char *filename, /* Database filename (UTF-8) */ + sqlite3 **ppDb /* OUT: SQLite db handle */ +); +int sqlite3_open16( + const void *filename, /* Database filename (UTF-16) */ + sqlite3 **ppDb /* OUT: SQLite db handle */ +); + +/* +** CAPI3REF: Error Codes And Messages +** +** The sqlite3_errcode() interface returns the numeric +** [SQLITE_OK | result code] or [SQLITE_IOERR_READ | extended result code] +** for the most recent failed sqlite3_* API call associated +** with [sqlite3] handle 'db'. If a prior API call failed but the +** most recent API call succeeded, the return value from sqlite3_errcode() +** is undefined. +** +** The sqlite3_errmsg() and sqlite3_errmsg16() return English-langauge +** text that describes the error, as either UTF8 or UTF16 respectively. +** Memory to hold the error message string is managed internally. The +** string may be overwritten or deallocated by subsequent calls to SQLite +** interface functions. +** +** Calls to many sqlite3_* functions set the error code and string returned +** by [sqlite3_errcode()], [sqlite3_errmsg()], and [sqlite3_errmsg16()] +** (overwriting the previous values). Note that calls to [sqlite3_errcode()], +** [sqlite3_errmsg()], and [sqlite3_errmsg16()] themselves do not affect the +** results of future invocations. Calls to API routines that do not return +** an error code (examples: [sqlite3_data_count()] or [sqlite3_mprintf()]) do +** not change the error code returned by this routine. +** +** Assuming no other intervening sqlite3_* API calls are made, the error +** code returned by this function is associated with the same error as +** the strings returned by [sqlite3_errmsg()] and [sqlite3_errmsg16()]. +*/ +int sqlite3_errcode(sqlite3 *db); +const char *sqlite3_errmsg(sqlite3*); +const void *sqlite3_errmsg16(sqlite3*); + +/* +** CAPI3REF: SQL Statement Object +** +** Instance of this object represent single SQL statements. This +** is variously known as a "prepared statement" or a +** "compiled SQL statement" or simply as a "statement". +** +** The life of a statement object goes something like this: +** +**
    +**
  1. Create the object using [sqlite3_prepare_v2()] or a related +** function. +**
  2. Bind values to host parameters using +** [sqlite3_bind_blob | sqlite3_bind_* interfaces]. +**
  3. Run the SQL by calling [sqlite3_step()] one or more times. +**
  4. Reset the statement using [sqlite3_reset()] then go back +** to step 2. Do this zero or more times. +**
  5. Destroy the object using [sqlite3_finalize()]. +**
+** +** Refer to documentation on individual methods above for additional +** information. +*/ +typedef struct sqlite3_stmt sqlite3_stmt; + +/* +** CAPI3REF: Compiling An SQL Statement +** +** To execute an SQL query, it must first be compiled into a byte-code +** program using one of these routines. +** +** The first argument "db" is an [sqlite3 | SQLite database handle] +** obtained from a prior call to [sqlite3_open()] or [sqlite3_open16()]. +** The second argument "zSql" is the statement to be compiled, encoded +** as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2() +** interfaces uses UTF-8 and sqlite3_prepare16() and sqlite3_prepare16_v2() +** use UTF-16. +** +** If the nByte argument is less +** than zero, then zSql is read up to the first zero terminator. If +** nByte is non-negative, then it is the maximum number of +** bytes read from zSql. When nByte is non-negative, the +** zSql string ends at either the first '\000' character or +** until the nByte-th byte, whichever comes first. +** +** *pzTail is made to point to the first byte past the end of the first +** SQL statement in zSql. This routine only compiles the first statement +** in zSql, so *pzTail is left pointing to what remains uncompiled. +** +** *ppStmt is left pointing to a compiled +** [sqlite3_stmt | SQL statement structure] that can be +** executed using [sqlite3_step()]. Or if there is an error, *ppStmt may be +** set to NULL. If the input text contained no SQL (if the input is and +** empty string or a comment) then *ppStmt is set to NULL. The calling +** procedure is responsible for deleting the compiled SQL statement +** using [sqlite3_finalize()] after it has finished with it. +** +** On success, [SQLITE_OK] is returned. Otherwise an +** [SQLITE_ERROR | error code] is returned. +** +** The sqlite3_prepare_v2() and sqlite3_prepare16_v2() interfaces are +** recommended for all new programs. The two older interfaces are retained +** for backwards compatibility, but their use is discouraged. +** In the "v2" interfaces, the prepared statement +** that is returned (the [sqlite3_stmt] object) contains a copy of the +** original SQL text. This causes the [sqlite3_step()] interface to +** behave a differently in two ways: +** +**
    +**
  1. +** If the database schema changes, instead of returning [SQLITE_SCHEMA] as it +** always used to do, [sqlite3_step()] will automatically recompile the SQL +** statement and try to run it again. If the schema has changed in a way +** that makes the statement no longer valid, [sqlite3_step()] will still +** return [SQLITE_SCHEMA]. But unlike the legacy behavior, [SQLITE_SCHEMA] is +** now a fatal error. Calling [sqlite3_prepare_v2()] again will not make the +** error go away. Note: use [sqlite3_errmsg()] to find the text of the parsing +** error that results in an [SQLITE_SCHEMA] return. +**
  2. +** +**
  3. +** When an error occurs, +** [sqlite3_step()] will return one of the detailed +** [SQLITE_ERROR | result codes] or +** [SQLITE_IOERR_READ | extended result codes] such as directly. +** The legacy behavior was that [sqlite3_step()] would only return a generic +** [SQLITE_ERROR] result code and you would have to make a second call to +** [sqlite3_reset()] in order to find the underlying cause of the problem. +** With the "v2" prepare interfaces, the underlying reason for the error is +** returned immediately. +**
  4. +**
+*/ +int sqlite3_prepare( + sqlite3 *db, /* Database handle */ + const char *zSql, /* SQL statement, UTF-8 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const char **pzTail /* OUT: Pointer to unused portion of zSql */ +); +int sqlite3_prepare_v2( + sqlite3 *db, /* Database handle */ + const char *zSql, /* SQL statement, UTF-8 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const char **pzTail /* OUT: Pointer to unused portion of zSql */ +); +int sqlite3_prepare16( + sqlite3 *db, /* Database handle */ + const void *zSql, /* SQL statement, UTF-16 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const void **pzTail /* OUT: Pointer to unused portion of zSql */ +); +int sqlite3_prepare16_v2( + sqlite3 *db, /* Database handle */ + const void *zSql, /* SQL statement, UTF-16 encoded */ + int nByte, /* Maximum length of zSql in bytes. */ + sqlite3_stmt **ppStmt, /* OUT: Statement handle */ + const void **pzTail /* OUT: Pointer to unused portion of zSql */ +); + +/* +** CAPI3REF: Dynamically Typed Value Object +** +** SQLite uses dynamic typing for the values it stores. Values can +** be integers, floating point values, strings, BLOBs, or NULL. When +** passing around values internally, each value is represented as +** an instance of the sqlite3_value object. +*/ +typedef struct Mem sqlite3_value; + +/* +** CAPI3REF: SQL Function Context Object +** +** The context in which an SQL function executes is stored in an +** sqlite3_context object. A pointer to such an object is the +** first parameter to user-defined SQL functions. +*/ +typedef struct sqlite3_context sqlite3_context; + +/* +** CAPI3REF: Binding Values To Prepared Statements +** +** In the SQL strings input to [sqlite3_prepare_v2()] and its variants, +** one or more literals can be replace by a parameter in one of these +** forms: +** +**
    +**
  • ? +**
  • ?NNN +**
  • :AAA +**
  • @AAA +**
  • $VVV +**
+** +** In the parameter forms shown above NNN is an integer literal, +** AAA is an alphanumeric identifier and VVV is a variable name according +** to the syntax rules of the TCL programming language. +** The values of these parameters (also called "host parameter names") +** can be set using the sqlite3_bind_*() routines defined here. +** +** The first argument to the sqlite3_bind_*() routines always is a pointer +** to the [sqlite3_stmt] object returned from [sqlite3_prepare_v2()] or +** its variants. The second +** argument is the index of the parameter to be set. The first parameter has +** an index of 1. When the same named parameter is used more than once, second +** and subsequent +** occurrences have the same index as the first occurrence. The index for +** named parameters can be looked up using the +** [sqlite3_bind_parameter_name()] API if desired. The index for "?NNN" +** parametes is the value of NNN. +** The NNN value must be between 1 and the compile-time +** parameter SQLITE_MAX_VARIABLE_NUMBER (default value: 999). +** See limits.html for additional information. +** +** The third argument is the value to bind to the parameter. +** +** In those +** routines that have a fourth argument, its value is the number of bytes +** in the parameter. To be clear: the value is the number of bytes in the +** string, not the number of characters. The number +** of bytes does not include the zero-terminator at the end of strings. +** If the fourth parameter is negative, the length of the string is +** number of bytes up to the first zero terminator. +** +** The fifth argument to sqlite3_bind_blob(), sqlite3_bind_text(), and +** sqlite3_bind_text16() is a destructor used to dispose of the BLOB or +** text after SQLite has finished with it. If the fifth argument is the +** special value [SQLITE_STATIC], then the library assumes that the information +** is in static, unmanaged space and does not need to be freed. If the +** fifth argument has the value [SQLITE_TRANSIENT], then SQLite makes its +** own private copy of the data immediately, before the sqlite3_bind_*() +** routine returns. +** +** The sqlite3_bind_zeroblob() routine binds a BLOB of length n that +** is filled with zeros. A zeroblob uses a fixed amount of memory +** (just an integer to hold it size) while it is being processed. +** Zeroblobs are intended to serve as place-holders for BLOBs whose +** content is later written using +** [sqlite3_blob_open | increment BLOB I/O] routines. +** +** The sqlite3_bind_*() routines must be called after +** [sqlite3_prepare_v2()] (and its variants) or [sqlite3_reset()] and +** before [sqlite3_step()]. +** Bindings are not cleared by the [sqlite3_reset()] routine. +** Unbound parameters are interpreted as NULL. +** +** These routines return [SQLITE_OK] on success or an error code if +** anything goes wrong. [SQLITE_RANGE] is returned if the parameter +** index is out of range. [SQLITE_NOMEM] is returned if malloc fails. +** [SQLITE_MISUSE] is returned if these routines are called on a virtual +** machine that is the wrong state or which has already been finalized. +*/ +int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*)); +int sqlite3_bind_double(sqlite3_stmt*, int, double); +int sqlite3_bind_int(sqlite3_stmt*, int, int); +int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite_int64); +int sqlite3_bind_null(sqlite3_stmt*, int); +int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*)); +int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*)); +int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); +int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); + +/* +** CAPI3REF: Number Of Host Parameters +** +** Return the largest host parameter index in the precompiled statement given +** as the argument. When the host parameters are of the forms like ":AAA" +** or "?", then they are assigned sequential increasing numbers beginning +** with one, so the value returned is the number of parameters. However +** if the same host parameter name is used multiple times, each occurrance +** is given the same number, so the value returned in that case is the number +** of unique host parameter names. If host parameters of the form "?NNN" +** are used (where NNN is an integer) then there might be gaps in the +** numbering and the value returned by this interface is the index of the +** host parameter with the largest index value. +*/ +int sqlite3_bind_parameter_count(sqlite3_stmt*); + +/* +** CAPI3REF: Name Of A Host Parameter +** +** This routine returns a pointer to the name of the n-th parameter in a +** [sqlite3_stmt | prepared statement]. +** Host parameters of the form ":AAA" or "@AAA" or "$VVV" have a name +** which is the string ":AAA" or "@AAA" or "$VVV". +** In other words, the initial ":" or "$" or "@" +** is included as part of the name. +** Parameters of the form "?" or "?NNN" have no name. +** +** The first bound parameter has an index of 1, not 0. +** +** If the value n is out of range or if the n-th parameter is nameless, +** then NULL is returned. The returned string is always in the +** UTF-8 encoding even if the named parameter was originally specified +** as UTF-16 in [sqlite3_prepare16()] or [sqlite3_prepare16_v2()]. +*/ +const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); + +/* +** CAPI3REF: Index Of A Parameter With A Given Name +** +** This routine returns the index of a host parameter with the given name. +** The name must match exactly. If no parameter with the given name is +** found, return 0. Parameter names must be UTF8. +*/ +int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); + +/* +** CAPI3REF: Reset All Bindings On A Prepared Statement +** +** Contrary to the intuition of many, [sqlite3_reset()] does not +** reset the [sqlite3_bind_blob | bindings] on a +** [sqlite3_stmt | prepared statement]. Use this routine to +** reset all host parameters to NULL. +*/ +int sqlite3_clear_bindings(sqlite3_stmt*); + +/* +** CAPI3REF: Number Of Columns In A Result Set +** +** Return the number of columns in the result set returned by the +** [sqlite3_stmt | compiled SQL statement]. This routine returns 0 +** if pStmt is an SQL statement that does not return data (for +** example an UPDATE). +*/ +int sqlite3_column_count(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Column Names In A Result Set +** +** These routines return the name assigned to a particular column +** in the result set of a SELECT statement. The sqlite3_column_name() +** interface returns a pointer to a UTF8 string and sqlite3_column_name16() +** returns a pointer to a UTF16 string. The first parameter is the +** [sqlite_stmt | prepared statement] that implements the SELECT statement. +** The second parameter is the column number. The left-most column is +** number 0. +** +** The returned string pointer is valid until either the +** [sqlite_stmt | prepared statement] is destroyed by [sqlite3_finalize()] +** or until the next call sqlite3_column_name() or sqlite3_column_name16() +** on the same column. +*/ +const char *sqlite3_column_name(sqlite3_stmt*, int N); +const void *sqlite3_column_name16(sqlite3_stmt*, int N); + +/* +** CAPI3REF: Source Of Data In A Query Result +** +** These routines provide a means to determine what column of what +** table in which database a result of a SELECT statement comes from. +** The name of the database or table or column can be returned as +** either a UTF8 or UTF16 string. The _database_ routines return +** the database name, the _table_ routines return the table name, and +** the origin_ routines return the column name. +** The returned string is valid until +** the [sqlite3_stmt | prepared statement] is destroyed using +** [sqlite3_finalize()] or until the same information is requested +** again in a different encoding. +** +** The names returned are the original un-aliased names of the +** database, table, and column. +** +** The first argument to the following calls is a +** [sqlite3_stmt | compiled SQL statement]. +** These functions return information about the Nth column returned by +** the statement, where N is the second function argument. +** +** If the Nth column returned by the statement is an expression +** or subquery and is not a column value, then all of these functions +** return NULL. Otherwise, they return the +** name of the attached database, table and column that query result +** column was extracted from. +** +** As with all other SQLite APIs, those postfixed with "16" return UTF-16 +** encoded strings, the other functions return UTF-8. +** +** These APIs are only available if the library was compiled with the +** SQLITE_ENABLE_COLUMN_METADATA preprocessor symbol defined. +*/ +const char *sqlite3_column_database_name(sqlite3_stmt*,int); +const void *sqlite3_column_database_name16(sqlite3_stmt*,int); +const char *sqlite3_column_table_name(sqlite3_stmt*,int); +const void *sqlite3_column_table_name16(sqlite3_stmt*,int); +const char *sqlite3_column_origin_name(sqlite3_stmt*,int); +const void *sqlite3_column_origin_name16(sqlite3_stmt*,int); + +/* +** CAPI3REF: Declared Datatype Of A Query Result +** +** The first parameter is a [sqlite3_stmt | compiled SQL statement]. +** If this statement is a SELECT statement and the Nth column of the +** returned result set of that SELECT is a table column (not an +** expression or subquery) then the declared type of the table +** column is returned. If the Nth column of the result set is an +** expression or subquery, then a NULL pointer is returned. +** The returned string is always UTF-8 encoded. For example, in +** the database schema: +** +** CREATE TABLE t1(c1 VARIANT); +** +** And the following statement compiled: +** +** SELECT c1 + 1, c1 FROM t1; +** +** Then this routine would return the string "VARIANT" for the second +** result column (i==1), and a NULL pointer for the first result column +** (i==0). +** +** SQLite uses dynamic run-time typing. So just because a column +** is declared to contain a particular type does not mean that the +** data stored in that column is of the declared type. SQLite is +** strongly typed, but the typing is dynamic not static. Type +** is associated with individual values, not with the containers +** used to hold those values. +*/ +const char *sqlite3_column_decltype(sqlite3_stmt *, int i); +const void *sqlite3_column_decltype16(sqlite3_stmt*,int); + +/* +** CAPI3REF: Evaluate An SQL Statement +** +** After an [sqlite3_stmt | SQL statement] has been prepared with a call +** to either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or to one of +** the legacy interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], +** then this function must be called one or more times to evaluate the +** statement. +** +** The details of the behavior of this sqlite3_step() interface depend +** on whether the statement was prepared using the newer "v2" interface +** [sqlite3_prepare_v2()] and [sqlite3_prepare16_v2()] or the older legacy +** interface [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the +** new "v2" interface is recommended for new applications but the legacy +** interface will continue to be supported. +** +** In the lagacy interface, the return value will be either [SQLITE_BUSY], +** [SQLITE_DONE], [SQLITE_ROW], [SQLITE_ERROR], or [SQLITE_MISUSE]. +** With the "v2" interface, any of the other [SQLITE_OK | result code] +** or [SQLITE_IOERR_READ | extended result code] might be returned as +** well. +** +** [SQLITE_BUSY] means that the database engine was unable to acquire the +** database locks it needs to do its job. If the statement is a COMMIT +** or occurs outside of an explicit transaction, then you can retry the +** statement. If the statement is not a COMMIT and occurs within a +** explicit transaction then you should rollback the transaction before +** continuing. +** +** [SQLITE_DONE] means that the statement has finished executing +** successfully. sqlite3_step() should not be called again on this virtual +** machine without first calling [sqlite3_reset()] to reset the virtual +** machine back to its initial state. +** +** If the SQL statement being executed returns any data, then +** [SQLITE_ROW] is returned each time a new row of data is ready +** for processing by the caller. The values may be accessed using +** the [sqlite3_column_int | column access functions]. +** sqlite3_step() is called again to retrieve the next row of data. +** +** [SQLITE_ERROR] means that a run-time error (such as a constraint +** violation) has occurred. sqlite3_step() should not be called again on +** the VM. More information may be found by calling [sqlite3_errmsg()]. +** With the legacy interface, a more specific error code (example: +** [SQLITE_INTERRUPT], [SQLITE_SCHEMA], [SQLITE_CORRUPT], and so forth) +** can be obtained by calling [sqlite3_reset()] on the +** [sqlite_stmt | prepared statement]. In the "v2" interface, +** the more specific error code is returned directly by sqlite3_step(). +** +** [SQLITE_MISUSE] means that the this routine was called inappropriately. +** Perhaps it was called on a [sqlite_stmt | prepared statement] that has +** already been [sqlite3_finalize | finalized] or on one that had +** previously returned [SQLITE_ERROR] or [SQLITE_DONE]. Or it could +** be the case that the same database connection is being used by two or +** more threads at the same moment in time. +** +** Goofy Interface Alert: +** In the legacy interface, +** the sqlite3_step() API always returns a generic error code, +** [SQLITE_ERROR], following any error other than [SQLITE_BUSY] +** and [SQLITE_MISUSE]. You must call [sqlite3_reset()] or +** [sqlite3_finalize()] in order to find one of the specific +** [SQLITE_ERROR | result codes] that better describes the error. +** We admit that this is a goofy design. The problem has been fixed +** with the "v2" interface. If you prepare all of your SQL statements +** using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] instead +** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()], then the +** more specific [SQLITE_ERROR | result codes] are returned directly +** by sqlite3_step(). The use of the "v2" interface is recommended. +*/ +int sqlite3_step(sqlite3_stmt*); + +/* +** CAPI3REF: +** +** Return the number of values in the current row of the result set. +** +** After a call to [sqlite3_step()] that returns [SQLITE_ROW], this routine +** will return the same value as the [sqlite3_column_count()] function. +** After [sqlite3_step()] has returned an [SQLITE_DONE], [SQLITE_BUSY], or +** a [SQLITE_ERROR | error code], or before [sqlite3_step()] has been +** called on the [sqlite_stmt | prepared statement] for the first time, +** this routine returns zero. +*/ +int sqlite3_data_count(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Fundamental Datatypes +** +** Every value in SQLite has one of five fundamental datatypes: +** +**
    +**
  • 64-bit signed integer +**
  • 64-bit IEEE floating point number +**
  • string +**
  • BLOB +**
  • NULL +**
+** +** These constants are codes for each of those types. +** +** Note that the SQLITE_TEXT constant was also used in SQLite version 2 +** for a completely different meaning. Software that links against both +** SQLite version 2 and SQLite version 3 should use SQLITE3_TEXT not +** SQLITE_TEXT. +*/ +#define SQLITE_INTEGER 1 +#define SQLITE_FLOAT 2 +#define SQLITE_BLOB 4 +#define SQLITE_NULL 5 +#ifdef SQLITE_TEXT +# undef SQLITE_TEXT +#else +# define SQLITE_TEXT 3 +#endif +#define SQLITE3_TEXT 3 + +/* +** CAPI3REF: Results Values From A Query +** +** These routines return information about the information +** in a single column of the current result row of a query. In every +** case the first argument is a pointer to the +** [sqlite3_stmt | SQL statement] that is being +** evaluate (the [sqlite_stmt*] that was returned from +** [sqlite3_prepare_v2()] or one of its variants) and +** the second argument is the index of the column for which information +** should be returned. The left-most column has an index of 0. +** +** If the SQL statement is not currently point to a valid row, or if the +** the column index is out of range, the result is undefined. +** +** The sqlite3_column_type() routine returns +** [SQLITE_INTEGER | datatype code] for the initial data type +** of the result column. The returned value is one of [SQLITE_INTEGER], +** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL]. The value +** returned by sqlite3_column_type() is only meaningful if no type +** conversions have occurred as described below. After a type conversion, +** the value returned by sqlite3_column_type() is undefined. Future +** versions of SQLite may change the behavior of sqlite3_column_type() +** following a type conversion. +** +** If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes() +** routine returns the number of bytes in that BLOB or string. +** If the result is a UTF-16 string, then sqlite3_column_bytes() converts +** the string to UTF-8 and then returns the number of bytes. +** If the result is a numeric value then sqlite3_column_bytes() uses +** [sqlite3_snprintf()] to convert that value to a UTF-8 string and returns +** the number of bytes in that string. +** The value returned does not include the zero terminator at the end +** of the string. For clarity: the value returned is the number of +** bytes in the string, not the number of characters. +** +** The sqlite3_column_bytes16() routine is similar to sqlite3_column_bytes() +** but leaves the result in UTF-16 instead of UTF-8. +** The zero terminator is not included in this count. +** +** These routines attempt to convert the value where appropriate. For +** example, if the internal representation is FLOAT and a text result +** is requested, [sqlite3_snprintf()] is used internally to do the conversion +** automatically. The following table details the conversions that +** are applied: +** +**
+**
+**
Internal Requested +**
Type Type Conversion +** +**
NULL INTEGER Result is 0 +**
NULL FLOAT Result is 0.0 +**
NULL TEXT Result is NULL pointer +**
NULL BLOB Result is NULL pointer +**
INTEGER FLOAT Convert from integer to float +**
INTEGER TEXT ASCII rendering of the integer +**
INTEGER BLOB Same as for INTEGER->TEXT +**
FLOAT INTEGER Convert from float to integer +**
FLOAT TEXT ASCII rendering of the float +**
FLOAT BLOB Same as FLOAT->TEXT +**
TEXT INTEGER Use atoi() +**
TEXT FLOAT Use atof() +**
TEXT BLOB No change +**
BLOB INTEGER Convert to TEXT then use atoi() +**
BLOB FLOAT Convert to TEXT then use atof() +**
BLOB TEXT Add a zero terminator if needed +**
+** +** +** The table above makes reference to standard C library functions atoi() +** and atof(). SQLite does not really use these functions. It has its +** on equavalent internal routines. The atoi() and atof() names are +** used in the table for brevity and because they are familiar to most +** C programmers. +** +** Note that when type conversions occur, pointers returned by prior +** calls to sqlite3_column_blob(), sqlite3_column_text(), and/or +** sqlite3_column_text16() may be invalidated. +** Type conversions and pointer invalidations might occur +** in the following cases: +** +**
    +**
  • The initial content is a BLOB and sqlite3_column_text() +** or sqlite3_column_text16() is called. A zero-terminator might +** need to be added to the string.

  • +** +**
  • The initial content is UTF-8 text and sqlite3_column_bytes16() or +** sqlite3_column_text16() is called. The content must be converted +** to UTF-16.

  • +** +**
  • The initial content is UTF-16 text and sqlite3_column_bytes() or +** sqlite3_column_text() is called. The content must be converted +** to UTF-8.

  • +**
+** +** Conversions between UTF-16be and UTF-16le are always done in place and do +** not invalidate a prior pointer, though of course the content of the buffer +** that the prior pointer points to will have been modified. Other kinds +** of conversion are done in place when it is possible, but sometime it is +** not possible and in those cases prior pointers are invalidated. +** +** The safest and easiest to remember policy is to invoke these routines +** in one of the following ways: +** +**
    +**
  • sqlite3_column_text() followed by sqlite3_column_bytes()
  • +**
  • sqlite3_column_blob() followed by sqlite3_column_bytes()
  • +**
  • sqlite3_column_text16() followed by sqlite3_column_bytes16()
  • +**
+** +** In other words, you should call sqlite3_column_text(), sqlite3_column_blob(), +** or sqlite3_column_text16() first to force the result into the desired +** format, then invoke sqlite3_column_bytes() or sqlite3_column_bytes16() to +** find the size of the result. Do not mix call to sqlite3_column_text() or +** sqlite3_column_blob() with calls to sqlite3_column_bytes16(). And do not +** mix calls to sqlite3_column_text16() with calls to sqlite3_column_bytes(). +*/ +const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); +int sqlite3_column_bytes(sqlite3_stmt*, int iCol); +int sqlite3_column_bytes16(sqlite3_stmt*, int iCol); +double sqlite3_column_double(sqlite3_stmt*, int iCol); +int sqlite3_column_int(sqlite3_stmt*, int iCol); +sqlite_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); +const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); +const void *sqlite3_column_text16(sqlite3_stmt*, int iCol); +int sqlite3_column_type(sqlite3_stmt*, int iCol); +sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol); + +/* +** CAPI3REF: Destroy A Prepared Statement Object +** +** The sqlite3_finalize() function is called to delete a +** [sqlite3_stmt | compiled SQL statement]. If the statement was +** executed successfully, or not executed at all, then SQLITE_OK is returned. +** If execution of the statement failed then an +** [SQLITE_ERROR | error code] or [SQLITE_IOERR_READ | extended error code] +** is returned. +** +** This routine can be called at any point during the execution of the +** [sqlite3_stmt | virtual machine]. If the virtual machine has not +** completed execution when this routine is called, that is like +** encountering an error or an interrupt. (See [sqlite3_interrupt()].) +** Incomplete updates may be rolled back and transactions cancelled, +** depending on the circumstances, and the +** [SQLITE_ERROR | result code] returned will be [SQLITE_ABORT]. +*/ +int sqlite3_finalize(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Reset A Prepared Statement Object +** +** The sqlite3_reset() function is called to reset a +** [sqlite_stmt | compiled SQL statement] object. +** back to it's initial state, ready to be re-executed. +** Any SQL statement variables that had values bound to them using +** the [sqlite3_bind_blob | sqlite3_bind_*() API] retain their values. +** Use [sqlite3_clear_bindings()] to reset the bindings. +*/ +int sqlite3_reset(sqlite3_stmt *pStmt); + +/* +** CAPI3REF: Create Or Redefine SQL Functions +** +** The following two functions are used to add SQL functions or aggregates +** or to redefine the behavior of existing SQL functions or aggregates. The +** difference only between the two is that the second parameter, the +** name of the (scalar) function or aggregate, is encoded in UTF-8 for +** sqlite3_create_function() and UTF-16 for sqlite3_create_function16(). +** +** The first argument is the [sqlite3 | database handle] that holds the +** SQL function or aggregate is to be added or redefined. If a single +** program uses more than one database handle internally, then SQL +** functions or aggregates must be added individually to each database +** handle with which they will be used. +** +** The second parameter is the name of the SQL function to be created +** or redefined. +** The length of the name is limited to 255 bytes, exclusive of the +** zero-terminator. Note that the name length limit is in bytes, not +** characters. Any attempt to create a function with a longer name +** will result in an SQLITE_ERROR error. +** +** The third parameter is the number of arguments that the SQL function or +** aggregate takes. If this parameter is negative, then the SQL function or +** aggregate may take any number of arguments. +** +** The fourth parameter, eTextRep, specifies what +** [SQLITE_UTF8 | text encoding] this SQL function prefers for +** its parameters. Any SQL function implementation should be able to work +** work with UTF-8, UTF-16le, or UTF-16be. But some implementations may be +** more efficient with one encoding than another. It is allowed to +** invoke sqlite_create_function() or sqlite3_create_function16() multiple +** times with the same function but with different values of eTextRep. +** When multiple implementations of the same function are available, SQLite +** will pick the one that involves the least amount of data conversion. +** If there is only a single implementation which does not care what +** text encoding is used, then the fourth argument should be +** [SQLITE_ANY]. +** +** The fifth parameter is an arbitrary pointer. The implementation +** of the function can gain access to this pointer using +** [sqlite_user_data()]. +** +** The seventh, eighth and ninth parameters, xFunc, xStep and xFinal, are +** pointers to C-language functions that implement the SQL +** function or aggregate. A scalar SQL function requires an implementation of +** the xFunc callback only, NULL pointers should be passed as the xStep +** and xFinal parameters. An aggregate SQL function requires an implementation +** of xStep and xFinal and NULL should be passed for xFunc. To delete an +** existing SQL function or aggregate, pass NULL for all three function +** callback. +** +** It is permitted to register multiple implementations of the same +** functions with the same name but with either differing numbers of +** arguments or differing perferred text encodings. SQLite will use +** the implementation most closely matches the way in which the +** SQL function is used. +*/ +int sqlite3_create_function( + sqlite3 *, + const char *zFunctionName, + int nArg, + int eTextRep, + void*, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*) +); +int sqlite3_create_function16( + sqlite3*, + const void *zFunctionName, + int nArg, + int eTextRep, + void*, + void (*xFunc)(sqlite3_context*,int,sqlite3_value**), + void (*xStep)(sqlite3_context*,int,sqlite3_value**), + void (*xFinal)(sqlite3_context*) +); + +/* +** CAPI3REF: Text Encodings +** +** These constant define integer codes that represent the various +** text encodings supported by SQLite. +*/ +#define SQLITE_UTF8 1 +#define SQLITE_UTF16LE 2 +#define SQLITE_UTF16BE 3 +#define SQLITE_UTF16 4 /* Use native byte order */ +#define SQLITE_ANY 5 /* sqlite3_create_function only */ +#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */ + +/* +** CAPI3REF: Obsolete Functions +** +** These functions are all now obsolete. In order to maintain +** backwards compatibility with older code, we continue to support +** these functions. However, new development projects should avoid +** the use of these functions. To help encourage people to avoid +** using these functions, we are not going to tell you want they do. +*/ +int sqlite3_aggregate_count(sqlite3_context*); +int sqlite3_expired(sqlite3_stmt*); +int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*); +int sqlite3_global_recover(void); + + +/* +** CAPI3REF: Obtaining SQL Function Parameter Values +** +** The C-language implementation of SQL functions and aggregates uses +** this set of interface routines to access the parameter values on +** the function or aggregate. +** +** The xFunc (for scalar functions) or xStep (for aggregates) parameters +** to [sqlite3_create_function()] and [sqlite3_create_function16()] +** define callbacks that implement the SQL functions and aggregates. +** The 4th parameter to these callbacks is an array of pointers to +** [sqlite3_value] objects. There is one [sqlite3_value] object for +** each parameter to the SQL function. These routines are used to +** extract values from the [sqlite3_value] objects. +** +** These routines work just like the corresponding +** [sqlite3_column_blob | sqlite3_column_* routines] except that +** these routines take a single [sqlite3_value*] pointer instead +** of an [sqlite3_stmt*] pointer and an integer column number. +** +** The sqlite3_value_text16() interface extracts a UTF16 string +** in the native byte-order of the host machine. The +** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces +** extract UTF16 strings as big-endian and little-endian respectively. +** +** The sqlite3_value_numeric_type() interface attempts to apply +** numeric affinity to the value. This means that an attempt is +** made to convert the value to an integer or floating point. If +** such a conversion is possible without loss of information (in order +** words if the value is original a string that looks like a number) +** then it is done. Otherwise no conversion occurs. The +** [SQLITE_INTEGER | datatype] after conversion is returned. +** +** Please pay particular attention to the fact that the pointer that +** is returned from [sqlite3_value_blob()], [sqlite3_value_text()], or +** [sqlite3_value_text16()] can be invalidated by a subsequent call to +** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite_value_text()], +** or [sqlite3_value_text16()]. +*/ +const void *sqlite3_value_blob(sqlite3_value*); +int sqlite3_value_bytes(sqlite3_value*); +int sqlite3_value_bytes16(sqlite3_value*); +double sqlite3_value_double(sqlite3_value*); +int sqlite3_value_int(sqlite3_value*); +sqlite_int64 sqlite3_value_int64(sqlite3_value*); +const unsigned char *sqlite3_value_text(sqlite3_value*); +const void *sqlite3_value_text16(sqlite3_value*); +const void *sqlite3_value_text16le(sqlite3_value*); +const void *sqlite3_value_text16be(sqlite3_value*); +int sqlite3_value_type(sqlite3_value*); +int sqlite3_value_numeric_type(sqlite3_value*); + +/* +** CAPI3REF: Obtain Aggregate Function Context +** +** The implementation of aggregate SQL functions use this routine to allocate +** a structure for storing their state. The first time this routine +** is called for a particular aggregate, a new structure of size nBytes +** is allocated, zeroed, and returned. On subsequent calls (for the +** same aggregate instance) the same buffer is returned. The implementation +** of the aggregate can use the returned buffer to accumulate data. +** +** The buffer allocated is freed automatically by SQLite whan the aggregate +** query concludes. +** +** The first parameter should be a copy of the +** [sqlite3_context | SQL function context] that is the first +** parameter to the callback routine that implements the aggregate +** function. +*/ +void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); + +/* +** CAPI3REF: User Data For Functions +** +** The pUserData parameter to the [sqlite3_create_function()] +** and [sqlite3_create_function16()] routines +** used to register user functions is available to +** the implementation of the function using this call. +*/ +void *sqlite3_user_data(sqlite3_context*); + +/* +** CAPI3REF: Function Auxiliary Data +** +** The following two functions may be used by scalar SQL functions to +** associate meta-data with argument values. If the same value is passed to +** multiple invocations of the same SQL function during query execution, under +** some circumstances the associated meta-data may be preserved. This may +** be used, for example, to add a regular-expression matching scalar +** function. The compiled version of the regular expression is stored as +** meta-data associated with the SQL value passed as the regular expression +** pattern. The compiled regular expression can be reused on multiple +** invocations of the same function so that the original pattern string +** does not need to be recompiled on each invocation. +** +** The sqlite3_get_auxdata() interface returns a pointer to the meta-data +** associated with the Nth argument value to the current SQL function +** call, where N is the second parameter. If no meta-data has been set for +** that value, then a NULL pointer is returned. +** +** The sqlite3_set_auxdata() is used to associate meta-data with an SQL +** function argument. The third parameter is a pointer to the meta-data +** to be associated with the Nth user function argument value. The fourth +** parameter specifies a destructor that will be called on the meta- +** data pointer to release it when it is no longer required. If the +** destructor is NULL, it is not invoked. +** +** In practice, meta-data is preserved between function calls for +** expressions that are constant at compile time. This includes literal +** values and SQL variables. +*/ +void *sqlite3_get_auxdata(sqlite3_context*, int); +void sqlite3_set_auxdata(sqlite3_context*, int, void*, void (*)(void*)); + + +/* +** CAPI3REF: Constants Defining Special Destructor Behavior +** +** These are special value for the destructor that is passed in as the +** final argument to routines like [sqlite3_result_blob()]. If the destructor +** argument is SQLITE_STATIC, it means that the content pointer is constant +** and will never change. It does not need to be destroyed. The +** SQLITE_TRANSIENT value means that the content will likely change in +** the near future and that SQLite should make its own private copy of +** the content before returning. +** +** The typedef is necessary to work around problems in certain +** C++ compilers. See ticket #2191. +*/ +typedef void (*sqlite3_destructor_type)(void*); +#define SQLITE_STATIC ((sqlite3_destructor_type)0) +#define SQLITE_TRANSIENT ((sqlite3_destructor_type)-1) + +/* +** CAPI3REF: Setting The Result Of An SQL Function +** +** These routines are used by the xFunc or xFinal callbacks that +** implement SQL functions and aggregates. See +** [sqlite3_create_function()] and [sqlite3_create_function16()] +** for additional information. +** +** These functions work very much like the +** [sqlite3_bind_blob | sqlite3_bind_*] family of functions used +** to bind values to host parameters in prepared statements. +** Refer to the +** [sqlite3_bind_blob | sqlite3_bind_* documentation] for +** additional information. +** +** The sqlite3_result_error() and sqlite3_result_error16() functions +** cause the implemented SQL function to throw an exception. The +** parameter to sqlite3_result_error() or sqlite3_result_error16() +** is the text of an error message. +** +** The sqlite3_result_toobig() cause the function implementation +** to throw and error indicating that a string or BLOB is to long +** to represent. +*/ +void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*)); +void sqlite3_result_double(sqlite3_context*, double); +void sqlite3_result_error(sqlite3_context*, const char*, int); +void sqlite3_result_error16(sqlite3_context*, const void*, int); +void sqlite3_result_error_toobig(sqlite3_context*); +void sqlite3_result_int(sqlite3_context*, int); +void sqlite3_result_int64(sqlite3_context*, sqlite_int64); +void sqlite3_result_null(sqlite3_context*); +void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*)); +void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); +void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); +void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); +void sqlite3_result_value(sqlite3_context*, sqlite3_value*); +void sqlite3_result_zeroblob(sqlite3_context*, int n); + +/* +** CAPI3REF: Define New Collating Sequences +** +** These functions are used to add new collation sequences to the +** [sqlite3*] handle specified as the first argument. +** +** The name of the new collation sequence is specified as a UTF-8 string +** for sqlite3_create_collation() and sqlite3_create_collation_v2() +** and a UTF-16 string for sqlite3_create_collation16(). In all cases +** the name is passed as the second function argument. +** +** The third argument must be one of the constants [SQLITE_UTF8], +** [SQLITE_UTF16LE] or [SQLITE_UTF16BE], indicating that the user-supplied +** routine expects to be passed pointers to strings encoded using UTF-8, +** UTF-16 little-endian or UTF-16 big-endian respectively. +** +** A pointer to the user supplied routine must be passed as the fifth +** argument. If it is NULL, this is the same as deleting the collation +** sequence (so that SQLite cannot call it anymore). Each time the user +** supplied function is invoked, it is passed a copy of the void* passed as +** the fourth argument to sqlite3_create_collation() or +** sqlite3_create_collation16() as its first parameter. +** +** The remaining arguments to the user-supplied routine are two strings, +** each represented by a [length, data] pair and encoded in the encoding +** that was passed as the third argument when the collation sequence was +** registered. The user routine should return negative, zero or positive if +** the first string is less than, equal to, or greater than the second +** string. i.e. (STRING1 - STRING2). +** +** The sqlite3_create_collation_v2() works like sqlite3_create_collation() +** excapt that it takes an extra argument which is a destructor for +** the collation. The destructor is called when the collation is +** destroyed and is passed a copy of the fourth parameter void* pointer +** of the sqlite3_create_collation_v2(). Collations are destroyed when +** they are overridden by later calls to the collation creation functions +** or when the [sqlite3*] database handle is closed using [sqlite3_close()]. +** +** The sqlite3_create_collation_v2() interface is experimental and +** subject to change in future releases. The other collation creation +** functions are stable. +*/ +int sqlite3_create_collation( + sqlite3*, + const char *zName, + int eTextRep, + void*, + int(*xCompare)(void*,int,const void*,int,const void*) +); +int sqlite3_create_collation_v2( + sqlite3*, + const char *zName, + int eTextRep, + void*, + int(*xCompare)(void*,int,const void*,int,const void*), + void(*xDestroy)(void*) +); +int sqlite3_create_collation16( + sqlite3*, + const char *zName, + int eTextRep, + void*, + int(*xCompare)(void*,int,const void*,int,const void*) +); + +/* +** CAPI3REF: Collation Needed Callbacks +** +** To avoid having to register all collation sequences before a database +** can be used, a single callback function may be registered with the +** database handle to be called whenever an undefined collation sequence is +** required. +** +** If the function is registered using the sqlite3_collation_needed() API, +** then it is passed the names of undefined collation sequences as strings +** encoded in UTF-8. If sqlite3_collation_needed16() is used, the names +** are passed as UTF-16 in machine native byte order. A call to either +** function replaces any existing callback. +** +** When the callback is invoked, the first argument passed is a copy +** of the second argument to sqlite3_collation_needed() or +** sqlite3_collation_needed16(). The second argument is the database +** handle. The third argument is one of [SQLITE_UTF8], [SQLITE_UTF16BE], or +** [SQLITE_UTF16LE], indicating the most desirable form of the collation +** sequence function required. The fourth parameter is the name of the +** required collation sequence. +** +** The callback function should register the desired collation using +** [sqlite3_create_collation()], [sqlite3_create_collation16()], or +** [sqlite3_create_collation_v2()]. +*/ +int sqlite3_collation_needed( + sqlite3*, + void*, + void(*)(void*,sqlite3*,int eTextRep,const char*) +); +int sqlite3_collation_needed16( + sqlite3*, + void*, + void(*)(void*,sqlite3*,int eTextRep,const void*) +); + +/* +** Specify the key for an encrypted database. This routine should be +** called right after sqlite3_open(). +** +** The code to implement this API is not available in the public release +** of SQLite. +*/ +int sqlite3_key( + sqlite3 *db, /* Database to be rekeyed */ + const void *pKey, int nKey /* The key */ +); + +/* +** Change the key on an open database. If the current database is not +** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the +** database is decrypted. +** +** The code to implement this API is not available in the public release +** of SQLite. +*/ +int sqlite3_rekey( + sqlite3 *db, /* Database to be rekeyed */ + const void *pKey, int nKey /* The new key */ +); + +/* +** CAPI3REF: Suspend Execution For A Short Time +** +** This function causes the current thread to suspend execution +** a number of milliseconds specified in its parameter. +** +** If the operating system does not support sleep requests with +** millisecond time resolution, then the time will be rounded up to +** the nearest second. The number of milliseconds of sleep actually +** requested from the operating system is returned. +*/ +int sqlite3_sleep(int); + +/* +** CAPI3REF: Name Of The Folder Holding Temporary Files +** +** If this global variable is made to point to a string which is +** the name of a folder (a.ka. directory), then all temporary files +** created by SQLite will be placed in that directory. If this variable +** is NULL pointer, then SQLite does a search for an appropriate temporary +** file directory. +** +** Once [sqlite3_open()] has been called, changing this variable will +** invalidate the current temporary database, if any. Generally speaking, +** it is not safe to invoke this routine after [sqlite3_open()] has +** been called. +*/ +extern char *sqlite3_temp_directory; + +/* +** CAPI3REF: Test To See If The Databse Is In Auto-Commit Mode +** +** Test to see whether or not the database connection is in autocommit +** mode. Return TRUE if it is and FALSE if not. Autocommit mode is on +** by default. Autocommit is disabled by a BEGIN statement and reenabled +** by the next COMMIT or ROLLBACK. +*/ +int sqlite3_get_autocommit(sqlite3*); + +/* +** CAPI3REF: Find The Database Handle Associated With A Prepared Statement +** +** Return the [sqlite3*] database handle to which a +** [sqlite3_stmt | prepared statement] belongs. +** This is the same database handle that was +** the first argument to the [sqlite3_prepare_v2()] or its variants +** that was used to create the statement in the first place. +*/ +sqlite3 *sqlite3_db_handle(sqlite3_stmt*); + + +/* +** CAPI3REF: Commit And Rollback Notification Callbacks +** +** These routines +** register callback functions to be invoked whenever a transaction +** is committed or rolled back. The pArg argument is passed through +** to the callback. If the callback on a commit hook function +** returns non-zero, then the commit is converted into a rollback. +** +** If another function was previously registered, its pArg value is returned. +** Otherwise NULL is returned. +** +** Registering a NULL function disables the callback. +** +** For the purposes of this API, a transaction is said to have been +** rolled back if an explicit "ROLLBACK" statement is executed, or +** an error or constraint causes an implicit rollback to occur. The +** callback is not invoked if a transaction is automatically rolled +** back because the database connection is closed. +** +** These are experimental interfaces and are subject to change. +*/ +void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*); +void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); + +/* +** CAPI3REF: Data Change Notification Callbacks +** +** Register a callback function with the database connection identified by the +** first argument to be invoked whenever a row is updated, inserted or deleted. +** Any callback set by a previous call to this function for the same +** database connection is overridden. +** +** The second argument is a pointer to the function to invoke when a +** row is updated, inserted or deleted. The first argument to the callback is +** a copy of the third argument to sqlite3_update_hook(). The second callback +** argument is one of SQLITE_INSERT, SQLITE_DELETE or SQLITE_UPDATE, depending +** on the operation that caused the callback to be invoked. The third and +** fourth arguments to the callback contain pointers to the database and +** table name containing the affected row. The final callback parameter is +** the rowid of the row. In the case of an update, this is the rowid after +** the update takes place. +** +** The update hook is not invoked when internal system tables are +** modified (i.e. sqlite_master and sqlite_sequence). +** +** If another function was previously registered, its pArg value is returned. +** Otherwise NULL is returned. +*/ +void *sqlite3_update_hook( + sqlite3*, + void(*)(void *,int ,char const *,char const *,sqlite_int64), + void* +); + +/* +** CAPI3REF: Enable Or Disable Shared Pager Cache +** +** This routine enables or disables the sharing of the database cache +** and schema data structures between connections to the same database. +** Sharing is enabled if the argument is true and disabled if the argument +** is false. +** +** Cache sharing is enabled and disabled on a thread-by-thread basis. +** Each call to this routine enables or disables cache sharing only for +** connections created in the same thread in which this routine is called. +** There is no mechanism for sharing cache between database connections +** running in different threads. +** +** Sharing must be disabled prior to shutting down a thread or else +** the thread will leak memory. Call this routine with an argument of +** 0 to turn off sharing. Or use the sqlite3_thread_cleanup() API. +** +** This routine must not be called when any database connections +** are active in the current thread. Enabling or disabling shared +** cache while there are active database connections will result +** in memory corruption. +** +** When the shared cache is enabled, the +** following routines must always be called from the same thread: +** [sqlite3_open()], [sqlite3_prepare_v2()], [sqlite3_step()], +** [sqlite3_reset()], [sqlite3_finalize()], and [sqlite3_close()]. +** This is due to the fact that the shared cache makes use of +** thread-specific storage so that it will be available for sharing +** with other connections. +** +** Virtual tables cannot be used with a shared cache. When shared +** cache is enabled, the sqlite3_create_module() API used to register +** virtual tables will always return an error. +** +** This routine returns [SQLITE_OK] if shared cache was +** enabled or disabled successfully. An [SQLITE_ERROR | error code] +** is returned otherwise. +** +** Shared cache is disabled by default for backward compatibility. +*/ +int sqlite3_enable_shared_cache(int); + +/* +** CAPI3REF: Attempt To Free Heap Memory +** +** Attempt to free N bytes of heap memory by deallocating non-essential +** memory allocations held by the database library (example: memory +** used to cache database pages to improve performance). +** +** This function is not a part of standard builds. It is only created +** if SQLite is compiled with the SQLITE_ENABLE_MEMORY_MANAGEMENT macro. +*/ +int sqlite3_release_memory(int); + +/* +** CAPI3REF: Impose A Limit On Heap Size +** +** Place a "soft" limit on the amount of heap memory that may be allocated by +** SQLite within the current thread. If an internal allocation is requested +** that would exceed the specified limit, [sqlite3_release_memory()] is invoked +** one or more times to free up some space before the allocation is made. +** +** The limit is called "soft", because if [sqlite3_release_memory()] cannot free +** sufficient memory to prevent the limit from being exceeded, the memory is +** allocated anyway and the current operation proceeds. +** +** Prior to shutting down a thread sqlite3_soft_heap_limit() must be set to +** zero (the default) or else the thread will leak memory. Alternatively, use +** the [sqlite3_thread_cleanup()] API. +** +** A negative or zero value for N means that there is no soft heap limit and +** [sqlite3_release_memory()] will only be called when memory is exhaused. +** The default value for the soft heap limit is zero. +** +** SQLite makes a best effort to honor the soft heap limit. But if it +** is unable to reduce memory usage below the soft limit, execution will +** continue without error or notification. This is why the limit is +** called a "soft" limit. It is advisory only. +** +** This function is only available if the library was compiled with the +** SQLITE_ENABLE_MEMORY_MANAGEMENT option set. +** memory-management has been enabled. +*/ +void sqlite3_soft_heap_limit(int); + +/* +** CAPI3REF: Clean Up Thread Local Storage +** +** This routine makes sure that all thread-local storage has been +** deallocated for the current thread. +** +** This routine is not technically necessary. All thread-local storage +** will be automatically deallocated once memory-management and +** shared-cache are disabled and the soft heap limit has been set +** to zero. This routine is provided as a convenience for users who +** want to make absolutely sure they have not forgotten something +** prior to killing off a thread. +*/ +void sqlite3_thread_cleanup(void); + +/* +** CAPI3REF: Extract Metadata About A Column Of A Table +** +** This routine +** returns meta-data about a specific column of a specific database +** table accessible using the connection handle passed as the first function +** argument. +** +** The column is identified by the second, third and fourth parameters to +** this function. The second parameter is either the name of the database +** (i.e. "main", "temp" or an attached database) containing the specified +** table or NULL. If it is NULL, then all attached databases are searched +** for the table using the same algorithm as the database engine uses to +** resolve unqualified table references. +** +** The third and fourth parameters to this function are the table and column +** name of the desired column, respectively. Neither of these parameters +** may be NULL. +** +** Meta information is returned by writing to the memory locations passed as +** the 5th and subsequent parameters to this function. Any of these +** arguments may be NULL, in which case the corresponding element of meta +** information is ommitted. +** +**
+** Parameter     Output Type      Description
+** -----------------------------------
+**
+**   5th         const char*      Data type
+**   6th         const char*      Name of the default collation sequence 
+**   7th         int              True if the column has a NOT NULL constraint
+**   8th         int              True if the column is part of the PRIMARY KEY
+**   9th         int              True if the column is AUTOINCREMENT
+** 
+** +** +** The memory pointed to by the character pointers returned for the +** declaration type and collation sequence is valid only until the next +** call to any sqlite API function. +** +** If the specified table is actually a view, then an error is returned. +** +** If the specified column is "rowid", "oid" or "_rowid_" and an +** INTEGER PRIMARY KEY column has been explicitly declared, then the output +** parameters are set for the explicitly declared column. If there is no +** explicitly declared IPK column, then the output parameters are set as +** follows: +** +**
+**     data type: "INTEGER"
+**     collation sequence: "BINARY"
+**     not null: 0
+**     primary key: 1
+**     auto increment: 0
+** 
+** +** This function may load one or more schemas from database files. If an +** error occurs during this process, or if the requested table or column +** cannot be found, an SQLITE error code is returned and an error message +** left in the database handle (to be retrieved using sqlite3_errmsg()). +** +** This API is only available if the library was compiled with the +** SQLITE_ENABLE_COLUMN_METADATA preprocessor symbol defined. +*/ +int sqlite3_table_column_metadata( + sqlite3 *db, /* Connection handle */ + const char *zDbName, /* Database name or NULL */ + const char *zTableName, /* Table name */ + const char *zColumnName, /* Column name */ + char const **pzDataType, /* OUTPUT: Declared data type */ + char const **pzCollSeq, /* OUTPUT: Collation sequence name */ + int *pNotNull, /* OUTPUT: True if NOT NULL constraint exists */ + int *pPrimaryKey, /* OUTPUT: True if column part of PK */ + int *pAutoinc /* OUTPUT: True if colums is auto-increment */ +); + +/* +** CAPI3REF: Load An Extension +** +** Attempt to load an SQLite extension library contained in the file +** zFile. The entry point is zProc. zProc may be 0 in which case the +** name of the entry point defaults to "sqlite3_extension_init". +** +** Return [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong. +** +** If an error occurs and pzErrMsg is not 0, then fill *pzErrMsg with +** error message text. The calling function should free this memory +** by calling [sqlite3_free()]. +** +** Extension loading must be enabled using [sqlite3_enable_load_extension()] +** prior to calling this API or an error will be returned. +*/ +int sqlite3_load_extension( + sqlite3 *db, /* Load the extension into this database connection */ + const char *zFile, /* Name of the shared library containing extension */ + const char *zProc, /* Entry point. Derived from zFile if 0 */ + char **pzErrMsg /* Put error message here if not 0 */ +); + +/* +** CAPI3REF: Enable Or Disable Extension Loading +** +** So as not to open security holes in older applications that are +** unprepared to deal with extension loading, and as a means of disabling +** extension loading while evaluating user-entered SQL, the following +** API is provided to turn the [sqlite3_load_extension()] mechanism on and +** off. It is off by default. See ticket #1863. +** +** Call this routine with onoff==1 to turn extension loading on +** and call it with onoff==0 to turn it back off again. +*/ +int sqlite3_enable_load_extension(sqlite3 *db, int onoff); + +/* +** CAPI3REF: Make Arrangements To Automatically Load An Extension +** +** Register an extension entry point that is automatically invoked +** whenever a new database connection is opened using +** [sqlite3_open()] or [sqlite3_open16()]. +** +** This API can be invoked at program startup in order to register +** one or more statically linked extensions that will be available +** to all new database connections. +** +** Duplicate extensions are detected so calling this routine multiple +** times with the same extension is harmless. +** +** This routine stores a pointer to the extension in an array +** that is obtained from malloc(). If you run a memory leak +** checker on your program and it reports a leak because of this +** array, then invoke [sqlite3_automatic_extension_reset()] prior +** to shutdown to free the memory. +** +** Automatic extensions apply across all threads. +** +** This interface is experimental and is subject to change or +** removal in future releases of SQLite. +*/ +int sqlite3_auto_extension(void *xEntryPoint); + + +/* +** CAPI3REF: Reset Automatic Extension Loading +** +** Disable all previously registered automatic extensions. This +** routine undoes the effect of all prior [sqlite3_automatic_extension()] +** calls. +** +** This call disabled automatic extensions in all threads. +** +** This interface is experimental and is subject to change or +** removal in future releases of SQLite. +*/ +void sqlite3_reset_auto_extension(void); + + +/* +****** EXPERIMENTAL - subject to change without notice ************** +** +** The interface to the virtual-table mechanism is currently considered +** to be experimental. The interface might change in incompatible ways. +** If this is a problem for you, do not use the interface at this time. +** +** When the virtual-table mechanism stablizes, we will declare the +** interface fixed, support it indefinitely, and remove this comment. +*/ + +/* +** Structures used by the virtual table interface +*/ +typedef struct sqlite3_vtab sqlite3_vtab; +typedef struct sqlite3_index_info sqlite3_index_info; +typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor; +typedef struct sqlite3_module sqlite3_module; + +/* +** A module is a class of virtual tables. Each module is defined +** by an instance of the following structure. This structure consists +** mostly of methods for the module. +*/ +struct sqlite3_module { + int iVersion; + int (*xCreate)(sqlite3*, void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVTab, char**); + int (*xConnect)(sqlite3*, void *pAux, + int argc, const char *const*argv, + sqlite3_vtab **ppVTab, char**); + int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*); + int (*xDisconnect)(sqlite3_vtab *pVTab); + int (*xDestroy)(sqlite3_vtab *pVTab); + int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor); + int (*xClose)(sqlite3_vtab_cursor*); + int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, + int argc, sqlite3_value **argv); + int (*xNext)(sqlite3_vtab_cursor*); + int (*xEof)(sqlite3_vtab_cursor*); + int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int); + int (*xRowid)(sqlite3_vtab_cursor*, sqlite_int64 *pRowid); + int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite_int64 *); + int (*xBegin)(sqlite3_vtab *pVTab); + int (*xSync)(sqlite3_vtab *pVTab); + int (*xCommit)(sqlite3_vtab *pVTab); + int (*xRollback)(sqlite3_vtab *pVTab); + int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName, + void (**pxFunc)(sqlite3_context*,int,sqlite3_value**), + void **ppArg); + + int (*xRename)(sqlite3_vtab *pVtab, const char *zNew); +}; + +/* +** The sqlite3_index_info structure and its substructures is used to +** pass information into and receive the reply from the xBestIndex +** method of an sqlite3_module. The fields under **Inputs** are the +** inputs to xBestIndex and are read-only. xBestIndex inserts its +** results into the **Outputs** fields. +** +** The aConstraint[] array records WHERE clause constraints of the +** form: +** +** column OP expr +** +** Where OP is =, <, <=, >, or >=. The particular operator is stored +** in aConstraint[].op. The index of the column is stored in +** aConstraint[].iColumn. aConstraint[].usable is TRUE if the +** expr on the right-hand side can be evaluated (and thus the constraint +** is usable) and false if it cannot. +** +** The optimizer automatically inverts terms of the form "expr OP column" +** and makes other simplificatinos to the WHERE clause in an attempt to +** get as many WHERE clause terms into the form shown above as possible. +** The aConstraint[] array only reports WHERE clause terms in the correct +** form that refer to the particular virtual table being queried. +** +** Information about the ORDER BY clause is stored in aOrderBy[]. +** Each term of aOrderBy records a column of the ORDER BY clause. +** +** The xBestIndex method must fill aConstraintUsage[] with information +** about what parameters to pass to xFilter. If argvIndex>0 then +** the right-hand side of the corresponding aConstraint[] is evaluated +** and becomes the argvIndex-th entry in argv. If aConstraintUsage[].omit +** is true, then the constraint is assumed to be fully handled by the +** virtual table and is not checked again by SQLite. +** +** The idxNum and idxPtr values are recorded and passed into xFilter. +** sqlite3_free() is used to free idxPtr if needToFreeIdxPtr is true. +** +** The orderByConsumed means that output from xFilter will occur in +** the correct order to satisfy the ORDER BY clause so that no separate +** sorting step is required. +** +** The estimatedCost value is an estimate of the cost of doing the +** particular lookup. A full scan of a table with N entries should have +** a cost of N. A binary search of a table of N entries should have a +** cost of approximately log(N). +*/ +struct sqlite3_index_info { + /* Inputs */ + const int nConstraint; /* Number of entries in aConstraint */ + const struct sqlite3_index_constraint { + int iColumn; /* Column on left-hand side of constraint */ + unsigned char op; /* Constraint operator */ + unsigned char usable; /* True if this constraint is usable */ + int iTermOffset; /* Used internally - xBestIndex should ignore */ + } *const aConstraint; /* Table of WHERE clause constraints */ + const int nOrderBy; /* Number of terms in the ORDER BY clause */ + const struct sqlite3_index_orderby { + int iColumn; /* Column number */ + unsigned char desc; /* True for DESC. False for ASC. */ + } *const aOrderBy; /* The ORDER BY clause */ + + /* Outputs */ + struct sqlite3_index_constraint_usage { + int argvIndex; /* if >0, constraint is part of argv to xFilter */ + unsigned char omit; /* Do not code a test for this constraint */ + } *const aConstraintUsage; + int idxNum; /* Number used to identify the index */ + char *idxStr; /* String, possibly obtained from sqlite3_malloc */ + int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */ + int orderByConsumed; /* True if output is already ordered */ + double estimatedCost; /* Estimated cost of using this index */ +}; +#define SQLITE_INDEX_CONSTRAINT_EQ 2 +#define SQLITE_INDEX_CONSTRAINT_GT 4 +#define SQLITE_INDEX_CONSTRAINT_LE 8 +#define SQLITE_INDEX_CONSTRAINT_LT 16 +#define SQLITE_INDEX_CONSTRAINT_GE 32 +#define SQLITE_INDEX_CONSTRAINT_MATCH 64 + +/* +** This routine is used to register a new module name with an SQLite +** connection. Module names must be registered before creating new +** virtual tables on the module, or before using preexisting virtual +** tables of the module. +*/ +int sqlite3_create_module( + sqlite3 *db, /* SQLite connection to register module with */ + const char *zName, /* Name of the module */ + const sqlite3_module *, /* Methods for the module */ + void * /* Client data for xCreate/xConnect */ +); + +/* +** This routine is identical to the sqlite3_create_module() method above, +** except that it allows a destructor function to be specified. It is +** even more experimental than the rest of the virtual tables API. +*/ +int sqlite3_create_module_v2( + sqlite3 *db, /* SQLite connection to register module with */ + const char *zName, /* Name of the module */ + const sqlite3_module *, /* Methods for the module */ + void *, /* Client data for xCreate/xConnect */ + void(*xDestroy)(void*) /* Module destructor function */ +); + +/* +** Every module implementation uses a subclass of the following structure +** to describe a particular instance of the module. Each subclass will +** be taylored to the specific needs of the module implementation. The +** purpose of this superclass is to define certain fields that are common +** to all module implementations. +** +** Virtual tables methods can set an error message by assigning a +** string obtained from sqlite3_mprintf() to zErrMsg. The method should +** take care that any prior string is freed by a call to sqlite3_free() +** prior to assigning a new string to zErrMsg. After the error message +** is delivered up to the client application, the string will be automatically +** freed by sqlite3_free() and the zErrMsg field will be zeroed. Note +** that sqlite3_mprintf() and sqlite3_free() are used on the zErrMsg field +** since virtual tables are commonly implemented in loadable extensions which +** do not have access to sqlite3MPrintf() or sqlite3Free(). +*/ +struct sqlite3_vtab { + const sqlite3_module *pModule; /* The module for this virtual table */ + int nRef; /* Used internally */ + char *zErrMsg; /* Error message from sqlite3_mprintf() */ + /* Virtual table implementations will typically add additional fields */ +}; + +/* Every module implementation uses a subclass of the following structure +** to describe cursors that point into the virtual table and are used +** to loop through the virtual table. Cursors are created using the +** xOpen method of the module. Each module implementation will define +** the content of a cursor structure to suit its own needs. +** +** This superclass exists in order to define fields of the cursor that +** are common to all implementations. +*/ +struct sqlite3_vtab_cursor { + sqlite3_vtab *pVtab; /* Virtual table of this cursor */ + /* Virtual table implementations will typically add additional fields */ +}; + +/* +** The xCreate and xConnect methods of a module use the following API +** to declare the format (the names and datatypes of the columns) of +** the virtual tables they implement. +*/ +int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable); + +/* +** Virtual tables can provide alternative implementations of functions +** using the xFindFunction method. But global versions of those functions +** must exist in order to be overloaded. +** +** This API makes sure a global version of a function with a particular +** name and number of parameters exists. If no such function exists +** before this API is called, a new function is created. The implementation +** of the new function always causes an exception to be thrown. So +** the new function is not good for anything by itself. Its only +** purpose is to be a place-holder function that can be overloaded +** by virtual tables. +** +** This API should be considered part of the virtual table interface, +** which is experimental and subject to change. +*/ +int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg); + +/* +** The interface to the virtual-table mechanism defined above (back up +** to a comment remarkably similar to this one) is currently considered +** to be experimental. The interface might change in incompatible ways. +** If this is a problem for you, do not use the interface at this time. +** +** When the virtual-table mechanism stablizes, we will declare the +** interface fixed, support it indefinitely, and remove this comment. +** +****** EXPERIMENTAL - subject to change without notice ************** +*/ + +/* +** CAPI3REF: A Handle To An Open BLOB +** +** An instance of the following opaque structure is used to +** represent an blob-handle. A blob-handle is created by +** [sqlite3_blob_open()] and destroyed by [sqlite3_blob_close()]. +** The [sqlite3_blob_read()] and [sqlite3_blob_write()] interfaces +** can be used to read or write small subsections of the blob. +** The [sqltie3_blob_size()] interface returns the size of the +** blob in bytes. +*/ +typedef struct sqlite3_blob sqlite3_blob; + +/* +** CAPI3REF: Open A BLOB For Incremental I/O +** +** Open a handle to the blob located in row iRow,, column zColumn, +** table zTable in database zDb. i.e. the same blob that would +** be selected by: +** +**
+**     SELECT zColumn FROM zDb.zTable WHERE rowid = iRow;
+** 
+** +** If the flags parameter is non-zero, the blob is opened for +** read and write access. If it is zero, the blob is opened for read +** access. +** +** On success, [SQLITE_OK] is returned and the new +** [sqlite3_blob | blob handle] is written to *ppBlob. +** Otherwise an error code is returned and +** any value written to *ppBlob should not be used by the caller. +** This function sets the database-handle error code and message +** accessible via [sqlite3_errcode()] and [sqlite3_errmsg()]. +*/ +int sqlite3_blob_open( + sqlite3*, + const char *zDb, + const char *zTable, + const char *zColumn, + sqlite_int64 iRow, + int flags, + sqlite3_blob **ppBlob +); + +/* +** CAPI3REF: Close A BLOB Handle +** +** Close an open [sqlite3_blob | blob handle]. +*/ +int sqlite3_blob_close(sqlite3_blob *); + +/* +** CAPI3REF: Return The Size Of An Open BLOB +** +** Return the size in bytes of the blob accessible via the open +** [sqlite3_blob | blob-handle] passed as an argument. +*/ +int sqlite3_blob_bytes(sqlite3_blob *); + +/* +** CAPI3REF: Read Data From A BLOB Incrementally +** +** This function is used to read data from an open +** [sqlite3_blob | blob-handle] into a caller supplied buffer. +** n bytes of data are copied into buffer +** z from the open blob, starting at offset iOffset. +** +** On success, SQLITE_OK is returned. Otherwise, an +** [SQLITE_ERROR | SQLite error code] or an +** [SQLITE_IOERR_READ | extended error code] is returned. +*/ +int sqlite3_blob_read(sqlite3_blob *, void *z, int n, int iOffset); + +/* +** CAPI3REF: Write Data Into A BLOB Incrementally +** +** This function is used to write data into an open +** [sqlite3_blob | blob-handle] from a user supplied buffer. +** n bytes of data are copied from the buffer +** pointed to by z into the open blob, starting at offset iOffset. +** +** If the [sqlite3_blob | blob-handle] passed as the first argument +** was not opened for writing (the flags parameter to [sqlite3_blob_open()] +*** was zero), this function returns [SQLITE_READONLY]. +** +** This function may only modify the contents of the blob, it is +** not possible to increase the size of a blob using this API. If +** offset iOffset is less than n bytes from the end of the blob, +** [SQLITE_ERROR] is returned and no data is written. +** +** On success, SQLITE_OK is returned. Otherwise, an +** [SQLITE_ERROR | SQLite error code] or an +** [SQLITE_IOERR_READ | extended error code] is returned. +*/ +int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset); + +/* +** Undo the hack that converts floating point types to integer for +** builds on processors without floating point support. +*/ +#ifdef SQLITE_OMIT_FLOATING_POINT +# undef double +#endif + +#ifdef __cplusplus +} /* End of the 'extern "C"' block */ +#endif +#endif diff --git a/extensions/sqlite/sqlite-source/sqlite3ext.h b/extensions/sqlite/sqlite-source/sqlite3ext.h new file mode 100644 index 00000000..ef253310 --- /dev/null +++ b/extensions/sqlite/sqlite-source/sqlite3ext.h @@ -0,0 +1,298 @@ +/* +** 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$ +*/ +#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. +** +** WARNING: In order to maintain backwards compatibility, add new +** interfaces to the end of this structure only. If you insert new +** interfaces in the middle of this structure, then older different +** versions of SQLite will not be able to load each others shared +** libraries! +*/ +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); + int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**); + int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**); + int (*clear_bindings)(sqlite3_stmt*); + int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,void (*xDestroy)(void *)); +}; + +/* +** 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_create_module_v2 sqlite3_api->create_module_v2 +#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_prepare_v2 sqlite3_api->prepare_v2 +#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2 +#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 +#define sqlite3_prepare_v2 sqlite3_api->prepare_v2 +#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2 +#define sqlite3_clear_bindings sqlite3_api->clear_bindings +#endif /* SQLITE_CORE */ + +#define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api; +#define SQLITE_EXTENSION_INIT2(v) sqlite3_api = v; + +#endif /* _SQLITE3EXT_H_ */ diff --git a/extensions/sqlite/sqlite-source/sqliteInt.h b/extensions/sqlite/sqlite-source/sqliteInt.h new file mode 100644 index 00000000..ee9a3c2f --- /dev/null +++ b/extensions/sqlite/sqlite-source/sqliteInt.h @@ -0,0 +1,2002 @@ +/* +** 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. +** +************************************************************************* +** Internal interface definitions for SQLite. +** +** @(#) $Id$ +*/ +#ifndef _SQLITEINT_H_ +#define _SQLITEINT_H_ +#include "sqliteLimit.h" + + +#if defined(SQLITE_TCL) || defined(TCLSH) +# include +#endif + +/* +** Many people are failing to set -DNDEBUG=1 when compiling SQLite. +** Setting NDEBUG makes the code smaller and run faster. So the following +** lines are added to automatically set NDEBUG unless the -DSQLITE_DEBUG=1 +** option is set. Thus NDEBUG becomes an opt-in rather than an opt-out +** feature. +*/ +#if !defined(NDEBUG) && !defined(SQLITE_DEBUG) +# define NDEBUG 1 +#endif + +/* +** These #defines should enable >2GB file support on Posix if the +** underlying operating system supports it. If the OS lacks +** large file support, or if the OS is windows, these should be no-ops. +** +** Large file support can be disabled using the -DSQLITE_DISABLE_LFS switch +** on the compiler command line. This is necessary if you are compiling +** on a recent machine (ex: RedHat 7.2) but you want your code to work +** on an older machine (ex: RedHat 6.0). If you compile on RedHat 7.2 +** without this option, LFS is enable. But LFS does not exist in the kernel +** in RedHat 6.0, so the code won't work. Hence, for maximum binary +** portability you should omit LFS. +** +** Similar is true for MacOS. LFS is only supported on MacOS 9 and later. +*/ +#ifndef SQLITE_DISABLE_LFS +# define _LARGE_FILE 1 +# ifndef _FILE_OFFSET_BITS +# define _FILE_OFFSET_BITS 64 +# endif +# define _LARGEFILE_SOURCE 1 +#endif + +#include "sqlite3.h" +#include "hash.h" +#include "parse.h" +#include +#include +#include +#include +#include + +#define sqlite3_isnan(X) ((X)!=(X)) + +/* +** If compiling for a processor that lacks floating point support, +** substitute integer for floating-point +*/ +#ifdef SQLITE_OMIT_FLOATING_POINT +# define double sqlite_int64 +# define LONGDOUBLE_TYPE sqlite_int64 +# ifndef SQLITE_BIG_DBL +# define SQLITE_BIG_DBL (0x7fffffffffffffff) +# endif +# define SQLITE_OMIT_DATETIME_FUNCS 1 +# define SQLITE_OMIT_TRACE 1 +# undef SQLITE_MIXED_ENDIAN_64BIT_FLOAT +#endif +#ifndef SQLITE_BIG_DBL +# define SQLITE_BIG_DBL (1e99) +#endif + +/* +** OMIT_TEMPDB is set to 1 if SQLITE_OMIT_TEMPDB is defined, or 0 +** afterward. Having this macro allows us to cause the C compiler +** to omit code used by TEMP tables without messy #ifndef statements. +*/ +#ifdef SQLITE_OMIT_TEMPDB +#define OMIT_TEMPDB 1 +#else +#define OMIT_TEMPDB 0 +#endif + +/* +** If the following macro is set to 1, then NULL values are considered +** distinct when determining whether or not two entries are the same +** in a UNIQUE index. This is the way PostgreSQL, Oracle, DB2, MySQL, +** OCELOT, and Firebird all work. The SQL92 spec explicitly says this +** is the way things are suppose to work. +** +** If the following macro is set to 0, the NULLs are indistinct for +** a UNIQUE index. In this mode, you can only have a single NULL entry +** for a column declared UNIQUE. This is the way Informix and SQL Server +** work. +*/ +#define NULL_DISTINCT_FOR_UNIQUE 1 + +/* +** The "file format" number is an integer that is incremented whenever +** the VDBE-level file format changes. The following macros define the +** the default file format for new databases and the maximum file format +** that the library can read. +*/ +#define SQLITE_MAX_FILE_FORMAT 4 +#ifndef SQLITE_DEFAULT_FILE_FORMAT +# define SQLITE_DEFAULT_FILE_FORMAT 1 +#endif + +/* +** Provide a default value for TEMP_STORE in case it is not specified +** on the command-line +*/ +#ifndef TEMP_STORE +# define TEMP_STORE 1 +#endif + +/* +** GCC does not define the offsetof() macro so we'll have to do it +** ourselves. +*/ +#ifndef offsetof +#define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD)) +#endif + +/* +** Check to see if this machine uses EBCDIC. (Yes, believe it or +** not, there are still machines out there that use EBCDIC.) +*/ +#if 'A' == '\301' +# define SQLITE_EBCDIC 1 +#else +# define SQLITE_ASCII 1 +#endif + +/* +** Integers of known sizes. These typedefs might change for architectures +** where the sizes very. Preprocessor macros are available so that the +** types can be conveniently redefined at compile-type. Like this: +** +** cc '-DUINTPTR_TYPE=long long int' ... +*/ +#ifndef UINT32_TYPE +# define UINT32_TYPE unsigned int +#endif +#ifndef UINT16_TYPE +# define UINT16_TYPE unsigned short int +#endif +#ifndef INT16_TYPE +# define INT16_TYPE short int +#endif +#ifndef UINT8_TYPE +# define UINT8_TYPE unsigned char +#endif +#ifndef INT8_TYPE +# define INT8_TYPE signed char +#endif +#ifndef LONGDOUBLE_TYPE +# define LONGDOUBLE_TYPE long double +#endif +typedef sqlite_int64 i64; /* 8-byte signed integer */ +typedef sqlite_uint64 u64; /* 8-byte unsigned integer */ +typedef UINT32_TYPE u32; /* 4-byte unsigned integer */ +typedef UINT16_TYPE u16; /* 2-byte unsigned integer */ +typedef INT16_TYPE i16; /* 2-byte signed integer */ +typedef UINT8_TYPE u8; /* 1-byte unsigned integer */ +typedef UINT8_TYPE i8; /* 1-byte signed integer */ + +/* +** Macros to determine whether the machine is big or little endian, +** evaluated at runtime. +*/ +extern const int sqlite3one; +#if defined(i386) || defined(__i386__) || defined(_M_IX86) +# define SQLITE_BIGENDIAN 0 +# define SQLITE_LITTLEENDIAN 1 +# define SQLITE_UTF16NATIVE SQLITE_UTF16LE +#else +# define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0) +# define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1) +# define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE) +#endif + +/* +** An instance of the following structure is used to store the busy-handler +** callback for a given sqlite handle. +** +** The sqlite.busyHandler member of the sqlite struct contains the busy +** callback for the database handle. Each pager opened via the sqlite +** handle is passed a pointer to sqlite.busyHandler. The busy-handler +** callback is currently invoked only from within pager.c. +*/ +typedef struct BusyHandler BusyHandler; +struct BusyHandler { + int (*xFunc)(void *,int); /* The busy callback */ + void *pArg; /* First arg to busy callback */ + int nBusy; /* Incremented with each busy call */ +}; + +/* +** Defer sourcing vdbe.h and btree.h until after the "u8" and +** "BusyHandler typedefs. +*/ +#include "vdbe.h" +#include "btree.h" +#include "pager.h" + +#ifdef SQLITE_MEMDEBUG +/* +** The following global variables are used for testing and debugging +** only. They only work if SQLITE_MEMDEBUG is defined. +*/ +extern int sqlite3_nMalloc; /* Number of sqliteMalloc() calls */ +extern int sqlite3_nFree; /* Number of sqliteFree() calls */ +extern int sqlite3_iMallocFail; /* Fail sqliteMalloc() after this many calls */ +extern int sqlite3_iMallocReset; /* Set iMallocFail to this when it reaches 0 */ + +extern void *sqlite3_pFirst; /* Pointer to linked list of allocations */ +extern int sqlite3_nMaxAlloc; /* High water mark of ThreadData.nAlloc */ +extern int sqlite3_mallocDisallowed; /* assert() in sqlite3Malloc() if set */ +extern int sqlite3_isFail; /* True if all malloc calls should fail */ +extern const char *sqlite3_zFile; /* Filename to associate debug info with */ +extern int sqlite3_iLine; /* Line number for debug info */ + +#define ENTER_MALLOC (sqlite3_zFile = __FILE__, sqlite3_iLine = __LINE__) +#define sqliteMalloc(x) (ENTER_MALLOC, sqlite3Malloc(x,1)) +#define sqliteMallocRaw(x) (ENTER_MALLOC, sqlite3MallocRaw(x,1)) +#define sqliteRealloc(x,y) (ENTER_MALLOC, sqlite3Realloc(x,y)) +#define sqliteStrDup(x) (ENTER_MALLOC, sqlite3StrDup(x)) +#define sqliteStrNDup(x,y) (ENTER_MALLOC, sqlite3StrNDup(x,y)) +#define sqliteReallocOrFree(x,y) (ENTER_MALLOC, sqlite3ReallocOrFree(x,y)) + +#else + +#define ENTER_MALLOC 0 +#define sqliteMalloc(x) sqlite3Malloc(x,1) +#define sqliteMallocRaw(x) sqlite3MallocRaw(x,1) +#define sqliteRealloc(x,y) sqlite3Realloc(x,y) +#define sqliteStrDup(x) sqlite3StrDup(x) +#define sqliteStrNDup(x,y) sqlite3StrNDup(x,y) +#define sqliteReallocOrFree(x,y) sqlite3ReallocOrFree(x,y) + +#endif + +/* Variable sqlite3_mallocHasFailed is set to true after a malloc() +** failure occurs. +** +** The sqlite3MallocFailed() macro returns true if a malloc has failed +** in this thread since the last call to sqlite3ApiExit(), or false +** otherwise. +*/ +extern int sqlite3_mallocHasFailed; +#define sqlite3MallocFailed() (sqlite3_mallocHasFailed && sqlite3OsInMutex(1)) + +#define sqliteFree(x) sqlite3FreeX(x) +#define sqliteAllocSize(x) sqlite3AllocSize(x) + +/* +** An instance of this structure might be allocated to store information +** specific to a single thread. +*/ +struct ThreadData { + int dummy; /* So that this structure is never empty */ + +#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT + int nSoftHeapLimit; /* Suggested max mem allocation. No limit if <0 */ + int nAlloc; /* Number of bytes currently allocated */ + Pager *pPager; /* Linked list of all pagers in this thread */ +#endif + +#ifndef SQLITE_OMIT_SHARED_CACHE + u8 useSharedData; /* True if shared pagers and schemas are enabled */ + BtShared *pBtree; /* Linked list of all currently open BTrees */ +#endif +}; + +/* +** Name of the master database table. The master database table +** is a special table that holds the names and attributes of all +** user tables and indices. +*/ +#define MASTER_NAME "sqlite_master" +#define TEMP_MASTER_NAME "sqlite_temp_master" + +/* +** The root-page of the master database table. +*/ +#define MASTER_ROOT 1 + +/* +** The name of the schema table. +*/ +#define SCHEMA_TABLE(x) ((!OMIT_TEMPDB)&&(x==1)?TEMP_MASTER_NAME:MASTER_NAME) + +/* +** A convenience macro that returns the number of elements in +** an array. +*/ +#define ArraySize(X) (sizeof(X)/sizeof(X[0])) + +/* +** Forward references to structures +*/ +typedef struct AggInfo AggInfo; +typedef struct AuthContext AuthContext; +typedef struct CollSeq CollSeq; +typedef struct Column Column; +typedef struct Db Db; +typedef struct Schema Schema; +typedef struct Expr Expr; +typedef struct ExprList ExprList; +typedef struct FKey FKey; +typedef struct FuncDef FuncDef; +typedef struct IdList IdList; +typedef struct Index Index; +typedef struct KeyClass KeyClass; +typedef struct KeyInfo KeyInfo; +typedef struct Module Module; +typedef struct NameContext NameContext; +typedef struct Parse Parse; +typedef struct Select Select; +typedef struct SrcList SrcList; +typedef struct ThreadData ThreadData; +typedef struct Table Table; +typedef struct TableLock TableLock; +typedef struct Token Token; +typedef struct TriggerStack TriggerStack; +typedef struct TriggerStep TriggerStep; +typedef struct Trigger Trigger; +typedef struct WhereInfo WhereInfo; +typedef struct WhereLevel WhereLevel; + +#include "os.h" + +/* +** Each database file to be accessed by the system is an instance +** of the following structure. There are normally two of these structures +** in the sqlite.aDb[] array. aDb[0] is the main database file and +** aDb[1] is the database file used to hold temporary tables. Additional +** databases may be attached. +*/ +struct Db { + char *zName; /* Name of this database */ + Btree *pBt; /* The B*Tree structure for this database file */ + u8 inTrans; /* 0: not writable. 1: Transaction. 2: Checkpoint */ + u8 safety_level; /* How aggressive at synching data to disk */ + void *pAux; /* Auxiliary data. Usually NULL */ + void (*xFreeAux)(void*); /* Routine to free pAux */ + Schema *pSchema; /* Pointer to database schema (possibly shared) */ +}; + +/* +** An instance of the following structure stores a database schema. +** +** If there are no virtual tables configured in this schema, the +** Schema.db variable is set to NULL. After the first virtual table +** has been added, it is set to point to the database connection +** used to create the connection. Once a virtual table has been +** added to the Schema structure and the Schema.db variable populated, +** only that database connection may use the Schema to prepare +** statements. +*/ +struct Schema { + int schema_cookie; /* Database schema version number for this file */ + Hash tblHash; /* All tables indexed by name */ + Hash idxHash; /* All (named) indices indexed by name */ + Hash trigHash; /* All triggers indexed by name */ + Hash aFKey; /* Foreign keys indexed by to-table */ + Table *pSeqTab; /* The sqlite_sequence table used by AUTOINCREMENT */ + u8 file_format; /* Schema format version for this file */ + u8 enc; /* Text encoding used by this database */ + u16 flags; /* Flags associated with this schema */ + int cache_size; /* Number of pages to use in the cache */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + sqlite3 *db; /* "Owner" connection. See comment above */ +#endif +}; + +/* +** These macros can be used to test, set, or clear bits in the +** Db.flags field. +*/ +#define DbHasProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))==(P)) +#define DbHasAnyProperty(D,I,P) (((D)->aDb[I].pSchema->flags&(P))!=0) +#define DbSetProperty(D,I,P) (D)->aDb[I].pSchema->flags|=(P) +#define DbClearProperty(D,I,P) (D)->aDb[I].pSchema->flags&=~(P) + +/* +** Allowed values for the DB.flags field. +** +** The DB_SchemaLoaded flag is set after the database schema has been +** read into internal hash tables. +** +** DB_UnresetViews means that one or more views have column names that +** have been filled out. If the schema changes, these column names might +** changes and so the view will need to be reset. +*/ +#define DB_SchemaLoaded 0x0001 /* The schema has been loaded */ +#define DB_UnresetViews 0x0002 /* Some views have defined column names */ +#define DB_Empty 0x0004 /* The file is empty (length 0 bytes) */ + + +/* +** Each database is an instance of the following structure. +** +** The sqlite.lastRowid records the last insert rowid generated by an +** insert statement. Inserts on views do not affect its value. Each +** trigger has its own context, so that lastRowid can be updated inside +** triggers as usual. The previous value will be restored once the trigger +** exits. Upon entering a before or instead of trigger, lastRowid is no +** longer (since after version 2.8.12) reset to -1. +** +** The sqlite.nChange does not count changes within triggers and keeps no +** context. It is reset at start of sqlite3_exec. +** The sqlite.lsChange represents the number of changes made by the last +** insert, update, or delete statement. It remains constant throughout the +** length of a statement and is then updated by OP_SetCounts. It keeps a +** context stack just like lastRowid so that the count of changes +** within a trigger is not seen outside the trigger. Changes to views do not +** affect the value of lsChange. +** The sqlite.csChange keeps track of the number of current changes (since +** the last statement) and is used to update sqlite_lsChange. +** +** The member variables sqlite.errCode, sqlite.zErrMsg and sqlite.zErrMsg16 +** store the most recent error code and, if applicable, string. The +** internal function sqlite3Error() is used to set these variables +** consistently. +*/ +struct sqlite3 { + int nDb; /* Number of backends currently in use */ + Db *aDb; /* All backends */ + int flags; /* Miscellanous flags. See below */ + int errCode; /* Most recent error code (SQLITE_*) */ + int errMask; /* & result codes with this before returning */ + u8 autoCommit; /* The auto-commit flag. */ + u8 temp_store; /* 1: file 2: memory 0: default */ + int nTable; /* Number of tables in the database */ + CollSeq *pDfltColl; /* The default collating sequence (BINARY) */ + i64 lastRowid; /* ROWID of most recent insert (see above) */ + i64 priorNewRowid; /* Last randomly generated ROWID */ + int magic; /* Magic number for detect library misuse */ + int nChange; /* Value returned by sqlite3_changes() */ + int nTotalChange; /* Value returned by sqlite3_total_changes() */ + struct sqlite3InitInfo { /* Information used during initialization */ + int iDb; /* When back is being initialized */ + int newTnum; /* Rootpage of table being initialized */ + u8 busy; /* TRUE if currently initializing */ + } init; + int nExtension; /* Number of loaded extensions */ + void **aExtension; /* Array of shared libraray handles */ + struct Vdbe *pVdbe; /* List of active virtual machines */ + int activeVdbeCnt; /* Number of vdbes currently executing */ + void (*xTrace)(void*,const char*); /* Trace function */ + void *pTraceArg; /* Argument to the trace function */ + void (*xProfile)(void*,const char*,u64); /* Profiling function */ + void *pProfileArg; /* Argument to profile function */ + void *pCommitArg; /* Argument to xCommitCallback() */ + int (*xCommitCallback)(void*); /* Invoked at every commit. */ + void *pRollbackArg; /* Argument to xRollbackCallback() */ + void (*xRollbackCallback)(void*); /* Invoked at every commit. */ + void *pUpdateArg; + void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64); + void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*); + void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*); + void *pCollNeededArg; + sqlite3_value *pErr; /* Most recent error message */ + char *zErrMsg; /* Most recent error message (UTF-8 encoded) */ + char *zErrMsg16; /* Most recent error message (UTF-16 encoded) */ + union { + int isInterrupted; /* True if sqlite3_interrupt has been called */ + double notUsed1; /* Spacer */ + } u1; +#ifndef SQLITE_OMIT_AUTHORIZATION + int (*xAuth)(void*,int,const char*,const char*,const char*,const char*); + /* Access authorization function */ + void *pAuthArg; /* 1st argument to the access auth function */ +#endif +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK + int (*xProgress)(void *); /* The progress callback */ + void *pProgressArg; /* Argument to the progress callback */ + int nProgressOps; /* Number of opcodes for progress callback */ +#endif +#ifndef SQLITE_OMIT_VIRTUALTABLE + Hash aModule; /* populated by sqlite3_create_module() */ + Table *pVTab; /* vtab with active Connect/Create method */ + sqlite3_vtab **aVTrans; /* Virtual tables with open transactions */ + int nVTrans; /* Allocated size of aVTrans */ +#endif + Hash aFunc; /* All functions that can be in SQL exprs */ + Hash aCollSeq; /* All collating sequences */ + BusyHandler busyHandler; /* Busy callback */ + int busyTimeout; /* Busy handler timeout, in msec */ + Db aDbStatic[2]; /* Static space for the 2 default backends */ +#ifdef SQLITE_SSE + sqlite3_stmt *pFetch; /* Used by SSE to fetch stored statements */ +#endif + u8 dfltLockMode; /* Default locking-mode for attached dbs */ +}; + +/* +** A macro to discover the encoding of a database. +*/ +#define ENC(db) ((db)->aDb[0].pSchema->enc) + +/* +** Possible values for the sqlite.flags and or Db.flags fields. +** +** On sqlite.flags, the SQLITE_InTrans value means that we have +** executed a BEGIN. On Db.flags, SQLITE_InTrans means a statement +** transaction is active on that particular database file. +*/ +#define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */ +#define SQLITE_InTrans 0x00000008 /* True if in a transaction */ +#define SQLITE_InternChanges 0x00000010 /* Uncommitted Hash table changes */ +#define SQLITE_FullColNames 0x00000020 /* Show full column names on SELECT */ +#define SQLITE_ShortColNames 0x00000040 /* Show short columns names */ +#define SQLITE_CountRows 0x00000080 /* Count rows changed by INSERT, */ + /* DELETE, or UPDATE and return */ + /* the count using a callback. */ +#define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */ + /* result set is empty */ +#define SQLITE_SqlTrace 0x00000200 /* Debug print SQL as it executes */ +#define SQLITE_VdbeListing 0x00000400 /* Debug listings of VDBE programs */ +#define SQLITE_WriteSchema 0x00000800 /* OK to update SQLITE_MASTER */ +#define SQLITE_NoReadlock 0x00001000 /* Readlocks are omitted when + ** accessing read-only databases */ +#define SQLITE_IgnoreChecks 0x00002000 /* Do not enforce check constraints */ +#define SQLITE_ReadUncommitted 0x00004000 /* For shared-cache mode */ +#define SQLITE_LegacyFileFmt 0x00008000 /* Create new databases in format 1 */ +#define SQLITE_FullFSync 0x00010000 /* Use full fsync on the backend */ +#define SQLITE_LoadExtension 0x00020000 /* Enable load_extension */ + +#define SQLITE_RecoveryMode 0x00040000 /* Ignore schema errors */ + +/* +** Possible values for the sqlite.magic field. +** The numbers are obtained at random and have no special meaning, other +** than being distinct from one another. +*/ +#define SQLITE_MAGIC_OPEN 0xa029a697 /* Database is open */ +#define SQLITE_MAGIC_CLOSED 0x9f3c2d33 /* Database is closed */ +#define SQLITE_MAGIC_BUSY 0xf03b7906 /* Database currently in use */ +#define SQLITE_MAGIC_ERROR 0xb5357930 /* An SQLITE_MISUSE error occurred */ + +/* +** Each SQL function is defined by an instance of the following +** structure. A pointer to this structure is stored in the sqlite.aFunc +** hash table. When multiple functions have the same name, the hash table +** points to a linked list of these structures. +*/ +struct FuncDef { + i16 nArg; /* Number of arguments. -1 means unlimited */ + u8 iPrefEnc; /* Preferred text encoding (SQLITE_UTF8, 16LE, 16BE) */ + u8 needCollSeq; /* True if sqlite3GetFuncCollSeq() might be called */ + u8 flags; /* Some combination of SQLITE_FUNC_* */ + void *pUserData; /* User data parameter */ + FuncDef *pNext; /* Next function with same name */ + void (*xFunc)(sqlite3_context*,int,sqlite3_value**); /* Regular function */ + void (*xStep)(sqlite3_context*,int,sqlite3_value**); /* Aggregate step */ + void (*xFinalize)(sqlite3_context*); /* Aggregate finializer */ + char zName[1]; /* SQL name of the function. MUST BE LAST */ +}; + +/* +** Each SQLite module (virtual table definition) is defined by an +** instance of the following structure, stored in the sqlite3.aModule +** hash table. +*/ +struct Module { + const sqlite3_module *pModule; /* Callback pointers */ + const char *zName; /* Name passed to create_module() */ + void *pAux; /* pAux passed to create_module() */ + void (*xDestroy)(void *); /* Module destructor function */ +}; + +/* +** Possible values for FuncDef.flags +*/ +#define SQLITE_FUNC_LIKE 0x01 /* Candidate for the LIKE optimization */ +#define SQLITE_FUNC_CASE 0x02 /* Case-sensitive LIKE-type function */ +#define SQLITE_FUNC_EPHEM 0x04 /* Ephermeral. Delete with VDBE */ + +/* +** information about each column of an SQL table is held in an instance +** of this structure. +*/ +struct Column { + char *zName; /* Name of this column */ + Expr *pDflt; /* Default value of this column */ + char *zType; /* Data type for this column */ + char *zColl; /* Collating sequence. If NULL, use the default */ + u8 notNull; /* True if there is a NOT NULL constraint */ + u8 isPrimKey; /* True if this column is part of the PRIMARY KEY */ + char affinity; /* One of the SQLITE_AFF_... values */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + u8 isHidden; /* True if this column is 'hidden' */ +#endif +}; + +/* +** A "Collating Sequence" is defined by an instance of the following +** structure. Conceptually, a collating sequence consists of a name and +** a comparison routine that defines the order of that sequence. +** +** There may two seperate implementations of the collation function, one +** that processes text in UTF-8 encoding (CollSeq.xCmp) and another that +** processes text encoded in UTF-16 (CollSeq.xCmp16), using the machine +** native byte order. When a collation sequence is invoked, SQLite selects +** the version that will require the least expensive encoding +** translations, if any. +** +** The CollSeq.pUser member variable is an extra parameter that passed in +** as the first argument to the UTF-8 comparison function, xCmp. +** CollSeq.pUser16 is the equivalent for the UTF-16 comparison function, +** xCmp16. +** +** If both CollSeq.xCmp and CollSeq.xCmp16 are NULL, it means that the +** collating sequence is undefined. Indices built on an undefined +** collating sequence may not be read or written. +*/ +struct CollSeq { + char *zName; /* Name of the collating sequence, UTF-8 encoded */ + u8 enc; /* Text encoding handled by xCmp() */ + u8 type; /* One of the SQLITE_COLL_... values below */ + void *pUser; /* First argument to xCmp() */ + int (*xCmp)(void*,int, const void*, int, const void*); + void (*xDel)(void*); /* Destructor for pUser */ +}; + +/* +** Allowed values of CollSeq flags: +*/ +#define SQLITE_COLL_BINARY 1 /* The default memcmp() collating sequence */ +#define SQLITE_COLL_NOCASE 2 /* The built-in NOCASE collating sequence */ +#define SQLITE_COLL_REVERSE 3 /* The built-in REVERSE collating sequence */ +#define SQLITE_COLL_USER 0 /* Any other user-defined collating sequence */ + +/* +** A sort order can be either ASC or DESC. +*/ +#define SQLITE_SO_ASC 0 /* Sort in ascending order */ +#define SQLITE_SO_DESC 1 /* Sort in ascending order */ + +/* +** Column affinity types. +** +** These used to have mnemonic name like 'i' for SQLITE_AFF_INTEGER and +** 't' for SQLITE_AFF_TEXT. But we can save a little space and improve +** the speed a little by number the values consecutively. +** +** But rather than start with 0 or 1, we begin with 'a'. That way, +** when multiple affinity types are concatenated into a string and +** used as the P3 operand, they will be more readable. +** +** Note also that the numeric types are grouped together so that testing +** for a numeric type is a single comparison. +*/ +#define SQLITE_AFF_TEXT 'a' +#define SQLITE_AFF_NONE 'b' +#define SQLITE_AFF_NUMERIC 'c' +#define SQLITE_AFF_INTEGER 'd' +#define SQLITE_AFF_REAL 'e' + +#define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC) + +/* +** Each SQL table is represented in memory by an instance of the +** following structure. +** +** Table.zName is the name of the table. The case of the original +** CREATE TABLE statement is stored, but case is not significant for +** comparisons. +** +** Table.nCol is the number of columns in this table. Table.aCol is a +** pointer to an array of Column structures, one for each column. +** +** If the table has an INTEGER PRIMARY KEY, then Table.iPKey is the index of +** the column that is that key. Otherwise Table.iPKey is negative. Note +** that the datatype of the PRIMARY KEY must be INTEGER for this field to +** be set. An INTEGER PRIMARY KEY is used as the rowid for each row of +** the table. If a table has no INTEGER PRIMARY KEY, then a random rowid +** is generated for each row of the table. Table.hasPrimKey is true if +** the table has any PRIMARY KEY, INTEGER or otherwise. +** +** Table.tnum is the page number for the root BTree page of the table in the +** database file. If Table.iDb is the index of the database table backend +** in sqlite.aDb[]. 0 is for the main database and 1 is for the file that +** holds temporary tables and indices. If Table.isEphem +** is true, then the table is stored in a file that is automatically deleted +** when the VDBE cursor to the table is closed. In this case Table.tnum +** refers VDBE cursor number that holds the table open, not to the root +** page number. Transient tables are used to hold the results of a +** sub-query that appears instead of a real table name in the FROM clause +** of a SELECT statement. +*/ +struct Table { + char *zName; /* Name of the table */ + int nCol; /* Number of columns in this table */ + Column *aCol; /* Information about each column */ + int iPKey; /* If not less then 0, use aCol[iPKey] as the primary key */ + Index *pIndex; /* List of SQL indexes on this table. */ + int tnum; /* Root BTree node for this table (see note above) */ + Select *pSelect; /* NULL for tables. Points to definition if a view. */ + int nRef; /* Number of pointers to this Table */ + Trigger *pTrigger; /* List of SQL triggers on this table */ + FKey *pFKey; /* Linked list of all foreign keys in this table */ + char *zColAff; /* String defining the affinity of each column */ +#ifndef SQLITE_OMIT_CHECK + Expr *pCheck; /* The AND of all CHECK constraints */ +#endif +#ifndef SQLITE_OMIT_ALTERTABLE + int addColOffset; /* Offset in CREATE TABLE statement to add a new column */ +#endif + u8 readOnly; /* True if this table should not be written by the user */ + u8 isEphem; /* True if created using OP_OpenEphermeral */ + u8 hasPrimKey; /* True if there exists a primary key */ + u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ + u8 autoInc; /* True if the integer primary key is autoincrement */ +#ifndef SQLITE_OMIT_VIRTUALTABLE + u8 isVirtual; /* True if this is a virtual table */ + u8 isCommit; /* True once the CREATE TABLE has been committed */ + Module *pMod; /* Pointer to the implementation of the module */ + sqlite3_vtab *pVtab; /* Pointer to the module instance */ + int nModuleArg; /* Number of arguments to the module */ + char **azModuleArg; /* Text of all module args. [0] is module name */ +#endif + Schema *pSchema; +}; + +/* +** Test to see whether or not a table is a virtual table. This is +** done as a macro so that it will be optimized out when virtual +** table support is omitted from the build. +*/ +#ifndef SQLITE_OMIT_VIRTUALTABLE +# define IsVirtual(X) ((X)->isVirtual) +# define IsHiddenColumn(X) ((X)->isHidden) +#else +# define IsVirtual(X) 0 +# define IsHiddenColumn(X) 0 +#endif + +/* +** Each foreign key constraint is an instance of the following structure. +** +** A foreign key is associated with two tables. The "from" table is +** the table that contains the REFERENCES clause that creates the foreign +** key. The "to" table is the table that is named in the REFERENCES clause. +** Consider this example: +** +** CREATE TABLE ex1( +** a INTEGER PRIMARY KEY, +** b INTEGER CONSTRAINT fk1 REFERENCES ex2(x) +** ); +** +** For foreign key "fk1", the from-table is "ex1" and the to-table is "ex2". +** +** Each REFERENCES clause generates an instance of the following structure +** which is attached to the from-table. The to-table need not exist when +** the from-table is created. The existance of the to-table is not checked +** until an attempt is made to insert data into the from-table. +** +** The sqlite.aFKey hash table stores pointers to this structure +** given the name of a to-table. For each to-table, all foreign keys +** associated with that table are on a linked list using the FKey.pNextTo +** field. +*/ +struct FKey { + Table *pFrom; /* The table that constains the REFERENCES clause */ + FKey *pNextFrom; /* Next foreign key in pFrom */ + char *zTo; /* Name of table that the key points to */ + FKey *pNextTo; /* Next foreign key that points to zTo */ + int nCol; /* Number of columns in this key */ + struct sColMap { /* Mapping of columns in pFrom to columns in zTo */ + int iFrom; /* Index of column in pFrom */ + char *zCol; /* Name of column in zTo. If 0 use PRIMARY KEY */ + } *aCol; /* One entry for each of nCol column s */ + u8 isDeferred; /* True if constraint checking is deferred till COMMIT */ + u8 updateConf; /* How to resolve conflicts that occur on UPDATE */ + u8 deleteConf; /* How to resolve conflicts that occur on DELETE */ + u8 insertConf; /* How to resolve conflicts that occur on INSERT */ +}; + +/* +** SQLite supports many different ways to resolve a contraint +** error. ROLLBACK processing means that a constraint violation +** causes the operation in process to fail and for the current transaction +** to be rolled back. ABORT processing means the operation in process +** fails and any prior changes from that one operation are backed out, +** but the transaction is not rolled back. FAIL processing means that +** the operation in progress stops and returns an error code. But prior +** changes due to the same operation are not backed out and no rollback +** occurs. IGNORE means that the particular row that caused the constraint +** error is not inserted or updated. Processing continues and no error +** is returned. REPLACE means that preexisting database rows that caused +** a UNIQUE constraint violation are removed so that the new insert or +** update can proceed. Processing continues and no error is reported. +** +** RESTRICT, SETNULL, and CASCADE actions apply only to foreign keys. +** RESTRICT is the same as ABORT for IMMEDIATE foreign keys and the +** same as ROLLBACK for DEFERRED keys. SETNULL means that the foreign +** key is set to NULL. CASCADE means that a DELETE or UPDATE of the +** referenced table row is propagated into the row that holds the +** foreign key. +** +** The following symbolic values are used to record which type +** of action to take. +*/ +#define OE_None 0 /* There is no constraint to check */ +#define OE_Rollback 1 /* Fail the operation and rollback the transaction */ +#define OE_Abort 2 /* Back out changes but do no rollback transaction */ +#define OE_Fail 3 /* Stop the operation but leave all prior changes */ +#define OE_Ignore 4 /* Ignore the error. Do not do the INSERT or UPDATE */ +#define OE_Replace 5 /* Delete existing record, then do INSERT or UPDATE */ + +#define OE_Restrict 6 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */ +#define OE_SetNull 7 /* Set the foreign key value to NULL */ +#define OE_SetDflt 8 /* Set the foreign key value to its default */ +#define OE_Cascade 9 /* Cascade the changes */ + +#define OE_Default 99 /* Do whatever the default action is */ + + +/* +** An instance of the following structure is passed as the first +** argument to sqlite3VdbeKeyCompare and is used to control the +** comparison of the two index keys. +** +** If the KeyInfo.incrKey value is true and the comparison would +** otherwise be equal, then return a result as if the second key +** were larger. +*/ +struct KeyInfo { + u8 enc; /* Text encoding - one of the TEXT_Utf* values */ + u8 incrKey; /* Increase 2nd key by epsilon before comparison */ + int nField; /* Number of entries in aColl[] */ + u8 *aSortOrder; /* If defined an aSortOrder[i] is true, sort DESC */ + CollSeq *aColl[1]; /* Collating sequence for each term of the key */ +}; + +/* +** Each SQL index is represented in memory by an +** instance of the following structure. +** +** The columns of the table that are to be indexed are described +** by the aiColumn[] field of this structure. For example, suppose +** we have the following table and index: +** +** CREATE TABLE Ex1(c1 int, c2 int, c3 text); +** CREATE INDEX Ex2 ON Ex1(c3,c1); +** +** In the Table structure describing Ex1, nCol==3 because there are +** three columns in the table. In the Index structure describing +** Ex2, nColumn==2 since 2 of the 3 columns of Ex1 are indexed. +** The value of aiColumn is {2, 0}. aiColumn[0]==2 because the +** first column to be indexed (c3) has an index of 2 in Ex1.aCol[]. +** The second column to be indexed (c1) has an index of 0 in +** Ex1.aCol[], hence Ex2.aiColumn[1]==0. +** +** The Index.onError field determines whether or not the indexed columns +** must be unique and what to do if they are not. When Index.onError=OE_None, +** it means this is not a unique index. Otherwise it is a unique index +** and the value of Index.onError indicate the which conflict resolution +** algorithm to employ whenever an attempt is made to insert a non-unique +** element. +*/ +struct Index { + char *zName; /* Name of this index */ + int nColumn; /* Number of columns in the table used by this index */ + int *aiColumn; /* Which columns are used by this index. 1st is 0 */ + unsigned *aiRowEst; /* Result of ANALYZE: Est. rows selected by each column */ + Table *pTable; /* The SQL table being indexed */ + int tnum; /* Page containing root of this index in database file */ + u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ + u8 autoIndex; /* True if is automatically created (ex: by UNIQUE) */ + char *zColAff; /* String defining the affinity of each column */ + Index *pNext; /* The next index associated with the same table */ + Schema *pSchema; /* Schema containing this index */ + u8 *aSortOrder; /* Array of size Index.nColumn. True==DESC, False==ASC */ + char **azColl; /* Array of collation sequence names for index */ +}; + +/* +** Each token coming out of the lexer is an instance of +** this structure. Tokens are also used as part of an expression. +** +** Note if Token.z==0 then Token.dyn and Token.n are undefined and +** may contain random values. Do not make any assuptions about Token.dyn +** and Token.n when Token.z==0. +*/ +struct Token { + const unsigned char *z; /* Text of the token. Not NULL-terminated! */ + unsigned dyn : 1; /* True for malloced memory, false for static */ + unsigned n : 31; /* Number of characters in this token */ +}; + +/* +** An instance of this structure contains information needed to generate +** code for a SELECT that contains aggregate functions. +** +** If Expr.op==TK_AGG_COLUMN or TK_AGG_FUNCTION then Expr.pAggInfo is a +** pointer to this structure. The Expr.iColumn field is the index in +** AggInfo.aCol[] or AggInfo.aFunc[] of information needed to generate +** code for that node. +** +** AggInfo.pGroupBy and AggInfo.aFunc.pExpr point to fields within the +** original Select structure that describes the SELECT statement. These +** fields do not need to be freed when deallocating the AggInfo structure. +*/ +struct AggInfo { + u8 directMode; /* Direct rendering mode means take data directly + ** from source tables rather than from accumulators */ + u8 useSortingIdx; /* In direct mode, reference the sorting index rather + ** than the source table */ + int sortingIdx; /* Cursor number of the sorting index */ + ExprList *pGroupBy; /* The group by clause */ + int nSortingColumn; /* Number of columns in the sorting index */ + struct AggInfo_col { /* For each column used in source tables */ + Table *pTab; /* Source table */ + int iTable; /* Cursor number of the source table */ + int iColumn; /* Column number within the source table */ + int iSorterColumn; /* Column number in the sorting index */ + int iMem; /* Memory location that acts as accumulator */ + Expr *pExpr; /* The original expression */ + } *aCol; + int nColumn; /* Number of used entries in aCol[] */ + int nColumnAlloc; /* Number of slots allocated for aCol[] */ + int nAccumulator; /* Number of columns that show through to the output. + ** Additional columns are used only as parameters to + ** aggregate functions */ + struct AggInfo_func { /* For each aggregate function */ + Expr *pExpr; /* Expression encoding the function */ + FuncDef *pFunc; /* The aggregate function implementation */ + int iMem; /* Memory location that acts as accumulator */ + int iDistinct; /* Ephermeral table used to enforce DISTINCT */ + } *aFunc; + int nFunc; /* Number of entries in aFunc[] */ + int nFuncAlloc; /* Number of slots allocated for aFunc[] */ +}; + +/* +** Each node of an expression in the parse tree is an instance +** of this structure. +** +** Expr.op is the opcode. The integer parser token codes are reused +** as opcodes here. For example, the parser defines TK_GE to be an integer +** code representing the ">=" operator. This same integer code is reused +** to represent the greater-than-or-equal-to operator in the expression +** tree. +** +** Expr.pRight and Expr.pLeft are subexpressions. Expr.pList is a list +** of argument if the expression is a function. +** +** Expr.token is the operator token for this node. For some expressions +** that have subexpressions, Expr.token can be the complete text that gave +** rise to the Expr. In the latter case, the token is marked as being +** a compound token. +** +** An expression of the form ID or ID.ID refers to a column in a table. +** For such expressions, Expr.op is set to TK_COLUMN and Expr.iTable is +** the integer cursor number of a VDBE cursor pointing to that table and +** Expr.iColumn is the column number for the specific column. If the +** expression is used as a result in an aggregate SELECT, then the +** value is also stored in the Expr.iAgg column in the aggregate so that +** it can be accessed after all aggregates are computed. +** +** If the expression is a function, the Expr.iTable is an integer code +** representing which function. If the expression is an unbound variable +** marker (a question mark character '?' in the original SQL) then the +** Expr.iTable holds the index number for that variable. +** +** If the expression is a subquery then Expr.iColumn holds an integer +** register number containing the result of the subquery. If the +** subquery gives a constant result, then iTable is -1. If the subquery +** gives a different answer at different times during statement processing +** then iTable is the address of a subroutine that computes the subquery. +** +** The Expr.pSelect field points to a SELECT statement. The SELECT might +** be the right operand of an IN operator. Or, if a scalar SELECT appears +** in an expression the opcode is TK_SELECT and Expr.pSelect is the only +** operand. +** +** If the Expr is of type OP_Column, and the table it is selecting from +** is a disk table or the "old.*" pseudo-table, then pTab points to the +** corresponding table definition. +*/ +struct Expr { + u8 op; /* Operation performed by this node */ + char affinity; /* The affinity of the column or 0 if not a column */ + u16 flags; /* Various flags. See below */ + CollSeq *pColl; /* The collation type of the column or 0 */ + Expr *pLeft, *pRight; /* Left and right subnodes */ + ExprList *pList; /* A list of expressions used as function arguments + ** or in " IN (aCol[] or ->aFunc[] */ + int iRightJoinTable; /* If EP_FromJoin, the right table of the join */ + Select *pSelect; /* When the expression is a sub-select. Also the + ** right side of " IN (