61043 lines
2.2 MiB
61043 lines
2.2 MiB
/******************************************************************************
|
|
** This file is an amalgamation of many separate C source files from SQLite
|
|
** version 3.45.3. By combining all the individual C code files into this
|
|
** single large file, the entire code can be compiled as a single translation
|
|
** unit. This allows many compilers to do optimizations that would not be
|
|
** possible if the files were compiled separately. Performance improvements
|
|
** of 5% or more are commonly seen when SQLite is compiled as a single
|
|
** translation unit.
|
|
**
|
|
** This file is all you need to compile SQLite. To use SQLite in other
|
|
** programs, you need this file and the "sqlite3.h" header file that defines
|
|
** the programming interface to the SQLite library. (If you do not have
|
|
** the "sqlite3.h" header file at hand, you will find a copy embedded within
|
|
** the text of this file. Search for "Begin file sqlite3.h" to find the start
|
|
** of the embedded sqlite3.h header file.) Additional code files may be needed
|
|
** if you want a wrapper to interface SQLite with your choice of programming
|
|
** language. The code for the "sqlite3" command-line shell is also in a
|
|
** separate file. This file contains only code for the core SQLite library.
|
|
**
|
|
** The content in this amalgamation comes from Fossil check-in
|
|
** 8653b758870e6ef0c98d46b3ace27849054a.
|
|
*/
|
|
#define SQLITE_CORE 1
|
|
#define SQLITE_AMALGAMATION 1
|
|
#ifndef SQLITE_PRIVATE
|
|
# define SQLITE_PRIVATE static
|
|
#endif
|
|
#define SQLITE_UDL_CAPABLE_PARSER 1
|
|
/************** Begin file sqliteInt.h ***************************************/
|
|
/*
|
|
** 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.
|
|
**
|
|
*/
|
|
#ifndef SQLITEINT_H
|
|
#define SQLITEINT_H
|
|
|
|
/* Special Comments:
|
|
**
|
|
** Some comments have special meaning to the tools that measure test
|
|
** coverage:
|
|
**
|
|
** NO_TEST - The branches on this line are not
|
|
** measured by branch coverage. This is
|
|
** used on lines of code that actually
|
|
** implement parts of coverage testing.
|
|
**
|
|
** OPTIMIZATION-IF-TRUE - This branch is allowed to always be false
|
|
** and the correct answer is still obtained,
|
|
** though perhaps more slowly.
|
|
**
|
|
** OPTIMIZATION-IF-FALSE - This branch is allowed to always be true
|
|
** and the correct answer is still obtained,
|
|
** though perhaps more slowly.
|
|
**
|
|
** PREVENTS-HARMLESS-OVERREAD - This branch prevents a buffer overread
|
|
** that would be harmless and undetectable
|
|
** if it did occur.
|
|
**
|
|
** In all cases, the special comment must be enclosed in the usual
|
|
** slash-asterisk...asterisk-slash comment marks, with no spaces between the
|
|
** asterisks and the comment text.
|
|
*/
|
|
|
|
/*
|
|
** Make sure the Tcl calling convention macro is defined. This macro is
|
|
** only used by test code and Tcl integration code.
|
|
*/
|
|
#ifndef SQLITE_TCLAPI
|
|
# define SQLITE_TCLAPI
|
|
#endif
|
|
|
|
/*
|
|
** Include the header file used to customize the compiler options for MSVC.
|
|
** This should be done first so that it can successfully prevent spurious
|
|
** compiler warnings due to subsequent content in this file and other files
|
|
** that are included by this file.
|
|
*/
|
|
/************** Include msvc.h in the middle of sqliteInt.h ******************/
|
|
/************** Begin file msvc.h ********************************************/
|
|
/*
|
|
** 2015 January 12
|
|
**
|
|
** 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 MSVC.
|
|
*/
|
|
#ifndef SQLITE_MSVC_H
|
|
#define SQLITE_MSVC_H
|
|
|
|
#if defined(_MSC_VER)
|
|
#pragma warning(disable : 4054)
|
|
#pragma warning(disable : 4055)
|
|
#pragma warning(disable : 4100)
|
|
#pragma warning(disable : 4127)
|
|
#pragma warning(disable : 4130)
|
|
#pragma warning(disable : 4152)
|
|
#pragma warning(disable : 4189)
|
|
#pragma warning(disable : 4206)
|
|
#pragma warning(disable : 4210)
|
|
#pragma warning(disable : 4232)
|
|
#pragma warning(disable : 4244)
|
|
#pragma warning(disable : 4305)
|
|
#pragma warning(disable : 4306)
|
|
#pragma warning(disable : 4702)
|
|
#pragma warning(disable : 4706)
|
|
#endif /* defined(_MSC_VER) */
|
|
|
|
#if defined(_MSC_VER) && !defined(_WIN64)
|
|
#undef SQLITE_4_BYTE_ALIGNED_MALLOC
|
|
#define SQLITE_4_BYTE_ALIGNED_MALLOC
|
|
#endif /* defined(_MSC_VER) && !defined(_WIN64) */
|
|
|
|
#if !defined(HAVE_LOG2) && defined(_MSC_VER) && _MSC_VER<1800
|
|
#define HAVE_LOG2 0
|
|
#endif /* !defined(HAVE_LOG2) && defined(_MSC_VER) && _MSC_VER<1800 */
|
|
|
|
#endif /* SQLITE_MSVC_H */
|
|
|
|
/************** End of msvc.h ************************************************/
|
|
/************** Continuing where we left off in sqliteInt.h ******************/
|
|
|
|
/*
|
|
** Special setup for VxWorks
|
|
*/
|
|
/************** Include vxworks.h in the middle of sqliteInt.h ***************/
|
|
/************** Begin file vxworks.h *****************************************/
|
|
/*
|
|
** 2015-03-02
|
|
**
|
|
** 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 Wind River's VxWorks
|
|
*/
|
|
#if defined(__RTP__) || defined(_WRS_KERNEL)
|
|
/* This is VxWorks. Set up things specially for that OS
|
|
*/
|
|
#include <vxWorks.h>
|
|
#include <pthread.h> /* amalgamator: dontcache */
|
|
#define OS_VXWORKS 1
|
|
#define SQLITE_OS_OTHER 0
|
|
#define SQLITE_HOMEGROWN_RECURSIVE_MUTEX 1
|
|
#define SQLITE_OMIT_LOAD_EXTENSION 1
|
|
#define SQLITE_ENABLE_LOCKING_STYLE 0
|
|
#define HAVE_UTIME 1
|
|
#else
|
|
/* This is not VxWorks. */
|
|
#define OS_VXWORKS 0
|
|
#define HAVE_FCHOWN 1
|
|
#define HAVE_READLINK 1
|
|
#define HAVE_LSTAT 1
|
|
#endif /* defined(_WRS_KERNEL) */
|
|
|
|
/************** End of vxworks.h *********************************************/
|
|
/************** Continuing where we left off in sqliteInt.h ******************/
|
|
|
|
/*
|
|
** 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.
|
|
**
|
|
** Ticket #2739: The _LARGEFILE_SOURCE macro must appear before any
|
|
** system #includes. Hence, this block of code must be the very first
|
|
** code in all source files.
|
|
**
|
|
** 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: Red Hat 7.2) but you want your code to work
|
|
** on an older machine (ex: Red Hat 6.0). If you compile on Red Hat 7.2
|
|
** without this option, LFS is enable. But LFS does not exist in the kernel
|
|
** in Red Hat 6.0, so the code won't work. Hence, for maximum binary
|
|
** portability you should omit LFS.
|
|
**
|
|
** The previous paragraph was written in 2005. (This paragraph is written
|
|
** on 2008-11-28.) These days, all Linux kernels support large files, so
|
|
** you should probably leave LFS enabled. But some embedded platforms might
|
|
** lack LFS in which case the SQLITE_DISABLE_LFS macro might still be useful.
|
|
**
|
|
** Similar is true for Mac OS X. LFS is only supported on Mac OS X 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
|
|
|
|
/* The GCC_VERSION and MSVC_VERSION macros are used to
|
|
** conditionally include optimizations for each of these compilers. A
|
|
** value of 0 means that compiler is not being used. The
|
|
** SQLITE_DISABLE_INTRINSIC macro means do not use any compiler-specific
|
|
** optimizations, and hence set all compiler macros to 0
|
|
**
|
|
** There was once also a CLANG_VERSION macro. However, we learn that the
|
|
** version numbers in clang are for "marketing" only and are inconsistent
|
|
** and unreliable. Fortunately, all versions of clang also recognize the
|
|
** gcc version numbers and have reasonable settings for gcc version numbers,
|
|
** so the GCC_VERSION macro will be set to a correct non-zero value even
|
|
** when compiling with clang.
|
|
*/
|
|
#if defined(__GNUC__) && !defined(SQLITE_DISABLE_INTRINSIC)
|
|
# define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__)
|
|
#else
|
|
# define GCC_VERSION 0
|
|
#endif
|
|
#if defined(_MSC_VER) && !defined(SQLITE_DISABLE_INTRINSIC)
|
|
# define MSVC_VERSION _MSC_VER
|
|
#else
|
|
# define MSVC_VERSION 0
|
|
#endif
|
|
|
|
/*
|
|
** Some C99 functions in "math.h" are only present for MSVC when its version
|
|
** is associated with Visual Studio 2013 or higher.
|
|
*/
|
|
#ifndef SQLITE_HAVE_C99_MATH_FUNCS
|
|
# if MSVC_VERSION==0 || MSVC_VERSION>=1800
|
|
# define SQLITE_HAVE_C99_MATH_FUNCS (1)
|
|
# else
|
|
# define SQLITE_HAVE_C99_MATH_FUNCS (0)
|
|
# endif
|
|
#endif
|
|
|
|
/* Needed for various definitions... */
|
|
#if defined(__GNUC__) && !defined(_GNU_SOURCE)
|
|
# define _GNU_SOURCE
|
|
#endif
|
|
|
|
#if defined(__OpenBSD__) && !defined(_BSD_SOURCE)
|
|
# define _BSD_SOURCE
|
|
#endif
|
|
|
|
/*
|
|
** Macro to disable warnings about missing "break" at the end of a "case".
|
|
*/
|
|
#if GCC_VERSION>=7000000
|
|
# define deliberate_fall_through __attribute__((fallthrough));
|
|
#else
|
|
# define deliberate_fall_through
|
|
#endif
|
|
|
|
/*
|
|
** For MinGW, check to see if we can include the header file containing its
|
|
** version information, among other things. Normally, this internal MinGW
|
|
** header file would [only] be included automatically by other MinGW header
|
|
** files; however, the contained version information is now required by this
|
|
** header file to work around binary compatibility issues (see below) and
|
|
** this is the only known way to reliably obtain it. This entire #if block
|
|
** would be completely unnecessary if there was any other way of detecting
|
|
** MinGW via their preprocessor (e.g. if they customized their GCC to define
|
|
** some MinGW-specific macros). When compiling for MinGW, either the
|
|
** _HAVE_MINGW_H or _HAVE__MINGW_H (note the extra underscore) macro must be
|
|
** defined; otherwise, detection of conditions specific to MinGW will be
|
|
** disabled.
|
|
*/
|
|
#if defined(_HAVE_MINGW_H)
|
|
# include "mingw.h"
|
|
#elif defined(_HAVE__MINGW_H)
|
|
# include "_mingw.h"
|
|
#endif
|
|
|
|
/*
|
|
** For MinGW version 4.x (and higher), check to see if the _USE_32BIT_TIME_T
|
|
** define is required to maintain binary compatibility with the MSVC runtime
|
|
** library in use (e.g. for Windows XP).
|
|
*/
|
|
#if !defined(_USE_32BIT_TIME_T) && !defined(_USE_64BIT_TIME_T) && \
|
|
defined(_WIN32) && !defined(_WIN64) && \
|
|
defined(__MINGW_MAJOR_VERSION) && __MINGW_MAJOR_VERSION >= 4 && \
|
|
defined(__MSVCRT__)
|
|
# define _USE_32BIT_TIME_T
|
|
#endif
|
|
|
|
/* Optionally #include a user-defined header, whereby compilation options
|
|
** may be set prior to where they take effect, but after platform setup.
|
|
** If SQLITE_CUSTOM_INCLUDE=? is defined, its value names the #include
|
|
** file.
|
|
*/
|
|
#ifdef SQLITE_CUSTOM_INCLUDE
|
|
# define INC_STRINGIFY_(f) #f
|
|
# define INC_STRINGIFY(f) INC_STRINGIFY_(f)
|
|
# include INC_STRINGIFY(SQLITE_CUSTOM_INCLUDE)
|
|
#endif
|
|
|
|
/* The public SQLite interface. The _FILE_OFFSET_BITS macro must appear
|
|
** first in QNX. Also, the _USE_32BIT_TIME_T macro must appear first for
|
|
** MinGW.
|
|
*/
|
|
/************** Include sqlite3.h in the middle of sqliteInt.h ***************/
|
|
/************** Begin file sqlite3.h *****************************************/
|
|
/*
|
|
** 2001-09-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 the right 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 supposed 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.
|
|
*/
|
|
#ifndef SQLITE3_H
|
|
#define SQLITE3_H
|
|
#include <stdarg.h> /* Needed for the definition of va_list */
|
|
|
|
/*
|
|
** Make sure we can call this stuff from C++.
|
|
*/
|
|
#if 0
|
|
extern "C" {
|
|
#endif
|
|
|
|
|
|
/*
|
|
** Facilitate override of interface linkage and calling conventions.
|
|
** Be aware that these macros may not be used within this particular
|
|
** translation of the amalgamation and its associated header file.
|
|
**
|
|
** The SQLITE_EXTERN and SQLITE_API macros are used to instruct the
|
|
** compiler that the target identifier should have external linkage.
|
|
**
|
|
** The SQLITE_CDECL macro is used to set the calling convention for
|
|
** public functions that accept a variable number of arguments.
|
|
**
|
|
** The SQLITE_APICALL macro is used to set the calling convention for
|
|
** public functions that accept a fixed number of arguments.
|
|
**
|
|
** The SQLITE_STDCALL macro is no longer used and is now deprecated.
|
|
**
|
|
** The SQLITE_CALLBACK macro is used to set the calling convention for
|
|
** function pointers.
|
|
**
|
|
** The SQLITE_SYSAPI macro is used to set the calling convention for
|
|
** functions provided by the operating system.
|
|
**
|
|
** Currently, the SQLITE_CDECL, SQLITE_APICALL, SQLITE_CALLBACK, and
|
|
** SQLITE_SYSAPI macros are used only when building for environments
|
|
** that require non-default calling conventions.
|
|
*/
|
|
#ifndef SQLITE_EXTERN
|
|
# define SQLITE_EXTERN extern
|
|
#endif
|
|
#ifndef SQLITE_API
|
|
# define SQLITE_API
|
|
#endif
|
|
#ifndef SQLITE_CDECL
|
|
# define SQLITE_CDECL
|
|
#endif
|
|
#ifndef SQLITE_APICALL
|
|
# define SQLITE_APICALL
|
|
#endif
|
|
#ifndef SQLITE_STDCALL
|
|
# define SQLITE_STDCALL SQLITE_APICALL
|
|
#endif
|
|
#ifndef SQLITE_CALLBACK
|
|
# define SQLITE_CALLBACK
|
|
#endif
|
|
#ifndef SQLITE_SYSAPI
|
|
# define SQLITE_SYSAPI
|
|
#endif
|
|
|
|
/*
|
|
** These no-op macros are used in front of interfaces to mark those
|
|
** interfaces as either deprecated or experimental. New applications
|
|
** should not use deprecated interfaces - they are supported for backwards
|
|
** compatibility only. Application writers should be aware that
|
|
** experimental interfaces are subject to change in point releases.
|
|
**
|
|
** These macros used to resolve to various kinds of compiler magic that
|
|
** would generate warning messages when they were used. But that
|
|
** compiler magic ended up generating such a flurry of bug reports
|
|
** that we have taken it all out and gone back to using simple
|
|
** noop macros.
|
|
*/
|
|
#define SQLITE_DEPRECATED
|
|
#define SQLITE_EXPERIMENTAL
|
|
|
|
/*
|
|
** Ensure these symbols were 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 [SQLITE_VERSION] C preprocessor macro in the sqlite3.h header
|
|
** evaluates to a string literal that is the SQLite version in the
|
|
** format "X.Y.Z" where X is the major version number (always 3 for
|
|
** SQLite3) and Y is the minor version number and Z is the release number.)^
|
|
** ^(The [SQLITE_VERSION_NUMBER] C preprocessor macro resolves to an integer
|
|
** with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are the same
|
|
** numbers used in [SQLITE_VERSION].)^
|
|
** The SQLITE_VERSION_NUMBER for any given release of SQLite will also
|
|
** be larger than the release from which it is derived. Either Y will
|
|
** be held constant and Z will be incremented or else Y will be incremented
|
|
** and Z will be reset to zero.
|
|
**
|
|
** Since [version 3.6.18] ([dateof:3.6.18]),
|
|
** SQLite source code has been stored in the
|
|
** <a href="http://www.fossil-scm.org/">Fossil configuration management
|
|
** system</a>. ^The SQLITE_SOURCE_ID macro evaluates to
|
|
** a string which identifies a particular check-in of SQLite
|
|
** within its configuration management system. ^The SQLITE_SOURCE_ID
|
|
** string contains the date and time of the check-in (UTC) and a SHA1
|
|
** or SHA3-256 hash of the entire source tree. If the source code has
|
|
** been edited in any way since it was last checked in, then the last
|
|
** four hexadecimal digits of the hash may be modified.
|
|
**
|
|
** See also: [sqlite3_libversion()],
|
|
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
|
** [sqlite_version()] and [sqlite_source_id()].
|
|
*/
|
|
#define SQLITE_VERSION "3.45.3"
|
|
#define SQLITE_VERSION_NUMBER 3045003
|
|
#define SQLITE_SOURCE_ID "2024-04-15 13:34:05 8653b758870e6ef0c98d46b3ace27849054af85da891eb121e9aaa537f1e8355"
|
|
|
|
/*
|
|
** CAPI3REF: Run-Time Library Version Numbers
|
|
** KEYWORDS: sqlite3_version sqlite3_sourceid
|
|
**
|
|
** These interfaces provide the same information as the [SQLITE_VERSION],
|
|
** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
|
|
** but are associated with the library instead of the header file. ^(Cautious
|
|
** programmers might include assert() statements in their application to
|
|
** verify that values returned by these interfaces match the macros in
|
|
** the header, and thus ensure that the application is
|
|
** compiled with matching library and header files.
|
|
**
|
|
** <blockquote><pre>
|
|
** assert( sqlite3_libversion_number()==SQLITE_VERSION_NUMBER );
|
|
** assert( strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,80)==0 );
|
|
** assert( strcmp(sqlite3_libversion(),SQLITE_VERSION)==0 );
|
|
** </pre></blockquote>)^
|
|
**
|
|
** ^The sqlite3_version[] string constant contains the text of [SQLITE_VERSION]
|
|
** macro. ^The sqlite3_libversion() function returns a pointer to the
|
|
** to the sqlite3_version[] string constant. The sqlite3_libversion()
|
|
** function is provided for use in DLLs since DLL users usually do not have
|
|
** direct access to string constants within the DLL. ^The
|
|
** sqlite3_libversion_number() function returns an integer equal to
|
|
** [SQLITE_VERSION_NUMBER]. ^(The sqlite3_sourceid() function returns
|
|
** a pointer to a string constant whose value is the same as the
|
|
** [SQLITE_SOURCE_ID] C preprocessor macro. Except if SQLite is built
|
|
** using an edited copy of [the amalgamation], then the last four characters
|
|
** of the hash might be different from [SQLITE_SOURCE_ID].)^
|
|
**
|
|
** See also: [sqlite_version()] and [sqlite_source_id()].
|
|
*/
|
|
SQLITE_API const char sqlite3_version[] = SQLITE_VERSION;
|
|
SQLITE_API const char *sqlite3_libversion(void);
|
|
SQLITE_API const char *sqlite3_sourceid(void);
|
|
SQLITE_API int sqlite3_libversion_number(void);
|
|
|
|
/*
|
|
** CAPI3REF: Run-Time Library Compilation Options Diagnostics
|
|
**
|
|
** ^The sqlite3_compileoption_used() function returns 0 or 1
|
|
** indicating whether the specified option was defined at
|
|
** compile time. ^The SQLITE_ prefix may be omitted from the
|
|
** option name passed to sqlite3_compileoption_used().
|
|
**
|
|
** ^The sqlite3_compileoption_get() function allows iterating
|
|
** over the list of options that were defined at compile time by
|
|
** returning the N-th compile time option string. ^If N is out of range,
|
|
** sqlite3_compileoption_get() returns a NULL pointer. ^The SQLITE_
|
|
** prefix is omitted from any strings returned by
|
|
** sqlite3_compileoption_get().
|
|
**
|
|
** ^Support for the diagnostic functions sqlite3_compileoption_used()
|
|
** and sqlite3_compileoption_get() may be omitted by specifying the
|
|
** [SQLITE_OMIT_COMPILEOPTION_DIAGS] option at compile time.
|
|
**
|
|
** See also: SQL functions [sqlite_compileoption_used()] and
|
|
** [sqlite_compileoption_get()] and the [compile_options pragma].
|
|
*/
|
|
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
|
|
SQLITE_API int sqlite3_compileoption_used(const char *zOptName);
|
|
SQLITE_API const char *sqlite3_compileoption_get(int N);
|
|
#else
|
|
# define sqlite3_compileoption_used(X) 0
|
|
# define sqlite3_compileoption_get(X) ((void*)0)
|
|
#endif
|
|
|
|
/*
|
|
** CAPI3REF: Test To See If The Library Is Threadsafe
|
|
**
|
|
** ^The sqlite3_threadsafe() function returns zero if and only if
|
|
** SQLite was compiled with mutexing code omitted due to the
|
|
** [SQLITE_THREADSAFE] compile-time option being set to 0.
|
|
**
|
|
** SQLite can be compiled with or without mutexes. When
|
|
** the [SQLITE_THREADSAFE] C preprocessor macro is 1 or 2, mutexes
|
|
** are enabled and SQLite is threadsafe. When the
|
|
** [SQLITE_THREADSAFE] macro is 0,
|
|
** the mutexes are omitted. Without the mutexes, it is not safe
|
|
** to use SQLite concurrently from more than one thread.
|
|
**
|
|
** Enabling mutexes incurs a measurable performance penalty.
|
|
** So if speed is of utmost importance, it makes sense to disable
|
|
** the mutexes. But for maximum safety, mutexes should be enabled.
|
|
** ^The default behavior is for mutexes to be enabled.
|
|
**
|
|
** This interface can be used by an application to make sure that the
|
|
** version of SQLite that it is linking against was compiled with
|
|
** the desired setting of the [SQLITE_THREADSAFE] macro.
|
|
**
|
|
** This interface only reports on the compile-time mutex setting
|
|
** of the [SQLITE_THREADSAFE] flag. If SQLite is compiled with
|
|
** SQLITE_THREADSAFE=1 or =2 then mutexes are enabled by default but
|
|
** can be fully or partially disabled using a call to [sqlite3_config()]
|
|
** with the verbs [SQLITE_CONFIG_SINGLETHREAD], [SQLITE_CONFIG_MULTITHREAD],
|
|
** or [SQLITE_CONFIG_SERIALIZED]. ^(The return value of the
|
|
** sqlite3_threadsafe() function shows only the compile-time setting of
|
|
** thread safety, not any run-time changes to that setting made by
|
|
** sqlite3_config(). In other words, the return value from sqlite3_threadsafe()
|
|
** is unchanged by calls to sqlite3_config().)^
|
|
**
|
|
** See the [threading mode] documentation for additional information.
|
|
*/
|
|
SQLITE_API int sqlite3_threadsafe(void);
|
|
|
|
/*
|
|
** CAPI3REF: Database Connection Handle
|
|
** KEYWORDS: {database connection} {database connections}
|
|
**
|
|
** Each open SQLite database is represented by a 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()], [sqlite3_open16()], and
|
|
** [sqlite3_open_v2()] interfaces are its constructors, and [sqlite3_close()]
|
|
** and [sqlite3_close_v2()] are its destructors. 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 an
|
|
** sqlite3 object.
|
|
*/
|
|
typedef struct sqlite3 sqlite3;
|
|
|
|
/*
|
|
** CAPI3REF: 64-Bit Integer Types
|
|
** KEYWORDS: sqlite_int64 sqlite_uint64
|
|
**
|
|
** Because there is no cross-platform way to specify 64-bit integer types
|
|
** SQLite includes typedefs for 64-bit signed and unsigned integers.
|
|
**
|
|
** The sqlite3_int64 and sqlite3_uint64 are the preferred type definitions.
|
|
** The sqlite_int64 and sqlite_uint64 types are supported for backwards
|
|
** compatibility only.
|
|
**
|
|
** ^The sqlite3_int64 and sqlite_int64 types can store integer values
|
|
** between -9223372036854775808 and +9223372036854775807 inclusive. ^The
|
|
** sqlite3_uint64 and sqlite_uint64 types can store integer values
|
|
** between 0 and +18446744073709551615 inclusive.
|
|
*/
|
|
#ifdef SQLITE_INT64_TYPE
|
|
typedef SQLITE_INT64_TYPE sqlite_int64;
|
|
# ifdef SQLITE_UINT64_TYPE
|
|
typedef SQLITE_UINT64_TYPE sqlite_uint64;
|
|
# else
|
|
typedef unsigned SQLITE_INT64_TYPE sqlite_uint64;
|
|
# endif
|
|
#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
|
|
typedef sqlite_int64 sqlite3_int64;
|
|
typedef sqlite_uint64 sqlite3_uint64;
|
|
|
|
/*
|
|
** If compiling for a processor that lacks floating point support,
|
|
** substitute integer for floating-point.
|
|
*/
|
|
#ifdef SQLITE_OMIT_FLOATING_POINT
|
|
# define double sqlite3_int64
|
|
#endif
|
|
|
|
/*
|
|
** CAPI3REF: Closing A Database Connection
|
|
** DESTRUCTOR: sqlite3
|
|
**
|
|
** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
|
|
** for the [sqlite3] object.
|
|
** ^Calls to sqlite3_close() and sqlite3_close_v2() return [SQLITE_OK] if
|
|
** the [sqlite3] object is successfully destroyed and all associated
|
|
** resources are deallocated.
|
|
**
|
|
** Ideally, applications should [sqlite3_finalize | finalize] all
|
|
** [prepared statements], [sqlite3_blob_close | close] all [BLOB handles], and
|
|
** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
|
|
** with the [sqlite3] object prior to attempting to close the object.
|
|
** ^If the database connection is associated with unfinalized prepared
|
|
** statements, BLOB handlers, and/or unfinished sqlite3_backup objects then
|
|
** sqlite3_close() will leave the database connection open and return
|
|
** [SQLITE_BUSY]. ^If sqlite3_close_v2() is called with unfinalized prepared
|
|
** statements, unclosed BLOB handlers, and/or unfinished sqlite3_backups,
|
|
** it returns [SQLITE_OK] regardless, but instead of deallocating the database
|
|
** connection immediately, it marks the database connection as an unusable
|
|
** "zombie" and makes arrangements to automatically deallocate the database
|
|
** connection after all prepared statements are finalized, all BLOB handles
|
|
** are closed, and all backups have finished. The sqlite3_close_v2() interface
|
|
** is intended for use with host languages that are garbage collected, and
|
|
** where the order in which destructors are called is arbitrary.
|
|
**
|
|
** ^If an [sqlite3] object is destroyed while a transaction is open,
|
|
** the transaction is automatically rolled back.
|
|
**
|
|
** The C parameter to [sqlite3_close(C)] and [sqlite3_close_v2(C)]
|
|
** must be either a NULL
|
|
** pointer or an [sqlite3] object pointer obtained
|
|
** from [sqlite3_open()], [sqlite3_open16()], or
|
|
** [sqlite3_open_v2()], and not previously closed.
|
|
** ^Calling sqlite3_close() or sqlite3_close_v2() with a NULL pointer
|
|
** argument is a harmless no-op.
|
|
*/
|
|
SQLITE_API int sqlite3_close(sqlite3*);
|
|
SQLITE_API int sqlite3_close_v2(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
|
|
** METHOD: sqlite3
|
|
**
|
|
** The sqlite3_exec() interface is a convenience wrapper around
|
|
** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()],
|
|
** that allows an application to run multiple statements of SQL
|
|
** without having to use a lot of C code.
|
|
**
|
|
** ^The sqlite3_exec() interface runs zero or more UTF-8 encoded,
|
|
** semicolon-separate SQL statements passed into its 2nd argument,
|
|
** in the context of the [database connection] passed in as its 1st
|
|
** argument. ^If the callback function of the 3rd argument to
|
|
** sqlite3_exec() is not NULL, then it is invoked for each result row
|
|
** coming out of the evaluated SQL statements. ^The 4th argument to
|
|
** sqlite3_exec() is relayed through to the 1st argument of each
|
|
** callback invocation. ^If the callback pointer to sqlite3_exec()
|
|
** is NULL, then no callback is ever invoked and result rows are
|
|
** ignored.
|
|
**
|
|
** ^If an error occurs while evaluating the SQL statements passed into
|
|
** sqlite3_exec(), then execution of the current statement stops and
|
|
** subsequent statements are skipped. ^If the 5th parameter to sqlite3_exec()
|
|
** is not NULL then any error message is written into memory obtained
|
|
** from [sqlite3_malloc()] and passed back through the 5th parameter.
|
|
** To avoid memory leaks, the application should invoke [sqlite3_free()]
|
|
** on error message strings returned through the 5th parameter of
|
|
** sqlite3_exec() after the error message string is no longer needed.
|
|
** ^If the 5th parameter to sqlite3_exec() is not NULL and no errors
|
|
** occur, then sqlite3_exec() sets the pointer in its 5th parameter to
|
|
** NULL before returning.
|
|
**
|
|
** ^If an sqlite3_exec() callback returns non-zero, the sqlite3_exec()
|
|
** routine returns SQLITE_ABORT without invoking the callback again and
|
|
** without running any subsequent SQL statements.
|
|
**
|
|
** ^The 2nd argument to the sqlite3_exec() callback function is the
|
|
** number of columns in the result. ^The 3rd argument to the sqlite3_exec()
|
|
** callback is an array of pointers to strings obtained as if from
|
|
** [sqlite3_column_text()], one for each column. ^If an element of a
|
|
** result row is NULL then the corresponding string pointer for the
|
|
** sqlite3_exec() callback is a NULL pointer. ^The 4th argument to the
|
|
** sqlite3_exec() callback is an array of pointers to strings where each
|
|
** entry represents the name of corresponding result column as obtained
|
|
** from [sqlite3_column_name()].
|
|
**
|
|
** ^If the 2nd parameter to sqlite3_exec() is a NULL pointer, a pointer
|
|
** to an empty string, or a pointer that contains only whitespace and/or
|
|
** SQL comments, then no SQL statements are evaluated and the database
|
|
** is not changed.
|
|
**
|
|
** Restrictions:
|
|
**
|
|
** <ul>
|
|
** <li> The application must ensure that the 1st parameter to sqlite3_exec()
|
|
** is a valid and open [database connection].
|
|
** <li> The application must not close the [database connection] specified by
|
|
** the 1st parameter to sqlite3_exec() while sqlite3_exec() is running.
|
|
** <li> The application must not modify the SQL statement text passed into
|
|
** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running.
|
|
** <li> The application must not dereference the arrays or string pointers
|
|
** passed as the 3rd and 4th callback parameters after it returns.
|
|
** </ul>
|
|
*/
|
|
SQLITE_API int sqlite3_exec(
|
|
sqlite3*, /* An open database */
|
|
const char *sql, /* SQL to be evaluated */
|
|
int (*callback)(void*,int,char**,char**), /* Callback function */
|
|
void *, /* 1st argument to callback */
|
|
char **errmsg /* Error msg written here */
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Result Codes
|
|
** KEYWORDS: {result code definitions}
|
|
**
|
|
** Many SQLite functions return an integer result code from the set shown
|
|
** here in order to indicate success or failure.
|
|
**
|
|
** New error codes may be added in future versions of SQLite.
|
|
**
|
|
** See also: [extended result code definitions]
|
|
*/
|
|
#define SQLITE_OK 0 /* Successful result */
|
|
/* beginning-of-error-codes */
|
|
#define SQLITE_ERROR 1 /* Generic error */
|
|
#define SQLITE_INTERNAL 2 /* 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 /* Unknown opcode in sqlite3_file_control() */
|
|
#define SQLITE_FULL 13 /* Insertion failed because database is full */
|
|
#define SQLITE_CANTOPEN 14 /* Unable to open the database file */
|
|
#define SQLITE_PROTOCOL 15 /* Database lock protocol error */
|
|
#define SQLITE_EMPTY 16 /* Internal use only */
|
|
#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 constraint 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 /* Not used */
|
|
#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_NOTICE 27 /* Notifications from sqlite3_log() */
|
|
#define SQLITE_WARNING 28 /* Warnings from sqlite3_log() */
|
|
#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
|
|
** KEYWORDS: {extended result code definitions}
|
|
**
|
|
** In its default configuration, SQLite API routines return one of 30 integer
|
|
** [result codes]. However, experience has shown that many of
|
|
** these result codes are too coarse-grained. They do not provide as
|
|
** much information about problems as programmers might like. In an effort to
|
|
** address this, newer versions of SQLite (version 3.3.8 [dateof:3.3.8]
|
|
** and later) include
|
|
** support for additional result codes that provide more detailed information
|
|
** about errors. These [extended result codes] are enabled or disabled
|
|
** on a per database connection basis using the
|
|
** [sqlite3_extended_result_codes()] API. Or, the extended code for
|
|
** the most recent error can be obtained using
|
|
** [sqlite3_extended_errcode()].
|
|
*/
|
|
#define SQLITE_ERROR_MISSING_COLLSEQ (SQLITE_ERROR | (1<<8))
|
|
#define SQLITE_ERROR_RETRY (SQLITE_ERROR | (2<<8))
|
|
#define SQLITE_ERROR_SNAPSHOT (SQLITE_ERROR | (3<<8))
|
|
#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))
|
|
#define SQLITE_IOERR_NOMEM (SQLITE_IOERR | (12<<8))
|
|
#define SQLITE_IOERR_ACCESS (SQLITE_IOERR | (13<<8))
|
|
#define SQLITE_IOERR_CHECKRESERVEDLOCK (SQLITE_IOERR | (14<<8))
|
|
#define SQLITE_IOERR_LOCK (SQLITE_IOERR | (15<<8))
|
|
#define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8))
|
|
#define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8))
|
|
#define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8))
|
|
#define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8))
|
|
#define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8))
|
|
#define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8))
|
|
#define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8))
|
|
#define SQLITE_IOERR_DELETE_NOENT (SQLITE_IOERR | (23<<8))
|
|
#define SQLITE_IOERR_MMAP (SQLITE_IOERR | (24<<8))
|
|
#define SQLITE_IOERR_GETTEMPPATH (SQLITE_IOERR | (25<<8))
|
|
#define SQLITE_IOERR_CONVPATH (SQLITE_IOERR | (26<<8))
|
|
#define SQLITE_IOERR_VNODE (SQLITE_IOERR | (27<<8))
|
|
#define SQLITE_IOERR_AUTH (SQLITE_IOERR | (28<<8))
|
|
#define SQLITE_IOERR_BEGIN_ATOMIC (SQLITE_IOERR | (29<<8))
|
|
#define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8))
|
|
#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
|
|
#define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8))
|
|
#define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33<<8))
|
|
#define SQLITE_IOERR_IN_PAGE (SQLITE_IOERR | (34<<8))
|
|
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
|
|
#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8))
|
|
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
|
|
#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8))
|
|
#define SQLITE_BUSY_TIMEOUT (SQLITE_BUSY | (3<<8))
|
|
#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
|
|
#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
|
|
#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
|
|
#define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8))
|
|
#define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */
|
|
#define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8))
|
|
#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
|
|
#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8))
|
|
#define SQLITE_CORRUPT_INDEX (SQLITE_CORRUPT | (3<<8))
|
|
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
|
|
#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
|
|
#define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8))
|
|
#define SQLITE_READONLY_DBMOVED (SQLITE_READONLY | (4<<8))
|
|
#define SQLITE_READONLY_CANTINIT (SQLITE_READONLY | (5<<8))
|
|
#define SQLITE_READONLY_DIRECTORY (SQLITE_READONLY | (6<<8))
|
|
#define SQLITE_ABORT_ROLLBACK (SQLITE_ABORT | (2<<8))
|
|
#define SQLITE_CONSTRAINT_CHECK (SQLITE_CONSTRAINT | (1<<8))
|
|
#define SQLITE_CONSTRAINT_COMMITHOOK (SQLITE_CONSTRAINT | (2<<8))
|
|
#define SQLITE_CONSTRAINT_FOREIGNKEY (SQLITE_CONSTRAINT | (3<<8))
|
|
#define SQLITE_CONSTRAINT_FUNCTION (SQLITE_CONSTRAINT | (4<<8))
|
|
#define SQLITE_CONSTRAINT_NOTNULL (SQLITE_CONSTRAINT | (5<<8))
|
|
#define SQLITE_CONSTRAINT_PRIMARYKEY (SQLITE_CONSTRAINT | (6<<8))
|
|
#define SQLITE_CONSTRAINT_TRIGGER (SQLITE_CONSTRAINT | (7<<8))
|
|
#define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8<<8))
|
|
#define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8))
|
|
#define SQLITE_CONSTRAINT_ROWID (SQLITE_CONSTRAINT |(10<<8))
|
|
#define SQLITE_CONSTRAINT_PINNED (SQLITE_CONSTRAINT |(11<<8))
|
|
#define SQLITE_CONSTRAINT_DATATYPE (SQLITE_CONSTRAINT |(12<<8))
|
|
#define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8))
|
|
#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8))
|
|
#define SQLITE_NOTICE_RBU (SQLITE_NOTICE | (3<<8))
|
|
#define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8))
|
|
#define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8))
|
|
#define SQLITE_OK_LOAD_PERMANENTLY (SQLITE_OK | (1<<8))
|
|
#define SQLITE_OK_SYMLINK (SQLITE_OK | (2<<8)) /* internal use only */
|
|
|
|
/*
|
|
** CAPI3REF: Flags For File Open Operations
|
|
**
|
|
** These bit values are intended for use in the
|
|
** 3rd parameter to the [sqlite3_open_v2()] interface and
|
|
** in the 4th parameter to the [sqlite3_vfs.xOpen] method.
|
|
**
|
|
** Only those flags marked as "Ok for sqlite3_open_v2()" may be
|
|
** used as the third argument to the [sqlite3_open_v2()] interface.
|
|
** The other flags have historically been ignored by sqlite3_open_v2(),
|
|
** though future versions of SQLite might change so that an error is
|
|
** raised if any of the disallowed bits are passed into sqlite3_open_v2().
|
|
** Applications should not depend on the historical behavior.
|
|
**
|
|
** Note in particular that passing the SQLITE_OPEN_EXCLUSIVE flag into
|
|
** [sqlite3_open_v2()] does *not* cause the underlying database file
|
|
** to be opened using O_EXCL. Passing SQLITE_OPEN_EXCLUSIVE into
|
|
** [sqlite3_open_v2()] has historically be a no-op and might become an
|
|
** error in future versions of SQLite.
|
|
*/
|
|
#define SQLITE_OPEN_READONLY 0x00000001 /* Ok for sqlite3_open_v2() */
|
|
#define SQLITE_OPEN_READWRITE 0x00000002 /* Ok for sqlite3_open_v2() */
|
|
#define SQLITE_OPEN_CREATE 0x00000004 /* Ok for sqlite3_open_v2() */
|
|
#define SQLITE_OPEN_DELETEONCLOSE 0x00000008 /* VFS only */
|
|
#define SQLITE_OPEN_EXCLUSIVE 0x00000010 /* VFS only */
|
|
#define SQLITE_OPEN_AUTOPROXY 0x00000020 /* VFS only */
|
|
#define SQLITE_OPEN_URI 0x00000040 /* Ok for sqlite3_open_v2() */
|
|
#define SQLITE_OPEN_MEMORY 0x00000080 /* Ok for sqlite3_open_v2() */
|
|
#define SQLITE_OPEN_MAIN_DB 0x00000100 /* VFS only */
|
|
#define SQLITE_OPEN_TEMP_DB 0x00000200 /* VFS only */
|
|
#define SQLITE_OPEN_TRANSIENT_DB 0x00000400 /* VFS only */
|
|
#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */
|
|
#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */
|
|
#define SQLITE_OPEN_SUBJOURNAL 0x00002000 /* VFS only */
|
|
#define SQLITE_OPEN_SUPER_JOURNAL 0x00004000 /* VFS only */
|
|
#define SQLITE_OPEN_NOMUTEX 0x00008000 /* Ok for sqlite3_open_v2() */
|
|
#define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */
|
|
#define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */
|
|
#define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */
|
|
#define SQLITE_OPEN_WAL 0x00080000 /* VFS only */
|
|
#define SQLITE_OPEN_NOFOLLOW 0x01000000 /* Ok for sqlite3_open_v2() */
|
|
#define SQLITE_OPEN_EXRESCODE 0x02000000 /* Extended result codes */
|
|
|
|
/* Reserved: 0x00F00000 */
|
|
/* Legacy compatibility: */
|
|
#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */
|
|
|
|
|
|
/*
|
|
** CAPI3REF: Device Characteristics
|
|
**
|
|
** The xDeviceCharacteristics method of the [sqlite3_io_methods]
|
|
** object returns an integer which is a vector of these
|
|
** bit values expressing I/O characteristics of the mass storage
|
|
** device that holds the file that the [sqlite3_io_methods]
|
|
** refers to.
|
|
**
|
|
** The SQLITE_IOCAP_ATOMIC property means that all writes of
|
|
** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values
|
|
** mean that writes of blocks that are nnn bytes in size and
|
|
** are aligned to an address which is an integer multiple of
|
|
** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means
|
|
** that when data is appended to a file, the data is appended
|
|
** first then the size of the file is extended, never the other
|
|
** way around. The SQLITE_IOCAP_SEQUENTIAL property means that
|
|
** information is written to disk in the same order as calls
|
|
** to xWrite(). The SQLITE_IOCAP_POWERSAFE_OVERWRITE property means that
|
|
** after reboot following a crash or power loss, the only bytes in a
|
|
** file that were written at the application level might have changed
|
|
** and that adjacent bytes, even bytes within the same sector are
|
|
** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
|
|
** flag indicates that a file cannot be deleted when open. The
|
|
** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on
|
|
** read-only media and cannot be changed even by processes with
|
|
** elevated privileges.
|
|
**
|
|
** The SQLITE_IOCAP_BATCH_ATOMIC property means that the underlying
|
|
** filesystem supports doing multiple write operations atomically when those
|
|
** write operations are bracketed by [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] and
|
|
** [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE].
|
|
*/
|
|
#define SQLITE_IOCAP_ATOMIC 0x00000001
|
|
#define SQLITE_IOCAP_ATOMIC512 0x00000002
|
|
#define SQLITE_IOCAP_ATOMIC1K 0x00000004
|
|
#define SQLITE_IOCAP_ATOMIC2K 0x00000008
|
|
#define SQLITE_IOCAP_ATOMIC4K 0x00000010
|
|
#define SQLITE_IOCAP_ATOMIC8K 0x00000020
|
|
#define SQLITE_IOCAP_ATOMIC16K 0x00000040
|
|
#define SQLITE_IOCAP_ATOMIC32K 0x00000080
|
|
#define SQLITE_IOCAP_ATOMIC64K 0x00000100
|
|
#define SQLITE_IOCAP_SAFE_APPEND 0x00000200
|
|
#define SQLITE_IOCAP_SEQUENTIAL 0x00000400
|
|
#define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800
|
|
#define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000
|
|
#define SQLITE_IOCAP_IMMUTABLE 0x00002000
|
|
#define SQLITE_IOCAP_BATCH_ATOMIC 0x00004000
|
|
|
|
/*
|
|
** CAPI3REF: File Locking Levels
|
|
**
|
|
** SQLite uses one of these integer values as the second
|
|
** argument to calls it makes to the xLock() and xUnlock() methods
|
|
** of an [sqlite3_io_methods] object. These values are ordered from
|
|
** lest restrictive to most restrictive.
|
|
**
|
|
** The argument to xLock() is always SHARED or higher. The argument to
|
|
** xUnlock is either SHARED or NONE.
|
|
*/
|
|
#define SQLITE_LOCK_NONE 0 /* xUnlock() only */
|
|
#define SQLITE_LOCK_SHARED 1 /* xLock() or xUnlock() */
|
|
#define SQLITE_LOCK_RESERVED 2 /* xLock() only */
|
|
#define SQLITE_LOCK_PENDING 3 /* xLock() only */
|
|
#define SQLITE_LOCK_EXCLUSIVE 4 /* xLock() only */
|
|
|
|
/*
|
|
** CAPI3REF: Synchronization Type Flags
|
|
**
|
|
** When SQLite invokes the xSync() method of an
|
|
** [sqlite3_io_methods] object it uses a combination of
|
|
** these integer values as the second argument.
|
|
**
|
|
** When the SQLITE_SYNC_DATAONLY flag is used, it means that the
|
|
** sync operation only needs to flush data to mass storage. Inode
|
|
** information need not be flushed. If the lower four bits of the flag
|
|
** equal SQLITE_SYNC_NORMAL, that means to use normal fsync() semantics.
|
|
** If the lower four bits equal SQLITE_SYNC_FULL, that means
|
|
** to use Mac OS X style fullsync instead of fsync().
|
|
**
|
|
** Do not confuse the SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags
|
|
** with the [PRAGMA synchronous]=NORMAL and [PRAGMA synchronous]=FULL
|
|
** settings. The [synchronous pragma] determines when calls to the
|
|
** xSync VFS method occur and applies uniformly across all platforms.
|
|
** The SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL flags determine how
|
|
** energetic or rigorous or forceful the sync operations are and
|
|
** only make a difference on Mac OSX for the default SQLite code.
|
|
** (Third-party VFS implementations might also make the distinction
|
|
** between SQLITE_SYNC_NORMAL and SQLITE_SYNC_FULL, but among the
|
|
** operating systems natively supported by SQLite, only Mac OSX
|
|
** cares about the difference.)
|
|
*/
|
|
#define SQLITE_SYNC_NORMAL 0x00002
|
|
#define SQLITE_SYNC_FULL 0x00003
|
|
#define SQLITE_SYNC_DATAONLY 0x00010
|
|
|
|
/*
|
|
** CAPI3REF: OS Interface Open File Handle
|
|
**
|
|
** An [sqlite3_file] object represents an open file in the
|
|
** [sqlite3_vfs | OS interface layer]. Individual OS interface
|
|
** implementations will
|
|
** want to subclass this object by appending additional fields
|
|
** for their own use. The pMethods entry is a pointer to an
|
|
** [sqlite3_io_methods] object that defines methods for performing
|
|
** I/O operations on the open file.
|
|
*/
|
|
typedef struct sqlite3_file sqlite3_file;
|
|
struct sqlite3_file {
|
|
const struct sqlite3_io_methods *pMethods; /* Methods for an open file */
|
|
};
|
|
|
|
/*
|
|
** CAPI3REF: OS Interface File Virtual Methods Object
|
|
**
|
|
** Every file opened by the [sqlite3_vfs.xOpen] method populates an
|
|
** [sqlite3_file] object (or, more commonly, a subclass of the
|
|
** [sqlite3_file] object) with a pointer to an instance of this object.
|
|
** This object defines the methods used to perform various operations
|
|
** against the open file represented by the [sqlite3_file] object.
|
|
**
|
|
** If the [sqlite3_vfs.xOpen] method sets the sqlite3_file.pMethods element
|
|
** to a non-NULL pointer, then the sqlite3_io_methods.xClose method
|
|
** may be invoked even if the [sqlite3_vfs.xOpen] reported that it failed. The
|
|
** only way to prevent a call to xClose following a failed [sqlite3_vfs.xOpen]
|
|
** is for the [sqlite3_vfs.xOpen] to set the sqlite3_file.pMethods element
|
|
** to NULL.
|
|
**
|
|
** The flags argument to xSync may be one of [SQLITE_SYNC_NORMAL] or
|
|
** [SQLITE_SYNC_FULL]. The first choice is the normal fsync().
|
|
** The second choice is a Mac OS X style fullsync. The [SQLITE_SYNC_DATAONLY]
|
|
** flag may be ORed in to indicate that only the data of the file
|
|
** and not its inode needs to be synced.
|
|
**
|
|
** The integer values to xLock() and xUnlock() are one of
|
|
** <ul>
|
|
** <li> [SQLITE_LOCK_NONE],
|
|
** <li> [SQLITE_LOCK_SHARED],
|
|
** <li> [SQLITE_LOCK_RESERVED],
|
|
** <li> [SQLITE_LOCK_PENDING], or
|
|
** <li> [SQLITE_LOCK_EXCLUSIVE].
|
|
** </ul>
|
|
** xLock() upgrades the database file lock. In other words, xLock() moves the
|
|
** database file lock in the direction NONE toward EXCLUSIVE. The argument to
|
|
** xLock() is always on of SHARED, RESERVED, PENDING, or EXCLUSIVE, never
|
|
** SQLITE_LOCK_NONE. If the database file lock is already at or above the
|
|
** requested lock, then the call to xLock() is a no-op.
|
|
** xUnlock() downgrades the database file lock to either SHARED or NONE.
|
|
* If the lock is already at or below the requested lock state, then the call
|
|
** to xUnlock() is a no-op.
|
|
** The xCheckReservedLock() method checks whether any database connection,
|
|
** either in this process or in some other process, is holding a RESERVED,
|
|
** PENDING, or EXCLUSIVE lock on the file. It returns true
|
|
** if such a lock exists and false otherwise.
|
|
**
|
|
** The xFileControl() method is a generic interface that allows custom
|
|
** VFS implementations to directly control an open file using the
|
|
** [sqlite3_file_control()] interface. The second "op" argument is an
|
|
** integer opcode. The third argument is a generic pointer intended to
|
|
** point to a structure that may contain arguments or space in which to
|
|
** write return values. Potential uses for xFileControl() might be
|
|
** functions to enable blocking locks with timeouts, to change the
|
|
** locking strategy (for example to use dot-file locks), to inquire
|
|
** about the status of a lock, or to break stale locks. The SQLite
|
|
** core reserves all opcodes less than 100 for its own use.
|
|
** A [file control opcodes | list of opcodes] less than 100 is available.
|
|
** Applications that define a custom xFileControl method should use opcodes
|
|
** greater than 100 to avoid conflicts. VFS implementations should
|
|
** return [SQLITE_NOTFOUND] for file control opcodes that they do not
|
|
** recognize.
|
|
**
|
|
** The xSectorSize() method returns the sector size of the
|
|
** device that underlies the file. The sector size is the
|
|
** minimum write that can be performed without disturbing
|
|
** other bytes in the file. The xDeviceCharacteristics()
|
|
** method returns a bit vector describing behaviors of the
|
|
** underlying device:
|
|
**
|
|
** <ul>
|
|
** <li> [SQLITE_IOCAP_ATOMIC]
|
|
** <li> [SQLITE_IOCAP_ATOMIC512]
|
|
** <li> [SQLITE_IOCAP_ATOMIC1K]
|
|
** <li> [SQLITE_IOCAP_ATOMIC2K]
|
|
** <li> [SQLITE_IOCAP_ATOMIC4K]
|
|
** <li> [SQLITE_IOCAP_ATOMIC8K]
|
|
** <li> [SQLITE_IOCAP_ATOMIC16K]
|
|
** <li> [SQLITE_IOCAP_ATOMIC32K]
|
|
** <li> [SQLITE_IOCAP_ATOMIC64K]
|
|
** <li> [SQLITE_IOCAP_SAFE_APPEND]
|
|
** <li> [SQLITE_IOCAP_SEQUENTIAL]
|
|
** <li> [SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN]
|
|
** <li> [SQLITE_IOCAP_POWERSAFE_OVERWRITE]
|
|
** <li> [SQLITE_IOCAP_IMMUTABLE]
|
|
** <li> [SQLITE_IOCAP_BATCH_ATOMIC]
|
|
** </ul>
|
|
**
|
|
** The SQLITE_IOCAP_ATOMIC property means that all writes of
|
|
** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values
|
|
** mean that writes of blocks that are nnn bytes in size and
|
|
** are aligned to an address which is an integer multiple of
|
|
** nnn are atomic. The SQLITE_IOCAP_SAFE_APPEND value means
|
|
** that when data is appended to a file, the data is appended
|
|
** first then the size of the file is extended, never the other
|
|
** way around. The SQLITE_IOCAP_SEQUENTIAL property means that
|
|
** information is written to disk in the same order as calls
|
|
** to xWrite().
|
|
**
|
|
** If xRead() returns SQLITE_IOERR_SHORT_READ it must also fill
|
|
** in the unread portions of the buffer with zeros. A VFS that
|
|
** fails to zero-fill short reads might seem to work. However,
|
|
** failure to zero-fill short reads will eventually lead to
|
|
** database corruption.
|
|
*/
|
|
typedef struct sqlite3_io_methods sqlite3_io_methods;
|
|
struct sqlite3_io_methods {
|
|
int iVersion;
|
|
int (*xClose)(sqlite3_file*);
|
|
int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
|
|
int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst);
|
|
int (*xTruncate)(sqlite3_file*, sqlite3_int64 size);
|
|
int (*xSync)(sqlite3_file*, int flags);
|
|
int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize);
|
|
int (*xLock)(sqlite3_file*, int);
|
|
int (*xUnlock)(sqlite3_file*, int);
|
|
int (*xCheckReservedLock)(sqlite3_file*, int *pResOut);
|
|
int (*xFileControl)(sqlite3_file*, int op, void *pArg);
|
|
int (*xSectorSize)(sqlite3_file*);
|
|
int (*xDeviceCharacteristics)(sqlite3_file*);
|
|
/* Methods above are valid for version 1 */
|
|
int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
|
|
int (*xShmLock)(sqlite3_file*, int offset, int n, int flags);
|
|
void (*xShmBarrier)(sqlite3_file*);
|
|
int (*xShmUnmap)(sqlite3_file*, int deleteFlag);
|
|
/* Methods above are valid for version 2 */
|
|
int (*xFetch)(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
|
|
int (*xUnfetch)(sqlite3_file*, sqlite3_int64 iOfst, void *p);
|
|
/* Methods above are valid for version 3 */
|
|
/* Additional methods may be added in future releases */
|
|
};
|
|
|
|
/*
|
|
** CAPI3REF: Standard File Control Opcodes
|
|
** KEYWORDS: {file control opcodes} {file control opcode}
|
|
**
|
|
** These integer constants are opcodes for the xFileControl method
|
|
** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
|
|
** interface.
|
|
**
|
|
** <ul>
|
|
** <li>[[SQLITE_FCNTL_LOCKSTATE]]
|
|
** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This
|
|
** opcode causes the xFileControl method to write the current state of
|
|
** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED],
|
|
** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE])
|
|
** into an integer that the pArg argument points to.
|
|
** This capability is only available if SQLite is compiled with [SQLITE_DEBUG].
|
|
**
|
|
** <li>[[SQLITE_FCNTL_SIZE_HINT]]
|
|
** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS
|
|
** layer a hint of how large the database file will grow to be during the
|
|
** current transaction. This hint is not guaranteed to be accurate but it
|
|
** is often close. The underlying VFS might choose to preallocate database
|
|
** file space based on this hint in order to help writes to the database
|
|
** file run faster.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_SIZE_LIMIT]]
|
|
** The [SQLITE_FCNTL_SIZE_LIMIT] opcode is used by in-memory VFS that
|
|
** implements [sqlite3_deserialize()] to set an upper bound on the size
|
|
** of the in-memory database. The argument is a pointer to a [sqlite3_int64].
|
|
** If the integer pointed to is negative, then it is filled in with the
|
|
** current limit. Otherwise the limit is set to the larger of the value
|
|
** of the integer pointed to and the current database size. The integer
|
|
** pointed to is set to the new limit.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_CHUNK_SIZE]]
|
|
** The [SQLITE_FCNTL_CHUNK_SIZE] opcode is used to request that the VFS
|
|
** extends and truncates the database file in chunks of a size specified
|
|
** by the user. The fourth argument to [sqlite3_file_control()] should
|
|
** point to an integer (type int) containing the new chunk-size to use
|
|
** for the nominated database. Allocating database file space in large
|
|
** chunks (say 1MB at a time), may reduce file-system fragmentation and
|
|
** improve performance on some systems.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_FILE_POINTER]]
|
|
** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer
|
|
** to the [sqlite3_file] object associated with a particular database
|
|
** connection. See also [SQLITE_FCNTL_JOURNAL_POINTER].
|
|
**
|
|
** <li>[[SQLITE_FCNTL_JOURNAL_POINTER]]
|
|
** The [SQLITE_FCNTL_JOURNAL_POINTER] opcode is used to obtain a pointer
|
|
** to the [sqlite3_file] object associated with the journal file (either
|
|
** the [rollback journal] or the [write-ahead log]) for a particular database
|
|
** connection. See also [SQLITE_FCNTL_FILE_POINTER].
|
|
**
|
|
** <li>[[SQLITE_FCNTL_SYNC_OMITTED]]
|
|
** No longer in use.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_SYNC]]
|
|
** The [SQLITE_FCNTL_SYNC] opcode is generated internally by SQLite and
|
|
** sent to the VFS immediately before the xSync method is invoked on a
|
|
** database file descriptor. Or, if the xSync method is not invoked
|
|
** because the user has configured SQLite with
|
|
** [PRAGMA synchronous | PRAGMA synchronous=OFF] it is invoked in place
|
|
** of the xSync method. In most cases, the pointer argument passed with
|
|
** this file-control is NULL. However, if the database file is being synced
|
|
** as part of a multi-database commit, the argument points to a nul-terminated
|
|
** string containing the transactions super-journal file name. VFSes that
|
|
** do not need this signal should silently ignore this opcode. Applications
|
|
** should not call [sqlite3_file_control()] with this opcode as doing so may
|
|
** disrupt the operation of the specialized VFSes that do require it.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_COMMIT_PHASETWO]]
|
|
** The [SQLITE_FCNTL_COMMIT_PHASETWO] opcode is generated internally by SQLite
|
|
** and sent to the VFS after a transaction has been committed immediately
|
|
** but before the database is unlocked. VFSes that do not need this signal
|
|
** should silently ignore this opcode. Applications should not call
|
|
** [sqlite3_file_control()] with this opcode as doing so may disrupt the
|
|
** operation of the specialized VFSes that do require it.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_WIN32_AV_RETRY]]
|
|
** ^The [SQLITE_FCNTL_WIN32_AV_RETRY] opcode is used to configure automatic
|
|
** retry counts and intervals for certain disk I/O operations for the
|
|
** windows [VFS] in order to provide robustness in the presence of
|
|
** anti-virus programs. By default, the windows VFS will retry file read,
|
|
** file write, and file delete operations up to 10 times, with a delay
|
|
** of 25 milliseconds before the first retry and with the delay increasing
|
|
** by an additional 25 milliseconds with each subsequent retry. This
|
|
** opcode allows these two values (10 retries and 25 milliseconds of delay)
|
|
** to be adjusted. The values are changed for all database connections
|
|
** within the same process. The argument is a pointer to an array of two
|
|
** integers where the first integer is the new retry count and the second
|
|
** integer is the delay. If either integer is negative, then the setting
|
|
** is not changed but instead the prior value of that setting is written
|
|
** into the array entry, allowing the current retry settings to be
|
|
** interrogated. The zDbName parameter is ignored.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_PERSIST_WAL]]
|
|
** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the
|
|
** persistent [WAL | Write Ahead Log] setting. By default, the auxiliary
|
|
** write ahead log ([WAL file]) and shared memory
|
|
** files used for transaction control
|
|
** are automatically deleted when the latest connection to the database
|
|
** closes. Setting persistent WAL mode causes those files to persist after
|
|
** close. Persisting the files is useful when other processes that do not
|
|
** have write permission on the directory containing the database file want
|
|
** to read the database file, as the WAL and shared memory files must exist
|
|
** in order for the database to be readable. The fourth parameter to
|
|
** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
|
|
** That integer is 0 to disable persistent WAL mode or 1 to enable persistent
|
|
** WAL mode. If the integer is -1, then it is overwritten with the current
|
|
** WAL persistence setting.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_POWERSAFE_OVERWRITE]]
|
|
** ^The [SQLITE_FCNTL_POWERSAFE_OVERWRITE] opcode is used to set or query the
|
|
** persistent "powersafe-overwrite" or "PSOW" setting. The PSOW setting
|
|
** determines the [SQLITE_IOCAP_POWERSAFE_OVERWRITE] bit of the
|
|
** xDeviceCharacteristics methods. The fourth parameter to
|
|
** [sqlite3_file_control()] for this opcode should be a pointer to an integer.
|
|
** That integer is 0 to disable zero-damage mode or 1 to enable zero-damage
|
|
** mode. If the integer is -1, then it is overwritten with the current
|
|
** zero-damage mode setting.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_OVERWRITE]]
|
|
** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening
|
|
** a write transaction to indicate that, unless it is rolled back for some
|
|
** reason, the entire database file will be overwritten by the current
|
|
** transaction. This is used by VACUUM operations.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_VFSNAME]]
|
|
** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of
|
|
** all [VFSes] in the VFS stack. The names are of all VFS shims and the
|
|
** final bottom-level VFS are written into memory obtained from
|
|
** [sqlite3_malloc()] and the result is stored in the char* variable
|
|
** that the fourth parameter of [sqlite3_file_control()] points to.
|
|
** The caller is responsible for freeing the memory when done. As with
|
|
** all file-control actions, there is no guarantee that this will actually
|
|
** do anything. Callers should initialize the char* variable to a NULL
|
|
** pointer in case this file-control is not implemented. This file-control
|
|
** is intended for diagnostic use only.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_VFS_POINTER]]
|
|
** ^The [SQLITE_FCNTL_VFS_POINTER] opcode finds a pointer to the top-level
|
|
** [VFSes] currently in use. ^(The argument X in
|
|
** sqlite3_file_control(db,SQLITE_FCNTL_VFS_POINTER,X) must be
|
|
** of type "[sqlite3_vfs] **". This opcodes will set *X
|
|
** to a pointer to the top-level VFS.)^
|
|
** ^When there are multiple VFS shims in the stack, this opcode finds the
|
|
** upper-most shim only.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_PRAGMA]]
|
|
** ^Whenever a [PRAGMA] statement is parsed, an [SQLITE_FCNTL_PRAGMA]
|
|
** file control is sent to the open [sqlite3_file] object corresponding
|
|
** to the database file to which the pragma statement refers. ^The argument
|
|
** to the [SQLITE_FCNTL_PRAGMA] file control is an array of
|
|
** pointers to strings (char**) in which the second element of the array
|
|
** is the name of the pragma and the third element is the argument to the
|
|
** pragma or NULL if the pragma has no argument. ^The handler for an
|
|
** [SQLITE_FCNTL_PRAGMA] file control can optionally make the first element
|
|
** of the char** argument point to a string obtained from [sqlite3_mprintf()]
|
|
** or the equivalent and that string will become the result of the pragma or
|
|
** the error message if the pragma fails. ^If the
|
|
** [SQLITE_FCNTL_PRAGMA] file control returns [SQLITE_NOTFOUND], then normal
|
|
** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA]
|
|
** file control returns [SQLITE_OK], then the parser assumes that the
|
|
** VFS has handled the PRAGMA itself and the parser generates a no-op
|
|
** prepared statement if result string is NULL, or that returns a copy
|
|
** of the result string if the string is non-NULL.
|
|
** ^If the [SQLITE_FCNTL_PRAGMA] file control returns
|
|
** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means
|
|
** that the VFS encountered an error while handling the [PRAGMA] and the
|
|
** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA]
|
|
** file control occurs at the beginning of pragma statement analysis and so
|
|
** it is able to override built-in [PRAGMA] statements.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_BUSYHANDLER]]
|
|
** ^The [SQLITE_FCNTL_BUSYHANDLER]
|
|
** file-control may be invoked by SQLite on the database file handle
|
|
** shortly after it is opened in order to provide a custom VFS with access
|
|
** to the connection's busy-handler callback. The argument is of type (void**)
|
|
** - an array of two (void *) values. The first (void *) actually points
|
|
** to a function of type (int (*)(void *)). In order to invoke the connection's
|
|
** busy-handler, this function should be invoked with the second (void *) in
|
|
** the array as the only argument. If it returns non-zero, then the operation
|
|
** should be retried. If it returns zero, the custom VFS should abandon the
|
|
** current operation.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_TEMPFILENAME]]
|
|
** ^Applications can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control
|
|
** to have SQLite generate a
|
|
** temporary filename using the same algorithm that is followed to generate
|
|
** temporary filenames for TEMP tables and other internal uses. The
|
|
** argument should be a char** which will be filled with the filename
|
|
** written into memory obtained from [sqlite3_malloc()]. The caller should
|
|
** invoke [sqlite3_free()] on the result to avoid a memory leak.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_MMAP_SIZE]]
|
|
** The [SQLITE_FCNTL_MMAP_SIZE] file control is used to query or set the
|
|
** maximum number of bytes that will be used for memory-mapped I/O.
|
|
** The argument is a pointer to a value of type sqlite3_int64 that
|
|
** is an advisory maximum number of bytes in the file to memory map. The
|
|
** pointer is overwritten with the old value. The limit is not changed if
|
|
** the value originally pointed to is negative, and so the current limit
|
|
** can be queried by passing in a pointer to a negative number. This
|
|
** file-control is used internally to implement [PRAGMA mmap_size].
|
|
**
|
|
** <li>[[SQLITE_FCNTL_TRACE]]
|
|
** The [SQLITE_FCNTL_TRACE] file control provides advisory information
|
|
** to the VFS about what the higher layers of the SQLite stack are doing.
|
|
** This file control is used by some VFS activity tracing [shims].
|
|
** The argument is a zero-terminated string. Higher layers in the
|
|
** SQLite stack may generate instances of this file control if
|
|
** the [SQLITE_USE_FCNTL_TRACE] compile-time option is enabled.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_HAS_MOVED]]
|
|
** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a
|
|
** pointer to an integer and it writes a boolean into that integer depending
|
|
** on whether or not the file has been renamed, moved, or deleted since it
|
|
** was first opened.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_WIN32_GET_HANDLE]]
|
|
** The [SQLITE_FCNTL_WIN32_GET_HANDLE] opcode can be used to obtain the
|
|
** underlying native file handle associated with a file handle. This file
|
|
** control interprets its argument as a pointer to a native file handle and
|
|
** writes the resulting value there.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]]
|
|
** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This
|
|
** opcode causes the xFileControl method to swap the file handle with the one
|
|
** pointed to by the pArg argument. This capability is used during testing
|
|
** and only needs to be supported when SQLITE_TEST is defined.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_WAL_BLOCK]]
|
|
** The [SQLITE_FCNTL_WAL_BLOCK] is a signal to the VFS layer that it might
|
|
** be advantageous to block on the next WAL lock if the lock is not immediately
|
|
** available. The WAL subsystem issues this signal during rare
|
|
** circumstances in order to fix a problem with priority inversion.
|
|
** Applications should <em>not</em> use this file-control.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_ZIPVFS]]
|
|
** The [SQLITE_FCNTL_ZIPVFS] opcode is implemented by zipvfs only. All other
|
|
** VFS should return SQLITE_NOTFOUND for this opcode.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_RBU]]
|
|
** The [SQLITE_FCNTL_RBU] opcode is implemented by the special VFS used by
|
|
** the RBU extension only. All other VFS should return SQLITE_NOTFOUND for
|
|
** this opcode.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_BEGIN_ATOMIC_WRITE]]
|
|
** If the [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] opcode returns SQLITE_OK, then
|
|
** the file descriptor is placed in "batch write mode", which
|
|
** means all subsequent write operations will be deferred and done
|
|
** atomically at the next [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]. Systems
|
|
** that do not support batch atomic writes will return SQLITE_NOTFOUND.
|
|
** ^Following a successful SQLITE_FCNTL_BEGIN_ATOMIC_WRITE and prior to
|
|
** the closing [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE] or
|
|
** [SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE], SQLite will make
|
|
** no VFS interface calls on the same [sqlite3_file] file descriptor
|
|
** except for calls to the xWrite method and the xFileControl method
|
|
** with [SQLITE_FCNTL_SIZE_HINT].
|
|
**
|
|
** <li>[[SQLITE_FCNTL_COMMIT_ATOMIC_WRITE]]
|
|
** The [SQLITE_FCNTL_COMMIT_ATOMIC_WRITE] opcode causes all write
|
|
** operations since the previous successful call to
|
|
** [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] to be performed atomically.
|
|
** This file control returns [SQLITE_OK] if and only if the writes were
|
|
** all performed successfully and have been committed to persistent storage.
|
|
** ^Regardless of whether or not it is successful, this file control takes
|
|
** the file descriptor out of batch write mode so that all subsequent
|
|
** write operations are independent.
|
|
** ^SQLite will never invoke SQLITE_FCNTL_COMMIT_ATOMIC_WRITE without
|
|
** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE].
|
|
**
|
|
** <li>[[SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE]]
|
|
** The [SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE] opcode causes all write
|
|
** operations since the previous successful call to
|
|
** [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE] to be rolled back.
|
|
** ^This file control takes the file descriptor out of batch write mode
|
|
** so that all subsequent write operations are independent.
|
|
** ^SQLite will never invoke SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE without
|
|
** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE].
|
|
**
|
|
** <li>[[SQLITE_FCNTL_LOCK_TIMEOUT]]
|
|
** The [SQLITE_FCNTL_LOCK_TIMEOUT] opcode is used to configure a VFS
|
|
** to block for up to M milliseconds before failing when attempting to
|
|
** obtain a file lock using the xLock or xShmLock methods of the VFS.
|
|
** The parameter is a pointer to a 32-bit signed integer that contains
|
|
** the value that M is to be set to. Before returning, the 32-bit signed
|
|
** integer is overwritten with the previous value of M.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_DATA_VERSION]]
|
|
** The [SQLITE_FCNTL_DATA_VERSION] opcode is used to detect changes to
|
|
** a database file. The argument is a pointer to a 32-bit unsigned integer.
|
|
** The "data version" for the pager is written into the pointer. The
|
|
** "data version" changes whenever any change occurs to the corresponding
|
|
** database file, either through SQL statements on the same database
|
|
** connection or through transactions committed by separate database
|
|
** connections possibly in other processes. The [sqlite3_total_changes()]
|
|
** interface can be used to find if any database on the connection has changed,
|
|
** but that interface responds to changes on TEMP as well as MAIN and does
|
|
** not provide a mechanism to detect changes to MAIN only. Also, the
|
|
** [sqlite3_total_changes()] interface responds to internal changes only and
|
|
** omits changes made by other database connections. The
|
|
** [PRAGMA data_version] command provides a mechanism to detect changes to
|
|
** a single attached database that occur due to other database connections,
|
|
** but omits changes implemented by the database connection on which it is
|
|
** called. This file control is the only mechanism to detect changes that
|
|
** happen either internally or externally and that are associated with
|
|
** a particular attached database.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_CKPT_START]]
|
|
** The [SQLITE_FCNTL_CKPT_START] opcode is invoked from within a checkpoint
|
|
** in wal mode before the client starts to copy pages from the wal
|
|
** file to the database file.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_CKPT_DONE]]
|
|
** The [SQLITE_FCNTL_CKPT_DONE] opcode is invoked from within a checkpoint
|
|
** in wal mode after the client has finished copying pages from the wal
|
|
** file to the database file, but before the *-shm file is updated to
|
|
** record the fact that the pages have been checkpointed.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_EXTERNAL_READER]]
|
|
** The EXPERIMENTAL [SQLITE_FCNTL_EXTERNAL_READER] opcode is used to detect
|
|
** whether or not there is a database client in another process with a wal-mode
|
|
** transaction open on the database or not. It is only available on unix.The
|
|
** (void*) argument passed with this file-control should be a pointer to a
|
|
** value of type (int). The integer value is set to 1 if the database is a wal
|
|
** mode database and there exists at least one client in another process that
|
|
** currently has an SQL transaction open on the database. It is set to 0 if
|
|
** the database is not a wal-mode db, or if there is no such connection in any
|
|
** other process. This opcode cannot be used to detect transactions opened
|
|
** by clients within the current process, only within other processes.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_CKSM_FILE]]
|
|
** The [SQLITE_FCNTL_CKSM_FILE] opcode is for use internally by the
|
|
** [checksum VFS shim] only.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_RESET_CACHE]]
|
|
** If there is currently no transaction open on the database, and the
|
|
** database is not a temp db, then the [SQLITE_FCNTL_RESET_CACHE] file-control
|
|
** purges the contents of the in-memory page cache. If there is an open
|
|
** transaction, or if the db is a temp-db, this opcode is a no-op, not an error.
|
|
** </ul>
|
|
*/
|
|
#define SQLITE_FCNTL_LOCKSTATE 1
|
|
#define SQLITE_FCNTL_GET_LOCKPROXYFILE 2
|
|
#define SQLITE_FCNTL_SET_LOCKPROXYFILE 3
|
|
#define SQLITE_FCNTL_LAST_ERRNO 4
|
|
#define SQLITE_FCNTL_SIZE_HINT 5
|
|
#define SQLITE_FCNTL_CHUNK_SIZE 6
|
|
#define SQLITE_FCNTL_FILE_POINTER 7
|
|
#define SQLITE_FCNTL_SYNC_OMITTED 8
|
|
#define SQLITE_FCNTL_WIN32_AV_RETRY 9
|
|
#define SQLITE_FCNTL_PERSIST_WAL 10
|
|
#define SQLITE_FCNTL_OVERWRITE 11
|
|
#define SQLITE_FCNTL_VFSNAME 12
|
|
#define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13
|
|
#define SQLITE_FCNTL_PRAGMA 14
|
|
#define SQLITE_FCNTL_BUSYHANDLER 15
|
|
#define SQLITE_FCNTL_TEMPFILENAME 16
|
|
#define SQLITE_FCNTL_MMAP_SIZE 18
|
|
#define SQLITE_FCNTL_TRACE 19
|
|
#define SQLITE_FCNTL_HAS_MOVED 20
|
|
#define SQLITE_FCNTL_SYNC 21
|
|
#define SQLITE_FCNTL_COMMIT_PHASETWO 22
|
|
#define SQLITE_FCNTL_WIN32_SET_HANDLE 23
|
|
#define SQLITE_FCNTL_WAL_BLOCK 24
|
|
#define SQLITE_FCNTL_ZIPVFS 25
|
|
#define SQLITE_FCNTL_RBU 26
|
|
#define SQLITE_FCNTL_VFS_POINTER 27
|
|
#define SQLITE_FCNTL_JOURNAL_POINTER 28
|
|
#define SQLITE_FCNTL_WIN32_GET_HANDLE 29
|
|
#define SQLITE_FCNTL_PDB 30
|
|
#define SQLITE_FCNTL_BEGIN_ATOMIC_WRITE 31
|
|
#define SQLITE_FCNTL_COMMIT_ATOMIC_WRITE 32
|
|
#define SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE 33
|
|
#define SQLITE_FCNTL_LOCK_TIMEOUT 34
|
|
#define SQLITE_FCNTL_DATA_VERSION 35
|
|
#define SQLITE_FCNTL_SIZE_LIMIT 36
|
|
#define SQLITE_FCNTL_CKPT_DONE 37
|
|
#define SQLITE_FCNTL_RESERVE_BYTES 38
|
|
#define SQLITE_FCNTL_CKPT_START 39
|
|
#define SQLITE_FCNTL_EXTERNAL_READER 40
|
|
#define SQLITE_FCNTL_CKSM_FILE 41
|
|
#define SQLITE_FCNTL_RESET_CACHE 42
|
|
|
|
/* deprecated names */
|
|
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
|
|
#define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE
|
|
#define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO
|
|
|
|
|
|
/*
|
|
** CAPI3REF: Mutex Handle
|
|
**
|
|
** The mutex module within SQLite defines [sqlite3_mutex] to be an
|
|
** abstract type for a mutex object. The SQLite core never looks
|
|
** at the internal representation of an [sqlite3_mutex]. It only
|
|
** deals with pointers to the [sqlite3_mutex] object.
|
|
**
|
|
** Mutexes are created using [sqlite3_mutex_alloc()].
|
|
*/
|
|
typedef struct sqlite3_mutex sqlite3_mutex;
|
|
|
|
/*
|
|
** CAPI3REF: Loadable Extension Thunk
|
|
**
|
|
** A pointer to the opaque sqlite3_api_routines structure is passed as
|
|
** the third parameter to entry points of [loadable extensions]. This
|
|
** structure must be typedefed in order to work around compiler warnings
|
|
** on some platforms.
|
|
*/
|
|
typedef struct sqlite3_api_routines sqlite3_api_routines;
|
|
|
|
/*
|
|
** CAPI3REF: File Name
|
|
**
|
|
** Type [sqlite3_filename] is used by SQLite to pass filenames to the
|
|
** xOpen method of a [VFS]. It may be cast to (const char*) and treated
|
|
** as a normal, nul-terminated, UTF-8 buffer containing the filename, but
|
|
** may also be passed to special APIs such as:
|
|
**
|
|
** <ul>
|
|
** <li> sqlite3_filename_database()
|
|
** <li> sqlite3_filename_journal()
|
|
** <li> sqlite3_filename_wal()
|
|
** <li> sqlite3_uri_parameter()
|
|
** <li> sqlite3_uri_boolean()
|
|
** <li> sqlite3_uri_int64()
|
|
** <li> sqlite3_uri_key()
|
|
** </ul>
|
|
*/
|
|
typedef const char *sqlite3_filename;
|
|
|
|
/*
|
|
** CAPI3REF: OS Interface Object
|
|
**
|
|
** An instance of the sqlite3_vfs object defines the interface between
|
|
** the SQLite core and the underlying operating system. The "vfs"
|
|
** in the name of the object stands for "virtual file system". See
|
|
** the [VFS | VFS documentation] for further information.
|
|
**
|
|
** The VFS interface is sometimes extended by adding new methods onto
|
|
** the end. Each time such an extension occurs, the iVersion field
|
|
** is incremented. The iVersion value started out as 1 in
|
|
** SQLite [version 3.5.0] on [dateof:3.5.0], then increased to 2
|
|
** with SQLite [version 3.7.0] on [dateof:3.7.0], and then increased
|
|
** to 3 with SQLite [version 3.7.6] on [dateof:3.7.6]. Additional fields
|
|
** may be appended to the sqlite3_vfs object and the iVersion value
|
|
** may increase again in future versions of SQLite.
|
|
** Note that due to an oversight, the structure
|
|
** of the sqlite3_vfs object changed in the transition from
|
|
** SQLite [version 3.5.9] to [version 3.6.0] on [dateof:3.6.0]
|
|
** and yet the iVersion field was not increased.
|
|
**
|
|
** The szOsFile field is the size of the subclassed [sqlite3_file]
|
|
** structure used by this VFS. mxPathname is the maximum length of
|
|
** a pathname in this VFS.
|
|
**
|
|
** Registered sqlite3_vfs objects are kept on a linked list formed by
|
|
** the pNext pointer. The [sqlite3_vfs_register()]
|
|
** and [sqlite3_vfs_unregister()] interfaces manage this list
|
|
** in a thread-safe way. The [sqlite3_vfs_find()] interface
|
|
** searches the list. Neither the application code nor the VFS
|
|
** implementation should use the pNext pointer.
|
|
**
|
|
** The pNext field is the only field in the sqlite3_vfs
|
|
** structure that SQLite will ever modify. SQLite will only access
|
|
** or modify this field while holding a particular static mutex.
|
|
** The application should never modify anything within the sqlite3_vfs
|
|
** object once the object has been registered.
|
|
**
|
|
** The zName field holds the name of the VFS module. The name must
|
|
** be unique across all VFS modules.
|
|
**
|
|
** [[sqlite3_vfs.xOpen]]
|
|
** ^SQLite guarantees that the zFilename parameter to xOpen
|
|
** is either a NULL pointer or string obtained
|
|
** from xFullPathname() with an optional suffix added.
|
|
** ^If a suffix is added to the zFilename parameter, it will
|
|
** consist of a single "-" character followed by no more than
|
|
** 11 alphanumeric and/or "-" characters.
|
|
** ^SQLite further guarantees that
|
|
** the string will be valid and unchanged until xClose() is
|
|
** called. Because of the previous sentence,
|
|
** the [sqlite3_file] can safely store a pointer to the
|
|
** filename if it needs to remember the filename for some reason.
|
|
** If the zFilename parameter to xOpen is a NULL pointer then xOpen
|
|
** must invent its own temporary name for the file. ^Whenever the
|
|
** xFilename parameter is NULL it will also be the case that the
|
|
** flags parameter will include [SQLITE_OPEN_DELETEONCLOSE].
|
|
**
|
|
** The flags argument to xOpen() includes all bits set in
|
|
** the flags argument to [sqlite3_open_v2()]. Or if [sqlite3_open()]
|
|
** or [sqlite3_open16()] is used, then flags includes at least
|
|
** [SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE].
|
|
** If xOpen() opens a file read-only then it sets *pOutFlags to
|
|
** include [SQLITE_OPEN_READONLY]. Other bits in *pOutFlags may be set.
|
|
**
|
|
** ^(SQLite will also add one of the following flags to the xOpen()
|
|
** call, depending on the object being opened:
|
|
**
|
|
** <ul>
|
|
** <li> [SQLITE_OPEN_MAIN_DB]
|
|
** <li> [SQLITE_OPEN_MAIN_JOURNAL]
|
|
** <li> [SQLITE_OPEN_TEMP_DB]
|
|
** <li> [SQLITE_OPEN_TEMP_JOURNAL]
|
|
** <li> [SQLITE_OPEN_TRANSIENT_DB]
|
|
** <li> [SQLITE_OPEN_SUBJOURNAL]
|
|
** <li> [SQLITE_OPEN_SUPER_JOURNAL]
|
|
** <li> [SQLITE_OPEN_WAL]
|
|
** </ul>)^
|
|
**
|
|
** The file I/O implementation can use the object type flags to
|
|
** change the way it deals with files. For example, an application
|
|
** that does not care about crash recovery or rollback might make
|
|
** the open of a journal file a no-op. Writes to this journal would
|
|
** also be no-ops, and any attempt to read the journal would return
|
|
** SQLITE_IOERR. Or the implementation might recognize that a database
|
|
** file will be doing page-aligned sector reads and writes in a random
|
|
** order and set up its I/O subsystem accordingly.
|
|
**
|
|
** SQLite might also add one of the following flags to the xOpen method:
|
|
**
|
|
** <ul>
|
|
** <li> [SQLITE_OPEN_DELETEONCLOSE]
|
|
** <li> [SQLITE_OPEN_EXCLUSIVE]
|
|
** </ul>
|
|
**
|
|
** The [SQLITE_OPEN_DELETEONCLOSE] flag means the file should be
|
|
** deleted when it is closed. ^The [SQLITE_OPEN_DELETEONCLOSE]
|
|
** will be set for TEMP databases and their journals, transient
|
|
** databases, and subjournals.
|
|
**
|
|
** ^The [SQLITE_OPEN_EXCLUSIVE] flag is always used in conjunction
|
|
** with the [SQLITE_OPEN_CREATE] flag, which are both directly
|
|
** analogous to the O_EXCL and O_CREAT flags of the POSIX open()
|
|
** API. The SQLITE_OPEN_EXCLUSIVE flag, when paired with the
|
|
** SQLITE_OPEN_CREATE, is used to indicate that file should always
|
|
** be created, and that it is an error if it already exists.
|
|
** It is <i>not</i> used to indicate the file should be opened
|
|
** for exclusive access.
|
|
**
|
|
** ^At least szOsFile bytes of memory are allocated by SQLite
|
|
** to hold the [sqlite3_file] structure passed as the third
|
|
** argument to xOpen. The xOpen method does not have to
|
|
** allocate the structure; it should just fill it in. Note that
|
|
** the xOpen method must set the sqlite3_file.pMethods to either
|
|
** a valid [sqlite3_io_methods] object or to NULL. xOpen must do
|
|
** this even if the open fails. SQLite expects that the sqlite3_file.pMethods
|
|
** element will be valid after xOpen returns regardless of the success
|
|
** or failure of the xOpen call.
|
|
**
|
|
** [[sqlite3_vfs.xAccess]]
|
|
** ^The flags argument to xAccess() may be [SQLITE_ACCESS_EXISTS]
|
|
** to test for the existence of a file, or [SQLITE_ACCESS_READWRITE] to
|
|
** test whether a file is readable and writable, or [SQLITE_ACCESS_READ]
|
|
** to test whether a file is at least readable. The SQLITE_ACCESS_READ
|
|
** flag is never actually used and is not implemented in the built-in
|
|
** VFSes of SQLite. The file is named by the second argument and can be a
|
|
** directory. The xAccess method returns [SQLITE_OK] on success or some
|
|
** non-zero error code if there is an I/O error or if the name of
|
|
** the file given in the second argument is illegal. If SQLITE_OK
|
|
** is returned, then non-zero or zero is written into *pResOut to indicate
|
|
** whether or not the file is accessible.
|
|
**
|
|
** ^SQLite will always allocate at least mxPathname+1 bytes for the
|
|
** output buffer xFullPathname. The exact size of the output buffer
|
|
** is also passed as a parameter to both methods. If the output buffer
|
|
** is not large enough, [SQLITE_CANTOPEN] should be returned. Since this is
|
|
** handled as a fatal error by SQLite, vfs implementations should endeavor
|
|
** to prevent this by setting mxPathname to a sufficiently large value.
|
|
**
|
|
** The xRandomness(), xSleep(), xCurrentTime(), and xCurrentTimeInt64()
|
|
** interfaces are not strictly a part of the filesystem, but they are
|
|
** included in the VFS structure for completeness.
|
|
** The xRandomness() function attempts to return nBytes bytes
|
|
** of good-quality randomness into zOut. The return value is
|
|
** the actual number of bytes of randomness obtained.
|
|
** The xSleep() method causes the calling thread to sleep for at
|
|
** least the number of microseconds given. ^The xCurrentTime()
|
|
** method returns a Julian Day Number for the current date and time as
|
|
** a floating point value.
|
|
** ^The xCurrentTimeInt64() method returns, as an integer, the Julian
|
|
** Day Number multiplied by 86400000 (the number of milliseconds in
|
|
** a 24-hour day).
|
|
** ^SQLite will use the xCurrentTimeInt64() method to get the current
|
|
** date and time if that method is available (if iVersion is 2 or
|
|
** greater and the function pointer is not NULL) and will fall back
|
|
** to xCurrentTime() if xCurrentTimeInt64() is unavailable.
|
|
**
|
|
** ^The xSetSystemCall(), xGetSystemCall(), and xNestSystemCall() interfaces
|
|
** are not used by the SQLite core. These optional interfaces are provided
|
|
** by some VFSes to facilitate testing of the VFS code. By overriding
|
|
** system calls with functions under its control, a test program can
|
|
** simulate faults and error conditions that would otherwise be difficult
|
|
** or impossible to induce. The set of system calls that can be overridden
|
|
** varies from one VFS to another, and from one version of the same VFS to the
|
|
** next. Applications that use these interfaces must be prepared for any
|
|
** or all of these interfaces to be NULL or for their behavior to change
|
|
** from one release to the next. Applications must not attempt to access
|
|
** any of these methods if the iVersion of the VFS is less than 3.
|
|
*/
|
|
typedef struct sqlite3_vfs sqlite3_vfs;
|
|
typedef void (*sqlite3_syscall_ptr)(void);
|
|
struct sqlite3_vfs {
|
|
int iVersion; /* Structure version number (currently 3) */
|
|
int szOsFile; /* Size of subclassed sqlite3_file */
|
|
int mxPathname; /* Maximum file pathname length */
|
|
sqlite3_vfs *pNext; /* Next registered VFS */
|
|
const char *zName; /* Name of this virtual file system */
|
|
void *pAppData; /* Pointer to application-specific data */
|
|
int (*xOpen)(sqlite3_vfs*, sqlite3_filename zName, sqlite3_file*,
|
|
int flags, int *pOutFlags);
|
|
int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir);
|
|
int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut);
|
|
int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut);
|
|
void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename);
|
|
void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg);
|
|
void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void);
|
|
void (*xDlClose)(sqlite3_vfs*, void*);
|
|
int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut);
|
|
int (*xSleep)(sqlite3_vfs*, int microseconds);
|
|
int (*xCurrentTime)(sqlite3_vfs*, double*);
|
|
int (*xGetLastError)(sqlite3_vfs*, int, char *);
|
|
/*
|
|
** The methods above are in version 1 of the sqlite_vfs object
|
|
** definition. Those that follow are added in version 2 or later
|
|
*/
|
|
int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*);
|
|
/*
|
|
** The methods above are in versions 1 and 2 of the sqlite_vfs object.
|
|
** Those below are for version 3 and greater.
|
|
*/
|
|
int (*xSetSystemCall)(sqlite3_vfs*, const char *zName, sqlite3_syscall_ptr);
|
|
sqlite3_syscall_ptr (*xGetSystemCall)(sqlite3_vfs*, const char *zName);
|
|
const char *(*xNextSystemCall)(sqlite3_vfs*, const char *zName);
|
|
/*
|
|
** The methods above are in versions 1 through 3 of the sqlite_vfs object.
|
|
** New fields may be appended in future versions. The iVersion
|
|
** value will increment whenever this happens.
|
|
*/
|
|
};
|
|
|
|
/*
|
|
** CAPI3REF: Flags for the xAccess VFS method
|
|
**
|
|
** These integer constants can be used as the third parameter to
|
|
** the xAccess method of an [sqlite3_vfs] object. They determine
|
|
** what kind of permissions the xAccess method is looking for.
|
|
** With SQLITE_ACCESS_EXISTS, the xAccess method
|
|
** simply checks whether the file exists.
|
|
** With SQLITE_ACCESS_READWRITE, the xAccess method
|
|
** checks whether the named directory is both readable and writable
|
|
** (in other words, if files can be added, removed, and renamed within
|
|
** the directory).
|
|
** The SQLITE_ACCESS_READWRITE constant is currently used only by the
|
|
** [temp_store_directory pragma], though this could change in a future
|
|
** release of SQLite.
|
|
** With SQLITE_ACCESS_READ, the xAccess method
|
|
** checks whether the file is readable. The SQLITE_ACCESS_READ constant is
|
|
** currently unused, though it might be used in a future release of
|
|
** SQLite.
|
|
*/
|
|
#define SQLITE_ACCESS_EXISTS 0
|
|
#define SQLITE_ACCESS_READWRITE 1 /* Used by PRAGMA temp_store_directory */
|
|
#define SQLITE_ACCESS_READ 2 /* Unused */
|
|
|
|
/*
|
|
** CAPI3REF: Flags for the xShmLock VFS method
|
|
**
|
|
** These integer constants define the various locking operations
|
|
** allowed by the xShmLock method of [sqlite3_io_methods]. The
|
|
** following are the only legal combinations of flags to the
|
|
** xShmLock method:
|
|
**
|
|
** <ul>
|
|
** <li> SQLITE_SHM_LOCK | SQLITE_SHM_SHARED
|
|
** <li> SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE
|
|
** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED
|
|
** <li> SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE
|
|
** </ul>
|
|
**
|
|
** When unlocking, the same SHARED or EXCLUSIVE flag must be supplied as
|
|
** was given on the corresponding lock.
|
|
**
|
|
** The xShmLock method can transition between unlocked and SHARED or
|
|
** between unlocked and EXCLUSIVE. It cannot transition between SHARED
|
|
** and EXCLUSIVE.
|
|
*/
|
|
#define SQLITE_SHM_UNLOCK 1
|
|
#define SQLITE_SHM_LOCK 2
|
|
#define SQLITE_SHM_SHARED 4
|
|
#define SQLITE_SHM_EXCLUSIVE 8
|
|
|
|
/*
|
|
** CAPI3REF: Maximum xShmLock index
|
|
**
|
|
** The xShmLock method on [sqlite3_io_methods] may use values
|
|
** between 0 and this upper bound as its "offset" argument.
|
|
** The SQLite core will never attempt to acquire or release a
|
|
** lock outside of this range
|
|
*/
|
|
#define SQLITE_SHM_NLOCK 8
|
|
|
|
|
|
/*
|
|
** CAPI3REF: Initialize The SQLite Library
|
|
**
|
|
** ^The sqlite3_initialize() routine initializes the
|
|
** SQLite library. ^The sqlite3_shutdown() routine
|
|
** deallocates any resources that were allocated by sqlite3_initialize().
|
|
** These routines are designed to aid in process initialization and
|
|
** shutdown on embedded systems. Workstation applications using
|
|
** SQLite normally do not need to invoke either of these routines.
|
|
**
|
|
** A call to sqlite3_initialize() is an "effective" call if it is
|
|
** the first time sqlite3_initialize() is invoked during the lifetime of
|
|
** the process, or if it is the first time sqlite3_initialize() is invoked
|
|
** following a call to sqlite3_shutdown(). ^(Only an effective call
|
|
** of sqlite3_initialize() does any initialization. All other calls
|
|
** are harmless no-ops.)^
|
|
**
|
|
** A call to sqlite3_shutdown() is an "effective" call if it is the first
|
|
** call to sqlite3_shutdown() since the last sqlite3_initialize(). ^(Only
|
|
** an effective call to sqlite3_shutdown() does any deinitialization.
|
|
** All other valid calls to sqlite3_shutdown() are harmless no-ops.)^
|
|
**
|
|
** The sqlite3_initialize() interface is threadsafe, but sqlite3_shutdown()
|
|
** is not. The sqlite3_shutdown() interface must only be called from a
|
|
** single thread. All open [database connections] must be closed and all
|
|
** other SQLite resources must be deallocated prior to invoking
|
|
** sqlite3_shutdown().
|
|
**
|
|
** Among other things, ^sqlite3_initialize() will invoke
|
|
** sqlite3_os_init(). Similarly, ^sqlite3_shutdown()
|
|
** will invoke sqlite3_os_end().
|
|
**
|
|
** ^The sqlite3_initialize() routine returns [SQLITE_OK] on success.
|
|
** ^If for some reason, sqlite3_initialize() is unable to initialize
|
|
** the library (perhaps it is unable to allocate a needed resource such
|
|
** as a mutex) it returns an [error code] other than [SQLITE_OK].
|
|
**
|
|
** ^The sqlite3_initialize() routine is called internally by many other
|
|
** SQLite interfaces so that an application usually does not need to
|
|
** invoke sqlite3_initialize() directly. For example, [sqlite3_open()]
|
|
** calls sqlite3_initialize() so the SQLite library will be automatically
|
|
** initialized when [sqlite3_open()] is called if it has not be initialized
|
|
** already. ^However, if SQLite is compiled with the [SQLITE_OMIT_AUTOINIT]
|
|
** compile-time option, then the automatic calls to sqlite3_initialize()
|
|
** are omitted and the application must call sqlite3_initialize() directly
|
|
** prior to using any other SQLite interface. For maximum portability,
|
|
** it is recommended that applications always invoke sqlite3_initialize()
|
|
** directly prior to using any other SQLite interface. Future releases
|
|
** of SQLite may require this. In other words, the behavior exhibited
|
|
** when SQLite is compiled with [SQLITE_OMIT_AUTOINIT] might become the
|
|
** default behavior in some future release of SQLite.
|
|
**
|
|
** The sqlite3_os_init() routine does operating-system specific
|
|
** initialization of the SQLite library. The sqlite3_os_end()
|
|
** routine undoes the effect of sqlite3_os_init(). Typical tasks
|
|
** performed by these routines include allocation or deallocation
|
|
** of static resources, initialization of global variables,
|
|
** setting up a default [sqlite3_vfs] module, or setting up
|
|
** a default configuration using [sqlite3_config()].
|
|
**
|
|
** The application should never invoke either sqlite3_os_init()
|
|
** or sqlite3_os_end() directly. The application should only invoke
|
|
** sqlite3_initialize() and sqlite3_shutdown(). The sqlite3_os_init()
|
|
** interface is called automatically by sqlite3_initialize() and
|
|
** sqlite3_os_end() is called by sqlite3_shutdown(). Appropriate
|
|
** implementations for sqlite3_os_init() and sqlite3_os_end()
|
|
** are built into SQLite when it is compiled for Unix, Windows, or OS/2.
|
|
** When [custom builds | built for other platforms]
|
|
** (using the [SQLITE_OS_OTHER=1] compile-time
|
|
** option) the application must supply a suitable implementation for
|
|
** sqlite3_os_init() and sqlite3_os_end(). An application-supplied
|
|
** implementation of sqlite3_os_init() or sqlite3_os_end()
|
|
** must return [SQLITE_OK] on success and some other [error code] upon
|
|
** failure.
|
|
*/
|
|
SQLITE_API int sqlite3_initialize(void);
|
|
SQLITE_API int sqlite3_shutdown(void);
|
|
SQLITE_API int sqlite3_os_init(void);
|
|
SQLITE_API int sqlite3_os_end(void);
|
|
|
|
/*
|
|
** CAPI3REF: Configuring The SQLite Library
|
|
**
|
|
** The sqlite3_config() interface is used to make global configuration
|
|
** changes to SQLite in order to tune SQLite to the specific needs of
|
|
** the application. The default configuration is recommended for most
|
|
** applications and so this routine is usually not necessary. It is
|
|
** provided to support rare applications with unusual needs.
|
|
**
|
|
** <b>The sqlite3_config() interface is not threadsafe. The application
|
|
** must ensure that no other SQLite interfaces are invoked by other
|
|
** threads while sqlite3_config() is running.</b>
|
|
**
|
|
** The first argument to sqlite3_config() is an integer
|
|
** [configuration option] that determines
|
|
** what property of SQLite is to be configured. Subsequent arguments
|
|
** vary depending on the [configuration option]
|
|
** in the first argument.
|
|
**
|
|
** For most configuration options, the sqlite3_config() interface
|
|
** may only be invoked prior to library initialization using
|
|
** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()].
|
|
** The exceptional configuration options that may be invoked at any time
|
|
** are called "anytime configuration options".
|
|
** ^If sqlite3_config() is called after [sqlite3_initialize()] and before
|
|
** [sqlite3_shutdown()] with a first argument that is not an anytime
|
|
** configuration option, then the sqlite3_config() call will return SQLITE_MISUSE.
|
|
** Note, however, that ^sqlite3_config() can be called as part of the
|
|
** implementation of an application-defined [sqlite3_os_init()].
|
|
**
|
|
** ^When a configuration option is set, sqlite3_config() returns [SQLITE_OK].
|
|
** ^If the option is unknown or SQLite is unable to set the option
|
|
** then this routine returns a non-zero [error code].
|
|
*/
|
|
SQLITE_API int sqlite3_config(int, ...);
|
|
|
|
/*
|
|
** CAPI3REF: Configure database connections
|
|
** METHOD: sqlite3
|
|
**
|
|
** The sqlite3_db_config() interface is used to make configuration
|
|
** changes to a [database connection]. The interface is similar to
|
|
** [sqlite3_config()] except that the changes apply to a single
|
|
** [database connection] (specified in the first argument).
|
|
**
|
|
** The second argument to sqlite3_db_config(D,V,...) is the
|
|
** [SQLITE_DBCONFIG_LOOKASIDE | configuration verb] - an integer code
|
|
** that indicates what aspect of the [database connection] is being configured.
|
|
** Subsequent arguments vary depending on the configuration verb.
|
|
**
|
|
** ^Calls to sqlite3_db_config() return SQLITE_OK if and only if
|
|
** the call is considered successful.
|
|
*/
|
|
SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...);
|
|
|
|
/*
|
|
** CAPI3REF: Memory Allocation Routines
|
|
**
|
|
** An instance of this object defines the interface between SQLite
|
|
** and low-level memory allocation routines.
|
|
**
|
|
** This object is used in only one place in the SQLite interface.
|
|
** A pointer to an instance of this object is the argument to
|
|
** [sqlite3_config()] when the configuration option is
|
|
** [SQLITE_CONFIG_MALLOC] or [SQLITE_CONFIG_GETMALLOC].
|
|
** By creating an instance of this object
|
|
** and passing it to [sqlite3_config]([SQLITE_CONFIG_MALLOC])
|
|
** during configuration, an application can specify an alternative
|
|
** memory allocation subsystem for SQLite to use for all of its
|
|
** dynamic memory needs.
|
|
**
|
|
** Note that SQLite comes with several [built-in memory allocators]
|
|
** that are perfectly adequate for the overwhelming majority of applications
|
|
** and that this object is only useful to a tiny minority of applications
|
|
** with specialized memory allocation requirements. This object is
|
|
** also used during testing of SQLite in order to specify an alternative
|
|
** memory allocator that simulates memory out-of-memory conditions in
|
|
** order to verify that SQLite recovers gracefully from such
|
|
** conditions.
|
|
**
|
|
** The xMalloc, xRealloc, and xFree methods must work like the
|
|
** malloc(), realloc() and free() functions from the standard C library.
|
|
** ^SQLite guarantees that the second argument to
|
|
** xRealloc is always a value returned by a prior call to xRoundup.
|
|
**
|
|
** xSize should return the allocated size of a memory allocation
|
|
** previously obtained from xMalloc or xRealloc. The allocated size
|
|
** is always at least as big as the requested size but may be larger.
|
|
**
|
|
** The xRoundup method returns what would be the allocated size of
|
|
** a memory allocation given a particular requested size. Most memory
|
|
** allocators round up memory allocations at least to the next multiple
|
|
** of 8. Some allocators round up to a larger multiple or to a power of 2.
|
|
** Every memory allocation request coming in through [sqlite3_malloc()]
|
|
** or [sqlite3_realloc()] first calls xRoundup. If xRoundup returns 0,
|
|
** that causes the corresponding memory allocation to fail.
|
|
**
|
|
** The xInit method initializes the memory allocator. For example,
|
|
** it might allocate any required mutexes or initialize internal data
|
|
** structures. The xShutdown method is invoked (indirectly) by
|
|
** [sqlite3_shutdown()] and should deallocate any resources acquired
|
|
** by xInit. The pAppData pointer is used as the only parameter to
|
|
** xInit and xShutdown.
|
|
**
|
|
** SQLite holds the [SQLITE_MUTEX_STATIC_MAIN] mutex when it invokes
|
|
** the xInit method, so the xInit method need not be threadsafe. The
|
|
** xShutdown method is only called from [sqlite3_shutdown()] so it does
|
|
** not need to be threadsafe either. For all other methods, SQLite
|
|
** holds the [SQLITE_MUTEX_STATIC_MEM] mutex as long as the
|
|
** [SQLITE_CONFIG_MEMSTATUS] configuration option is turned on (which
|
|
** it is by default) and so the methods are automatically serialized.
|
|
** However, if [SQLITE_CONFIG_MEMSTATUS] is disabled, then the other
|
|
** methods must be threadsafe or else make their own arrangements for
|
|
** serialization.
|
|
**
|
|
** SQLite will never invoke xInit() more than once without an intervening
|
|
** call to xShutdown().
|
|
*/
|
|
typedef struct sqlite3_mem_methods sqlite3_mem_methods;
|
|
struct sqlite3_mem_methods {
|
|
void *(*xMalloc)(int); /* Memory allocation function */
|
|
void (*xFree)(void*); /* Free a prior allocation */
|
|
void *(*xRealloc)(void*,int); /* Resize an allocation */
|
|
int (*xSize)(void*); /* Return the size of an allocation */
|
|
int (*xRoundup)(int); /* Round up request size to allocation size */
|
|
int (*xInit)(void*); /* Initialize the memory allocator */
|
|
void (*xShutdown)(void*); /* Deinitialize the memory allocator */
|
|
void *pAppData; /* Argument to xInit() and xShutdown() */
|
|
};
|
|
|
|
/*
|
|
** CAPI3REF: Configuration Options
|
|
** KEYWORDS: {configuration option}
|
|
**
|
|
** These constants are the available integer configuration options that
|
|
** can be passed as the first argument to the [sqlite3_config()] interface.
|
|
**
|
|
** Most of the configuration options for sqlite3_config()
|
|
** will only work if invoked prior to [sqlite3_initialize()] or after
|
|
** [sqlite3_shutdown()]. The few exceptions to this rule are called
|
|
** "anytime configuration options".
|
|
** ^Calling [sqlite3_config()] with a first argument that is not an
|
|
** anytime configuration option in between calls to [sqlite3_initialize()] and
|
|
** [sqlite3_shutdown()] is a no-op that returns SQLITE_MISUSE.
|
|
**
|
|
** The set of anytime configuration options can change (by insertions
|
|
** and/or deletions) from one release of SQLite to the next.
|
|
** As of SQLite version 3.42.0, the complete set of anytime configuration
|
|
** options is:
|
|
** <ul>
|
|
** <li> SQLITE_CONFIG_LOG
|
|
** <li> SQLITE_CONFIG_PCACHE_HDRSZ
|
|
** </ul>
|
|
**
|
|
** New configuration options may be added in future releases of SQLite.
|
|
** Existing configuration options might be discontinued. Applications
|
|
** should check the return code from [sqlite3_config()] to make sure that
|
|
** the call worked. The [sqlite3_config()] interface will return a
|
|
** non-zero [error code] if a discontinued or unsupported configuration option
|
|
** is invoked.
|
|
**
|
|
** <dl>
|
|
** [[SQLITE_CONFIG_SINGLETHREAD]] <dt>SQLITE_CONFIG_SINGLETHREAD</dt>
|
|
** <dd>There are no arguments to this option. ^This option sets the
|
|
** [threading mode] to Single-thread. In other words, it disables
|
|
** all mutexing and puts SQLite into a mode where it can only be used
|
|
** by a single thread. ^If SQLite is compiled with
|
|
** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
|
|
** it is not possible to change the [threading mode] from its default
|
|
** value of Single-thread and so [sqlite3_config()] will return
|
|
** [SQLITE_ERROR] if called with the SQLITE_CONFIG_SINGLETHREAD
|
|
** configuration option.</dd>
|
|
**
|
|
** [[SQLITE_CONFIG_MULTITHREAD]] <dt>SQLITE_CONFIG_MULTITHREAD</dt>
|
|
** <dd>There are no arguments to this option. ^This option sets the
|
|
** [threading mode] to Multi-thread. In other words, it disables
|
|
** mutexing on [database connection] and [prepared statement] objects.
|
|
** The application is responsible for serializing access to
|
|
** [database connections] and [prepared statements]. But other mutexes
|
|
** are enabled so that SQLite will be safe to use in a multi-threaded
|
|
** environment as long as no two threads attempt to use the same
|
|
** [database connection] at the same time. ^If SQLite is compiled with
|
|
** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
|
|
** it is not possible to set the Multi-thread [threading mode] and
|
|
** [sqlite3_config()] will return [SQLITE_ERROR] if called with the
|
|
** SQLITE_CONFIG_MULTITHREAD configuration option.</dd>
|
|
**
|
|
** [[SQLITE_CONFIG_SERIALIZED]] <dt>SQLITE_CONFIG_SERIALIZED</dt>
|
|
** <dd>There are no arguments to this option. ^This option sets the
|
|
** [threading mode] to Serialized. In other words, this option enables
|
|
** all mutexes including the recursive
|
|
** mutexes on [database connection] and [prepared statement] objects.
|
|
** In this mode (which is the default when SQLite is compiled with
|
|
** [SQLITE_THREADSAFE=1]) the SQLite library will itself serialize access
|
|
** to [database connections] and [prepared statements] so that the
|
|
** application is free to use the same [database connection] or the
|
|
** same [prepared statement] in different threads at the same time.
|
|
** ^If SQLite is compiled with
|
|
** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
|
|
** it is not possible to set the Serialized [threading mode] and
|
|
** [sqlite3_config()] will return [SQLITE_ERROR] if called with the
|
|
** SQLITE_CONFIG_SERIALIZED configuration option.</dd>
|
|
**
|
|
** [[SQLITE_CONFIG_MALLOC]] <dt>SQLITE_CONFIG_MALLOC</dt>
|
|
** <dd> ^(The SQLITE_CONFIG_MALLOC option takes a single argument which is
|
|
** a pointer to an instance of the [sqlite3_mem_methods] structure.
|
|
** The argument specifies
|
|
** alternative low-level memory allocation routines to be used in place of
|
|
** the memory allocation routines built into SQLite.)^ ^SQLite makes
|
|
** its own private copy of the content of the [sqlite3_mem_methods] structure
|
|
** before the [sqlite3_config()] call returns.</dd>
|
|
**
|
|
** [[SQLITE_CONFIG_GETMALLOC]] <dt>SQLITE_CONFIG_GETMALLOC</dt>
|
|
** <dd> ^(The SQLITE_CONFIG_GETMALLOC option takes a single argument which
|
|
** is a pointer to an instance of the [sqlite3_mem_methods] structure.
|
|
** The [sqlite3_mem_methods]
|
|
** structure is filled with the currently defined memory allocation routines.)^
|
|
** This option can be used to overload the default memory allocation
|
|
** routines with a wrapper that simulations memory allocation failure or
|
|
** tracks memory usage, for example. </dd>
|
|
**
|
|
** [[SQLITE_CONFIG_SMALL_MALLOC]] <dt>SQLITE_CONFIG_SMALL_MALLOC</dt>
|
|
** <dd> ^The SQLITE_CONFIG_SMALL_MALLOC option takes single argument of
|
|
** type int, interpreted as a boolean, which if true provides a hint to
|
|
** SQLite that it should avoid large memory allocations if possible.
|
|
** SQLite will run faster if it is free to make large memory allocations,
|
|
** but some application might prefer to run slower in exchange for
|
|
** guarantees about memory fragmentation that are possible if large
|
|
** allocations are avoided. This hint is normally off.
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_CONFIG_MEMSTATUS]] <dt>SQLITE_CONFIG_MEMSTATUS</dt>
|
|
** <dd> ^The SQLITE_CONFIG_MEMSTATUS option takes single argument of type int,
|
|
** interpreted as a boolean, which enables or disables the collection of
|
|
** memory allocation statistics. ^(When memory allocation statistics are
|
|
** disabled, the following SQLite interfaces become non-operational:
|
|
** <ul>
|
|
** <li> [sqlite3_hard_heap_limit64()]
|
|
** <li> [sqlite3_memory_used()]
|
|
** <li> [sqlite3_memory_highwater()]
|
|
** <li> [sqlite3_soft_heap_limit64()]
|
|
** <li> [sqlite3_status64()]
|
|
** </ul>)^
|
|
** ^Memory allocation statistics are enabled by default unless SQLite is
|
|
** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory
|
|
** allocation statistics are disabled by default.
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_CONFIG_SCRATCH]] <dt>SQLITE_CONFIG_SCRATCH</dt>
|
|
** <dd> The SQLITE_CONFIG_SCRATCH option is no longer used.
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_CONFIG_PAGECACHE]] <dt>SQLITE_CONFIG_PAGECACHE</dt>
|
|
** <dd> ^The SQLITE_CONFIG_PAGECACHE option specifies a memory pool
|
|
** that SQLite can use for the database page cache with the default page
|
|
** cache implementation.
|
|
** This configuration option is a no-op if an application-defined page
|
|
** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2].
|
|
** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to
|
|
** 8-byte aligned memory (pMem), the size of each page cache line (sz),
|
|
** and the number of cache lines (N).
|
|
** The sz argument should be the size of the largest database page
|
|
** (a power of two between 512 and 65536) plus some extra bytes for each
|
|
** page header. ^The number of extra bytes needed by the page header
|
|
** can be determined using [SQLITE_CONFIG_PCACHE_HDRSZ].
|
|
** ^It is harmless, apart from the wasted memory,
|
|
** for the sz parameter to be larger than necessary. The pMem
|
|
** argument must be either a NULL pointer or a pointer to an 8-byte
|
|
** aligned block of memory of at least sz*N bytes, otherwise
|
|
** subsequent behavior is undefined.
|
|
** ^When pMem is not NULL, SQLite will strive to use the memory provided
|
|
** to satisfy page cache needs, falling back to [sqlite3_malloc()] if
|
|
** a page cache line is larger than sz bytes or if all of the pMem buffer
|
|
** is exhausted.
|
|
** ^If pMem is NULL and N is non-zero, then each database connection
|
|
** does an initial bulk allocation for page cache memory
|
|
** from [sqlite3_malloc()] sufficient for N cache lines if N is positive or
|
|
** of -1024*N bytes if N is negative, . ^If additional
|
|
** page cache memory is needed beyond what is provided by the initial
|
|
** allocation, then SQLite goes to [sqlite3_malloc()] separately for each
|
|
** additional cache line. </dd>
|
|
**
|
|
** [[SQLITE_CONFIG_HEAP]] <dt>SQLITE_CONFIG_HEAP</dt>
|
|
** <dd> ^The SQLITE_CONFIG_HEAP option specifies a static memory buffer
|
|
** that SQLite will use for all of its dynamic memory allocation needs
|
|
** beyond those provided for by [SQLITE_CONFIG_PAGECACHE].
|
|
** ^The SQLITE_CONFIG_HEAP option is only available if SQLite is compiled
|
|
** with either [SQLITE_ENABLE_MEMSYS3] or [SQLITE_ENABLE_MEMSYS5] and returns
|
|
** [SQLITE_ERROR] if invoked otherwise.
|
|
** ^There are three arguments to SQLITE_CONFIG_HEAP:
|
|
** An 8-byte aligned pointer to the memory,
|
|
** the number of bytes in the memory buffer, and the minimum allocation size.
|
|
** ^If the first pointer (the memory pointer) is NULL, then SQLite reverts
|
|
** to using its default memory allocator (the system malloc() implementation),
|
|
** undoing any prior invocation of [SQLITE_CONFIG_MALLOC]. ^If the
|
|
** memory pointer is not NULL then the alternative memory
|
|
** allocator is engaged to handle all of SQLites memory allocation needs.
|
|
** The first pointer (the memory pointer) must be aligned to an 8-byte
|
|
** boundary or subsequent behavior of SQLite will be undefined.
|
|
** The minimum allocation size is capped at 2**12. Reasonable values
|
|
** for the minimum allocation size are 2**5 through 2**8.</dd>
|
|
**
|
|
** [[SQLITE_CONFIG_MUTEX]] <dt>SQLITE_CONFIG_MUTEX</dt>
|
|
** <dd> ^(The SQLITE_CONFIG_MUTEX option takes a single argument which is a
|
|
** pointer to an instance of the [sqlite3_mutex_methods] structure.
|
|
** The argument specifies alternative low-level mutex routines to be used
|
|
** in place the mutex routines built into SQLite.)^ ^SQLite makes a copy of
|
|
** the content of the [sqlite3_mutex_methods] structure before the call to
|
|
** [sqlite3_config()] returns. ^If SQLite is compiled with
|
|
** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
|
|
** the entire mutexing subsystem is omitted from the build and hence calls to
|
|
** [sqlite3_config()] with the SQLITE_CONFIG_MUTEX configuration option will
|
|
** return [SQLITE_ERROR].</dd>
|
|
**
|
|
** [[SQLITE_CONFIG_GETMUTEX]] <dt>SQLITE_CONFIG_GETMUTEX</dt>
|
|
** <dd> ^(The SQLITE_CONFIG_GETMUTEX option takes a single argument which
|
|
** is a pointer to an instance of the [sqlite3_mutex_methods] structure. The
|
|
** [sqlite3_mutex_methods]
|
|
** structure is filled with the currently defined mutex routines.)^
|
|
** This option can be used to overload the default mutex allocation
|
|
** routines with a wrapper used to track mutex usage for performance
|
|
** profiling or testing, for example. ^If SQLite is compiled with
|
|
** the [SQLITE_THREADSAFE | SQLITE_THREADSAFE=0] compile-time option then
|
|
** the entire mutexing subsystem is omitted from the build and hence calls to
|
|
** [sqlite3_config()] with the SQLITE_CONFIG_GETMUTEX configuration option will
|
|
** return [SQLITE_ERROR].</dd>
|
|
**
|
|
** [[SQLITE_CONFIG_LOOKASIDE]] <dt>SQLITE_CONFIG_LOOKASIDE</dt>
|
|
** <dd> ^(The SQLITE_CONFIG_LOOKASIDE option takes two arguments that determine
|
|
** the default size of lookaside memory on each [database connection].
|
|
** The first argument is the
|
|
** size of each lookaside buffer slot and the second is the number of
|
|
** slots allocated to each database connection.)^ ^(SQLITE_CONFIG_LOOKASIDE
|
|
** sets the <i>default</i> lookaside size. The [SQLITE_DBCONFIG_LOOKASIDE]
|
|
** option to [sqlite3_db_config()] can be used to change the lookaside
|
|
** configuration on individual connections.)^ </dd>
|
|
**
|
|
** [[SQLITE_CONFIG_PCACHE2]] <dt>SQLITE_CONFIG_PCACHE2</dt>
|
|
** <dd> ^(The SQLITE_CONFIG_PCACHE2 option takes a single argument which is
|
|
** a pointer to an [sqlite3_pcache_methods2] object. This object specifies
|
|
** the interface to a custom page cache implementation.)^
|
|
** ^SQLite makes a copy of the [sqlite3_pcache_methods2] object.</dd>
|
|
**
|
|
** [[SQLITE_CONFIG_GETPCACHE2]] <dt>SQLITE_CONFIG_GETPCACHE2</dt>
|
|
** <dd> ^(The SQLITE_CONFIG_GETPCACHE2 option takes a single argument which
|
|
** is a pointer to an [sqlite3_pcache_methods2] object. SQLite copies of
|
|
** the current page cache implementation into that object.)^ </dd>
|
|
**
|
|
** [[SQLITE_CONFIG_LOG]] <dt>SQLITE_CONFIG_LOG</dt>
|
|
** <dd> The SQLITE_CONFIG_LOG option is used to configure the SQLite
|
|
** global [error log].
|
|
** (^The SQLITE_CONFIG_LOG option takes two arguments: a pointer to a
|
|
** function with a call signature of void(*)(void*,int,const char*),
|
|
** and a pointer to void. ^If the function pointer is not NULL, it is
|
|
** invoked by [sqlite3_log()] to process each logging event. ^If the
|
|
** function pointer is NULL, the [sqlite3_log()] interface becomes a no-op.
|
|
** ^The void pointer that is the second argument to SQLITE_CONFIG_LOG is
|
|
** passed through as the first parameter to the application-defined logger
|
|
** function whenever that function is invoked. ^The second parameter to
|
|
** the logger function is a copy of the first parameter to the corresponding
|
|
** [sqlite3_log()] call and is intended to be a [result code] or an
|
|
** [extended result code]. ^The third parameter passed to the logger is
|
|
** log message after formatting via [sqlite3_snprintf()].
|
|
** The SQLite logging interface is not reentrant; the logger function
|
|
** supplied by the application must not invoke any SQLite interface.
|
|
** In a multi-threaded application, the application-defined logger
|
|
** function must be threadsafe. </dd>
|
|
**
|
|
** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI
|
|
** <dd>^(The SQLITE_CONFIG_URI option takes a single argument of type int.
|
|
** If non-zero, then URI handling is globally enabled. If the parameter is zero,
|
|
** then URI handling is globally disabled.)^ ^If URI handling is globally
|
|
** enabled, all filenames passed to [sqlite3_open()], [sqlite3_open_v2()],
|
|
** [sqlite3_open16()] or
|
|
** specified as part of [ATTACH] commands are interpreted as URIs, regardless
|
|
** of whether or not the [SQLITE_OPEN_URI] flag is set when the database
|
|
** connection is opened. ^If it is globally disabled, filenames are
|
|
** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the
|
|
** database connection is opened. ^(By default, URI handling is globally
|
|
** disabled. The default value may be changed by compiling with the
|
|
** [SQLITE_USE_URI] symbol defined.)^
|
|
**
|
|
** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
|
|
** <dd>^The SQLITE_CONFIG_COVERING_INDEX_SCAN option takes a single integer
|
|
** argument which is interpreted as a boolean in order to enable or disable
|
|
** the use of covering indices for full table scans in the query optimizer.
|
|
** ^The default setting is determined
|
|
** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
|
|
** if that compile-time option is omitted.
|
|
** The ability to disable the use of covering indices for full table scans
|
|
** is because some incorrectly coded legacy applications might malfunction
|
|
** when the optimization is enabled. Providing the ability to
|
|
** disable the optimization allows the older, buggy application code to work
|
|
** without change even with newer versions of SQLite.
|
|
**
|
|
** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]]
|
|
** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE
|
|
** <dd> These options are obsolete and should not be used by new code.
|
|
** They are retained for backwards compatibility but are now no-ops.
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_CONFIG_SQLLOG]]
|
|
** <dt>SQLITE_CONFIG_SQLLOG
|
|
** <dd>This option is only available if sqlite is compiled with the
|
|
** [SQLITE_ENABLE_SQLLOG] pre-processor macro defined. The first argument should
|
|
** be a pointer to a function of type void(*)(void*,sqlite3*,const char*, int).
|
|
** The second should be of type (void*). The callback is invoked by the library
|
|
** in three separate circumstances, identified by the value passed as the
|
|
** fourth parameter. If the fourth parameter is 0, then the database connection
|
|
** passed as the second argument has just been opened. The third argument
|
|
** points to a buffer containing the name of the main database file. If the
|
|
** fourth parameter is 1, then the SQL statement that the third parameter
|
|
** points to has just been executed. Or, if the fourth parameter is 2, then
|
|
** the connection being passed as the second parameter is being closed. The
|
|
** third parameter is passed NULL In this case. An example of using this
|
|
** configuration option can be seen in the "test_sqllog.c" source file in
|
|
** the canonical SQLite source tree.</dd>
|
|
**
|
|
** [[SQLITE_CONFIG_MMAP_SIZE]]
|
|
** <dt>SQLITE_CONFIG_MMAP_SIZE
|
|
** <dd>^SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values
|
|
** that are the default mmap size limit (the default setting for
|
|
** [PRAGMA mmap_size]) and the maximum allowed mmap size limit.
|
|
** ^The default setting can be overridden by each database connection using
|
|
** either the [PRAGMA mmap_size] command, or by using the
|
|
** [SQLITE_FCNTL_MMAP_SIZE] file control. ^(The maximum allowed mmap size
|
|
** will be silently truncated if necessary so that it does not exceed the
|
|
** compile-time maximum mmap size set by the
|
|
** [SQLITE_MAX_MMAP_SIZE] compile-time option.)^
|
|
** ^If either argument to this option is negative, then that argument is
|
|
** changed to its compile-time default.
|
|
**
|
|
** [[SQLITE_CONFIG_WIN32_HEAPSIZE]]
|
|
** <dt>SQLITE_CONFIG_WIN32_HEAPSIZE
|
|
** <dd>^The SQLITE_CONFIG_WIN32_HEAPSIZE option is only available if SQLite is
|
|
** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro
|
|
** defined. ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value
|
|
** that specifies the maximum size of the created heap.
|
|
**
|
|
** [[SQLITE_CONFIG_PCACHE_HDRSZ]]
|
|
** <dt>SQLITE_CONFIG_PCACHE_HDRSZ
|
|
** <dd>^The SQLITE_CONFIG_PCACHE_HDRSZ option takes a single parameter which
|
|
** is a pointer to an integer and writes into that integer the number of extra
|
|
** bytes per page required for each page in [SQLITE_CONFIG_PAGECACHE].
|
|
** The amount of extra space required can change depending on the compiler,
|
|
** target platform, and SQLite version.
|
|
**
|
|
** [[SQLITE_CONFIG_PMASZ]]
|
|
** <dt>SQLITE_CONFIG_PMASZ
|
|
** <dd>^The SQLITE_CONFIG_PMASZ option takes a single parameter which
|
|
** is an unsigned integer and sets the "Minimum PMA Size" for the multithreaded
|
|
** sorter to that integer. The default minimum PMA Size is set by the
|
|
** [SQLITE_SORTER_PMASZ] compile-time option. New threads are launched
|
|
** to help with sort operations when multithreaded sorting
|
|
** is enabled (using the [PRAGMA threads] command) and the amount of content
|
|
** to be sorted exceeds the page size times the minimum of the
|
|
** [PRAGMA cache_size] setting and this value.
|
|
**
|
|
** [[SQLITE_CONFIG_STMTJRNL_SPILL]]
|
|
** <dt>SQLITE_CONFIG_STMTJRNL_SPILL
|
|
** <dd>^The SQLITE_CONFIG_STMTJRNL_SPILL option takes a single parameter which
|
|
** becomes the [statement journal] spill-to-disk threshold.
|
|
** [Statement journals] are held in memory until their size (in bytes)
|
|
** exceeds this threshold, at which point they are written to disk.
|
|
** Or if the threshold is -1, statement journals are always held
|
|
** exclusively in memory.
|
|
** Since many statement journals never become large, setting the spill
|
|
** threshold to a value such as 64KiB can greatly reduce the amount of
|
|
** I/O required to support statement rollback.
|
|
** The default value for this setting is controlled by the
|
|
** [SQLITE_STMTJRNL_SPILL] compile-time option.
|
|
**
|
|
** [[SQLITE_CONFIG_SORTERREF_SIZE]]
|
|
** <dt>SQLITE_CONFIG_SORTERREF_SIZE
|
|
** <dd>The SQLITE_CONFIG_SORTERREF_SIZE option accepts a single parameter
|
|
** of type (int) - the new value of the sorter-reference size threshold.
|
|
** Usually, when SQLite uses an external sort to order records according
|
|
** to an ORDER BY clause, all fields required by the caller are present in the
|
|
** sorted records. However, if SQLite determines based on the declared type
|
|
** of a table column that its values are likely to be very large - larger
|
|
** than the configured sorter-reference size threshold - then a reference
|
|
** is stored in each sorted record and the required column values loaded
|
|
** from the database as records are returned in sorted order. The default
|
|
** value for this option is to never use this optimization. Specifying a
|
|
** negative value for this option restores the default behavior.
|
|
** This option is only available if SQLite is compiled with the
|
|
** [SQLITE_ENABLE_SORTER_REFERENCES] compile-time option.
|
|
**
|
|
** [[SQLITE_CONFIG_MEMDB_MAXSIZE]]
|
|
** <dt>SQLITE_CONFIG_MEMDB_MAXSIZE
|
|
** <dd>The SQLITE_CONFIG_MEMDB_MAXSIZE option accepts a single parameter
|
|
** [sqlite3_int64] parameter which is the default maximum size for an in-memory
|
|
** database created using [sqlite3_deserialize()]. This default maximum
|
|
** size can be adjusted up or down for individual databases using the
|
|
** [SQLITE_FCNTL_SIZE_LIMIT] [sqlite3_file_control|file-control]. If this
|
|
** configuration setting is never used, then the default maximum is determined
|
|
** by the [SQLITE_MEMDB_DEFAULT_MAXSIZE] compile-time option. If that
|
|
** compile-time option is not set, then the default maximum is 1073741824.
|
|
**
|
|
** [[SQLITE_CONFIG_ROWID_IN_VIEW]]
|
|
** <dt>SQLITE_CONFIG_ROWID_IN_VIEW
|
|
** <dd>The SQLITE_CONFIG_ROWID_IN_VIEW option enables or disables the ability
|
|
** for VIEWs to have a ROWID. The capability can only be enabled if SQLite is
|
|
** compiled with -DSQLITE_ALLOW_ROWID_IN_VIEW, in which case the capability
|
|
** defaults to on. This configuration option queries the current setting or
|
|
** changes the setting to off or on. The argument is a pointer to an integer.
|
|
** If that integer initially holds a value of 1, then the ability for VIEWs to
|
|
** have ROWIDs is activated. If the integer initially holds zero, then the
|
|
** ability is deactivated. Any other initial value for the integer leaves the
|
|
** setting unchanged. After changes, if any, the integer is written with
|
|
** a 1 or 0, if the ability for VIEWs to have ROWIDs is on or off. If SQLite
|
|
** is compiled without -DSQLITE_ALLOW_ROWID_IN_VIEW (which is the usual and
|
|
** recommended case) then the integer is always filled with zero, regardless
|
|
** if its initial value.
|
|
** </dl>
|
|
*/
|
|
#define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */
|
|
#define SQLITE_CONFIG_MULTITHREAD 2 /* nil */
|
|
#define SQLITE_CONFIG_SERIALIZED 3 /* nil */
|
|
#define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */
|
|
#define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */
|
|
#define SQLITE_CONFIG_SCRATCH 6 /* No longer used */
|
|
#define SQLITE_CONFIG_PAGECACHE 7 /* void*, int sz, int N */
|
|
#define SQLITE_CONFIG_HEAP 8 /* void*, int nByte, int min */
|
|
#define SQLITE_CONFIG_MEMSTATUS 9 /* boolean */
|
|
#define SQLITE_CONFIG_MUTEX 10 /* sqlite3_mutex_methods* */
|
|
#define SQLITE_CONFIG_GETMUTEX 11 /* sqlite3_mutex_methods* */
|
|
/* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */
|
|
#define SQLITE_CONFIG_LOOKASIDE 13 /* int int */
|
|
#define SQLITE_CONFIG_PCACHE 14 /* no-op */
|
|
#define SQLITE_CONFIG_GETPCACHE 15 /* no-op */
|
|
#define SQLITE_CONFIG_LOG 16 /* xFunc, void* */
|
|
#define SQLITE_CONFIG_URI 17 /* int */
|
|
#define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */
|
|
#define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */
|
|
#define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */
|
|
#define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */
|
|
#define SQLITE_CONFIG_MMAP_SIZE 22 /* sqlite3_int64, sqlite3_int64 */
|
|
#define SQLITE_CONFIG_WIN32_HEAPSIZE 23 /* int nByte */
|
|
#define SQLITE_CONFIG_PCACHE_HDRSZ 24 /* int *psz */
|
|
#define SQLITE_CONFIG_PMASZ 25 /* unsigned int szPma */
|
|
#define SQLITE_CONFIG_STMTJRNL_SPILL 26 /* int nByte */
|
|
#define SQLITE_CONFIG_SMALL_MALLOC 27 /* boolean */
|
|
#define SQLITE_CONFIG_SORTERREF_SIZE 28 /* int nByte */
|
|
#define SQLITE_CONFIG_MEMDB_MAXSIZE 29 /* sqlite3_int64 */
|
|
#define SQLITE_CONFIG_ROWID_IN_VIEW 30 /* int* */
|
|
|
|
/*
|
|
** CAPI3REF: Database Connection Configuration Options
|
|
**
|
|
** These constants are the available integer configuration options that
|
|
** can be passed as the second argument to the [sqlite3_db_config()] interface.
|
|
**
|
|
** New configuration options may be added in future releases of SQLite.
|
|
** Existing configuration options might be discontinued. Applications
|
|
** should check the return code from [sqlite3_db_config()] to make sure that
|
|
** the call worked. ^The [sqlite3_db_config()] interface will return a
|
|
** non-zero [error code] if a discontinued or unsupported configuration option
|
|
** is invoked.
|
|
**
|
|
** <dl>
|
|
** [[SQLITE_DBCONFIG_LOOKASIDE]]
|
|
** <dt>SQLITE_DBCONFIG_LOOKASIDE</dt>
|
|
** <dd> ^This option takes three additional arguments that determine the
|
|
** [lookaside memory allocator] configuration for the [database connection].
|
|
** ^The first argument (the third parameter to [sqlite3_db_config()] is a
|
|
** pointer to a memory buffer to use for lookaside memory.
|
|
** ^The first argument after the SQLITE_DBCONFIG_LOOKASIDE verb
|
|
** may be NULL in which case SQLite will allocate the
|
|
** lookaside buffer itself using [sqlite3_malloc()]. ^The second argument is the
|
|
** size of each lookaside buffer slot. ^The third argument is the number of
|
|
** slots. The size of the buffer in the first argument must be greater than
|
|
** or equal to the product of the second and third arguments. The buffer
|
|
** must be aligned to an 8-byte boundary. ^If the second argument to
|
|
** SQLITE_DBCONFIG_LOOKASIDE is not a multiple of 8, it is internally
|
|
** rounded down to the next smaller multiple of 8. ^(The lookaside memory
|
|
** configuration for a database connection can only be changed when that
|
|
** connection is not currently using lookaside memory, or in other words
|
|
** when the "current value" returned by
|
|
** [sqlite3_db_status](D,[SQLITE_DBSTATUS_LOOKASIDE_USED],...) is zero.
|
|
** Any attempt to change the lookaside memory configuration when lookaside
|
|
** memory is in use leaves the configuration unchanged and returns
|
|
** [SQLITE_BUSY].)^</dd>
|
|
**
|
|
** [[SQLITE_DBCONFIG_ENABLE_FKEY]]
|
|
** <dt>SQLITE_DBCONFIG_ENABLE_FKEY</dt>
|
|
** <dd> ^This option is used to enable or disable the enforcement of
|
|
** [foreign key constraints]. There should be two additional arguments.
|
|
** The first argument is an integer which is 0 to disable FK enforcement,
|
|
** positive to enable FK enforcement or negative to leave FK enforcement
|
|
** unchanged. The second parameter is a pointer to an integer into which
|
|
** is written 0 or 1 to indicate whether FK enforcement is off or on
|
|
** following this call. The second parameter may be a NULL pointer, in
|
|
** which case the FK enforcement setting is not reported back. </dd>
|
|
**
|
|
** [[SQLITE_DBCONFIG_ENABLE_TRIGGER]]
|
|
** <dt>SQLITE_DBCONFIG_ENABLE_TRIGGER</dt>
|
|
** <dd> ^This option is used to enable or disable [CREATE TRIGGER | triggers].
|
|
** There should be two additional arguments.
|
|
** The first argument is an integer which is 0 to disable triggers,
|
|
** positive to enable triggers or negative to leave the setting unchanged.
|
|
** The second parameter is a pointer to an integer into which
|
|
** is written 0 or 1 to indicate whether triggers are disabled or enabled
|
|
** following this call. The second parameter may be a NULL pointer, in
|
|
** which case the trigger setting is not reported back.
|
|
**
|
|
** <p>Originally this option disabled all triggers. ^(However, since
|
|
** SQLite version 3.35.0, TEMP triggers are still allowed even if
|
|
** this option is off. So, in other words, this option now only disables
|
|
** triggers in the main database schema or in the schemas of ATTACH-ed
|
|
** databases.)^ </dd>
|
|
**
|
|
** [[SQLITE_DBCONFIG_ENABLE_VIEW]]
|
|
** <dt>SQLITE_DBCONFIG_ENABLE_VIEW</dt>
|
|
** <dd> ^This option is used to enable or disable [CREATE VIEW | views].
|
|
** There should be two additional arguments.
|
|
** The first argument is an integer which is 0 to disable views,
|
|
** positive to enable views or negative to leave the setting unchanged.
|
|
** The second parameter is a pointer to an integer into which
|
|
** is written 0 or 1 to indicate whether views are disabled or enabled
|
|
** following this call. The second parameter may be a NULL pointer, in
|
|
** which case the view setting is not reported back.
|
|
**
|
|
** <p>Originally this option disabled all views. ^(However, since
|
|
** SQLite version 3.35.0, TEMP views are still allowed even if
|
|
** this option is off. So, in other words, this option now only disables
|
|
** views in the main database schema or in the schemas of ATTACH-ed
|
|
** databases.)^ </dd>
|
|
**
|
|
** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
|
|
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
|
|
** <dd> ^This option is used to enable or disable the
|
|
** [fts3_tokenizer()] function which is part of the
|
|
** [FTS3] full-text search engine extension.
|
|
** There should be two additional arguments.
|
|
** The first argument is an integer which is 0 to disable fts3_tokenizer() or
|
|
** positive to enable fts3_tokenizer() or negative to leave the setting
|
|
** unchanged.
|
|
** The second parameter is a pointer to an integer into which
|
|
** is written 0 or 1 to indicate whether fts3_tokenizer is disabled or enabled
|
|
** following this call. The second parameter may be a NULL pointer, in
|
|
** which case the new setting is not reported back. </dd>
|
|
**
|
|
** [[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION]]
|
|
** <dt>SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION</dt>
|
|
** <dd> ^This option is used to enable or disable the [sqlite3_load_extension()]
|
|
** interface independently of the [load_extension()] SQL function.
|
|
** The [sqlite3_enable_load_extension()] API enables or disables both the
|
|
** C-API [sqlite3_load_extension()] and the SQL function [load_extension()].
|
|
** There should be two additional arguments.
|
|
** When the first argument to this interface is 1, then only the C-API is
|
|
** enabled and the SQL function remains disabled. If the first argument to
|
|
** this interface is 0, then both the C-API and the SQL function are disabled.
|
|
** If the first argument is -1, then no changes are made to state of either the
|
|
** C-API or the SQL function.
|
|
** The second parameter is a pointer to an integer into which
|
|
** is written 0 or 1 to indicate whether [sqlite3_load_extension()] interface
|
|
** is disabled or enabled following this call. The second parameter may
|
|
** be a NULL pointer, in which case the new setting is not reported back.
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_DBCONFIG_MAINDBNAME]] <dt>SQLITE_DBCONFIG_MAINDBNAME</dt>
|
|
** <dd> ^This option is used to change the name of the "main" database
|
|
** schema. ^The sole argument is a pointer to a constant UTF8 string
|
|
** which will become the new schema name in place of "main". ^SQLite
|
|
** does not make a copy of the new main schema name string, so the application
|
|
** must ensure that the argument passed into this DBCONFIG option is unchanged
|
|
** until after the database connection closes.
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE]]
|
|
** <dt>SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE</dt>
|
|
** <dd> Usually, when a database in wal mode is closed or detached from a
|
|
** database handle, SQLite checks if this will mean that there are now no
|
|
** connections at all to the database. If so, it performs a checkpoint
|
|
** operation before closing the connection. This option may be used to
|
|
** override this behavior. The first parameter passed to this operation
|
|
** is an integer - positive to disable checkpoints-on-close, or zero (the
|
|
** default) to enable them, and negative to leave the setting unchanged.
|
|
** The second parameter is a pointer to an integer
|
|
** into which is written 0 or 1 to indicate whether checkpoints-on-close
|
|
** have been disabled - 0 if they are not disabled, 1 if they are.
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_DBCONFIG_ENABLE_QPSG]] <dt>SQLITE_DBCONFIG_ENABLE_QPSG</dt>
|
|
** <dd>^(The SQLITE_DBCONFIG_ENABLE_QPSG option activates or deactivates
|
|
** the [query planner stability guarantee] (QPSG). When the QPSG is active,
|
|
** a single SQL query statement will always use the same algorithm regardless
|
|
** of values of [bound parameters].)^ The QPSG disables some query optimizations
|
|
** that look at the values of bound parameters, which can make some queries
|
|
** slower. But the QPSG has the advantage of more predictable behavior. With
|
|
** the QPSG active, SQLite will always use the same query plan in the field as
|
|
** was used during testing in the lab.
|
|
** The first argument to this setting is an integer which is 0 to disable
|
|
** the QPSG, positive to enable QPSG, or negative to leave the setting
|
|
** unchanged. The second parameter is a pointer to an integer into which
|
|
** is written 0 or 1 to indicate whether the QPSG is disabled or enabled
|
|
** following this call.
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_DBCONFIG_TRIGGER_EQP]] <dt>SQLITE_DBCONFIG_TRIGGER_EQP</dt>
|
|
** <dd> By default, the output of EXPLAIN QUERY PLAN commands does not
|
|
** include output for any operations performed by trigger programs. This
|
|
** option is used to set or clear (the default) a flag that governs this
|
|
** behavior. The first parameter passed to this operation is an integer -
|
|
** positive to enable output for trigger programs, or zero to disable it,
|
|
** or negative to leave the setting unchanged.
|
|
** The second parameter is a pointer to an integer into which is written
|
|
** 0 or 1 to indicate whether output-for-triggers has been disabled - 0 if
|
|
** it is not disabled, 1 if it is.
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_DBCONFIG_RESET_DATABASE]] <dt>SQLITE_DBCONFIG_RESET_DATABASE</dt>
|
|
** <dd> Set the SQLITE_DBCONFIG_RESET_DATABASE flag and then run
|
|
** [VACUUM] in order to reset a database back to an empty database
|
|
** with no schema and no content. The following process works even for
|
|
** a badly corrupted database file:
|
|
** <ol>
|
|
** <li> If the database connection is newly opened, make sure it has read the
|
|
** database schema by preparing then discarding some query against the
|
|
** database, or calling sqlite3_table_column_metadata(), ignoring any
|
|
** errors. This step is only necessary if the application desires to keep
|
|
** the database in WAL mode after the reset if it was in WAL mode before
|
|
** the reset.
|
|
** <li> sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0);
|
|
** <li> [sqlite3_exec](db, "[VACUUM]", 0, 0, 0);
|
|
** <li> sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0);
|
|
** </ol>
|
|
** Because resetting a database is destructive and irreversible, the
|
|
** process requires the use of this obscure API and multiple steps to
|
|
** help ensure that it does not happen by accident. Because this
|
|
** feature must be capable of resetting corrupt databases, and
|
|
** shutting down virtual tables may require access to that corrupt
|
|
** storage, the library must abandon any installed virtual tables
|
|
** without calling their xDestroy() methods.
|
|
**
|
|
** [[SQLITE_DBCONFIG_DEFENSIVE]] <dt>SQLITE_DBCONFIG_DEFENSIVE</dt>
|
|
** <dd>The SQLITE_DBCONFIG_DEFENSIVE option activates or deactivates the
|
|
** "defensive" flag for a database connection. When the defensive
|
|
** flag is enabled, language features that allow ordinary SQL to
|
|
** deliberately corrupt the database file are disabled. The disabled
|
|
** features include but are not limited to the following:
|
|
** <ul>
|
|
** <li> The [PRAGMA writable_schema=ON] statement.
|
|
** <li> The [PRAGMA journal_mode=OFF] statement.
|
|
** <li> The [PRAGMA schema_version=N] statement.
|
|
** <li> Writes to the [sqlite_dbpage] virtual table.
|
|
** <li> Direct writes to [shadow tables].
|
|
** </ul>
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_DBCONFIG_WRITABLE_SCHEMA]] <dt>SQLITE_DBCONFIG_WRITABLE_SCHEMA</dt>
|
|
** <dd>The SQLITE_DBCONFIG_WRITABLE_SCHEMA option activates or deactivates the
|
|
** "writable_schema" flag. This has the same effect and is logically equivalent
|
|
** to setting [PRAGMA writable_schema=ON] or [PRAGMA writable_schema=OFF].
|
|
** The first argument to this setting is an integer which is 0 to disable
|
|
** the writable_schema, positive to enable writable_schema, or negative to
|
|
** leave the setting unchanged. The second parameter is a pointer to an
|
|
** integer into which is written 0 or 1 to indicate whether the writable_schema
|
|
** is enabled or disabled following this call.
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_DBCONFIG_LEGACY_ALTER_TABLE]]
|
|
** <dt>SQLITE_DBCONFIG_LEGACY_ALTER_TABLE</dt>
|
|
** <dd>The SQLITE_DBCONFIG_LEGACY_ALTER_TABLE option activates or deactivates
|
|
** the legacy behavior of the [ALTER TABLE RENAME] command such it
|
|
** behaves as it did prior to [version 3.24.0] (2018-06-04). See the
|
|
** "Compatibility Notice" on the [ALTER TABLE RENAME documentation] for
|
|
** additional information. This feature can also be turned on and off
|
|
** using the [PRAGMA legacy_alter_table] statement.
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_DBCONFIG_DQS_DML]]
|
|
** <dt>SQLITE_DBCONFIG_DQS_DML</dt>
|
|
** <dd>The SQLITE_DBCONFIG_DQS_DML option activates or deactivates
|
|
** the legacy [double-quoted string literal] misfeature for DML statements
|
|
** only, that is DELETE, INSERT, SELECT, and UPDATE statements. The
|
|
** default value of this setting is determined by the [-DSQLITE_DQS]
|
|
** compile-time option.
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_DBCONFIG_DQS_DDL]]
|
|
** <dt>SQLITE_DBCONFIG_DQS_DDL</dt>
|
|
** <dd>The SQLITE_DBCONFIG_DQS option activates or deactivates
|
|
** the legacy [double-quoted string literal] misfeature for DDL statements,
|
|
** such as CREATE TABLE and CREATE INDEX. The
|
|
** default value of this setting is determined by the [-DSQLITE_DQS]
|
|
** compile-time option.
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_DBCONFIG_TRUSTED_SCHEMA]]
|
|
** <dt>SQLITE_DBCONFIG_TRUSTED_SCHEMA</dt>
|
|
** <dd>The SQLITE_DBCONFIG_TRUSTED_SCHEMA option tells SQLite to
|
|
** assume that database schemas are untainted by malicious content.
|
|
** When the SQLITE_DBCONFIG_TRUSTED_SCHEMA option is disabled, SQLite
|
|
** takes additional defensive steps to protect the application from harm
|
|
** including:
|
|
** <ul>
|
|
** <li> Prohibit the use of SQL functions inside triggers, views,
|
|
** CHECK constraints, DEFAULT clauses, expression indexes,
|
|
** partial indexes, or generated columns
|
|
** unless those functions are tagged with [SQLITE_INNOCUOUS].
|
|
** <li> Prohibit the use of virtual tables inside of triggers or views
|
|
** unless those virtual tables are tagged with [SQLITE_VTAB_INNOCUOUS].
|
|
** </ul>
|
|
** This setting defaults to "on" for legacy compatibility, however
|
|
** all applications are advised to turn it off if possible. This setting
|
|
** can also be controlled using the [PRAGMA trusted_schema] statement.
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_DBCONFIG_LEGACY_FILE_FORMAT]]
|
|
** <dt>SQLITE_DBCONFIG_LEGACY_FILE_FORMAT</dt>
|
|
** <dd>The SQLITE_DBCONFIG_LEGACY_FILE_FORMAT option activates or deactivates
|
|
** the legacy file format flag. When activated, this flag causes all newly
|
|
** created database file to have a schema format version number (the 4-byte
|
|
** integer found at offset 44 into the database header) of 1. This in turn
|
|
** means that the resulting database file will be readable and writable by
|
|
** any SQLite version back to 3.0.0 ([dateof:3.0.0]). Without this setting,
|
|
** newly created databases are generally not understandable by SQLite versions
|
|
** prior to 3.3.0 ([dateof:3.3.0]). As these words are written, there
|
|
** is now scarcely any need to generate database files that are compatible
|
|
** all the way back to version 3.0.0, and so this setting is of little
|
|
** practical use, but is provided so that SQLite can continue to claim the
|
|
** ability to generate new database files that are compatible with version
|
|
** 3.0.0.
|
|
** <p>Note that when the SQLITE_DBCONFIG_LEGACY_FILE_FORMAT setting is on,
|
|
** the [VACUUM] command will fail with an obscure error when attempting to
|
|
** process a table with generated columns and a descending index. This is
|
|
** not considered a bug since SQLite versions 3.3.0 and earlier do not support
|
|
** either generated columns or descending indexes.
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_DBCONFIG_STMT_SCANSTATUS]]
|
|
** <dt>SQLITE_DBCONFIG_STMT_SCANSTATUS</dt>
|
|
** <dd>The SQLITE_DBCONFIG_STMT_SCANSTATUS option is only useful in
|
|
** SQLITE_ENABLE_STMT_SCANSTATUS builds. In this case, it sets or clears
|
|
** a flag that enables collection of the sqlite3_stmt_scanstatus_v2()
|
|
** statistics. For statistics to be collected, the flag must be set on
|
|
** the database handle both when the SQL statement is prepared and when it
|
|
** is stepped. The flag is set (collection of statistics is enabled)
|
|
** by default. This option takes two arguments: an integer and a pointer to
|
|
** an integer.. The first argument is 1, 0, or -1 to enable, disable, or
|
|
** leave unchanged the statement scanstatus option. If the second argument
|
|
** is not NULL, then the value of the statement scanstatus setting after
|
|
** processing the first argument is written into the integer that the second
|
|
** argument points to.
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_DBCONFIG_REVERSE_SCANORDER]]
|
|
** <dt>SQLITE_DBCONFIG_REVERSE_SCANORDER</dt>
|
|
** <dd>The SQLITE_DBCONFIG_REVERSE_SCANORDER option changes the default order
|
|
** in which tables and indexes are scanned so that the scans start at the end
|
|
** and work toward the beginning rather than starting at the beginning and
|
|
** working toward the end. Setting SQLITE_DBCONFIG_REVERSE_SCANORDER is the
|
|
** same as setting [PRAGMA reverse_unordered_selects]. This option takes
|
|
** two arguments which are an integer and a pointer to an integer. The first
|
|
** argument is 1, 0, or -1 to enable, disable, or leave unchanged the
|
|
** reverse scan order flag, respectively. If the second argument is not NULL,
|
|
** then 0 or 1 is written into the integer that the second argument points to
|
|
** depending on if the reverse scan order flag is set after processing the
|
|
** first argument.
|
|
** </dd>
|
|
**
|
|
** </dl>
|
|
*/
|
|
#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
|
|
#define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */
|
|
#define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */
|
|
#define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */
|
|
#define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */
|
|
#define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */
|
|
#define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */
|
|
#define SQLITE_DBCONFIG_ENABLE_QPSG 1007 /* int int* */
|
|
#define SQLITE_DBCONFIG_TRIGGER_EQP 1008 /* int int* */
|
|
#define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */
|
|
#define SQLITE_DBCONFIG_DEFENSIVE 1010 /* int int* */
|
|
#define SQLITE_DBCONFIG_WRITABLE_SCHEMA 1011 /* int int* */
|
|
#define SQLITE_DBCONFIG_LEGACY_ALTER_TABLE 1012 /* int int* */
|
|
#define SQLITE_DBCONFIG_DQS_DML 1013 /* int int* */
|
|
#define SQLITE_DBCONFIG_DQS_DDL 1014 /* int int* */
|
|
#define SQLITE_DBCONFIG_ENABLE_VIEW 1015 /* int int* */
|
|
#define SQLITE_DBCONFIG_LEGACY_FILE_FORMAT 1016 /* int int* */
|
|
#define SQLITE_DBCONFIG_TRUSTED_SCHEMA 1017 /* int int* */
|
|
#define SQLITE_DBCONFIG_STMT_SCANSTATUS 1018 /* int int* */
|
|
#define SQLITE_DBCONFIG_REVERSE_SCANORDER 1019 /* int int* */
|
|
#define SQLITE_DBCONFIG_MAX 1019 /* Largest DBCONFIG */
|
|
|
|
/*
|
|
** CAPI3REF: Enable Or Disable Extended Result Codes
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^The sqlite3_extended_result_codes() routine enables or disables the
|
|
** [extended result codes] feature of SQLite. ^The extended result
|
|
** codes are disabled by default for historical compatibility.
|
|
*/
|
|
SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff);
|
|
|
|
/*
|
|
** CAPI3REF: Last Insert Rowid
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^Each entry in most SQLite tables (except for [WITHOUT ROWID] tables)
|
|
** has a unique 64-bit signed
|
|
** integer key called the [ROWID | "rowid"]. ^The rowid is always available
|
|
** as an undeclared column named ROWID, OID, or _ROWID_ as long as those
|
|
** names are not also used by explicitly declared columns. ^If
|
|
** the table has a column of type [INTEGER PRIMARY KEY] then that column
|
|
** is another alias for the rowid.
|
|
**
|
|
** ^The sqlite3_last_insert_rowid(D) interface usually returns the [rowid] of
|
|
** the most recent successful [INSERT] into a rowid table or [virtual table]
|
|
** on database connection D. ^Inserts into [WITHOUT ROWID] tables are not
|
|
** recorded. ^If no successful [INSERT]s into rowid tables have ever occurred
|
|
** on the database connection D, then sqlite3_last_insert_rowid(D) returns
|
|
** zero.
|
|
**
|
|
** As well as being set automatically as rows are inserted into database
|
|
** tables, the value returned by this function may be set explicitly by
|
|
** [sqlite3_set_last_insert_rowid()]
|
|
**
|
|
** Some virtual table implementations may INSERT rows into rowid tables as
|
|
** part of committing a transaction (e.g. to flush data accumulated in memory
|
|
** to disk). In this case subsequent calls to this function return the rowid
|
|
** associated with these internal INSERT operations, which leads to
|
|
** unintuitive results. Virtual table implementations that do write to rowid
|
|
** tables in this way can avoid this problem by restoring the original
|
|
** rowid value using [sqlite3_set_last_insert_rowid()] before returning
|
|
** control to the user.
|
|
**
|
|
** ^(If an [INSERT] occurs within a trigger then this routine will
|
|
** return the [rowid] of the inserted row as long as the trigger is
|
|
** running. Once the trigger program ends, the value returned
|
|
** by this routine reverts to what it was before the trigger was fired.)^
|
|
**
|
|
** ^An [INSERT] that fails due to a constraint violation is not a
|
|
** successful [INSERT] and does not change the value returned by this
|
|
** routine. ^Thus INSERT OR FAIL, INSERT OR IGNORE, INSERT OR ROLLBACK,
|
|
** and INSERT OR ABORT make no changes to the return value of this
|
|
** routine when their insertion fails. ^(When INSERT OR REPLACE
|
|
** encounters a constraint violation, it does not fail. The
|
|
** INSERT continues to completion after deleting rows that caused
|
|
** the constraint problem so INSERT OR REPLACE will always change
|
|
** the return value of this interface.)^
|
|
**
|
|
** ^For the purposes of this routine, an [INSERT] is considered to
|
|
** be successful even if it is subsequently rolled back.
|
|
**
|
|
** This function is accessible to SQL statements via the
|
|
** [last_insert_rowid() SQL function].
|
|
**
|
|
** If a separate thread performs a new [INSERT] on the same
|
|
** database connection while the [sqlite3_last_insert_rowid()]
|
|
** function is running and thus changes the last insert [rowid],
|
|
** then the value returned by [sqlite3_last_insert_rowid()] is
|
|
** unpredictable and might not equal either the old or the new
|
|
** last insert [rowid].
|
|
*/
|
|
SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
|
|
|
|
/*
|
|
** CAPI3REF: Set the Last Insert Rowid value.
|
|
** METHOD: sqlite3
|
|
**
|
|
** The sqlite3_set_last_insert_rowid(D, R) method allows the application to
|
|
** set the value returned by calling sqlite3_last_insert_rowid(D) to R
|
|
** without inserting a row into the database.
|
|
*/
|
|
SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64);
|
|
|
|
/*
|
|
** CAPI3REF: Count The Number Of Rows Modified
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^These functions return the number of rows modified, inserted or
|
|
** deleted by the most recently completed INSERT, UPDATE or DELETE
|
|
** statement on the database connection specified by the only parameter.
|
|
** The two functions are identical except for the type of the return value
|
|
** and that if the number of rows modified by the most recent INSERT, UPDATE
|
|
** or DELETE is greater than the maximum value supported by type "int", then
|
|
** the return value of sqlite3_changes() is undefined. ^Executing any other
|
|
** type of SQL statement does not modify the value returned by these functions.
|
|
**
|
|
** ^Only changes made directly by the INSERT, UPDATE or DELETE statement are
|
|
** considered - auxiliary changes caused by [CREATE TRIGGER | triggers],
|
|
** [foreign key actions] or [REPLACE] constraint resolution are not counted.
|
|
**
|
|
** Changes to a view that are intercepted by
|
|
** [INSTEAD OF trigger | INSTEAD OF triggers] are not counted. ^The value
|
|
** returned by sqlite3_changes() immediately after an INSERT, UPDATE or
|
|
** DELETE statement run on a view is always zero. Only changes made to real
|
|
** tables are counted.
|
|
**
|
|
** Things are more complicated if the sqlite3_changes() function is
|
|
** executed while a trigger program is running. This may happen if the
|
|
** program uses the [changes() SQL function], or if some other callback
|
|
** function invokes sqlite3_changes() directly. Essentially:
|
|
**
|
|
** <ul>
|
|
** <li> ^(Before entering a trigger program the value returned by
|
|
** sqlite3_changes() function is saved. After the trigger program
|
|
** has finished, the original value is restored.)^
|
|
**
|
|
** <li> ^(Within a trigger program each INSERT, UPDATE and DELETE
|
|
** statement sets the value returned by sqlite3_changes()
|
|
** upon completion as normal. Of course, this value will not include
|
|
** any changes performed by sub-triggers, as the sqlite3_changes()
|
|
** value will be saved and restored after each sub-trigger has run.)^
|
|
** </ul>
|
|
**
|
|
** ^This means that if the changes() SQL function (or similar) is used
|
|
** by the first INSERT, UPDATE or DELETE statement within a trigger, it
|
|
** returns the value as set when the calling statement began executing.
|
|
** ^If it is used by the second or subsequent such statement within a trigger
|
|
** program, the value returned reflects the number of rows modified by the
|
|
** previous INSERT, UPDATE or DELETE statement within the same trigger.
|
|
**
|
|
** If a separate thread makes changes on the same database connection
|
|
** while [sqlite3_changes()] is running then the value returned
|
|
** is unpredictable and not meaningful.
|
|
**
|
|
** See also:
|
|
** <ul>
|
|
** <li> the [sqlite3_total_changes()] interface
|
|
** <li> the [count_changes pragma]
|
|
** <li> the [changes() SQL function]
|
|
** <li> the [data_version pragma]
|
|
** </ul>
|
|
*/
|
|
SQLITE_API int sqlite3_changes(sqlite3*);
|
|
SQLITE_API sqlite3_int64 sqlite3_changes64(sqlite3*);
|
|
|
|
/*
|
|
** CAPI3REF: Total Number Of Rows Modified
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^These functions return the total number of rows inserted, modified or
|
|
** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed
|
|
** since the database connection was opened, including those executed as
|
|
** part of trigger programs. The two functions are identical except for the
|
|
** type of the return value and that if the number of rows modified by the
|
|
** connection exceeds the maximum value supported by type "int", then
|
|
** the return value of sqlite3_total_changes() is undefined. ^Executing
|
|
** any other type of SQL statement does not affect the value returned by
|
|
** sqlite3_total_changes().
|
|
**
|
|
** ^Changes made as part of [foreign key actions] are included in the
|
|
** count, but those made as part of REPLACE constraint resolution are
|
|
** not. ^Changes to a view that are intercepted by INSTEAD OF triggers
|
|
** are not counted.
|
|
**
|
|
** The [sqlite3_total_changes(D)] interface only reports the number
|
|
** of rows that changed due to SQL statement run against database
|
|
** connection D. Any changes by other database connections are ignored.
|
|
** To detect changes against a database file from other database
|
|
** connections use the [PRAGMA data_version] command or the
|
|
** [SQLITE_FCNTL_DATA_VERSION] [file control].
|
|
**
|
|
** If a separate thread makes changes on the same database connection
|
|
** while [sqlite3_total_changes()] is running then the value
|
|
** returned is unpredictable and not meaningful.
|
|
**
|
|
** See also:
|
|
** <ul>
|
|
** <li> the [sqlite3_changes()] interface
|
|
** <li> the [count_changes pragma]
|
|
** <li> the [changes() SQL function]
|
|
** <li> the [data_version pragma]
|
|
** <li> the [SQLITE_FCNTL_DATA_VERSION] [file control]
|
|
** </ul>
|
|
*/
|
|
SQLITE_API int sqlite3_total_changes(sqlite3*);
|
|
SQLITE_API sqlite3_int64 sqlite3_total_changes64(sqlite3*);
|
|
|
|
/*
|
|
** CAPI3REF: Interrupt A Long-Running Query
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^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. But it
|
|
** is not safe to call this routine with a [database connection] that
|
|
** is closed or might close before sqlite3_interrupt() returns.
|
|
**
|
|
** ^If an SQL operation is very nearly finished at the time when
|
|
** sqlite3_interrupt() is called, then it might not have an opportunity
|
|
** to be interrupted and might continue to completion.
|
|
**
|
|
** ^An SQL operation that is interrupted will return [SQLITE_INTERRUPT].
|
|
** ^If the interrupted SQL operation is an INSERT, UPDATE, or DELETE
|
|
** that is inside an explicit transaction, then the entire transaction
|
|
** will be rolled back automatically.
|
|
**
|
|
** ^The sqlite3_interrupt(D) call is in effect until all currently running
|
|
** SQL statements on [database connection] D complete. ^Any new SQL statements
|
|
** that are started after the sqlite3_interrupt() call and before the
|
|
** running statement count reaches zero are interrupted as if they had been
|
|
** running prior to the sqlite3_interrupt() call. ^New SQL statements
|
|
** that are started after the running statement count reaches zero are
|
|
** not effected by the sqlite3_interrupt().
|
|
** ^A call to sqlite3_interrupt(D) that occurs when there are no running
|
|
** SQL statements is a no-op and has no effect on SQL statements
|
|
** that are started after the sqlite3_interrupt() call returns.
|
|
**
|
|
** ^The [sqlite3_is_interrupted(D)] interface can be used to determine whether
|
|
** or not an interrupt is currently in effect for [database connection] D.
|
|
** It returns 1 if an interrupt is currently in effect, or 0 otherwise.
|
|
*/
|
|
SQLITE_API void sqlite3_interrupt(sqlite3*);
|
|
SQLITE_API int sqlite3_is_interrupted(sqlite3*);
|
|
|
|
/*
|
|
** CAPI3REF: Determine If An SQL Statement Is Complete
|
|
**
|
|
** These routines are useful during command-line input to determine if the
|
|
** currently entered text seems to form a complete SQL statement or
|
|
** if additional input is needed before sending the text into
|
|
** SQLite for parsing. ^These routines return 1 if the input string
|
|
** appears to be a complete SQL statement. ^A statement is judged to be
|
|
** complete if it ends with a semicolon token and is not a prefix of a
|
|
** well-formed CREATE TRIGGER statement. ^Semicolons that are embedded within
|
|
** string literals or quoted identifier names or comments are not
|
|
** independent tokens (they are part of the token in which they are
|
|
** embedded) and thus do not count as a statement terminator. ^Whitespace
|
|
** and comments that follow the final semicolon are ignored.
|
|
**
|
|
** ^These routines return 0 if the statement is incomplete. ^If a
|
|
** memory allocation fails, then SQLITE_NOMEM is returned.
|
|
**
|
|
** ^These routines do not parse the SQL statements thus
|
|
** will not detect syntactically incorrect SQL.
|
|
**
|
|
** ^(If SQLite has not been initialized using [sqlite3_initialize()] prior
|
|
** to invoking sqlite3_complete16() then sqlite3_initialize() is invoked
|
|
** automatically by sqlite3_complete16(). If that initialization fails,
|
|
** then the return value from sqlite3_complete16() will be non-zero
|
|
** regardless of whether or not the input SQL is complete.)^
|
|
**
|
|
** The input to [sqlite3_complete()] must be a zero-terminated
|
|
** UTF-8 string.
|
|
**
|
|
** The input to [sqlite3_complete16()] must be a zero-terminated
|
|
** UTF-16 string in native byte order.
|
|
*/
|
|
SQLITE_API int sqlite3_complete(const char *sql);
|
|
SQLITE_API int sqlite3_complete16(const void *sql);
|
|
|
|
/*
|
|
** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors
|
|
** KEYWORDS: {busy-handler callback} {busy handler}
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X
|
|
** that might be invoked with argument P whenever
|
|
** an attempt is made to access a database table associated with
|
|
** [database connection] D when another thread
|
|
** or process has the table locked.
|
|
** The sqlite3_busy_handler() interface is used to implement
|
|
** [sqlite3_busy_timeout()] and [PRAGMA busy_timeout].
|
|
**
|
|
** ^If the busy callback is NULL, then [SQLITE_BUSY]
|
|
** is returned immediately upon encountering the lock. ^If the busy callback
|
|
** is not NULL, then the callback might be invoked with two arguments.
|
|
**
|
|
** ^The first argument to the busy handler is a copy of the void* pointer which
|
|
** is the third argument to sqlite3_busy_handler(). ^The second argument to
|
|
** the busy handler callback is the number of times that the busy handler has
|
|
** been invoked previously for the same locking event. ^If the
|
|
** busy callback returns 0, then no additional attempts are made to
|
|
** access the database and [SQLITE_BUSY] is returned
|
|
** to the application.
|
|
** ^If the callback returns non-zero, then another attempt
|
|
** is made to access the database 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 go ahead and return [SQLITE_BUSY]
|
|
** to the application instead of invoking the
|
|
** busy handler.
|
|
** 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.
|
|
**
|
|
** ^(There can only be a single busy handler defined for each
|
|
** [database connection]. Setting a new busy handler clears any
|
|
** previously set handler.)^ ^Note that calling [sqlite3_busy_timeout()]
|
|
** or evaluating [PRAGMA busy_timeout=N] will change the
|
|
** busy handler and thus clear any previously set busy handler.
|
|
**
|
|
** The busy callback should not take any actions which modify the
|
|
** database connection that invoked the busy handler. In other words,
|
|
** the busy handler is not reentrant. Any such actions
|
|
** result in undefined behavior.
|
|
**
|
|
** A busy handler must not close the database connection
|
|
** or [prepared statement] that invoked the busy handler.
|
|
*/
|
|
SQLITE_API int sqlite3_busy_handler(sqlite3*,int(*)(void*,int),void*);
|
|
|
|
/*
|
|
** CAPI3REF: Set A Busy Timeout
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps
|
|
** for a specified amount of time when a table is locked. ^The handler
|
|
** will sleep multiple times until at least "ms" milliseconds of sleeping
|
|
** have accumulated. ^After at least "ms" milliseconds of sleeping,
|
|
** the handler returns 0 which causes [sqlite3_step()] to return
|
|
** [SQLITE_BUSY].
|
|
**
|
|
** ^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] at any given moment. If another busy handler
|
|
** was defined (using [sqlite3_busy_handler()]) prior to calling
|
|
** this routine, that other busy handler is cleared.)^
|
|
**
|
|
** See also: [PRAGMA busy_timeout]
|
|
*/
|
|
SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
|
|
|
|
/*
|
|
** CAPI3REF: Convenience Routines For Running Queries
|
|
** METHOD: sqlite3
|
|
**
|
|
** This is a legacy interface that is preserved for backwards compatibility.
|
|
** Use of this interface is not recommended.
|
|
**
|
|
** Definition: A <b>result table</b> is memory data structure created by the
|
|
** [sqlite3_get_table()] interface. A result table records the
|
|
** complete query results from one or more queries.
|
|
**
|
|
** The table conceptually has a number of rows and columns. But
|
|
** these numbers are not part of the result table itself. These
|
|
** numbers are obtained separately. Let N be the number of rows
|
|
** and M be the number of columns.
|
|
**
|
|
** A result table is an array of pointers to zero-terminated UTF-8 strings.
|
|
** There are (N+1)*M elements in the array. The first M pointers point
|
|
** to zero-terminated strings that contain the names of the columns.
|
|
** The remaining entries all point to query results. NULL values result
|
|
** in NULL pointers. All other values are in their UTF-8 zero-terminated
|
|
** string representation as returned by [sqlite3_column_text()].
|
|
**
|
|
** A result table might consist of one or more memory allocations.
|
|
** It is not safe to pass a result table directly to [sqlite3_free()].
|
|
** A result table should be deallocated using [sqlite3_free_table()].
|
|
**
|
|
** ^(As an example of the result table format, suppose a query result
|
|
** is as follows:
|
|
**
|
|
** <blockquote><pre>
|
|
** Name | Age
|
|
** -----------------------
|
|
** Alice | 43
|
|
** Bob | 28
|
|
** Cindy | 21
|
|
** </pre></blockquote>
|
|
**
|
|
** There are two columns (M==2) and three rows (N==3). Thus the
|
|
** result table has 8 entries. Suppose the result table is stored
|
|
** in an array named azResult. Then azResult holds this content:
|
|
**
|
|
** <blockquote><pre>
|
|
** azResult[0] = "Name";
|
|
** azResult[1] = "Age";
|
|
** azResult[2] = "Alice";
|
|
** azResult[3] = "43";
|
|
** azResult[4] = "Bob";
|
|
** azResult[5] = "28";
|
|
** azResult[6] = "Cindy";
|
|
** azResult[7] = "21";
|
|
** </pre></blockquote>)^
|
|
**
|
|
** ^The sqlite3_get_table() function evaluates one or more
|
|
** semicolon-separated SQL statements in the zero-terminated UTF-8
|
|
** string of its 2nd parameter and returns a result table to the
|
|
** pointer given in its 3rd parameter.
|
|
**
|
|
** After the application has finished with the result from sqlite3_get_table(),
|
|
** it must pass the result table pointer to sqlite3_free_table() in order to
|
|
** release the memory that was malloced. Because of the way the
|
|
** [sqlite3_malloc()] happens within sqlite3_get_table(), 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 sqlite3_get_table() interface is implemented as a wrapper around
|
|
** [sqlite3_exec()]. The sqlite3_get_table() routine does not have access
|
|
** to any internal data structures of SQLite. It uses only the public
|
|
** interface defined here. As a consequence, errors that occur in the
|
|
** wrapper layer outside of the internal [sqlite3_exec()] call are not
|
|
** reflected in subsequent calls to [sqlite3_errcode()] or
|
|
** [sqlite3_errmsg()].
|
|
*/
|
|
SQLITE_API int sqlite3_get_table(
|
|
sqlite3 *db, /* An open database */
|
|
const char *zSql, /* SQL to be evaluated */
|
|
char ***pazResult, /* Results of the query */
|
|
int *pnRow, /* Number of result rows written here */
|
|
int *pnColumn, /* Number of result columns written here */
|
|
char **pzErrmsg /* Error msg written here */
|
|
);
|
|
SQLITE_API void sqlite3_free_table(char **result);
|
|
|
|
/*
|
|
** CAPI3REF: Formatted String Printing Functions
|
|
**
|
|
** These routines are work-alikes of the "printf()" family of functions
|
|
** from the standard C library.
|
|
** These routines understand most of the common formatting options from
|
|
** the standard library printf()
|
|
** plus some additional non-standard formats ([%q], [%Q], [%w], and [%z]).
|
|
** See the [built-in printf()] documentation for details.
|
|
**
|
|
** ^The sqlite3_mprintf() and sqlite3_vmprintf() routines write their
|
|
** results into memory obtained from [sqlite3_malloc64()].
|
|
** The strings returned by these two routines should be
|
|
** released by [sqlite3_free()]. ^Both routines return a
|
|
** NULL pointer if [sqlite3_malloc64()] is unable to allocate enough
|
|
** memory to hold the resulting string.
|
|
**
|
|
** ^(The 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.
|
|
**
|
|
** ^The sqlite3_vsnprintf() routine is a varargs version of sqlite3_snprintf().
|
|
**
|
|
** See also: [built-in printf()], [printf() SQL function]
|
|
*/
|
|
SQLITE_API char *sqlite3_mprintf(const char*,...);
|
|
SQLITE_API char *sqlite3_vmprintf(const char*, va_list);
|
|
SQLITE_API char *sqlite3_snprintf(int,char*,const char*, ...);
|
|
SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list);
|
|
|
|
/*
|
|
** CAPI3REF: Memory Allocation Subsystem
|
|
**
|
|
** The SQLite core uses these three routines for all of its own
|
|
** internal memory allocation needs. "Core" in the previous sentence
|
|
** does not include operating-system specific [VFS] implementation. The
|
|
** Windows VFS uses native malloc() and free() for some operations.
|
|
**
|
|
** ^The sqlite3_malloc() routine returns a pointer to a block
|
|
** of memory at least N bytes in length, where N is the parameter.
|
|
** ^If sqlite3_malloc() is unable to obtain sufficient free
|
|
** memory, it returns a NULL pointer. ^If the parameter N to
|
|
** sqlite3_malloc() is zero or negative then sqlite3_malloc() returns
|
|
** a NULL pointer.
|
|
**
|
|
** ^The sqlite3_malloc64(N) routine works just like
|
|
** sqlite3_malloc(N) except that N is an unsigned 64-bit integer instead
|
|
** of a signed 32-bit integer.
|
|
**
|
|
** ^Calling sqlite3_free() with a pointer previously returned
|
|
** by sqlite3_malloc() or sqlite3_realloc() releases that memory so
|
|
** that it might be reused. ^The sqlite3_free() routine is
|
|
** a no-op if is called with a NULL pointer. Passing a NULL pointer
|
|
** to sqlite3_free() is harmless. After being freed, memory
|
|
** should neither be read nor written. Even reading previously freed
|
|
** memory might result in a segmentation fault or other severe error.
|
|
** Memory corruption, a segmentation fault, or other severe error
|
|
** might result if sqlite3_free() is called with a non-NULL pointer that
|
|
** was not obtained from sqlite3_malloc() or sqlite3_realloc().
|
|
**
|
|
** ^The sqlite3_realloc(X,N) interface attempts to resize a
|
|
** prior memory allocation X to be at least N bytes.
|
|
** ^If the X parameter to sqlite3_realloc(X,N)
|
|
** is a NULL pointer then its behavior is identical to calling
|
|
** sqlite3_malloc(N).
|
|
** ^If the N parameter to sqlite3_realloc(X,N) is zero or
|
|
** negative then the behavior is exactly the same as calling
|
|
** sqlite3_free(X).
|
|
** ^sqlite3_realloc(X,N) returns a pointer to a memory allocation
|
|
** of at least N bytes in size or NULL if insufficient memory is available.
|
|
** ^If M is the size of the prior allocation, then min(N,M) bytes
|
|
** of the prior allocation are copied into the beginning of buffer returned
|
|
** by sqlite3_realloc(X,N) and the prior allocation is freed.
|
|
** ^If sqlite3_realloc(X,N) returns NULL and N is positive, then the
|
|
** prior allocation is not freed.
|
|
**
|
|
** ^The sqlite3_realloc64(X,N) interfaces works the same as
|
|
** sqlite3_realloc(X,N) except that N is a 64-bit unsigned integer instead
|
|
** of a 32-bit signed integer.
|
|
**
|
|
** ^If X is a memory allocation previously obtained from sqlite3_malloc(),
|
|
** sqlite3_malloc64(), sqlite3_realloc(), or sqlite3_realloc64(), then
|
|
** sqlite3_msize(X) returns the size of that memory allocation in bytes.
|
|
** ^The value returned by sqlite3_msize(X) might be larger than the number
|
|
** of bytes requested when X was allocated. ^If X is a NULL pointer then
|
|
** sqlite3_msize(X) returns zero. If X points to something that is not
|
|
** the beginning of memory allocation, or if it points to a formerly
|
|
** valid memory allocation that has now been freed, then the behavior
|
|
** of sqlite3_msize(X) is undefined and possibly harmful.
|
|
**
|
|
** ^The memory returned by sqlite3_malloc(), sqlite3_realloc(),
|
|
** sqlite3_malloc64(), and sqlite3_realloc64()
|
|
** is always aligned to at least an 8 byte boundary, or to a
|
|
** 4 byte boundary if the [SQLITE_4_BYTE_ALIGNED_MALLOC] compile-time
|
|
** option is used.
|
|
**
|
|
** The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()]
|
|
** must be either NULL or else pointers obtained from a prior
|
|
** invocation of [sqlite3_malloc()] or [sqlite3_realloc()] that have
|
|
** not yet been released.
|
|
**
|
|
** The application must not read or write any part of
|
|
** a block of memory after it has been released using
|
|
** [sqlite3_free()] or [sqlite3_realloc()].
|
|
*/
|
|
SQLITE_API void *sqlite3_malloc(int);
|
|
SQLITE_API void *sqlite3_malloc64(sqlite3_uint64);
|
|
SQLITE_API void *sqlite3_realloc(void*, int);
|
|
SQLITE_API void *sqlite3_realloc64(void*, sqlite3_uint64);
|
|
SQLITE_API void sqlite3_free(void*);
|
|
SQLITE_API sqlite3_uint64 sqlite3_msize(void*);
|
|
|
|
/*
|
|
** CAPI3REF: Memory Allocator Statistics
|
|
**
|
|
** SQLite provides these two interfaces for reporting on the status
|
|
** of the [sqlite3_malloc()], [sqlite3_free()], and [sqlite3_realloc()]
|
|
** routines, which form the built-in memory allocation subsystem.
|
|
**
|
|
** ^The [sqlite3_memory_used()] routine returns the number of bytes
|
|
** of memory currently outstanding (malloced but not freed).
|
|
** ^The [sqlite3_memory_highwater()] routine returns the maximum
|
|
** value of [sqlite3_memory_used()] since the high-water mark
|
|
** was last reset. ^The values returned by [sqlite3_memory_used()] and
|
|
** [sqlite3_memory_highwater()] include any overhead
|
|
** added by SQLite in its implementation of [sqlite3_malloc()],
|
|
** but not overhead added by the any underlying system library
|
|
** routines that [sqlite3_malloc()] may call.
|
|
**
|
|
** ^The memory high-water mark is reset to the current value of
|
|
** [sqlite3_memory_used()] if and only if the parameter to
|
|
** [sqlite3_memory_highwater()] is true. ^The value returned
|
|
** by [sqlite3_memory_highwater(1)] is the high-water mark
|
|
** prior to the reset.
|
|
*/
|
|
SQLITE_API sqlite3_int64 sqlite3_memory_used(void);
|
|
SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag);
|
|
|
|
/*
|
|
** CAPI3REF: Pseudo-Random Number Generator
|
|
**
|
|
** SQLite contains a high-quality pseudo-random number generator (PRNG) used to
|
|
** select random [ROWID | ROWIDs] when inserting new records into a table that
|
|
** already uses the largest possible [ROWID]. The PRNG is also used for
|
|
** the built-in random() and randomblob() SQL functions. This interface allows
|
|
** applications to access the same PRNG for other purposes.
|
|
**
|
|
** ^A call to this routine stores N bytes of randomness into buffer P.
|
|
** ^The P parameter can be a NULL pointer.
|
|
**
|
|
** ^If this routine has not been previously called or if the previous
|
|
** call had N less than one or a NULL pointer for P, then the PRNG is
|
|
** seeded using randomness obtained from the xRandomness method of
|
|
** the default [sqlite3_vfs] object.
|
|
** ^If the previous call to this routine had an N of 1 or more and a
|
|
** non-NULL P then the pseudo-randomness is generated
|
|
** internally and without recourse to the [sqlite3_vfs] xRandomness
|
|
** method.
|
|
*/
|
|
SQLITE_API void sqlite3_randomness(int N, void *P);
|
|
|
|
/*
|
|
** CAPI3REF: Compile-Time Authorization Callbacks
|
|
** METHOD: sqlite3
|
|
** KEYWORDS: {authorizer callback}
|
|
**
|
|
** ^This routine registers an authorizer callback with a particular
|
|
** [database connection], supplied in the first argument.
|
|
** ^The authorizer callback is invoked as SQL statements are being compiled
|
|
** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()],
|
|
** [sqlite3_prepare_v3()], [sqlite3_prepare16()], [sqlite3_prepare16_v2()],
|
|
** and [sqlite3_prepare16_v3()]. ^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. ^If the authorizer callback returns
|
|
** any value other than [SQLITE_IGNORE], [SQLITE_OK], or [SQLITE_DENY]
|
|
** then the [sqlite3_prepare_v2()] or equivalent call that triggered
|
|
** the authorizer will fail with an error message.
|
|
**
|
|
** When the callback returns [SQLITE_OK], that means the operation
|
|
** requested is ok. ^When the callback returns [SQLITE_DENY], the
|
|
** [sqlite3_prepare_v2()] or equivalent call that triggered the
|
|
** authorizer will fail with an error message explaining that
|
|
** access is denied.
|
|
**
|
|
** ^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 third through sixth parameters
|
|
** to the callback are either NULL pointers or zero-terminated strings
|
|
** that contain additional details about the action to be authorized.
|
|
** Applications must always be prepared to encounter a NULL pointer in any
|
|
** of the third through the sixth parameters of the authorization callback.
|
|
**
|
|
** ^If the action code is [SQLITE_READ]
|
|
** and the callback returns [SQLITE_IGNORE] then the
|
|
** [prepared statement] statement is constructed to substitute
|
|
** a NULL value in place of the table column that would have
|
|
** been read if [SQLITE_OK] had been returned. The [SQLITE_IGNORE]
|
|
** return can be used to deny an untrusted user access to individual
|
|
** columns of a table.
|
|
** ^When a table is referenced by a [SELECT] but no column values are
|
|
** extracted from that table (for example in a query like
|
|
** "SELECT count(*) FROM tab") then the [SQLITE_READ] authorizer callback
|
|
** is invoked once for that table with a column name that is an empty string.
|
|
** ^If the action code is [SQLITE_DELETE] and the callback returns
|
|
** [SQLITE_IGNORE] then the [DELETE] operation proceeds but the
|
|
** [truncate optimization] is disabled and all rows are deleted individually.
|
|
**
|
|
** An authorizer is used when [sqlite3_prepare | preparing]
|
|
** SQL statements from an untrusted source, to ensure that the SQL statements
|
|
** do not try to access data 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 [sqlite3_prepare | prepared] that
|
|
** disallows everything except [SELECT] statements.
|
|
**
|
|
** Applications that need to process SQL from untrusted sources
|
|
** might also consider lowering resource limits using [sqlite3_limit()]
|
|
** and limiting database size using the [max_page_count] [PRAGMA]
|
|
** in addition to using an authorizer.
|
|
**
|
|
** ^(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.)^ ^Disable the authorizer by installing a NULL callback.
|
|
** The authorizer is disabled by default.
|
|
**
|
|
** The authorizer callback must not do anything that will modify
|
|
** the database connection that invoked the authorizer callback.
|
|
** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
|
|
** database connections for the meaning of "modify" in this paragraph.
|
|
**
|
|
** ^When [sqlite3_prepare_v2()] is used to prepare a statement, the
|
|
** statement might be re-prepared during [sqlite3_step()] due to a
|
|
** schema change. Hence, the application should ensure that the
|
|
** correct authorizer callback remains in place during the [sqlite3_step()].
|
|
**
|
|
** ^Note that the authorizer callback is invoked only during
|
|
** [sqlite3_prepare()] or its variants. Authorization is not
|
|
** performed during statement evaluation in [sqlite3_step()], unless
|
|
** as stated in the previous paragraph, sqlite3_step() invokes
|
|
** sqlite3_prepare_v2() to reprepare a statement after a schema change.
|
|
*/
|
|
SQLITE_API 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.
|
|
**
|
|
** Note that SQLITE_IGNORE is also used as a [conflict resolution mode]
|
|
** returned from the [sqlite3_vtab_on_conflict()] interface.
|
|
*/
|
|
#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 authorize 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 /* Operation 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 /* NULL Function Name */
|
|
#define SQLITE_SAVEPOINT 32 /* Operation Savepoint Name */
|
|
#define SQLITE_COPY 0 /* No longer used */
|
|
#define SQLITE_RECURSIVE 33 /* NULL NULL */
|
|
|
|
/*
|
|
** CAPI3REF: Tracing And Profiling Functions
|
|
** METHOD: sqlite3
|
|
**
|
|
** These routines are deprecated. Use the [sqlite3_trace_v2()] interface
|
|
** instead of the routines described here.
|
|
**
|
|
** 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
|
|
** various times when an SQL statement is being run by [sqlite3_step()].
|
|
** ^The sqlite3_trace() callback is invoked with a UTF-8 rendering of the
|
|
** SQL statement text as the statement first begins executing.
|
|
** ^(Additional sqlite3_trace() callbacks might occur
|
|
** as each triggered subprogram is entered. The callbacks for triggers
|
|
** contain a UTF-8 SQL comment that identifies the trigger.)^
|
|
**
|
|
** The [SQLITE_TRACE_SIZE_LIMIT] compile-time option can be used to limit
|
|
** the length of [bound parameter] expansion in the output of sqlite3_trace().
|
|
**
|
|
** ^The callback function registered by sqlite3_profile() is invoked
|
|
** as each SQL statement finishes. ^The profile callback contains
|
|
** the original statement text and an estimate of wall-clock time
|
|
** of how long that statement took to run. ^The profile callback
|
|
** time is in units of nanoseconds, however the current implementation
|
|
** is only capable of millisecond resolution so the six least significant
|
|
** digits in the time are meaningless. Future versions of SQLite
|
|
** might provide greater resolution on the profiler callback. Invoking
|
|
** either [sqlite3_trace()] or [sqlite3_trace_v2()] will cancel the
|
|
** profile callback.
|
|
*/
|
|
SQLITE_API SQLITE_DEPRECATED void *sqlite3_trace(sqlite3*,
|
|
void(*xTrace)(void*,const char*), void*);
|
|
SQLITE_API SQLITE_DEPRECATED void *sqlite3_profile(sqlite3*,
|
|
void(*xProfile)(void*,const char*,sqlite3_uint64), void*);
|
|
|
|
/*
|
|
** CAPI3REF: SQL Trace Event Codes
|
|
** KEYWORDS: SQLITE_TRACE
|
|
**
|
|
** These constants identify classes of events that can be monitored
|
|
** using the [sqlite3_trace_v2()] tracing logic. The M argument
|
|
** to [sqlite3_trace_v2(D,M,X,P)] is an OR-ed combination of one or more of
|
|
** the following constants. ^The first argument to the trace callback
|
|
** is one of the following constants.
|
|
**
|
|
** New tracing constants may be added in future releases.
|
|
**
|
|
** ^A trace callback has four arguments: xCallback(T,C,P,X).
|
|
** ^The T argument is one of the integer type codes above.
|
|
** ^The C argument is a copy of the context pointer passed in as the
|
|
** fourth argument to [sqlite3_trace_v2()].
|
|
** The P and X arguments are pointers whose meanings depend on T.
|
|
**
|
|
** <dl>
|
|
** [[SQLITE_TRACE_STMT]] <dt>SQLITE_TRACE_STMT</dt>
|
|
** <dd>^An SQLITE_TRACE_STMT callback is invoked when a prepared statement
|
|
** first begins running and possibly at other times during the
|
|
** execution of the prepared statement, such as at the start of each
|
|
** trigger subprogram. ^The P argument is a pointer to the
|
|
** [prepared statement]. ^The X argument is a pointer to a string which
|
|
** is the unexpanded SQL text of the prepared statement or an SQL comment
|
|
** that indicates the invocation of a trigger. ^The callback can compute
|
|
** the same text that would have been returned by the legacy [sqlite3_trace()]
|
|
** interface by using the X argument when X begins with "--" and invoking
|
|
** [sqlite3_expanded_sql(P)] otherwise.
|
|
**
|
|
** [[SQLITE_TRACE_PROFILE]] <dt>SQLITE_TRACE_PROFILE</dt>
|
|
** <dd>^An SQLITE_TRACE_PROFILE callback provides approximately the same
|
|
** information as is provided by the [sqlite3_profile()] callback.
|
|
** ^The P argument is a pointer to the [prepared statement] and the
|
|
** X argument points to a 64-bit integer which is approximately
|
|
** the number of nanoseconds that the prepared statement took to run.
|
|
** ^The SQLITE_TRACE_PROFILE callback is invoked when the statement finishes.
|
|
**
|
|
** [[SQLITE_TRACE_ROW]] <dt>SQLITE_TRACE_ROW</dt>
|
|
** <dd>^An SQLITE_TRACE_ROW callback is invoked whenever a prepared
|
|
** statement generates a single row of result.
|
|
** ^The P argument is a pointer to the [prepared statement] and the
|
|
** X argument is unused.
|
|
**
|
|
** [[SQLITE_TRACE_CLOSE]] <dt>SQLITE_TRACE_CLOSE</dt>
|
|
** <dd>^An SQLITE_TRACE_CLOSE callback is invoked when a database
|
|
** connection closes.
|
|
** ^The P argument is a pointer to the [database connection] object
|
|
** and the X argument is unused.
|
|
** </dl>
|
|
*/
|
|
#define SQLITE_TRACE_STMT 0x01
|
|
#define SQLITE_TRACE_PROFILE 0x02
|
|
#define SQLITE_TRACE_ROW 0x04
|
|
#define SQLITE_TRACE_CLOSE 0x08
|
|
|
|
/*
|
|
** CAPI3REF: SQL Trace Hook
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^The sqlite3_trace_v2(D,M,X,P) interface registers a trace callback
|
|
** function X against [database connection] D, using property mask M
|
|
** and context pointer P. ^If the X callback is
|
|
** NULL or if the M mask is zero, then tracing is disabled. The
|
|
** M argument should be the bitwise OR-ed combination of
|
|
** zero or more [SQLITE_TRACE] constants.
|
|
**
|
|
** ^Each call to either sqlite3_trace(D,X,P) or sqlite3_trace_v2(D,M,X,P)
|
|
** overrides (cancels) all prior calls to sqlite3_trace(D,X,P) or
|
|
** sqlite3_trace_v2(D,M,X,P) for the [database connection] D. Each
|
|
** database connection may have at most one trace callback.
|
|
**
|
|
** ^The X callback is invoked whenever any of the events identified by
|
|
** mask M occur. ^The integer return value from the callback is currently
|
|
** ignored, though this may change in future releases. Callback
|
|
** implementations should return zero to ensure future compatibility.
|
|
**
|
|
** ^A trace callback is invoked with four arguments: callback(T,C,P,X).
|
|
** ^The T argument is one of the [SQLITE_TRACE]
|
|
** constants to indicate why the callback was invoked.
|
|
** ^The C argument is a copy of the context pointer.
|
|
** The P and X arguments are pointers whose meanings depend on T.
|
|
**
|
|
** The sqlite3_trace_v2() interface is intended to replace the legacy
|
|
** interfaces [sqlite3_trace()] and [sqlite3_profile()], both of which
|
|
** are deprecated.
|
|
*/
|
|
SQLITE_API int sqlite3_trace_v2(
|
|
sqlite3*,
|
|
unsigned uMask,
|
|
int(*xCallback)(unsigned,void*,void*,void*),
|
|
void *pCtx
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Query Progress Callbacks
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback
|
|
** function X to be invoked periodically during long running calls to
|
|
** [sqlite3_step()] and [sqlite3_prepare()] and similar for
|
|
** database connection D. An example use for this
|
|
** interface is to keep a GUI updated during a large query.
|
|
**
|
|
** ^The parameter P is passed through as the only parameter to the
|
|
** callback function X. ^The parameter N is the approximate number of
|
|
** [virtual machine instructions] that are evaluated between successive
|
|
** invocations of the callback X. ^If N is less than one then the progress
|
|
** handler is disabled.
|
|
**
|
|
** ^Only a single progress handler may be defined at one time per
|
|
** [database connection]; setting a new progress handler cancels the
|
|
** old one. ^Setting parameter X to NULL disables the progress handler.
|
|
** ^The progress handler is also disabled by setting N to a value less
|
|
** than 1.
|
|
**
|
|
** ^If the progress callback returns non-zero, the operation is
|
|
** interrupted. This feature can be used to implement a
|
|
** "Cancel" button on a GUI progress dialog box.
|
|
**
|
|
** The progress handler callback must not do anything that will modify
|
|
** the database connection that invoked the progress handler.
|
|
** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
|
|
** database connections for the meaning of "modify" in this paragraph.
|
|
**
|
|
** The progress handler callback would originally only be invoked from the
|
|
** bytecode engine. It still might be invoked during [sqlite3_prepare()]
|
|
** and similar because those routines might force a reparse of the schema
|
|
** which involves running the bytecode engine. However, beginning with
|
|
** SQLite version 3.41.0, the progress handler callback might also be
|
|
** invoked directly from [sqlite3_prepare()] while analyzing and generating
|
|
** code for complex queries.
|
|
*/
|
|
SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
|
|
|
|
/*
|
|
** CAPI3REF: Opening A New Database Connection
|
|
** CONSTRUCTOR: sqlite3
|
|
**
|
|
** ^These routines open an SQLite database file as specified by the
|
|
** filename argument. ^The filename argument is interpreted as UTF-8 for
|
|
** sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte
|
|
** order for sqlite3_open16(). ^(A [database connection] handle is usually
|
|
** returned in *ppDb, even if an error occurs. The only exception is that
|
|
** if SQLite is unable to allocate memory to hold the [sqlite3] object,
|
|
** a NULL will be written into *ppDb instead of a pointer to the [sqlite3]
|
|
** object.)^ ^(If the database is opened (and/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 following a failure of any
|
|
** of the sqlite3_open() routines.
|
|
**
|
|
** ^The default encoding will be UTF-8 for databases created using
|
|
** sqlite3_open() or sqlite3_open_v2(). ^The default encoding for databases
|
|
** created using sqlite3_open16() will be UTF-16 in the native byte order.
|
|
**
|
|
** Whether or not an error occurs when it is opened, resources
|
|
** associated with the [database connection] handle should be released by
|
|
** passing it to [sqlite3_close()] when it is no longer required.
|
|
**
|
|
** The sqlite3_open_v2() interface works like sqlite3_open()
|
|
** except that it accepts two additional parameters for additional control
|
|
** over the new database connection. ^(The flags parameter to
|
|
** sqlite3_open_v2() must include, at a minimum, one of the following
|
|
** three flag combinations:)^
|
|
**
|
|
** <dl>
|
|
** ^(<dt>[SQLITE_OPEN_READONLY]</dt>
|
|
** <dd>The database is opened in read-only mode. If the database does
|
|
** not already exist, an error is returned.</dd>)^
|
|
**
|
|
** ^(<dt>[SQLITE_OPEN_READWRITE]</dt>
|
|
** <dd>The database is opened for reading and writing if possible, or
|
|
** reading only if the file is write protected by the operating
|
|
** system. In either case the database must already exist, otherwise
|
|
** an error is returned. For historical reasons, if opening in
|
|
** read-write mode fails due to OS-level permissions, an attempt is
|
|
** made to open it in read-only mode. [sqlite3_db_readonly()] can be
|
|
** used to determine whether the database is actually
|
|
** read-write.</dd>)^
|
|
**
|
|
** ^(<dt>[SQLITE_OPEN_READWRITE] | [SQLITE_OPEN_CREATE]</dt>
|
|
** <dd>The database is opened for reading and writing, and is created if
|
|
** it does not already exist. This is the behavior that is always used for
|
|
** sqlite3_open() and sqlite3_open16().</dd>)^
|
|
** </dl>
|
|
**
|
|
** In addition to the required flags, the following optional flags are
|
|
** also supported:
|
|
**
|
|
** <dl>
|
|
** ^(<dt>[SQLITE_OPEN_URI]</dt>
|
|
** <dd>The filename can be interpreted as a URI if this flag is set.</dd>)^
|
|
**
|
|
** ^(<dt>[SQLITE_OPEN_MEMORY]</dt>
|
|
** <dd>The database will be opened as an in-memory database. The database
|
|
** is named by the "filename" argument for the purposes of cache-sharing,
|
|
** if shared cache mode is enabled, but the "filename" is otherwise ignored.
|
|
** </dd>)^
|
|
**
|
|
** ^(<dt>[SQLITE_OPEN_NOMUTEX]</dt>
|
|
** <dd>The new database connection will use the "multi-thread"
|
|
** [threading mode].)^ This means that separate threads are allowed
|
|
** to use SQLite at the same time, as long as each thread is using
|
|
** a different [database connection].
|
|
**
|
|
** ^(<dt>[SQLITE_OPEN_FULLMUTEX]</dt>
|
|
** <dd>The new database connection will use the "serialized"
|
|
** [threading mode].)^ This means the multiple threads can safely
|
|
** attempt to use the same database connection at the same time.
|
|
** (Mutexes will block any actual concurrency, but in this mode
|
|
** there is no harm in trying.)
|
|
**
|
|
** ^(<dt>[SQLITE_OPEN_SHAREDCACHE]</dt>
|
|
** <dd>The database is opened [shared cache] enabled, overriding
|
|
** the default shared cache setting provided by
|
|
** [sqlite3_enable_shared_cache()].)^
|
|
** The [use of shared cache mode is discouraged] and hence shared cache
|
|
** capabilities may be omitted from many builds of SQLite. In such cases,
|
|
** this option is a no-op.
|
|
**
|
|
** ^(<dt>[SQLITE_OPEN_PRIVATECACHE]</dt>
|
|
** <dd>The database is opened [shared cache] disabled, overriding
|
|
** the default shared cache setting provided by
|
|
** [sqlite3_enable_shared_cache()].)^
|
|
**
|
|
** [[OPEN_EXRESCODE]] ^(<dt>[SQLITE_OPEN_EXRESCODE]</dt>
|
|
** <dd>The database connection comes up in "extended result code mode".
|
|
** In other words, the database behaves has if
|
|
** [sqlite3_extended_result_codes(db,1)] where called on the database
|
|
** connection as soon as the connection is created. In addition to setting
|
|
** the extended result code mode, this flag also causes [sqlite3_open_v2()]
|
|
** to return an extended result code.</dd>
|
|
**
|
|
** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt>
|
|
** <dd>The database filename is not allowed to contain a symbolic link</dd>
|
|
** </dl>)^
|
|
**
|
|
** If the 3rd parameter to sqlite3_open_v2() is not one of the
|
|
** required combinations shown above optionally combined with other
|
|
** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits]
|
|
** then the behavior is undefined. Historic versions of SQLite
|
|
** have silently ignored surplus bits in the flags parameter to
|
|
** sqlite3_open_v2(), however that behavior might not be carried through
|
|
** into future versions of SQLite and so applications should not rely
|
|
** upon it. Note in particular that the SQLITE_OPEN_EXCLUSIVE flag is a no-op
|
|
** for sqlite3_open_v2(). The SQLITE_OPEN_EXCLUSIVE does *not* cause
|
|
** the open to fail if the database already exists. The SQLITE_OPEN_EXCLUSIVE
|
|
** flag is intended for use by the [sqlite3_vfs|VFS interface] only, and not
|
|
** by sqlite3_open_v2().
|
|
**
|
|
** ^The fourth parameter to sqlite3_open_v2() is the name of the
|
|
** [sqlite3_vfs] object that defines the operating system interface that
|
|
** the new database connection should use. ^If the fourth parameter is
|
|
** a NULL pointer then the default [sqlite3_vfs] object is used.
|
|
**
|
|
** ^If the filename is ":memory:", then a private, temporary in-memory database
|
|
** is created for the connection. ^This in-memory database will vanish when
|
|
** the database connection is closed. Future versions of SQLite might
|
|
** make use of additional special filenames that begin with the ":" character.
|
|
** It is recommended that when a database filename actually does begin with
|
|
** a ":" character you should prefix the filename with a pathname such as
|
|
** "./" to avoid ambiguity.
|
|
**
|
|
** ^If the filename is an empty string, then a private, temporary
|
|
** on-disk database will be created. ^This private database will be
|
|
** automatically deleted as soon as the database connection is closed.
|
|
**
|
|
** [[URI filenames in sqlite3_open()]] <h3>URI Filenames</h3>
|
|
**
|
|
** ^If [URI filename] interpretation is enabled, and the filename argument
|
|
** begins with "file:", then the filename is interpreted as a URI. ^URI
|
|
** filename interpretation is enabled if the [SQLITE_OPEN_URI] flag is
|
|
** set in the third argument to sqlite3_open_v2(), or if it has
|
|
** been enabled globally using the [SQLITE_CONFIG_URI] option with the
|
|
** [sqlite3_config()] method or by the [SQLITE_USE_URI] compile-time option.
|
|
** URI filename interpretation is turned off
|
|
** by default, but future releases of SQLite might enable URI filename
|
|
** interpretation by default. See "[URI filenames]" for additional
|
|
** information.
|
|
**
|
|
** URI filenames are parsed according to RFC 3986. ^If the URI contains an
|
|
** authority, then it must be either an empty string or the string
|
|
** "localhost". ^If the authority is not an empty string or "localhost", an
|
|
** error is returned to the caller. ^The fragment component of a URI, if
|
|
** present, is ignored.
|
|
**
|
|
** ^SQLite uses the path component of the URI as the name of the disk file
|
|
** which contains the database. ^If the path begins with a '/' character,
|
|
** then it is interpreted as an absolute path. ^If the path does not begin
|
|
** with a '/' (meaning that the authority section is omitted from the URI)
|
|
** then the path is interpreted as a relative path.
|
|
** ^(On windows, the first component of an absolute path
|
|
** is a drive specification (e.g. "C:").)^
|
|
**
|
|
** [[core URI query parameters]]
|
|
** The query component of a URI may contain parameters that are interpreted
|
|
** either by SQLite itself, or by a [VFS | custom VFS implementation].
|
|
** SQLite and its built-in [VFSes] interpret the
|
|
** following query parameters:
|
|
**
|
|
** <ul>
|
|
** <li> <b>vfs</b>: ^The "vfs" parameter may be used to specify the name of
|
|
** a VFS object that provides the operating system interface that should
|
|
** be used to access the database file on disk. ^If this option is set to
|
|
** an empty string the default VFS object is used. ^Specifying an unknown
|
|
** VFS is an error. ^If sqlite3_open_v2() is used and the vfs option is
|
|
** present, then the VFS specified by the option takes precedence over
|
|
** the value passed as the fourth parameter to sqlite3_open_v2().
|
|
**
|
|
** <li> <b>mode</b>: ^(The mode parameter may be set to either "ro", "rw",
|
|
** "rwc", or "memory". Attempting to set it to any other value is
|
|
** an error)^.
|
|
** ^If "ro" is specified, then the database is opened for read-only
|
|
** access, just as if the [SQLITE_OPEN_READONLY] flag had been set in the
|
|
** third argument to sqlite3_open_v2(). ^If the mode option is set to
|
|
** "rw", then the database is opened for read-write (but not create)
|
|
** access, as if SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had
|
|
** been set. ^Value "rwc" is equivalent to setting both
|
|
** SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. ^If the mode option is
|
|
** set to "memory" then a pure [in-memory database] that never reads
|
|
** or writes from disk is used. ^It is an error to specify a value for
|
|
** the mode parameter that is less restrictive than that specified by
|
|
** the flags passed in the third parameter to sqlite3_open_v2().
|
|
**
|
|
** <li> <b>cache</b>: ^The cache parameter may be set to either "shared" or
|
|
** "private". ^Setting it to "shared" is equivalent to setting the
|
|
** SQLITE_OPEN_SHAREDCACHE bit in the flags argument passed to
|
|
** sqlite3_open_v2(). ^Setting the cache parameter to "private" is
|
|
** equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
|
|
** ^If sqlite3_open_v2() is used and the "cache" parameter is present in
|
|
** a URI filename, its value overrides any behavior requested by setting
|
|
** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
|
|
**
|
|
** <li> <b>psow</b>: ^The psow parameter indicates whether or not the
|
|
** [powersafe overwrite] property does or does not apply to the
|
|
** storage media on which the database file resides.
|
|
**
|
|
** <li> <b>nolock</b>: ^The nolock parameter is a boolean query parameter
|
|
** which if set disables file locking in rollback journal modes. This
|
|
** is useful for accessing a database on a filesystem that does not
|
|
** support locking. Caution: Database corruption might result if two
|
|
** or more processes write to the same database and any one of those
|
|
** processes uses nolock=1.
|
|
**
|
|
** <li> <b>immutable</b>: ^The immutable parameter is a boolean query
|
|
** parameter that indicates that the database file is stored on
|
|
** read-only media. ^When immutable is set, SQLite assumes that the
|
|
** database file cannot be changed, even by a process with higher
|
|
** privilege, and so the database is opened read-only and all locking
|
|
** and change detection is disabled. Caution: Setting the immutable
|
|
** property on a database file that does in fact change can result
|
|
** in incorrect query results and/or [SQLITE_CORRUPT] errors.
|
|
** See also: [SQLITE_IOCAP_IMMUTABLE].
|
|
**
|
|
** </ul>
|
|
**
|
|
** ^Specifying an unknown parameter in the query component of a URI is not an
|
|
** error. Future versions of SQLite might understand additional query
|
|
** parameters. See "[query parameters with special meaning to SQLite]" for
|
|
** additional information.
|
|
**
|
|
** [[URI filename examples]] <h3>URI filename examples</h3>
|
|
**
|
|
** <table border="1" align=center cellpadding=5>
|
|
** <tr><th> URI filenames <th> Results
|
|
** <tr><td> file:data.db <td>
|
|
** Open the file "data.db" in the current directory.
|
|
** <tr><td> file:/home/fred/data.db<br>
|
|
** file:///home/fred/data.db <br>
|
|
** file://localhost/home/fred/data.db <br> <td>
|
|
** Open the database file "/home/fred/data.db".
|
|
** <tr><td> file://darkstar/home/fred/data.db <td>
|
|
** An error. "darkstar" is not a recognized authority.
|
|
** <tr><td style="white-space:nowrap">
|
|
** file:///C:/Documents%20and%20Settings/fred/Desktop/data.db
|
|
** <td> Windows only: Open the file "data.db" on fred's desktop on drive
|
|
** C:. Note that the %20 escaping in this example is not strictly
|
|
** necessary - space characters can be used literally
|
|
** in URI filenames.
|
|
** <tr><td> file:data.db?mode=ro&cache=private <td>
|
|
** Open file "data.db" in the current directory for read-only access.
|
|
** Regardless of whether or not shared-cache mode is enabled by
|
|
** default, use a private cache.
|
|
** <tr><td> file:/home/fred/data.db?vfs=unix-dotfile <td>
|
|
** Open file "/home/fred/data.db". Use the special VFS "unix-dotfile"
|
|
** that uses dot-files in place of posix advisory locking.
|
|
** <tr><td> file:data.db?mode=readonly <td>
|
|
** An error. "readonly" is not a valid option for the "mode" parameter.
|
|
** Use "ro" instead: "file:data.db?mode=ro".
|
|
** </table>
|
|
**
|
|
** ^URI hexadecimal escape sequences (%HH) are supported within the path and
|
|
** query components of a URI. A hexadecimal escape sequence consists of a
|
|
** percent sign - "%" - followed by exactly two hexadecimal digits
|
|
** specifying an octet value. ^Before the path or query components of a
|
|
** URI filename are interpreted, they are encoded using UTF-8 and all
|
|
** hexadecimal escape sequences replaced by a single byte containing the
|
|
** corresponding octet. If this process generates an invalid UTF-8 encoding,
|
|
** the results are undefined.
|
|
**
|
|
** <b>Note to Windows users:</b> The encoding used for the filename argument
|
|
** of sqlite3_open() and sqlite3_open_v2() 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() or sqlite3_open_v2().
|
|
**
|
|
** <b>Note to Windows Runtime users:</b> The temporary directory must be set
|
|
** prior to calling sqlite3_open() or sqlite3_open_v2(). Otherwise, various
|
|
** features that require the use of temporary files may fail.
|
|
**
|
|
** See also: [sqlite3_temp_directory]
|
|
*/
|
|
SQLITE_API int sqlite3_open(
|
|
const char *filename, /* Database filename (UTF-8) */
|
|
sqlite3 **ppDb /* OUT: SQLite db handle */
|
|
);
|
|
SQLITE_API int sqlite3_open16(
|
|
const void *filename, /* Database filename (UTF-16) */
|
|
sqlite3 **ppDb /* OUT: SQLite db handle */
|
|
);
|
|
SQLITE_API int sqlite3_open_v2(
|
|
const char *filename, /* Database filename (UTF-8) */
|
|
sqlite3 **ppDb, /* OUT: SQLite db handle */
|
|
int flags, /* Flags */
|
|
const char *zVfs /* Name of VFS module to use */
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Obtain Values For URI Parameters
|
|
**
|
|
** These are utility routines, useful to [VFS|custom VFS implementations],
|
|
** that check if a database file was a URI that contained a specific query
|
|
** parameter, and if so obtains the value of that query parameter.
|
|
**
|
|
** The first parameter to these interfaces (hereafter referred to
|
|
** as F) must be one of:
|
|
** <ul>
|
|
** <li> A database filename pointer created by the SQLite core and
|
|
** passed into the xOpen() method of a VFS implementation, or
|
|
** <li> A filename obtained from [sqlite3_db_filename()], or
|
|
** <li> A new filename constructed using [sqlite3_create_filename()].
|
|
** </ul>
|
|
** If the F parameter is not one of the above, then the behavior is
|
|
** undefined and probably undesirable. Older versions of SQLite were
|
|
** more tolerant of invalid F parameters than newer versions.
|
|
**
|
|
** If F is a suitable filename (as described in the previous paragraph)
|
|
** and if P is the name of the query parameter, then
|
|
** sqlite3_uri_parameter(F,P) returns the value of the P
|
|
** parameter if it exists or a NULL pointer if P does not appear as a
|
|
** query parameter on F. If P is a query parameter of F and it
|
|
** has no explicit value, then sqlite3_uri_parameter(F,P) returns
|
|
** a pointer to an empty string.
|
|
**
|
|
** The sqlite3_uri_boolean(F,P,B) routine assumes that P is a boolean
|
|
** parameter and returns true (1) or false (0) according to the value
|
|
** of P. The sqlite3_uri_boolean(F,P,B) routine returns true (1) if the
|
|
** value of query parameter P is one of "yes", "true", or "on" in any
|
|
** case or if the value begins with a non-zero number. The
|
|
** sqlite3_uri_boolean(F,P,B) routines returns false (0) if the value of
|
|
** query parameter P is one of "no", "false", or "off" in any case or
|
|
** if the value begins with a numeric zero. If P is not a query
|
|
** parameter on F or if the value of P does not match any of the
|
|
** above, then sqlite3_uri_boolean(F,P,B) returns (B!=0).
|
|
**
|
|
** The sqlite3_uri_int64(F,P,D) routine converts the value of P into a
|
|
** 64-bit signed integer and returns that integer, or D if P does not
|
|
** exist. If the value of P is something other than an integer, then
|
|
** zero is returned.
|
|
**
|
|
** The sqlite3_uri_key(F,N) returns a pointer to the name (not
|
|
** the value) of the N-th query parameter for filename F, or a NULL
|
|
** pointer if N is less than zero or greater than the number of query
|
|
** parameters minus 1. The N value is zero-based so N should be 0 to obtain
|
|
** the name of the first query parameter, 1 for the second parameter, and
|
|
** so forth.
|
|
**
|
|
** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and
|
|
** sqlite3_uri_boolean(F,P,B) returns B. If F is not a NULL pointer and
|
|
** is not a database file pathname pointer that the SQLite core passed
|
|
** into the xOpen VFS method, then the behavior of this routine is undefined
|
|
** and probably undesirable.
|
|
**
|
|
** Beginning with SQLite [version 3.31.0] ([dateof:3.31.0]) the input F
|
|
** parameter can also be the name of a rollback journal file or WAL file
|
|
** in addition to the main database file. Prior to version 3.31.0, these
|
|
** routines would only work if F was the name of the main database file.
|
|
** When the F parameter is the name of the rollback journal or WAL file,
|
|
** it has access to all the same query parameters as were found on the
|
|
** main database file.
|
|
**
|
|
** See the [URI filename] documentation for additional information.
|
|
*/
|
|
SQLITE_API const char *sqlite3_uri_parameter(sqlite3_filename z, const char *zParam);
|
|
SQLITE_API int sqlite3_uri_boolean(sqlite3_filename z, const char *zParam, int bDefault);
|
|
SQLITE_API sqlite3_int64 sqlite3_uri_int64(sqlite3_filename, const char*, sqlite3_int64);
|
|
SQLITE_API const char *sqlite3_uri_key(sqlite3_filename z, int N);
|
|
|
|
/*
|
|
** CAPI3REF: Translate filenames
|
|
**
|
|
** These routines are available to [VFS|custom VFS implementations] for
|
|
** translating filenames between the main database file, the journal file,
|
|
** and the WAL file.
|
|
**
|
|
** If F is the name of an sqlite database file, journal file, or WAL file
|
|
** passed by the SQLite core into the VFS, then sqlite3_filename_database(F)
|
|
** returns the name of the corresponding database file.
|
|
**
|
|
** If F is the name of an sqlite database file, journal file, or WAL file
|
|
** passed by the SQLite core into the VFS, or if F is a database filename
|
|
** obtained from [sqlite3_db_filename()], then sqlite3_filename_journal(F)
|
|
** returns the name of the corresponding rollback journal file.
|
|
**
|
|
** If F is the name of an sqlite database file, journal file, or WAL file
|
|
** that was passed by the SQLite core into the VFS, or if F is a database
|
|
** filename obtained from [sqlite3_db_filename()], then
|
|
** sqlite3_filename_wal(F) returns the name of the corresponding
|
|
** WAL file.
|
|
**
|
|
** In all of the above, if F is not the name of a database, journal or WAL
|
|
** filename passed into the VFS from the SQLite core and F is not the
|
|
** return value from [sqlite3_db_filename()], then the result is
|
|
** undefined and is likely a memory access violation.
|
|
*/
|
|
SQLITE_API const char *sqlite3_filename_database(sqlite3_filename);
|
|
SQLITE_API const char *sqlite3_filename_journal(sqlite3_filename);
|
|
SQLITE_API const char *sqlite3_filename_wal(sqlite3_filename);
|
|
|
|
/*
|
|
** CAPI3REF: Database File Corresponding To A Journal
|
|
**
|
|
** ^If X is the name of a rollback or WAL-mode journal file that is
|
|
** passed into the xOpen method of [sqlite3_vfs], then
|
|
** sqlite3_database_file_object(X) returns a pointer to the [sqlite3_file]
|
|
** object that represents the main database file.
|
|
**
|
|
** This routine is intended for use in custom [VFS] implementations
|
|
** only. It is not a general-purpose interface.
|
|
** The argument sqlite3_file_object(X) must be a filename pointer that
|
|
** has been passed into [sqlite3_vfs].xOpen method where the
|
|
** flags parameter to xOpen contains one of the bits
|
|
** [SQLITE_OPEN_MAIN_JOURNAL] or [SQLITE_OPEN_WAL]. Any other use
|
|
** of this routine results in undefined and probably undesirable
|
|
** behavior.
|
|
*/
|
|
SQLITE_API sqlite3_file *sqlite3_database_file_object(const char*);
|
|
|
|
/*
|
|
** CAPI3REF: Create and Destroy VFS Filenames
|
|
**
|
|
** These interfaces are provided for use by [VFS shim] implementations and
|
|
** are not useful outside of that context.
|
|
**
|
|
** The sqlite3_create_filename(D,J,W,N,P) allocates memory to hold a version of
|
|
** database filename D with corresponding journal file J and WAL file W and
|
|
** with N URI parameters key/values pairs in the array P. The result from
|
|
** sqlite3_create_filename(D,J,W,N,P) is a pointer to a database filename that
|
|
** is safe to pass to routines like:
|
|
** <ul>
|
|
** <li> [sqlite3_uri_parameter()],
|
|
** <li> [sqlite3_uri_boolean()],
|
|
** <li> [sqlite3_uri_int64()],
|
|
** <li> [sqlite3_uri_key()],
|
|
** <li> [sqlite3_filename_database()],
|
|
** <li> [sqlite3_filename_journal()], or
|
|
** <li> [sqlite3_filename_wal()].
|
|
** </ul>
|
|
** If a memory allocation error occurs, sqlite3_create_filename() might
|
|
** return a NULL pointer. The memory obtained from sqlite3_create_filename(X)
|
|
** must be released by a corresponding call to sqlite3_free_filename(Y).
|
|
**
|
|
** The P parameter in sqlite3_create_filename(D,J,W,N,P) should be an array
|
|
** of 2*N pointers to strings. Each pair of pointers in this array corresponds
|
|
** to a key and value for a query parameter. The P parameter may be a NULL
|
|
** pointer if N is zero. None of the 2*N pointers in the P array may be
|
|
** NULL pointers and key pointers should not be empty strings.
|
|
** None of the D, J, or W parameters to sqlite3_create_filename(D,J,W,N,P) may
|
|
** be NULL pointers, though they can be empty strings.
|
|
**
|
|
** The sqlite3_free_filename(Y) routine releases a memory allocation
|
|
** previously obtained from sqlite3_create_filename(). Invoking
|
|
** sqlite3_free_filename(Y) where Y is a NULL pointer is a harmless no-op.
|
|
**
|
|
** If the Y parameter to sqlite3_free_filename(Y) is anything other
|
|
** than a NULL pointer or a pointer previously acquired from
|
|
** sqlite3_create_filename(), then bad things such as heap
|
|
** corruption or segfaults may occur. The value Y should not be
|
|
** used again after sqlite3_free_filename(Y) has been called. This means
|
|
** that if the [sqlite3_vfs.xOpen()] method of a VFS has been called using Y,
|
|
** then the corresponding [sqlite3_module.xClose() method should also be
|
|
** invoked prior to calling sqlite3_free_filename(Y).
|
|
*/
|
|
SQLITE_API sqlite3_filename sqlite3_create_filename(
|
|
const char *zDatabase,
|
|
const char *zJournal,
|
|
const char *zWal,
|
|
int nParam,
|
|
const char **azParam
|
|
);
|
|
SQLITE_API void sqlite3_free_filename(sqlite3_filename);
|
|
|
|
/*
|
|
** CAPI3REF: Error Codes And Messages
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^If the most recent sqlite3_* API call associated with
|
|
** [database connection] D failed, then the sqlite3_errcode(D) interface
|
|
** returns the numeric [result code] or [extended result code] for that
|
|
** API call.
|
|
** ^The sqlite3_extended_errcode()
|
|
** interface is the same except that it always returns the
|
|
** [extended result code] even when extended result codes are
|
|
** disabled.
|
|
**
|
|
** The values returned by sqlite3_errcode() and/or
|
|
** sqlite3_extended_errcode() might change with each API call.
|
|
** Except, there are some interfaces that are guaranteed to never
|
|
** change the value of the error code. The error-code preserving
|
|
** interfaces include the following:
|
|
**
|
|
** <ul>
|
|
** <li> sqlite3_errcode()
|
|
** <li> sqlite3_extended_errcode()
|
|
** <li> sqlite3_errmsg()
|
|
** <li> sqlite3_errmsg16()
|
|
** <li> sqlite3_error_offset()
|
|
** </ul>
|
|
**
|
|
** ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language
|
|
** text that describes the error, as either UTF-8 or UTF-16 respectively,
|
|
** or NULL if no error message is available.
|
|
** (See how SQLite handles [invalid UTF] for exceptions to this rule.)
|
|
** ^(Memory to hold the error message string is managed internally.
|
|
** The application does not need to worry about freeing the result.
|
|
** However, the error string might be overwritten or deallocated by
|
|
** subsequent calls to other SQLite interface functions.)^
|
|
**
|
|
** ^The sqlite3_errstr(E) interface returns the English-language text
|
|
** that describes the [result code] E, as UTF-8, or NULL if E is not an
|
|
** result code for which a text error message is available.
|
|
** ^(Memory to hold the error message string is managed internally
|
|
** and must not be freed by the application)^.
|
|
**
|
|
** ^If the most recent error references a specific token in the input
|
|
** SQL, the sqlite3_error_offset() interface returns the byte offset
|
|
** of the start of that token. ^The byte offset returned by
|
|
** sqlite3_error_offset() assumes that the input SQL is UTF8.
|
|
** ^If the most recent error does not reference a specific token in the input
|
|
** SQL, then the sqlite3_error_offset() function returns -1.
|
|
**
|
|
** When the serialized [threading mode] is in use, it might be the
|
|
** case that a second error occurs on a separate thread in between
|
|
** the time of the first error and the call to these interfaces.
|
|
** When that happens, the second error will be reported since these
|
|
** interfaces always report the most recent result. To avoid
|
|
** this, each thread can obtain exclusive use of the [database connection] D
|
|
** by invoking [sqlite3_mutex_enter]([sqlite3_db_mutex](D)) before beginning
|
|
** to use D and invoking [sqlite3_mutex_leave]([sqlite3_db_mutex](D)) after
|
|
** all calls to the interfaces listed here are completed.
|
|
**
|
|
** If an interface fails with SQLITE_MISUSE, that means the interface
|
|
** was invoked incorrectly by the application. In that case, the
|
|
** error code and message may or may not be set.
|
|
*/
|
|
SQLITE_API int sqlite3_errcode(sqlite3 *db);
|
|
SQLITE_API int sqlite3_extended_errcode(sqlite3 *db);
|
|
SQLITE_API const char *sqlite3_errmsg(sqlite3*);
|
|
SQLITE_API const void *sqlite3_errmsg16(sqlite3*);
|
|
SQLITE_API const char *sqlite3_errstr(int);
|
|
SQLITE_API int sqlite3_error_offset(sqlite3 *db);
|
|
|
|
/*
|
|
** CAPI3REF: Prepared Statement Object
|
|
** KEYWORDS: {prepared statement} {prepared statements}
|
|
**
|
|
** An instance of this object represents a single SQL statement that
|
|
** has been compiled into binary form and is ready to be evaluated.
|
|
**
|
|
** Think of each SQL statement as a separate computer program. The
|
|
** original SQL text is source code. A prepared statement object
|
|
** is the compiled object code. All SQL must be converted into a
|
|
** prepared statement before it can be run.
|
|
**
|
|
** The life-cycle of a prepared statement object usually goes like this:
|
|
**
|
|
** <ol>
|
|
** <li> Create the prepared statement object using [sqlite3_prepare_v2()].
|
|
** <li> Bind values to [parameters] using the sqlite3_bind_*()
|
|
** interfaces.
|
|
** <li> Run the SQL by calling [sqlite3_step()] one or more times.
|
|
** <li> Reset the prepared statement using [sqlite3_reset()] then go back
|
|
** to step 2. Do this zero or more times.
|
|
** <li> Destroy the object using [sqlite3_finalize()].
|
|
** </ol>
|
|
*/
|
|
typedef struct sqlite3_stmt sqlite3_stmt;
|
|
|
|
/*
|
|
** CAPI3REF: Run-time Limits
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^(This interface allows the size of various constructs to be limited
|
|
** on a connection by connection basis. The first parameter is the
|
|
** [database connection] whose limit is to be set or queried. The
|
|
** second parameter is one of the [limit categories] that define a
|
|
** class of constructs to be size limited. The third parameter is the
|
|
** new limit for that construct.)^
|
|
**
|
|
** ^If the new limit is a negative number, the limit is unchanged.
|
|
** ^(For each limit category SQLITE_LIMIT_<i>NAME</i> there is a
|
|
** [limits | hard upper bound]
|
|
** set at compile-time by a C preprocessor macro called
|
|
** [limits | SQLITE_MAX_<i>NAME</i>].
|
|
** (The "_LIMIT_" in the name is changed to "_MAX_".))^
|
|
** ^Attempts to increase a limit above its hard upper bound are
|
|
** silently truncated to the hard upper bound.
|
|
**
|
|
** ^Regardless of whether or not the limit was changed, the
|
|
** [sqlite3_limit()] interface returns the prior value of the limit.
|
|
** ^Hence, to find the current value of a limit without changing it,
|
|
** simply invoke this interface with the third parameter set to -1.
|
|
**
|
|
** Run-time limits are intended for use in applications that manage
|
|
** both their own internal database and also databases that are controlled
|
|
** by untrusted external sources. An example application might be a
|
|
** web browser that has its own databases for storing history and
|
|
** separate databases controlled by JavaScript applications downloaded
|
|
** off the Internet. The internal databases can be given the
|
|
** large, default limits. Databases managed by external sources can
|
|
** be given much smaller limits designed to prevent a denial of service
|
|
** attack. Developers might also want to use the [sqlite3_set_authorizer()]
|
|
** interface to further control untrusted SQL. The size of the database
|
|
** created by an untrusted script can be contained using the
|
|
** [max_page_count] [PRAGMA].
|
|
**
|
|
** New run-time limit categories may be added in future releases.
|
|
*/
|
|
SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
|
|
|
|
/*
|
|
** CAPI3REF: Run-Time Limit Categories
|
|
** KEYWORDS: {limit category} {*limit categories}
|
|
**
|
|
** These constants define various performance limits
|
|
** that can be lowered at run-time using [sqlite3_limit()].
|
|
** The synopsis of the meanings of the various limits is shown below.
|
|
** Additional information is available at [limits | Limits in SQLite].
|
|
**
|
|
** <dl>
|
|
** [[SQLITE_LIMIT_LENGTH]] ^(<dt>SQLITE_LIMIT_LENGTH</dt>
|
|
** <dd>The maximum size of any string or BLOB or table row, in bytes.<dd>)^
|
|
**
|
|
** [[SQLITE_LIMIT_SQL_LENGTH]] ^(<dt>SQLITE_LIMIT_SQL_LENGTH</dt>
|
|
** <dd>The maximum length of an SQL statement, in bytes.</dd>)^
|
|
**
|
|
** [[SQLITE_LIMIT_COLUMN]] ^(<dt>SQLITE_LIMIT_COLUMN</dt>
|
|
** <dd>The maximum number of columns in a table definition or in the
|
|
** result set of a [SELECT] or the maximum number of columns in an index
|
|
** or in an ORDER BY or GROUP BY clause.</dd>)^
|
|
**
|
|
** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(<dt>SQLITE_LIMIT_EXPR_DEPTH</dt>
|
|
** <dd>The maximum depth of the parse tree on any expression.</dd>)^
|
|
**
|
|
** [[SQLITE_LIMIT_COMPOUND_SELECT]] ^(<dt>SQLITE_LIMIT_COMPOUND_SELECT</dt>
|
|
** <dd>The maximum number of terms in a compound SELECT statement.</dd>)^
|
|
**
|
|
** [[SQLITE_LIMIT_VDBE_OP]] ^(<dt>SQLITE_LIMIT_VDBE_OP</dt>
|
|
** <dd>The maximum number of instructions in a virtual machine program
|
|
** used to implement an SQL statement. If [sqlite3_prepare_v2()] or
|
|
** the equivalent tries to allocate space for more than this many opcodes
|
|
** in a single prepared statement, an SQLITE_NOMEM error is returned.</dd>)^
|
|
**
|
|
** [[SQLITE_LIMIT_FUNCTION_ARG]] ^(<dt>SQLITE_LIMIT_FUNCTION_ARG</dt>
|
|
** <dd>The maximum number of arguments on a function.</dd>)^
|
|
**
|
|
** [[SQLITE_LIMIT_ATTACHED]] ^(<dt>SQLITE_LIMIT_ATTACHED</dt>
|
|
** <dd>The maximum number of [ATTACH | attached databases].)^</dd>
|
|
**
|
|
** [[SQLITE_LIMIT_LIKE_PATTERN_LENGTH]]
|
|
** ^(<dt>SQLITE_LIMIT_LIKE_PATTERN_LENGTH</dt>
|
|
** <dd>The maximum length of the pattern argument to the [LIKE] or
|
|
** [GLOB] operators.</dd>)^
|
|
**
|
|
** [[SQLITE_LIMIT_VARIABLE_NUMBER]]
|
|
** ^(<dt>SQLITE_LIMIT_VARIABLE_NUMBER</dt>
|
|
** <dd>The maximum index number of any [parameter] in an SQL statement.)^
|
|
**
|
|
** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt>
|
|
** <dd>The maximum depth of recursion for triggers.</dd>)^
|
|
**
|
|
** [[SQLITE_LIMIT_WORKER_THREADS]] ^(<dt>SQLITE_LIMIT_WORKER_THREADS</dt>
|
|
** <dd>The maximum number of auxiliary worker threads that a single
|
|
** [prepared statement] may start.</dd>)^
|
|
** </dl>
|
|
*/
|
|
#define SQLITE_LIMIT_LENGTH 0
|
|
#define SQLITE_LIMIT_SQL_LENGTH 1
|
|
#define SQLITE_LIMIT_COLUMN 2
|
|
#define SQLITE_LIMIT_EXPR_DEPTH 3
|
|
#define SQLITE_LIMIT_COMPOUND_SELECT 4
|
|
#define SQLITE_LIMIT_VDBE_OP 5
|
|
#define SQLITE_LIMIT_FUNCTION_ARG 6
|
|
#define SQLITE_LIMIT_ATTACHED 7
|
|
#define SQLITE_LIMIT_LIKE_PATTERN_LENGTH 8
|
|
#define SQLITE_LIMIT_VARIABLE_NUMBER 9
|
|
#define SQLITE_LIMIT_TRIGGER_DEPTH 10
|
|
#define SQLITE_LIMIT_WORKER_THREADS 11
|
|
|
|
/*
|
|
** CAPI3REF: Prepare Flags
|
|
**
|
|
** These constants define various flags that can be passed into
|
|
** "prepFlags" parameter of the [sqlite3_prepare_v3()] and
|
|
** [sqlite3_prepare16_v3()] interfaces.
|
|
**
|
|
** New flags may be added in future releases of SQLite.
|
|
**
|
|
** <dl>
|
|
** [[SQLITE_PREPARE_PERSISTENT]] ^(<dt>SQLITE_PREPARE_PERSISTENT</dt>
|
|
** <dd>The SQLITE_PREPARE_PERSISTENT flag is a hint to the query planner
|
|
** that the prepared statement will be retained for a long time and
|
|
** probably reused many times.)^ ^Without this flag, [sqlite3_prepare_v3()]
|
|
** and [sqlite3_prepare16_v3()] assume that the prepared statement will
|
|
** be used just once or at most a few times and then destroyed using
|
|
** [sqlite3_finalize()] relatively soon. The current implementation acts
|
|
** on this hint by avoiding the use of [lookaside memory] so as not to
|
|
** deplete the limited store of lookaside memory. Future versions of
|
|
** SQLite may act on this hint differently.
|
|
**
|
|
** [[SQLITE_PREPARE_NORMALIZE]] <dt>SQLITE_PREPARE_NORMALIZE</dt>
|
|
** <dd>The SQLITE_PREPARE_NORMALIZE flag is a no-op. This flag used
|
|
** to be required for any prepared statement that wanted to use the
|
|
** [sqlite3_normalized_sql()] interface. However, the
|
|
** [sqlite3_normalized_sql()] interface is now available to all
|
|
** prepared statements, regardless of whether or not they use this
|
|
** flag.
|
|
**
|
|
** [[SQLITE_PREPARE_NO_VTAB]] <dt>SQLITE_PREPARE_NO_VTAB</dt>
|
|
** <dd>The SQLITE_PREPARE_NO_VTAB flag causes the SQL compiler
|
|
** to return an error (error code SQLITE_ERROR) if the statement uses
|
|
** any virtual tables.
|
|
** </dl>
|
|
*/
|
|
#define SQLITE_PREPARE_PERSISTENT 0x01
|
|
#define SQLITE_PREPARE_NORMALIZE 0x02
|
|
#define SQLITE_PREPARE_NO_VTAB 0x04
|
|
|
|
/*
|
|
** CAPI3REF: Compiling An SQL Statement
|
|
** KEYWORDS: {SQL statement compiler}
|
|
** METHOD: sqlite3
|
|
** CONSTRUCTOR: sqlite3_stmt
|
|
**
|
|
** To execute an SQL statement, it must first be compiled into a byte-code
|
|
** program using one of these routines. Or, in other words, these routines
|
|
** are constructors for the [prepared statement] object.
|
|
**
|
|
** The preferred routine to use is [sqlite3_prepare_v2()]. The
|
|
** [sqlite3_prepare()] interface is legacy and should be avoided.
|
|
** [sqlite3_prepare_v3()] has an extra "prepFlags" option that is used
|
|
** for special purposes.
|
|
**
|
|
** The use of the UTF-8 interfaces is preferred, as SQLite currently
|
|
** does all parsing using UTF-8. The UTF-16 interfaces are provided
|
|
** as a convenience. The UTF-16 interfaces work by converting the
|
|
** input text into UTF-8, then invoking the corresponding UTF-8 interface.
|
|
**
|
|
** The first argument, "db", is a [database connection] obtained from a
|
|
** prior successful call to [sqlite3_open()], [sqlite3_open_v2()] or
|
|
** [sqlite3_open16()]. The database connection must not have been closed.
|
|
**
|
|
** The second argument, "zSql", is the statement to be compiled, encoded
|
|
** as either UTF-8 or UTF-16. The sqlite3_prepare(), sqlite3_prepare_v2(),
|
|
** and sqlite3_prepare_v3()
|
|
** interfaces use UTF-8, and sqlite3_prepare16(), sqlite3_prepare16_v2(),
|
|
** and sqlite3_prepare16_v3() use UTF-16.
|
|
**
|
|
** ^If the nByte argument is negative, then zSql is read up to the
|
|
** first zero terminator. ^If nByte is positive, then it is the
|
|
** number of bytes read from zSql. ^If nByte is zero, then no prepared
|
|
** statement is generated.
|
|
** If the caller knows that the supplied string is nul-terminated, then
|
|
** there is a small performance advantage to passing an nByte parameter that
|
|
** is the number of bytes in the input string <i>including</i>
|
|
** the nul-terminator.
|
|
**
|
|
** ^If pzTail is not NULL then *pzTail is made to point to the first byte
|
|
** past the end of the first SQL statement in zSql. These routines only
|
|
** compile the first statement in zSql, so *pzTail is left pointing to
|
|
** what remains uncompiled.
|
|
**
|
|
** ^*ppStmt is left pointing to a compiled [prepared statement] that can be
|
|
** executed using [sqlite3_step()]. ^If there is an error, *ppStmt is set
|
|
** to NULL. ^If the input text contains no SQL (if the input is an 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.
|
|
** ppStmt may not be NULL.
|
|
**
|
|
** ^On success, the sqlite3_prepare() family of routines return [SQLITE_OK];
|
|
** otherwise an [error code] is returned.
|
|
**
|
|
** The sqlite3_prepare_v2(), sqlite3_prepare_v3(), sqlite3_prepare16_v2(),
|
|
** and sqlite3_prepare16_v3() interfaces are recommended for all new programs.
|
|
** The older interfaces (sqlite3_prepare() and sqlite3_prepare16())
|
|
** are retained for backwards compatibility, but their use is discouraged.
|
|
** ^In the "vX" 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 differently in three ways:
|
|
**
|
|
** <ol>
|
|
** <li>
|
|
** ^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. As many as [SQLITE_MAX_SCHEMA_RETRY]
|
|
** retries will occur before sqlite3_step() gives up and returns an error.
|
|
** </li>
|
|
**
|
|
** <li>
|
|
** ^When an error occurs, [sqlite3_step()] will return one of the detailed
|
|
** [error codes] or [extended error codes]. ^The legacy behavior was that
|
|
** [sqlite3_step()] would only return a generic [SQLITE_ERROR] result code
|
|
** and the application 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.
|
|
** </li>
|
|
**
|
|
** <li>
|
|
** ^If the specific value bound to a [parameter | host parameter] in the
|
|
** WHERE clause might influence the choice of query plan for a statement,
|
|
** then the statement will be automatically recompiled, as if there had been
|
|
** a schema change, on the first [sqlite3_step()] call following any change
|
|
** to the [sqlite3_bind_text | bindings] of that [parameter].
|
|
** ^The specific value of a WHERE-clause [parameter] might influence the
|
|
** choice of query plan if the parameter is the left-hand side of a [LIKE]
|
|
** or [GLOB] operator or if the parameter is compared to an indexed column
|
|
** and the [SQLITE_ENABLE_STAT4] compile-time option is enabled.
|
|
** </li>
|
|
** </ol>
|
|
**
|
|
** <p>^sqlite3_prepare_v3() differs from sqlite3_prepare_v2() only in having
|
|
** the extra prepFlags parameter, which is a bit array consisting of zero or
|
|
** more of the [SQLITE_PREPARE_PERSISTENT|SQLITE_PREPARE_*] flags. ^The
|
|
** sqlite3_prepare_v2() interface works exactly the same as
|
|
** sqlite3_prepare_v3() with a zero prepFlags parameter.
|
|
*/
|
|
SQLITE_API 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 */
|
|
);
|
|
SQLITE_API 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 */
|
|
);
|
|
SQLITE_API int sqlite3_prepare_v3(
|
|
sqlite3 *db, /* Database handle */
|
|
const char *zSql, /* SQL statement, UTF-8 encoded */
|
|
int nByte, /* Maximum length of zSql in bytes. */
|
|
unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_ flags */
|
|
sqlite3_stmt **ppStmt, /* OUT: Statement handle */
|
|
const char **pzTail /* OUT: Pointer to unused portion of zSql */
|
|
);
|
|
SQLITE_API 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 */
|
|
);
|
|
SQLITE_API 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 */
|
|
);
|
|
SQLITE_API int sqlite3_prepare16_v3(
|
|
sqlite3 *db, /* Database handle */
|
|
const void *zSql, /* SQL statement, UTF-16 encoded */
|
|
int nByte, /* Maximum length of zSql in bytes. */
|
|
unsigned int prepFlags, /* Zero or more SQLITE_PREPARE_ flags */
|
|
sqlite3_stmt **ppStmt, /* OUT: Statement handle */
|
|
const void **pzTail /* OUT: Pointer to unused portion of zSql */
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Retrieving Statement SQL
|
|
** METHOD: sqlite3_stmt
|
|
**
|
|
** ^The sqlite3_sql(P) interface returns a pointer to a copy of the UTF-8
|
|
** SQL text used to create [prepared statement] P if P was
|
|
** created by [sqlite3_prepare_v2()], [sqlite3_prepare_v3()],
|
|
** [sqlite3_prepare16_v2()], or [sqlite3_prepare16_v3()].
|
|
** ^The sqlite3_expanded_sql(P) interface returns a pointer to a UTF-8
|
|
** string containing the SQL text of prepared statement P with
|
|
** [bound parameters] expanded.
|
|
** ^The sqlite3_normalized_sql(P) interface returns a pointer to a UTF-8
|
|
** string containing the normalized SQL text of prepared statement P. The
|
|
** semantics used to normalize a SQL statement are unspecified and subject
|
|
** to change. At a minimum, literal values will be replaced with suitable
|
|
** placeholders.
|
|
**
|
|
** ^(For example, if a prepared statement is created using the SQL
|
|
** text "SELECT $abc,:xyz" and if parameter $abc is bound to integer 2345
|
|
** and parameter :xyz is unbound, then sqlite3_sql() will return
|
|
** the original string, "SELECT $abc,:xyz" but sqlite3_expanded_sql()
|
|
** will return "SELECT 2345,NULL".)^
|
|
**
|
|
** ^The sqlite3_expanded_sql() interface returns NULL if insufficient memory
|
|
** is available to hold the result, or if the result would exceed the
|
|
** the maximum string length determined by the [SQLITE_LIMIT_LENGTH].
|
|
**
|
|
** ^The [SQLITE_TRACE_SIZE_LIMIT] compile-time option limits the size of
|
|
** bound parameter expansions. ^The [SQLITE_OMIT_TRACE] compile-time
|
|
** option causes sqlite3_expanded_sql() to always return NULL.
|
|
**
|
|
** ^The strings returned by sqlite3_sql(P) and sqlite3_normalized_sql(P)
|
|
** are managed by SQLite and are automatically freed when the prepared
|
|
** statement is finalized.
|
|
** ^The string returned by sqlite3_expanded_sql(P), on the other hand,
|
|
** is obtained from [sqlite3_malloc()] and must be freed by the application
|
|
** by passing it to [sqlite3_free()].
|
|
**
|
|
** ^The sqlite3_normalized_sql() interface is only available if
|
|
** the [SQLITE_ENABLE_NORMALIZE] compile-time option is defined.
|
|
*/
|
|
SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt);
|
|
SQLITE_API char *sqlite3_expanded_sql(sqlite3_stmt *pStmt);
|
|
#ifdef SQLITE_ENABLE_NORMALIZE
|
|
SQLITE_API const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt);
|
|
#endif
|
|
|
|
/*
|
|
** CAPI3REF: Determine If An SQL Statement Writes The Database
|
|
** METHOD: sqlite3_stmt
|
|
**
|
|
** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if
|
|
** and only if the [prepared statement] X makes no direct changes to
|
|
** the content of the database file.
|
|
**
|
|
** Note that [application-defined SQL functions] or
|
|
** [virtual tables] might change the database indirectly as a side effect.
|
|
** ^(For example, if an application defines a function "eval()" that
|
|
** calls [sqlite3_exec()], then the following SQL statement would
|
|
** change the database file through side-effects:
|
|
**
|
|
** <blockquote><pre>
|
|
** SELECT eval('DELETE FROM t1') FROM t2;
|
|
** </pre></blockquote>
|
|
**
|
|
** But because the [SELECT] statement does not change the database file
|
|
** directly, sqlite3_stmt_readonly() would still return true.)^
|
|
**
|
|
** ^Transaction control statements such as [BEGIN], [COMMIT], [ROLLBACK],
|
|
** [SAVEPOINT], and [RELEASE] cause sqlite3_stmt_readonly() to return true,
|
|
** since the statements themselves do not actually modify the database but
|
|
** rather they control the timing of when other statements modify the
|
|
** database. ^The [ATTACH] and [DETACH] statements also cause
|
|
** sqlite3_stmt_readonly() to return true since, while those statements
|
|
** change the configuration of a database connection, they do not make
|
|
** changes to the content of the database files on disk.
|
|
** ^The sqlite3_stmt_readonly() interface returns true for [BEGIN] since
|
|
** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and
|
|
** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so
|
|
** sqlite3_stmt_readonly() returns false for those commands.
|
|
**
|
|
** ^This routine returns false if there is any possibility that the
|
|
** statement might change the database file. ^A false return does
|
|
** not guarantee that the statement will change the database file.
|
|
** ^For example, an UPDATE statement might have a WHERE clause that
|
|
** makes it a no-op, but the sqlite3_stmt_readonly() result would still
|
|
** be false. ^Similarly, a CREATE TABLE IF NOT EXISTS statement is a
|
|
** read-only no-op if the table already exists, but
|
|
** sqlite3_stmt_readonly() still returns false for such a statement.
|
|
**
|
|
** ^If prepared statement X is an [EXPLAIN] or [EXPLAIN QUERY PLAN]
|
|
** statement, then sqlite3_stmt_readonly(X) returns the same value as
|
|
** if the EXPLAIN or EXPLAIN QUERY PLAN prefix were omitted.
|
|
*/
|
|
SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
|
|
|
|
/*
|
|
** CAPI3REF: Query The EXPLAIN Setting For A Prepared Statement
|
|
** METHOD: sqlite3_stmt
|
|
**
|
|
** ^The sqlite3_stmt_isexplain(S) interface returns 1 if the
|
|
** prepared statement S is an EXPLAIN statement, or 2 if the
|
|
** statement S is an EXPLAIN QUERY PLAN.
|
|
** ^The sqlite3_stmt_isexplain(S) interface returns 0 if S is
|
|
** an ordinary statement or a NULL pointer.
|
|
*/
|
|
SQLITE_API int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt);
|
|
|
|
/*
|
|
** CAPI3REF: Change The EXPLAIN Setting For A Prepared Statement
|
|
** METHOD: sqlite3_stmt
|
|
**
|
|
** The sqlite3_stmt_explain(S,E) interface changes the EXPLAIN
|
|
** setting for [prepared statement] S. If E is zero, then S becomes
|
|
** a normal prepared statement. If E is 1, then S behaves as if
|
|
** its SQL text began with "[EXPLAIN]". If E is 2, then S behaves as if
|
|
** its SQL text began with "[EXPLAIN QUERY PLAN]".
|
|
**
|
|
** Calling sqlite3_stmt_explain(S,E) might cause S to be reprepared.
|
|
** SQLite tries to avoid a reprepare, but a reprepare might be necessary
|
|
** on the first transition into EXPLAIN or EXPLAIN QUERY PLAN mode.
|
|
**
|
|
** Because of the potential need to reprepare, a call to
|
|
** sqlite3_stmt_explain(S,E) will fail with SQLITE_ERROR if S cannot be
|
|
** reprepared because it was created using [sqlite3_prepare()] instead of
|
|
** the newer [sqlite3_prepare_v2()] or [sqlite3_prepare_v3()] interfaces and
|
|
** hence has no saved SQL text with which to reprepare.
|
|
**
|
|
** Changing the explain setting for a prepared statement does not change
|
|
** the original SQL text for the statement. Hence, if the SQL text originally
|
|
** began with EXPLAIN or EXPLAIN QUERY PLAN, but sqlite3_stmt_explain(S,0)
|
|
** is called to convert the statement into an ordinary statement, the EXPLAIN
|
|
** or EXPLAIN QUERY PLAN keywords will still appear in the sqlite3_sql(S)
|
|
** output, even though the statement now acts like a normal SQL statement.
|
|
**
|
|
** This routine returns SQLITE_OK if the explain mode is successfully
|
|
** changed, or an error code if the explain mode could not be changed.
|
|
** The explain mode cannot be changed while a statement is active.
|
|
** Hence, it is good practice to call [sqlite3_reset(S)]
|
|
** immediately prior to calling sqlite3_stmt_explain(S,E).
|
|
*/
|
|
SQLITE_API int sqlite3_stmt_explain(sqlite3_stmt *pStmt, int eMode);
|
|
|
|
/*
|
|
** CAPI3REF: Determine If A Prepared Statement Has Been Reset
|
|
** METHOD: sqlite3_stmt
|
|
**
|
|
** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the
|
|
** [prepared statement] S has been stepped at least once using
|
|
** [sqlite3_step(S)] but has neither run to completion (returned
|
|
** [SQLITE_DONE] from [sqlite3_step(S)]) nor
|
|
** been reset using [sqlite3_reset(S)]. ^The sqlite3_stmt_busy(S)
|
|
** interface returns false if S is a NULL pointer. If S is not a
|
|
** NULL pointer and is not a pointer to a valid [prepared statement]
|
|
** object, then the behavior is undefined and probably undesirable.
|
|
**
|
|
** This interface can be used in combination [sqlite3_next_stmt()]
|
|
** to locate all prepared statements associated with a database
|
|
** connection that are in need of being reset. This can be used,
|
|
** for example, in diagnostic routines to search for prepared
|
|
** statements that are holding a transaction open.
|
|
*/
|
|
SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*);
|
|
|
|
/*
|
|
** CAPI3REF: Dynamically Typed Value Object
|
|
** KEYWORDS: {protected sqlite3_value} {unprotected sqlite3_value}
|
|
**
|
|
** SQLite uses the sqlite3_value object to represent all values
|
|
** that can be stored in a database table. SQLite uses dynamic typing
|
|
** for the values it stores. ^Values stored in sqlite3_value objects
|
|
** can be integers, floating point values, strings, BLOBs, or NULL.
|
|
**
|
|
** An sqlite3_value object may be either "protected" or "unprotected".
|
|
** Some interfaces require a protected sqlite3_value. Other interfaces
|
|
** will accept either a protected or an unprotected sqlite3_value.
|
|
** Every interface that accepts sqlite3_value arguments specifies
|
|
** whether or not it requires a protected sqlite3_value. The
|
|
** [sqlite3_value_dup()] interface can be used to construct a new
|
|
** protected sqlite3_value from an unprotected sqlite3_value.
|
|
**
|
|
** The terms "protected" and "unprotected" refer to whether or not
|
|
** a mutex is held. An internal mutex is held for a protected
|
|
** sqlite3_value object but no mutex is held for an unprotected
|
|
** sqlite3_value object. If SQLite is compiled to be single-threaded
|
|
** (with [SQLITE_THREADSAFE=0] and with [sqlite3_threadsafe()] returning 0)
|
|
** or if SQLite is run in one of reduced mutex modes
|
|
** [SQLITE_CONFIG_SINGLETHREAD] or [SQLITE_CONFIG_MULTITHREAD]
|
|
** then there is no distinction between protected and unprotected
|
|
** sqlite3_value objects and they can be used interchangeably. However,
|
|
** for maximum code portability it is recommended that applications
|
|
** still make the distinction between protected and unprotected
|
|
** sqlite3_value objects even when not strictly required.
|
|
**
|
|
** ^The sqlite3_value objects that are passed as parameters into the
|
|
** implementation of [application-defined SQL functions] are protected.
|
|
** ^The sqlite3_value objects returned by [sqlite3_vtab_rhs_value()]
|
|
** are protected.
|
|
** ^The sqlite3_value object returned by
|
|
** [sqlite3_column_value()] is unprotected.
|
|
** Unprotected sqlite3_value objects may only be used as arguments
|
|
** to [sqlite3_result_value()], [sqlite3_bind_value()], and
|
|
** [sqlite3_value_dup()].
|
|
** The [sqlite3_value_blob | sqlite3_value_type()] family of
|
|
** interfaces require protected sqlite3_value objects.
|
|
*/
|
|
typedef struct sqlite3_value 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 an sqlite3_context object
|
|
** is always first parameter to [application-defined SQL functions].
|
|
** The application-defined SQL function implementation will pass this
|
|
** pointer through into calls to [sqlite3_result_int | sqlite3_result()],
|
|
** [sqlite3_aggregate_context()], [sqlite3_user_data()],
|
|
** [sqlite3_context_db_handle()], [sqlite3_get_auxdata()],
|
|
** and/or [sqlite3_set_auxdata()].
|
|
*/
|
|
typedef struct sqlite3_context sqlite3_context;
|
|
|
|
/*
|
|
** CAPI3REF: Binding Values To Prepared Statements
|
|
** KEYWORDS: {host parameter} {host parameters} {host parameter name}
|
|
** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding}
|
|
** METHOD: sqlite3_stmt
|
|
**
|
|
** ^(In the SQL statement text input to [sqlite3_prepare_v2()] and its variants,
|
|
** literals may be replaced by a [parameter] that matches one of following
|
|
** templates:
|
|
**
|
|
** <ul>
|
|
** <li> ?
|
|
** <li> ?NNN
|
|
** <li> :VVV
|
|
** <li> @VVV
|
|
** <li> $VVV
|
|
** </ul>
|
|
**
|
|
** In the templates above, NNN represents an integer literal,
|
|
** and VVV represents an alphanumeric identifier.)^ ^The values of these
|
|
** parameters (also called "host parameter names" or "SQL parameters")
|
|
** can be set using the sqlite3_bind_*() routines defined here.
|
|
**
|
|
** ^The first argument to the sqlite3_bind_*() routines is always
|
|
** a pointer to the [sqlite3_stmt] object returned from
|
|
** [sqlite3_prepare_v2()] or its variants.
|
|
**
|
|
** ^The second argument is the index of the SQL parameter to be set.
|
|
** ^The leftmost SQL parameter has an index of 1. ^When the same named
|
|
** SQL 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_index()] API if desired. ^The index
|
|
** for "?NNN" parameters is the value of NNN.
|
|
** ^The NNN value must be between 1 and the [sqlite3_limit()]
|
|
** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 32766).
|
|
**
|
|
** ^The third argument is the value to bind to the parameter.
|
|
** ^If the third parameter to sqlite3_bind_text() or sqlite3_bind_text16()
|
|
** or sqlite3_bind_blob() is a NULL pointer then the fourth parameter
|
|
** is ignored and the end result is the same as sqlite3_bind_null().
|
|
** ^If the third parameter to sqlite3_bind_text() is not NULL, then
|
|
** it should be a pointer to well-formed UTF8 text.
|
|
** ^If the third parameter to sqlite3_bind_text16() is not NULL, then
|
|
** it should be a pointer to well-formed UTF16 text.
|
|
** ^If the third parameter to sqlite3_bind_text64() is not NULL, then
|
|
** it should be a pointer to a well-formed unicode string that is
|
|
** either UTF8 if the sixth parameter is SQLITE_UTF8, or UTF16
|
|
** otherwise.
|
|
**
|
|
** [[byte-order determination rules]] ^The byte-order of
|
|
** UTF16 input text is determined by the byte-order mark (BOM, U+FEFF)
|
|
** found in first character, which is removed, or in the absence of a BOM
|
|
** the byte order is the native byte order of the host
|
|
** machine for sqlite3_bind_text16() or the byte order specified in
|
|
** the 6th parameter for sqlite3_bind_text64().)^
|
|
** ^If UTF16 input text contains invalid unicode
|
|
** characters, then SQLite might change those invalid characters
|
|
** into the unicode replacement character: U+FFFD.
|
|
**
|
|
** ^(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 <u>bytes</u> in the value, not the number of characters.)^
|
|
** ^If the fourth parameter to sqlite3_bind_text() or sqlite3_bind_text16()
|
|
** is negative, then the length of the string is
|
|
** the number of bytes up to the first zero terminator.
|
|
** If the fourth parameter to sqlite3_bind_blob() is negative, then
|
|
** the behavior is undefined.
|
|
** If a non-negative fourth parameter is provided to sqlite3_bind_text()
|
|
** or sqlite3_bind_text16() or sqlite3_bind_text64() then
|
|
** that parameter must be the byte offset
|
|
** where the NUL terminator would occur assuming the string were NUL
|
|
** terminated. If any NUL characters occurs at byte offsets less than
|
|
** the value of the fourth parameter then the resulting string value will
|
|
** contain embedded NULs. The result of expressions involving strings
|
|
** with embedded NULs is undefined.
|
|
**
|
|
** ^The fifth argument to the BLOB and string binding interfaces controls
|
|
** or indicates the lifetime of the object referenced by the third parameter.
|
|
** These three options exist:
|
|
** ^ (1) A destructor to dispose of the BLOB or string after SQLite has finished
|
|
** with it may be passed. ^It is called to dispose of the BLOB or string even
|
|
** if the call to the bind API fails, except the destructor is not called if
|
|
** the third parameter is a NULL pointer or the fourth parameter is negative.
|
|
** ^ (2) The special constant, [SQLITE_STATIC], may be passed to indicate that
|
|
** the application remains responsible for disposing of the object. ^In this
|
|
** case, the object and the provided pointer to it must remain valid until
|
|
** either the prepared statement is finalized or the same SQL parameter is
|
|
** bound to something else, whichever occurs sooner.
|
|
** ^ (3) The constant, [SQLITE_TRANSIENT], may be passed to indicate that the
|
|
** object is to be copied prior to the return from sqlite3_bind_*(). ^The
|
|
** object and pointer to it must remain valid until then. ^SQLite will then
|
|
** manage the lifetime of its private copy.
|
|
**
|
|
** ^The sixth argument to sqlite3_bind_text64() must be one of
|
|
** [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE]
|
|
** to specify the encoding of the text in the third parameter. If
|
|
** the sixth argument to sqlite3_bind_text64() is not one of the
|
|
** allowed values shown above, or if the text encoding is different
|
|
** from the encoding specified by the sixth parameter, then the behavior
|
|
** is undefined.
|
|
**
|
|
** ^The sqlite3_bind_zeroblob() routine binds a BLOB of length N that
|
|
** is filled with zeroes. ^A zeroblob uses a fixed amount of memory
|
|
** (just an integer to hold its size) while it is being processed.
|
|
** Zeroblobs are intended to serve as placeholders for BLOBs whose
|
|
** content is later written using
|
|
** [sqlite3_blob_open | incremental BLOB I/O] routines.
|
|
** ^A negative value for the zeroblob results in a zero-length BLOB.
|
|
**
|
|
** ^The sqlite3_bind_pointer(S,I,P,T,D) routine causes the I-th parameter in
|
|
** [prepared statement] S to have an SQL value of NULL, but to also be
|
|
** associated with the pointer P of type T. ^D is either a NULL pointer or
|
|
** a pointer to a destructor function for P. ^SQLite will invoke the
|
|
** destructor D with a single argument of P when it is finished using
|
|
** P. The T parameter should be a static string, preferably a string
|
|
** literal. The sqlite3_bind_pointer() routine is part of the
|
|
** [pointer passing interface] added for SQLite 3.20.0.
|
|
**
|
|
** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer
|
|
** for the [prepared statement] or with a prepared statement for which
|
|
** [sqlite3_step()] has been called more recently than [sqlite3_reset()],
|
|
** then the call will return [SQLITE_MISUSE]. If any sqlite3_bind_()
|
|
** routine is passed a [prepared statement] that has been finalized, the
|
|
** result is undefined and probably harmful.
|
|
**
|
|
** ^Bindings are not cleared by the [sqlite3_reset()] routine.
|
|
** ^Unbound parameters are interpreted as NULL.
|
|
**
|
|
** ^The sqlite3_bind_* routines return [SQLITE_OK] on success or an
|
|
** [error code] if anything goes wrong.
|
|
** ^[SQLITE_TOOBIG] might be returned if the size of a string or BLOB
|
|
** exceeds limits imposed by [sqlite3_limit]([SQLITE_LIMIT_LENGTH]) or
|
|
** [SQLITE_MAX_LENGTH].
|
|
** ^[SQLITE_RANGE] is returned if the parameter
|
|
** index is out of range. ^[SQLITE_NOMEM] is returned if malloc() fails.
|
|
**
|
|
** See also: [sqlite3_bind_parameter_count()],
|
|
** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()].
|
|
*/
|
|
SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
|
|
SQLITE_API int sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64,
|
|
void(*)(void*));
|
|
SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double);
|
|
SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int);
|
|
SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
|
|
SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int);
|
|
SQLITE_API int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*));
|
|
SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
|
|
SQLITE_API int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64,
|
|
void(*)(void*), unsigned char encoding);
|
|
SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
|
|
SQLITE_API int sqlite3_bind_pointer(sqlite3_stmt*, int, void*, const char*,void(*)(void*));
|
|
SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
|
|
SQLITE_API int sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64);
|
|
|
|
/*
|
|
** CAPI3REF: Number Of SQL Parameters
|
|
** METHOD: sqlite3_stmt
|
|
**
|
|
** ^This routine can be used to find the number of [SQL parameters]
|
|
** in a [prepared statement]. SQL parameters are tokens of the
|
|
** form "?", "?NNN", ":AAA", "$AAA", or "@AAA" that serve as
|
|
** placeholders for values that are [sqlite3_bind_blob | bound]
|
|
** to the parameters at a later time.
|
|
**
|
|
** ^(This routine actually returns the index of the largest (rightmost)
|
|
** parameter. For all forms except ?NNN, this will correspond to the
|
|
** number of unique parameters. If parameters of the ?NNN form are used,
|
|
** there may be gaps in the list.)^
|
|
**
|
|
** See also: [sqlite3_bind_blob|sqlite3_bind()],
|
|
** [sqlite3_bind_parameter_name()], and
|
|
** [sqlite3_bind_parameter_index()].
|
|
*/
|
|
SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*);
|
|
|
|
/*
|
|
** CAPI3REF: Name Of A Host Parameter
|
|
** METHOD: sqlite3_stmt
|
|
**
|
|
** ^The sqlite3_bind_parameter_name(P,N) interface returns
|
|
** the name of the N-th [SQL parameter] in the [prepared statement] P.
|
|
** ^(SQL parameters of the form "?NNN" or ":AAA" or "@AAA" or "$AAA"
|
|
** have a name which is the string "?NNN" or ":AAA" or "@AAA" or "$AAA"
|
|
** respectively.
|
|
** In other words, the initial ":" or "$" or "@" or "?"
|
|
** is included as part of the name.)^
|
|
** ^Parameters of the form "?" without a following integer have no name
|
|
** and are referred to as "nameless" or "anonymous parameters".
|
|
**
|
|
** ^The first host 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 UTF-8 encoding even if the named parameter was
|
|
** originally specified as UTF-16 in [sqlite3_prepare16()],
|
|
** [sqlite3_prepare16_v2()], or [sqlite3_prepare16_v3()].
|
|
**
|
|
** See also: [sqlite3_bind_blob|sqlite3_bind()],
|
|
** [sqlite3_bind_parameter_count()], and
|
|
** [sqlite3_bind_parameter_index()].
|
|
*/
|
|
SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);
|
|
|
|
/*
|
|
** CAPI3REF: Index Of A Parameter With A Given Name
|
|
** METHOD: sqlite3_stmt
|
|
**
|
|
** ^Return the index of an SQL parameter given its name. ^The
|
|
** index value returned is suitable for use as the second
|
|
** parameter to [sqlite3_bind_blob|sqlite3_bind()]. ^A zero
|
|
** is returned if no matching parameter is found. ^The parameter
|
|
** name must be given in UTF-8 even if the original statement
|
|
** was prepared from UTF-16 text using [sqlite3_prepare16_v2()] or
|
|
** [sqlite3_prepare16_v3()].
|
|
**
|
|
** See also: [sqlite3_bind_blob|sqlite3_bind()],
|
|
** [sqlite3_bind_parameter_count()], and
|
|
** [sqlite3_bind_parameter_name()].
|
|
*/
|
|
SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName);
|
|
|
|
/*
|
|
** CAPI3REF: Reset All Bindings On A Prepared Statement
|
|
** METHOD: sqlite3_stmt
|
|
**
|
|
** ^Contrary to the intuition of many, [sqlite3_reset()] does not reset
|
|
** the [sqlite3_bind_blob | bindings] on a [prepared statement].
|
|
** ^Use this routine to reset all host parameters to NULL.
|
|
*/
|
|
SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*);
|
|
|
|
/*
|
|
** CAPI3REF: Number Of Columns In A Result Set
|
|
** METHOD: sqlite3_stmt
|
|
**
|
|
** ^Return the number of columns in the result set returned by the
|
|
** [prepared statement]. ^If this routine returns 0, that means the
|
|
** [prepared statement] returns no data (for example an [UPDATE]).
|
|
** ^However, just because this routine returns a positive number does not
|
|
** mean that one or more rows of data will be returned. ^A SELECT statement
|
|
** will always have a positive sqlite3_column_count() but depending on the
|
|
** WHERE clause constraints and the table content, it might return no rows.
|
|
**
|
|
** See also: [sqlite3_data_count()]
|
|
*/
|
|
SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt);
|
|
|
|
/*
|
|
** CAPI3REF: Column Names In A Result Set
|
|
** METHOD: sqlite3_stmt
|
|
**
|
|
** ^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 zero-terminated UTF-8 string
|
|
** and sqlite3_column_name16() returns a pointer to a zero-terminated
|
|
** UTF-16 string. ^The first parameter is the [prepared statement]
|
|
** that implements the [SELECT] statement. ^The second parameter is the
|
|
** column number. ^The leftmost column is number 0.
|
|
**
|
|
** ^The returned string pointer is valid until either the [prepared statement]
|
|
** is destroyed by [sqlite3_finalize()] or until the statement is automatically
|
|
** reprepared by the first call to [sqlite3_step()] for a particular run
|
|
** or until the next call to
|
|
** sqlite3_column_name() or sqlite3_column_name16() on the same column.
|
|
**
|
|
** ^If sqlite3_malloc() fails during the processing of either routine
|
|
** (for example during a conversion from UTF-8 to UTF-16) then a
|
|
** NULL pointer is returned.
|
|
**
|
|
** ^The name of a result column is the value of the "AS" clause for
|
|
** that column, if there is an AS clause. If there is no AS clause
|
|
** then the name of the column is unspecified and may change from
|
|
** one release of SQLite to the next.
|
|
*/
|
|
SQLITE_API const char *sqlite3_column_name(sqlite3_stmt*, int N);
|
|
SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N);
|
|
|
|
/*
|
|
** CAPI3REF: Source Of Data In A Query Result
|
|
** METHOD: sqlite3_stmt
|
|
**
|
|
** ^These routines provide a means to determine the database, table, and
|
|
** table column that is the origin of a particular result column in
|
|
** [SELECT] statement.
|
|
** ^The name of the database or table or column can be returned as
|
|
** either a UTF-8 or UTF-16 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 [prepared statement] is destroyed
|
|
** using [sqlite3_finalize()] or until the statement is automatically
|
|
** reprepared by the first call to [sqlite3_step()] for a particular run
|
|
** 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 these interfaces is a [prepared statement].
|
|
** ^These functions return information about the Nth result column returned by
|
|
** the statement, where N is the second function argument.
|
|
** ^The left-most column is column 0 for these routines.
|
|
**
|
|
** ^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. ^These routines might also return NULL if a memory allocation error
|
|
** occurs. ^Otherwise, they return the name of the attached database, table,
|
|
** or column that query result column was extracted from.
|
|
**
|
|
** ^As with all other SQLite APIs, those whose names end with "16" return
|
|
** UTF-16 encoded strings and the other functions return UTF-8.
|
|
**
|
|
** ^These APIs are only available if the library was compiled with the
|
|
** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol.
|
|
**
|
|
** If two or more threads call one or more
|
|
** [sqlite3_column_database_name | column metadata interfaces]
|
|
** for the same [prepared statement] and result column
|
|
** at the same time then the results are undefined.
|
|
*/
|
|
SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt*,int);
|
|
SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt*,int);
|
|
SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt*,int);
|
|
SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt*,int);
|
|
SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt*,int);
|
|
SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt*,int);
|
|
|
|
/*
|
|
** CAPI3REF: Declared Datatype Of A Query Result
|
|
** METHOD: sqlite3_stmt
|
|
**
|
|
** ^(The first parameter is a [prepared 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, given the database schema:
|
|
**
|
|
** CREATE TABLE t1(c1 VARIANT);
|
|
**
|
|
** and the following statement to be compiled:
|
|
**
|
|
** SELECT c1 + 1, c1 FROM t1;
|
|
**
|
|
** 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.
|
|
*/
|
|
SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt*,int);
|
|
SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
|
|
|
|
/*
|
|
** CAPI3REF: Evaluate An SQL Statement
|
|
** METHOD: sqlite3_stmt
|
|
**
|
|
** After a [prepared statement] has been prepared using any of
|
|
** [sqlite3_prepare_v2()], [sqlite3_prepare_v3()], [sqlite3_prepare16_v2()],
|
|
** or [sqlite3_prepare16_v3()] or one of the legacy
|
|
** interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], this function
|
|
** must be called one or more times to evaluate the statement.
|
|
**
|
|
** The details of the behavior of the sqlite3_step() interface depend
|
|
** on whether the statement was prepared using the newer "vX" interfaces
|
|
** [sqlite3_prepare_v3()], [sqlite3_prepare_v2()], [sqlite3_prepare16_v3()],
|
|
** [sqlite3_prepare16_v2()] or the older legacy
|
|
** interfaces [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the
|
|
** new "vX" interface is recommended for new applications but the legacy
|
|
** interface will continue to be supported.
|
|
**
|
|
** ^In the legacy 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 [result codes] or
|
|
** [extended result codes] 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 an
|
|
** 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 [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 (for example,
|
|
** [SQLITE_INTERRUPT], [SQLITE_SCHEMA], [SQLITE_CORRUPT], and so forth)
|
|
** can be obtained by calling [sqlite3_reset()] on the
|
|
** [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 [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.
|
|
**
|
|
** For all versions of SQLite up to and including 3.6.23.1, a call to
|
|
** [sqlite3_reset()] was required after sqlite3_step() returned anything
|
|
** other than [SQLITE_ROW] before any subsequent invocation of
|
|
** sqlite3_step(). Failure to reset the prepared statement using
|
|
** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from
|
|
** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1],
|
|
** sqlite3_step() began
|
|
** calling [sqlite3_reset()] automatically in this circumstance rather
|
|
** than returning [SQLITE_MISUSE]. This is not considered a compatibility
|
|
** break because any application that ever receives an SQLITE_MISUSE error
|
|
** is broken by definition. The [SQLITE_OMIT_AUTORESET] compile-time option
|
|
** can be used to restore the legacy behavior.
|
|
**
|
|
** <b>Goofy Interface Alert:</b> 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 [error 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 [sqlite3_prepare_v3()] or [sqlite3_prepare_v2()]
|
|
** or [sqlite3_prepare16_v2()] or [sqlite3_prepare16_v3()] instead
|
|
** of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()] interfaces,
|
|
** then the more specific [error codes] are returned directly
|
|
** by sqlite3_step(). The use of the "vX" interfaces is recommended.
|
|
*/
|
|
SQLITE_API int sqlite3_step(sqlite3_stmt*);
|
|
|
|
/*
|
|
** CAPI3REF: Number of columns in a result set
|
|
** METHOD: sqlite3_stmt
|
|
**
|
|
** ^The sqlite3_data_count(P) interface returns the number of columns in the
|
|
** current row of the result set of [prepared statement] P.
|
|
** ^If prepared statement P does not have results ready to return
|
|
** (via calls to the [sqlite3_column_int | sqlite3_column()] family of
|
|
** interfaces) then sqlite3_data_count(P) returns 0.
|
|
** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer.
|
|
** ^The sqlite3_data_count(P) routine returns 0 if the previous call to
|
|
** [sqlite3_step](P) returned [SQLITE_DONE]. ^The sqlite3_data_count(P)
|
|
** will return non-zero if previous call to [sqlite3_step](P) returned
|
|
** [SQLITE_ROW], except in the case of the [PRAGMA incremental_vacuum]
|
|
** where it always returns zero since each step of that multi-step
|
|
** pragma returns 0 columns of data.
|
|
**
|
|
** See also: [sqlite3_column_count()]
|
|
*/
|
|
SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
|
|
|
|
/*
|
|
** CAPI3REF: Fundamental Datatypes
|
|
** KEYWORDS: SQLITE_TEXT
|
|
**
|
|
** ^(Every value in SQLite has one of five fundamental datatypes:
|
|
**
|
|
** <ul>
|
|
** <li> 64-bit signed integer
|
|
** <li> 64-bit IEEE floating point number
|
|
** <li> string
|
|
** <li> BLOB
|
|
** <li> NULL
|
|
** </ul>)^
|
|
**
|
|
** 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: Result Values From A Query
|
|
** KEYWORDS: {column access functions}
|
|
** METHOD: sqlite3_stmt
|
|
**
|
|
** <b>Summary:</b>
|
|
** <blockquote><table border=0 cellpadding=0 cellspacing=0>
|
|
** <tr><td><b>sqlite3_column_blob</b><td>→<td>BLOB result
|
|
** <tr><td><b>sqlite3_column_double</b><td>→<td>REAL result
|
|
** <tr><td><b>sqlite3_column_int</b><td>→<td>32-bit INTEGER result
|
|
** <tr><td><b>sqlite3_column_int64</b><td>→<td>64-bit INTEGER result
|
|
** <tr><td><b>sqlite3_column_text</b><td>→<td>UTF-8 TEXT result
|
|
** <tr><td><b>sqlite3_column_text16</b><td>→<td>UTF-16 TEXT result
|
|
** <tr><td><b>sqlite3_column_value</b><td>→<td>The result as an
|
|
** [sqlite3_value|unprotected sqlite3_value] object.
|
|
** <tr><td> <td> <td>
|
|
** <tr><td><b>sqlite3_column_bytes</b><td>→<td>Size of a BLOB
|
|
** or a UTF-8 TEXT result in bytes
|
|
** <tr><td><b>sqlite3_column_bytes16 </b>
|
|
** <td>→ <td>Size of UTF-16
|
|
** TEXT in bytes
|
|
** <tr><td><b>sqlite3_column_type</b><td>→<td>Default
|
|
** datatype of the result
|
|
** </table></blockquote>
|
|
**
|
|
** <b>Details:</b>
|
|
**
|
|
** ^These routines return information about a single column of the current
|
|
** result row of a query. ^In every case the first argument is a pointer
|
|
** to the [prepared statement] that is being evaluated (the [sqlite3_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 leftmost column of the result set has the index 0.
|
|
** ^The number of columns in the result can be determined using
|
|
** [sqlite3_column_count()].
|
|
**
|
|
** If the SQL statement does not currently point to a valid row, or if the
|
|
** column index is out of range, the result is undefined.
|
|
** These routines may only be called when the most recent call to
|
|
** [sqlite3_step()] has returned [SQLITE_ROW] and neither
|
|
** [sqlite3_reset()] nor [sqlite3_finalize()] have been called subsequently.
|
|
** If any of these routines are called after [sqlite3_reset()] or
|
|
** [sqlite3_finalize()] or after [sqlite3_step()] has returned
|
|
** something other than [SQLITE_ROW], the results are undefined.
|
|
** If [sqlite3_step()] or [sqlite3_reset()] or [sqlite3_finalize()]
|
|
** are called from a different thread while any of these routines
|
|
** are pending, then the results are undefined.
|
|
**
|
|
** The first six interfaces (_blob, _double, _int, _int64, _text, and _text16)
|
|
** each return the value of a result column in a specific data format. If
|
|
** the result column is not initially in the requested format (for example,
|
|
** if the query returns an integer but the sqlite3_column_text() interface
|
|
** is used to extract the value) then an automatic type conversion is performed.
|
|
**
|
|
** ^The sqlite3_column_type() routine returns the
|
|
** [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 return value of sqlite3_column_type() can be used to decide which
|
|
** of the first six interface should be used to extract the column value.
|
|
** The value returned by sqlite3_column_type() is only meaningful if no
|
|
** automatic type conversions have occurred for the value in question.
|
|
** After a type conversion, the result of calling sqlite3_column_type()
|
|
** is undefined, though harmless. Future
|
|
** versions of SQLite may change the behavior of sqlite3_column_type()
|
|
** following a type conversion.
|
|
**
|
|
** If the result is a BLOB or a TEXT string, then the sqlite3_column_bytes()
|
|
** or sqlite3_column_bytes16() interfaces can be used to determine the size
|
|
** of that BLOB or string.
|
|
**
|
|
** ^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.
|
|
** ^If the result is NULL, then sqlite3_column_bytes() returns zero.
|
|
**
|
|
** ^If the result is a BLOB or UTF-16 string then the sqlite3_column_bytes16()
|
|
** routine returns the number of bytes in that BLOB or string.
|
|
** ^If the result is a UTF-8 string, then sqlite3_column_bytes16() converts
|
|
** the string to UTF-16 and then returns the number of bytes.
|
|
** ^If the result is a numeric value then sqlite3_column_bytes16() uses
|
|
** [sqlite3_snprintf()] to convert that value to a UTF-16 string and returns
|
|
** the number of bytes in that string.
|
|
** ^If the result is NULL, then sqlite3_column_bytes16() returns zero.
|
|
**
|
|
** ^The values returned by [sqlite3_column_bytes()] and
|
|
** [sqlite3_column_bytes16()] do not include the zero terminators at the end
|
|
** of the string. ^For clarity: the values returned by
|
|
** [sqlite3_column_bytes()] and [sqlite3_column_bytes16()] are the number of
|
|
** bytes in the string, not the number of characters.
|
|
**
|
|
** ^Strings returned by sqlite3_column_text() and sqlite3_column_text16(),
|
|
** even empty strings, are always zero-terminated. ^The return
|
|
** value from sqlite3_column_blob() for a zero-length BLOB is a NULL pointer.
|
|
**
|
|
** ^Strings returned by sqlite3_column_text16() always have the endianness
|
|
** which is native to the platform, regardless of the text encoding set
|
|
** for the database.
|
|
**
|
|
** <b>Warning:</b> ^The object returned by [sqlite3_column_value()] is an
|
|
** [unprotected sqlite3_value] object. In a multithreaded environment,
|
|
** an unprotected sqlite3_value object may only be used safely with
|
|
** [sqlite3_bind_value()] and [sqlite3_result_value()].
|
|
** If the [unprotected sqlite3_value] object returned by
|
|
** [sqlite3_column_value()] is used in any other way, including calls
|
|
** to routines like [sqlite3_value_int()], [sqlite3_value_text()],
|
|
** or [sqlite3_value_bytes()], the behavior is not threadsafe.
|
|
** Hence, the sqlite3_column_value() interface
|
|
** is normally only useful within the implementation of
|
|
** [application-defined SQL functions] or [virtual tables], not within
|
|
** top-level application code.
|
|
**
|
|
** These routines may attempt to convert the datatype of the result.
|
|
** ^For example, if the internal representation is FLOAT and a text result
|
|
** is requested, [sqlite3_snprintf()] is used internally to perform the
|
|
** conversion automatically. ^(The following table details the conversions
|
|
** that are applied:
|
|
**
|
|
** <blockquote>
|
|
** <table border="1">
|
|
** <tr><th> Internal<br>Type <th> Requested<br>Type <th> Conversion
|
|
**
|
|
** <tr><td> NULL <td> INTEGER <td> Result is 0
|
|
** <tr><td> NULL <td> FLOAT <td> Result is 0.0
|
|
** <tr><td> NULL <td> TEXT <td> Result is a NULL pointer
|
|
** <tr><td> NULL <td> BLOB <td> Result is a NULL pointer
|
|
** <tr><td> INTEGER <td> FLOAT <td> Convert from integer to float
|
|
** <tr><td> INTEGER <td> TEXT <td> ASCII rendering of the integer
|
|
** <tr><td> INTEGER <td> BLOB <td> Same as INTEGER->TEXT
|
|
** <tr><td> FLOAT <td> INTEGER <td> [CAST] to INTEGER
|
|
** <tr><td> FLOAT <td> TEXT <td> ASCII rendering of the float
|
|
** <tr><td> FLOAT <td> BLOB <td> [CAST] to BLOB
|
|
** <tr><td> TEXT <td> INTEGER <td> [CAST] to INTEGER
|
|
** <tr><td> TEXT <td> FLOAT <td> [CAST] to REAL
|
|
** <tr><td> TEXT <td> BLOB <td> No change
|
|
** <tr><td> BLOB <td> INTEGER <td> [CAST] to INTEGER
|
|
** <tr><td> BLOB <td> FLOAT <td> [CAST] to REAL
|
|
** <tr><td> BLOB <td> TEXT <td> [CAST] to TEXT, ensure zero terminator
|
|
** </table>
|
|
** </blockquote>)^
|
|
**
|
|
** 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:
|
|
**
|
|
** <ul>
|
|
** <li> 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.</li>
|
|
** <li> 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.</li>
|
|
** <li> 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.</li>
|
|
** </ul>
|
|
**
|
|
** ^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 references will have been modified. Other kinds
|
|
** of conversion are done in place when it is possible, but sometimes they
|
|
** are not possible and in those cases prior pointers are invalidated.
|
|
**
|
|
** The safest policy is to invoke these routines
|
|
** in one of the following ways:
|
|
**
|
|
** <ul>
|
|
** <li>sqlite3_column_text() followed by sqlite3_column_bytes()</li>
|
|
** <li>sqlite3_column_blob() followed by sqlite3_column_bytes()</li>
|
|
** <li>sqlite3_column_text16() followed by sqlite3_column_bytes16()</li>
|
|
** </ul>
|
|
**
|
|
** 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 calls
|
|
** 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().
|
|
**
|
|
** ^The pointers returned are valid until a type conversion occurs as
|
|
** described above, or until [sqlite3_step()] or [sqlite3_reset()] or
|
|
** [sqlite3_finalize()] is called. ^The memory space used to hold strings
|
|
** and BLOBs is freed automatically. Do not pass the pointers returned
|
|
** from [sqlite3_column_blob()], [sqlite3_column_text()], etc. into
|
|
** [sqlite3_free()].
|
|
**
|
|
** As long as the input parameters are correct, these routines will only
|
|
** fail if an out-of-memory error occurs during a format conversion.
|
|
** Only the following subset of interfaces are subject to out-of-memory
|
|
** errors:
|
|
**
|
|
** <ul>
|
|
** <li> sqlite3_column_blob()
|
|
** <li> sqlite3_column_text()
|
|
** <li> sqlite3_column_text16()
|
|
** <li> sqlite3_column_bytes()
|
|
** <li> sqlite3_column_bytes16()
|
|
** </ul>
|
|
**
|
|
** If an out-of-memory error occurs, then the return value from these
|
|
** routines is the same as if the column had contained an SQL NULL value.
|
|
** Valid SQL NULL returns can be distinguished from out-of-memory errors
|
|
** by invoking the [sqlite3_errcode()] immediately after the suspect
|
|
** return value is obtained and before any
|
|
** other SQLite interface is called on the same [database connection].
|
|
*/
|
|
SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
|
|
SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol);
|
|
SQLITE_API int sqlite3_column_int(sqlite3_stmt*, int iCol);
|
|
SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);
|
|
SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
|
|
SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);
|
|
SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
|
|
SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
|
|
SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol);
|
|
SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol);
|
|
|
|
/*
|
|
** CAPI3REF: Destroy A Prepared Statement Object
|
|
** DESTRUCTOR: sqlite3_stmt
|
|
**
|
|
** ^The sqlite3_finalize() function is called to delete a [prepared statement].
|
|
** ^If the most recent evaluation of the statement encountered no errors
|
|
** or if the statement is never been evaluated, then sqlite3_finalize() returns
|
|
** SQLITE_OK. ^If the most recent evaluation of statement S failed, then
|
|
** sqlite3_finalize(S) returns the appropriate [error code] or
|
|
** [extended error code].
|
|
**
|
|
** ^The sqlite3_finalize(S) routine can be called at any point during
|
|
** the life cycle of [prepared statement] S:
|
|
** before statement S is ever evaluated, after
|
|
** one or more calls to [sqlite3_reset()], or after any call
|
|
** to [sqlite3_step()] regardless of whether or not the statement has
|
|
** completed execution.
|
|
**
|
|
** ^Invoking sqlite3_finalize() on a NULL pointer is a harmless no-op.
|
|
**
|
|
** The application must finalize every [prepared statement] in order to avoid
|
|
** resource leaks. It is a grievous error for the application to try to use
|
|
** a prepared statement after it has been finalized. Any use of a prepared
|
|
** statement after it has been finalized can result in undefined and
|
|
** undesirable behavior such as segfaults and heap corruption.
|
|
*/
|
|
SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt);
|
|
|
|
/*
|
|
** CAPI3REF: Reset A Prepared Statement Object
|
|
** METHOD: sqlite3_stmt
|
|
**
|
|
** The sqlite3_reset() function is called to reset a [prepared statement]
|
|
** object back to its 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.
|
|
**
|
|
** ^The [sqlite3_reset(S)] interface resets the [prepared statement] S
|
|
** back to the beginning of its program.
|
|
**
|
|
** ^The return code from [sqlite3_reset(S)] indicates whether or not
|
|
** the previous evaluation of prepared statement S completed successfully.
|
|
** ^If [sqlite3_step(S)] has never before been called on S or if
|
|
** [sqlite3_step(S)] has not been called since the previous call
|
|
** to [sqlite3_reset(S)], then [sqlite3_reset(S)] will return
|
|
** [SQLITE_OK].
|
|
**
|
|
** ^If the most recent call to [sqlite3_step(S)] for the
|
|
** [prepared statement] S indicated an error, then
|
|
** [sqlite3_reset(S)] returns an appropriate [error code].
|
|
** ^The [sqlite3_reset(S)] interface might also return an [error code]
|
|
** if there were no prior errors but the process of resetting
|
|
** the prepared statement caused a new error. ^For example, if an
|
|
** [INSERT] statement with a [RETURNING] clause is only stepped one time,
|
|
** that one call to [sqlite3_step(S)] might return SQLITE_ROW but
|
|
** the overall statement might still fail and the [sqlite3_reset(S)] call
|
|
** might return SQLITE_BUSY if locking constraints prevent the
|
|
** database change from committing. Therefore, it is important that
|
|
** applications check the return code from [sqlite3_reset(S)] even if
|
|
** no prior call to [sqlite3_step(S)] indicated a problem.
|
|
**
|
|
** ^The [sqlite3_reset(S)] interface does not change the values
|
|
** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S.
|
|
*/
|
|
SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
|
|
|
|
|
|
/*
|
|
** CAPI3REF: Create Or Redefine SQL Functions
|
|
** KEYWORDS: {function creation routines}
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^These functions (collectively known as "function creation routines")
|
|
** are used to add SQL functions or aggregates or to redefine the behavior
|
|
** of existing SQL functions or aggregates. The only differences between
|
|
** the three "sqlite3_create_function*" routines are the text encoding
|
|
** expected for the second parameter (the name of the function being
|
|
** created) and the presence or absence of a destructor callback for
|
|
** the application data pointer. Function sqlite3_create_window_function()
|
|
** is similar, but allows the user to supply the extra callback functions
|
|
** needed by [aggregate window functions].
|
|
**
|
|
** ^The first parameter is the [database connection] to which the SQL
|
|
** function is to be added. ^If an application uses more than one database
|
|
** connection then application-defined SQL functions must be added
|
|
** to each database connection separately.
|
|
**
|
|
** ^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 in a UTF-8
|
|
** representation, exclusive of the zero-terminator. ^Note that the name
|
|
** length limit is in UTF-8 bytes, not characters nor UTF-16 bytes.
|
|
** ^Any attempt to create a function with a longer name
|
|
** will result in [SQLITE_MISUSE] being returned.
|
|
**
|
|
** ^The third parameter (nArg)
|
|
** is the number of arguments that the SQL function or
|
|
** aggregate takes. ^If this parameter is -1, then the SQL function or
|
|
** aggregate may take any number of arguments between 0 and the limit
|
|
** set by [sqlite3_limit]([SQLITE_LIMIT_FUNCTION_ARG]). If the third
|
|
** parameter is less than -1 or greater than 127 then the behavior is
|
|
** undefined.
|
|
**
|
|
** ^The fourth parameter, eTextRep, specifies what
|
|
** [SQLITE_UTF8 | text encoding] this SQL function prefers for
|
|
** its parameters. The application should set this parameter to
|
|
** [SQLITE_UTF16LE] if the function implementation invokes
|
|
** [sqlite3_value_text16le()] on an input, or [SQLITE_UTF16BE] if the
|
|
** implementation invokes [sqlite3_value_text16be()] on an input, or
|
|
** [SQLITE_UTF16] if [sqlite3_value_text16()] is used, or [SQLITE_UTF8]
|
|
** otherwise. ^The same SQL function may be registered multiple times using
|
|
** different preferred text encodings, with different implementations for
|
|
** each encoding.
|
|
** ^When multiple implementations of the same function are available, SQLite
|
|
** will pick the one that involves the least amount of data conversion.
|
|
**
|
|
** ^The fourth parameter may optionally be ORed with [SQLITE_DETERMINISTIC]
|
|
** to signal that the function will always return the same result given
|
|
** the same inputs within a single SQL statement. Most SQL functions are
|
|
** deterministic. The built-in [random()] SQL function is an example of a
|
|
** function that is not deterministic. The SQLite query planner is able to
|
|
** perform additional optimizations on deterministic functions, so use
|
|
** of the [SQLITE_DETERMINISTIC] flag is recommended where possible.
|
|
**
|
|
** ^The fourth parameter may also optionally include the [SQLITE_DIRECTONLY]
|
|
** flag, which if present prevents the function from being invoked from
|
|
** within VIEWs, TRIGGERs, CHECK constraints, generated column expressions,
|
|
** index expressions, or the WHERE clause of partial indexes.
|
|
**
|
|
** For best security, the [SQLITE_DIRECTONLY] flag is recommended for
|
|
** all application-defined SQL functions that do not need to be
|
|
** used inside of triggers, view, CHECK constraints, or other elements of
|
|
** the database schema. This flags is especially recommended for SQL
|
|
** functions that have side effects or reveal internal application state.
|
|
** Without this flag, an attacker might be able to modify the schema of
|
|
** a database file to include invocations of the function with parameters
|
|
** chosen by the attacker, which the application will then execute when
|
|
** the database file is opened and read.
|
|
**
|
|
** ^(The fifth parameter is an arbitrary pointer. The implementation of the
|
|
** function can gain access to this pointer using [sqlite3_user_data()].)^
|
|
**
|
|
** ^The sixth, seventh and eighth parameters passed to the three
|
|
** "sqlite3_create_function*" functions, 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 must be passed as the xStep and xFinal
|
|
** parameters. ^An aggregate SQL function requires an implementation of xStep
|
|
** and xFinal and NULL pointer must be passed for xFunc. ^To delete an existing
|
|
** SQL function or aggregate, pass NULL pointers for all three function
|
|
** callbacks.
|
|
**
|
|
** ^The sixth, seventh, eighth and ninth parameters (xStep, xFinal, xValue
|
|
** and xInverse) passed to sqlite3_create_window_function are pointers to
|
|
** C-language callbacks that implement the new function. xStep and xFinal
|
|
** must both be non-NULL. xValue and xInverse may either both be NULL, in
|
|
** which case a regular aggregate function is created, or must both be
|
|
** non-NULL, in which case the new function may be used as either an aggregate
|
|
** or aggregate window function. More details regarding the implementation
|
|
** of aggregate window functions are
|
|
** [user-defined window functions|available here].
|
|
**
|
|
** ^(If the final parameter to sqlite3_create_function_v2() or
|
|
** sqlite3_create_window_function() is not NULL, then it is destructor for
|
|
** the application data pointer. The destructor is invoked when the function
|
|
** is deleted, either by being overloaded or when the database connection
|
|
** closes.)^ ^The destructor is also invoked if the call to
|
|
** sqlite3_create_function_v2() fails. ^When the destructor callback is
|
|
** invoked, it is passed a single argument which is a copy of the application
|
|
** data pointer which was the fifth parameter to sqlite3_create_function_v2().
|
|
**
|
|
** ^It is permitted to register multiple implementations of the same
|
|
** functions with the same name but with either differing numbers of
|
|
** arguments or differing preferred text encodings. ^SQLite will use
|
|
** the implementation that most closely matches the way in which the
|
|
** SQL function is used. ^A function implementation with a non-negative
|
|
** nArg parameter is a better match than a function implementation with
|
|
** a negative nArg. ^A function where the preferred text encoding
|
|
** matches the database encoding is a better
|
|
** match than a function where the encoding is different.
|
|
** ^A function where the encoding difference is between UTF16le and UTF16be
|
|
** is a closer match than a function where the encoding difference is
|
|
** between UTF8 and UTF16.
|
|
**
|
|
** ^Built-in functions may be overloaded by new application-defined functions.
|
|
**
|
|
** ^An application-defined function is permitted to call other
|
|
** SQLite interfaces. However, such calls must not
|
|
** close the database connection nor finalize or reset the prepared
|
|
** statement in which the function is running.
|
|
*/
|
|
SQLITE_API int sqlite3_create_function(
|
|
sqlite3 *db,
|
|
const char *zFunctionName,
|
|
int nArg,
|
|
int eTextRep,
|
|
void *pApp,
|
|
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
|
|
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
|
void (*xFinal)(sqlite3_context*)
|
|
);
|
|
SQLITE_API int sqlite3_create_function16(
|
|
sqlite3 *db,
|
|
const void *zFunctionName,
|
|
int nArg,
|
|
int eTextRep,
|
|
void *pApp,
|
|
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
|
|
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
|
void (*xFinal)(sqlite3_context*)
|
|
);
|
|
SQLITE_API int sqlite3_create_function_v2(
|
|
sqlite3 *db,
|
|
const char *zFunctionName,
|
|
int nArg,
|
|
int eTextRep,
|
|
void *pApp,
|
|
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
|
|
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
|
void (*xFinal)(sqlite3_context*),
|
|
void(*xDestroy)(void*)
|
|
);
|
|
SQLITE_API int sqlite3_create_window_function(
|
|
sqlite3 *db,
|
|
const char *zFunctionName,
|
|
int nArg,
|
|
int eTextRep,
|
|
void *pApp,
|
|
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
|
void (*xFinal)(sqlite3_context*),
|
|
void (*xValue)(sqlite3_context*),
|
|
void (*xInverse)(sqlite3_context*,int,sqlite3_value**),
|
|
void(*xDestroy)(void*)
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Text Encodings
|
|
**
|
|
** These constant define integer codes that represent the various
|
|
** text encodings supported by SQLite.
|
|
*/
|
|
#define SQLITE_UTF8 1 /* IMP: R-37514-35566 */
|
|
#define SQLITE_UTF16LE 2 /* IMP: R-03371-37637 */
|
|
#define SQLITE_UTF16BE 3 /* IMP: R-51971-34154 */
|
|
#define SQLITE_UTF16 4 /* Use native byte order */
|
|
#define SQLITE_ANY 5 /* Deprecated */
|
|
#define SQLITE_UTF16_ALIGNED 8 /* sqlite3_create_collation only */
|
|
|
|
/*
|
|
** CAPI3REF: Function Flags
|
|
**
|
|
** These constants may be ORed together with the
|
|
** [SQLITE_UTF8 | preferred text encoding] as the fourth argument
|
|
** to [sqlite3_create_function()], [sqlite3_create_function16()], or
|
|
** [sqlite3_create_function_v2()].
|
|
**
|
|
** <dl>
|
|
** [[SQLITE_DETERMINISTIC]] <dt>SQLITE_DETERMINISTIC</dt><dd>
|
|
** The SQLITE_DETERMINISTIC flag means that the new function always gives
|
|
** the same output when the input parameters are the same.
|
|
** The [abs|abs() function] is deterministic, for example, but
|
|
** [randomblob|randomblob()] is not. Functions must
|
|
** be deterministic in order to be used in certain contexts such as
|
|
** with the WHERE clause of [partial indexes] or in [generated columns].
|
|
** SQLite might also optimize deterministic functions by factoring them
|
|
** out of inner loops.
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_DIRECTONLY]] <dt>SQLITE_DIRECTONLY</dt><dd>
|
|
** The SQLITE_DIRECTONLY flag means that the function may only be invoked
|
|
** from top-level SQL, and cannot be used in VIEWs or TRIGGERs nor in
|
|
** schema structures such as [CHECK constraints], [DEFAULT clauses],
|
|
** [expression indexes], [partial indexes], or [generated columns].
|
|
** <p>
|
|
** The SQLITE_DIRECTONLY flag is recommended for any
|
|
** [application-defined SQL function]
|
|
** that has side-effects or that could potentially leak sensitive information.
|
|
** This will prevent attacks in which an application is tricked
|
|
** into using a database file that has had its schema surreptitiously
|
|
** modified to invoke the application-defined function in ways that are
|
|
** harmful.
|
|
** <p>
|
|
** Some people say it is good practice to set SQLITE_DIRECTONLY on all
|
|
** [application-defined SQL functions], regardless of whether or not they
|
|
** are security sensitive, as doing so prevents those functions from being used
|
|
** inside of the database schema, and thus ensures that the database
|
|
** can be inspected and modified using generic tools (such as the [CLI])
|
|
** that do not have access to the application-defined functions.
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_INNOCUOUS]] <dt>SQLITE_INNOCUOUS</dt><dd>
|
|
** The SQLITE_INNOCUOUS flag means that the function is unlikely
|
|
** to cause problems even if misused. An innocuous function should have
|
|
** no side effects and should not depend on any values other than its
|
|
** input parameters. The [abs|abs() function] is an example of an
|
|
** innocuous function.
|
|
** The [load_extension() SQL function] is not innocuous because of its
|
|
** side effects.
|
|
** <p> SQLITE_INNOCUOUS is similar to SQLITE_DETERMINISTIC, but is not
|
|
** exactly the same. The [random|random() function] is an example of a
|
|
** function that is innocuous but not deterministic.
|
|
** <p>Some heightened security settings
|
|
** ([SQLITE_DBCONFIG_TRUSTED_SCHEMA] and [PRAGMA trusted_schema=OFF])
|
|
** disable the use of SQL functions inside views and triggers and in
|
|
** schema structures such as [CHECK constraints], [DEFAULT clauses],
|
|
** [expression indexes], [partial indexes], and [generated columns] unless
|
|
** the function is tagged with SQLITE_INNOCUOUS. Most built-in functions
|
|
** are innocuous. Developers are advised to avoid using the
|
|
** SQLITE_INNOCUOUS flag for application-defined functions unless the
|
|
** function has been carefully audited and found to be free of potentially
|
|
** security-adverse side-effects and information-leaks.
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_SUBTYPE]] <dt>SQLITE_SUBTYPE</dt><dd>
|
|
** The SQLITE_SUBTYPE flag indicates to SQLite that a function might call
|
|
** [sqlite3_value_subtype()] to inspect the sub-types of its arguments.
|
|
** This flag instructs SQLite to omit some corner-case optimizations that
|
|
** might disrupt the operation of the [sqlite3_value_subtype()] function,
|
|
** causing it to return zero rather than the correct subtype().
|
|
** SQL functions that invokes [sqlite3_value_subtype()] should have this
|
|
** property. If the SQLITE_SUBTYPE property is omitted, then the return
|
|
** value from [sqlite3_value_subtype()] might sometimes be zero even though
|
|
** a non-zero subtype was specified by the function argument expression.
|
|
**
|
|
** [[SQLITE_RESULT_SUBTYPE]] <dt>SQLITE_RESULT_SUBTYPE</dt><dd>
|
|
** The SQLITE_RESULT_SUBTYPE flag indicates to SQLite that a function might call
|
|
** [sqlite3_result_subtype()] to cause a sub-type to be associated with its
|
|
** result.
|
|
** Every function that invokes [sqlite3_result_subtype()] should have this
|
|
** property. If it does not, then the call to [sqlite3_result_subtype()]
|
|
** might become a no-op if the function is used as term in an
|
|
** [expression index]. On the other hand, SQL functions that never invoke
|
|
** [sqlite3_result_subtype()] should avoid setting this property, as the
|
|
** purpose of this property is to disable certain optimizations that are
|
|
** incompatible with subtypes.
|
|
** </dd>
|
|
** </dl>
|
|
*/
|
|
#define SQLITE_DETERMINISTIC 0x000000800
|
|
#define SQLITE_DIRECTONLY 0x000080000
|
|
#define SQLITE_SUBTYPE 0x000100000
|
|
#define SQLITE_INNOCUOUS 0x000200000
|
|
#define SQLITE_RESULT_SUBTYPE 0x001000000
|
|
|
|
/*
|
|
** CAPI3REF: Deprecated Functions
|
|
** DEPRECATED
|
|
**
|
|
** These functions are [deprecated]. In order to maintain
|
|
** backwards compatibility with older code, these functions continue
|
|
** to be supported. However, new applications should avoid
|
|
** the use of these functions. To encourage programmers to avoid
|
|
** these functions, we will not explain what they do.
|
|
*/
|
|
#ifndef SQLITE_OMIT_DEPRECATED
|
|
SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*);
|
|
SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*);
|
|
SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
|
|
SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void);
|
|
SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void);
|
|
SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),
|
|
void*,sqlite3_int64);
|
|
#endif
|
|
|
|
/*
|
|
** CAPI3REF: Obtaining SQL Values
|
|
** METHOD: sqlite3_value
|
|
**
|
|
** <b>Summary:</b>
|
|
** <blockquote><table border=0 cellpadding=0 cellspacing=0>
|
|
** <tr><td><b>sqlite3_value_blob</b><td>→<td>BLOB value
|
|
** <tr><td><b>sqlite3_value_double</b><td>→<td>REAL value
|
|
** <tr><td><b>sqlite3_value_int</b><td>→<td>32-bit INTEGER value
|
|
** <tr><td><b>sqlite3_value_int64</b><td>→<td>64-bit INTEGER value
|
|
** <tr><td><b>sqlite3_value_pointer</b><td>→<td>Pointer value
|
|
** <tr><td><b>sqlite3_value_text</b><td>→<td>UTF-8 TEXT value
|
|
** <tr><td><b>sqlite3_value_text16</b><td>→<td>UTF-16 TEXT value in
|
|
** the native byteorder
|
|
** <tr><td><b>sqlite3_value_text16be</b><td>→<td>UTF-16be TEXT value
|
|
** <tr><td><b>sqlite3_value_text16le</b><td>→<td>UTF-16le TEXT value
|
|
** <tr><td> <td> <td>
|
|
** <tr><td><b>sqlite3_value_bytes</b><td>→<td>Size of a BLOB
|
|
** or a UTF-8 TEXT in bytes
|
|
** <tr><td><b>sqlite3_value_bytes16 </b>
|
|
** <td>→ <td>Size of UTF-16
|
|
** TEXT in bytes
|
|
** <tr><td><b>sqlite3_value_type</b><td>→<td>Default
|
|
** datatype of the value
|
|
** <tr><td><b>sqlite3_value_numeric_type </b>
|
|
** <td>→ <td>Best numeric datatype of the value
|
|
** <tr><td><b>sqlite3_value_nochange </b>
|
|
** <td>→ <td>True if the column is unchanged in an UPDATE
|
|
** against a virtual table.
|
|
** <tr><td><b>sqlite3_value_frombind </b>
|
|
** <td>→ <td>True if value originated from a [bound parameter]
|
|
** </table></blockquote>
|
|
**
|
|
** <b>Details:</b>
|
|
**
|
|
** These routines extract type, size, and content information from
|
|
** [protected sqlite3_value] objects. Protected sqlite3_value objects
|
|
** are used to pass parameter information into the functions that
|
|
** implement [application-defined SQL functions] and [virtual tables].
|
|
**
|
|
** These routines work only with [protected sqlite3_value] objects.
|
|
** Any attempt to use these routines on an [unprotected sqlite3_value]
|
|
** is not threadsafe.
|
|
**
|
|
** ^These routines work just like the corresponding [column access functions]
|
|
** except that these routines take a single [protected sqlite3_value] object
|
|
** pointer instead of a [sqlite3_stmt*] pointer and an integer column number.
|
|
**
|
|
** ^The sqlite3_value_text16() interface extracts a UTF-16 string
|
|
** in the native byte-order of the host machine. ^The
|
|
** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces
|
|
** extract UTF-16 strings as big-endian and little-endian respectively.
|
|
**
|
|
** ^If [sqlite3_value] object V was initialized
|
|
** using [sqlite3_bind_pointer(S,I,P,X,D)] or [sqlite3_result_pointer(C,P,X,D)]
|
|
** and if X and Y are strings that compare equal according to strcmp(X,Y),
|
|
** then sqlite3_value_pointer(V,Y) will return the pointer P. ^Otherwise,
|
|
** sqlite3_value_pointer(V,Y) returns a NULL. The sqlite3_bind_pointer()
|
|
** routine is part of the [pointer passing interface] added for SQLite 3.20.0.
|
|
**
|
|
** ^(The sqlite3_value_type(V) interface returns the
|
|
** [SQLITE_INTEGER | datatype code] for the initial datatype of the
|
|
** [sqlite3_value] object V. The returned value is one of [SQLITE_INTEGER],
|
|
** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL].)^
|
|
** Other interfaces might change the datatype for an sqlite3_value object.
|
|
** For example, if the datatype is initially SQLITE_INTEGER and
|
|
** sqlite3_value_text(V) is called to extract a text value for that
|
|
** integer, then subsequent calls to sqlite3_value_type(V) might return
|
|
** SQLITE_TEXT. Whether or not a persistent internal datatype conversion
|
|
** occurs is undefined and may change from one release of SQLite to the next.
|
|
**
|
|
** ^(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 other
|
|
** words, if the value is a string that looks like a number)
|
|
** then the conversion is performed. Otherwise no conversion occurs.
|
|
** The [SQLITE_INTEGER | datatype] after conversion is returned.)^
|
|
**
|
|
** ^Within the [xUpdate] method of a [virtual table], the
|
|
** sqlite3_value_nochange(X) interface returns true if and only if
|
|
** the column corresponding to X is unchanged by the UPDATE operation
|
|
** that the xUpdate method call was invoked to implement and if
|
|
** and the prior [xColumn] method call that was invoked to extracted
|
|
** the value for that column returned without setting a result (probably
|
|
** because it queried [sqlite3_vtab_nochange()] and found that the column
|
|
** was unchanging). ^Within an [xUpdate] method, any value for which
|
|
** sqlite3_value_nochange(X) is true will in all other respects appear
|
|
** to be a NULL value. If sqlite3_value_nochange(X) is invoked anywhere other
|
|
** than within an [xUpdate] method call for an UPDATE statement, then
|
|
** the return value is arbitrary and meaningless.
|
|
**
|
|
** ^The sqlite3_value_frombind(X) interface returns non-zero if the
|
|
** value X originated from one of the [sqlite3_bind_int|sqlite3_bind()]
|
|
** interfaces. ^If X comes from an SQL literal value, or a table column,
|
|
** or an expression, then sqlite3_value_frombind(X) returns zero.
|
|
**
|
|
** Please pay particular attention to the fact that the pointer 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()], [sqlite3_value_text()],
|
|
** or [sqlite3_value_text16()].
|
|
**
|
|
** These routines must be called from the same thread as
|
|
** the SQL function that supplied the [sqlite3_value*] parameters.
|
|
**
|
|
** As long as the input parameter is correct, these routines can only
|
|
** fail if an out-of-memory error occurs during a format conversion.
|
|
** Only the following subset of interfaces are subject to out-of-memory
|
|
** errors:
|
|
**
|
|
** <ul>
|
|
** <li> sqlite3_value_blob()
|
|
** <li> sqlite3_value_text()
|
|
** <li> sqlite3_value_text16()
|
|
** <li> sqlite3_value_text16le()
|
|
** <li> sqlite3_value_text16be()
|
|
** <li> sqlite3_value_bytes()
|
|
** <li> sqlite3_value_bytes16()
|
|
** </ul>
|
|
**
|
|
** If an out-of-memory error occurs, then the return value from these
|
|
** routines is the same as if the column had contained an SQL NULL value.
|
|
** Valid SQL NULL returns can be distinguished from out-of-memory errors
|
|
** by invoking the [sqlite3_errcode()] immediately after the suspect
|
|
** return value is obtained and before any
|
|
** other SQLite interface is called on the same [database connection].
|
|
*/
|
|
SQLITE_API const void *sqlite3_value_blob(sqlite3_value*);
|
|
SQLITE_API double sqlite3_value_double(sqlite3_value*);
|
|
SQLITE_API int sqlite3_value_int(sqlite3_value*);
|
|
SQLITE_API sqlite3_int64 sqlite3_value_int64(sqlite3_value*);
|
|
SQLITE_API void *sqlite3_value_pointer(sqlite3_value*, const char*);
|
|
SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value*);
|
|
SQLITE_API const void *sqlite3_value_text16(sqlite3_value*);
|
|
SQLITE_API const void *sqlite3_value_text16le(sqlite3_value*);
|
|
SQLITE_API const void *sqlite3_value_text16be(sqlite3_value*);
|
|
SQLITE_API int sqlite3_value_bytes(sqlite3_value*);
|
|
SQLITE_API int sqlite3_value_bytes16(sqlite3_value*);
|
|
SQLITE_API int sqlite3_value_type(sqlite3_value*);
|
|
SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
|
|
SQLITE_API int sqlite3_value_nochange(sqlite3_value*);
|
|
SQLITE_API int sqlite3_value_frombind(sqlite3_value*);
|
|
|
|
/*
|
|
** CAPI3REF: Report the internal text encoding state of an sqlite3_value object
|
|
** METHOD: sqlite3_value
|
|
**
|
|
** ^(The sqlite3_value_encoding(X) interface returns one of [SQLITE_UTF8],
|
|
** [SQLITE_UTF16BE], or [SQLITE_UTF16LE] according to the current text encoding
|
|
** of the value X, assuming that X has type TEXT.)^ If sqlite3_value_type(X)
|
|
** returns something other than SQLITE_TEXT, then the return value from
|
|
** sqlite3_value_encoding(X) is meaningless. ^Calls to
|
|
** [sqlite3_value_text(X)], [sqlite3_value_text16(X)], [sqlite3_value_text16be(X)],
|
|
** [sqlite3_value_text16le(X)], [sqlite3_value_bytes(X)], or
|
|
** [sqlite3_value_bytes16(X)] might change the encoding of the value X and
|
|
** thus change the return from subsequent calls to sqlite3_value_encoding(X).
|
|
**
|
|
** This routine is intended for used by applications that test and validate
|
|
** the SQLite implementation. This routine is inquiring about the opaque
|
|
** internal state of an [sqlite3_value] object. Ordinary applications should
|
|
** not need to know what the internal state of an sqlite3_value object is and
|
|
** hence should not need to use this interface.
|
|
*/
|
|
SQLITE_API int sqlite3_value_encoding(sqlite3_value*);
|
|
|
|
/*
|
|
** CAPI3REF: Finding The Subtype Of SQL Values
|
|
** METHOD: sqlite3_value
|
|
**
|
|
** The sqlite3_value_subtype(V) function returns the subtype for
|
|
** an [application-defined SQL function] argument V. The subtype
|
|
** information can be used to pass a limited amount of context from
|
|
** one SQL function to another. Use the [sqlite3_result_subtype()]
|
|
** routine to set the subtype for the return value of an SQL function.
|
|
**
|
|
** Every [application-defined SQL function] that invoke this interface
|
|
** should include the [SQLITE_SUBTYPE] property in the text
|
|
** encoding argument when the function is [sqlite3_create_function|registered].
|
|
** If the [SQLITE_SUBTYPE] property is omitted, then sqlite3_value_subtype()
|
|
** might return zero instead of the upstream subtype in some corner cases.
|
|
*/
|
|
SQLITE_API unsigned int sqlite3_value_subtype(sqlite3_value*);
|
|
|
|
/*
|
|
** CAPI3REF: Copy And Free SQL Values
|
|
** METHOD: sqlite3_value
|
|
**
|
|
** ^The sqlite3_value_dup(V) interface makes a copy of the [sqlite3_value]
|
|
** object D and returns a pointer to that copy. ^The [sqlite3_value] returned
|
|
** is a [protected sqlite3_value] object even if the input is not.
|
|
** ^The sqlite3_value_dup(V) interface returns NULL if V is NULL or if a
|
|
** memory allocation fails. ^If V is a [pointer value], then the result
|
|
** of sqlite3_value_dup(V) is a NULL value.
|
|
**
|
|
** ^The sqlite3_value_free(V) interface frees an [sqlite3_value] object
|
|
** previously obtained from [sqlite3_value_dup()]. ^If V is a NULL pointer
|
|
** then sqlite3_value_free(V) is a harmless no-op.
|
|
*/
|
|
SQLITE_API sqlite3_value *sqlite3_value_dup(const sqlite3_value*);
|
|
SQLITE_API void sqlite3_value_free(sqlite3_value*);
|
|
|
|
/*
|
|
** CAPI3REF: Obtain Aggregate Function Context
|
|
** METHOD: sqlite3_context
|
|
**
|
|
** Implementations of aggregate SQL functions use this
|
|
** routine to allocate memory for storing their state.
|
|
**
|
|
** ^The first time the sqlite3_aggregate_context(C,N) routine is called
|
|
** for a particular aggregate function, SQLite allocates
|
|
** N bytes of memory, zeroes out that memory, and returns a pointer
|
|
** to the new memory. ^On second and subsequent calls to
|
|
** sqlite3_aggregate_context() for the same aggregate function instance,
|
|
** the same buffer is returned. Sqlite3_aggregate_context() is normally
|
|
** called once for each invocation of the xStep callback and then one
|
|
** last time when the xFinal callback is invoked. ^(When no rows match
|
|
** an aggregate query, the xStep() callback of the aggregate function
|
|
** implementation is never called and xFinal() is called exactly once.
|
|
** In those cases, sqlite3_aggregate_context() might be called for the
|
|
** first time from within xFinal().)^
|
|
**
|
|
** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer
|
|
** when first called if N is less than or equal to zero or if a memory
|
|
** allocation error occurs.
|
|
**
|
|
** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
|
|
** determined by the N parameter on first successful call. Changing the
|
|
** value of N in any subsequent call to sqlite3_aggregate_context() within
|
|
** the same aggregate function instance will not resize the memory
|
|
** allocation.)^ Within the xFinal callback, it is customary to set
|
|
** N=0 in calls to sqlite3_aggregate_context(C,N) so that no
|
|
** pointless memory allocations occur.
|
|
**
|
|
** ^SQLite automatically frees the memory allocated by
|
|
** sqlite3_aggregate_context() when the aggregate query concludes.
|
|
**
|
|
** The first parameter must be a copy of the
|
|
** [sqlite3_context | SQL function context] that is the first parameter
|
|
** to the xStep or xFinal callback routine that implements the aggregate
|
|
** function.
|
|
**
|
|
** This routine must be called from the same thread in which
|
|
** the aggregate SQL function is running.
|
|
*/
|
|
SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes);
|
|
|
|
/*
|
|
** CAPI3REF: User Data For Functions
|
|
** METHOD: sqlite3_context
|
|
**
|
|
** ^The sqlite3_user_data() interface returns a copy of
|
|
** the pointer that was the pUserData parameter (the 5th parameter)
|
|
** of the [sqlite3_create_function()]
|
|
** and [sqlite3_create_function16()] routines that originally
|
|
** registered the application defined function.
|
|
**
|
|
** This routine must be called from the same thread in which
|
|
** the application-defined function is running.
|
|
*/
|
|
SQLITE_API void *sqlite3_user_data(sqlite3_context*);
|
|
|
|
/*
|
|
** CAPI3REF: Database Connection For Functions
|
|
** METHOD: sqlite3_context
|
|
**
|
|
** ^The sqlite3_context_db_handle() interface returns a copy of
|
|
** the pointer to the [database connection] (the 1st parameter)
|
|
** of the [sqlite3_create_function()]
|
|
** and [sqlite3_create_function16()] routines that originally
|
|
** registered the application defined function.
|
|
*/
|
|
SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
|
|
|
|
/*
|
|
** CAPI3REF: Function Auxiliary Data
|
|
** METHOD: sqlite3_context
|
|
**
|
|
** These functions may be used by (non-aggregate) SQL functions to
|
|
** associate auxiliary data with argument values. If the same argument
|
|
** value is passed to multiple invocations of the same SQL function during
|
|
** query execution, under some circumstances the associated auxiliary data
|
|
** might be preserved. An example of where this might be useful is in a
|
|
** regular-expression matching function. The compiled version of the regular
|
|
** expression can be stored as auxiliary data associated with the pattern string.
|
|
** Then as long as the pattern string remains the same,
|
|
** the compiled regular expression can be reused on multiple
|
|
** invocations of the same function.
|
|
**
|
|
** ^The sqlite3_get_auxdata(C,N) interface returns a pointer to the auxiliary data
|
|
** associated by the sqlite3_set_auxdata(C,N,P,X) function with the Nth argument
|
|
** value to the application-defined function. ^N is zero for the left-most
|
|
** function argument. ^If there is no auxiliary data
|
|
** associated with the function argument, the sqlite3_get_auxdata(C,N) interface
|
|
** returns a NULL pointer.
|
|
**
|
|
** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as auxiliary data for the
|
|
** N-th argument of the application-defined function. ^Subsequent
|
|
** calls to sqlite3_get_auxdata(C,N) return P from the most recent
|
|
** sqlite3_set_auxdata(C,N,P,X) call if the auxiliary data is still valid or
|
|
** NULL if the auxiliary data has been discarded.
|
|
** ^After each call to sqlite3_set_auxdata(C,N,P,X) where X is not NULL,
|
|
** SQLite will invoke the destructor function X with parameter P exactly
|
|
** once, when the auxiliary data is discarded.
|
|
** SQLite is free to discard the auxiliary data at any time, including: <ul>
|
|
** <li> ^(when the corresponding function parameter changes)^, or
|
|
** <li> ^(when [sqlite3_reset()] or [sqlite3_finalize()] is called for the
|
|
** SQL statement)^, or
|
|
** <li> ^(when sqlite3_set_auxdata() is invoked again on the same
|
|
** parameter)^, or
|
|
** <li> ^(during the original sqlite3_set_auxdata() call when a memory
|
|
** allocation error occurs.)^
|
|
** <li> ^(during the original sqlite3_set_auxdata() call if the function
|
|
** is evaluated during query planning instead of during query execution,
|
|
** as sometimes happens with [SQLITE_ENABLE_STAT4].)^ </ul>
|
|
**
|
|
** Note the last two bullets in particular. The destructor X in
|
|
** sqlite3_set_auxdata(C,N,P,X) might be called immediately, before the
|
|
** sqlite3_set_auxdata() interface even returns. Hence sqlite3_set_auxdata()
|
|
** should be called near the end of the function implementation and the
|
|
** function implementation should not make any use of P after
|
|
** sqlite3_set_auxdata() has been called. Furthermore, a call to
|
|
** sqlite3_get_auxdata() that occurs immediately after a corresponding call
|
|
** to sqlite3_set_auxdata() might still return NULL if an out-of-memory
|
|
** condition occurred during the sqlite3_set_auxdata() call or if the
|
|
** function is being evaluated during query planning rather than during
|
|
** query execution.
|
|
**
|
|
** ^(In practice, auxiliary data is preserved between function calls for
|
|
** function parameters that are compile-time constants, including literal
|
|
** values and [parameters] and expressions composed from the same.)^
|
|
**
|
|
** The value of the N parameter to these interfaces should be non-negative.
|
|
** Future enhancements may make use of negative N values to define new
|
|
** kinds of function caching behavior.
|
|
**
|
|
** These routines must be called from the same thread in which
|
|
** the SQL function is running.
|
|
**
|
|
** See also: [sqlite3_get_clientdata()] and [sqlite3_set_clientdata()].
|
|
*/
|
|
SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N);
|
|
SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*));
|
|
|
|
/*
|
|
** CAPI3REF: Database Connection Client Data
|
|
** METHOD: sqlite3
|
|
**
|
|
** These functions are used to associate one or more named pointers
|
|
** with a [database connection].
|
|
** A call to sqlite3_set_clientdata(D,N,P,X) causes the pointer P
|
|
** to be attached to [database connection] D using name N. Subsequent
|
|
** calls to sqlite3_get_clientdata(D,N) will return a copy of pointer P
|
|
** or a NULL pointer if there were no prior calls to
|
|
** sqlite3_set_clientdata() with the same values of D and N.
|
|
** Names are compared using strcmp() and are thus case sensitive.
|
|
**
|
|
** If P and X are both non-NULL, then the destructor X is invoked with
|
|
** argument P on the first of the following occurrences:
|
|
** <ul>
|
|
** <li> An out-of-memory error occurs during the call to
|
|
** sqlite3_set_clientdata() which attempts to register pointer P.
|
|
** <li> A subsequent call to sqlite3_set_clientdata(D,N,P,X) is made
|
|
** with the same D and N parameters.
|
|
** <li> The database connection closes. SQLite does not make any guarantees
|
|
** about the order in which destructors are called, only that all
|
|
** destructors will be called exactly once at some point during the
|
|
** database connection closing process.
|
|
** </ul>
|
|
**
|
|
** SQLite does not do anything with client data other than invoke
|
|
** destructors on the client data at the appropriate time. The intended
|
|
** use for client data is to provide a mechanism for wrapper libraries
|
|
** to store additional information about an SQLite database connection.
|
|
**
|
|
** There is no limit (other than available memory) on the number of different
|
|
** client data pointers (with different names) that can be attached to a
|
|
** single database connection. However, the implementation is optimized
|
|
** for the case of having only one or two different client data names.
|
|
** Applications and wrapper libraries are discouraged from using more than
|
|
** one client data name each.
|
|
**
|
|
** There is no way to enumerate the client data pointers
|
|
** associated with a database connection. The N parameter can be thought
|
|
** of as a secret key such that only code that knows the secret key is able
|
|
** to access the associated data.
|
|
**
|
|
** Security Warning: These interfaces should not be exposed in scripting
|
|
** languages or in other circumstances where it might be possible for an
|
|
** an attacker to invoke them. Any agent that can invoke these interfaces
|
|
** can probably also take control of the process.
|
|
**
|
|
** Database connection client data is only available for SQLite
|
|
** version 3.44.0 ([dateof:3.44.0]) and later.
|
|
**
|
|
** See also: [sqlite3_set_auxdata()] and [sqlite3_get_auxdata()].
|
|
*/
|
|
SQLITE_API void *sqlite3_get_clientdata(sqlite3*,const char*);
|
|
SQLITE_API int sqlite3_set_clientdata(sqlite3*, const char*, void*, void(*)(void*));
|
|
|
|
/*
|
|
** CAPI3REF: Constants Defining Special Destructor Behavior
|
|
**
|
|
** These are special values 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.
|
|
*/
|
|
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
|
|
** METHOD: sqlite3_context
|
|
**
|
|
** 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 [parameter binding] family of
|
|
** functions used to bind values to host parameters in prepared statements.
|
|
** Refer to the [SQL parameter] documentation for additional information.
|
|
**
|
|
** ^The sqlite3_result_blob() interface sets the result from
|
|
** an application-defined function to be the BLOB whose content is pointed
|
|
** to by the second parameter and which is N bytes long where N is the
|
|
** third parameter.
|
|
**
|
|
** ^The sqlite3_result_zeroblob(C,N) and sqlite3_result_zeroblob64(C,N)
|
|
** interfaces set the result of the application-defined function to be
|
|
** a BLOB containing all zero bytes and N bytes in size.
|
|
**
|
|
** ^The sqlite3_result_double() interface sets the result from
|
|
** an application-defined function to be a floating point value specified
|
|
** by its 2nd argument.
|
|
**
|
|
** ^The sqlite3_result_error() and sqlite3_result_error16() functions
|
|
** cause the implemented SQL function to throw an exception.
|
|
** ^SQLite uses the string pointed to by the
|
|
** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16()
|
|
** as the text of an error message. ^SQLite interprets the error
|
|
** message string from sqlite3_result_error() as UTF-8. ^SQLite
|
|
** interprets the string from sqlite3_result_error16() as UTF-16 using
|
|
** the same [byte-order determination rules] as [sqlite3_bind_text16()].
|
|
** ^If the third parameter to sqlite3_result_error()
|
|
** or sqlite3_result_error16() is negative then SQLite takes as the error
|
|
** message all text up through the first zero character.
|
|
** ^If the third parameter to sqlite3_result_error() or
|
|
** sqlite3_result_error16() is non-negative then SQLite takes that many
|
|
** bytes (not characters) from the 2nd parameter as the error message.
|
|
** ^The sqlite3_result_error() and sqlite3_result_error16()
|
|
** routines make a private copy of the error message text before
|
|
** they return. Hence, the calling function can deallocate or
|
|
** modify the text after they return without harm.
|
|
** ^The sqlite3_result_error_code() function changes the error code
|
|
** returned by SQLite as a result of an error in a function. ^By default,
|
|
** the error code is SQLITE_ERROR. ^A subsequent call to sqlite3_result_error()
|
|
** or sqlite3_result_error16() resets the error code to SQLITE_ERROR.
|
|
**
|
|
** ^The sqlite3_result_error_toobig() interface causes SQLite to throw an
|
|
** error indicating that a string or BLOB is too long to represent.
|
|
**
|
|
** ^The sqlite3_result_error_nomem() interface causes SQLite to throw an
|
|
** error indicating that a memory allocation failed.
|
|
**
|
|
** ^The sqlite3_result_int() interface sets the return value
|
|
** of the application-defined function to be the 32-bit signed integer
|
|
** value given in the 2nd argument.
|
|
** ^The sqlite3_result_int64() interface sets the return value
|
|
** of the application-defined function to be the 64-bit signed integer
|
|
** value given in the 2nd argument.
|
|
**
|
|
** ^The sqlite3_result_null() interface sets the return value
|
|
** of the application-defined function to be NULL.
|
|
**
|
|
** ^The sqlite3_result_text(), sqlite3_result_text16(),
|
|
** sqlite3_result_text16le(), and sqlite3_result_text16be() interfaces
|
|
** set the return value of the application-defined function to be
|
|
** a text string which is represented as UTF-8, UTF-16 native byte order,
|
|
** UTF-16 little endian, or UTF-16 big endian, respectively.
|
|
** ^The sqlite3_result_text64() interface sets the return value of an
|
|
** application-defined function to be a text string in an encoding
|
|
** specified by the fifth (and last) parameter, which must be one
|
|
** of [SQLITE_UTF8], [SQLITE_UTF16], [SQLITE_UTF16BE], or [SQLITE_UTF16LE].
|
|
** ^SQLite takes the text result from the application from
|
|
** the 2nd parameter of the sqlite3_result_text* interfaces.
|
|
** ^If the 3rd parameter to any of the sqlite3_result_text* interfaces
|
|
** other than sqlite3_result_text64() is negative, then SQLite computes
|
|
** the string length itself by searching the 2nd parameter for the first
|
|
** zero character.
|
|
** ^If the 3rd parameter to the sqlite3_result_text* interfaces
|
|
** is non-negative, then as many bytes (not characters) of the text
|
|
** pointed to by the 2nd parameter are taken as the application-defined
|
|
** function result. If the 3rd parameter is non-negative, then it
|
|
** must be the byte offset into the string where the NUL terminator would
|
|
** appear if the string where NUL terminated. If any NUL characters occur
|
|
** in the string at a byte offset that is less than the value of the 3rd
|
|
** parameter, then the resulting string will contain embedded NULs and the
|
|
** result of expressions operating on strings with embedded NULs is undefined.
|
|
** ^If the 4th parameter to the sqlite3_result_text* interfaces
|
|
** or sqlite3_result_blob is a non-NULL pointer, then SQLite calls that
|
|
** function as the destructor on the text or BLOB result when it has
|
|
** finished using that result.
|
|
** ^If the 4th parameter to the sqlite3_result_text* interfaces or to
|
|
** sqlite3_result_blob is the special constant SQLITE_STATIC, then SQLite
|
|
** assumes that the text or BLOB result is in constant space and does not
|
|
** copy the content of the parameter nor call a destructor on the content
|
|
** when it has finished using that result.
|
|
** ^If the 4th parameter to the sqlite3_result_text* interfaces
|
|
** or sqlite3_result_blob is the special constant SQLITE_TRANSIENT
|
|
** then SQLite makes a copy of the result into space obtained
|
|
** from [sqlite3_malloc()] before it returns.
|
|
**
|
|
** ^For the sqlite3_result_text16(), sqlite3_result_text16le(), and
|
|
** sqlite3_result_text16be() routines, and for sqlite3_result_text64()
|
|
** when the encoding is not UTF8, if the input UTF16 begins with a
|
|
** byte-order mark (BOM, U+FEFF) then the BOM is removed from the
|
|
** string and the rest of the string is interpreted according to the
|
|
** byte-order specified by the BOM. ^The byte-order specified by
|
|
** the BOM at the beginning of the text overrides the byte-order
|
|
** specified by the interface procedure. ^So, for example, if
|
|
** sqlite3_result_text16le() is invoked with text that begins
|
|
** with bytes 0xfe, 0xff (a big-endian byte-order mark) then the
|
|
** first two bytes of input are skipped and the remaining input
|
|
** is interpreted as UTF16BE text.
|
|
**
|
|
** ^For UTF16 input text to the sqlite3_result_text16(),
|
|
** sqlite3_result_text16be(), sqlite3_result_text16le(), and
|
|
** sqlite3_result_text64() routines, if the text contains invalid
|
|
** UTF16 characters, the invalid characters might be converted
|
|
** into the unicode replacement character, U+FFFD.
|
|
**
|
|
** ^The sqlite3_result_value() interface sets the result of
|
|
** the application-defined function to be a copy of the
|
|
** [unprotected sqlite3_value] object specified by the 2nd parameter. ^The
|
|
** sqlite3_result_value() interface makes a copy of the [sqlite3_value]
|
|
** so that the [sqlite3_value] specified in the parameter may change or
|
|
** be deallocated after sqlite3_result_value() returns without harm.
|
|
** ^A [protected sqlite3_value] object may always be used where an
|
|
** [unprotected sqlite3_value] object is required, so either
|
|
** kind of [sqlite3_value] object can be used with this interface.
|
|
**
|
|
** ^The sqlite3_result_pointer(C,P,T,D) interface sets the result to an
|
|
** SQL NULL value, just like [sqlite3_result_null(C)], except that it
|
|
** also associates the host-language pointer P or type T with that
|
|
** NULL value such that the pointer can be retrieved within an
|
|
** [application-defined SQL function] using [sqlite3_value_pointer()].
|
|
** ^If the D parameter is not NULL, then it is a pointer to a destructor
|
|
** for the P parameter. ^SQLite invokes D with P as its only argument
|
|
** when SQLite is finished with P. The T parameter should be a static
|
|
** string and preferably a string literal. The sqlite3_result_pointer()
|
|
** routine is part of the [pointer passing interface] added for SQLite 3.20.0.
|
|
**
|
|
** If these routines are called from within the different thread
|
|
** than the one containing the application-defined function that received
|
|
** the [sqlite3_context] pointer, the results are undefined.
|
|
*/
|
|
SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
|
|
SQLITE_API void sqlite3_result_blob64(sqlite3_context*,const void*,
|
|
sqlite3_uint64,void(*)(void*));
|
|
SQLITE_API void sqlite3_result_double(sqlite3_context*, double);
|
|
SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int);
|
|
SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int);
|
|
SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*);
|
|
SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*);
|
|
SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int);
|
|
SQLITE_API void sqlite3_result_int(sqlite3_context*, int);
|
|
SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64);
|
|
SQLITE_API void sqlite3_result_null(sqlite3_context*);
|
|
SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
|
|
SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64,
|
|
void(*)(void*), unsigned char encoding);
|
|
SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
|
|
SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
|
|
SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
|
|
SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
|
|
SQLITE_API void sqlite3_result_pointer(sqlite3_context*, void*,const char*,void(*)(void*));
|
|
SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n);
|
|
SQLITE_API int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n);
|
|
|
|
|
|
/*
|
|
** CAPI3REF: Setting The Subtype Of An SQL Function
|
|
** METHOD: sqlite3_context
|
|
**
|
|
** The sqlite3_result_subtype(C,T) function causes the subtype of
|
|
** the result from the [application-defined SQL function] with
|
|
** [sqlite3_context] C to be the value T. Only the lower 8 bits
|
|
** of the subtype T are preserved in current versions of SQLite;
|
|
** higher order bits are discarded.
|
|
** The number of subtype bytes preserved by SQLite might increase
|
|
** in future releases of SQLite.
|
|
**
|
|
** Every [application-defined SQL function] that invokes this interface
|
|
** should include the [SQLITE_RESULT_SUBTYPE] property in its
|
|
** text encoding argument when the SQL function is
|
|
** [sqlite3_create_function|registered]. If the [SQLITE_RESULT_SUBTYPE]
|
|
** property is omitted from the function that invokes sqlite3_result_subtype(),
|
|
** then in some cases the sqlite3_result_subtype() might fail to set
|
|
** the result subtype.
|
|
**
|
|
** If SQLite is compiled with -DSQLITE_STRICT_SUBTYPE=1, then any
|
|
** SQL function that invokes the sqlite3_result_subtype() interface
|
|
** and that does not have the SQLITE_RESULT_SUBTYPE property will raise
|
|
** an error. Future versions of SQLite might enable -DSQLITE_STRICT_SUBTYPE=1
|
|
** by default.
|
|
*/
|
|
SQLITE_API void sqlite3_result_subtype(sqlite3_context*,unsigned int);
|
|
|
|
/*
|
|
** CAPI3REF: Define New Collating Sequences
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^These functions add, remove, or modify a [collation] associated
|
|
** with the [database connection] specified as the first argument.
|
|
**
|
|
** ^The name of the collation is a UTF-8 string
|
|
** for sqlite3_create_collation() and sqlite3_create_collation_v2()
|
|
** and a UTF-16 string in native byte order for sqlite3_create_collation16().
|
|
** ^Collation names that compare equal according to [sqlite3_strnicmp()] are
|
|
** considered to be the same name.
|
|
**
|
|
** ^(The third argument (eTextRep) must be one of the constants:
|
|
** <ul>
|
|
** <li> [SQLITE_UTF8],
|
|
** <li> [SQLITE_UTF16LE],
|
|
** <li> [SQLITE_UTF16BE],
|
|
** <li> [SQLITE_UTF16], or
|
|
** <li> [SQLITE_UTF16_ALIGNED].
|
|
** </ul>)^
|
|
** ^The eTextRep argument determines the encoding of strings passed
|
|
** to the collating function callback, xCompare.
|
|
** ^The [SQLITE_UTF16] and [SQLITE_UTF16_ALIGNED] values for eTextRep
|
|
** force strings to be UTF16 with native byte order.
|
|
** ^The [SQLITE_UTF16_ALIGNED] value for eTextRep forces strings to begin
|
|
** on an even byte address.
|
|
**
|
|
** ^The fourth argument, pArg, is an application data pointer that is passed
|
|
** through as the first argument to the collating function callback.
|
|
**
|
|
** ^The fifth argument, xCompare, is a pointer to the collating function.
|
|
** ^Multiple collating functions can be registered using the same name but
|
|
** with different eTextRep parameters and SQLite will use whichever
|
|
** function requires the least amount of data transformation.
|
|
** ^If the xCompare argument is NULL then the collating function is
|
|
** deleted. ^When all collating functions having the same name are deleted,
|
|
** that collation is no longer usable.
|
|
**
|
|
** ^The collating function callback is invoked with a copy of the pArg
|
|
** application data pointer and with two strings in the encoding specified
|
|
** by the eTextRep argument. The two integer parameters to the collating
|
|
** function callback are the length of the two strings, in bytes. The collating
|
|
** function must return an integer that is negative, zero, or positive
|
|
** if the first string is less than, equal to, or greater than the second,
|
|
** respectively. A collating function must always return the same answer
|
|
** given the same inputs. If two or more collating functions are registered
|
|
** to the same collation name (using different eTextRep values) then all
|
|
** must give an equivalent answer when invoked with equivalent strings.
|
|
** The collating function must obey the following properties for all
|
|
** strings A, B, and C:
|
|
**
|
|
** <ol>
|
|
** <li> If A==B then B==A.
|
|
** <li> If A==B and B==C then A==C.
|
|
** <li> If A<B THEN B>A.
|
|
** <li> If A<B and B<C then A<C.
|
|
** </ol>
|
|
**
|
|
** If a collating function fails any of the above constraints and that
|
|
** collating function is registered and used, then the behavior of SQLite
|
|
** is undefined.
|
|
**
|
|
** ^The sqlite3_create_collation_v2() works like sqlite3_create_collation()
|
|
** with the addition that the xDestroy callback is invoked on pArg when
|
|
** the collating function is deleted.
|
|
** ^Collating functions are deleted when they are overridden by later
|
|
** calls to the collation creation functions or when the
|
|
** [database connection] is closed using [sqlite3_close()].
|
|
**
|
|
** ^The xDestroy callback is <u>not</u> called if the
|
|
** sqlite3_create_collation_v2() function fails. Applications that invoke
|
|
** sqlite3_create_collation_v2() with a non-NULL xDestroy argument should
|
|
** check the return code and dispose of the application data pointer
|
|
** themselves rather than expecting SQLite to deal with it for them.
|
|
** This is different from every other SQLite interface. The inconsistency
|
|
** is unfortunate but cannot be changed without breaking backwards
|
|
** compatibility.
|
|
**
|
|
** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()].
|
|
*/
|
|
SQLITE_API int sqlite3_create_collation(
|
|
sqlite3*,
|
|
const char *zName,
|
|
int eTextRep,
|
|
void *pArg,
|
|
int(*xCompare)(void*,int,const void*,int,const void*)
|
|
);
|
|
SQLITE_API int sqlite3_create_collation_v2(
|
|
sqlite3*,
|
|
const char *zName,
|
|
int eTextRep,
|
|
void *pArg,
|
|
int(*xCompare)(void*,int,const void*,int,const void*),
|
|
void(*xDestroy)(void*)
|
|
);
|
|
SQLITE_API int sqlite3_create_collation16(
|
|
sqlite3*,
|
|
const void *zName,
|
|
int eTextRep,
|
|
void *pArg,
|
|
int(*xCompare)(void*,int,const void*,int,const void*)
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Collation Needed Callbacks
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^To avoid having to register all collation sequences before a database
|
|
** can be used, a single callback function may be registered with the
|
|
** [database connection] to be invoked 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 the existing collation-needed 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
|
|
** connection. 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()].
|
|
*/
|
|
SQLITE_API int sqlite3_collation_needed(
|
|
sqlite3*,
|
|
void*,
|
|
void(*)(void*,sqlite3*,int eTextRep,const char*)
|
|
);
|
|
SQLITE_API int sqlite3_collation_needed16(
|
|
sqlite3*,
|
|
void*,
|
|
void(*)(void*,sqlite3*,int eTextRep,const void*)
|
|
);
|
|
|
|
#ifdef SQLITE_ENABLE_CEROD
|
|
/*
|
|
** Specify the activation key for a CEROD database. Unless
|
|
** activated, none of the CEROD routines will work.
|
|
*/
|
|
SQLITE_API void sqlite3_activate_cerod(
|
|
const char *zPassPhrase /* Activation phrase */
|
|
);
|
|
#endif
|
|
|
|
/*
|
|
** CAPI3REF: Suspend Execution For A Short Time
|
|
**
|
|
** The sqlite3_sleep() function causes the current thread to suspend execution
|
|
** for at least 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.
|
|
**
|
|
** ^SQLite implements this interface by calling the xSleep()
|
|
** method of the default [sqlite3_vfs] object. If the xSleep() method
|
|
** of the default VFS is not implemented correctly, or not implemented at
|
|
** all, then the behavior of sqlite3_sleep() may deviate from the description
|
|
** in the previous paragraphs.
|
|
**
|
|
** If a negative argument is passed to sqlite3_sleep() the results vary by
|
|
** VFS and operating system. Some system treat a negative argument as an
|
|
** instruction to sleep forever. Others understand it to mean do not sleep
|
|
** at all. ^In SQLite version 3.42.0 and later, a negative
|
|
** argument passed into sqlite3_sleep() is changed to zero before it is relayed
|
|
** down into the xSleep method of the VFS.
|
|
*/
|
|
SQLITE_API 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.k.a. directory), then all temporary files
|
|
** created by SQLite when using a built-in [sqlite3_vfs | VFS]
|
|
** will be placed in that directory.)^ ^If this variable
|
|
** is a NULL pointer, then SQLite performs a search for an appropriate
|
|
** temporary file directory.
|
|
**
|
|
** Applications are strongly discouraged from using this global variable.
|
|
** It is required to set a temporary folder on Windows Runtime (WinRT).
|
|
** But for all other platforms, it is highly recommended that applications
|
|
** neither read nor write this variable. This global variable is a relic
|
|
** that exists for backwards compatibility of legacy applications and should
|
|
** be avoided in new projects.
|
|
**
|
|
** It is not safe to read or modify this variable in more than one
|
|
** thread at a time. It is not safe to read or modify this variable
|
|
** if a [database connection] is being used at the same time in a separate
|
|
** thread.
|
|
** It is intended that this variable be set once
|
|
** as part of process initialization and before any SQLite interface
|
|
** routines have been called and that this variable remain unchanged
|
|
** thereafter.
|
|
**
|
|
** ^The [temp_store_directory pragma] may modify this variable and cause
|
|
** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore,
|
|
** the [temp_store_directory pragma] always assumes that any string
|
|
** that this variable points to is held in memory obtained from
|
|
** [sqlite3_malloc] and the pragma may attempt to free that memory
|
|
** using [sqlite3_free].
|
|
** Hence, if this variable is modified directly, either it should be
|
|
** made NULL or made to point to memory obtained from [sqlite3_malloc]
|
|
** or else the use of the [temp_store_directory pragma] should be avoided.
|
|
** Except when requested by the [temp_store_directory pragma], SQLite
|
|
** does not free the memory that sqlite3_temp_directory points to. If
|
|
** the application wants that memory to be freed, it must do
|
|
** so itself, taking care to only do so after all [database connection]
|
|
** objects have been destroyed.
|
|
**
|
|
** <b>Note to Windows Runtime users:</b> The temporary directory must be set
|
|
** prior to calling [sqlite3_open] or [sqlite3_open_v2]. Otherwise, various
|
|
** features that require the use of temporary files may fail. Here is an
|
|
** example of how to do this using C++ with the Windows Runtime:
|
|
**
|
|
** <blockquote><pre>
|
|
** LPCWSTR zPath = Windows::Storage::ApplicationData::Current->
|
|
** TemporaryFolder->Path->Data();
|
|
** char zPathBuf[MAX_PATH + 1];
|
|
** memset(zPathBuf, 0, sizeof(zPathBuf));
|
|
** WideCharToMultiByte(CP_UTF8, 0, zPath, -1, zPathBuf, sizeof(zPathBuf),
|
|
** NULL, NULL);
|
|
** sqlite3_temp_directory = sqlite3_mprintf("%s", zPathBuf);
|
|
** </pre></blockquote>
|
|
*/
|
|
SQLITE_API char *sqlite3_temp_directory;
|
|
|
|
/*
|
|
** CAPI3REF: Name Of The Folder Holding Database Files
|
|
**
|
|
** ^(If this global variable is made to point to a string which is
|
|
** the name of a folder (a.k.a. directory), then all database files
|
|
** specified with a relative pathname and created or accessed by
|
|
** SQLite when using a built-in windows [sqlite3_vfs | VFS] will be assumed
|
|
** to be relative to that directory.)^ ^If this variable is a NULL
|
|
** pointer, then SQLite assumes that all database files specified
|
|
** with a relative pathname are relative to the current directory
|
|
** for the process. Only the windows VFS makes use of this global
|
|
** variable; it is ignored by the unix VFS.
|
|
**
|
|
** Changing the value of this variable while a database connection is
|
|
** open can result in a corrupt database.
|
|
**
|
|
** It is not safe to read or modify this variable in more than one
|
|
** thread at a time. It is not safe to read or modify this variable
|
|
** if a [database connection] is being used at the same time in a separate
|
|
** thread.
|
|
** It is intended that this variable be set once
|
|
** as part of process initialization and before any SQLite interface
|
|
** routines have been called and that this variable remain unchanged
|
|
** thereafter.
|
|
**
|
|
** ^The [data_store_directory pragma] may modify this variable and cause
|
|
** it to point to memory obtained from [sqlite3_malloc]. ^Furthermore,
|
|
** the [data_store_directory pragma] always assumes that any string
|
|
** that this variable points to is held in memory obtained from
|
|
** [sqlite3_malloc] and the pragma may attempt to free that memory
|
|
** using [sqlite3_free].
|
|
** Hence, if this variable is modified directly, either it should be
|
|
** made NULL or made to point to memory obtained from [sqlite3_malloc]
|
|
** or else the use of the [data_store_directory pragma] should be avoided.
|
|
*/
|
|
SQLITE_API char *sqlite3_data_directory;
|
|
|
|
/*
|
|
** CAPI3REF: Win32 Specific Interface
|
|
**
|
|
** These interfaces are available only on Windows. The
|
|
** [sqlite3_win32_set_directory] interface is used to set the value associated
|
|
** with the [sqlite3_temp_directory] or [sqlite3_data_directory] variable, to
|
|
** zValue, depending on the value of the type parameter. The zValue parameter
|
|
** should be NULL to cause the previous value to be freed via [sqlite3_free];
|
|
** a non-NULL value will be copied into memory obtained from [sqlite3_malloc]
|
|
** prior to being used. The [sqlite3_win32_set_directory] interface returns
|
|
** [SQLITE_OK] to indicate success, [SQLITE_ERROR] if the type is unsupported,
|
|
** or [SQLITE_NOMEM] if memory could not be allocated. The value of the
|
|
** [sqlite3_data_directory] variable is intended to act as a replacement for
|
|
** the current directory on the sub-platforms of Win32 where that concept is
|
|
** not present, e.g. WinRT and UWP. The [sqlite3_win32_set_directory8] and
|
|
** [sqlite3_win32_set_directory16] interfaces behave exactly the same as the
|
|
** sqlite3_win32_set_directory interface except the string parameter must be
|
|
** UTF-8 or UTF-16, respectively.
|
|
*/
|
|
SQLITE_API int sqlite3_win32_set_directory(
|
|
unsigned long type, /* Identifier for directory being set or reset */
|
|
void *zValue /* New value for directory being set or reset */
|
|
);
|
|
SQLITE_API int sqlite3_win32_set_directory8(unsigned long type, const char *zValue);
|
|
SQLITE_API int sqlite3_win32_set_directory16(unsigned long type, const void *zValue);
|
|
|
|
/*
|
|
** CAPI3REF: Win32 Directory Types
|
|
**
|
|
** These macros are only available on Windows. They define the allowed values
|
|
** for the type argument to the [sqlite3_win32_set_directory] interface.
|
|
*/
|
|
#define SQLITE_WIN32_DATA_DIRECTORY_TYPE 1
|
|
#define SQLITE_WIN32_TEMP_DIRECTORY_TYPE 2
|
|
|
|
/*
|
|
** CAPI3REF: Test For Auto-Commit Mode
|
|
** KEYWORDS: {autocommit mode}
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^The sqlite3_get_autocommit() interface returns non-zero or
|
|
** zero if the given database connection is or is not in autocommit mode,
|
|
** respectively. ^Autocommit mode is on by default.
|
|
** ^Autocommit mode is disabled by a [BEGIN] statement.
|
|
** ^Autocommit mode is re-enabled by a [COMMIT] or [ROLLBACK].
|
|
**
|
|
** If certain kinds of errors occur on a statement within a multi-statement
|
|
** transaction (errors including [SQLITE_FULL], [SQLITE_IOERR],
|
|
** [SQLITE_NOMEM], [SQLITE_BUSY], and [SQLITE_INTERRUPT]) then the
|
|
** transaction might be rolled back automatically. The only way to
|
|
** find out whether SQLite automatically rolled back the transaction after
|
|
** an error is to use this function.
|
|
**
|
|
** If another thread changes the autocommit status of the database
|
|
** connection while this routine is running, then the return value
|
|
** is undefined.
|
|
*/
|
|
SQLITE_API int sqlite3_get_autocommit(sqlite3*);
|
|
|
|
/*
|
|
** CAPI3REF: Find The Database Handle Of A Prepared Statement
|
|
** METHOD: sqlite3_stmt
|
|
**
|
|
** ^The sqlite3_db_handle interface returns the [database connection] handle
|
|
** to which a [prepared statement] belongs. ^The [database connection]
|
|
** returned by sqlite3_db_handle is the same [database connection]
|
|
** that was the first argument
|
|
** to the [sqlite3_prepare_v2()] call (or its variants) that was used to
|
|
** create the statement in the first place.
|
|
*/
|
|
SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
|
|
|
|
/*
|
|
** CAPI3REF: Return The Schema Name For A Database Connection
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^The sqlite3_db_name(D,N) interface returns a pointer to the schema name
|
|
** for the N-th database on database connection D, or a NULL pointer of N is
|
|
** out of range. An N value of 0 means the main database file. An N of 1 is
|
|
** the "temp" schema. Larger values of N correspond to various ATTACH-ed
|
|
** databases.
|
|
**
|
|
** Space to hold the string that is returned by sqlite3_db_name() is managed
|
|
** by SQLite itself. The string might be deallocated by any operation that
|
|
** changes the schema, including [ATTACH] or [DETACH] or calls to
|
|
** [sqlite3_serialize()] or [sqlite3_deserialize()], even operations that
|
|
** occur on a different thread. Applications that need to
|
|
** remember the string long-term should make their own copy. Applications that
|
|
** are accessing the same database connection simultaneously on multiple
|
|
** threads should mutex-protect calls to this API and should make their own
|
|
** private copy of the result prior to releasing the mutex.
|
|
*/
|
|
SQLITE_API const char *sqlite3_db_name(sqlite3 *db, int N);
|
|
|
|
/*
|
|
** CAPI3REF: Return The Filename For A Database Connection
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^The sqlite3_db_filename(D,N) interface returns a pointer to the filename
|
|
** associated with database N of connection D.
|
|
** ^If there is no attached database N on the database
|
|
** connection D, or if database N is a temporary or in-memory database, then
|
|
** this function will return either a NULL pointer or an empty string.
|
|
**
|
|
** ^The string value returned by this routine is owned and managed by
|
|
** the database connection. ^The value will be valid until the database N
|
|
** is [DETACH]-ed or until the database connection closes.
|
|
**
|
|
** ^The filename returned by this function is the output of the
|
|
** xFullPathname method of the [VFS]. ^In other words, the filename
|
|
** will be an absolute pathname, even if the filename used
|
|
** to open the database originally was a URI or relative pathname.
|
|
**
|
|
** If the filename pointer returned by this routine is not NULL, then it
|
|
** can be used as the filename input parameter to these routines:
|
|
** <ul>
|
|
** <li> [sqlite3_uri_parameter()]
|
|
** <li> [sqlite3_uri_boolean()]
|
|
** <li> [sqlite3_uri_int64()]
|
|
** <li> [sqlite3_filename_database()]
|
|
** <li> [sqlite3_filename_journal()]
|
|
** <li> [sqlite3_filename_wal()]
|
|
** </ul>
|
|
*/
|
|
SQLITE_API sqlite3_filename sqlite3_db_filename(sqlite3 *db, const char *zDbName);
|
|
|
|
/*
|
|
** CAPI3REF: Determine if a database is read-only
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N
|
|
** of connection D is read-only, 0 if it is read/write, or -1 if N is not
|
|
** the name of a database on connection D.
|
|
*/
|
|
SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
|
|
|
|
/*
|
|
** CAPI3REF: Determine the transaction state of a database
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^The sqlite3_txn_state(D,S) interface returns the current
|
|
** [transaction state] of schema S in database connection D. ^If S is NULL,
|
|
** then the highest transaction state of any schema on database connection D
|
|
** is returned. Transaction states are (in order of lowest to highest):
|
|
** <ol>
|
|
** <li value="0"> SQLITE_TXN_NONE
|
|
** <li value="1"> SQLITE_TXN_READ
|
|
** <li value="2"> SQLITE_TXN_WRITE
|
|
** </ol>
|
|
** ^If the S argument to sqlite3_txn_state(D,S) is not the name of
|
|
** a valid schema, then -1 is returned.
|
|
*/
|
|
SQLITE_API int sqlite3_txn_state(sqlite3*,const char *zSchema);
|
|
|
|
/*
|
|
** CAPI3REF: Allowed return values from sqlite3_txn_state()
|
|
** KEYWORDS: {transaction state}
|
|
**
|
|
** These constants define the current transaction state of a database file.
|
|
** ^The [sqlite3_txn_state(D,S)] interface returns one of these
|
|
** constants in order to describe the transaction state of schema S
|
|
** in [database connection] D.
|
|
**
|
|
** <dl>
|
|
** [[SQLITE_TXN_NONE]] <dt>SQLITE_TXN_NONE</dt>
|
|
** <dd>The SQLITE_TXN_NONE state means that no transaction is currently
|
|
** pending.</dd>
|
|
**
|
|
** [[SQLITE_TXN_READ]] <dt>SQLITE_TXN_READ</dt>
|
|
** <dd>The SQLITE_TXN_READ state means that the database is currently
|
|
** in a read transaction. Content has been read from the database file
|
|
** but nothing in the database file has changed. The transaction state
|
|
** will advanced to SQLITE_TXN_WRITE if any changes occur and there are
|
|
** no other conflicting concurrent write transactions. The transaction
|
|
** state will revert to SQLITE_TXN_NONE following a [ROLLBACK] or
|
|
** [COMMIT].</dd>
|
|
**
|
|
** [[SQLITE_TXN_WRITE]] <dt>SQLITE_TXN_WRITE</dt>
|
|
** <dd>The SQLITE_TXN_WRITE state means that the database is currently
|
|
** in a write transaction. Content has been written to the database file
|
|
** but has not yet committed. The transaction state will change to
|
|
** to SQLITE_TXN_NONE at the next [ROLLBACK] or [COMMIT].</dd>
|
|
*/
|
|
#define SQLITE_TXN_NONE 0
|
|
#define SQLITE_TXN_READ 1
|
|
#define SQLITE_TXN_WRITE 2
|
|
|
|
/*
|
|
** CAPI3REF: Find the next prepared statement
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^This interface returns a pointer to the next [prepared statement] after
|
|
** pStmt associated with the [database connection] pDb. ^If pStmt is NULL
|
|
** then this interface returns a pointer to the first prepared statement
|
|
** associated with the database connection pDb. ^If no prepared statement
|
|
** satisfies the conditions of this routine, it returns NULL.
|
|
**
|
|
** The [database connection] pointer D in a call to
|
|
** [sqlite3_next_stmt(D,S)] must refer to an open database
|
|
** connection and in particular must not be a NULL pointer.
|
|
*/
|
|
SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt);
|
|
|
|
/*
|
|
** CAPI3REF: Commit And Rollback Notification Callbacks
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^The sqlite3_commit_hook() interface registers a callback
|
|
** function to be invoked whenever a transaction is [COMMIT | committed].
|
|
** ^Any callback set by a previous call to sqlite3_commit_hook()
|
|
** for the same database connection is overridden.
|
|
** ^The sqlite3_rollback_hook() interface registers a callback
|
|
** function to be invoked whenever a transaction is [ROLLBACK | rolled back].
|
|
** ^Any callback set by a previous call to sqlite3_rollback_hook()
|
|
** for the same database connection is overridden.
|
|
** ^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.
|
|
**
|
|
** ^The sqlite3_commit_hook(D,C,P) and sqlite3_rollback_hook(D,C,P) functions
|
|
** return the P argument from the previous call of the same function
|
|
** on the same [database connection] D, or NULL for
|
|
** the first call for each function on D.
|
|
**
|
|
** The commit and rollback hook callbacks are not reentrant.
|
|
** The callback implementation must not do anything that will modify
|
|
** the database connection that invoked the callback. Any actions
|
|
** to modify the database connection must be deferred until after the
|
|
** completion of the [sqlite3_step()] call that triggered the commit
|
|
** or rollback hook in the first place.
|
|
** Note that running any other SQL statements, including SELECT statements,
|
|
** or merely calling [sqlite3_prepare_v2()] and [sqlite3_step()] will modify
|
|
** the database connections for the meaning of "modify" in this paragraph.
|
|
**
|
|
** ^Registering a NULL function disables the callback.
|
|
**
|
|
** ^When the commit hook callback routine returns zero, the [COMMIT]
|
|
** operation is allowed to continue normally. ^If the commit hook
|
|
** returns non-zero, then the [COMMIT] is converted into a [ROLLBACK].
|
|
** ^The rollback hook is invoked on a rollback that results from a commit
|
|
** hook returning non-zero, just as it would be with any other rollback.
|
|
**
|
|
** ^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 rollback callback is not invoked if a transaction is
|
|
** automatically rolled back because the database connection is closed.
|
|
**
|
|
** See also the [sqlite3_update_hook()] interface.
|
|
*/
|
|
SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*);
|
|
SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
|
|
|
|
/*
|
|
** CAPI3REF: Autovacuum Compaction Amount Callback
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^The sqlite3_autovacuum_pages(D,C,P,X) interface registers a callback
|
|
** function C that is invoked prior to each autovacuum of the database
|
|
** file. ^The callback is passed a copy of the generic data pointer (P),
|
|
** the schema-name of the attached database that is being autovacuumed,
|
|
** the size of the database file in pages, the number of free pages,
|
|
** and the number of bytes per page, respectively. The callback should
|
|
** return the number of free pages that should be removed by the
|
|
** autovacuum. ^If the callback returns zero, then no autovacuum happens.
|
|
** ^If the value returned is greater than or equal to the number of
|
|
** free pages, then a complete autovacuum happens.
|
|
**
|
|
** <p>^If there are multiple ATTACH-ed database files that are being
|
|
** modified as part of a transaction commit, then the autovacuum pages
|
|
** callback is invoked separately for each file.
|
|
**
|
|
** <p><b>The callback is not reentrant.</b> The callback function should
|
|
** not attempt to invoke any other SQLite interface. If it does, bad
|
|
** things may happen, including segmentation faults and corrupt database
|
|
** files. The callback function should be a simple function that
|
|
** does some arithmetic on its input parameters and returns a result.
|
|
**
|
|
** ^The X parameter to sqlite3_autovacuum_pages(D,C,P,X) is an optional
|
|
** destructor for the P parameter. ^If X is not NULL, then X(P) is
|
|
** invoked whenever the database connection closes or when the callback
|
|
** is overwritten by another invocation of sqlite3_autovacuum_pages().
|
|
**
|
|
** <p>^There is only one autovacuum pages callback per database connection.
|
|
** ^Each call to the sqlite3_autovacuum_pages() interface overrides all
|
|
** previous invocations for that database connection. ^If the callback
|
|
** argument (C) to sqlite3_autovacuum_pages(D,C,P,X) is a NULL pointer,
|
|
** then the autovacuum steps callback is canceled. The return value
|
|
** from sqlite3_autovacuum_pages() is normally SQLITE_OK, but might
|
|
** be some other error code if something goes wrong. The current
|
|
** implementation will only return SQLITE_OK or SQLITE_MISUSE, but other
|
|
** return codes might be added in future releases.
|
|
**
|
|
** <p>If no autovacuum pages callback is specified (the usual case) or
|
|
** a NULL pointer is provided for the callback,
|
|
** then the default behavior is to vacuum all free pages. So, in other
|
|
** words, the default behavior is the same as if the callback function
|
|
** were something like this:
|
|
**
|
|
** <blockquote><pre>
|
|
** unsigned int demonstration_autovac_pages_callback(
|
|
** void *pClientData,
|
|
** const char *zSchema,
|
|
** unsigned int nDbPage,
|
|
** unsigned int nFreePage,
|
|
** unsigned int nBytePerPage
|
|
** ){
|
|
** return nFreePage;
|
|
** }
|
|
** </pre></blockquote>
|
|
*/
|
|
SQLITE_API int sqlite3_autovacuum_pages(
|
|
sqlite3 *db,
|
|
unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int),
|
|
void*,
|
|
void(*)(void*)
|
|
);
|
|
|
|
|
|
/*
|
|
** CAPI3REF: Data Change Notification Callbacks
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^The sqlite3_update_hook() interface registers a callback function
|
|
** with the [database connection] identified by the first argument
|
|
** to be invoked whenever a row is updated, inserted or deleted in
|
|
** a [rowid table].
|
|
** ^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 in a rowid table.
|
|
** ^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_sequence).)^
|
|
** ^The update hook is not invoked when [WITHOUT ROWID] tables are modified.
|
|
**
|
|
** ^In the current implementation, the update hook
|
|
** is not invoked when conflicting rows are deleted because of an
|
|
** [ON CONFLICT | ON CONFLICT REPLACE] clause. ^Nor is the update hook
|
|
** invoked when rows are deleted using the [truncate optimization].
|
|
** The exceptions defined in this paragraph might change in a future
|
|
** release of SQLite.
|
|
**
|
|
** The update hook implementation must not do anything that will modify
|
|
** the database connection that invoked the update hook. Any actions
|
|
** to modify the database connection must be deferred until after the
|
|
** completion of the [sqlite3_step()] call that triggered the update hook.
|
|
** Note that [sqlite3_prepare_v2()] and [sqlite3_step()] both modify their
|
|
** database connections for the meaning of "modify" in this paragraph.
|
|
**
|
|
** ^The sqlite3_update_hook(D,C,P) function
|
|
** returns the P argument from the previous call
|
|
** on the same [database connection] D, or NULL for
|
|
** the first call on D.
|
|
**
|
|
** See also the [sqlite3_commit_hook()], [sqlite3_rollback_hook()],
|
|
** and [sqlite3_preupdate_hook()] interfaces.
|
|
*/
|
|
SQLITE_API void *sqlite3_update_hook(
|
|
sqlite3*,
|
|
void(*)(void *,int ,char const *,char const *,sqlite3_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 [database connection | connections]
|
|
** to the same database. Sharing is enabled if the argument is true
|
|
** and disabled if the argument is false.)^
|
|
**
|
|
** This interface is omitted if SQLite is compiled with
|
|
** [-DSQLITE_OMIT_SHARED_CACHE]. The [-DSQLITE_OMIT_SHARED_CACHE]
|
|
** compile-time option is recommended because the
|
|
** [use of shared cache mode is discouraged].
|
|
**
|
|
** ^Cache sharing is enabled and disabled for an entire process.
|
|
** This is a change as of SQLite [version 3.5.0] ([dateof:3.5.0]).
|
|
** In prior versions of SQLite,
|
|
** sharing was enabled or disabled for each thread separately.
|
|
**
|
|
** ^(The cache sharing mode set by this interface effects all subsequent
|
|
** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()].
|
|
** Existing database connections continue to use the sharing mode
|
|
** that was in effect at the time they were opened.)^
|
|
**
|
|
** ^(This routine returns [SQLITE_OK] if shared cache was enabled or disabled
|
|
** successfully. An [error code] is returned otherwise.)^
|
|
**
|
|
** ^Shared cache is disabled by default. It is recommended that it stay
|
|
** that way. In other words, do not use this routine. This interface
|
|
** continues to be provided for historical compatibility, but its use is
|
|
** discouraged. Any use of shared cache is discouraged. If shared cache
|
|
** must be used, it is recommended that shared cache only be enabled for
|
|
** individual database connections using the [sqlite3_open_v2()] interface
|
|
** with the [SQLITE_OPEN_SHAREDCACHE] flag.
|
|
**
|
|
** Note: This method is disabled on MacOS X 10.7 and iOS version 5.0
|
|
** and will always return SQLITE_MISUSE. On those systems,
|
|
** shared cache mode should be enabled per-database connection via
|
|
** [sqlite3_open_v2()] with [SQLITE_OPEN_SHAREDCACHE].
|
|
**
|
|
** This interface is threadsafe on processors where writing a
|
|
** 32-bit integer is atomic.
|
|
**
|
|
** See Also: [SQLite Shared-Cache Mode]
|
|
*/
|
|
SQLITE_API int sqlite3_enable_shared_cache(int);
|
|
|
|
/*
|
|
** CAPI3REF: Attempt To Free Heap Memory
|
|
**
|
|
** ^The sqlite3_release_memory() interface attempts to free N bytes
|
|
** of heap memory by deallocating non-essential memory allocations
|
|
** held by the database library. Memory used to cache database
|
|
** pages to improve performance is an example of non-essential memory.
|
|
** ^sqlite3_release_memory() returns the number of bytes actually freed,
|
|
** which might be more or less than the amount requested.
|
|
** ^The sqlite3_release_memory() routine is a no-op returning zero
|
|
** if SQLite is not compiled with [SQLITE_ENABLE_MEMORY_MANAGEMENT].
|
|
**
|
|
** See also: [sqlite3_db_release_memory()]
|
|
*/
|
|
SQLITE_API int sqlite3_release_memory(int);
|
|
|
|
/*
|
|
** CAPI3REF: Free Memory Used By A Database Connection
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^The sqlite3_db_release_memory(D) interface attempts to free as much heap
|
|
** memory as possible from database connection D. Unlike the
|
|
** [sqlite3_release_memory()] interface, this interface is in effect even
|
|
** when the [SQLITE_ENABLE_MEMORY_MANAGEMENT] compile-time option is
|
|
** omitted.
|
|
**
|
|
** See also: [sqlite3_release_memory()]
|
|
*/
|
|
SQLITE_API int sqlite3_db_release_memory(sqlite3*);
|
|
|
|
/*
|
|
** CAPI3REF: Impose A Limit On Heap Size
|
|
**
|
|
** These interfaces impose limits on the amount of heap memory that will be
|
|
** by all database connections within a single process.
|
|
**
|
|
** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the
|
|
** soft limit on the amount of heap memory that may be allocated by SQLite.
|
|
** ^SQLite strives to keep heap memory utilization below the soft heap
|
|
** limit by reducing the number of pages held in the page cache
|
|
** as heap memory usages approaches the limit.
|
|
** ^The soft heap limit is "soft" because even though SQLite strives to stay
|
|
** below the limit, it will exceed the limit rather than generate
|
|
** an [SQLITE_NOMEM] error. In other words, the soft heap limit
|
|
** is advisory only.
|
|
**
|
|
** ^The sqlite3_hard_heap_limit64(N) interface sets a hard upper bound of
|
|
** N bytes on the amount of memory that will be allocated. ^The
|
|
** sqlite3_hard_heap_limit64(N) interface is similar to
|
|
** sqlite3_soft_heap_limit64(N) except that memory allocations will fail
|
|
** when the hard heap limit is reached.
|
|
**
|
|
** ^The return value from both sqlite3_soft_heap_limit64() and
|
|
** sqlite3_hard_heap_limit64() is the size of
|
|
** the heap limit prior to the call, or negative in the case of an
|
|
** error. ^If the argument N is negative
|
|
** then no change is made to the heap limit. Hence, the current
|
|
** size of heap limits can be determined by invoking
|
|
** sqlite3_soft_heap_limit64(-1) or sqlite3_hard_heap_limit(-1).
|
|
**
|
|
** ^Setting the heap limits to zero disables the heap limiter mechanism.
|
|
**
|
|
** ^The soft heap limit may not be greater than the hard heap limit.
|
|
** ^If the hard heap limit is enabled and if sqlite3_soft_heap_limit(N)
|
|
** is invoked with a value of N that is greater than the hard heap limit,
|
|
** the soft heap limit is set to the value of the hard heap limit.
|
|
** ^The soft heap limit is automatically enabled whenever the hard heap
|
|
** limit is enabled. ^When sqlite3_hard_heap_limit64(N) is invoked and
|
|
** the soft heap limit is outside the range of 1..N, then the soft heap
|
|
** limit is set to N. ^Invoking sqlite3_soft_heap_limit64(0) when the
|
|
** hard heap limit is enabled makes the soft heap limit equal to the
|
|
** hard heap limit.
|
|
**
|
|
** The memory allocation limits can also be adjusted using
|
|
** [PRAGMA soft_heap_limit] and [PRAGMA hard_heap_limit].
|
|
**
|
|
** ^(The heap limits are not enforced in the current implementation
|
|
** if one or more of following conditions are true:
|
|
**
|
|
** <ul>
|
|
** <li> The limit value is set to zero.
|
|
** <li> Memory accounting is disabled using a combination of the
|
|
** [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],...) start-time option and
|
|
** the [SQLITE_DEFAULT_MEMSTATUS] compile-time option.
|
|
** <li> An alternative page cache implementation is specified using
|
|
** [sqlite3_config]([SQLITE_CONFIG_PCACHE2],...).
|
|
** <li> The page cache allocates from its own memory pool supplied
|
|
** by [sqlite3_config]([SQLITE_CONFIG_PAGECACHE],...) rather than
|
|
** from the heap.
|
|
** </ul>)^
|
|
**
|
|
** The circumstances under which SQLite will enforce the heap limits may
|
|
** changes in future releases of SQLite.
|
|
*/
|
|
SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N);
|
|
SQLITE_API sqlite3_int64 sqlite3_hard_heap_limit64(sqlite3_int64 N);
|
|
|
|
/*
|
|
** CAPI3REF: Deprecated Soft Heap Limit Interface
|
|
** DEPRECATED
|
|
**
|
|
** This is a deprecated version of the [sqlite3_soft_heap_limit64()]
|
|
** interface. This routine is provided for historical compatibility
|
|
** only. All new applications should use the
|
|
** [sqlite3_soft_heap_limit64()] interface rather than this one.
|
|
*/
|
|
SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N);
|
|
|
|
|
|
/*
|
|
** CAPI3REF: Extract Metadata About A Column Of A Table
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns
|
|
** information about column C of table T in database D
|
|
** on [database connection] X.)^ ^The sqlite3_table_column_metadata()
|
|
** interface returns SQLITE_OK and fills in the non-NULL pointers in
|
|
** the final five arguments with appropriate values if the specified
|
|
** column exists. ^The sqlite3_table_column_metadata() interface returns
|
|
** SQLITE_ERROR if the specified column does not exist.
|
|
** ^If the column-name parameter to sqlite3_table_column_metadata() is a
|
|
** NULL pointer, then this routine simply checks for the existence of the
|
|
** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it
|
|
** does not. If the table name parameter T in a call to
|
|
** sqlite3_table_column_metadata(X,D,T,C,...) is NULL then the result is
|
|
** undefined behavior.
|
|
**
|
|
** ^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 used by the database engine to
|
|
** resolve unqualified table references.
|
|
**
|
|
** ^The third and fourth parameters to this function are the table and column
|
|
** name of the desired column, respectively.
|
|
**
|
|
** ^Metadata 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 metadata is omitted.
|
|
**
|
|
** ^(<blockquote>
|
|
** <table border="1">
|
|
** <tr><th> Parameter <th> Output<br>Type <th> Description
|
|
**
|
|
** <tr><td> 5th <td> const char* <td> Data type
|
|
** <tr><td> 6th <td> const char* <td> Name of default collation sequence
|
|
** <tr><td> 7th <td> int <td> True if column has a NOT NULL constraint
|
|
** <tr><td> 8th <td> int <td> True if column is part of the PRIMARY KEY
|
|
** <tr><td> 9th <td> int <td> True if column is [AUTOINCREMENT]
|
|
** </table>
|
|
** </blockquote>)^
|
|
**
|
|
** ^The memory pointed to by the character pointers returned for the
|
|
** declaration type and collation sequence is valid until the next
|
|
** call to any SQLite API function.
|
|
**
|
|
** ^If the specified table is actually a view, an [error code] is returned.
|
|
**
|
|
** ^If the specified column is "rowid", "oid" or "_rowid_" and the table
|
|
** is not a [WITHOUT ROWID] table 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
|
|
** [INTEGER PRIMARY KEY] column, then the outputs
|
|
** for the [rowid] are set as follows:
|
|
**
|
|
** <pre>
|
|
** data type: "INTEGER"
|
|
** collation sequence: "BINARY"
|
|
** not null: 0
|
|
** primary key: 1
|
|
** auto increment: 0
|
|
** </pre>)^
|
|
**
|
|
** ^This function causes all database schemas to be read from disk and
|
|
** parsed, if that has not already been done, and returns an error if
|
|
** any errors are encountered while loading the schema.
|
|
*/
|
|
SQLITE_API 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 column is auto-increment */
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Load An Extension
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^This interface loads an SQLite extension library from the named file.
|
|
**
|
|
** ^The sqlite3_load_extension() interface attempts to load an
|
|
** [SQLite extension] library contained in the file zFile. If
|
|
** the file cannot be loaded directly, attempts are made to load
|
|
** with various operating-system specific extensions added.
|
|
** So for example, if "samplelib" cannot be loaded, then names like
|
|
** "samplelib.so" or "samplelib.dylib" or "samplelib.dll" might
|
|
** be tried also.
|
|
**
|
|
** ^The entry point is zProc.
|
|
** ^(zProc may be 0, in which case SQLite will try to come up with an
|
|
** entry point name on its own. It first tries "sqlite3_extension_init".
|
|
** If that does not work, it constructs a name "sqlite3_X_init" where the
|
|
** X is consists of the lower-case equivalent of all ASCII alphabetic
|
|
** characters in the filename from the last "/" to the first following
|
|
** "." and omitting any initial "lib".)^
|
|
** ^The sqlite3_load_extension() interface returns
|
|
** [SQLITE_OK] on success and [SQLITE_ERROR] if something goes wrong.
|
|
** ^If an error occurs and pzErrMsg is not 0, then the
|
|
** [sqlite3_load_extension()] interface shall attempt to
|
|
** fill *pzErrMsg with error message text stored in memory
|
|
** obtained from [sqlite3_malloc()]. The calling function
|
|
** should free this memory by calling [sqlite3_free()].
|
|
**
|
|
** ^Extension loading must be enabled using
|
|
** [sqlite3_enable_load_extension()] or
|
|
** [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],1,NULL)
|
|
** prior to calling this API,
|
|
** otherwise an error will be returned.
|
|
**
|
|
** <b>Security warning:</b> It is recommended that the
|
|
** [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method be used to enable only this
|
|
** interface. The use of the [sqlite3_enable_load_extension()] interface
|
|
** should be avoided. This will keep the SQL function [load_extension()]
|
|
** disabled and prevent SQL injections from giving attackers
|
|
** access to extension loading capabilities.
|
|
**
|
|
** See also the [load_extension() SQL function].
|
|
*/
|
|
SQLITE_API 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
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^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.
|
|
**
|
|
** ^Extension loading is off by default.
|
|
** ^Call the sqlite3_enable_load_extension() routine with onoff==1
|
|
** to turn extension loading on and call it with onoff==0 to turn
|
|
** it back off again.
|
|
**
|
|
** ^This interface enables or disables both the C-API
|
|
** [sqlite3_load_extension()] and the SQL function [load_extension()].
|
|
** ^(Use [sqlite3_db_config](db,[SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION],..)
|
|
** to enable or disable only the C-API.)^
|
|
**
|
|
** <b>Security warning:</b> It is recommended that extension loading
|
|
** be enabled using the [SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION] method
|
|
** rather than this interface, so the [load_extension()] SQL function
|
|
** remains disabled. This will prevent SQL injections from giving attackers
|
|
** access to extension loading capabilities.
|
|
*/
|
|
SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
|
|
|
|
/*
|
|
** CAPI3REF: Automatically Load Statically Linked Extensions
|
|
**
|
|
** ^This interface causes the xEntryPoint() function to be invoked for
|
|
** each new [database connection] that is created. The idea here is that
|
|
** xEntryPoint() is the entry point for a statically linked [SQLite extension]
|
|
** that is to be automatically loaded into all new database connections.
|
|
**
|
|
** ^(Even though the function prototype shows that xEntryPoint() takes
|
|
** no arguments and returns void, SQLite invokes xEntryPoint() with three
|
|
** arguments and expects an integer result as if the signature of the
|
|
** entry point where as follows:
|
|
**
|
|
** <blockquote><pre>
|
|
** int xEntryPoint(
|
|
** sqlite3 *db,
|
|
** const char **pzErrMsg,
|
|
** const struct sqlite3_api_routines *pThunk
|
|
** );
|
|
** </pre></blockquote>)^
|
|
**
|
|
** If the xEntryPoint routine encounters an error, it should make *pzErrMsg
|
|
** point to an appropriate error message (obtained from [sqlite3_mprintf()])
|
|
** and return an appropriate [error code]. ^SQLite ensures that *pzErrMsg
|
|
** is NULL before calling the xEntryPoint(). ^SQLite will invoke
|
|
** [sqlite3_free()] on *pzErrMsg after xEntryPoint() returns. ^If any
|
|
** xEntryPoint() returns an error, the [sqlite3_open()], [sqlite3_open16()],
|
|
** or [sqlite3_open_v2()] call that provoked the xEntryPoint() will fail.
|
|
**
|
|
** ^Calling sqlite3_auto_extension(X) with an entry point X that is already
|
|
** on the list of automatic extensions is a harmless no-op. ^No entry point
|
|
** will be called more than once for each database connection that is opened.
|
|
**
|
|
** See also: [sqlite3_reset_auto_extension()]
|
|
** and [sqlite3_cancel_auto_extension()]
|
|
*/
|
|
SQLITE_API int sqlite3_auto_extension(void(*xEntryPoint)(void));
|
|
|
|
/*
|
|
** CAPI3REF: Cancel Automatic Extension Loading
|
|
**
|
|
** ^The [sqlite3_cancel_auto_extension(X)] interface unregisters the
|
|
** initialization routine X that was registered using a prior call to
|
|
** [sqlite3_auto_extension(X)]. ^The [sqlite3_cancel_auto_extension(X)]
|
|
** routine returns 1 if initialization routine X was successfully
|
|
** unregistered and it returns 0 if X was not on the list of initialization
|
|
** routines.
|
|
*/
|
|
SQLITE_API int sqlite3_cancel_auto_extension(void(*xEntryPoint)(void));
|
|
|
|
/*
|
|
** CAPI3REF: Reset Automatic Extension Loading
|
|
**
|
|
** ^This interface disables all automatic extensions previously
|
|
** registered using [sqlite3_auto_extension()].
|
|
*/
|
|
SQLITE_API void sqlite3_reset_auto_extension(void);
|
|
|
|
/*
|
|
** 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;
|
|
|
|
/*
|
|
** CAPI3REF: Virtual Table Object
|
|
** KEYWORDS: sqlite3_module {virtual table module}
|
|
**
|
|
** This structure, sometimes called a "virtual table module",
|
|
** defines the implementation of a [virtual table].
|
|
** This structure consists mostly of methods for the module.
|
|
**
|
|
** ^A virtual table module is created by filling in a persistent
|
|
** instance of this structure and passing a pointer to that instance
|
|
** to [sqlite3_create_module()] or [sqlite3_create_module_v2()].
|
|
** ^The registration remains valid until it is replaced by a different
|
|
** module or until the [database connection] closes. The content
|
|
** of this structure must not change while it is registered with
|
|
** any database connection.
|
|
*/
|
|
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*, sqlite3_int64 *pRowid);
|
|
int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_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 methods above are in version 1 of the sqlite_module object. Those
|
|
** below are for version 2 and greater. */
|
|
int (*xSavepoint)(sqlite3_vtab *pVTab, int);
|
|
int (*xRelease)(sqlite3_vtab *pVTab, int);
|
|
int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
|
|
/* The methods above are in versions 1 and 2 of the sqlite_module object.
|
|
** Those below are for version 3 and greater. */
|
|
int (*xShadowName)(const char*);
|
|
/* The methods above are in versions 1 through 3 of the sqlite_module object.
|
|
** Those below are for version 4 and greater. */
|
|
int (*xIntegrity)(sqlite3_vtab *pVTab, const char *zSchema,
|
|
const char *zTabName, int mFlags, char **pzErr);
|
|
};
|
|
|
|
/*
|
|
** CAPI3REF: Virtual Table Indexing Information
|
|
** KEYWORDS: sqlite3_index_info
|
|
**
|
|
** The sqlite3_index_info structure and its substructures is used as part
|
|
** of the [virtual table] interface to
|
|
** pass information into and receive the reply from the [xBestIndex]
|
|
** method of a [virtual table 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:
|
|
**
|
|
** <blockquote>column OP expr</blockquote>
|
|
**
|
|
** where OP is =, <, <=, >, or >=.)^ ^(The particular operator is
|
|
** stored in aConstraint[].op using one of the
|
|
** [SQLITE_INDEX_CONSTRAINT_EQ | SQLITE_INDEX_CONSTRAINT_ values].)^
|
|
** ^(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 simplifications 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 that are
|
|
** relevant 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 colUsed field indicates which columns of the virtual table may be
|
|
** required by the current scan. Virtual table columns are numbered from
|
|
** zero in the order in which they appear within the CREATE TABLE statement
|
|
** passed to sqlite3_declare_vtab(). For the first 63 columns (columns 0-62),
|
|
** the corresponding bit is set within the colUsed mask if the column may be
|
|
** required by SQLite. If the table has at least 64 columns and any column
|
|
** to the right of the first 63 is required, then bit 63 of colUsed is also
|
|
** set. In other words, column iCol may be required if the expression
|
|
** (colUsed & ((sqlite3_uint64)1 << (iCol>=63 ? 63 : iCol))) evaluates to
|
|
** non-zero.
|
|
**
|
|
** 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 might not be checked again by the byte code.)^ ^(The
|
|
** aConstraintUsage[].omit flag is an optimization hint. When the omit flag
|
|
** is left in its default setting of false, the constraint will always be
|
|
** checked separately in byte code. If the omit flag is change to true, then
|
|
** the constraint may or may not be checked in byte code. In other words,
|
|
** when the omit flag is true there is no guarantee that the constraint will
|
|
** not be checked again using byte code.)^
|
|
**
|
|
** ^The idxNum and idxStr values are recorded and passed into the
|
|
** [xFilter] method.
|
|
** ^[sqlite3_free()] is used to free idxStr if and only if
|
|
** needToFreeIdxStr is true.
|
|
**
|
|
** ^The orderByConsumed means that output from [xFilter]/[xNext] 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 a particular
|
|
** strategy. A cost of N indicates that the cost of the strategy is similar
|
|
** to a linear scan of an SQLite table with N rows. A cost of log(N)
|
|
** indicates that the expense of the operation is similar to that of a
|
|
** binary search on a unique indexed field of an SQLite table with N rows.
|
|
**
|
|
** ^The estimatedRows value is an estimate of the number of rows that
|
|
** will be returned by the strategy.
|
|
**
|
|
** The xBestIndex method may optionally populate the idxFlags field with a
|
|
** mask of SQLITE_INDEX_SCAN_* flags. Currently there is only one such flag -
|
|
** SQLITE_INDEX_SCAN_UNIQUE. If the xBestIndex method sets this flag, SQLite
|
|
** assumes that the strategy may visit at most one row.
|
|
**
|
|
** Additionally, if xBestIndex sets the SQLITE_INDEX_SCAN_UNIQUE flag, then
|
|
** SQLite also assumes that if a call to the xUpdate() method is made as
|
|
** part of the same statement to delete or update a virtual table row and the
|
|
** implementation returns SQLITE_CONSTRAINT, then there is no need to rollback
|
|
** any database changes. In other words, if the xUpdate() returns
|
|
** SQLITE_CONSTRAINT, the database contents must be exactly as they were
|
|
** before xUpdate was called. By contrast, if SQLITE_INDEX_SCAN_UNIQUE is not
|
|
** set and xUpdate returns SQLITE_CONSTRAINT, any database changes made by
|
|
** the xUpdate method are automatically rolled back by SQLite.
|
|
**
|
|
** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info
|
|
** structure for SQLite [version 3.8.2] ([dateof:3.8.2]).
|
|
** If a virtual table extension is
|
|
** used with an SQLite version earlier than 3.8.2, the results of attempting
|
|
** to read or write the estimatedRows field are undefined (but are likely
|
|
** to include crashing the application). The estimatedRows field should
|
|
** therefore only be used if [sqlite3_libversion_number()] returns a
|
|
** value greater than or equal to 3008002. Similarly, the idxFlags field
|
|
** was added for [version 3.9.0] ([dateof:3.9.0]).
|
|
** It may therefore only be used if
|
|
** sqlite3_libversion_number() returns a value greater than or equal to
|
|
** 3009000.
|
|
*/
|
|
struct sqlite3_index_info {
|
|
/* Inputs */
|
|
int nConstraint; /* Number of entries in aConstraint */
|
|
struct sqlite3_index_constraint {
|
|
int iColumn; /* Column constrained. -1 for ROWID */
|
|
unsigned char op; /* Constraint operator */
|
|
unsigned char usable; /* True if this constraint is usable */
|
|
int iTermOffset; /* Used internally - xBestIndex should ignore */
|
|
} *aConstraint; /* Table of WHERE clause constraints */
|
|
int nOrderBy; /* Number of terms in the ORDER BY clause */
|
|
struct sqlite3_index_orderby {
|
|
int iColumn; /* Column number */
|
|
unsigned char desc; /* True for DESC. False for ASC. */
|
|
} *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 */
|
|
} *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 */
|
|
/* Fields below are only available in SQLite 3.8.2 and later */
|
|
sqlite3_int64 estimatedRows; /* Estimated number of rows returned */
|
|
/* Fields below are only available in SQLite 3.9.0 and later */
|
|
int idxFlags; /* Mask of SQLITE_INDEX_SCAN_* flags */
|
|
/* Fields below are only available in SQLite 3.10.0 and later */
|
|
sqlite3_uint64 colUsed; /* Input: Mask of columns used by statement */
|
|
};
|
|
|
|
/*
|
|
** CAPI3REF: Virtual Table Scan Flags
|
|
**
|
|
** Virtual table implementations are allowed to set the
|
|
** [sqlite3_index_info].idxFlags field to some combination of
|
|
** these bits.
|
|
*/
|
|
#define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */
|
|
|
|
/*
|
|
** CAPI3REF: Virtual Table Constraint Operator Codes
|
|
**
|
|
** These macros define the allowed values for the
|
|
** [sqlite3_index_info].aConstraint[].op field. Each value represents
|
|
** an operator that is part of a constraint term in the WHERE clause of
|
|
** a query that uses a [virtual table].
|
|
**
|
|
** ^The left-hand operand of the operator is given by the corresponding
|
|
** aConstraint[].iColumn field. ^An iColumn of -1 indicates the left-hand
|
|
** operand is the rowid.
|
|
** The SQLITE_INDEX_CONSTRAINT_LIMIT and SQLITE_INDEX_CONSTRAINT_OFFSET
|
|
** operators have no left-hand operand, and so for those operators the
|
|
** corresponding aConstraint[].iColumn is meaningless and should not be
|
|
** used.
|
|
**
|
|
** All operator values from SQLITE_INDEX_CONSTRAINT_FUNCTION through
|
|
** value 255 are reserved to represent functions that are overloaded
|
|
** by the [xFindFunction|xFindFunction method] of the virtual table
|
|
** implementation.
|
|
**
|
|
** The right-hand operands for each constraint might be accessible using
|
|
** the [sqlite3_vtab_rhs_value()] interface. Usually the right-hand
|
|
** operand is only available if it appears as a single constant literal
|
|
** in the input SQL. If the right-hand operand is another column or an
|
|
** expression (even a constant expression) or a parameter, then the
|
|
** sqlite3_vtab_rhs_value() probably will not be able to extract it.
|
|
** ^The SQLITE_INDEX_CONSTRAINT_ISNULL and
|
|
** SQLITE_INDEX_CONSTRAINT_ISNOTNULL operators have no right-hand operand
|
|
** and hence calls to sqlite3_vtab_rhs_value() for those operators will
|
|
** always return SQLITE_NOTFOUND.
|
|
**
|
|
** The collating sequence to be used for comparison can be found using
|
|
** the [sqlite3_vtab_collation()] interface. For most real-world virtual
|
|
** tables, the collating sequence of constraints does not matter (for example
|
|
** because the constraints are numeric) and so the sqlite3_vtab_collation()
|
|
** interface is not commonly needed.
|
|
*/
|
|
#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
|
|
#define SQLITE_INDEX_CONSTRAINT_LIKE 65
|
|
#define SQLITE_INDEX_CONSTRAINT_GLOB 66
|
|
#define SQLITE_INDEX_CONSTRAINT_REGEXP 67
|
|
#define SQLITE_INDEX_CONSTRAINT_NE 68
|
|
#define SQLITE_INDEX_CONSTRAINT_ISNOT 69
|
|
#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70
|
|
#define SQLITE_INDEX_CONSTRAINT_ISNULL 71
|
|
#define SQLITE_INDEX_CONSTRAINT_IS 72
|
|
#define SQLITE_INDEX_CONSTRAINT_LIMIT 73
|
|
#define SQLITE_INDEX_CONSTRAINT_OFFSET 74
|
|
#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150
|
|
|
|
/*
|
|
** CAPI3REF: Register A Virtual Table Implementation
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^These routines are used to register a new [virtual table module] name.
|
|
** ^Module names must be registered before
|
|
** creating a new [virtual table] using the module and before using a
|
|
** preexisting [virtual table] for the module.
|
|
**
|
|
** ^The module name is registered on the [database connection] specified
|
|
** by the first parameter. ^The name of the module is given by the
|
|
** second parameter. ^The third parameter is a pointer to
|
|
** the implementation of the [virtual table module]. ^The fourth
|
|
** parameter is an arbitrary client data pointer that is passed through
|
|
** into the [xCreate] and [xConnect] methods of the virtual table module
|
|
** when a new virtual table is be being created or reinitialized.
|
|
**
|
|
** ^The sqlite3_create_module_v2() interface has a fifth parameter which
|
|
** is a pointer to a destructor for the pClientData. ^SQLite will
|
|
** invoke the destructor function (if it is not NULL) when SQLite
|
|
** no longer needs the pClientData pointer. ^The destructor will also
|
|
** be invoked if the call to sqlite3_create_module_v2() fails.
|
|
** ^The sqlite3_create_module()
|
|
** interface is equivalent to sqlite3_create_module_v2() with a NULL
|
|
** destructor.
|
|
**
|
|
** ^If the third parameter (the pointer to the sqlite3_module object) is
|
|
** NULL then no new module is created and any existing modules with the
|
|
** same name are dropped.
|
|
**
|
|
** See also: [sqlite3_drop_modules()]
|
|
*/
|
|
SQLITE_API int sqlite3_create_module(
|
|
sqlite3 *db, /* SQLite connection to register module with */
|
|
const char *zName, /* Name of the module */
|
|
const sqlite3_module *p, /* Methods for the module */
|
|
void *pClientData /* Client data for xCreate/xConnect */
|
|
);
|
|
SQLITE_API int sqlite3_create_module_v2(
|
|
sqlite3 *db, /* SQLite connection to register module with */
|
|
const char *zName, /* Name of the module */
|
|
const sqlite3_module *p, /* Methods for the module */
|
|
void *pClientData, /* Client data for xCreate/xConnect */
|
|
void(*xDestroy)(void*) /* Module destructor function */
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Remove Unnecessary Virtual Table Implementations
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^The sqlite3_drop_modules(D,L) interface removes all virtual
|
|
** table modules from database connection D except those named on list L.
|
|
** The L parameter must be either NULL or a pointer to an array of pointers
|
|
** to strings where the array is terminated by a single NULL pointer.
|
|
** ^If the L parameter is NULL, then all virtual table modules are removed.
|
|
**
|
|
** See also: [sqlite3_create_module()]
|
|
*/
|
|
SQLITE_API int sqlite3_drop_modules(
|
|
sqlite3 *db, /* Remove modules from this connection */
|
|
const char **azKeep /* Except, do not remove the ones named here */
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Virtual Table Instance Object
|
|
** KEYWORDS: sqlite3_vtab
|
|
**
|
|
** Every [virtual table module] implementation uses a subclass
|
|
** of this object to describe a particular instance
|
|
** of the [virtual table]. Each subclass will
|
|
** be tailored 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.
|
|
*/
|
|
struct sqlite3_vtab {
|
|
const sqlite3_module *pModule; /* The module for this virtual table */
|
|
int nRef; /* Number of open cursors */
|
|
char *zErrMsg; /* Error message from sqlite3_mprintf() */
|
|
/* Virtual table implementations will typically add additional fields */
|
|
};
|
|
|
|
/*
|
|
** CAPI3REF: Virtual Table Cursor Object
|
|
** KEYWORDS: sqlite3_vtab_cursor {virtual table cursor}
|
|
**
|
|
** Every [virtual table 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
|
|
** [sqlite3_module.xOpen | xOpen] method of the module and are destroyed
|
|
** by the [sqlite3_module.xClose | xClose] method. Cursors are used
|
|
** by the [xFilter], [xNext], [xEof], [xColumn], and [xRowid] methods
|
|
** 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 */
|
|
};
|
|
|
|
/*
|
|
** CAPI3REF: Declare The Schema Of A Virtual Table
|
|
**
|
|
** ^The [xCreate] and [xConnect] methods of a
|
|
** [virtual table module] call this interface
|
|
** to declare the format (the names and datatypes of the columns) of
|
|
** the virtual tables they implement.
|
|
*/
|
|
SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL);
|
|
|
|
/*
|
|
** CAPI3REF: Overload A Function For A Virtual Table
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^(Virtual tables can provide alternative implementations of functions
|
|
** using the [xFindFunction] method of the [virtual table module].
|
|
** 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 placeholder function that can be overloaded
|
|
** by a [virtual table].
|
|
*/
|
|
SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
|
|
|
|
/*
|
|
** CAPI3REF: A Handle To An Open BLOB
|
|
** KEYWORDS: {BLOB handle} {BLOB handles}
|
|
**
|
|
** An instance of this object represents an open BLOB on which
|
|
** [sqlite3_blob_open | incremental BLOB I/O] can be performed.
|
|
** ^Objects of this type are 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 [sqlite3_blob_bytes()] interface returns the size of the BLOB in bytes.
|
|
*/
|
|
typedef struct sqlite3_blob sqlite3_blob;
|
|
|
|
/*
|
|
** CAPI3REF: Open A BLOB For Incremental I/O
|
|
** METHOD: sqlite3
|
|
** CONSTRUCTOR: sqlite3_blob
|
|
**
|
|
** ^(This interfaces opens a [BLOB handle | handle] to the BLOB located
|
|
** in row iRow, column zColumn, table zTable in database zDb;
|
|
** in other words, the same BLOB that would be selected by:
|
|
**
|
|
** <pre>
|
|
** SELECT zColumn FROM zDb.zTable WHERE [rowid] = iRow;
|
|
** </pre>)^
|
|
**
|
|
** ^(Parameter zDb is not the filename that contains the database, but
|
|
** rather the symbolic name of the database. For attached databases, this is
|
|
** the name that appears after the AS keyword in the [ATTACH] statement.
|
|
** For the main database file, the database name is "main". For TEMP
|
|
** tables, the database name is "temp".)^
|
|
**
|
|
** ^If the flags parameter is non-zero, then the BLOB is opened for read
|
|
** and write access. ^If the flags parameter is zero, the BLOB is opened for
|
|
** read-only access.
|
|
**
|
|
** ^(On success, [SQLITE_OK] is returned and the new [BLOB handle] is stored
|
|
** in *ppBlob. Otherwise an [error code] is returned and, unless the error
|
|
** code is SQLITE_MISUSE, *ppBlob is set to NULL.)^ ^This means that, provided
|
|
** the API is not misused, it is always safe to call [sqlite3_blob_close()]
|
|
** on *ppBlob after this function it returns.
|
|
**
|
|
** This function fails with SQLITE_ERROR if any of the following are true:
|
|
** <ul>
|
|
** <li> ^(Database zDb does not exist)^,
|
|
** <li> ^(Table zTable does not exist within database zDb)^,
|
|
** <li> ^(Table zTable is a WITHOUT ROWID table)^,
|
|
** <li> ^(Column zColumn does not exist)^,
|
|
** <li> ^(Row iRow is not present in the table)^,
|
|
** <li> ^(The specified column of row iRow contains a value that is not
|
|
** a TEXT or BLOB value)^,
|
|
** <li> ^(Column zColumn is part of an index, PRIMARY KEY or UNIQUE
|
|
** constraint and the blob is being opened for read/write access)^,
|
|
** <li> ^([foreign key constraints | Foreign key constraints] are enabled,
|
|
** column zColumn is part of a [child key] definition and the blob is
|
|
** being opened for read/write access)^.
|
|
** </ul>
|
|
**
|
|
** ^Unless it returns SQLITE_MISUSE, this function sets the
|
|
** [database connection] error code and message accessible via
|
|
** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions.
|
|
**
|
|
** A BLOB referenced by sqlite3_blob_open() may be read using the
|
|
** [sqlite3_blob_read()] interface and modified by using
|
|
** [sqlite3_blob_write()]. The [BLOB handle] can be moved to a
|
|
** different row of the same table using the [sqlite3_blob_reopen()]
|
|
** interface. However, the column, table, or database of a [BLOB handle]
|
|
** cannot be changed after the [BLOB handle] is opened.
|
|
**
|
|
** ^(If the row that a BLOB handle points to is modified by an
|
|
** [UPDATE], [DELETE], or by [ON CONFLICT] side-effects
|
|
** then the BLOB handle is marked as "expired".
|
|
** This is true if any column of the row is changed, even a column
|
|
** other than the one the BLOB handle is open on.)^
|
|
** ^Calls to [sqlite3_blob_read()] and [sqlite3_blob_write()] for
|
|
** an expired BLOB handle fail with a return code of [SQLITE_ABORT].
|
|
** ^(Changes written into a BLOB prior to the BLOB expiring are not
|
|
** rolled back by the expiration of the BLOB. Such changes will eventually
|
|
** commit if the transaction continues to completion.)^
|
|
**
|
|
** ^Use the [sqlite3_blob_bytes()] interface to determine the size of
|
|
** the opened blob. ^The size of a blob may not be changed by this
|
|
** interface. Use the [UPDATE] SQL command to change the size of a
|
|
** blob.
|
|
**
|
|
** ^The [sqlite3_bind_zeroblob()] and [sqlite3_result_zeroblob()] interfaces
|
|
** and the built-in [zeroblob] SQL function may be used to create a
|
|
** zero-filled blob to read or write using the incremental-blob interface.
|
|
**
|
|
** To avoid a resource leak, every open [BLOB handle] should eventually
|
|
** be released by a call to [sqlite3_blob_close()].
|
|
**
|
|
** See also: [sqlite3_blob_close()],
|
|
** [sqlite3_blob_reopen()], [sqlite3_blob_read()],
|
|
** [sqlite3_blob_bytes()], [sqlite3_blob_write()].
|
|
*/
|
|
SQLITE_API int sqlite3_blob_open(
|
|
sqlite3*,
|
|
const char *zDb,
|
|
const char *zTable,
|
|
const char *zColumn,
|
|
sqlite3_int64 iRow,
|
|
int flags,
|
|
sqlite3_blob **ppBlob
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Move a BLOB Handle to a New Row
|
|
** METHOD: sqlite3_blob
|
|
**
|
|
** ^This function is used to move an existing [BLOB handle] so that it points
|
|
** to a different row of the same database table. ^The new row is identified
|
|
** by the rowid value passed as the second argument. Only the row can be
|
|
** changed. ^The database, table and column on which the blob handle is open
|
|
** remain the same. Moving an existing [BLOB handle] to a new row is
|
|
** faster than closing the existing handle and opening a new one.
|
|
**
|
|
** ^(The new row must meet the same criteria as for [sqlite3_blob_open()] -
|
|
** it must exist and there must be either a blob or text value stored in
|
|
** the nominated column.)^ ^If the new row is not present in the table, or if
|
|
** it does not contain a blob or text value, or if another error occurs, an
|
|
** SQLite error code is returned and the blob handle is considered aborted.
|
|
** ^All subsequent calls to [sqlite3_blob_read()], [sqlite3_blob_write()] or
|
|
** [sqlite3_blob_reopen()] on an aborted blob handle immediately return
|
|
** SQLITE_ABORT. ^Calling [sqlite3_blob_bytes()] on an aborted blob handle
|
|
** always returns zero.
|
|
**
|
|
** ^This function sets the database handle error code and message.
|
|
*/
|
|
SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64);
|
|
|
|
/*
|
|
** CAPI3REF: Close A BLOB Handle
|
|
** DESTRUCTOR: sqlite3_blob
|
|
**
|
|
** ^This function closes an open [BLOB handle]. ^(The BLOB handle is closed
|
|
** unconditionally. Even if this routine returns an error code, the
|
|
** handle is still closed.)^
|
|
**
|
|
** ^If the blob handle being closed was opened for read-write access, and if
|
|
** the database is in auto-commit mode and there are no other open read-write
|
|
** blob handles or active write statements, the current transaction is
|
|
** committed. ^If an error occurs while committing the transaction, an error
|
|
** code is returned and the transaction rolled back.
|
|
**
|
|
** Calling this function with an argument that is not a NULL pointer or an
|
|
** open blob handle results in undefined behavior. ^Calling this routine
|
|
** with a null pointer (such as would be returned by a failed call to
|
|
** [sqlite3_blob_open()]) is a harmless no-op. ^Otherwise, if this function
|
|
** is passed a valid open blob handle, the values returned by the
|
|
** sqlite3_errcode() and sqlite3_errmsg() functions are set before returning.
|
|
*/
|
|
SQLITE_API int sqlite3_blob_close(sqlite3_blob *);
|
|
|
|
/*
|
|
** CAPI3REF: Return The Size Of An Open BLOB
|
|
** METHOD: sqlite3_blob
|
|
**
|
|
** ^Returns the size in bytes of the BLOB accessible via the
|
|
** successfully opened [BLOB handle] in its only argument. ^The
|
|
** incremental blob I/O routines can only read or overwriting existing
|
|
** blob content; they cannot change the size of a blob.
|
|
**
|
|
** This routine only works on a [BLOB handle] which has been created
|
|
** by a prior successful call to [sqlite3_blob_open()] and which has not
|
|
** been closed by [sqlite3_blob_close()]. Passing any other pointer in
|
|
** to this routine results in undefined and probably undesirable behavior.
|
|
*/
|
|
SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *);
|
|
|
|
/*
|
|
** CAPI3REF: Read Data From A BLOB Incrementally
|
|
** METHOD: sqlite3_blob
|
|
**
|
|
** ^(This function is used to read data from an open [BLOB handle] into a
|
|
** caller-supplied buffer. N bytes of data are copied into buffer Z
|
|
** from the open BLOB, starting at offset iOffset.)^
|
|
**
|
|
** ^If offset iOffset is less than N bytes from the end of the BLOB,
|
|
** [SQLITE_ERROR] is returned and no data is read. ^If N or iOffset is
|
|
** less than zero, [SQLITE_ERROR] is returned and no data is read.
|
|
** ^The size of the blob (and hence the maximum value of N+iOffset)
|
|
** can be determined using the [sqlite3_blob_bytes()] interface.
|
|
**
|
|
** ^An attempt to read from an expired [BLOB handle] fails with an
|
|
** error code of [SQLITE_ABORT].
|
|
**
|
|
** ^(On success, sqlite3_blob_read() returns SQLITE_OK.
|
|
** Otherwise, an [error code] or an [extended error code] is returned.)^
|
|
**
|
|
** This routine only works on a [BLOB handle] which has been created
|
|
** by a prior successful call to [sqlite3_blob_open()] and which has not
|
|
** been closed by [sqlite3_blob_close()]. Passing any other pointer in
|
|
** to this routine results in undefined and probably undesirable behavior.
|
|
**
|
|
** See also: [sqlite3_blob_write()].
|
|
*/
|
|
SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset);
|
|
|
|
/*
|
|
** CAPI3REF: Write Data Into A BLOB Incrementally
|
|
** METHOD: sqlite3_blob
|
|
**
|
|
** ^(This function is used to write data into an open [BLOB handle] from a
|
|
** caller-supplied buffer. N bytes of data are copied from the buffer Z
|
|
** into the open BLOB, starting at offset iOffset.)^
|
|
**
|
|
** ^(On success, sqlite3_blob_write() returns SQLITE_OK.
|
|
** Otherwise, an [error code] or an [extended error code] is returned.)^
|
|
** ^Unless SQLITE_MISUSE is returned, this function sets the
|
|
** [database connection] error code and message accessible via
|
|
** [sqlite3_errcode()] and [sqlite3_errmsg()] and related functions.
|
|
**
|
|
** ^If the [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. The size of the
|
|
** BLOB (and hence the maximum value of N+iOffset) can be determined
|
|
** using the [sqlite3_blob_bytes()] interface. ^If N or iOffset are less
|
|
** than zero [SQLITE_ERROR] is returned and no data is written.
|
|
**
|
|
** ^An attempt to write to an expired [BLOB handle] fails with an
|
|
** error code of [SQLITE_ABORT]. ^Writes to the BLOB that occurred
|
|
** before the [BLOB handle] expired are not rolled back by the
|
|
** expiration of the handle, though of course those changes might
|
|
** have been overwritten by the statement that expired the BLOB handle
|
|
** or by other independent statements.
|
|
**
|
|
** This routine only works on a [BLOB handle] which has been created
|
|
** by a prior successful call to [sqlite3_blob_open()] and which has not
|
|
** been closed by [sqlite3_blob_close()]. Passing any other pointer in
|
|
** to this routine results in undefined and probably undesirable behavior.
|
|
**
|
|
** See also: [sqlite3_blob_read()].
|
|
*/
|
|
SQLITE_API int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset);
|
|
|
|
/*
|
|
** CAPI3REF: Virtual File System Objects
|
|
**
|
|
** A virtual filesystem (VFS) is an [sqlite3_vfs] object
|
|
** that SQLite uses to interact
|
|
** with the underlying operating system. Most SQLite builds come with a
|
|
** single default VFS that is appropriate for the host computer.
|
|
** New VFSes can be registered and existing VFSes can be unregistered.
|
|
** The following interfaces are provided.
|
|
**
|
|
** ^The sqlite3_vfs_find() interface returns a pointer to a VFS given its name.
|
|
** ^Names are case sensitive.
|
|
** ^Names are zero-terminated UTF-8 strings.
|
|
** ^If there is no match, a NULL pointer is returned.
|
|
** ^If zVfsName is NULL then the default VFS is returned.
|
|
**
|
|
** ^New VFSes are registered with sqlite3_vfs_register().
|
|
** ^Each new VFS becomes the default VFS if the makeDflt flag is set.
|
|
** ^The same VFS can be registered multiple times without injury.
|
|
** ^To make an existing VFS into the default VFS, register it again
|
|
** with the makeDflt flag set. If two different VFSes with the
|
|
** same name are registered, the behavior is undefined. If a
|
|
** VFS is registered with a name that is NULL or an empty string,
|
|
** then the behavior is undefined.
|
|
**
|
|
** ^Unregister a VFS with the sqlite3_vfs_unregister() interface.
|
|
** ^(If the default VFS is unregistered, another VFS is chosen as
|
|
** the default. The choice for the new VFS is arbitrary.)^
|
|
*/
|
|
SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName);
|
|
SQLITE_API int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt);
|
|
SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
|
|
|
|
/*
|
|
** CAPI3REF: Mutexes
|
|
**
|
|
** The SQLite core uses these routines for thread
|
|
** synchronization. Though they are intended for internal
|
|
** use by SQLite, code that links against SQLite is
|
|
** permitted to use any of these routines.
|
|
**
|
|
** The SQLite source code contains multiple implementations
|
|
** of these mutex routines. An appropriate implementation
|
|
** is selected automatically at compile-time. The following
|
|
** implementations are available in the SQLite core:
|
|
**
|
|
** <ul>
|
|
** <li> SQLITE_MUTEX_PTHREADS
|
|
** <li> SQLITE_MUTEX_W32
|
|
** <li> SQLITE_MUTEX_NOOP
|
|
** </ul>
|
|
**
|
|
** The SQLITE_MUTEX_NOOP implementation is a set of routines
|
|
** that does no real locking and is appropriate for use in
|
|
** a single-threaded application. The SQLITE_MUTEX_PTHREADS and
|
|
** SQLITE_MUTEX_W32 implementations are appropriate for use on Unix
|
|
** and Windows.
|
|
**
|
|
** If SQLite is compiled with the SQLITE_MUTEX_APPDEF preprocessor
|
|
** macro defined (with "-DSQLITE_MUTEX_APPDEF=1"), then no mutex
|
|
** implementation is included with the library. In this case the
|
|
** application must supply a custom mutex implementation using the
|
|
** [SQLITE_CONFIG_MUTEX] option of the sqlite3_config() function
|
|
** before calling sqlite3_initialize() or any other public sqlite3_
|
|
** function that calls sqlite3_initialize().
|
|
**
|
|
** ^The sqlite3_mutex_alloc() routine allocates a new
|
|
** mutex and returns a pointer to it. ^The sqlite3_mutex_alloc()
|
|
** routine returns NULL if it is unable to allocate the requested
|
|
** mutex. The argument to sqlite3_mutex_alloc() must one of these
|
|
** integer constants:
|
|
**
|
|
** <ul>
|
|
** <li> SQLITE_MUTEX_FAST
|
|
** <li> SQLITE_MUTEX_RECURSIVE
|
|
** <li> SQLITE_MUTEX_STATIC_MAIN
|
|
** <li> SQLITE_MUTEX_STATIC_MEM
|
|
** <li> SQLITE_MUTEX_STATIC_OPEN
|
|
** <li> SQLITE_MUTEX_STATIC_PRNG
|
|
** <li> SQLITE_MUTEX_STATIC_LRU
|
|
** <li> SQLITE_MUTEX_STATIC_PMEM
|
|
** <li> SQLITE_MUTEX_STATIC_APP1
|
|
** <li> SQLITE_MUTEX_STATIC_APP2
|
|
** <li> SQLITE_MUTEX_STATIC_APP3
|
|
** <li> SQLITE_MUTEX_STATIC_VFS1
|
|
** <li> SQLITE_MUTEX_STATIC_VFS2
|
|
** <li> SQLITE_MUTEX_STATIC_VFS3
|
|
** </ul>
|
|
**
|
|
** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE)
|
|
** cause sqlite3_mutex_alloc() to create
|
|
** a new mutex. ^The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
|
|
** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
|
|
** The mutex implementation does not need to make a distinction
|
|
** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
|
|
** not want to. SQLite will only request a recursive mutex in
|
|
** cases where it really needs one. If a faster non-recursive mutex
|
|
** implementation is available on the host platform, the mutex subsystem
|
|
** might return such a mutex in response to SQLITE_MUTEX_FAST.
|
|
**
|
|
** ^The other allowed parameters to sqlite3_mutex_alloc() (anything other
|
|
** than SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE) each return
|
|
** a pointer to a static preexisting mutex. ^Nine static mutexes are
|
|
** used by the current version of SQLite. Future versions of SQLite
|
|
** may add additional static mutexes. Static mutexes are for internal
|
|
** use by SQLite only. Applications that use SQLite mutexes should
|
|
** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
|
|
** SQLITE_MUTEX_RECURSIVE.
|
|
**
|
|
** ^Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
|
|
** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
|
|
** returns a different mutex on every call. ^For the static
|
|
** mutex types, the same mutex is returned on every call that has
|
|
** the same type number.
|
|
**
|
|
** ^The sqlite3_mutex_free() routine deallocates a previously
|
|
** allocated dynamic mutex. Attempting to deallocate a static
|
|
** mutex results in undefined behavior.
|
|
**
|
|
** ^The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
|
|
** to enter a mutex. ^If another thread is already within the mutex,
|
|
** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
|
|
** SQLITE_BUSY. ^The sqlite3_mutex_try() interface returns [SQLITE_OK]
|
|
** upon successful entry. ^(Mutexes created using
|
|
** SQLITE_MUTEX_RECURSIVE can be entered multiple times by the same thread.
|
|
** In such cases, the
|
|
** mutex must be exited an equal number of times before another thread
|
|
** can enter.)^ If the same thread tries to enter any mutex other
|
|
** than an SQLITE_MUTEX_RECURSIVE more than once, the behavior is undefined.
|
|
**
|
|
** ^(Some systems (for example, Windows 95) do not support the operation
|
|
** implemented by sqlite3_mutex_try(). On those systems, sqlite3_mutex_try()
|
|
** will always return SQLITE_BUSY. In most cases the SQLite core only uses
|
|
** sqlite3_mutex_try() as an optimization, so this is acceptable
|
|
** behavior. The exceptions are unix builds that set the
|
|
** SQLITE_ENABLE_SETLK_TIMEOUT build option. In that case a working
|
|
** sqlite3_mutex_try() is required.)^
|
|
**
|
|
** ^The sqlite3_mutex_leave() routine exits a mutex that was
|
|
** previously entered by the same thread. The behavior
|
|
** is undefined if the mutex is not currently entered by the
|
|
** calling thread or is not currently allocated.
|
|
**
|
|
** ^If the argument to sqlite3_mutex_enter(), sqlite3_mutex_try(),
|
|
** sqlite3_mutex_leave(), or sqlite3_mutex_free() is a NULL pointer,
|
|
** then any of the four routines behaves as a no-op.
|
|
**
|
|
** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()].
|
|
*/
|
|
SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int);
|
|
SQLITE_API void sqlite3_mutex_free(sqlite3_mutex*);
|
|
SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex*);
|
|
SQLITE_API int sqlite3_mutex_try(sqlite3_mutex*);
|
|
SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*);
|
|
|
|
/*
|
|
** CAPI3REF: Mutex Methods Object
|
|
**
|
|
** An instance of this structure defines the low-level routines
|
|
** used to allocate and use mutexes.
|
|
**
|
|
** Usually, the default mutex implementations provided by SQLite are
|
|
** sufficient, however the application has the option of substituting a custom
|
|
** implementation for specialized deployments or systems for which SQLite
|
|
** does not provide a suitable implementation. In this case, the application
|
|
** creates and populates an instance of this structure to pass
|
|
** to sqlite3_config() along with the [SQLITE_CONFIG_MUTEX] option.
|
|
** Additionally, an instance of this structure can be used as an
|
|
** output variable when querying the system for the current mutex
|
|
** implementation, using the [SQLITE_CONFIG_GETMUTEX] option.
|
|
**
|
|
** ^The xMutexInit method defined by this structure is invoked as
|
|
** part of system initialization by the sqlite3_initialize() function.
|
|
** ^The xMutexInit routine is called by SQLite exactly once for each
|
|
** effective call to [sqlite3_initialize()].
|
|
**
|
|
** ^The xMutexEnd method defined by this structure is invoked as
|
|
** part of system shutdown by the sqlite3_shutdown() function. The
|
|
** implementation of this method is expected to release all outstanding
|
|
** resources obtained by the mutex methods implementation, especially
|
|
** those obtained by the xMutexInit method. ^The xMutexEnd()
|
|
** interface is invoked exactly once for each call to [sqlite3_shutdown()].
|
|
**
|
|
** ^(The remaining seven methods defined by this structure (xMutexAlloc,
|
|
** xMutexFree, xMutexEnter, xMutexTry, xMutexLeave, xMutexHeld and
|
|
** xMutexNotheld) implement the following interfaces (respectively):
|
|
**
|
|
** <ul>
|
|
** <li> [sqlite3_mutex_alloc()] </li>
|
|
** <li> [sqlite3_mutex_free()] </li>
|
|
** <li> [sqlite3_mutex_enter()] </li>
|
|
** <li> [sqlite3_mutex_try()] </li>
|
|
** <li> [sqlite3_mutex_leave()] </li>
|
|
** <li> [sqlite3_mutex_held()] </li>
|
|
** <li> [sqlite3_mutex_notheld()] </li>
|
|
** </ul>)^
|
|
**
|
|
** The only difference is that the public sqlite3_XXX functions enumerated
|
|
** above silently ignore any invocations that pass a NULL pointer instead
|
|
** of a valid mutex handle. The implementations of the methods defined
|
|
** by this structure are not required to handle this case. The results
|
|
** of passing a NULL pointer instead of a valid mutex handle are undefined
|
|
** (i.e. it is acceptable to provide an implementation that segfaults if
|
|
** it is passed a NULL pointer).
|
|
**
|
|
** The xMutexInit() method must be threadsafe. It must be harmless to
|
|
** invoke xMutexInit() multiple times within the same process and without
|
|
** intervening calls to xMutexEnd(). Second and subsequent calls to
|
|
** xMutexInit() must be no-ops.
|
|
**
|
|
** xMutexInit() must not use SQLite memory allocation ([sqlite3_malloc()]
|
|
** and its associates). Similarly, xMutexAlloc() must not use SQLite memory
|
|
** allocation for a static mutex. ^However xMutexAlloc() may use SQLite
|
|
** memory allocation for a fast or recursive mutex.
|
|
**
|
|
** ^SQLite will invoke the xMutexEnd() method when [sqlite3_shutdown()] is
|
|
** called, but only if the prior call to xMutexInit returned SQLITE_OK.
|
|
** If xMutexInit fails in any way, it is expected to clean up after itself
|
|
** prior to returning.
|
|
*/
|
|
typedef struct sqlite3_mutex_methods sqlite3_mutex_methods;
|
|
struct sqlite3_mutex_methods {
|
|
int (*xMutexInit)(void);
|
|
int (*xMutexEnd)(void);
|
|
sqlite3_mutex *(*xMutexAlloc)(int);
|
|
void (*xMutexFree)(sqlite3_mutex *);
|
|
void (*xMutexEnter)(sqlite3_mutex *);
|
|
int (*xMutexTry)(sqlite3_mutex *);
|
|
void (*xMutexLeave)(sqlite3_mutex *);
|
|
int (*xMutexHeld)(sqlite3_mutex *);
|
|
int (*xMutexNotheld)(sqlite3_mutex *);
|
|
};
|
|
|
|
/*
|
|
** CAPI3REF: Mutex Verification Routines
|
|
**
|
|
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routines
|
|
** are intended for use inside assert() statements. The SQLite core
|
|
** never uses these routines except inside an assert() and applications
|
|
** are advised to follow the lead of the core. The SQLite core only
|
|
** provides implementations for these routines when it is compiled
|
|
** with the SQLITE_DEBUG flag. External mutex implementations
|
|
** are only required to provide these routines if SQLITE_DEBUG is
|
|
** defined and if NDEBUG is not defined.
|
|
**
|
|
** These routines should return true if the mutex in their argument
|
|
** is held or not held, respectively, by the calling thread.
|
|
**
|
|
** The implementation is not required to provide versions of these
|
|
** routines that actually work. If the implementation does not provide working
|
|
** versions of these routines, it should at least provide stubs that always
|
|
** return true so that one does not get spurious assertion failures.
|
|
**
|
|
** If the argument to sqlite3_mutex_held() is a NULL pointer then
|
|
** the routine should return 1. This seems counter-intuitive since
|
|
** clearly the mutex cannot be held if it does not exist. But
|
|
** the reason the mutex does not exist is because the build is not
|
|
** using mutexes. And we do not want the assert() containing the
|
|
** call to sqlite3_mutex_held() to fail, so a non-zero return is
|
|
** the appropriate thing to do. The sqlite3_mutex_notheld()
|
|
** interface should also return 1 when given a NULL pointer.
|
|
*/
|
|
#ifndef NDEBUG
|
|
SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*);
|
|
SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*);
|
|
#endif
|
|
|
|
/*
|
|
** CAPI3REF: Mutex Types
|
|
**
|
|
** The [sqlite3_mutex_alloc()] interface takes a single argument
|
|
** which is one of these integer constants.
|
|
**
|
|
** The set of static mutexes may change from one SQLite release to the
|
|
** next. Applications that override the built-in mutex logic must be
|
|
** prepared to accommodate additional static mutexes.
|
|
*/
|
|
#define SQLITE_MUTEX_FAST 0
|
|
#define SQLITE_MUTEX_RECURSIVE 1
|
|
#define SQLITE_MUTEX_STATIC_MAIN 2
|
|
#define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */
|
|
#define SQLITE_MUTEX_STATIC_MEM2 4 /* NOT USED */
|
|
#define SQLITE_MUTEX_STATIC_OPEN 4 /* sqlite3BtreeOpen() */
|
|
#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_randomness() */
|
|
#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */
|
|
#define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */
|
|
#define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */
|
|
#define SQLITE_MUTEX_STATIC_APP1 8 /* For use by application */
|
|
#define SQLITE_MUTEX_STATIC_APP2 9 /* For use by application */
|
|
#define SQLITE_MUTEX_STATIC_APP3 10 /* For use by application */
|
|
#define SQLITE_MUTEX_STATIC_VFS1 11 /* For use by built-in VFS */
|
|
#define SQLITE_MUTEX_STATIC_VFS2 12 /* For use by extension VFS */
|
|
#define SQLITE_MUTEX_STATIC_VFS3 13 /* For use by application VFS */
|
|
|
|
/* Legacy compatibility: */
|
|
#define SQLITE_MUTEX_STATIC_MASTER 2
|
|
|
|
|
|
/*
|
|
** CAPI3REF: Retrieve the mutex for a database connection
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^This interface returns a pointer the [sqlite3_mutex] object that
|
|
** serializes access to the [database connection] given in the argument
|
|
** when the [threading mode] is Serialized.
|
|
** ^If the [threading mode] is Single-thread or Multi-thread then this
|
|
** routine returns a NULL pointer.
|
|
*/
|
|
SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
|
|
|
|
/*
|
|
** CAPI3REF: Low-Level Control Of Database Files
|
|
** METHOD: sqlite3
|
|
** KEYWORDS: {file control}
|
|
**
|
|
** ^The [sqlite3_file_control()] interface makes a direct call to the
|
|
** xFileControl method for the [sqlite3_io_methods] object associated
|
|
** with a particular database identified by the second argument. ^The
|
|
** name of the database is "main" for the main database or "temp" for the
|
|
** TEMP database, or the name that appears after the AS keyword for
|
|
** databases that are added using the [ATTACH] SQL command.
|
|
** ^A NULL pointer can be used in place of "main" to refer to the
|
|
** main database file.
|
|
** ^The third and fourth parameters to this routine
|
|
** are passed directly through to the second and third parameters of
|
|
** the xFileControl method. ^The return value of the xFileControl
|
|
** method becomes the return value of this routine.
|
|
**
|
|
** A few opcodes for [sqlite3_file_control()] are handled directly
|
|
** by the SQLite core and never invoke the
|
|
** sqlite3_io_methods.xFileControl method.
|
|
** ^The [SQLITE_FCNTL_FILE_POINTER] value for the op parameter causes
|
|
** a pointer to the underlying [sqlite3_file] object to be written into
|
|
** the space pointed to by the 4th parameter. The
|
|
** [SQLITE_FCNTL_JOURNAL_POINTER] works similarly except that it returns
|
|
** the [sqlite3_file] object associated with the journal file instead of
|
|
** the main database. The [SQLITE_FCNTL_VFS_POINTER] opcode returns
|
|
** a pointer to the underlying [sqlite3_vfs] object for the file.
|
|
** The [SQLITE_FCNTL_DATA_VERSION] returns the data version counter
|
|
** from the pager.
|
|
**
|
|
** ^If the second parameter (zDbName) does not match the name of any
|
|
** open database file, then SQLITE_ERROR is returned. ^This error
|
|
** code is not remembered and will not be recalled by [sqlite3_errcode()]
|
|
** or [sqlite3_errmsg()]. The underlying xFileControl method might
|
|
** also return SQLITE_ERROR. There is no way to distinguish between
|
|
** an incorrect zDbName and an SQLITE_ERROR return from the underlying
|
|
** xFileControl method.
|
|
**
|
|
** See also: [file control opcodes]
|
|
*/
|
|
SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*);
|
|
|
|
/*
|
|
** CAPI3REF: Testing Interface
|
|
**
|
|
** ^The sqlite3_test_control() interface is used to read out internal
|
|
** state of SQLite and to inject faults into SQLite for testing
|
|
** purposes. ^The first parameter is an operation code that determines
|
|
** the number, meaning, and operation of all subsequent parameters.
|
|
**
|
|
** This interface is not for use by applications. It exists solely
|
|
** for verifying the correct operation of the SQLite library. Depending
|
|
** on how the SQLite library is compiled, this interface might not exist.
|
|
**
|
|
** The details of the operation codes, their meanings, the parameters
|
|
** they take, and what they do are all subject to change without notice.
|
|
** Unlike most of the SQLite API, this function is not guaranteed to
|
|
** operate consistently from one release to the next.
|
|
*/
|
|
SQLITE_API int sqlite3_test_control(int op, ...);
|
|
|
|
/*
|
|
** CAPI3REF: Testing Interface Operation Codes
|
|
**
|
|
** These constants are the valid operation code parameters used
|
|
** as the first argument to [sqlite3_test_control()].
|
|
**
|
|
** These parameters and their meanings are subject to change
|
|
** without notice. These values are for testing purposes only.
|
|
** Applications should not use any of these parameters or the
|
|
** [sqlite3_test_control()] interface.
|
|
*/
|
|
#define SQLITE_TESTCTRL_FIRST 5
|
|
#define SQLITE_TESTCTRL_PRNG_SAVE 5
|
|
#define SQLITE_TESTCTRL_PRNG_RESTORE 6
|
|
#define SQLITE_TESTCTRL_PRNG_RESET 7 /* NOT USED */
|
|
#define SQLITE_TESTCTRL_FK_NO_ACTION 7
|
|
#define SQLITE_TESTCTRL_BITVEC_TEST 8
|
|
#define SQLITE_TESTCTRL_FAULT_INSTALL 9
|
|
#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10
|
|
#define SQLITE_TESTCTRL_PENDING_BYTE 11
|
|
#define SQLITE_TESTCTRL_ASSERT 12
|
|
#define SQLITE_TESTCTRL_ALWAYS 13
|
|
#define SQLITE_TESTCTRL_RESERVE 14 /* NOT USED */
|
|
#define SQLITE_TESTCTRL_JSON_SELFCHECK 14
|
|
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
|
|
#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */
|
|
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */
|
|
#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17
|
|
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
|
|
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */
|
|
#define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19
|
|
#define SQLITE_TESTCTRL_NEVER_CORRUPT 20
|
|
#define SQLITE_TESTCTRL_VDBE_COVERAGE 21
|
|
#define SQLITE_TESTCTRL_BYTEORDER 22
|
|
#define SQLITE_TESTCTRL_ISINIT 23
|
|
#define SQLITE_TESTCTRL_SORTER_MMAP 24
|
|
#define SQLITE_TESTCTRL_IMPOSTER 25
|
|
#define SQLITE_TESTCTRL_PARSER_COVERAGE 26
|
|
#define SQLITE_TESTCTRL_RESULT_INTREAL 27
|
|
#define SQLITE_TESTCTRL_PRNG_SEED 28
|
|
#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29
|
|
#define SQLITE_TESTCTRL_SEEK_COUNT 30
|
|
#define SQLITE_TESTCTRL_TRACEFLAGS 31
|
|
#define SQLITE_TESTCTRL_TUNE 32
|
|
#define SQLITE_TESTCTRL_LOGEST 33
|
|
#define SQLITE_TESTCTRL_USELONGDOUBLE 34
|
|
#define SQLITE_TESTCTRL_LAST 34 /* Largest TESTCTRL */
|
|
|
|
/*
|
|
** CAPI3REF: SQL Keyword Checking
|
|
**
|
|
** These routines provide access to the set of SQL language keywords
|
|
** recognized by SQLite. Applications can uses these routines to determine
|
|
** whether or not a specific identifier needs to be escaped (for example,
|
|
** by enclosing in double-quotes) so as not to confuse the parser.
|
|
**
|
|
** The sqlite3_keyword_count() interface returns the number of distinct
|
|
** keywords understood by SQLite.
|
|
**
|
|
** The sqlite3_keyword_name(N,Z,L) interface finds the N-th keyword and
|
|
** makes *Z point to that keyword expressed as UTF8 and writes the number
|
|
** of bytes in the keyword into *L. The string that *Z points to is not
|
|
** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns
|
|
** SQLITE_OK if N is within bounds and SQLITE_ERROR if not. If either Z
|
|
** or L are NULL or invalid pointers then calls to
|
|
** sqlite3_keyword_name(N,Z,L) result in undefined behavior.
|
|
**
|
|
** The sqlite3_keyword_check(Z,L) interface checks to see whether or not
|
|
** the L-byte UTF8 identifier that Z points to is a keyword, returning non-zero
|
|
** if it is and zero if not.
|
|
**
|
|
** The parser used by SQLite is forgiving. It is often possible to use
|
|
** a keyword as an identifier as long as such use does not result in a
|
|
** parsing ambiguity. For example, the statement
|
|
** "CREATE TABLE BEGIN(REPLACE,PRAGMA,END);" is accepted by SQLite, and
|
|
** creates a new table named "BEGIN" with three columns named
|
|
** "REPLACE", "PRAGMA", and "END". Nevertheless, best practice is to avoid
|
|
** using keywords as identifiers. Common techniques used to avoid keyword
|
|
** name collisions include:
|
|
** <ul>
|
|
** <li> Put all identifier names inside double-quotes. This is the official
|
|
** SQL way to escape identifier names.
|
|
** <li> Put identifier names inside [...]. This is not standard SQL,
|
|
** but it is what SQL Server does and so lots of programmers use this
|
|
** technique.
|
|
** <li> Begin every identifier with the letter "Z" as no SQL keywords start
|
|
** with "Z".
|
|
** <li> Include a digit somewhere in every identifier name.
|
|
** </ul>
|
|
**
|
|
** Note that the number of keywords understood by SQLite can depend on
|
|
** compile-time options. For example, "VACUUM" is not a keyword if
|
|
** SQLite is compiled with the [-DSQLITE_OMIT_VACUUM] option. Also,
|
|
** new keywords may be added to future releases of SQLite.
|
|
*/
|
|
SQLITE_API int sqlite3_keyword_count(void);
|
|
SQLITE_API int sqlite3_keyword_name(int,const char**,int*);
|
|
SQLITE_API int sqlite3_keyword_check(const char*,int);
|
|
|
|
/*
|
|
** CAPI3REF: Dynamic String Object
|
|
** KEYWORDS: {dynamic string}
|
|
**
|
|
** An instance of the sqlite3_str object contains a dynamically-sized
|
|
** string under construction.
|
|
**
|
|
** The lifecycle of an sqlite3_str object is as follows:
|
|
** <ol>
|
|
** <li> ^The sqlite3_str object is created using [sqlite3_str_new()].
|
|
** <li> ^Text is appended to the sqlite3_str object using various
|
|
** methods, such as [sqlite3_str_appendf()].
|
|
** <li> ^The sqlite3_str object is destroyed and the string it created
|
|
** is returned using the [sqlite3_str_finish()] interface.
|
|
** </ol>
|
|
*/
|
|
typedef struct sqlite3_str sqlite3_str;
|
|
|
|
/*
|
|
** CAPI3REF: Create A New Dynamic String Object
|
|
** CONSTRUCTOR: sqlite3_str
|
|
**
|
|
** ^The [sqlite3_str_new(D)] interface allocates and initializes
|
|
** a new [sqlite3_str] object. To avoid memory leaks, the object returned by
|
|
** [sqlite3_str_new()] must be freed by a subsequent call to
|
|
** [sqlite3_str_finish(X)].
|
|
**
|
|
** ^The [sqlite3_str_new(D)] interface always returns a pointer to a
|
|
** valid [sqlite3_str] object, though in the event of an out-of-memory
|
|
** error the returned object might be a special singleton that will
|
|
** silently reject new text, always return SQLITE_NOMEM from
|
|
** [sqlite3_str_errcode()], always return 0 for
|
|
** [sqlite3_str_length()], and always return NULL from
|
|
** [sqlite3_str_finish(X)]. It is always safe to use the value
|
|
** returned by [sqlite3_str_new(D)] as the sqlite3_str parameter
|
|
** to any of the other [sqlite3_str] methods.
|
|
**
|
|
** The D parameter to [sqlite3_str_new(D)] may be NULL. If the
|
|
** D parameter in [sqlite3_str_new(D)] is not NULL, then the maximum
|
|
** length of the string contained in the [sqlite3_str] object will be
|
|
** the value set for [sqlite3_limit](D,[SQLITE_LIMIT_LENGTH]) instead
|
|
** of [SQLITE_MAX_LENGTH].
|
|
*/
|
|
SQLITE_API sqlite3_str *sqlite3_str_new(sqlite3*);
|
|
|
|
/*
|
|
** CAPI3REF: Finalize A Dynamic String
|
|
** DESTRUCTOR: sqlite3_str
|
|
**
|
|
** ^The [sqlite3_str_finish(X)] interface destroys the sqlite3_str object X
|
|
** and returns a pointer to a memory buffer obtained from [sqlite3_malloc64()]
|
|
** that contains the constructed string. The calling application should
|
|
** pass the returned value to [sqlite3_free()] to avoid a memory leak.
|
|
** ^The [sqlite3_str_finish(X)] interface may return a NULL pointer if any
|
|
** errors were encountered during construction of the string. ^The
|
|
** [sqlite3_str_finish(X)] interface will also return a NULL pointer if the
|
|
** string in [sqlite3_str] object X is zero bytes long.
|
|
*/
|
|
SQLITE_API char *sqlite3_str_finish(sqlite3_str*);
|
|
|
|
/*
|
|
** CAPI3REF: Add Content To A Dynamic String
|
|
** METHOD: sqlite3_str
|
|
**
|
|
** These interfaces add content to an sqlite3_str object previously obtained
|
|
** from [sqlite3_str_new()].
|
|
**
|
|
** ^The [sqlite3_str_appendf(X,F,...)] and
|
|
** [sqlite3_str_vappendf(X,F,V)] interfaces uses the [built-in printf]
|
|
** functionality of SQLite to append formatted text onto the end of
|
|
** [sqlite3_str] object X.
|
|
**
|
|
** ^The [sqlite3_str_append(X,S,N)] method appends exactly N bytes from string S
|
|
** onto the end of the [sqlite3_str] object X. N must be non-negative.
|
|
** S must contain at least N non-zero bytes of content. To append a
|
|
** zero-terminated string in its entirety, use the [sqlite3_str_appendall()]
|
|
** method instead.
|
|
**
|
|
** ^The [sqlite3_str_appendall(X,S)] method appends the complete content of
|
|
** zero-terminated string S onto the end of [sqlite3_str] object X.
|
|
**
|
|
** ^The [sqlite3_str_appendchar(X,N,C)] method appends N copies of the
|
|
** single-byte character C onto the end of [sqlite3_str] object X.
|
|
** ^This method can be used, for example, to add whitespace indentation.
|
|
**
|
|
** ^The [sqlite3_str_reset(X)] method resets the string under construction
|
|
** inside [sqlite3_str] object X back to zero bytes in length.
|
|
**
|
|
** These methods do not return a result code. ^If an error occurs, that fact
|
|
** is recorded in the [sqlite3_str] object and can be recovered by a
|
|
** subsequent call to [sqlite3_str_errcode(X)].
|
|
*/
|
|
SQLITE_API void sqlite3_str_appendf(sqlite3_str*, const char *zFormat, ...);
|
|
SQLITE_API void sqlite3_str_vappendf(sqlite3_str*, const char *zFormat, va_list);
|
|
SQLITE_API void sqlite3_str_append(sqlite3_str*, const char *zIn, int N);
|
|
SQLITE_API void sqlite3_str_appendall(sqlite3_str*, const char *zIn);
|
|
SQLITE_API void sqlite3_str_appendchar(sqlite3_str*, int N, char C);
|
|
SQLITE_API void sqlite3_str_reset(sqlite3_str*);
|
|
|
|
/*
|
|
** CAPI3REF: Status Of A Dynamic String
|
|
** METHOD: sqlite3_str
|
|
**
|
|
** These interfaces return the current status of an [sqlite3_str] object.
|
|
**
|
|
** ^If any prior errors have occurred while constructing the dynamic string
|
|
** in sqlite3_str X, then the [sqlite3_str_errcode(X)] method will return
|
|
** an appropriate error code. ^The [sqlite3_str_errcode(X)] method returns
|
|
** [SQLITE_NOMEM] following any out-of-memory error, or
|
|
** [SQLITE_TOOBIG] if the size of the dynamic string exceeds
|
|
** [SQLITE_MAX_LENGTH], or [SQLITE_OK] if there have been no errors.
|
|
**
|
|
** ^The [sqlite3_str_length(X)] method returns the current length, in bytes,
|
|
** of the dynamic string under construction in [sqlite3_str] object X.
|
|
** ^The length returned by [sqlite3_str_length(X)] does not include the
|
|
** zero-termination byte.
|
|
**
|
|
** ^The [sqlite3_str_value(X)] method returns a pointer to the current
|
|
** content of the dynamic string under construction in X. The value
|
|
** returned by [sqlite3_str_value(X)] is managed by the sqlite3_str object X
|
|
** and might be freed or altered by any subsequent method on the same
|
|
** [sqlite3_str] object. Applications must not used the pointer returned
|
|
** [sqlite3_str_value(X)] after any subsequent method call on the same
|
|
** object. ^Applications may change the content of the string returned
|
|
** by [sqlite3_str_value(X)] as long as they do not write into any bytes
|
|
** outside the range of 0 to [sqlite3_str_length(X)] and do not read or
|
|
** write any byte after any subsequent sqlite3_str method call.
|
|
*/
|
|
SQLITE_API int sqlite3_str_errcode(sqlite3_str*);
|
|
SQLITE_API int sqlite3_str_length(sqlite3_str*);
|
|
SQLITE_API char *sqlite3_str_value(sqlite3_str*);
|
|
|
|
/*
|
|
** CAPI3REF: SQLite Runtime Status
|
|
**
|
|
** ^These interfaces are used to retrieve runtime status information
|
|
** about the performance of SQLite, and optionally to reset various
|
|
** highwater marks. ^The first argument is an integer code for
|
|
** the specific parameter to measure. ^(Recognized integer codes
|
|
** are of the form [status parameters | SQLITE_STATUS_...].)^
|
|
** ^The current value of the parameter is returned into *pCurrent.
|
|
** ^The highest recorded value is returned in *pHighwater. ^If the
|
|
** resetFlag is true, then the highest record value is reset after
|
|
** *pHighwater is written. ^(Some parameters do not record the highest
|
|
** value. For those parameters
|
|
** nothing is written into *pHighwater and the resetFlag is ignored.)^
|
|
** ^(Other parameters record only the highwater mark and not the current
|
|
** value. For these latter parameters nothing is written into *pCurrent.)^
|
|
**
|
|
** ^The sqlite3_status() and sqlite3_status64() routines return
|
|
** SQLITE_OK on success and a non-zero [error code] on failure.
|
|
**
|
|
** If either the current value or the highwater mark is too large to
|
|
** be represented by a 32-bit integer, then the values returned by
|
|
** sqlite3_status() are undefined.
|
|
**
|
|
** See also: [sqlite3_db_status()]
|
|
*/
|
|
SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
|
|
SQLITE_API int sqlite3_status64(
|
|
int op,
|
|
sqlite3_int64 *pCurrent,
|
|
sqlite3_int64 *pHighwater,
|
|
int resetFlag
|
|
);
|
|
|
|
|
|
/*
|
|
** CAPI3REF: Status Parameters
|
|
** KEYWORDS: {status parameters}
|
|
**
|
|
** These integer constants designate various run-time status parameters
|
|
** that can be returned by [sqlite3_status()].
|
|
**
|
|
** <dl>
|
|
** [[SQLITE_STATUS_MEMORY_USED]] ^(<dt>SQLITE_STATUS_MEMORY_USED</dt>
|
|
** <dd>This parameter is the current amount of memory checked out
|
|
** using [sqlite3_malloc()], either directly or indirectly. The
|
|
** figure includes calls made to [sqlite3_malloc()] by the application
|
|
** and internal memory usage by the SQLite library. Auxiliary page-cache
|
|
** memory controlled by [SQLITE_CONFIG_PAGECACHE] is not included in
|
|
** this parameter. The amount returned is the sum of the allocation
|
|
** sizes as reported by the xSize method in [sqlite3_mem_methods].</dd>)^
|
|
**
|
|
** [[SQLITE_STATUS_MALLOC_SIZE]] ^(<dt>SQLITE_STATUS_MALLOC_SIZE</dt>
|
|
** <dd>This parameter records the largest memory allocation request
|
|
** handed to [sqlite3_malloc()] or [sqlite3_realloc()] (or their
|
|
** internal equivalents). Only the value returned in the
|
|
** *pHighwater parameter to [sqlite3_status()] is of interest.
|
|
** The value written into the *pCurrent parameter is undefined.</dd>)^
|
|
**
|
|
** [[SQLITE_STATUS_MALLOC_COUNT]] ^(<dt>SQLITE_STATUS_MALLOC_COUNT</dt>
|
|
** <dd>This parameter records the number of separate memory allocations
|
|
** currently checked out.</dd>)^
|
|
**
|
|
** [[SQLITE_STATUS_PAGECACHE_USED]] ^(<dt>SQLITE_STATUS_PAGECACHE_USED</dt>
|
|
** <dd>This parameter returns the number of pages used out of the
|
|
** [pagecache memory allocator] that was configured using
|
|
** [SQLITE_CONFIG_PAGECACHE]. The
|
|
** value returned is in pages, not in bytes.</dd>)^
|
|
**
|
|
** [[SQLITE_STATUS_PAGECACHE_OVERFLOW]]
|
|
** ^(<dt>SQLITE_STATUS_PAGECACHE_OVERFLOW</dt>
|
|
** <dd>This parameter returns the number of bytes of page cache
|
|
** allocation which could not be satisfied by the [SQLITE_CONFIG_PAGECACHE]
|
|
** buffer and where forced to overflow to [sqlite3_malloc()]. The
|
|
** returned value includes allocations that overflowed because they
|
|
** where too large (they were larger than the "sz" parameter to
|
|
** [SQLITE_CONFIG_PAGECACHE]) and allocations that overflowed because
|
|
** no space was left in the page cache.</dd>)^
|
|
**
|
|
** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
|
|
** <dd>This parameter records the largest memory allocation request
|
|
** handed to the [pagecache memory allocator]. Only the value returned in the
|
|
** *pHighwater parameter to [sqlite3_status()] is of interest.
|
|
** The value written into the *pCurrent parameter is undefined.</dd>)^
|
|
**
|
|
** [[SQLITE_STATUS_SCRATCH_USED]] <dt>SQLITE_STATUS_SCRATCH_USED</dt>
|
|
** <dd>No longer used.</dd>
|
|
**
|
|
** [[SQLITE_STATUS_SCRATCH_OVERFLOW]] ^(<dt>SQLITE_STATUS_SCRATCH_OVERFLOW</dt>
|
|
** <dd>No longer used.</dd>
|
|
**
|
|
** [[SQLITE_STATUS_SCRATCH_SIZE]] <dt>SQLITE_STATUS_SCRATCH_SIZE</dt>
|
|
** <dd>No longer used.</dd>
|
|
**
|
|
** [[SQLITE_STATUS_PARSER_STACK]] ^(<dt>SQLITE_STATUS_PARSER_STACK</dt>
|
|
** <dd>The *pHighwater parameter records the deepest parser stack.
|
|
** The *pCurrent value is undefined. The *pHighwater value is only
|
|
** meaningful if SQLite is compiled with [YYTRACKMAXSTACKDEPTH].</dd>)^
|
|
** </dl>
|
|
**
|
|
** New status parameters may be added from time to time.
|
|
*/
|
|
#define SQLITE_STATUS_MEMORY_USED 0
|
|
#define SQLITE_STATUS_PAGECACHE_USED 1
|
|
#define SQLITE_STATUS_PAGECACHE_OVERFLOW 2
|
|
#define SQLITE_STATUS_SCRATCH_USED 3 /* NOT USED */
|
|
#define SQLITE_STATUS_SCRATCH_OVERFLOW 4 /* NOT USED */
|
|
#define SQLITE_STATUS_MALLOC_SIZE 5
|
|
#define SQLITE_STATUS_PARSER_STACK 6
|
|
#define SQLITE_STATUS_PAGECACHE_SIZE 7
|
|
#define SQLITE_STATUS_SCRATCH_SIZE 8 /* NOT USED */
|
|
#define SQLITE_STATUS_MALLOC_COUNT 9
|
|
|
|
/*
|
|
** CAPI3REF: Database Connection Status
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^This interface is used to retrieve runtime status information
|
|
** about a single [database connection]. ^The first argument is the
|
|
** database connection object to be interrogated. ^The second argument
|
|
** is an integer constant, taken from the set of
|
|
** [SQLITE_DBSTATUS options], that
|
|
** determines the parameter to interrogate. The set of
|
|
** [SQLITE_DBSTATUS options] is likely
|
|
** to grow in future releases of SQLite.
|
|
**
|
|
** ^The current value of the requested parameter is written into *pCur
|
|
** and the highest instantaneous value is written into *pHiwtr. ^If
|
|
** the resetFlg is true, then the highest instantaneous value is
|
|
** reset back down to the current value.
|
|
**
|
|
** ^The sqlite3_db_status() routine returns SQLITE_OK on success and a
|
|
** non-zero [error code] on failure.
|
|
**
|
|
** See also: [sqlite3_status()] and [sqlite3_stmt_status()].
|
|
*/
|
|
SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
|
|
|
|
/*
|
|
** CAPI3REF: Status Parameters for database connections
|
|
** KEYWORDS: {SQLITE_DBSTATUS options}
|
|
**
|
|
** These constants are the available integer "verbs" that can be passed as
|
|
** the second argument to the [sqlite3_db_status()] interface.
|
|
**
|
|
** New verbs may be added in future releases of SQLite. Existing verbs
|
|
** might be discontinued. Applications should check the return code from
|
|
** [sqlite3_db_status()] to make sure that the call worked.
|
|
** The [sqlite3_db_status()] interface will return a non-zero error code
|
|
** if a discontinued or unsupported verb is invoked.
|
|
**
|
|
** <dl>
|
|
** [[SQLITE_DBSTATUS_LOOKASIDE_USED]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_USED</dt>
|
|
** <dd>This parameter returns the number of lookaside memory slots currently
|
|
** checked out.</dd>)^
|
|
**
|
|
** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
|
|
** <dd>This parameter returns the number of malloc attempts that were
|
|
** satisfied using lookaside memory. Only the high-water value is meaningful;
|
|
** the current value is always zero.)^
|
|
**
|
|
** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE]]
|
|
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE</dt>
|
|
** <dd>This parameter returns the number malloc attempts that might have
|
|
** been satisfied using lookaside memory but failed due to the amount of
|
|
** memory requested being larger than the lookaside slot size.
|
|
** Only the high-water value is meaningful;
|
|
** the current value is always zero.)^
|
|
**
|
|
** [[SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL]]
|
|
** ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL</dt>
|
|
** <dd>This parameter returns the number malloc attempts that might have
|
|
** been satisfied using lookaside memory but failed due to all lookaside
|
|
** memory already being in use.
|
|
** Only the high-water value is meaningful;
|
|
** the current value is always zero.)^
|
|
**
|
|
** [[SQLITE_DBSTATUS_CACHE_USED]] ^(<dt>SQLITE_DBSTATUS_CACHE_USED</dt>
|
|
** <dd>This parameter returns the approximate number of bytes of heap
|
|
** memory used by all pager caches associated with the database connection.)^
|
|
** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
|
|
**
|
|
** [[SQLITE_DBSTATUS_CACHE_USED_SHARED]]
|
|
** ^(<dt>SQLITE_DBSTATUS_CACHE_USED_SHARED</dt>
|
|
** <dd>This parameter is similar to DBSTATUS_CACHE_USED, except that if a
|
|
** pager cache is shared between two or more connections the bytes of heap
|
|
** memory used by that pager cache is divided evenly between the attached
|
|
** connections.)^ In other words, if none of the pager caches associated
|
|
** with the database connection are shared, this request returns the same
|
|
** value as DBSTATUS_CACHE_USED. Or, if one or more or the pager caches are
|
|
** shared, the value returned by this call will be smaller than that returned
|
|
** by DBSTATUS_CACHE_USED. ^The highwater mark associated with
|
|
** SQLITE_DBSTATUS_CACHE_USED_SHARED is always 0.
|
|
**
|
|
** [[SQLITE_DBSTATUS_SCHEMA_USED]] ^(<dt>SQLITE_DBSTATUS_SCHEMA_USED</dt>
|
|
** <dd>This parameter returns the approximate number of bytes of heap
|
|
** memory used to store the schema for all databases associated
|
|
** with the connection - main, temp, and any [ATTACH]-ed databases.)^
|
|
** ^The full amount of memory used by the schemas is reported, even if the
|
|
** schema memory is shared with other database connections due to
|
|
** [shared cache mode] being enabled.
|
|
** ^The highwater mark associated with SQLITE_DBSTATUS_SCHEMA_USED is always 0.
|
|
**
|
|
** [[SQLITE_DBSTATUS_STMT_USED]] ^(<dt>SQLITE_DBSTATUS_STMT_USED</dt>
|
|
** <dd>This parameter returns the approximate number of bytes of heap
|
|
** and lookaside memory used by all prepared statements associated with
|
|
** the database connection.)^
|
|
** ^The highwater mark associated with SQLITE_DBSTATUS_STMT_USED is always 0.
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_DBSTATUS_CACHE_HIT]] ^(<dt>SQLITE_DBSTATUS_CACHE_HIT</dt>
|
|
** <dd>This parameter returns the number of pager cache hits that have
|
|
** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_HIT
|
|
** is always 0.
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_DBSTATUS_CACHE_MISS]] ^(<dt>SQLITE_DBSTATUS_CACHE_MISS</dt>
|
|
** <dd>This parameter returns the number of pager cache misses that have
|
|
** occurred.)^ ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_MISS
|
|
** is always 0.
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_DBSTATUS_CACHE_WRITE]] ^(<dt>SQLITE_DBSTATUS_CACHE_WRITE</dt>
|
|
** <dd>This parameter returns the number of dirty cache entries that have
|
|
** been written to disk. Specifically, the number of pages written to the
|
|
** wal file in wal mode databases, or the number of pages written to the
|
|
** database file in rollback mode databases. Any pages written as part of
|
|
** transaction rollback or database recovery operations are not included.
|
|
** If an IO or other error occurs while writing a page to disk, the effect
|
|
** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The
|
|
** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0.
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_DBSTATUS_CACHE_SPILL]] ^(<dt>SQLITE_DBSTATUS_CACHE_SPILL</dt>
|
|
** <dd>This parameter returns the number of dirty cache entries that have
|
|
** been written to disk in the middle of a transaction due to the page
|
|
** cache overflowing. Transactions are more efficient if they are written
|
|
** to disk all at once. When pages spill mid-transaction, that introduces
|
|
** additional overhead. This parameter can be used help identify
|
|
** inefficiencies that can be resolved by increasing the cache size.
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(<dt>SQLITE_DBSTATUS_DEFERRED_FKS</dt>
|
|
** <dd>This parameter returns zero for the current value if and only if
|
|
** all foreign key constraints (deferred or immediate) have been
|
|
** resolved.)^ ^The highwater mark is always 0.
|
|
** </dd>
|
|
** </dl>
|
|
*/
|
|
#define SQLITE_DBSTATUS_LOOKASIDE_USED 0
|
|
#define SQLITE_DBSTATUS_CACHE_USED 1
|
|
#define SQLITE_DBSTATUS_SCHEMA_USED 2
|
|
#define SQLITE_DBSTATUS_STMT_USED 3
|
|
#define SQLITE_DBSTATUS_LOOKASIDE_HIT 4
|
|
#define SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE 5
|
|
#define SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL 6
|
|
#define SQLITE_DBSTATUS_CACHE_HIT 7
|
|
#define SQLITE_DBSTATUS_CACHE_MISS 8
|
|
#define SQLITE_DBSTATUS_CACHE_WRITE 9
|
|
#define SQLITE_DBSTATUS_DEFERRED_FKS 10
|
|
#define SQLITE_DBSTATUS_CACHE_USED_SHARED 11
|
|
#define SQLITE_DBSTATUS_CACHE_SPILL 12
|
|
#define SQLITE_DBSTATUS_MAX 12 /* Largest defined DBSTATUS */
|
|
|
|
|
|
/*
|
|
** CAPI3REF: Prepared Statement Status
|
|
** METHOD: sqlite3_stmt
|
|
**
|
|
** ^(Each prepared statement maintains various
|
|
** [SQLITE_STMTSTATUS counters] that measure the number
|
|
** of times it has performed specific operations.)^ These counters can
|
|
** be used to monitor the performance characteristics of the prepared
|
|
** statements. For example, if the number of table steps greatly exceeds
|
|
** the number of table searches or result rows, that would tend to indicate
|
|
** that the prepared statement is using a full table scan rather than
|
|
** an index.
|
|
**
|
|
** ^(This interface is used to retrieve and reset counter values from
|
|
** a [prepared statement]. The first argument is the prepared statement
|
|
** object to be interrogated. The second argument
|
|
** is an integer code for a specific [SQLITE_STMTSTATUS counter]
|
|
** to be interrogated.)^
|
|
** ^The current value of the requested counter is returned.
|
|
** ^If the resetFlg is true, then the counter is reset to zero after this
|
|
** interface call returns.
|
|
**
|
|
** See also: [sqlite3_status()] and [sqlite3_db_status()].
|
|
*/
|
|
SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
|
|
|
|
/*
|
|
** CAPI3REF: Status Parameters for prepared statements
|
|
** KEYWORDS: {SQLITE_STMTSTATUS counter} {SQLITE_STMTSTATUS counters}
|
|
**
|
|
** These preprocessor macros define integer codes that name counter
|
|
** values associated with the [sqlite3_stmt_status()] interface.
|
|
** The meanings of the various counters are as follows:
|
|
**
|
|
** <dl>
|
|
** [[SQLITE_STMTSTATUS_FULLSCAN_STEP]] <dt>SQLITE_STMTSTATUS_FULLSCAN_STEP</dt>
|
|
** <dd>^This is the number of times that SQLite has stepped forward in
|
|
** a table as part of a full table scan. Large numbers for this counter
|
|
** may indicate opportunities for performance improvement through
|
|
** careful use of indices.</dd>
|
|
**
|
|
** [[SQLITE_STMTSTATUS_SORT]] <dt>SQLITE_STMTSTATUS_SORT</dt>
|
|
** <dd>^This is the number of sort operations that have occurred.
|
|
** A non-zero value in this counter may indicate an opportunity to
|
|
** improvement performance through careful use of indices.</dd>
|
|
**
|
|
** [[SQLITE_STMTSTATUS_AUTOINDEX]] <dt>SQLITE_STMTSTATUS_AUTOINDEX</dt>
|
|
** <dd>^This is the number of rows inserted into transient indices that
|
|
** were created automatically in order to help joins run faster.
|
|
** A non-zero value in this counter may indicate an opportunity to
|
|
** improvement performance by adding permanent indices that do not
|
|
** need to be reinitialized each time the statement is run.</dd>
|
|
**
|
|
** [[SQLITE_STMTSTATUS_VM_STEP]] <dt>SQLITE_STMTSTATUS_VM_STEP</dt>
|
|
** <dd>^This is the number of virtual machine operations executed
|
|
** by the prepared statement if that number is less than or equal
|
|
** to 2147483647. The number of virtual machine operations can be
|
|
** used as a proxy for the total work done by the prepared statement.
|
|
** If the number of virtual machine operations exceeds 2147483647
|
|
** then the value returned by this statement status code is undefined.
|
|
**
|
|
** [[SQLITE_STMTSTATUS_REPREPARE]] <dt>SQLITE_STMTSTATUS_REPREPARE</dt>
|
|
** <dd>^This is the number of times that the prepare statement has been
|
|
** automatically regenerated due to schema changes or changes to
|
|
** [bound parameters] that might affect the query plan.
|
|
**
|
|
** [[SQLITE_STMTSTATUS_RUN]] <dt>SQLITE_STMTSTATUS_RUN</dt>
|
|
** <dd>^This is the number of times that the prepared statement has
|
|
** been run. A single "run" for the purposes of this counter is one
|
|
** or more calls to [sqlite3_step()] followed by a call to [sqlite3_reset()].
|
|
** The counter is incremented on the first [sqlite3_step()] call of each
|
|
** cycle.
|
|
**
|
|
** [[SQLITE_STMTSTATUS_FILTER_MISS]]
|
|
** [[SQLITE_STMTSTATUS_FILTER HIT]]
|
|
** <dt>SQLITE_STMTSTATUS_FILTER_HIT<br>
|
|
** SQLITE_STMTSTATUS_FILTER_MISS</dt>
|
|
** <dd>^SQLITE_STMTSTATUS_FILTER_HIT is the number of times that a join
|
|
** step was bypassed because a Bloom filter returned not-found. The
|
|
** corresponding SQLITE_STMTSTATUS_FILTER_MISS value is the number of
|
|
** times that the Bloom filter returned a find, and thus the join step
|
|
** had to be processed as normal.
|
|
**
|
|
** [[SQLITE_STMTSTATUS_MEMUSED]] <dt>SQLITE_STMTSTATUS_MEMUSED</dt>
|
|
** <dd>^This is the approximate number of bytes of heap memory
|
|
** used to store the prepared statement. ^This value is not actually
|
|
** a counter, and so the resetFlg parameter to sqlite3_stmt_status()
|
|
** is ignored when the opcode is SQLITE_STMTSTATUS_MEMUSED.
|
|
** </dd>
|
|
** </dl>
|
|
*/
|
|
#define SQLITE_STMTSTATUS_FULLSCAN_STEP 1
|
|
#define SQLITE_STMTSTATUS_SORT 2
|
|
#define SQLITE_STMTSTATUS_AUTOINDEX 3
|
|
#define SQLITE_STMTSTATUS_VM_STEP 4
|
|
#define SQLITE_STMTSTATUS_REPREPARE 5
|
|
#define SQLITE_STMTSTATUS_RUN 6
|
|
#define SQLITE_STMTSTATUS_FILTER_MISS 7
|
|
#define SQLITE_STMTSTATUS_FILTER_HIT 8
|
|
#define SQLITE_STMTSTATUS_MEMUSED 99
|
|
|
|
/*
|
|
** CAPI3REF: Custom Page Cache Object
|
|
**
|
|
** The sqlite3_pcache type is opaque. It is implemented by
|
|
** the pluggable module. The SQLite core has no knowledge of
|
|
** its size or internal structure and never deals with the
|
|
** sqlite3_pcache object except by holding and passing pointers
|
|
** to the object.
|
|
**
|
|
** See [sqlite3_pcache_methods2] for additional information.
|
|
*/
|
|
typedef struct sqlite3_pcache sqlite3_pcache;
|
|
|
|
/*
|
|
** CAPI3REF: Custom Page Cache Object
|
|
**
|
|
** The sqlite3_pcache_page object represents a single page in the
|
|
** page cache. The page cache will allocate instances of this
|
|
** object. Various methods of the page cache use pointers to instances
|
|
** of this object as parameters or as their return value.
|
|
**
|
|
** See [sqlite3_pcache_methods2] for additional information.
|
|
*/
|
|
typedef struct sqlite3_pcache_page sqlite3_pcache_page;
|
|
struct sqlite3_pcache_page {
|
|
void *pBuf; /* The content of the page */
|
|
void *pExtra; /* Extra information associated with the page */
|
|
};
|
|
|
|
/*
|
|
** CAPI3REF: Application Defined Page Cache.
|
|
** KEYWORDS: {page cache}
|
|
**
|
|
** ^(The [sqlite3_config]([SQLITE_CONFIG_PCACHE2], ...) interface can
|
|
** register an alternative page cache implementation by passing in an
|
|
** instance of the sqlite3_pcache_methods2 structure.)^
|
|
** In many applications, most of the heap memory allocated by
|
|
** SQLite is used for the page cache.
|
|
** By implementing a
|
|
** custom page cache using this API, an application can better control
|
|
** the amount of memory consumed by SQLite, the way in which
|
|
** that memory is allocated and released, and the policies used to
|
|
** determine exactly which parts of a database file are cached and for
|
|
** how long.
|
|
**
|
|
** The alternative page cache mechanism is an
|
|
** extreme measure that is only needed by the most demanding applications.
|
|
** The built-in page cache is recommended for most uses.
|
|
**
|
|
** ^(The contents of the sqlite3_pcache_methods2 structure are copied to an
|
|
** internal buffer by SQLite within the call to [sqlite3_config]. Hence
|
|
** the application may discard the parameter after the call to
|
|
** [sqlite3_config()] returns.)^
|
|
**
|
|
** [[the xInit() page cache method]]
|
|
** ^(The xInit() method is called once for each effective
|
|
** call to [sqlite3_initialize()])^
|
|
** (usually only once during the lifetime of the process). ^(The xInit()
|
|
** method is passed a copy of the sqlite3_pcache_methods2.pArg value.)^
|
|
** The intent of the xInit() method is to set up global data structures
|
|
** required by the custom page cache implementation.
|
|
** ^(If the xInit() method is NULL, then the
|
|
** built-in default page cache is used instead of the application defined
|
|
** page cache.)^
|
|
**
|
|
** [[the xShutdown() page cache method]]
|
|
** ^The xShutdown() method is called by [sqlite3_shutdown()].
|
|
** It can be used to clean up
|
|
** any outstanding resources before process shutdown, if required.
|
|
** ^The xShutdown() method may be NULL.
|
|
**
|
|
** ^SQLite automatically serializes calls to the xInit method,
|
|
** so the xInit method need not be threadsafe. ^The
|
|
** xShutdown method is only called from [sqlite3_shutdown()] so it does
|
|
** not need to be threadsafe either. All other methods must be threadsafe
|
|
** in multithreaded applications.
|
|
**
|
|
** ^SQLite will never invoke xInit() more than once without an intervening
|
|
** call to xShutdown().
|
|
**
|
|
** [[the xCreate() page cache methods]]
|
|
** ^SQLite invokes the xCreate() method to construct a new cache instance.
|
|
** SQLite will typically create one cache instance for each open database file,
|
|
** though this is not guaranteed. ^The
|
|
** first parameter, szPage, is the size in bytes of the pages that must
|
|
** be allocated by the cache. ^szPage will always a power of two. ^The
|
|
** second parameter szExtra is a number of bytes of extra storage
|
|
** associated with each page cache entry. ^The szExtra parameter will
|
|
** a number less than 250. SQLite will use the
|
|
** extra szExtra bytes on each page to store metadata about the underlying
|
|
** database page on disk. The value passed into szExtra depends
|
|
** on the SQLite version, the target platform, and how SQLite was compiled.
|
|
** ^The third argument to xCreate(), bPurgeable, is true if the cache being
|
|
** created will be used to cache database pages of a file stored on disk, or
|
|
** false if it is used for an in-memory database. The cache implementation
|
|
** does not have to do anything special based with the value of bPurgeable;
|
|
** it is purely advisory. ^On a cache where bPurgeable is false, SQLite will
|
|
** never invoke xUnpin() except to deliberately delete a page.
|
|
** ^In other words, calls to xUnpin() on a cache with bPurgeable set to
|
|
** false will always have the "discard" flag set to true.
|
|
** ^Hence, a cache created with bPurgeable false will
|
|
** never contain any unpinned pages.
|
|
**
|
|
** [[the xCachesize() page cache method]]
|
|
** ^(The xCachesize() method may be called at any time by SQLite to set the
|
|
** suggested maximum cache-size (number of pages stored by) the cache
|
|
** instance passed as the first argument. This is the value configured using
|
|
** the SQLite "[PRAGMA cache_size]" command.)^ As with the bPurgeable
|
|
** parameter, the implementation is not required to do anything with this
|
|
** value; it is advisory only.
|
|
**
|
|
** [[the xPagecount() page cache methods]]
|
|
** The xPagecount() method must return the number of pages currently
|
|
** stored in the cache, both pinned and unpinned.
|
|
**
|
|
** [[the xFetch() page cache methods]]
|
|
** The xFetch() method locates a page in the cache and returns a pointer to
|
|
** an sqlite3_pcache_page object associated with that page, or a NULL pointer.
|
|
** The pBuf element of the returned sqlite3_pcache_page object will be a
|
|
** pointer to a buffer of szPage bytes used to store the content of a
|
|
** single database page. The pExtra element of sqlite3_pcache_page will be
|
|
** a pointer to the szExtra bytes of extra storage that SQLite has requested
|
|
** for each entry in the page cache.
|
|
**
|
|
** The page to be fetched is determined by the key. ^The minimum key value
|
|
** is 1. After it has been retrieved using xFetch, the page is considered
|
|
** to be "pinned".
|
|
**
|
|
** If the requested page is already in the page cache, then the page cache
|
|
** implementation must return a pointer to the page buffer with its content
|
|
** intact. If the requested page is not already in the cache, then the
|
|
** cache implementation should use the value of the createFlag
|
|
** parameter to help it determined what action to take:
|
|
**
|
|
** <table border=1 width=85% align=center>
|
|
** <tr><th> createFlag <th> Behavior when page is not already in cache
|
|
** <tr><td> 0 <td> Do not allocate a new page. Return NULL.
|
|
** <tr><td> 1 <td> Allocate a new page if it easy and convenient to do so.
|
|
** Otherwise return NULL.
|
|
** <tr><td> 2 <td> Make every effort to allocate a new page. Only return
|
|
** NULL if allocating a new page is effectively impossible.
|
|
** </table>
|
|
**
|
|
** ^(SQLite will normally invoke xFetch() with a createFlag of 0 or 1. SQLite
|
|
** will only use a createFlag of 2 after a prior call with a createFlag of 1
|
|
** failed.)^ In between the xFetch() calls, SQLite may
|
|
** attempt to unpin one or more cache pages by spilling the content of
|
|
** pinned pages to disk and synching the operating system disk cache.
|
|
**
|
|
** [[the xUnpin() page cache method]]
|
|
** ^xUnpin() is called by SQLite with a pointer to a currently pinned page
|
|
** as its second argument. If the third parameter, discard, is non-zero,
|
|
** then the page must be evicted from the cache.
|
|
** ^If the discard parameter is
|
|
** zero, then the page may be discarded or retained at the discretion of
|
|
** page cache implementation. ^The page cache implementation
|
|
** may choose to evict unpinned pages at any time.
|
|
**
|
|
** The cache must not perform any reference counting. A single
|
|
** call to xUnpin() unpins the page regardless of the number of prior calls
|
|
** to xFetch().
|
|
**
|
|
** [[the xRekey() page cache methods]]
|
|
** The xRekey() method is used to change the key value associated with the
|
|
** page passed as the second argument. If the cache
|
|
** previously contains an entry associated with newKey, it must be
|
|
** discarded. ^Any prior cache entry associated with newKey is guaranteed not
|
|
** to be pinned.
|
|
**
|
|
** When SQLite calls the xTruncate() method, the cache must discard all
|
|
** existing cache entries with page numbers (keys) greater than or equal
|
|
** to the value of the iLimit parameter passed to xTruncate(). If any
|
|
** of these pages are pinned, they are implicitly unpinned, meaning that
|
|
** they can be safely discarded.
|
|
**
|
|
** [[the xDestroy() page cache method]]
|
|
** ^The xDestroy() method is used to delete a cache allocated by xCreate().
|
|
** All resources associated with the specified cache should be freed. ^After
|
|
** calling the xDestroy() method, SQLite considers the [sqlite3_pcache*]
|
|
** handle invalid, and will not use it with any other sqlite3_pcache_methods2
|
|
** functions.
|
|
**
|
|
** [[the xShrink() page cache method]]
|
|
** ^SQLite invokes the xShrink() method when it wants the page cache to
|
|
** free up as much of heap memory as possible. The page cache implementation
|
|
** is not obligated to free any memory, but well-behaved implementations should
|
|
** do their best.
|
|
*/
|
|
typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2;
|
|
struct sqlite3_pcache_methods2 {
|
|
int iVersion;
|
|
void *pArg;
|
|
int (*xInit)(void*);
|
|
void (*xShutdown)(void*);
|
|
sqlite3_pcache *(*xCreate)(int szPage, int szExtra, int bPurgeable);
|
|
void (*xCachesize)(sqlite3_pcache*, int nCachesize);
|
|
int (*xPagecount)(sqlite3_pcache*);
|
|
sqlite3_pcache_page *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag);
|
|
void (*xUnpin)(sqlite3_pcache*, sqlite3_pcache_page*, int discard);
|
|
void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*,
|
|
unsigned oldKey, unsigned newKey);
|
|
void (*xTruncate)(sqlite3_pcache*, unsigned iLimit);
|
|
void (*xDestroy)(sqlite3_pcache*);
|
|
void (*xShrink)(sqlite3_pcache*);
|
|
};
|
|
|
|
/*
|
|
** This is the obsolete pcache_methods object that has now been replaced
|
|
** by sqlite3_pcache_methods2. This object is not used by SQLite. It is
|
|
** retained in the header file for backwards compatibility only.
|
|
*/
|
|
typedef struct sqlite3_pcache_methods sqlite3_pcache_methods;
|
|
struct sqlite3_pcache_methods {
|
|
void *pArg;
|
|
int (*xInit)(void*);
|
|
void (*xShutdown)(void*);
|
|
sqlite3_pcache *(*xCreate)(int szPage, int bPurgeable);
|
|
void (*xCachesize)(sqlite3_pcache*, int nCachesize);
|
|
int (*xPagecount)(sqlite3_pcache*);
|
|
void *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag);
|
|
void (*xUnpin)(sqlite3_pcache*, void*, int discard);
|
|
void (*xRekey)(sqlite3_pcache*, void*, unsigned oldKey, unsigned newKey);
|
|
void (*xTruncate)(sqlite3_pcache*, unsigned iLimit);
|
|
void (*xDestroy)(sqlite3_pcache*);
|
|
};
|
|
|
|
|
|
/*
|
|
** CAPI3REF: Online Backup Object
|
|
**
|
|
** The sqlite3_backup object records state information about an ongoing
|
|
** online backup operation. ^The sqlite3_backup object is created by
|
|
** a call to [sqlite3_backup_init()] and is destroyed by a call to
|
|
** [sqlite3_backup_finish()].
|
|
**
|
|
** See Also: [Using the SQLite Online Backup API]
|
|
*/
|
|
typedef struct sqlite3_backup sqlite3_backup;
|
|
|
|
/*
|
|
** CAPI3REF: Online Backup API.
|
|
**
|
|
** The backup API copies the content of one database into another.
|
|
** It is useful either for creating backups of databases or
|
|
** for copying in-memory databases to or from persistent files.
|
|
**
|
|
** See Also: [Using the SQLite Online Backup API]
|
|
**
|
|
** ^SQLite holds a write transaction open on the destination database file
|
|
** for the duration of the backup operation.
|
|
** ^The source database is read-locked only while it is being read;
|
|
** it is not locked continuously for the entire backup operation.
|
|
** ^Thus, the backup may be performed on a live source database without
|
|
** preventing other database connections from
|
|
** reading or writing to the source database while the backup is underway.
|
|
**
|
|
** ^(To perform a backup operation:
|
|
** <ol>
|
|
** <li><b>sqlite3_backup_init()</b> is called once to initialize the
|
|
** backup,
|
|
** <li><b>sqlite3_backup_step()</b> is called one or more times to transfer
|
|
** the data between the two databases, and finally
|
|
** <li><b>sqlite3_backup_finish()</b> is called to release all resources
|
|
** associated with the backup operation.
|
|
** </ol>)^
|
|
** There should be exactly one call to sqlite3_backup_finish() for each
|
|
** successful call to sqlite3_backup_init().
|
|
**
|
|
** [[sqlite3_backup_init()]] <b>sqlite3_backup_init()</b>
|
|
**
|
|
** ^The D and N arguments to sqlite3_backup_init(D,N,S,M) are the
|
|
** [database connection] associated with the destination database
|
|
** and the database name, respectively.
|
|
** ^The database name is "main" for the main database, "temp" for the
|
|
** temporary database, or the name specified after the AS keyword in
|
|
** an [ATTACH] statement for an attached database.
|
|
** ^The S and M arguments passed to
|
|
** sqlite3_backup_init(D,N,S,M) identify the [database connection]
|
|
** and database name of the source database, respectively.
|
|
** ^The source and destination [database connections] (parameters S and D)
|
|
** must be different or else sqlite3_backup_init(D,N,S,M) will fail with
|
|
** an error.
|
|
**
|
|
** ^A call to sqlite3_backup_init() will fail, returning NULL, if
|
|
** there is already a read or read-write transaction open on the
|
|
** destination database.
|
|
**
|
|
** ^If an error occurs within sqlite3_backup_init(D,N,S,M), then NULL is
|
|
** returned and an error code and error message are stored in the
|
|
** destination [database connection] D.
|
|
** ^The error code and message for the failed call to sqlite3_backup_init()
|
|
** can be retrieved using the [sqlite3_errcode()], [sqlite3_errmsg()], and/or
|
|
** [sqlite3_errmsg16()] functions.
|
|
** ^A successful call to sqlite3_backup_init() returns a pointer to an
|
|
** [sqlite3_backup] object.
|
|
** ^The [sqlite3_backup] object may be used with the sqlite3_backup_step() and
|
|
** sqlite3_backup_finish() functions to perform the specified backup
|
|
** operation.
|
|
**
|
|
** [[sqlite3_backup_step()]] <b>sqlite3_backup_step()</b>
|
|
**
|
|
** ^Function sqlite3_backup_step(B,N) will copy up to N pages between
|
|
** the source and destination databases specified by [sqlite3_backup] object B.
|
|
** ^If N is negative, all remaining source pages are copied.
|
|
** ^If sqlite3_backup_step(B,N) successfully copies N pages and there
|
|
** are still more pages to be copied, then the function returns [SQLITE_OK].
|
|
** ^If sqlite3_backup_step(B,N) successfully finishes copying all pages
|
|
** from source to destination, then it returns [SQLITE_DONE].
|
|
** ^If an error occurs while running sqlite3_backup_step(B,N),
|
|
** then an [error code] is returned. ^As well as [SQLITE_OK] and
|
|
** [SQLITE_DONE], a call to sqlite3_backup_step() may return [SQLITE_READONLY],
|
|
** [SQLITE_NOMEM], [SQLITE_BUSY], [SQLITE_LOCKED], or an
|
|
** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX] extended error code.
|
|
**
|
|
** ^(The sqlite3_backup_step() might return [SQLITE_READONLY] if
|
|
** <ol>
|
|
** <li> the destination database was opened read-only, or
|
|
** <li> the destination database is using write-ahead-log journaling
|
|
** and the destination and source page sizes differ, or
|
|
** <li> the destination database is an in-memory database and the
|
|
** destination and source page sizes differ.
|
|
** </ol>)^
|
|
**
|
|
** ^If sqlite3_backup_step() cannot obtain a required file-system lock, then
|
|
** the [sqlite3_busy_handler | busy-handler function]
|
|
** is invoked (if one is specified). ^If the
|
|
** busy-handler returns non-zero before the lock is available, then
|
|
** [SQLITE_BUSY] is returned to the caller. ^In this case the call to
|
|
** sqlite3_backup_step() can be retried later. ^If the source
|
|
** [database connection]
|
|
** is being used to write to the source database when sqlite3_backup_step()
|
|
** is called, then [SQLITE_LOCKED] is returned immediately. ^Again, in this
|
|
** case the call to sqlite3_backup_step() can be retried later on. ^(If
|
|
** [SQLITE_IOERR_ACCESS | SQLITE_IOERR_XXX], [SQLITE_NOMEM], or
|
|
** [SQLITE_READONLY] is returned, then
|
|
** there is no point in retrying the call to sqlite3_backup_step(). These
|
|
** errors are considered fatal.)^ The application must accept
|
|
** that the backup operation has failed and pass the backup operation handle
|
|
** to the sqlite3_backup_finish() to release associated resources.
|
|
**
|
|
** ^The first call to sqlite3_backup_step() obtains an exclusive lock
|
|
** on the destination file. ^The exclusive lock is not released until either
|
|
** sqlite3_backup_finish() is called or the backup operation is complete
|
|
** and sqlite3_backup_step() returns [SQLITE_DONE]. ^Every call to
|
|
** sqlite3_backup_step() obtains a [shared lock] on the source database that
|
|
** lasts for the duration of the sqlite3_backup_step() call.
|
|
** ^Because the source database is not locked between calls to
|
|
** sqlite3_backup_step(), the source database may be modified mid-way
|
|
** through the backup process. ^If the source database is modified by an
|
|
** external process or via a database connection other than the one being
|
|
** used by the backup operation, then the backup will be automatically
|
|
** restarted by the next call to sqlite3_backup_step(). ^If the source
|
|
** database is modified by the using the same database connection as is used
|
|
** by the backup operation, then the backup database is automatically
|
|
** updated at the same time.
|
|
**
|
|
** [[sqlite3_backup_finish()]] <b>sqlite3_backup_finish()</b>
|
|
**
|
|
** When sqlite3_backup_step() has returned [SQLITE_DONE], or when the
|
|
** application wishes to abandon the backup operation, the application
|
|
** should destroy the [sqlite3_backup] by passing it to sqlite3_backup_finish().
|
|
** ^The sqlite3_backup_finish() interfaces releases all
|
|
** resources associated with the [sqlite3_backup] object.
|
|
** ^If sqlite3_backup_step() has not yet returned [SQLITE_DONE], then any
|
|
** active write-transaction on the destination database is rolled back.
|
|
** The [sqlite3_backup] object is invalid
|
|
** and may not be used following a call to sqlite3_backup_finish().
|
|
**
|
|
** ^The value returned by sqlite3_backup_finish is [SQLITE_OK] if no
|
|
** sqlite3_backup_step() errors occurred, regardless or whether or not
|
|
** sqlite3_backup_step() completed.
|
|
** ^If an out-of-memory condition or IO error occurred during any prior
|
|
** sqlite3_backup_step() call on the same [sqlite3_backup] object, then
|
|
** sqlite3_backup_finish() returns the corresponding [error code].
|
|
**
|
|
** ^A return of [SQLITE_BUSY] or [SQLITE_LOCKED] from sqlite3_backup_step()
|
|
** is not a permanent error and does not affect the return value of
|
|
** sqlite3_backup_finish().
|
|
**
|
|
** [[sqlite3_backup_remaining()]] [[sqlite3_backup_pagecount()]]
|
|
** <b>sqlite3_backup_remaining() and sqlite3_backup_pagecount()</b>
|
|
**
|
|
** ^The sqlite3_backup_remaining() routine returns the number of pages still
|
|
** to be backed up at the conclusion of the most recent sqlite3_backup_step().
|
|
** ^The sqlite3_backup_pagecount() routine returns the total number of pages
|
|
** in the source database at the conclusion of the most recent
|
|
** sqlite3_backup_step().
|
|
** ^(The values returned by these functions are only updated by
|
|
** sqlite3_backup_step(). If the source database is modified in a way that
|
|
** changes the size of the source database or the number of pages remaining,
|
|
** those changes are not reflected in the output of sqlite3_backup_pagecount()
|
|
** and sqlite3_backup_remaining() until after the next
|
|
** sqlite3_backup_step().)^
|
|
**
|
|
** <b>Concurrent Usage of Database Handles</b>
|
|
**
|
|
** ^The source [database connection] may be used by the application for other
|
|
** purposes while a backup operation is underway or being initialized.
|
|
** ^If SQLite is compiled and configured to support threadsafe database
|
|
** connections, then the source database connection may be used concurrently
|
|
** from within other threads.
|
|
**
|
|
** However, the application must guarantee that the destination
|
|
** [database connection] is not passed to any other API (by any thread) after
|
|
** sqlite3_backup_init() is called and before the corresponding call to
|
|
** sqlite3_backup_finish(). SQLite does not currently check to see
|
|
** if the application incorrectly accesses the destination [database connection]
|
|
** and so no error code is reported, but the operations may malfunction
|
|
** nevertheless. Use of the destination database connection while a
|
|
** backup is in progress might also cause a mutex deadlock.
|
|
**
|
|
** If running in [shared cache mode], the application must
|
|
** guarantee that the shared cache used by the destination database
|
|
** is not accessed while the backup is running. In practice this means
|
|
** that the application must guarantee that the disk file being
|
|
** backed up to is not accessed by any connection within the process,
|
|
** not just the specific connection that was passed to sqlite3_backup_init().
|
|
**
|
|
** The [sqlite3_backup] object itself is partially threadsafe. Multiple
|
|
** threads may safely make multiple concurrent calls to sqlite3_backup_step().
|
|
** However, the sqlite3_backup_remaining() and sqlite3_backup_pagecount()
|
|
** APIs are not strictly speaking threadsafe. If they are invoked at the
|
|
** same time as another thread is invoking sqlite3_backup_step() it is
|
|
** possible that they return invalid values.
|
|
*/
|
|
SQLITE_API sqlite3_backup *sqlite3_backup_init(
|
|
sqlite3 *pDest, /* Destination database handle */
|
|
const char *zDestName, /* Destination database name */
|
|
sqlite3 *pSource, /* Source database handle */
|
|
const char *zSourceName /* Source database name */
|
|
);
|
|
SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage);
|
|
SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p);
|
|
SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p);
|
|
SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
|
|
|
|
/*
|
|
** CAPI3REF: Unlock Notification
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^When running in shared-cache mode, a database operation may fail with
|
|
** an [SQLITE_LOCKED] error if the required locks on the shared-cache or
|
|
** individual tables within the shared-cache cannot be obtained. See
|
|
** [SQLite Shared-Cache Mode] for a description of shared-cache locking.
|
|
** ^This API may be used to register a callback that SQLite will invoke
|
|
** when the connection currently holding the required lock relinquishes it.
|
|
** ^This API is only available if the library was compiled with the
|
|
** [SQLITE_ENABLE_UNLOCK_NOTIFY] C-preprocessor symbol defined.
|
|
**
|
|
** See Also: [Using the SQLite Unlock Notification Feature].
|
|
**
|
|
** ^Shared-cache locks are released when a database connection concludes
|
|
** its current transaction, either by committing it or rolling it back.
|
|
**
|
|
** ^When a connection (known as the blocked connection) fails to obtain a
|
|
** shared-cache lock and SQLITE_LOCKED is returned to the caller, the
|
|
** identity of the database connection (the blocking connection) that
|
|
** has locked the required resource is stored internally. ^After an
|
|
** application receives an SQLITE_LOCKED error, it may call the
|
|
** sqlite3_unlock_notify() method with the blocked connection handle as
|
|
** the first argument to register for a callback that will be invoked
|
|
** when the blocking connections current transaction is concluded. ^The
|
|
** callback is invoked from within the [sqlite3_step] or [sqlite3_close]
|
|
** call that concludes the blocking connection's transaction.
|
|
**
|
|
** ^(If sqlite3_unlock_notify() is called in a multi-threaded application,
|
|
** there is a chance that the blocking connection will have already
|
|
** concluded its transaction by the time sqlite3_unlock_notify() is invoked.
|
|
** If this happens, then the specified callback is invoked immediately,
|
|
** from within the call to sqlite3_unlock_notify().)^
|
|
**
|
|
** ^If the blocked connection is attempting to obtain a write-lock on a
|
|
** shared-cache table, and more than one other connection currently holds
|
|
** a read-lock on the same table, then SQLite arbitrarily selects one of
|
|
** the other connections to use as the blocking connection.
|
|
**
|
|
** ^(There may be at most one unlock-notify callback registered by a
|
|
** blocked connection. If sqlite3_unlock_notify() is called when the
|
|
** blocked connection already has a registered unlock-notify callback,
|
|
** then the new callback replaces the old.)^ ^If sqlite3_unlock_notify() is
|
|
** called with a NULL pointer as its second argument, then any existing
|
|
** unlock-notify callback is canceled. ^The blocked connections
|
|
** unlock-notify callback may also be canceled by closing the blocked
|
|
** connection using [sqlite3_close()].
|
|
**
|
|
** The unlock-notify callback is not reentrant. If an application invokes
|
|
** any sqlite3_xxx API functions from within an unlock-notify callback, a
|
|
** crash or deadlock may be the result.
|
|
**
|
|
** ^Unless deadlock is detected (see below), sqlite3_unlock_notify() always
|
|
** returns SQLITE_OK.
|
|
**
|
|
** <b>Callback Invocation Details</b>
|
|
**
|
|
** When an unlock-notify callback is registered, the application provides a
|
|
** single void* pointer that is passed to the callback when it is invoked.
|
|
** However, the signature of the callback function allows SQLite to pass
|
|
** it an array of void* context pointers. The first argument passed to
|
|
** an unlock-notify callback is a pointer to an array of void* pointers,
|
|
** and the second is the number of entries in the array.
|
|
**
|
|
** When a blocking connection's transaction is concluded, there may be
|
|
** more than one blocked connection that has registered for an unlock-notify
|
|
** callback. ^If two or more such blocked connections have specified the
|
|
** same callback function, then instead of invoking the callback function
|
|
** multiple times, it is invoked once with the set of void* context pointers
|
|
** specified by the blocked connections bundled together into an array.
|
|
** This gives the application an opportunity to prioritize any actions
|
|
** related to the set of unblocked database connections.
|
|
**
|
|
** <b>Deadlock Detection</b>
|
|
**
|
|
** Assuming that after registering for an unlock-notify callback a
|
|
** database waits for the callback to be issued before taking any further
|
|
** action (a reasonable assumption), then using this API may cause the
|
|
** application to deadlock. For example, if connection X is waiting for
|
|
** connection Y's transaction to be concluded, and similarly connection
|
|
** Y is waiting on connection X's transaction, then neither connection
|
|
** will proceed and the system may remain deadlocked indefinitely.
|
|
**
|
|
** To avoid this scenario, the sqlite3_unlock_notify() performs deadlock
|
|
** detection. ^If a given call to sqlite3_unlock_notify() would put the
|
|
** system in a deadlocked state, then SQLITE_LOCKED is returned and no
|
|
** unlock-notify callback is registered. The system is said to be in
|
|
** a deadlocked state if connection A has registered for an unlock-notify
|
|
** callback on the conclusion of connection B's transaction, and connection
|
|
** B has itself registered for an unlock-notify callback when connection
|
|
** A's transaction is concluded. ^Indirect deadlock is also detected, so
|
|
** the system is also considered to be deadlocked if connection B has
|
|
** registered for an unlock-notify callback on the conclusion of connection
|
|
** C's transaction, where connection C is waiting on connection A. ^Any
|
|
** number of levels of indirection are allowed.
|
|
**
|
|
** <b>The "DROP TABLE" Exception</b>
|
|
**
|
|
** When a call to [sqlite3_step()] returns SQLITE_LOCKED, it is almost
|
|
** always appropriate to call sqlite3_unlock_notify(). There is however,
|
|
** one exception. When executing a "DROP TABLE" or "DROP INDEX" statement,
|
|
** SQLite checks if there are any currently executing SELECT statements
|
|
** that belong to the same connection. If there are, SQLITE_LOCKED is
|
|
** returned. In this case there is no "blocking connection", so invoking
|
|
** sqlite3_unlock_notify() results in the unlock-notify callback being
|
|
** invoked immediately. If the application then re-attempts the "DROP TABLE"
|
|
** or "DROP INDEX" query, an infinite loop might be the result.
|
|
**
|
|
** One way around this problem is to check the extended error code returned
|
|
** by an sqlite3_step() call. ^(If there is a blocking connection, then the
|
|
** extended error code is set to SQLITE_LOCKED_SHAREDCACHE. Otherwise, in
|
|
** the special "DROP TABLE/INDEX" case, the extended error code is just
|
|
** SQLITE_LOCKED.)^
|
|
*/
|
|
SQLITE_API int sqlite3_unlock_notify(
|
|
sqlite3 *pBlocked, /* Waiting connection */
|
|
void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */
|
|
void *pNotifyArg /* Argument to pass to xNotify */
|
|
);
|
|
|
|
|
|
/*
|
|
** CAPI3REF: String Comparison
|
|
**
|
|
** ^The [sqlite3_stricmp()] and [sqlite3_strnicmp()] APIs allow applications
|
|
** and extensions to compare the contents of two buffers containing UTF-8
|
|
** strings in a case-independent fashion, using the same definition of "case
|
|
** independence" that SQLite uses internally when comparing identifiers.
|
|
*/
|
|
SQLITE_API int sqlite3_stricmp(const char *, const char *);
|
|
SQLITE_API int sqlite3_strnicmp(const char *, const char *, int);
|
|
|
|
/*
|
|
** CAPI3REF: String Globbing
|
|
*
|
|
** ^The [sqlite3_strglob(P,X)] interface returns zero if and only if
|
|
** string X matches the [GLOB] pattern P.
|
|
** ^The definition of [GLOB] pattern matching used in
|
|
** [sqlite3_strglob(P,X)] is the same as for the "X GLOB P" operator in the
|
|
** SQL dialect understood by SQLite. ^The [sqlite3_strglob(P,X)] function
|
|
** is case sensitive.
|
|
**
|
|
** Note that this routine returns zero on a match and non-zero if the strings
|
|
** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()].
|
|
**
|
|
** See also: [sqlite3_strlike()].
|
|
*/
|
|
SQLITE_API int sqlite3_strglob(const char *zGlob, const char *zStr);
|
|
|
|
/*
|
|
** CAPI3REF: String LIKE Matching
|
|
*
|
|
** ^The [sqlite3_strlike(P,X,E)] interface returns zero if and only if
|
|
** string X matches the [LIKE] pattern P with escape character E.
|
|
** ^The definition of [LIKE] pattern matching used in
|
|
** [sqlite3_strlike(P,X,E)] is the same as for the "X LIKE P ESCAPE E"
|
|
** operator in the SQL dialect understood by SQLite. ^For "X LIKE P" without
|
|
** the ESCAPE clause, set the E parameter of [sqlite3_strlike(P,X,E)] to 0.
|
|
** ^As with the LIKE operator, the [sqlite3_strlike(P,X,E)] function is case
|
|
** insensitive - equivalent upper and lower case ASCII characters match
|
|
** one another.
|
|
**
|
|
** ^The [sqlite3_strlike(P,X,E)] function matches Unicode characters, though
|
|
** only ASCII characters are case folded.
|
|
**
|
|
** Note that this routine returns zero on a match and non-zero if the strings
|
|
** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()].
|
|
**
|
|
** See also: [sqlite3_strglob()].
|
|
*/
|
|
SQLITE_API int sqlite3_strlike(const char *zGlob, const char *zStr, unsigned int cEsc);
|
|
|
|
/*
|
|
** CAPI3REF: Error Logging Interface
|
|
**
|
|
** ^The [sqlite3_log()] interface writes a message into the [error log]
|
|
** established by the [SQLITE_CONFIG_LOG] option to [sqlite3_config()].
|
|
** ^If logging is enabled, the zFormat string and subsequent arguments are
|
|
** used with [sqlite3_snprintf()] to generate the final output string.
|
|
**
|
|
** The sqlite3_log() interface is intended for use by extensions such as
|
|
** virtual tables, collating functions, and SQL functions. While there is
|
|
** nothing to prevent an application from calling sqlite3_log(), doing so
|
|
** is considered bad form.
|
|
**
|
|
** The zFormat string must not be NULL.
|
|
**
|
|
** To avoid deadlocks and other threading problems, the sqlite3_log() routine
|
|
** will not use dynamically allocated memory. The log message is stored in
|
|
** a fixed-length buffer on the stack. If the log message is longer than
|
|
** a few hundred characters, it will be truncated to the length of the
|
|
** buffer.
|
|
*/
|
|
SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...);
|
|
|
|
/*
|
|
** CAPI3REF: Write-Ahead Log Commit Hook
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^The [sqlite3_wal_hook()] function is used to register a callback that
|
|
** is invoked each time data is committed to a database in wal mode.
|
|
**
|
|
** ^(The callback is invoked by SQLite after the commit has taken place and
|
|
** the associated write-lock on the database released)^, so the implementation
|
|
** may read, write or [checkpoint] the database as required.
|
|
**
|
|
** ^The first parameter passed to the callback function when it is invoked
|
|
** is a copy of the third parameter passed to sqlite3_wal_hook() when
|
|
** registering the callback. ^The second is a copy of the database handle.
|
|
** ^The third parameter is the name of the database that was written to -
|
|
** either "main" or the name of an [ATTACH]-ed database. ^The fourth parameter
|
|
** is the number of pages currently in the write-ahead log file,
|
|
** including those that were just committed.
|
|
**
|
|
** The callback function should normally return [SQLITE_OK]. ^If an error
|
|
** code is returned, that error will propagate back up through the
|
|
** SQLite code base to cause the statement that provoked the callback
|
|
** to report an error, though the commit will have still occurred. If the
|
|
** callback returns [SQLITE_ROW] or [SQLITE_DONE], or if it returns a value
|
|
** that does not correspond to any valid SQLite error code, the results
|
|
** are undefined.
|
|
**
|
|
** A single database handle may have at most a single write-ahead log callback
|
|
** registered at one time. ^Calling [sqlite3_wal_hook()] replaces any
|
|
** previously registered write-ahead log callback. ^The return value is
|
|
** a copy of the third parameter from the previous call, if any, or 0.
|
|
** ^Note that the [sqlite3_wal_autocheckpoint()] interface and the
|
|
** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will
|
|
** overwrite any prior [sqlite3_wal_hook()] settings.
|
|
*/
|
|
SQLITE_API void *sqlite3_wal_hook(
|
|
sqlite3*,
|
|
int(*)(void *,sqlite3*,const char*,int),
|
|
void*
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Configure an auto-checkpoint
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around
|
|
** [sqlite3_wal_hook()] that causes any database on [database connection] D
|
|
** to automatically [checkpoint]
|
|
** after committing a transaction if there are N or
|
|
** more frames in the [write-ahead log] file. ^Passing zero or
|
|
** a negative value as the nFrame parameter disables automatic
|
|
** checkpoints entirely.
|
|
**
|
|
** ^The callback registered by this function replaces any existing callback
|
|
** registered using [sqlite3_wal_hook()]. ^Likewise, registering a callback
|
|
** using [sqlite3_wal_hook()] disables the automatic checkpoint mechanism
|
|
** configured by this function.
|
|
**
|
|
** ^The [wal_autocheckpoint pragma] can be used to invoke this interface
|
|
** from SQL.
|
|
**
|
|
** ^Checkpoints initiated by this mechanism are
|
|
** [sqlite3_wal_checkpoint_v2|PASSIVE].
|
|
**
|
|
** ^Every new [database connection] defaults to having the auto-checkpoint
|
|
** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT]
|
|
** pages. The use of this interface
|
|
** is only necessary if the default setting is found to be suboptimal
|
|
** for a particular application.
|
|
*/
|
|
SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
|
|
|
|
/*
|
|
** CAPI3REF: Checkpoint a database
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^(The sqlite3_wal_checkpoint(D,X) is equivalent to
|
|
** [sqlite3_wal_checkpoint_v2](D,X,[SQLITE_CHECKPOINT_PASSIVE],0,0).)^
|
|
**
|
|
** In brief, sqlite3_wal_checkpoint(D,X) causes the content in the
|
|
** [write-ahead log] for database X on [database connection] D to be
|
|
** transferred into the database file and for the write-ahead log to
|
|
** be reset. See the [checkpointing] documentation for addition
|
|
** information.
|
|
**
|
|
** This interface used to be the only way to cause a checkpoint to
|
|
** occur. But then the newer and more powerful [sqlite3_wal_checkpoint_v2()]
|
|
** interface was added. This interface is retained for backwards
|
|
** compatibility and as a convenience for applications that need to manually
|
|
** start a callback but which do not need the full power (and corresponding
|
|
** complication) of [sqlite3_wal_checkpoint_v2()].
|
|
*/
|
|
SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
|
|
|
|
/*
|
|
** CAPI3REF: Checkpoint a database
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^(The sqlite3_wal_checkpoint_v2(D,X,M,L,C) interface runs a checkpoint
|
|
** operation on database X of [database connection] D in mode M. Status
|
|
** information is written back into integers pointed to by L and C.)^
|
|
** ^(The M parameter must be a valid [checkpoint mode]:)^
|
|
**
|
|
** <dl>
|
|
** <dt>SQLITE_CHECKPOINT_PASSIVE<dd>
|
|
** ^Checkpoint as many frames as possible without waiting for any database
|
|
** readers or writers to finish, then sync the database file if all frames
|
|
** in the log were checkpointed. ^The [busy-handler callback]
|
|
** is never invoked in the SQLITE_CHECKPOINT_PASSIVE mode.
|
|
** ^On the other hand, passive mode might leave the checkpoint unfinished
|
|
** if there are concurrent readers or writers.
|
|
**
|
|
** <dt>SQLITE_CHECKPOINT_FULL<dd>
|
|
** ^This mode blocks (it invokes the
|
|
** [sqlite3_busy_handler|busy-handler callback]) until there is no
|
|
** database writer and all readers are reading from the most recent database
|
|
** snapshot. ^It then checkpoints all frames in the log file and syncs the
|
|
** database file. ^This mode blocks new database writers while it is pending,
|
|
** but new database readers are allowed to continue unimpeded.
|
|
**
|
|
** <dt>SQLITE_CHECKPOINT_RESTART<dd>
|
|
** ^This mode works the same way as SQLITE_CHECKPOINT_FULL with the addition
|
|
** that after checkpointing the log file it blocks (calls the
|
|
** [busy-handler callback])
|
|
** until all readers are reading from the database file only. ^This ensures
|
|
** that the next writer will restart the log file from the beginning.
|
|
** ^Like SQLITE_CHECKPOINT_FULL, this mode blocks new
|
|
** database writer attempts while it is pending, but does not impede readers.
|
|
**
|
|
** <dt>SQLITE_CHECKPOINT_TRUNCATE<dd>
|
|
** ^This mode works the same way as SQLITE_CHECKPOINT_RESTART with the
|
|
** addition that it also truncates the log file to zero bytes just prior
|
|
** to a successful return.
|
|
** </dl>
|
|
**
|
|
** ^If pnLog is not NULL, then *pnLog is set to the total number of frames in
|
|
** the log file or to -1 if the checkpoint could not run because
|
|
** of an error or because the database is not in [WAL mode]. ^If pnCkpt is not
|
|
** NULL,then *pnCkpt is set to the total number of checkpointed frames in the
|
|
** log file (including any that were already checkpointed before the function
|
|
** was called) or to -1 if the checkpoint could not run due to an error or
|
|
** because the database is not in WAL mode. ^Note that upon successful
|
|
** completion of an SQLITE_CHECKPOINT_TRUNCATE, the log file will have been
|
|
** truncated to zero bytes and so both *pnLog and *pnCkpt will be set to zero.
|
|
**
|
|
** ^All calls obtain an exclusive "checkpoint" lock on the database file. ^If
|
|
** any other process is running a checkpoint operation at the same time, the
|
|
** lock cannot be obtained and SQLITE_BUSY is returned. ^Even if there is a
|
|
** busy-handler configured, it will not be invoked in this case.
|
|
**
|
|
** ^The SQLITE_CHECKPOINT_FULL, RESTART and TRUNCATE modes also obtain the
|
|
** exclusive "writer" lock on the database file. ^If the writer lock cannot be
|
|
** obtained immediately, and a busy-handler is configured, it is invoked and
|
|
** the writer lock retried until either the busy-handler returns 0 or the lock
|
|
** is successfully obtained. ^The busy-handler is also invoked while waiting for
|
|
** database readers as described above. ^If the busy-handler returns 0 before
|
|
** the writer lock is obtained or while waiting for database readers, the
|
|
** checkpoint operation proceeds from that point in the same way as
|
|
** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible
|
|
** without blocking any further. ^SQLITE_BUSY is returned in this case.
|
|
**
|
|
** ^If parameter zDb is NULL or points to a zero length string, then the
|
|
** specified operation is attempted on all WAL databases [attached] to
|
|
** [database connection] db. In this case the
|
|
** values written to output parameters *pnLog and *pnCkpt are undefined. ^If
|
|
** an SQLITE_BUSY error is encountered when processing one or more of the
|
|
** attached WAL databases, the operation is still attempted on any remaining
|
|
** attached databases and SQLITE_BUSY is returned at the end. ^If any other
|
|
** error occurs while processing an attached database, processing is abandoned
|
|
** and the error code is returned to the caller immediately. ^If no error
|
|
** (SQLITE_BUSY or otherwise) is encountered while processing the attached
|
|
** databases, SQLITE_OK is returned.
|
|
**
|
|
** ^If database zDb is the name of an attached database that is not in WAL
|
|
** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. ^If
|
|
** zDb is not NULL (or a zero length string) and is not the name of any
|
|
** attached database, SQLITE_ERROR is returned to the caller.
|
|
**
|
|
** ^Unless it returns SQLITE_MISUSE,
|
|
** the sqlite3_wal_checkpoint_v2() interface
|
|
** sets the error information that is queried by
|
|
** [sqlite3_errcode()] and [sqlite3_errmsg()].
|
|
**
|
|
** ^The [PRAGMA wal_checkpoint] command can be used to invoke this interface
|
|
** from SQL.
|
|
*/
|
|
SQLITE_API int sqlite3_wal_checkpoint_v2(
|
|
sqlite3 *db, /* Database handle */
|
|
const char *zDb, /* Name of attached database (or NULL) */
|
|
int eMode, /* SQLITE_CHECKPOINT_* value */
|
|
int *pnLog, /* OUT: Size of WAL log in frames */
|
|
int *pnCkpt /* OUT: Total number of frames checkpointed */
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Checkpoint Mode Values
|
|
** KEYWORDS: {checkpoint mode}
|
|
**
|
|
** These constants define all valid values for the "checkpoint mode" passed
|
|
** as the third parameter to the [sqlite3_wal_checkpoint_v2()] interface.
|
|
** See the [sqlite3_wal_checkpoint_v2()] documentation for details on the
|
|
** meaning of each of these checkpoint modes.
|
|
*/
|
|
#define SQLITE_CHECKPOINT_PASSIVE 0 /* Do as much as possible w/o blocking */
|
|
#define SQLITE_CHECKPOINT_FULL 1 /* Wait for writers, then checkpoint */
|
|
#define SQLITE_CHECKPOINT_RESTART 2 /* Like FULL but wait for readers */
|
|
#define SQLITE_CHECKPOINT_TRUNCATE 3 /* Like RESTART but also truncate WAL */
|
|
|
|
/*
|
|
** CAPI3REF: Virtual Table Interface Configuration
|
|
**
|
|
** This function may be called by either the [xConnect] or [xCreate] method
|
|
** of a [virtual table] implementation to configure
|
|
** various facets of the virtual table interface.
|
|
**
|
|
** If this interface is invoked outside the context of an xConnect or
|
|
** xCreate virtual table method then the behavior is undefined.
|
|
**
|
|
** In the call sqlite3_vtab_config(D,C,...) the D parameter is the
|
|
** [database connection] in which the virtual table is being created and
|
|
** which is passed in as the first argument to the [xConnect] or [xCreate]
|
|
** method that is invoking sqlite3_vtab_config(). The C parameter is one
|
|
** of the [virtual table configuration options]. The presence and meaning
|
|
** of parameters after C depend on which [virtual table configuration option]
|
|
** is used.
|
|
*/
|
|
SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
|
|
|
|
/*
|
|
** CAPI3REF: Virtual Table Configuration Options
|
|
** KEYWORDS: {virtual table configuration options}
|
|
** KEYWORDS: {virtual table configuration option}
|
|
**
|
|
** These macros define the various options to the
|
|
** [sqlite3_vtab_config()] interface that [virtual table] implementations
|
|
** can use to customize and optimize their behavior.
|
|
**
|
|
** <dl>
|
|
** [[SQLITE_VTAB_CONSTRAINT_SUPPORT]]
|
|
** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT</dt>
|
|
** <dd>Calls of the form
|
|
** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported,
|
|
** where X is an integer. If X is zero, then the [virtual table] whose
|
|
** [xCreate] or [xConnect] method invoked [sqlite3_vtab_config()] does not
|
|
** support constraints. In this configuration (which is the default) if
|
|
** a call to the [xUpdate] method returns [SQLITE_CONSTRAINT], then the entire
|
|
** statement is rolled back as if [ON CONFLICT | OR ABORT] had been
|
|
** specified as part of the users SQL statement, regardless of the actual
|
|
** ON CONFLICT mode specified.
|
|
**
|
|
** If X is non-zero, then the virtual table implementation guarantees
|
|
** that if [xUpdate] returns [SQLITE_CONSTRAINT], it will do so before
|
|
** any modifications to internal or persistent data structures have been made.
|
|
** If the [ON CONFLICT] mode is ABORT, FAIL, IGNORE or ROLLBACK, SQLite
|
|
** is able to roll back a statement or database transaction, and abandon
|
|
** or continue processing the current SQL statement as appropriate.
|
|
** If the ON CONFLICT mode is REPLACE and the [xUpdate] method returns
|
|
** [SQLITE_CONSTRAINT], SQLite handles this as if the ON CONFLICT mode
|
|
** had been ABORT.
|
|
**
|
|
** Virtual table implementations that are required to handle OR REPLACE
|
|
** must do so within the [xUpdate] method. If a call to the
|
|
** [sqlite3_vtab_on_conflict()] function indicates that the current ON
|
|
** CONFLICT policy is REPLACE, the virtual table implementation should
|
|
** silently replace the appropriate rows within the xUpdate callback and
|
|
** return SQLITE_OK. Or, if this is not possible, it may return
|
|
** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT
|
|
** constraint handling.
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_VTAB_DIRECTONLY]]<dt>SQLITE_VTAB_DIRECTONLY</dt>
|
|
** <dd>Calls of the form
|
|
** [sqlite3_vtab_config](db,SQLITE_VTAB_DIRECTONLY) from within the
|
|
** the [xConnect] or [xCreate] methods of a [virtual table] implementation
|
|
** prohibits that virtual table from being used from within triggers and
|
|
** views.
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_VTAB_INNOCUOUS]]<dt>SQLITE_VTAB_INNOCUOUS</dt>
|
|
** <dd>Calls of the form
|
|
** [sqlite3_vtab_config](db,SQLITE_VTAB_INNOCUOUS) from within the
|
|
** the [xConnect] or [xCreate] methods of a [virtual table] implementation
|
|
** identify that virtual table as being safe to use from within triggers
|
|
** and views. Conceptually, the SQLITE_VTAB_INNOCUOUS tag means that the
|
|
** virtual table can do no serious harm even if it is controlled by a
|
|
** malicious hacker. Developers should avoid setting the SQLITE_VTAB_INNOCUOUS
|
|
** flag unless absolutely necessary.
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_VTAB_USES_ALL_SCHEMAS]]<dt>SQLITE_VTAB_USES_ALL_SCHEMAS</dt>
|
|
** <dd>Calls of the form
|
|
** [sqlite3_vtab_config](db,SQLITE_VTAB_USES_ALL_SCHEMA) from within the
|
|
** the [xConnect] or [xCreate] methods of a [virtual table] implementation
|
|
** instruct the query planner to begin at least a read transaction on
|
|
** all schemas ("main", "temp", and any ATTACH-ed databases) whenever the
|
|
** virtual table is used.
|
|
** </dd>
|
|
** </dl>
|
|
*/
|
|
#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1
|
|
#define SQLITE_VTAB_INNOCUOUS 2
|
|
#define SQLITE_VTAB_DIRECTONLY 3
|
|
#define SQLITE_VTAB_USES_ALL_SCHEMAS 4
|
|
|
|
/*
|
|
** CAPI3REF: Determine The Virtual Table Conflict Policy
|
|
**
|
|
** This function may only be called from within a call to the [xUpdate] method
|
|
** of a [virtual table] implementation for an INSERT or UPDATE operation. ^The
|
|
** value returned is one of [SQLITE_ROLLBACK], [SQLITE_IGNORE], [SQLITE_FAIL],
|
|
** [SQLITE_ABORT], or [SQLITE_REPLACE], according to the [ON CONFLICT] mode
|
|
** of the SQL statement that triggered the call to the [xUpdate] method of the
|
|
** [virtual table].
|
|
*/
|
|
SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
|
|
|
|
/*
|
|
** CAPI3REF: Determine If Virtual Table Column Access Is For UPDATE
|
|
**
|
|
** If the sqlite3_vtab_nochange(X) routine is called within the [xColumn]
|
|
** method of a [virtual table], then it might return true if the
|
|
** column is being fetched as part of an UPDATE operation during which the
|
|
** column value will not change. The virtual table implementation can use
|
|
** this hint as permission to substitute a return value that is less
|
|
** expensive to compute and that the corresponding
|
|
** [xUpdate] method understands as a "no-change" value.
|
|
**
|
|
** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that
|
|
** the column is not changed by the UPDATE statement, then the xColumn
|
|
** method can optionally return without setting a result, without calling
|
|
** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces].
|
|
** In that case, [sqlite3_value_nochange(X)] will return true for the
|
|
** same column in the [xUpdate] method.
|
|
**
|
|
** The sqlite3_vtab_nochange() routine is an optimization. Virtual table
|
|
** implementations should continue to give a correct answer even if the
|
|
** sqlite3_vtab_nochange() interface were to always return false. In the
|
|
** current implementation, the sqlite3_vtab_nochange() interface does always
|
|
** returns false for the enhanced [UPDATE FROM] statement.
|
|
*/
|
|
SQLITE_API int sqlite3_vtab_nochange(sqlite3_context*);
|
|
|
|
/*
|
|
** CAPI3REF: Determine The Collation For a Virtual Table Constraint
|
|
** METHOD: sqlite3_index_info
|
|
**
|
|
** This function may only be called from within a call to the [xBestIndex]
|
|
** method of a [virtual table]. This function returns a pointer to a string
|
|
** that is the name of the appropriate collation sequence to use for text
|
|
** comparisons on the constraint identified by its arguments.
|
|
**
|
|
** The first argument must be the pointer to the [sqlite3_index_info] object
|
|
** that is the first parameter to the xBestIndex() method. The second argument
|
|
** must be an index into the aConstraint[] array belonging to the
|
|
** sqlite3_index_info structure passed to xBestIndex.
|
|
**
|
|
** Important:
|
|
** The first parameter must be the same pointer that is passed into the
|
|
** xBestMethod() method. The first parameter may not be a pointer to a
|
|
** different [sqlite3_index_info] object, even an exact copy.
|
|
**
|
|
** The return value is computed as follows:
|
|
**
|
|
** <ol>
|
|
** <li><p> If the constraint comes from a WHERE clause expression that contains
|
|
** a [COLLATE operator], then the name of the collation specified by
|
|
** that COLLATE operator is returned.
|
|
** <li><p> If there is no COLLATE operator, but the column that is the subject
|
|
** of the constraint specifies an alternative collating sequence via
|
|
** a [COLLATE clause] on the column definition within the CREATE TABLE
|
|
** statement that was passed into [sqlite3_declare_vtab()], then the
|
|
** name of that alternative collating sequence is returned.
|
|
** <li><p> Otherwise, "BINARY" is returned.
|
|
** </ol>
|
|
*/
|
|
SQLITE_API const char *sqlite3_vtab_collation(sqlite3_index_info*,int);
|
|
|
|
/*
|
|
** CAPI3REF: Determine if a virtual table query is DISTINCT
|
|
** METHOD: sqlite3_index_info
|
|
**
|
|
** This API may only be used from within an [xBestIndex|xBestIndex method]
|
|
** of a [virtual table] implementation. The result of calling this
|
|
** interface from outside of xBestIndex() is undefined and probably harmful.
|
|
**
|
|
** ^The sqlite3_vtab_distinct() interface returns an integer between 0 and
|
|
** 3. The integer returned by sqlite3_vtab_distinct()
|
|
** gives the virtual table additional information about how the query
|
|
** planner wants the output to be ordered. As long as the virtual table
|
|
** can meet the ordering requirements of the query planner, it may set
|
|
** the "orderByConsumed" flag.
|
|
**
|
|
** <ol><li value="0"><p>
|
|
** ^If the sqlite3_vtab_distinct() interface returns 0, that means
|
|
** that the query planner needs the virtual table to return all rows in the
|
|
** sort order defined by the "nOrderBy" and "aOrderBy" fields of the
|
|
** [sqlite3_index_info] object. This is the default expectation. If the
|
|
** virtual table outputs all rows in sorted order, then it is always safe for
|
|
** the xBestIndex method to set the "orderByConsumed" flag, regardless of
|
|
** the return value from sqlite3_vtab_distinct().
|
|
** <li value="1"><p>
|
|
** ^(If the sqlite3_vtab_distinct() interface returns 1, that means
|
|
** that the query planner does not need the rows to be returned in sorted order
|
|
** as long as all rows with the same values in all columns identified by the
|
|
** "aOrderBy" field are adjacent.)^ This mode is used when the query planner
|
|
** is doing a GROUP BY.
|
|
** <li value="2"><p>
|
|
** ^(If the sqlite3_vtab_distinct() interface returns 2, that means
|
|
** that the query planner does not need the rows returned in any particular
|
|
** order, as long as rows with the same values in all "aOrderBy" columns
|
|
** are adjacent.)^ ^(Furthermore, only a single row for each particular
|
|
** combination of values in the columns identified by the "aOrderBy" field
|
|
** needs to be returned.)^ ^It is always ok for two or more rows with the same
|
|
** values in all "aOrderBy" columns to be returned, as long as all such rows
|
|
** are adjacent. ^The virtual table may, if it chooses, omit extra rows
|
|
** that have the same value for all columns identified by "aOrderBy".
|
|
** ^However omitting the extra rows is optional.
|
|
** This mode is used for a DISTINCT query.
|
|
** <li value="3"><p>
|
|
** ^(If the sqlite3_vtab_distinct() interface returns 3, that means
|
|
** that the query planner needs only distinct rows but it does need the
|
|
** rows to be sorted.)^ ^The virtual table implementation is free to omit
|
|
** rows that are identical in all aOrderBy columns, if it wants to, but
|
|
** it is not required to omit any rows. This mode is used for queries
|
|
** that have both DISTINCT and ORDER BY clauses.
|
|
** </ol>
|
|
**
|
|
** ^For the purposes of comparing virtual table output values to see if the
|
|
** values are same value for sorting purposes, two NULL values are considered
|
|
** to be the same. In other words, the comparison operator is "IS"
|
|
** (or "IS NOT DISTINCT FROM") and not "==".
|
|
**
|
|
** If a virtual table implementation is unable to meet the requirements
|
|
** specified above, then it must not set the "orderByConsumed" flag in the
|
|
** [sqlite3_index_info] object or an incorrect answer may result.
|
|
**
|
|
** ^A virtual table implementation is always free to return rows in any order
|
|
** it wants, as long as the "orderByConsumed" flag is not set. ^When the
|
|
** the "orderByConsumed" flag is unset, the query planner will add extra
|
|
** [bytecode] to ensure that the final results returned by the SQL query are
|
|
** ordered correctly. The use of the "orderByConsumed" flag and the
|
|
** sqlite3_vtab_distinct() interface is merely an optimization. ^Careful
|
|
** use of the sqlite3_vtab_distinct() interface and the "orderByConsumed"
|
|
** flag might help queries against a virtual table to run faster. Being
|
|
** overly aggressive and setting the "orderByConsumed" flag when it is not
|
|
** valid to do so, on the other hand, might cause SQLite to return incorrect
|
|
** results.
|
|
*/
|
|
SQLITE_API int sqlite3_vtab_distinct(sqlite3_index_info*);
|
|
|
|
/*
|
|
** CAPI3REF: Identify and handle IN constraints in xBestIndex
|
|
**
|
|
** This interface may only be used from within an
|
|
** [xBestIndex|xBestIndex() method] of a [virtual table] implementation.
|
|
** The result of invoking this interface from any other context is
|
|
** undefined and probably harmful.
|
|
**
|
|
** ^(A constraint on a virtual table of the form
|
|
** "[IN operator|column IN (...)]" is
|
|
** communicated to the xBestIndex method as a
|
|
** [SQLITE_INDEX_CONSTRAINT_EQ] constraint.)^ If xBestIndex wants to use
|
|
** this constraint, it must set the corresponding
|
|
** aConstraintUsage[].argvIndex to a positive integer. ^(Then, under
|
|
** the usual mode of handling IN operators, SQLite generates [bytecode]
|
|
** that invokes the [xFilter|xFilter() method] once for each value
|
|
** on the right-hand side of the IN operator.)^ Thus the virtual table
|
|
** only sees a single value from the right-hand side of the IN operator
|
|
** at a time.
|
|
**
|
|
** In some cases, however, it would be advantageous for the virtual
|
|
** table to see all values on the right-hand of the IN operator all at
|
|
** once. The sqlite3_vtab_in() interfaces facilitates this in two ways:
|
|
**
|
|
** <ol>
|
|
** <li><p>
|
|
** ^A call to sqlite3_vtab_in(P,N,-1) will return true (non-zero)
|
|
** if and only if the [sqlite3_index_info|P->aConstraint][N] constraint
|
|
** is an [IN operator] that can be processed all at once. ^In other words,
|
|
** sqlite3_vtab_in() with -1 in the third argument is a mechanism
|
|
** by which the virtual table can ask SQLite if all-at-once processing
|
|
** of the IN operator is even possible.
|
|
**
|
|
** <li><p>
|
|
** ^A call to sqlite3_vtab_in(P,N,F) with F==1 or F==0 indicates
|
|
** to SQLite that the virtual table does or does not want to process
|
|
** the IN operator all-at-once, respectively. ^Thus when the third
|
|
** parameter (F) is non-negative, this interface is the mechanism by
|
|
** which the virtual table tells SQLite how it wants to process the
|
|
** IN operator.
|
|
** </ol>
|
|
**
|
|
** ^The sqlite3_vtab_in(P,N,F) interface can be invoked multiple times
|
|
** within the same xBestIndex method call. ^For any given P,N pair,
|
|
** the return value from sqlite3_vtab_in(P,N,F) will always be the same
|
|
** within the same xBestIndex call. ^If the interface returns true
|
|
** (non-zero), that means that the constraint is an IN operator
|
|
** that can be processed all-at-once. ^If the constraint is not an IN
|
|
** operator or cannot be processed all-at-once, then the interface returns
|
|
** false.
|
|
**
|
|
** ^(All-at-once processing of the IN operator is selected if both of the
|
|
** following conditions are met:
|
|
**
|
|
** <ol>
|
|
** <li><p> The P->aConstraintUsage[N].argvIndex value is set to a positive
|
|
** integer. This is how the virtual table tells SQLite that it wants to
|
|
** use the N-th constraint.
|
|
**
|
|
** <li><p> The last call to sqlite3_vtab_in(P,N,F) for which F was
|
|
** non-negative had F>=1.
|
|
** </ol>)^
|
|
**
|
|
** ^If either or both of the conditions above are false, then SQLite uses
|
|
** the traditional one-at-a-time processing strategy for the IN constraint.
|
|
** ^If both conditions are true, then the argvIndex-th parameter to the
|
|
** xFilter method will be an [sqlite3_value] that appears to be NULL,
|
|
** but which can be passed to [sqlite3_vtab_in_first()] and
|
|
** [sqlite3_vtab_in_next()] to find all values on the right-hand side
|
|
** of the IN constraint.
|
|
*/
|
|
SQLITE_API int sqlite3_vtab_in(sqlite3_index_info*, int iCons, int bHandle);
|
|
|
|
/*
|
|
** CAPI3REF: Find all elements on the right-hand side of an IN constraint.
|
|
**
|
|
** These interfaces are only useful from within the
|
|
** [xFilter|xFilter() method] of a [virtual table] implementation.
|
|
** The result of invoking these interfaces from any other context
|
|
** is undefined and probably harmful.
|
|
**
|
|
** The X parameter in a call to sqlite3_vtab_in_first(X,P) or
|
|
** sqlite3_vtab_in_next(X,P) should be one of the parameters to the
|
|
** xFilter method which invokes these routines, and specifically
|
|
** a parameter that was previously selected for all-at-once IN constraint
|
|
** processing use the [sqlite3_vtab_in()] interface in the
|
|
** [xBestIndex|xBestIndex method]. ^(If the X parameter is not
|
|
** an xFilter argument that was selected for all-at-once IN constraint
|
|
** processing, then these routines return [SQLITE_ERROR].)^
|
|
**
|
|
** ^(Use these routines to access all values on the right-hand side
|
|
** of the IN constraint using code like the following:
|
|
**
|
|
** <blockquote><pre>
|
|
** for(rc=sqlite3_vtab_in_first(pList, &pVal);
|
|
** rc==SQLITE_OK && pVal;
|
|
** rc=sqlite3_vtab_in_next(pList, &pVal)
|
|
** ){
|
|
** // do something with pVal
|
|
** }
|
|
** if( rc!=SQLITE_OK ){
|
|
** // an error has occurred
|
|
** }
|
|
** </pre></blockquote>)^
|
|
**
|
|
** ^On success, the sqlite3_vtab_in_first(X,P) and sqlite3_vtab_in_next(X,P)
|
|
** routines return SQLITE_OK and set *P to point to the first or next value
|
|
** on the RHS of the IN constraint. ^If there are no more values on the
|
|
** right hand side of the IN constraint, then *P is set to NULL and these
|
|
** routines return [SQLITE_DONE]. ^The return value might be
|
|
** some other value, such as SQLITE_NOMEM, in the event of a malfunction.
|
|
**
|
|
** The *ppOut values returned by these routines are only valid until the
|
|
** next call to either of these routines or until the end of the xFilter
|
|
** method from which these routines were called. If the virtual table
|
|
** implementation needs to retain the *ppOut values for longer, it must make
|
|
** copies. The *ppOut values are [protected sqlite3_value|protected].
|
|
*/
|
|
SQLITE_API int sqlite3_vtab_in_first(sqlite3_value *pVal, sqlite3_value **ppOut);
|
|
SQLITE_API int sqlite3_vtab_in_next(sqlite3_value *pVal, sqlite3_value **ppOut);
|
|
|
|
/*
|
|
** CAPI3REF: Constraint values in xBestIndex()
|
|
** METHOD: sqlite3_index_info
|
|
**
|
|
** This API may only be used from within the [xBestIndex|xBestIndex method]
|
|
** of a [virtual table] implementation. The result of calling this interface
|
|
** from outside of an xBestIndex method are undefined and probably harmful.
|
|
**
|
|
** ^When the sqlite3_vtab_rhs_value(P,J,V) interface is invoked from within
|
|
** the [xBestIndex] method of a [virtual table] implementation, with P being
|
|
** a copy of the [sqlite3_index_info] object pointer passed into xBestIndex and
|
|
** J being a 0-based index into P->aConstraint[], then this routine
|
|
** attempts to set *V to the value of the right-hand operand of
|
|
** that constraint if the right-hand operand is known. ^If the
|
|
** right-hand operand is not known, then *V is set to a NULL pointer.
|
|
** ^The sqlite3_vtab_rhs_value(P,J,V) interface returns SQLITE_OK if
|
|
** and only if *V is set to a value. ^The sqlite3_vtab_rhs_value(P,J,V)
|
|
** inteface returns SQLITE_NOTFOUND if the right-hand side of the J-th
|
|
** constraint is not available. ^The sqlite3_vtab_rhs_value() interface
|
|
** can return an result code other than SQLITE_OK or SQLITE_NOTFOUND if
|
|
** something goes wrong.
|
|
**
|
|
** The sqlite3_vtab_rhs_value() interface is usually only successful if
|
|
** the right-hand operand of a constraint is a literal value in the original
|
|
** SQL statement. If the right-hand operand is an expression or a reference
|
|
** to some other column or a [host parameter], then sqlite3_vtab_rhs_value()
|
|
** will probably return [SQLITE_NOTFOUND].
|
|
**
|
|
** ^(Some constraints, such as [SQLITE_INDEX_CONSTRAINT_ISNULL] and
|
|
** [SQLITE_INDEX_CONSTRAINT_ISNOTNULL], have no right-hand operand. For such
|
|
** constraints, sqlite3_vtab_rhs_value() always returns SQLITE_NOTFOUND.)^
|
|
**
|
|
** ^The [sqlite3_value] object returned in *V is a protected sqlite3_value
|
|
** and remains valid for the duration of the xBestIndex method call.
|
|
** ^When xBestIndex returns, the sqlite3_value object returned by
|
|
** sqlite3_vtab_rhs_value() is automatically deallocated.
|
|
**
|
|
** The "_rhs_" in the name of this routine is an abbreviation for
|
|
** "Right-Hand Side".
|
|
*/
|
|
SQLITE_API int sqlite3_vtab_rhs_value(sqlite3_index_info*, int, sqlite3_value **ppVal);
|
|
|
|
/*
|
|
** CAPI3REF: Conflict resolution modes
|
|
** KEYWORDS: {conflict resolution mode}
|
|
**
|
|
** These constants are returned by [sqlite3_vtab_on_conflict()] to
|
|
** inform a [virtual table] implementation what the [ON CONFLICT] mode
|
|
** is for the SQL statement being evaluated.
|
|
**
|
|
** Note that the [SQLITE_IGNORE] constant is also used as a potential
|
|
** return value from the [sqlite3_set_authorizer()] callback and that
|
|
** [SQLITE_ABORT] is also a [result code].
|
|
*/
|
|
#define SQLITE_ROLLBACK 1
|
|
/* #define SQLITE_IGNORE 2 // Also used by sqlite3_authorizer() callback */
|
|
#define SQLITE_FAIL 3
|
|
/* #define SQLITE_ABORT 4 // Also an error code */
|
|
#define SQLITE_REPLACE 5
|
|
|
|
/*
|
|
** CAPI3REF: Prepared Statement Scan Status Opcodes
|
|
** KEYWORDS: {scanstatus options}
|
|
**
|
|
** The following constants can be used for the T parameter to the
|
|
** [sqlite3_stmt_scanstatus(S,X,T,V)] interface. Each constant designates a
|
|
** different metric for sqlite3_stmt_scanstatus() to return.
|
|
**
|
|
** When the value returned to V is a string, space to hold that string is
|
|
** managed by the prepared statement S and will be automatically freed when
|
|
** S is finalized.
|
|
**
|
|
** Not all values are available for all query elements. When a value is
|
|
** not available, the output variable is set to -1 if the value is numeric,
|
|
** or to NULL if it is a string (SQLITE_SCANSTAT_NAME).
|
|
**
|
|
** <dl>
|
|
** [[SQLITE_SCANSTAT_NLOOP]] <dt>SQLITE_SCANSTAT_NLOOP</dt>
|
|
** <dd>^The [sqlite3_int64] variable pointed to by the V parameter will be
|
|
** set to the total number of times that the X-th loop has run.</dd>
|
|
**
|
|
** [[SQLITE_SCANSTAT_NVISIT]] <dt>SQLITE_SCANSTAT_NVISIT</dt>
|
|
** <dd>^The [sqlite3_int64] variable pointed to by the V parameter will be set
|
|
** to the total number of rows examined by all iterations of the X-th loop.</dd>
|
|
**
|
|
** [[SQLITE_SCANSTAT_EST]] <dt>SQLITE_SCANSTAT_EST</dt>
|
|
** <dd>^The "double" variable pointed to by the V parameter will be set to the
|
|
** query planner's estimate for the average number of rows output from each
|
|
** iteration of the X-th loop. If the query planner's estimates was accurate,
|
|
** then this value will approximate the quotient NVISIT/NLOOP and the
|
|
** product of this value for all prior loops with the same SELECTID will
|
|
** be the NLOOP value for the current loop.
|
|
**
|
|
** [[SQLITE_SCANSTAT_NAME]] <dt>SQLITE_SCANSTAT_NAME</dt>
|
|
** <dd>^The "const char *" variable pointed to by the V parameter will be set
|
|
** to a zero-terminated UTF-8 string containing the name of the index or table
|
|
** used for the X-th loop.
|
|
**
|
|
** [[SQLITE_SCANSTAT_EXPLAIN]] <dt>SQLITE_SCANSTAT_EXPLAIN</dt>
|
|
** <dd>^The "const char *" variable pointed to by the V parameter will be set
|
|
** to a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN]
|
|
** description for the X-th loop.
|
|
**
|
|
** [[SQLITE_SCANSTAT_SELECTID]] <dt>SQLITE_SCANSTAT_SELECTID</dt>
|
|
** <dd>^The "int" variable pointed to by the V parameter will be set to the
|
|
** id for the X-th query plan element. The id value is unique within the
|
|
** statement. The select-id is the same value as is output in the first
|
|
** column of an [EXPLAIN QUERY PLAN] query.
|
|
**
|
|
** [[SQLITE_SCANSTAT_PARENTID]] <dt>SQLITE_SCANSTAT_PARENTID</dt>
|
|
** <dd>The "int" variable pointed to by the V parameter will be set to the
|
|
** the id of the parent of the current query element, if applicable, or
|
|
** to zero if the query element has no parent. This is the same value as
|
|
** returned in the second column of an [EXPLAIN QUERY PLAN] query.
|
|
**
|
|
** [[SQLITE_SCANSTAT_NCYCLE]] <dt>SQLITE_SCANSTAT_NCYCLE</dt>
|
|
** <dd>The sqlite3_int64 output value is set to the number of cycles,
|
|
** according to the processor time-stamp counter, that elapsed while the
|
|
** query element was being processed. This value is not available for
|
|
** all query elements - if it is unavailable the output variable is
|
|
** set to -1.
|
|
** </dl>
|
|
*/
|
|
#define SQLITE_SCANSTAT_NLOOP 0
|
|
#define SQLITE_SCANSTAT_NVISIT 1
|
|
#define SQLITE_SCANSTAT_EST 2
|
|
#define SQLITE_SCANSTAT_NAME 3
|
|
#define SQLITE_SCANSTAT_EXPLAIN 4
|
|
#define SQLITE_SCANSTAT_SELECTID 5
|
|
#define SQLITE_SCANSTAT_PARENTID 6
|
|
#define SQLITE_SCANSTAT_NCYCLE 7
|
|
|
|
/*
|
|
** CAPI3REF: Prepared Statement Scan Status
|
|
** METHOD: sqlite3_stmt
|
|
**
|
|
** These interfaces return information about the predicted and measured
|
|
** performance for pStmt. Advanced applications can use this
|
|
** interface to compare the predicted and the measured performance and
|
|
** issue warnings and/or rerun [ANALYZE] if discrepancies are found.
|
|
**
|
|
** Since this interface is expected to be rarely used, it is only
|
|
** available if SQLite is compiled using the [SQLITE_ENABLE_STMT_SCANSTATUS]
|
|
** compile-time option.
|
|
**
|
|
** The "iScanStatusOp" parameter determines which status information to return.
|
|
** The "iScanStatusOp" must be one of the [scanstatus options] or the behavior
|
|
** of this interface is undefined. ^The requested measurement is written into
|
|
** a variable pointed to by the "pOut" parameter.
|
|
**
|
|
** The "flags" parameter must be passed a mask of flags. At present only
|
|
** one flag is defined - SQLITE_SCANSTAT_COMPLEX. If SQLITE_SCANSTAT_COMPLEX
|
|
** is specified, then status information is available for all elements
|
|
** of a query plan that are reported by "EXPLAIN QUERY PLAN" output. If
|
|
** SQLITE_SCANSTAT_COMPLEX is not specified, then only query plan elements
|
|
** that correspond to query loops (the "SCAN..." and "SEARCH..." elements of
|
|
** the EXPLAIN QUERY PLAN output) are available. Invoking API
|
|
** sqlite3_stmt_scanstatus() is equivalent to calling
|
|
** sqlite3_stmt_scanstatus_v2() with a zeroed flags parameter.
|
|
**
|
|
** Parameter "idx" identifies the specific query element to retrieve statistics
|
|
** for. Query elements are numbered starting from zero. A value of -1 may be
|
|
** to query for statistics regarding the entire query. ^If idx is out of range
|
|
** - less than -1 or greater than or equal to the total number of query
|
|
** elements used to implement the statement - a non-zero value is returned and
|
|
** the variable that pOut points to is unchanged.
|
|
**
|
|
** See also: [sqlite3_stmt_scanstatus_reset()]
|
|
*/
|
|
SQLITE_API int sqlite3_stmt_scanstatus(
|
|
sqlite3_stmt *pStmt, /* Prepared statement for which info desired */
|
|
int idx, /* Index of loop to report on */
|
|
int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */
|
|
void *pOut /* Result written here */
|
|
);
|
|
SQLITE_API int sqlite3_stmt_scanstatus_v2(
|
|
sqlite3_stmt *pStmt, /* Prepared statement for which info desired */
|
|
int idx, /* Index of loop to report on */
|
|
int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */
|
|
int flags, /* Mask of flags defined below */
|
|
void *pOut /* Result written here */
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Prepared Statement Scan Status
|
|
** KEYWORDS: {scan status flags}
|
|
*/
|
|
#define SQLITE_SCANSTAT_COMPLEX 0x0001
|
|
|
|
/*
|
|
** CAPI3REF: Zero Scan-Status Counters
|
|
** METHOD: sqlite3_stmt
|
|
**
|
|
** ^Zero all [sqlite3_stmt_scanstatus()] related event counters.
|
|
**
|
|
** This API is only available if the library is built with pre-processor
|
|
** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined.
|
|
*/
|
|
SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
|
|
|
|
/*
|
|
** CAPI3REF: Flush caches to disk mid-transaction
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^If a write-transaction is open on [database connection] D when the
|
|
** [sqlite3_db_cacheflush(D)] interface invoked, any dirty
|
|
** pages in the pager-cache that are not currently in use are written out
|
|
** to disk. A dirty page may be in use if a database cursor created by an
|
|
** active SQL statement is reading from it, or if it is page 1 of a database
|
|
** file (page 1 is always "in use"). ^The [sqlite3_db_cacheflush(D)]
|
|
** interface flushes caches for all schemas - "main", "temp", and
|
|
** any [attached] databases.
|
|
**
|
|
** ^If this function needs to obtain extra database locks before dirty pages
|
|
** can be flushed to disk, it does so. ^If those locks cannot be obtained
|
|
** immediately and there is a busy-handler callback configured, it is invoked
|
|
** in the usual manner. ^If the required lock still cannot be obtained, then
|
|
** the database is skipped and an attempt made to flush any dirty pages
|
|
** belonging to the next (if any) database. ^If any databases are skipped
|
|
** because locks cannot be obtained, but no other error occurs, this
|
|
** function returns SQLITE_BUSY.
|
|
**
|
|
** ^If any other error occurs while flushing dirty pages to disk (for
|
|
** example an IO error or out-of-memory condition), then processing is
|
|
** abandoned and an SQLite [error code] is returned to the caller immediately.
|
|
**
|
|
** ^Otherwise, if no error occurs, [sqlite3_db_cacheflush()] returns SQLITE_OK.
|
|
**
|
|
** ^This function does not set the database handle error code or message
|
|
** returned by the [sqlite3_errcode()] and [sqlite3_errmsg()] functions.
|
|
*/
|
|
SQLITE_API int sqlite3_db_cacheflush(sqlite3*);
|
|
|
|
/*
|
|
** CAPI3REF: The pre-update hook.
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^These interfaces are only available if SQLite is compiled using the
|
|
** [SQLITE_ENABLE_PREUPDATE_HOOK] compile-time option.
|
|
**
|
|
** ^The [sqlite3_preupdate_hook()] interface registers a callback function
|
|
** that is invoked prior to each [INSERT], [UPDATE], and [DELETE] operation
|
|
** on a database table.
|
|
** ^At most one preupdate hook may be registered at a time on a single
|
|
** [database connection]; each call to [sqlite3_preupdate_hook()] overrides
|
|
** the previous setting.
|
|
** ^The preupdate hook is disabled by invoking [sqlite3_preupdate_hook()]
|
|
** with a NULL pointer as the second parameter.
|
|
** ^The third parameter to [sqlite3_preupdate_hook()] is passed through as
|
|
** the first parameter to callbacks.
|
|
**
|
|
** ^The preupdate hook only fires for changes to real database tables; the
|
|
** preupdate hook is not invoked for changes to [virtual tables] or to
|
|
** system tables like sqlite_sequence or sqlite_stat1.
|
|
**
|
|
** ^The second parameter to the preupdate callback is a pointer to
|
|
** the [database connection] that registered the preupdate hook.
|
|
** ^The third parameter to the preupdate callback is one of the constants
|
|
** [SQLITE_INSERT], [SQLITE_DELETE], or [SQLITE_UPDATE] to identify the
|
|
** kind of update operation that is about to occur.
|
|
** ^(The fourth parameter to the preupdate callback is the name of the
|
|
** database within the database connection that is being modified. This
|
|
** will be "main" for the main database or "temp" for TEMP tables or
|
|
** the name given after the AS keyword in the [ATTACH] statement for attached
|
|
** databases.)^
|
|
** ^The fifth parameter to the preupdate callback is the name of the
|
|
** table that is being modified.
|
|
**
|
|
** For an UPDATE or DELETE operation on a [rowid table], the sixth
|
|
** parameter passed to the preupdate callback is the initial [rowid] of the
|
|
** row being modified or deleted. For an INSERT operation on a rowid table,
|
|
** or any operation on a WITHOUT ROWID table, the value of the sixth
|
|
** parameter is undefined. For an INSERT or UPDATE on a rowid table the
|
|
** seventh parameter is the final rowid value of the row being inserted
|
|
** or updated. The value of the seventh parameter passed to the callback
|
|
** function is not defined for operations on WITHOUT ROWID tables, or for
|
|
** DELETE operations on rowid tables.
|
|
**
|
|
** ^The sqlite3_preupdate_hook(D,C,P) function returns the P argument from
|
|
** the previous call on the same [database connection] D, or NULL for
|
|
** the first call on D.
|
|
**
|
|
** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()],
|
|
** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces
|
|
** provide additional information about a preupdate event. These routines
|
|
** may only be called from within a preupdate callback. Invoking any of
|
|
** these routines from outside of a preupdate callback or with a
|
|
** [database connection] pointer that is different from the one supplied
|
|
** to the preupdate callback results in undefined and probably undesirable
|
|
** behavior.
|
|
**
|
|
** ^The [sqlite3_preupdate_count(D)] interface returns the number of columns
|
|
** in the row that is being inserted, updated, or deleted.
|
|
**
|
|
** ^The [sqlite3_preupdate_old(D,N,P)] interface writes into P a pointer to
|
|
** a [protected sqlite3_value] that contains the value of the Nth column of
|
|
** the table row before it is updated. The N parameter must be between 0
|
|
** and one less than the number of columns or the behavior will be
|
|
** undefined. This must only be used within SQLITE_UPDATE and SQLITE_DELETE
|
|
** preupdate callbacks; if it is used by an SQLITE_INSERT callback then the
|
|
** behavior is undefined. The [sqlite3_value] that P points to
|
|
** will be destroyed when the preupdate callback returns.
|
|
**
|
|
** ^The [sqlite3_preupdate_new(D,N,P)] interface writes into P a pointer to
|
|
** a [protected sqlite3_value] that contains the value of the Nth column of
|
|
** the table row after it is updated. The N parameter must be between 0
|
|
** and one less than the number of columns or the behavior will be
|
|
** undefined. This must only be used within SQLITE_INSERT and SQLITE_UPDATE
|
|
** preupdate callbacks; if it is used by an SQLITE_DELETE callback then the
|
|
** behavior is undefined. The [sqlite3_value] that P points to
|
|
** will be destroyed when the preupdate callback returns.
|
|
**
|
|
** ^The [sqlite3_preupdate_depth(D)] interface returns 0 if the preupdate
|
|
** callback was invoked as a result of a direct insert, update, or delete
|
|
** operation; or 1 for inserts, updates, or deletes invoked by top-level
|
|
** triggers; or 2 for changes resulting from triggers called by top-level
|
|
** triggers; and so forth.
|
|
**
|
|
** When the [sqlite3_blob_write()] API is used to update a blob column,
|
|
** the pre-update hook is invoked with SQLITE_DELETE. This is because the
|
|
** in this case the new values are not available. In this case, when a
|
|
** callback made with op==SQLITE_DELETE is actually a write using the
|
|
** sqlite3_blob_write() API, the [sqlite3_preupdate_blobwrite()] returns
|
|
** the index of the column being written. In other cases, where the
|
|
** pre-update hook is being invoked for some other reason, including a
|
|
** regular DELETE, sqlite3_preupdate_blobwrite() returns -1.
|
|
**
|
|
** See also: [sqlite3_update_hook()]
|
|
*/
|
|
#if defined(SQLITE_ENABLE_PREUPDATE_HOOK)
|
|
SQLITE_API void *sqlite3_preupdate_hook(
|
|
sqlite3 *db,
|
|
void(*xPreUpdate)(
|
|
void *pCtx, /* Copy of third arg to preupdate_hook() */
|
|
sqlite3 *db, /* Database handle */
|
|
int op, /* SQLITE_UPDATE, DELETE or INSERT */
|
|
char const *zDb, /* Database name */
|
|
char const *zName, /* Table name */
|
|
sqlite3_int64 iKey1, /* Rowid of row about to be deleted/updated */
|
|
sqlite3_int64 iKey2 /* New rowid value (for a rowid UPDATE) */
|
|
),
|
|
void*
|
|
);
|
|
SQLITE_API int sqlite3_preupdate_old(sqlite3 *, int, sqlite3_value **);
|
|
SQLITE_API int sqlite3_preupdate_count(sqlite3 *);
|
|
SQLITE_API int sqlite3_preupdate_depth(sqlite3 *);
|
|
SQLITE_API int sqlite3_preupdate_new(sqlite3 *, int, sqlite3_value **);
|
|
SQLITE_API int sqlite3_preupdate_blobwrite(sqlite3 *);
|
|
#endif
|
|
|
|
/*
|
|
** CAPI3REF: Low-level system error code
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^Attempt to return the underlying operating system error code or error
|
|
** number that caused the most recent I/O error or failure to open a file.
|
|
** The return value is OS-dependent. For example, on unix systems, after
|
|
** [sqlite3_open_v2()] returns [SQLITE_CANTOPEN], this interface could be
|
|
** called to get back the underlying "errno" that caused the problem, such
|
|
** as ENOSPC, EAUTH, EISDIR, and so forth.
|
|
*/
|
|
SQLITE_API int sqlite3_system_errno(sqlite3*);
|
|
|
|
/*
|
|
** CAPI3REF: Database Snapshot
|
|
** KEYWORDS: {snapshot} {sqlite3_snapshot}
|
|
**
|
|
** An instance of the snapshot object records the state of a [WAL mode]
|
|
** database for some specific point in history.
|
|
**
|
|
** In [WAL mode], multiple [database connections] that are open on the
|
|
** same database file can each be reading a different historical version
|
|
** of the database file. When a [database connection] begins a read
|
|
** transaction, that connection sees an unchanging copy of the database
|
|
** as it existed for the point in time when the transaction first started.
|
|
** Subsequent changes to the database from other connections are not seen
|
|
** by the reader until a new read transaction is started.
|
|
**
|
|
** The sqlite3_snapshot object records state information about an historical
|
|
** version of the database file so that it is possible to later open a new read
|
|
** transaction that sees that historical version of the database rather than
|
|
** the most recent version.
|
|
*/
|
|
typedef struct sqlite3_snapshot {
|
|
unsigned char hidden[48];
|
|
} sqlite3_snapshot;
|
|
|
|
/*
|
|
** CAPI3REF: Record A Database Snapshot
|
|
** CONSTRUCTOR: sqlite3_snapshot
|
|
**
|
|
** ^The [sqlite3_snapshot_get(D,S,P)] interface attempts to make a
|
|
** new [sqlite3_snapshot] object that records the current state of
|
|
** schema S in database connection D. ^On success, the
|
|
** [sqlite3_snapshot_get(D,S,P)] interface writes a pointer to the newly
|
|
** created [sqlite3_snapshot] object into *P and returns SQLITE_OK.
|
|
** If there is not already a read-transaction open on schema S when
|
|
** this function is called, one is opened automatically.
|
|
**
|
|
** The following must be true for this function to succeed. If any of
|
|
** the following statements are false when sqlite3_snapshot_get() is
|
|
** called, SQLITE_ERROR is returned. The final value of *P is undefined
|
|
** in this case.
|
|
**
|
|
** <ul>
|
|
** <li> The database handle must not be in [autocommit mode].
|
|
**
|
|
** <li> Schema S of [database connection] D must be a [WAL mode] database.
|
|
**
|
|
** <li> There must not be a write transaction open on schema S of database
|
|
** connection D.
|
|
**
|
|
** <li> One or more transactions must have been written to the current wal
|
|
** file since it was created on disk (by any connection). This means
|
|
** that a snapshot cannot be taken on a wal mode database with no wal
|
|
** file immediately after it is first opened. At least one transaction
|
|
** must be written to it first.
|
|
** </ul>
|
|
**
|
|
** This function may also return SQLITE_NOMEM. If it is called with the
|
|
** database handle in autocommit mode but fails for some other reason,
|
|
** whether or not a read transaction is opened on schema S is undefined.
|
|
**
|
|
** The [sqlite3_snapshot] object returned from a successful call to
|
|
** [sqlite3_snapshot_get()] must be freed using [sqlite3_snapshot_free()]
|
|
** to avoid a memory leak.
|
|
**
|
|
** The [sqlite3_snapshot_get()] interface is only available when the
|
|
** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
|
|
*/
|
|
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_get(
|
|
sqlite3 *db,
|
|
const char *zSchema,
|
|
sqlite3_snapshot **ppSnapshot
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Start a read transaction on an historical snapshot
|
|
** METHOD: sqlite3_snapshot
|
|
**
|
|
** ^The [sqlite3_snapshot_open(D,S,P)] interface either starts a new read
|
|
** transaction or upgrades an existing one for schema S of
|
|
** [database connection] D such that the read transaction refers to
|
|
** historical [snapshot] P, rather than the most recent change to the
|
|
** database. ^The [sqlite3_snapshot_open()] interface returns SQLITE_OK
|
|
** on success or an appropriate [error code] if it fails.
|
|
**
|
|
** ^In order to succeed, the database connection must not be in
|
|
** [autocommit mode] when [sqlite3_snapshot_open(D,S,P)] is called. If there
|
|
** is already a read transaction open on schema S, then the database handle
|
|
** must have no active statements (SELECT statements that have been passed
|
|
** to sqlite3_step() but not sqlite3_reset() or sqlite3_finalize()).
|
|
** SQLITE_ERROR is returned if either of these conditions is violated, or
|
|
** if schema S does not exist, or if the snapshot object is invalid.
|
|
**
|
|
** ^A call to sqlite3_snapshot_open() will fail to open if the specified
|
|
** snapshot has been overwritten by a [checkpoint]. In this case
|
|
** SQLITE_ERROR_SNAPSHOT is returned.
|
|
**
|
|
** If there is already a read transaction open when this function is
|
|
** invoked, then the same read transaction remains open (on the same
|
|
** database snapshot) if SQLITE_ERROR, SQLITE_BUSY or SQLITE_ERROR_SNAPSHOT
|
|
** is returned. If another error code - for example SQLITE_PROTOCOL or an
|
|
** SQLITE_IOERR error code - is returned, then the final state of the
|
|
** read transaction is undefined. If SQLITE_OK is returned, then the
|
|
** read transaction is now open on database snapshot P.
|
|
**
|
|
** ^(A call to [sqlite3_snapshot_open(D,S,P)] will fail if the
|
|
** database connection D does not know that the database file for
|
|
** schema S is in [WAL mode]. A database connection might not know
|
|
** that the database file is in [WAL mode] if there has been no prior
|
|
** I/O on that database connection, or if the database entered [WAL mode]
|
|
** after the most recent I/O on the database connection.)^
|
|
** (Hint: Run "[PRAGMA application_id]" against a newly opened
|
|
** database connection in order to make it ready to use snapshots.)
|
|
**
|
|
** The [sqlite3_snapshot_open()] interface is only available when the
|
|
** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
|
|
*/
|
|
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_open(
|
|
sqlite3 *db,
|
|
const char *zSchema,
|
|
sqlite3_snapshot *pSnapshot
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Destroy a snapshot
|
|
** DESTRUCTOR: sqlite3_snapshot
|
|
**
|
|
** ^The [sqlite3_snapshot_free(P)] interface destroys [sqlite3_snapshot] P.
|
|
** The application must eventually free every [sqlite3_snapshot] object
|
|
** using this routine to avoid a memory leak.
|
|
**
|
|
** The [sqlite3_snapshot_free()] interface is only available when the
|
|
** [SQLITE_ENABLE_SNAPSHOT] compile-time option is used.
|
|
*/
|
|
SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_snapshot_free(sqlite3_snapshot*);
|
|
|
|
/*
|
|
** CAPI3REF: Compare the ages of two snapshot handles.
|
|
** METHOD: sqlite3_snapshot
|
|
**
|
|
** The sqlite3_snapshot_cmp(P1, P2) interface is used to compare the ages
|
|
** of two valid snapshot handles.
|
|
**
|
|
** If the two snapshot handles are not associated with the same database
|
|
** file, the result of the comparison is undefined.
|
|
**
|
|
** Additionally, the result of the comparison is only valid if both of the
|
|
** snapshot handles were obtained by calling sqlite3_snapshot_get() since the
|
|
** last time the wal file was deleted. The wal file is deleted when the
|
|
** database is changed back to rollback mode or when the number of database
|
|
** clients drops to zero. If either snapshot handle was obtained before the
|
|
** wal file was last deleted, the value returned by this function
|
|
** is undefined.
|
|
**
|
|
** Otherwise, this API returns a negative value if P1 refers to an older
|
|
** snapshot than P2, zero if the two handles refer to the same database
|
|
** snapshot, and a positive value if P1 is a newer snapshot than P2.
|
|
**
|
|
** This interface is only available if SQLite is compiled with the
|
|
** [SQLITE_ENABLE_SNAPSHOT] option.
|
|
*/
|
|
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp(
|
|
sqlite3_snapshot *p1,
|
|
sqlite3_snapshot *p2
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Recover snapshots from a wal file
|
|
** METHOD: sqlite3_snapshot
|
|
**
|
|
** If a [WAL file] remains on disk after all database connections close
|
|
** (either through the use of the [SQLITE_FCNTL_PERSIST_WAL] [file control]
|
|
** or because the last process to have the database opened exited without
|
|
** calling [sqlite3_close()]) and a new connection is subsequently opened
|
|
** on that database and [WAL file], the [sqlite3_snapshot_open()] interface
|
|
** will only be able to open the last transaction added to the WAL file
|
|
** even though the WAL file contains other valid transactions.
|
|
**
|
|
** This function attempts to scan the WAL file associated with database zDb
|
|
** of database handle db and make all valid snapshots available to
|
|
** sqlite3_snapshot_open(). It is an error if there is already a read
|
|
** transaction open on the database, or if the database is not a WAL mode
|
|
** database.
|
|
**
|
|
** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
|
|
**
|
|
** This interface is only available if SQLite is compiled with the
|
|
** [SQLITE_ENABLE_SNAPSHOT] option.
|
|
*/
|
|
SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);
|
|
|
|
/*
|
|
** CAPI3REF: Serialize a database
|
|
**
|
|
** The sqlite3_serialize(D,S,P,F) interface returns a pointer to memory
|
|
** that is a serialization of the S database on [database connection] D.
|
|
** If P is not a NULL pointer, then the size of the database in bytes
|
|
** is written into *P.
|
|
**
|
|
** For an ordinary on-disk database file, the serialization is just a
|
|
** copy of the disk file. For an in-memory database or a "TEMP" database,
|
|
** the serialization is the same sequence of bytes which would be written
|
|
** to disk if that database where backed up to disk.
|
|
**
|
|
** The usual case is that sqlite3_serialize() copies the serialization of
|
|
** the database into memory obtained from [sqlite3_malloc64()] and returns
|
|
** a pointer to that memory. The caller is responsible for freeing the
|
|
** returned value to avoid a memory leak. However, if the F argument
|
|
** contains the SQLITE_SERIALIZE_NOCOPY bit, then no memory allocations
|
|
** are made, and the sqlite3_serialize() function will return a pointer
|
|
** to the contiguous memory representation of the database that SQLite
|
|
** is currently using for that database, or NULL if the no such contiguous
|
|
** memory representation of the database exists. A contiguous memory
|
|
** representation of the database will usually only exist if there has
|
|
** been a prior call to [sqlite3_deserialize(D,S,...)] with the same
|
|
** values of D and S.
|
|
** The size of the database is written into *P even if the
|
|
** SQLITE_SERIALIZE_NOCOPY bit is set but no contiguous copy
|
|
** of the database exists.
|
|
**
|
|
** After the call, if the SQLITE_SERIALIZE_NOCOPY bit had been set,
|
|
** the returned buffer content will remain accessible and unchanged
|
|
** until either the next write operation on the connection or when
|
|
** the connection is closed, and applications must not modify the
|
|
** buffer. If the bit had been clear, the returned buffer will not
|
|
** be accessed by SQLite after the call.
|
|
**
|
|
** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the
|
|
** SQLITE_SERIALIZE_NOCOPY bit is omitted from argument F if a memory
|
|
** allocation error occurs.
|
|
**
|
|
** This interface is omitted if SQLite is compiled with the
|
|
** [SQLITE_OMIT_DESERIALIZE] option.
|
|
*/
|
|
SQLITE_API unsigned char *sqlite3_serialize(
|
|
sqlite3 *db, /* The database connection */
|
|
const char *zSchema, /* Which DB to serialize. ex: "main", "temp", ... */
|
|
sqlite3_int64 *piSize, /* Write size of the DB here, if not NULL */
|
|
unsigned int mFlags /* Zero or more SQLITE_SERIALIZE_* flags */
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Flags for sqlite3_serialize
|
|
**
|
|
** Zero or more of the following constants can be OR-ed together for
|
|
** the F argument to [sqlite3_serialize(D,S,P,F)].
|
|
**
|
|
** SQLITE_SERIALIZE_NOCOPY means that [sqlite3_serialize()] will return
|
|
** a pointer to contiguous in-memory database that it is currently using,
|
|
** without making a copy of the database. If SQLite is not currently using
|
|
** a contiguous in-memory database, then this option causes
|
|
** [sqlite3_serialize()] to return a NULL pointer. SQLite will only be
|
|
** using a contiguous in-memory database if it has been initialized by a
|
|
** prior call to [sqlite3_deserialize()].
|
|
*/
|
|
#define SQLITE_SERIALIZE_NOCOPY 0x001 /* Do no memory allocations */
|
|
|
|
/*
|
|
** CAPI3REF: Deserialize a database
|
|
**
|
|
** The sqlite3_deserialize(D,S,P,N,M,F) interface causes the
|
|
** [database connection] D to disconnect from database S and then
|
|
** reopen S as an in-memory database based on the serialization contained
|
|
** in P. The serialized database P is N bytes in size. M is the size of
|
|
** the buffer P, which might be larger than N. If M is larger than N, and
|
|
** the SQLITE_DESERIALIZE_READONLY bit is not set in F, then SQLite is
|
|
** permitted to add content to the in-memory database as long as the total
|
|
** size does not exceed M bytes.
|
|
**
|
|
** If the SQLITE_DESERIALIZE_FREEONCLOSE bit is set in F, then SQLite will
|
|
** invoke sqlite3_free() on the serialization buffer when the database
|
|
** connection closes. If the SQLITE_DESERIALIZE_RESIZEABLE bit is set, then
|
|
** SQLite will try to increase the buffer size using sqlite3_realloc64()
|
|
** if writes on the database cause it to grow larger than M bytes.
|
|
**
|
|
** Applications must not modify the buffer P or invalidate it before
|
|
** the database connection D is closed.
|
|
**
|
|
** The sqlite3_deserialize() interface will fail with SQLITE_BUSY if the
|
|
** database is currently in a read transaction or is involved in a backup
|
|
** operation.
|
|
**
|
|
** It is not possible to deserialized into the TEMP database. If the
|
|
** S argument to sqlite3_deserialize(D,S,P,N,M,F) is "temp" then the
|
|
** function returns SQLITE_ERROR.
|
|
**
|
|
** The deserialized database should not be in [WAL mode]. If the database
|
|
** is in WAL mode, then any attempt to use the database file will result
|
|
** in an [SQLITE_CANTOPEN] error. The application can set the
|
|
** [file format version numbers] (bytes 18 and 19) of the input database P
|
|
** to 0x01 prior to invoking sqlite3_deserialize(D,S,P,N,M,F) to force the
|
|
** database file into rollback mode and work around this limitation.
|
|
**
|
|
** If sqlite3_deserialize(D,S,P,N,M,F) fails for any reason and if the
|
|
** SQLITE_DESERIALIZE_FREEONCLOSE bit is set in argument F, then
|
|
** [sqlite3_free()] is invoked on argument P prior to returning.
|
|
**
|
|
** This interface is omitted if SQLite is compiled with the
|
|
** [SQLITE_OMIT_DESERIALIZE] option.
|
|
*/
|
|
SQLITE_API int sqlite3_deserialize(
|
|
sqlite3 *db, /* The database connection */
|
|
const char *zSchema, /* Which DB to reopen with the deserialization */
|
|
unsigned char *pData, /* The serialized database content */
|
|
sqlite3_int64 szDb, /* Number bytes in the deserialization */
|
|
sqlite3_int64 szBuf, /* Total size of buffer pData[] */
|
|
unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Flags for sqlite3_deserialize()
|
|
**
|
|
** The following are allowed values for 6th argument (the F argument) to
|
|
** the [sqlite3_deserialize(D,S,P,N,M,F)] interface.
|
|
**
|
|
** The SQLITE_DESERIALIZE_FREEONCLOSE means that the database serialization
|
|
** in the P argument is held in memory obtained from [sqlite3_malloc64()]
|
|
** and that SQLite should take ownership of this memory and automatically
|
|
** free it when it has finished using it. Without this flag, the caller
|
|
** is responsible for freeing any dynamically allocated memory.
|
|
**
|
|
** The SQLITE_DESERIALIZE_RESIZEABLE flag means that SQLite is allowed to
|
|
** grow the size of the database using calls to [sqlite3_realloc64()]. This
|
|
** flag should only be used if SQLITE_DESERIALIZE_FREEONCLOSE is also used.
|
|
** Without this flag, the deserialized database cannot increase in size beyond
|
|
** the number of bytes specified by the M parameter.
|
|
**
|
|
** The SQLITE_DESERIALIZE_READONLY flag means that the deserialized database
|
|
** should be treated as read-only.
|
|
*/
|
|
#define SQLITE_DESERIALIZE_FREEONCLOSE 1 /* Call sqlite3_free() on close */
|
|
#define SQLITE_DESERIALIZE_RESIZEABLE 2 /* Resize using sqlite3_realloc64() */
|
|
#define SQLITE_DESERIALIZE_READONLY 4 /* Database is read-only */
|
|
|
|
/*
|
|
** 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
|
|
|
|
#if defined(__wasi__)
|
|
# undef SQLITE_WASI
|
|
# define SQLITE_WASI 1
|
|
# undef SQLITE_OMIT_WAL
|
|
# define SQLITE_OMIT_WAL 1/* because it requires shared memory APIs */
|
|
# ifndef SQLITE_OMIT_LOAD_EXTENSION
|
|
# define SQLITE_OMIT_LOAD_EXTENSION
|
|
# endif
|
|
# ifndef SQLITE_THREADSAFE
|
|
# define SQLITE_THREADSAFE 0
|
|
# endif
|
|
#endif
|
|
|
|
#if 0
|
|
} /* End of the 'extern "C"' block */
|
|
#endif
|
|
#endif /* SQLITE3_H */
|
|
|
|
/******** Begin file sqlite3rtree.h *********/
|
|
/*
|
|
** 2010 August 30
|
|
**
|
|
** 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.
|
|
**
|
|
*************************************************************************
|
|
*/
|
|
|
|
#ifndef _SQLITE3RTREE_H_
|
|
#define _SQLITE3RTREE_H_
|
|
|
|
|
|
#if 0
|
|
extern "C" {
|
|
#endif
|
|
|
|
typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry;
|
|
typedef struct sqlite3_rtree_query_info sqlite3_rtree_query_info;
|
|
|
|
/* The double-precision datatype used by RTree depends on the
|
|
** SQLITE_RTREE_INT_ONLY compile-time option.
|
|
*/
|
|
#ifdef SQLITE_RTREE_INT_ONLY
|
|
typedef sqlite3_int64 sqlite3_rtree_dbl;
|
|
#else
|
|
typedef double sqlite3_rtree_dbl;
|
|
#endif
|
|
|
|
/*
|
|
** Register a geometry callback named zGeom that can be used as part of an
|
|
** R-Tree geometry query as follows:
|
|
**
|
|
** SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zGeom(... params ...)
|
|
*/
|
|
SQLITE_API int sqlite3_rtree_geometry_callback(
|
|
sqlite3 *db,
|
|
const char *zGeom,
|
|
int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*),
|
|
void *pContext
|
|
);
|
|
|
|
|
|
/*
|
|
** A pointer to a structure of the following type is passed as the first
|
|
** argument to callbacks registered using rtree_geometry_callback().
|
|
*/
|
|
struct sqlite3_rtree_geometry {
|
|
void *pContext; /* Copy of pContext passed to s_r_g_c() */
|
|
int nParam; /* Size of array aParam[] */
|
|
sqlite3_rtree_dbl *aParam; /* Parameters passed to SQL geom function */
|
|
void *pUser; /* Callback implementation user data */
|
|
void (*xDelUser)(void *); /* Called by SQLite to clean up pUser */
|
|
};
|
|
|
|
/*
|
|
** Register a 2nd-generation geometry callback named zScore that can be
|
|
** used as part of an R-Tree geometry query as follows:
|
|
**
|
|
** SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zQueryFunc(... params ...)
|
|
*/
|
|
SQLITE_API int sqlite3_rtree_query_callback(
|
|
sqlite3 *db,
|
|
const char *zQueryFunc,
|
|
int (*xQueryFunc)(sqlite3_rtree_query_info*),
|
|
void *pContext,
|
|
void (*xDestructor)(void*)
|
|
);
|
|
|
|
|
|
/*
|
|
** A pointer to a structure of the following type is passed as the
|
|
** argument to scored geometry callback registered using
|
|
** sqlite3_rtree_query_callback().
|
|
**
|
|
** Note that the first 5 fields of this structure are identical to
|
|
** sqlite3_rtree_geometry. This structure is a subclass of
|
|
** sqlite3_rtree_geometry.
|
|
*/
|
|
struct sqlite3_rtree_query_info {
|
|
void *pContext; /* pContext from when function registered */
|
|
int nParam; /* Number of function parameters */
|
|
sqlite3_rtree_dbl *aParam; /* value of function parameters */
|
|
void *pUser; /* callback can use this, if desired */
|
|
void (*xDelUser)(void*); /* function to free pUser */
|
|
sqlite3_rtree_dbl *aCoord; /* Coordinates of node or entry to check */
|
|
unsigned int *anQueue; /* Number of pending entries in the queue */
|
|
int nCoord; /* Number of coordinates */
|
|
int iLevel; /* Level of current node or entry */
|
|
int mxLevel; /* The largest iLevel value in the tree */
|
|
sqlite3_int64 iRowid; /* Rowid for current entry */
|
|
sqlite3_rtree_dbl rParentScore; /* Score of parent node */
|
|
int eParentWithin; /* Visibility of parent node */
|
|
int eWithin; /* OUT: Visibility */
|
|
sqlite3_rtree_dbl rScore; /* OUT: Write the score here */
|
|
/* The following fields are only available in 3.8.11 and later */
|
|
sqlite3_value **apSqlParam; /* Original SQL values of parameters */
|
|
};
|
|
|
|
/*
|
|
** Allowed values for sqlite3_rtree_query.eWithin and .eParentWithin.
|
|
*/
|
|
#define NOT_WITHIN 0 /* Object completely outside of query region */
|
|
#define PARTLY_WITHIN 1 /* Object partially overlaps query region */
|
|
#define FULLY_WITHIN 2 /* Object fully contained within query region */
|
|
|
|
|
|
#if 0
|
|
} /* end of the 'extern "C"' block */
|
|
#endif
|
|
|
|
#endif /* ifndef _SQLITE3RTREE_H_ */
|
|
|
|
/******** End of sqlite3rtree.h *********/
|
|
/******** Begin file sqlite3session.h *********/
|
|
|
|
#if !defined(__SQLITESESSION_H_) && defined(SQLITE_ENABLE_SESSION)
|
|
#define __SQLITESESSION_H_ 1
|
|
|
|
/*
|
|
** Make sure we can call this stuff from C++.
|
|
*/
|
|
#if 0
|
|
extern "C" {
|
|
#endif
|
|
|
|
|
|
/*
|
|
** CAPI3REF: Session Object Handle
|
|
**
|
|
** An instance of this object is a [session] that can be used to
|
|
** record changes to a database.
|
|
*/
|
|
typedef struct sqlite3_session sqlite3_session;
|
|
|
|
/*
|
|
** CAPI3REF: Changeset Iterator Handle
|
|
**
|
|
** An instance of this object acts as a cursor for iterating
|
|
** over the elements of a [changeset] or [patchset].
|
|
*/
|
|
typedef struct sqlite3_changeset_iter sqlite3_changeset_iter;
|
|
|
|
/*
|
|
** CAPI3REF: Create A New Session Object
|
|
** CONSTRUCTOR: sqlite3_session
|
|
**
|
|
** Create a new session object attached to database handle db. If successful,
|
|
** a pointer to the new object is written to *ppSession and SQLITE_OK is
|
|
** returned. If an error occurs, *ppSession is set to NULL and an SQLite
|
|
** error code (e.g. SQLITE_NOMEM) is returned.
|
|
**
|
|
** It is possible to create multiple session objects attached to a single
|
|
** database handle.
|
|
**
|
|
** Session objects created using this function should be deleted using the
|
|
** [sqlite3session_delete()] function before the database handle that they
|
|
** are attached to is itself closed. If the database handle is closed before
|
|
** the session object is deleted, then the results of calling any session
|
|
** module function, including [sqlite3session_delete()] on the session object
|
|
** are undefined.
|
|
**
|
|
** Because the session module uses the [sqlite3_preupdate_hook()] API, it
|
|
** is not possible for an application to register a pre-update hook on a
|
|
** database handle that has one or more session objects attached. Nor is
|
|
** it possible to create a session object attached to a database handle for
|
|
** which a pre-update hook is already defined. The results of attempting
|
|
** either of these things are undefined.
|
|
**
|
|
** The session object will be used to create changesets for tables in
|
|
** database zDb, where zDb is either "main", or "temp", or the name of an
|
|
** attached database. It is not an error if database zDb is not attached
|
|
** to the database when the session object is created.
|
|
*/
|
|
SQLITE_API int sqlite3session_create(
|
|
sqlite3 *db, /* Database handle */
|
|
const char *zDb, /* Name of db (e.g. "main") */
|
|
sqlite3_session **ppSession /* OUT: New session object */
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Delete A Session Object
|
|
** DESTRUCTOR: sqlite3_session
|
|
**
|
|
** Delete a session object previously allocated using
|
|
** [sqlite3session_create()]. Once a session object has been deleted, the
|
|
** results of attempting to use pSession with any other session module
|
|
** function are undefined.
|
|
**
|
|
** Session objects must be deleted before the database handle to which they
|
|
** are attached is closed. Refer to the documentation for
|
|
** [sqlite3session_create()] for details.
|
|
*/
|
|
SQLITE_API void sqlite3session_delete(sqlite3_session *pSession);
|
|
|
|
/*
|
|
** CAPI3REF: Configure a Session Object
|
|
** METHOD: sqlite3_session
|
|
**
|
|
** This method is used to configure a session object after it has been
|
|
** created. At present the only valid values for the second parameter are
|
|
** [SQLITE_SESSION_OBJCONFIG_SIZE] and [SQLITE_SESSION_OBJCONFIG_ROWID].
|
|
**
|
|
*/
|
|
SQLITE_API int sqlite3session_object_config(sqlite3_session*, int op, void *pArg);
|
|
|
|
/*
|
|
** CAPI3REF: Options for sqlite3session_object_config
|
|
**
|
|
** The following values may passed as the the 2nd parameter to
|
|
** sqlite3session_object_config().
|
|
**
|
|
** <dt>SQLITE_SESSION_OBJCONFIG_SIZE <dd>
|
|
** This option is used to set, clear or query the flag that enables
|
|
** the [sqlite3session_changeset_size()] API. Because it imposes some
|
|
** computational overhead, this API is disabled by default. Argument
|
|
** pArg must point to a value of type (int). If the value is initially
|
|
** 0, then the sqlite3session_changeset_size() API is disabled. If it
|
|
** is greater than 0, then the same API is enabled. Or, if the initial
|
|
** value is less than zero, no change is made. In all cases the (int)
|
|
** variable is set to 1 if the sqlite3session_changeset_size() API is
|
|
** enabled following the current call, or 0 otherwise.
|
|
**
|
|
** It is an error (SQLITE_MISUSE) to attempt to modify this setting after
|
|
** the first table has been attached to the session object.
|
|
**
|
|
** <dt>SQLITE_SESSION_OBJCONFIG_ROWID <dd>
|
|
** This option is used to set, clear or query the flag that enables
|
|
** collection of data for tables with no explicit PRIMARY KEY.
|
|
**
|
|
** Normally, tables with no explicit PRIMARY KEY are simply ignored
|
|
** by the sessions module. However, if this flag is set, it behaves
|
|
** as if such tables have a column "_rowid_ INTEGER PRIMARY KEY" inserted
|
|
** as their leftmost columns.
|
|
**
|
|
** It is an error (SQLITE_MISUSE) to attempt to modify this setting after
|
|
** the first table has been attached to the session object.
|
|
*/
|
|
#define SQLITE_SESSION_OBJCONFIG_SIZE 1
|
|
#define SQLITE_SESSION_OBJCONFIG_ROWID 2
|
|
|
|
/*
|
|
** CAPI3REF: Enable Or Disable A Session Object
|
|
** METHOD: sqlite3_session
|
|
**
|
|
** Enable or disable the recording of changes by a session object. When
|
|
** enabled, a session object records changes made to the database. When
|
|
** disabled - it does not. A newly created session object is enabled.
|
|
** Refer to the documentation for [sqlite3session_changeset()] for further
|
|
** details regarding how enabling and disabling a session object affects
|
|
** the eventual changesets.
|
|
**
|
|
** Passing zero to this function disables the session. Passing a value
|
|
** greater than zero enables it. Passing a value less than zero is a
|
|
** no-op, and may be used to query the current state of the session.
|
|
**
|
|
** The return value indicates the final state of the session object: 0 if
|
|
** the session is disabled, or 1 if it is enabled.
|
|
*/
|
|
SQLITE_API int sqlite3session_enable(sqlite3_session *pSession, int bEnable);
|
|
|
|
/*
|
|
** CAPI3REF: Set Or Clear the Indirect Change Flag
|
|
** METHOD: sqlite3_session
|
|
**
|
|
** Each change recorded by a session object is marked as either direct or
|
|
** indirect. A change is marked as indirect if either:
|
|
**
|
|
** <ul>
|
|
** <li> The session object "indirect" flag is set when the change is
|
|
** made, or
|
|
** <li> The change is made by an SQL trigger or foreign key action
|
|
** instead of directly as a result of a users SQL statement.
|
|
** </ul>
|
|
**
|
|
** If a single row is affected by more than one operation within a session,
|
|
** then the change is considered indirect if all operations meet the criteria
|
|
** for an indirect change above, or direct otherwise.
|
|
**
|
|
** This function is used to set, clear or query the session object indirect
|
|
** flag. If the second argument passed to this function is zero, then the
|
|
** indirect flag is cleared. If it is greater than zero, the indirect flag
|
|
** is set. Passing a value less than zero does not modify the current value
|
|
** of the indirect flag, and may be used to query the current state of the
|
|
** indirect flag for the specified session object.
|
|
**
|
|
** The return value indicates the final state of the indirect flag: 0 if
|
|
** it is clear, or 1 if it is set.
|
|
*/
|
|
SQLITE_API int sqlite3session_indirect(sqlite3_session *pSession, int bIndirect);
|
|
|
|
/*
|
|
** CAPI3REF: Attach A Table To A Session Object
|
|
** METHOD: sqlite3_session
|
|
**
|
|
** If argument zTab is not NULL, then it is the name of a table to attach
|
|
** to the session object passed as the first argument. All subsequent changes
|
|
** made to the table while the session object is enabled will be recorded. See
|
|
** documentation for [sqlite3session_changeset()] for further details.
|
|
**
|
|
** Or, if argument zTab is NULL, then changes are recorded for all tables
|
|
** in the database. If additional tables are added to the database (by
|
|
** executing "CREATE TABLE" statements) after this call is made, changes for
|
|
** the new tables are also recorded.
|
|
**
|
|
** Changes can only be recorded for tables that have a PRIMARY KEY explicitly
|
|
** defined as part of their CREATE TABLE statement. It does not matter if the
|
|
** PRIMARY KEY is an "INTEGER PRIMARY KEY" (rowid alias) or not. The PRIMARY
|
|
** KEY may consist of a single column, or may be a composite key.
|
|
**
|
|
** It is not an error if the named table does not exist in the database. Nor
|
|
** is it an error if the named table does not have a PRIMARY KEY. However,
|
|
** no changes will be recorded in either of these scenarios.
|
|
**
|
|
** Changes are not recorded for individual rows that have NULL values stored
|
|
** in one or more of their PRIMARY KEY columns.
|
|
**
|
|
** SQLITE_OK is returned if the call completes without error. Or, if an error
|
|
** occurs, an SQLite error code (e.g. SQLITE_NOMEM) is returned.
|
|
**
|
|
** <h3>Special sqlite_stat1 Handling</h3>
|
|
**
|
|
** As of SQLite version 3.22.0, the "sqlite_stat1" table is an exception to
|
|
** some of the rules above. In SQLite, the schema of sqlite_stat1 is:
|
|
** <pre>
|
|
** CREATE TABLE sqlite_stat1(tbl,idx,stat)
|
|
** </pre>
|
|
**
|
|
** Even though sqlite_stat1 does not have a PRIMARY KEY, changes are
|
|
** recorded for it as if the PRIMARY KEY is (tbl,idx). Additionally, changes
|
|
** are recorded for rows for which (idx IS NULL) is true. However, for such
|
|
** rows a zero-length blob (SQL value X'') is stored in the changeset or
|
|
** patchset instead of a NULL value. This allows such changesets to be
|
|
** manipulated by legacy implementations of sqlite3changeset_invert(),
|
|
** concat() and similar.
|
|
**
|
|
** The sqlite3changeset_apply() function automatically converts the
|
|
** zero-length blob back to a NULL value when updating the sqlite_stat1
|
|
** table. However, if the application calls sqlite3changeset_new(),
|
|
** sqlite3changeset_old() or sqlite3changeset_conflict on a changeset
|
|
** iterator directly (including on a changeset iterator passed to a
|
|
** conflict-handler callback) then the X'' value is returned. The application
|
|
** must translate X'' to NULL itself if required.
|
|
**
|
|
** Legacy (older than 3.22.0) versions of the sessions module cannot capture
|
|
** changes made to the sqlite_stat1 table. Legacy versions of the
|
|
** sqlite3changeset_apply() function silently ignore any modifications to the
|
|
** sqlite_stat1 table that are part of a changeset or patchset.
|
|
*/
|
|
SQLITE_API int sqlite3session_attach(
|
|
sqlite3_session *pSession, /* Session object */
|
|
const char *zTab /* Table name */
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Set a table filter on a Session Object.
|
|
** METHOD: sqlite3_session
|
|
**
|
|
** The second argument (xFilter) is the "filter callback". For changes to rows
|
|
** in tables that are not attached to the Session object, the filter is called
|
|
** to determine whether changes to the table's rows should be tracked or not.
|
|
** If xFilter returns 0, changes are not tracked. Note that once a table is
|
|
** attached, xFilter will not be called again.
|
|
*/
|
|
SQLITE_API void sqlite3session_table_filter(
|
|
sqlite3_session *pSession, /* Session object */
|
|
int(*xFilter)(
|
|
void *pCtx, /* Copy of third arg to _filter_table() */
|
|
const char *zTab /* Table name */
|
|
),
|
|
void *pCtx /* First argument passed to xFilter */
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Generate A Changeset From A Session Object
|
|
** METHOD: sqlite3_session
|
|
**
|
|
** Obtain a changeset containing changes to the tables attached to the
|
|
** session object passed as the first argument. If successful,
|
|
** set *ppChangeset to point to a buffer containing the changeset
|
|
** and *pnChangeset to the size of the changeset in bytes before returning
|
|
** SQLITE_OK. If an error occurs, set both *ppChangeset and *pnChangeset to
|
|
** zero and return an SQLite error code.
|
|
**
|
|
** A changeset consists of zero or more INSERT, UPDATE and/or DELETE changes,
|
|
** each representing a change to a single row of an attached table. An INSERT
|
|
** change contains the values of each field of a new database row. A DELETE
|
|
** contains the original values of each field of a deleted database row. An
|
|
** UPDATE change contains the original values of each field of an updated
|
|
** database row along with the updated values for each updated non-primary-key
|
|
** column. It is not possible for an UPDATE change to represent a change that
|
|
** modifies the values of primary key columns. If such a change is made, it
|
|
** is represented in a changeset as a DELETE followed by an INSERT.
|
|
**
|
|
** Changes are not recorded for rows that have NULL values stored in one or
|
|
** more of their PRIMARY KEY columns. If such a row is inserted or deleted,
|
|
** no corresponding change is present in the changesets returned by this
|
|
** function. If an existing row with one or more NULL values stored in
|
|
** PRIMARY KEY columns is updated so that all PRIMARY KEY columns are non-NULL,
|
|
** only an INSERT is appears in the changeset. Similarly, if an existing row
|
|
** with non-NULL PRIMARY KEY values is updated so that one or more of its
|
|
** PRIMARY KEY columns are set to NULL, the resulting changeset contains a
|
|
** DELETE change only.
|
|
**
|
|
** The contents of a changeset may be traversed using an iterator created
|
|
** using the [sqlite3changeset_start()] API. A changeset may be applied to
|
|
** a database with a compatible schema using the [sqlite3changeset_apply()]
|
|
** API.
|
|
**
|
|
** Within a changeset generated by this function, all changes related to a
|
|
** single table are grouped together. In other words, when iterating through
|
|
** a changeset or when applying a changeset to a database, all changes related
|
|
** to a single table are processed before moving on to the next table. Tables
|
|
** are sorted in the same order in which they were attached (or auto-attached)
|
|
** to the sqlite3_session object. The order in which the changes related to
|
|
** a single table are stored is undefined.
|
|
**
|
|
** Following a successful call to this function, it is the responsibility of
|
|
** the caller to eventually free the buffer that *ppChangeset points to using
|
|
** [sqlite3_free()].
|
|
**
|
|
** <h3>Changeset Generation</h3>
|
|
**
|
|
** Once a table has been attached to a session object, the session object
|
|
** records the primary key values of all new rows inserted into the table.
|
|
** It also records the original primary key and other column values of any
|
|
** deleted or updated rows. For each unique primary key value, data is only
|
|
** recorded once - the first time a row with said primary key is inserted,
|
|
** updated or deleted in the lifetime of the session.
|
|
**
|
|
** There is one exception to the previous paragraph: when a row is inserted,
|
|
** updated or deleted, if one or more of its primary key columns contain a
|
|
** NULL value, no record of the change is made.
|
|
**
|
|
** The session object therefore accumulates two types of records - those
|
|
** that consist of primary key values only (created when the user inserts
|
|
** a new record) and those that consist of the primary key values and the
|
|
** original values of other table columns (created when the users deletes
|
|
** or updates a record).
|
|
**
|
|
** When this function is called, the requested changeset is created using
|
|
** both the accumulated records and the current contents of the database
|
|
** file. Specifically:
|
|
**
|
|
** <ul>
|
|
** <li> For each record generated by an insert, the database is queried
|
|
** for a row with a matching primary key. If one is found, an INSERT
|
|
** change is added to the changeset. If no such row is found, no change
|
|
** is added to the changeset.
|
|
**
|
|
** <li> For each record generated by an update or delete, the database is
|
|
** queried for a row with a matching primary key. If such a row is
|
|
** found and one or more of the non-primary key fields have been
|
|
** modified from their original values, an UPDATE change is added to
|
|
** the changeset. Or, if no such row is found in the table, a DELETE
|
|
** change is added to the changeset. If there is a row with a matching
|
|
** primary key in the database, but all fields contain their original
|
|
** values, no change is added to the changeset.
|
|
** </ul>
|
|
**
|
|
** This means, amongst other things, that if a row is inserted and then later
|
|
** deleted while a session object is active, neither the insert nor the delete
|
|
** will be present in the changeset. Or if a row is deleted and then later a
|
|
** row with the same primary key values inserted while a session object is
|
|
** active, the resulting changeset will contain an UPDATE change instead of
|
|
** a DELETE and an INSERT.
|
|
**
|
|
** When a session object is disabled (see the [sqlite3session_enable()] API),
|
|
** it does not accumulate records when rows are inserted, updated or deleted.
|
|
** This may appear to have some counter-intuitive effects if a single row
|
|
** is written to more than once during a session. For example, if a row
|
|
** is inserted while a session object is enabled, then later deleted while
|
|
** the same session object is disabled, no INSERT record will appear in the
|
|
** changeset, even though the delete took place while the session was disabled.
|
|
** Or, if one field of a row is updated while a session is disabled, and
|
|
** another field of the same row is updated while the session is enabled, the
|
|
** resulting changeset will contain an UPDATE change that updates both fields.
|
|
*/
|
|
SQLITE_API int sqlite3session_changeset(
|
|
sqlite3_session *pSession, /* Session object */
|
|
int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */
|
|
void **ppChangeset /* OUT: Buffer containing changeset */
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Return An Upper-limit For The Size Of The Changeset
|
|
** METHOD: sqlite3_session
|
|
**
|
|
** By default, this function always returns 0. For it to return
|
|
** a useful result, the sqlite3_session object must have been configured
|
|
** to enable this API using sqlite3session_object_config() with the
|
|
** SQLITE_SESSION_OBJCONFIG_SIZE verb.
|
|
**
|
|
** When enabled, this function returns an upper limit, in bytes, for the size
|
|
** of the changeset that might be produced if sqlite3session_changeset() were
|
|
** called. The final changeset size might be equal to or smaller than the
|
|
** size in bytes returned by this function.
|
|
*/
|
|
SQLITE_API sqlite3_int64 sqlite3session_changeset_size(sqlite3_session *pSession);
|
|
|
|
/*
|
|
** CAPI3REF: Load The Difference Between Tables Into A Session
|
|
** METHOD: sqlite3_session
|
|
**
|
|
** If it is not already attached to the session object passed as the first
|
|
** argument, this function attaches table zTbl in the same manner as the
|
|
** [sqlite3session_attach()] function. If zTbl does not exist, or if it
|
|
** does not have a primary key, this function is a no-op (but does not return
|
|
** an error).
|
|
**
|
|
** Argument zFromDb must be the name of a database ("main", "temp" etc.)
|
|
** attached to the same database handle as the session object that contains
|
|
** a table compatible with the table attached to the session by this function.
|
|
** A table is considered compatible if it:
|
|
**
|
|
** <ul>
|
|
** <li> Has the same name,
|
|
** <li> Has the same set of columns declared in the same order, and
|
|
** <li> Has the same PRIMARY KEY definition.
|
|
** </ul>
|
|
**
|
|
** If the tables are not compatible, SQLITE_SCHEMA is returned. If the tables
|
|
** are compatible but do not have any PRIMARY KEY columns, it is not an error
|
|
** but no changes are added to the session object. As with other session
|
|
** APIs, tables without PRIMARY KEYs are simply ignored.
|
|
**
|
|
** This function adds a set of changes to the session object that could be
|
|
** used to update the table in database zFrom (call this the "from-table")
|
|
** so that its content is the same as the table attached to the session
|
|
** object (call this the "to-table"). Specifically:
|
|
**
|
|
** <ul>
|
|
** <li> For each row (primary key) that exists in the to-table but not in
|
|
** the from-table, an INSERT record is added to the session object.
|
|
**
|
|
** <li> For each row (primary key) that exists in the to-table but not in
|
|
** the from-table, a DELETE record is added to the session object.
|
|
**
|
|
** <li> For each row (primary key) that exists in both tables, but features
|
|
** different non-PK values in each, an UPDATE record is added to the
|
|
** session.
|
|
** </ul>
|
|
**
|
|
** To clarify, if this function is called and then a changeset constructed
|
|
** using [sqlite3session_changeset()], then after applying that changeset to
|
|
** database zFrom the contents of the two compatible tables would be
|
|
** identical.
|
|
**
|
|
** It an error if database zFrom does not exist or does not contain the
|
|
** required compatible table.
|
|
**
|
|
** If the operation is successful, SQLITE_OK is returned. Otherwise, an SQLite
|
|
** error code. In this case, if argument pzErrMsg is not NULL, *pzErrMsg
|
|
** may be set to point to a buffer containing an English language error
|
|
** message. It is the responsibility of the caller to free this buffer using
|
|
** sqlite3_free().
|
|
*/
|
|
SQLITE_API int sqlite3session_diff(
|
|
sqlite3_session *pSession,
|
|
const char *zFromDb,
|
|
const char *zTbl,
|
|
char **pzErrMsg
|
|
);
|
|
|
|
|
|
/*
|
|
** CAPI3REF: Generate A Patchset From A Session Object
|
|
** METHOD: sqlite3_session
|
|
**
|
|
** The differences between a patchset and a changeset are that:
|
|
**
|
|
** <ul>
|
|
** <li> DELETE records consist of the primary key fields only. The
|
|
** original values of other fields are omitted.
|
|
** <li> The original values of any modified fields are omitted from
|
|
** UPDATE records.
|
|
** </ul>
|
|
**
|
|
** A patchset blob may be used with up to date versions of all
|
|
** sqlite3changeset_xxx API functions except for sqlite3changeset_invert(),
|
|
** which returns SQLITE_CORRUPT if it is passed a patchset. Similarly,
|
|
** attempting to use a patchset blob with old versions of the
|
|
** sqlite3changeset_xxx APIs also provokes an SQLITE_CORRUPT error.
|
|
**
|
|
** Because the non-primary key "old.*" fields are omitted, no
|
|
** SQLITE_CHANGESET_DATA conflicts can be detected or reported if a patchset
|
|
** is passed to the sqlite3changeset_apply() API. Other conflict types work
|
|
** in the same way as for changesets.
|
|
**
|
|
** Changes within a patchset are ordered in the same way as for changesets
|
|
** generated by the sqlite3session_changeset() function (i.e. all changes for
|
|
** a single table are grouped together, tables appear in the order in which
|
|
** they were attached to the session object).
|
|
*/
|
|
SQLITE_API int sqlite3session_patchset(
|
|
sqlite3_session *pSession, /* Session object */
|
|
int *pnPatchset, /* OUT: Size of buffer at *ppPatchset */
|
|
void **ppPatchset /* OUT: Buffer containing patchset */
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Test if a changeset has recorded any changes.
|
|
**
|
|
** Return non-zero if no changes to attached tables have been recorded by
|
|
** the session object passed as the first argument. Otherwise, if one or
|
|
** more changes have been recorded, return zero.
|
|
**
|
|
** Even if this function returns zero, it is possible that calling
|
|
** [sqlite3session_changeset()] on the session handle may still return a
|
|
** changeset that contains no changes. This can happen when a row in
|
|
** an attached table is modified and then later on the original values
|
|
** are restored. However, if this function returns non-zero, then it is
|
|
** guaranteed that a call to sqlite3session_changeset() will return a
|
|
** changeset containing zero changes.
|
|
*/
|
|
SQLITE_API int sqlite3session_isempty(sqlite3_session *pSession);
|
|
|
|
/*
|
|
** CAPI3REF: Query for the amount of heap memory used by a session object.
|
|
**
|
|
** This API returns the total amount of heap memory in bytes currently
|
|
** used by the session object passed as the only argument.
|
|
*/
|
|
SQLITE_API sqlite3_int64 sqlite3session_memory_used(sqlite3_session *pSession);
|
|
|
|
/*
|
|
** CAPI3REF: Create An Iterator To Traverse A Changeset
|
|
** CONSTRUCTOR: sqlite3_changeset_iter
|
|
**
|
|
** Create an iterator used to iterate through the contents of a changeset.
|
|
** If successful, *pp is set to point to the iterator handle and SQLITE_OK
|
|
** is returned. Otherwise, if an error occurs, *pp is set to zero and an
|
|
** SQLite error code is returned.
|
|
**
|
|
** The following functions can be used to advance and query a changeset
|
|
** iterator created by this function:
|
|
**
|
|
** <ul>
|
|
** <li> [sqlite3changeset_next()]
|
|
** <li> [sqlite3changeset_op()]
|
|
** <li> [sqlite3changeset_new()]
|
|
** <li> [sqlite3changeset_old()]
|
|
** </ul>
|
|
**
|
|
** It is the responsibility of the caller to eventually destroy the iterator
|
|
** by passing it to [sqlite3changeset_finalize()]. The buffer containing the
|
|
** changeset (pChangeset) must remain valid until after the iterator is
|
|
** destroyed.
|
|
**
|
|
** Assuming the changeset blob was created by one of the
|
|
** [sqlite3session_changeset()], [sqlite3changeset_concat()] or
|
|
** [sqlite3changeset_invert()] functions, all changes within the changeset
|
|
** that apply to a single table are grouped together. This means that when
|
|
** an application iterates through a changeset using an iterator created by
|
|
** this function, all changes that relate to a single table are visited
|
|
** consecutively. There is no chance that the iterator will visit a change
|
|
** the applies to table X, then one for table Y, and then later on visit
|
|
** another change for table X.
|
|
**
|
|
** The behavior of sqlite3changeset_start_v2() and its streaming equivalent
|
|
** may be modified by passing a combination of
|
|
** [SQLITE_CHANGESETSTART_INVERT | supported flags] as the 4th parameter.
|
|
**
|
|
** Note that the sqlite3changeset_start_v2() API is still <b>experimental</b>
|
|
** and therefore subject to change.
|
|
*/
|
|
SQLITE_API int sqlite3changeset_start(
|
|
sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */
|
|
int nChangeset, /* Size of changeset blob in bytes */
|
|
void *pChangeset /* Pointer to blob containing changeset */
|
|
);
|
|
SQLITE_API int sqlite3changeset_start_v2(
|
|
sqlite3_changeset_iter **pp, /* OUT: New changeset iterator handle */
|
|
int nChangeset, /* Size of changeset blob in bytes */
|
|
void *pChangeset, /* Pointer to blob containing changeset */
|
|
int flags /* SESSION_CHANGESETSTART_* flags */
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Flags for sqlite3changeset_start_v2
|
|
**
|
|
** The following flags may passed via the 4th parameter to
|
|
** [sqlite3changeset_start_v2] and [sqlite3changeset_start_v2_strm]:
|
|
**
|
|
** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd>
|
|
** Invert the changeset while iterating through it. This is equivalent to
|
|
** inverting a changeset using sqlite3changeset_invert() before applying it.
|
|
** It is an error to specify this flag with a patchset.
|
|
*/
|
|
#define SQLITE_CHANGESETSTART_INVERT 0x0002
|
|
|
|
|
|
/*
|
|
** CAPI3REF: Advance A Changeset Iterator
|
|
** METHOD: sqlite3_changeset_iter
|
|
**
|
|
** This function may only be used with iterators created by the function
|
|
** [sqlite3changeset_start()]. If it is called on an iterator passed to
|
|
** a conflict-handler callback by [sqlite3changeset_apply()], SQLITE_MISUSE
|
|
** is returned and the call has no effect.
|
|
**
|
|
** Immediately after an iterator is created by sqlite3changeset_start(), it
|
|
** does not point to any change in the changeset. Assuming the changeset
|
|
** is not empty, the first call to this function advances the iterator to
|
|
** point to the first change in the changeset. Each subsequent call advances
|
|
** the iterator to point to the next change in the changeset (if any). If
|
|
** no error occurs and the iterator points to a valid change after a call
|
|
** to sqlite3changeset_next() has advanced it, SQLITE_ROW is returned.
|
|
** Otherwise, if all changes in the changeset have already been visited,
|
|
** SQLITE_DONE is returned.
|
|
**
|
|
** If an error occurs, an SQLite error code is returned. Possible error
|
|
** codes include SQLITE_CORRUPT (if the changeset buffer is corrupt) or
|
|
** SQLITE_NOMEM.
|
|
*/
|
|
SQLITE_API int sqlite3changeset_next(sqlite3_changeset_iter *pIter);
|
|
|
|
/*
|
|
** CAPI3REF: Obtain The Current Operation From A Changeset Iterator
|
|
** METHOD: sqlite3_changeset_iter
|
|
**
|
|
** The pIter argument passed to this function may either be an iterator
|
|
** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator
|
|
** created by [sqlite3changeset_start()]. In the latter case, the most recent
|
|
** call to [sqlite3changeset_next()] must have returned [SQLITE_ROW]. If this
|
|
** is not the case, this function returns [SQLITE_MISUSE].
|
|
**
|
|
** Arguments pOp, pnCol and pzTab may not be NULL. Upon return, three
|
|
** outputs are set through these pointers:
|
|
**
|
|
** *pOp is set to one of [SQLITE_INSERT], [SQLITE_DELETE] or [SQLITE_UPDATE],
|
|
** depending on the type of change that the iterator currently points to;
|
|
**
|
|
** *pnCol is set to the number of columns in the table affected by the change; and
|
|
**
|
|
** *pzTab is set to point to a nul-terminated utf-8 encoded string containing
|
|
** the name of the table affected by the current change. The buffer remains
|
|
** valid until either sqlite3changeset_next() is called on the iterator
|
|
** or until the conflict-handler function returns.
|
|
**
|
|
** If pbIndirect is not NULL, then *pbIndirect is set to true (1) if the change
|
|
** is an indirect change, or false (0) otherwise. See the documentation for
|
|
** [sqlite3session_indirect()] for a description of direct and indirect
|
|
** changes.
|
|
**
|
|
** If no error occurs, SQLITE_OK is returned. If an error does occur, an
|
|
** SQLite error code is returned. The values of the output variables may not
|
|
** be trusted in this case.
|
|
*/
|
|
SQLITE_API int sqlite3changeset_op(
|
|
sqlite3_changeset_iter *pIter, /* Iterator object */
|
|
const char **pzTab, /* OUT: Pointer to table name */
|
|
int *pnCol, /* OUT: Number of columns in table */
|
|
int *pOp, /* OUT: SQLITE_INSERT, DELETE or UPDATE */
|
|
int *pbIndirect /* OUT: True for an 'indirect' change */
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Obtain The Primary Key Definition Of A Table
|
|
** METHOD: sqlite3_changeset_iter
|
|
**
|
|
** For each modified table, a changeset includes the following:
|
|
**
|
|
** <ul>
|
|
** <li> The number of columns in the table, and
|
|
** <li> Which of those columns make up the tables PRIMARY KEY.
|
|
** </ul>
|
|
**
|
|
** This function is used to find which columns comprise the PRIMARY KEY of
|
|
** the table modified by the change that iterator pIter currently points to.
|
|
** If successful, *pabPK is set to point to an array of nCol entries, where
|
|
** nCol is the number of columns in the table. Elements of *pabPK are set to
|
|
** 0x01 if the corresponding column is part of the tables primary key, or
|
|
** 0x00 if it is not.
|
|
**
|
|
** If argument pnCol is not NULL, then *pnCol is set to the number of columns
|
|
** in the table.
|
|
**
|
|
** If this function is called when the iterator does not point to a valid
|
|
** entry, SQLITE_MISUSE is returned and the output variables zeroed. Otherwise,
|
|
** SQLITE_OK is returned and the output variables populated as described
|
|
** above.
|
|
*/
|
|
SQLITE_API int sqlite3changeset_pk(
|
|
sqlite3_changeset_iter *pIter, /* Iterator object */
|
|
unsigned char **pabPK, /* OUT: Array of boolean - true for PK cols */
|
|
int *pnCol /* OUT: Number of entries in output array */
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Obtain old.* Values From A Changeset Iterator
|
|
** METHOD: sqlite3_changeset_iter
|
|
**
|
|
** The pIter argument passed to this function may either be an iterator
|
|
** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator
|
|
** created by [sqlite3changeset_start()]. In the latter case, the most recent
|
|
** call to [sqlite3changeset_next()] must have returned SQLITE_ROW.
|
|
** Furthermore, it may only be called if the type of change that the iterator
|
|
** currently points to is either [SQLITE_DELETE] or [SQLITE_UPDATE]. Otherwise,
|
|
** this function returns [SQLITE_MISUSE] and sets *ppValue to NULL.
|
|
**
|
|
** Argument iVal must be greater than or equal to 0, and less than the number
|
|
** of columns in the table affected by the current change. Otherwise,
|
|
** [SQLITE_RANGE] is returned and *ppValue is set to NULL.
|
|
**
|
|
** If successful, this function sets *ppValue to point to a protected
|
|
** sqlite3_value object containing the iVal'th value from the vector of
|
|
** original row values stored as part of the UPDATE or DELETE change and
|
|
** returns SQLITE_OK. The name of the function comes from the fact that this
|
|
** is similar to the "old.*" columns available to update or delete triggers.
|
|
**
|
|
** If some other error occurs (e.g. an OOM condition), an SQLite error code
|
|
** is returned and *ppValue is set to NULL.
|
|
*/
|
|
SQLITE_API int sqlite3changeset_old(
|
|
sqlite3_changeset_iter *pIter, /* Changeset iterator */
|
|
int iVal, /* Column number */
|
|
sqlite3_value **ppValue /* OUT: Old value (or NULL pointer) */
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Obtain new.* Values From A Changeset Iterator
|
|
** METHOD: sqlite3_changeset_iter
|
|
**
|
|
** The pIter argument passed to this function may either be an iterator
|
|
** passed to a conflict-handler by [sqlite3changeset_apply()], or an iterator
|
|
** created by [sqlite3changeset_start()]. In the latter case, the most recent
|
|
** call to [sqlite3changeset_next()] must have returned SQLITE_ROW.
|
|
** Furthermore, it may only be called if the type of change that the iterator
|
|
** currently points to is either [SQLITE_UPDATE] or [SQLITE_INSERT]. Otherwise,
|
|
** this function returns [SQLITE_MISUSE] and sets *ppValue to NULL.
|
|
**
|
|
** Argument iVal must be greater than or equal to 0, and less than the number
|
|
** of columns in the table affected by the current change. Otherwise,
|
|
** [SQLITE_RANGE] is returned and *ppValue is set to NULL.
|
|
**
|
|
** If successful, this function sets *ppValue to point to a protected
|
|
** sqlite3_value object containing the iVal'th value from the vector of
|
|
** new row values stored as part of the UPDATE or INSERT change and
|
|
** returns SQLITE_OK. If the change is an UPDATE and does not include
|
|
** a new value for the requested column, *ppValue is set to NULL and
|
|
** SQLITE_OK returned. The name of the function comes from the fact that
|
|
** this is similar to the "new.*" columns available to update or delete
|
|
** triggers.
|
|
**
|
|
** If some other error occurs (e.g. an OOM condition), an SQLite error code
|
|
** is returned and *ppValue is set to NULL.
|
|
*/
|
|
SQLITE_API int sqlite3changeset_new(
|
|
sqlite3_changeset_iter *pIter, /* Changeset iterator */
|
|
int iVal, /* Column number */
|
|
sqlite3_value **ppValue /* OUT: New value (or NULL pointer) */
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Obtain Conflicting Row Values From A Changeset Iterator
|
|
** METHOD: sqlite3_changeset_iter
|
|
**
|
|
** This function should only be used with iterator objects passed to a
|
|
** conflict-handler callback by [sqlite3changeset_apply()] with either
|
|
** [SQLITE_CHANGESET_DATA] or [SQLITE_CHANGESET_CONFLICT]. If this function
|
|
** is called on any other iterator, [SQLITE_MISUSE] is returned and *ppValue
|
|
** is set to NULL.
|
|
**
|
|
** Argument iVal must be greater than or equal to 0, and less than the number
|
|
** of columns in the table affected by the current change. Otherwise,
|
|
** [SQLITE_RANGE] is returned and *ppValue is set to NULL.
|
|
**
|
|
** If successful, this function sets *ppValue to point to a protected
|
|
** sqlite3_value object containing the iVal'th value from the
|
|
** "conflicting row" associated with the current conflict-handler callback
|
|
** and returns SQLITE_OK.
|
|
**
|
|
** If some other error occurs (e.g. an OOM condition), an SQLite error code
|
|
** is returned and *ppValue is set to NULL.
|
|
*/
|
|
SQLITE_API int sqlite3changeset_conflict(
|
|
sqlite3_changeset_iter *pIter, /* Changeset iterator */
|
|
int iVal, /* Column number */
|
|
sqlite3_value **ppValue /* OUT: Value from conflicting row */
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Determine The Number Of Foreign Key Constraint Violations
|
|
** METHOD: sqlite3_changeset_iter
|
|
**
|
|
** This function may only be called with an iterator passed to an
|
|
** SQLITE_CHANGESET_FOREIGN_KEY conflict handler callback. In this case
|
|
** it sets the output variable to the total number of known foreign key
|
|
** violations in the destination database and returns SQLITE_OK.
|
|
**
|
|
** In all other cases this function returns SQLITE_MISUSE.
|
|
*/
|
|
SQLITE_API int sqlite3changeset_fk_conflicts(
|
|
sqlite3_changeset_iter *pIter, /* Changeset iterator */
|
|
int *pnOut /* OUT: Number of FK violations */
|
|
);
|
|
|
|
|
|
/*
|
|
** CAPI3REF: Finalize A Changeset Iterator
|
|
** METHOD: sqlite3_changeset_iter
|
|
**
|
|
** This function is used to finalize an iterator allocated with
|
|
** [sqlite3changeset_start()].
|
|
**
|
|
** This function should only be called on iterators created using the
|
|
** [sqlite3changeset_start()] function. If an application calls this
|
|
** function with an iterator passed to a conflict-handler by
|
|
** [sqlite3changeset_apply()], [SQLITE_MISUSE] is immediately returned and the
|
|
** call has no effect.
|
|
**
|
|
** If an error was encountered within a call to an sqlite3changeset_xxx()
|
|
** function (for example an [SQLITE_CORRUPT] in [sqlite3changeset_next()] or an
|
|
** [SQLITE_NOMEM] in [sqlite3changeset_new()]) then an error code corresponding
|
|
** to that error is returned by this function. Otherwise, SQLITE_OK is
|
|
** returned. This is to allow the following pattern (pseudo-code):
|
|
**
|
|
** <pre>
|
|
** sqlite3changeset_start();
|
|
** while( SQLITE_ROW==sqlite3changeset_next() ){
|
|
** // Do something with change.
|
|
** }
|
|
** rc = sqlite3changeset_finalize();
|
|
** if( rc!=SQLITE_OK ){
|
|
** // An error has occurred
|
|
** }
|
|
** </pre>
|
|
*/
|
|
SQLITE_API int sqlite3changeset_finalize(sqlite3_changeset_iter *pIter);
|
|
|
|
/*
|
|
** CAPI3REF: Invert A Changeset
|
|
**
|
|
** This function is used to "invert" a changeset object. Applying an inverted
|
|
** changeset to a database reverses the effects of applying the uninverted
|
|
** changeset. Specifically:
|
|
**
|
|
** <ul>
|
|
** <li> Each DELETE change is changed to an INSERT, and
|
|
** <li> Each INSERT change is changed to a DELETE, and
|
|
** <li> For each UPDATE change, the old.* and new.* values are exchanged.
|
|
** </ul>
|
|
**
|
|
** This function does not change the order in which changes appear within
|
|
** the changeset. It merely reverses the sense of each individual change.
|
|
**
|
|
** If successful, a pointer to a buffer containing the inverted changeset
|
|
** is stored in *ppOut, the size of the same buffer is stored in *pnOut, and
|
|
** SQLITE_OK is returned. If an error occurs, both *pnOut and *ppOut are
|
|
** zeroed and an SQLite error code returned.
|
|
**
|
|
** It is the responsibility of the caller to eventually call sqlite3_free()
|
|
** on the *ppOut pointer to free the buffer allocation following a successful
|
|
** call to this function.
|
|
**
|
|
** WARNING/TODO: This function currently assumes that the input is a valid
|
|
** changeset. If it is not, the results are undefined.
|
|
*/
|
|
SQLITE_API int sqlite3changeset_invert(
|
|
int nIn, const void *pIn, /* Input changeset */
|
|
int *pnOut, void **ppOut /* OUT: Inverse of input */
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Concatenate Two Changeset Objects
|
|
**
|
|
** This function is used to concatenate two changesets, A and B, into a
|
|
** single changeset. The result is a changeset equivalent to applying
|
|
** changeset A followed by changeset B.
|
|
**
|
|
** This function combines the two input changesets using an
|
|
** sqlite3_changegroup object. Calling it produces similar results as the
|
|
** following code fragment:
|
|
**
|
|
** <pre>
|
|
** sqlite3_changegroup *pGrp;
|
|
** rc = sqlite3_changegroup_new(&pGrp);
|
|
** if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nA, pA);
|
|
** if( rc==SQLITE_OK ) rc = sqlite3changegroup_add(pGrp, nB, pB);
|
|
** if( rc==SQLITE_OK ){
|
|
** rc = sqlite3changegroup_output(pGrp, pnOut, ppOut);
|
|
** }else{
|
|
** *ppOut = 0;
|
|
** *pnOut = 0;
|
|
** }
|
|
** </pre>
|
|
**
|
|
** Refer to the sqlite3_changegroup documentation below for details.
|
|
*/
|
|
SQLITE_API int sqlite3changeset_concat(
|
|
int nA, /* Number of bytes in buffer pA */
|
|
void *pA, /* Pointer to buffer containing changeset A */
|
|
int nB, /* Number of bytes in buffer pB */
|
|
void *pB, /* Pointer to buffer containing changeset B */
|
|
int *pnOut, /* OUT: Number of bytes in output changeset */
|
|
void **ppOut /* OUT: Buffer containing output changeset */
|
|
);
|
|
|
|
|
|
/*
|
|
** CAPI3REF: Upgrade the Schema of a Changeset/Patchset
|
|
*/
|
|
SQLITE_API int sqlite3changeset_upgrade(
|
|
sqlite3 *db,
|
|
const char *zDb,
|
|
int nIn, const void *pIn, /* Input changeset */
|
|
int *pnOut, void **ppOut /* OUT: Inverse of input */
|
|
);
|
|
|
|
|
|
|
|
/*
|
|
** CAPI3REF: Changegroup Handle
|
|
**
|
|
** A changegroup is an object used to combine two or more
|
|
** [changesets] or [patchsets]
|
|
*/
|
|
typedef struct sqlite3_changegroup sqlite3_changegroup;
|
|
|
|
/*
|
|
** CAPI3REF: Create A New Changegroup Object
|
|
** CONSTRUCTOR: sqlite3_changegroup
|
|
**
|
|
** An sqlite3_changegroup object is used to combine two or more changesets
|
|
** (or patchsets) into a single changeset (or patchset). A single changegroup
|
|
** object may combine changesets or patchsets, but not both. The output is
|
|
** always in the same format as the input.
|
|
**
|
|
** If successful, this function returns SQLITE_OK and populates (*pp) with
|
|
** a pointer to a new sqlite3_changegroup object before returning. The caller
|
|
** should eventually free the returned object using a call to
|
|
** sqlite3changegroup_delete(). If an error occurs, an SQLite error code
|
|
** (i.e. SQLITE_NOMEM) is returned and *pp is set to NULL.
|
|
**
|
|
** The usual usage pattern for an sqlite3_changegroup object is as follows:
|
|
**
|
|
** <ul>
|
|
** <li> It is created using a call to sqlite3changegroup_new().
|
|
**
|
|
** <li> Zero or more changesets (or patchsets) are added to the object
|
|
** by calling sqlite3changegroup_add().
|
|
**
|
|
** <li> The result of combining all input changesets together is obtained
|
|
** by the application via a call to sqlite3changegroup_output().
|
|
**
|
|
** <li> The object is deleted using a call to sqlite3changegroup_delete().
|
|
** </ul>
|
|
**
|
|
** Any number of calls to add() and output() may be made between the calls to
|
|
** new() and delete(), and in any order.
|
|
**
|
|
** As well as the regular sqlite3changegroup_add() and
|
|
** sqlite3changegroup_output() functions, also available are the streaming
|
|
** versions sqlite3changegroup_add_strm() and sqlite3changegroup_output_strm().
|
|
*/
|
|
SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp);
|
|
|
|
/*
|
|
** CAPI3REF: Add a Schema to a Changegroup
|
|
** METHOD: sqlite3_changegroup_schema
|
|
**
|
|
** This method may be used to optionally enforce the rule that the changesets
|
|
** added to the changegroup handle must match the schema of database zDb
|
|
** ("main", "temp", or the name of an attached database). If
|
|
** sqlite3changegroup_add() is called to add a changeset that is not compatible
|
|
** with the configured schema, SQLITE_SCHEMA is returned and the changegroup
|
|
** object is left in an undefined state.
|
|
**
|
|
** A changeset schema is considered compatible with the database schema in
|
|
** the same way as for sqlite3changeset_apply(). Specifically, for each
|
|
** table in the changeset, there exists a database table with:
|
|
**
|
|
** <ul>
|
|
** <li> The name identified by the changeset, and
|
|
** <li> at least as many columns as recorded in the changeset, and
|
|
** <li> the primary key columns in the same position as recorded in
|
|
** the changeset.
|
|
** </ul>
|
|
**
|
|
** The output of the changegroup object always has the same schema as the
|
|
** database nominated using this function. In cases where changesets passed
|
|
** to sqlite3changegroup_add() have fewer columns than the corresponding table
|
|
** in the database schema, these are filled in using the default column
|
|
** values from the database schema. This makes it possible to combined
|
|
** changesets that have different numbers of columns for a single table
|
|
** within a changegroup, provided that they are otherwise compatible.
|
|
*/
|
|
SQLITE_API int sqlite3changegroup_schema(sqlite3_changegroup*, sqlite3*, const char *zDb);
|
|
|
|
/*
|
|
** CAPI3REF: Add A Changeset To A Changegroup
|
|
** METHOD: sqlite3_changegroup
|
|
**
|
|
** Add all changes within the changeset (or patchset) in buffer pData (size
|
|
** nData bytes) to the changegroup.
|
|
**
|
|
** If the buffer contains a patchset, then all prior calls to this function
|
|
** on the same changegroup object must also have specified patchsets. Or, if
|
|
** the buffer contains a changeset, so must have the earlier calls to this
|
|
** function. Otherwise, SQLITE_ERROR is returned and no changes are added
|
|
** to the changegroup.
|
|
**
|
|
** Rows within the changeset and changegroup are identified by the values in
|
|
** their PRIMARY KEY columns. A change in the changeset is considered to
|
|
** apply to the same row as a change already present in the changegroup if
|
|
** the two rows have the same primary key.
|
|
**
|
|
** Changes to rows that do not already appear in the changegroup are
|
|
** simply copied into it. Or, if both the new changeset and the changegroup
|
|
** contain changes that apply to a single row, the final contents of the
|
|
** changegroup depends on the type of each change, as follows:
|
|
**
|
|
** <table border=1 style="margin-left:8ex;margin-right:8ex">
|
|
** <tr><th style="white-space:pre">Existing Change </th>
|
|
** <th style="white-space:pre">New Change </th>
|
|
** <th>Output Change
|
|
** <tr><td>INSERT <td>INSERT <td>
|
|
** The new change is ignored. This case does not occur if the new
|
|
** changeset was recorded immediately after the changesets already
|
|
** added to the changegroup.
|
|
** <tr><td>INSERT <td>UPDATE <td>
|
|
** The INSERT change remains in the changegroup. The values in the
|
|
** INSERT change are modified as if the row was inserted by the
|
|
** existing change and then updated according to the new change.
|
|
** <tr><td>INSERT <td>DELETE <td>
|
|
** The existing INSERT is removed from the changegroup. The DELETE is
|
|
** not added.
|
|
** <tr><td>UPDATE <td>INSERT <td>
|
|
** The new change is ignored. This case does not occur if the new
|
|
** changeset was recorded immediately after the changesets already
|
|
** added to the changegroup.
|
|
** <tr><td>UPDATE <td>UPDATE <td>
|
|
** The existing UPDATE remains within the changegroup. It is amended
|
|
** so that the accompanying values are as if the row was updated once
|
|
** by the existing change and then again by the new change.
|
|
** <tr><td>UPDATE <td>DELETE <td>
|
|
** The existing UPDATE is replaced by the new DELETE within the
|
|
** changegroup.
|
|
** <tr><td>DELETE <td>INSERT <td>
|
|
** If one or more of the column values in the row inserted by the
|
|
** new change differ from those in the row deleted by the existing
|
|
** change, the existing DELETE is replaced by an UPDATE within the
|
|
** changegroup. Otherwise, if the inserted row is exactly the same
|
|
** as the deleted row, the existing DELETE is simply discarded.
|
|
** <tr><td>DELETE <td>UPDATE <td>
|
|
** The new change is ignored. This case does not occur if the new
|
|
** changeset was recorded immediately after the changesets already
|
|
** added to the changegroup.
|
|
** <tr><td>DELETE <td>DELETE <td>
|
|
** The new change is ignored. This case does not occur if the new
|
|
** changeset was recorded immediately after the changesets already
|
|
** added to the changegroup.
|
|
** </table>
|
|
**
|
|
** If the new changeset contains changes to a table that is already present
|
|
** in the changegroup, then the number of columns and the position of the
|
|
** primary key columns for the table must be consistent. If this is not the
|
|
** case, this function fails with SQLITE_SCHEMA. Except, if the changegroup
|
|
** object has been configured with a database schema using the
|
|
** sqlite3changegroup_schema() API, then it is possible to combine changesets
|
|
** with different numbers of columns for a single table, provided that
|
|
** they are otherwise compatible.
|
|
**
|
|
** If the input changeset appears to be corrupt and the corruption is
|
|
** detected, SQLITE_CORRUPT is returned. Or, if an out-of-memory condition
|
|
** occurs during processing, this function returns SQLITE_NOMEM.
|
|
**
|
|
** In all cases, if an error occurs the state of the final contents of the
|
|
** changegroup is undefined. If no error occurs, SQLITE_OK is returned.
|
|
*/
|
|
SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData);
|
|
|
|
/*
|
|
** CAPI3REF: Obtain A Composite Changeset From A Changegroup
|
|
** METHOD: sqlite3_changegroup
|
|
**
|
|
** Obtain a buffer containing a changeset (or patchset) representing the
|
|
** current contents of the changegroup. If the inputs to the changegroup
|
|
** were themselves changesets, the output is a changeset. Or, if the
|
|
** inputs were patchsets, the output is also a patchset.
|
|
**
|
|
** As with the output of the sqlite3session_changeset() and
|
|
** sqlite3session_patchset() functions, all changes related to a single
|
|
** table are grouped together in the output of this function. Tables appear
|
|
** in the same order as for the very first changeset added to the changegroup.
|
|
** If the second or subsequent changesets added to the changegroup contain
|
|
** changes for tables that do not appear in the first changeset, they are
|
|
** appended onto the end of the output changeset, again in the order in
|
|
** which they are first encountered.
|
|
**
|
|
** If an error occurs, an SQLite error code is returned and the output
|
|
** variables (*pnData) and (*ppData) are set to 0. Otherwise, SQLITE_OK
|
|
** is returned and the output variables are set to the size of and a
|
|
** pointer to the output buffer, respectively. In this case it is the
|
|
** responsibility of the caller to eventually free the buffer using a
|
|
** call to sqlite3_free().
|
|
*/
|
|
SQLITE_API int sqlite3changegroup_output(
|
|
sqlite3_changegroup*,
|
|
int *pnData, /* OUT: Size of output buffer in bytes */
|
|
void **ppData /* OUT: Pointer to output buffer */
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Delete A Changegroup Object
|
|
** DESTRUCTOR: sqlite3_changegroup
|
|
*/
|
|
SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*);
|
|
|
|
/*
|
|
** CAPI3REF: Apply A Changeset To A Database
|
|
**
|
|
** Apply a changeset or patchset to a database. These functions attempt to
|
|
** update the "main" database attached to handle db with the changes found in
|
|
** the changeset passed via the second and third arguments.
|
|
**
|
|
** The fourth argument (xFilter) passed to these functions is the "filter
|
|
** callback". If it is not NULL, then for each table affected by at least one
|
|
** change in the changeset, the filter callback is invoked with
|
|
** the table name as the second argument, and a copy of the context pointer
|
|
** passed as the sixth argument as the first. If the "filter callback"
|
|
** returns zero, then no attempt is made to apply any changes to the table.
|
|
** Otherwise, if the return value is non-zero or the xFilter argument to
|
|
** is NULL, all changes related to the table are attempted.
|
|
**
|
|
** For each table that is not excluded by the filter callback, this function
|
|
** tests that the target database contains a compatible table. A table is
|
|
** considered compatible if all of the following are true:
|
|
**
|
|
** <ul>
|
|
** <li> The table has the same name as the name recorded in the
|
|
** changeset, and
|
|
** <li> The table has at least as many columns as recorded in the
|
|
** changeset, and
|
|
** <li> The table has primary key columns in the same position as
|
|
** recorded in the changeset.
|
|
** </ul>
|
|
**
|
|
** If there is no compatible table, it is not an error, but none of the
|
|
** changes associated with the table are applied. A warning message is issued
|
|
** via the sqlite3_log() mechanism with the error code SQLITE_SCHEMA. At most
|
|
** one such warning is issued for each table in the changeset.
|
|
**
|
|
** For each change for which there is a compatible table, an attempt is made
|
|
** to modify the table contents according to the UPDATE, INSERT or DELETE
|
|
** change. If a change cannot be applied cleanly, the conflict handler
|
|
** function passed as the fifth argument to sqlite3changeset_apply() may be
|
|
** invoked. A description of exactly when the conflict handler is invoked for
|
|
** each type of change is below.
|
|
**
|
|
** Unlike the xFilter argument, xConflict may not be passed NULL. The results
|
|
** of passing anything other than a valid function pointer as the xConflict
|
|
** argument are undefined.
|
|
**
|
|
** Each time the conflict handler function is invoked, it must return one
|
|
** of [SQLITE_CHANGESET_OMIT], [SQLITE_CHANGESET_ABORT] or
|
|
** [SQLITE_CHANGESET_REPLACE]. SQLITE_CHANGESET_REPLACE may only be returned
|
|
** if the second argument passed to the conflict handler is either
|
|
** SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT. If the conflict-handler
|
|
** returns an illegal value, any changes already made are rolled back and
|
|
** the call to sqlite3changeset_apply() returns SQLITE_MISUSE. Different
|
|
** actions are taken by sqlite3changeset_apply() depending on the value
|
|
** returned by each invocation of the conflict-handler function. Refer to
|
|
** the documentation for the three
|
|
** [SQLITE_CHANGESET_OMIT|available return values] for details.
|
|
**
|
|
** <dl>
|
|
** <dt>DELETE Changes<dd>
|
|
** For each DELETE change, the function checks if the target database
|
|
** contains a row with the same primary key value (or values) as the
|
|
** original row values stored in the changeset. If it does, and the values
|
|
** stored in all non-primary key columns also match the values stored in
|
|
** the changeset the row is deleted from the target database.
|
|
**
|
|
** If a row with matching primary key values is found, but one or more of
|
|
** the non-primary key fields contains a value different from the original
|
|
** row value stored in the changeset, the conflict-handler function is
|
|
** invoked with [SQLITE_CHANGESET_DATA] as the second argument. If the
|
|
** database table has more columns than are recorded in the changeset,
|
|
** only the values of those non-primary key fields are compared against
|
|
** the current database contents - any trailing database table columns
|
|
** are ignored.
|
|
**
|
|
** If no row with matching primary key values is found in the database,
|
|
** the conflict-handler function is invoked with [SQLITE_CHANGESET_NOTFOUND]
|
|
** passed as the second argument.
|
|
**
|
|
** If the DELETE operation is attempted, but SQLite returns SQLITE_CONSTRAINT
|
|
** (which can only happen if a foreign key constraint is violated), the
|
|
** conflict-handler function is invoked with [SQLITE_CHANGESET_CONSTRAINT]
|
|
** passed as the second argument. This includes the case where the DELETE
|
|
** operation is attempted because an earlier call to the conflict handler
|
|
** function returned [SQLITE_CHANGESET_REPLACE].
|
|
**
|
|
** <dt>INSERT Changes<dd>
|
|
** For each INSERT change, an attempt is made to insert the new row into
|
|
** the database. If the changeset row contains fewer fields than the
|
|
** database table, the trailing fields are populated with their default
|
|
** values.
|
|
**
|
|
** If the attempt to insert the row fails because the database already
|
|
** contains a row with the same primary key values, the conflict handler
|
|
** function is invoked with the second argument set to
|
|
** [SQLITE_CHANGESET_CONFLICT].
|
|
**
|
|
** If the attempt to insert the row fails because of some other constraint
|
|
** violation (e.g. NOT NULL or UNIQUE), the conflict handler function is
|
|
** invoked with the second argument set to [SQLITE_CHANGESET_CONSTRAINT].
|
|
** This includes the case where the INSERT operation is re-attempted because
|
|
** an earlier call to the conflict handler function returned
|
|
** [SQLITE_CHANGESET_REPLACE].
|
|
**
|
|
** <dt>UPDATE Changes<dd>
|
|
** For each UPDATE change, the function checks if the target database
|
|
** contains a row with the same primary key value (or values) as the
|
|
** original row values stored in the changeset. If it does, and the values
|
|
** stored in all modified non-primary key columns also match the values
|
|
** stored in the changeset the row is updated within the target database.
|
|
**
|
|
** If a row with matching primary key values is found, but one or more of
|
|
** the modified non-primary key fields contains a value different from an
|
|
** original row value stored in the changeset, the conflict-handler function
|
|
** is invoked with [SQLITE_CHANGESET_DATA] as the second argument. Since
|
|
** UPDATE changes only contain values for non-primary key fields that are
|
|
** to be modified, only those fields need to match the original values to
|
|
** avoid the SQLITE_CHANGESET_DATA conflict-handler callback.
|
|
**
|
|
** If no row with matching primary key values is found in the database,
|
|
** the conflict-handler function is invoked with [SQLITE_CHANGESET_NOTFOUND]
|
|
** passed as the second argument.
|
|
**
|
|
** If the UPDATE operation is attempted, but SQLite returns
|
|
** SQLITE_CONSTRAINT, the conflict-handler function is invoked with
|
|
** [SQLITE_CHANGESET_CONSTRAINT] passed as the second argument.
|
|
** This includes the case where the UPDATE operation is attempted after
|
|
** an earlier call to the conflict handler function returned
|
|
** [SQLITE_CHANGESET_REPLACE].
|
|
** </dl>
|
|
**
|
|
** It is safe to execute SQL statements, including those that write to the
|
|
** table that the callback related to, from within the xConflict callback.
|
|
** This can be used to further customize the application's conflict
|
|
** resolution strategy.
|
|
**
|
|
** All changes made by these functions are enclosed in a savepoint transaction.
|
|
** If any other error (aside from a constraint failure when attempting to
|
|
** write to the target database) occurs, then the savepoint transaction is
|
|
** rolled back, restoring the target database to its original state, and an
|
|
** SQLite error code returned.
|
|
**
|
|
** If the output parameters (ppRebase) and (pnRebase) are non-NULL and
|
|
** the input is a changeset (not a patchset), then sqlite3changeset_apply_v2()
|
|
** may set (*ppRebase) to point to a "rebase" that may be used with the
|
|
** sqlite3_rebaser APIs buffer before returning. In this case (*pnRebase)
|
|
** is set to the size of the buffer in bytes. It is the responsibility of the
|
|
** caller to eventually free any such buffer using sqlite3_free(). The buffer
|
|
** is only allocated and populated if one or more conflicts were encountered
|
|
** while applying the patchset. See comments surrounding the sqlite3_rebaser
|
|
** APIs for further details.
|
|
**
|
|
** The behavior of sqlite3changeset_apply_v2() and its streaming equivalent
|
|
** may be modified by passing a combination of
|
|
** [SQLITE_CHANGESETAPPLY_NOSAVEPOINT | supported flags] as the 9th parameter.
|
|
**
|
|
** Note that the sqlite3changeset_apply_v2() API is still <b>experimental</b>
|
|
** and therefore subject to change.
|
|
*/
|
|
SQLITE_API int sqlite3changeset_apply(
|
|
sqlite3 *db, /* Apply change to "main" db of this handle */
|
|
int nChangeset, /* Size of changeset in bytes */
|
|
void *pChangeset, /* Changeset blob */
|
|
int(*xFilter)(
|
|
void *pCtx, /* Copy of sixth arg to _apply() */
|
|
const char *zTab /* Table name */
|
|
),
|
|
int(*xConflict)(
|
|
void *pCtx, /* Copy of sixth arg to _apply() */
|
|
int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
|
|
sqlite3_changeset_iter *p /* Handle describing change and conflict */
|
|
),
|
|
void *pCtx /* First argument passed to xConflict */
|
|
);
|
|
SQLITE_API int sqlite3changeset_apply_v2(
|
|
sqlite3 *db, /* Apply change to "main" db of this handle */
|
|
int nChangeset, /* Size of changeset in bytes */
|
|
void *pChangeset, /* Changeset blob */
|
|
int(*xFilter)(
|
|
void *pCtx, /* Copy of sixth arg to _apply() */
|
|
const char *zTab /* Table name */
|
|
),
|
|
int(*xConflict)(
|
|
void *pCtx, /* Copy of sixth arg to _apply() */
|
|
int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
|
|
sqlite3_changeset_iter *p /* Handle describing change and conflict */
|
|
),
|
|
void *pCtx, /* First argument passed to xConflict */
|
|
void **ppRebase, int *pnRebase, /* OUT: Rebase data */
|
|
int flags /* SESSION_CHANGESETAPPLY_* flags */
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Flags for sqlite3changeset_apply_v2
|
|
**
|
|
** The following flags may passed via the 9th parameter to
|
|
** [sqlite3changeset_apply_v2] and [sqlite3changeset_apply_v2_strm]:
|
|
**
|
|
** <dl>
|
|
** <dt>SQLITE_CHANGESETAPPLY_NOSAVEPOINT <dd>
|
|
** Usually, the sessions module encloses all operations performed by
|
|
** a single call to apply_v2() or apply_v2_strm() in a [SAVEPOINT]. The
|
|
** SAVEPOINT is committed if the changeset or patchset is successfully
|
|
** applied, or rolled back if an error occurs. Specifying this flag
|
|
** causes the sessions module to omit this savepoint. In this case, if the
|
|
** caller has an open transaction or savepoint when apply_v2() is called,
|
|
** it may revert the partially applied changeset by rolling it back.
|
|
**
|
|
** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd>
|
|
** Invert the changeset before applying it. This is equivalent to inverting
|
|
** a changeset using sqlite3changeset_invert() before applying it. It is
|
|
** an error to specify this flag with a patchset.
|
|
**
|
|
** <dt>SQLITE_CHANGESETAPPLY_IGNORENOOP <dd>
|
|
** Do not invoke the conflict handler callback for any changes that
|
|
** would not actually modify the database even if they were applied.
|
|
** Specifically, this means that the conflict handler is not invoked
|
|
** for:
|
|
** <ul>
|
|
** <li>a delete change if the row being deleted cannot be found,
|
|
** <li>an update change if the modified fields are already set to
|
|
** their new values in the conflicting row, or
|
|
** <li>an insert change if all fields of the conflicting row match
|
|
** the row being inserted.
|
|
** </ul>
|
|
**
|
|
** <dt>SQLITE_CHANGESETAPPLY_FKNOACTION <dd>
|
|
** If this flag it set, then all foreign key constraints in the target
|
|
** database behave as if they were declared with "ON UPDATE NO ACTION ON
|
|
** DELETE NO ACTION", even if they are actually CASCADE, RESTRICT, SET NULL
|
|
** or SET DEFAULT.
|
|
*/
|
|
#define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001
|
|
#define SQLITE_CHANGESETAPPLY_INVERT 0x0002
|
|
#define SQLITE_CHANGESETAPPLY_IGNORENOOP 0x0004
|
|
#define SQLITE_CHANGESETAPPLY_FKNOACTION 0x0008
|
|
|
|
/*
|
|
** CAPI3REF: Constants Passed To The Conflict Handler
|
|
**
|
|
** Values that may be passed as the second argument to a conflict-handler.
|
|
**
|
|
** <dl>
|
|
** <dt>SQLITE_CHANGESET_DATA<dd>
|
|
** The conflict handler is invoked with CHANGESET_DATA as the second argument
|
|
** when processing a DELETE or UPDATE change if a row with the required
|
|
** PRIMARY KEY fields is present in the database, but one or more other
|
|
** (non primary-key) fields modified by the update do not contain the
|
|
** expected "before" values.
|
|
**
|
|
** The conflicting row, in this case, is the database row with the matching
|
|
** primary key.
|
|
**
|
|
** <dt>SQLITE_CHANGESET_NOTFOUND<dd>
|
|
** The conflict handler is invoked with CHANGESET_NOTFOUND as the second
|
|
** argument when processing a DELETE or UPDATE change if a row with the
|
|
** required PRIMARY KEY fields is not present in the database.
|
|
**
|
|
** There is no conflicting row in this case. The results of invoking the
|
|
** sqlite3changeset_conflict() API are undefined.
|
|
**
|
|
** <dt>SQLITE_CHANGESET_CONFLICT<dd>
|
|
** CHANGESET_CONFLICT is passed as the second argument to the conflict
|
|
** handler while processing an INSERT change if the operation would result
|
|
** in duplicate primary key values.
|
|
**
|
|
** The conflicting row in this case is the database row with the matching
|
|
** primary key.
|
|
**
|
|
** <dt>SQLITE_CHANGESET_FOREIGN_KEY<dd>
|
|
** If foreign key handling is enabled, and applying a changeset leaves the
|
|
** database in a state containing foreign key violations, the conflict
|
|
** handler is invoked with CHANGESET_FOREIGN_KEY as the second argument
|
|
** exactly once before the changeset is committed. If the conflict handler
|
|
** returns CHANGESET_OMIT, the changes, including those that caused the
|
|
** foreign key constraint violation, are committed. Or, if it returns
|
|
** CHANGESET_ABORT, the changeset is rolled back.
|
|
**
|
|
** No current or conflicting row information is provided. The only function
|
|
** it is possible to call on the supplied sqlite3_changeset_iter handle
|
|
** is sqlite3changeset_fk_conflicts().
|
|
**
|
|
** <dt>SQLITE_CHANGESET_CONSTRAINT<dd>
|
|
** If any other constraint violation occurs while applying a change (i.e.
|
|
** a UNIQUE, CHECK or NOT NULL constraint), the conflict handler is
|
|
** invoked with CHANGESET_CONSTRAINT as the second argument.
|
|
**
|
|
** There is no conflicting row in this case. The results of invoking the
|
|
** sqlite3changeset_conflict() API are undefined.
|
|
**
|
|
** </dl>
|
|
*/
|
|
#define SQLITE_CHANGESET_DATA 1
|
|
#define SQLITE_CHANGESET_NOTFOUND 2
|
|
#define SQLITE_CHANGESET_CONFLICT 3
|
|
#define SQLITE_CHANGESET_CONSTRAINT 4
|
|
#define SQLITE_CHANGESET_FOREIGN_KEY 5
|
|
|
|
/*
|
|
** CAPI3REF: Constants Returned By The Conflict Handler
|
|
**
|
|
** A conflict handler callback must return one of the following three values.
|
|
**
|
|
** <dl>
|
|
** <dt>SQLITE_CHANGESET_OMIT<dd>
|
|
** If a conflict handler returns this value no special action is taken. The
|
|
** change that caused the conflict is not applied. The session module
|
|
** continues to the next change in the changeset.
|
|
**
|
|
** <dt>SQLITE_CHANGESET_REPLACE<dd>
|
|
** This value may only be returned if the second argument to the conflict
|
|
** handler was SQLITE_CHANGESET_DATA or SQLITE_CHANGESET_CONFLICT. If this
|
|
** is not the case, any changes applied so far are rolled back and the
|
|
** call to sqlite3changeset_apply() returns SQLITE_MISUSE.
|
|
**
|
|
** If CHANGESET_REPLACE is returned by an SQLITE_CHANGESET_DATA conflict
|
|
** handler, then the conflicting row is either updated or deleted, depending
|
|
** on the type of change.
|
|
**
|
|
** If CHANGESET_REPLACE is returned by an SQLITE_CHANGESET_CONFLICT conflict
|
|
** handler, then the conflicting row is removed from the database and a
|
|
** second attempt to apply the change is made. If this second attempt fails,
|
|
** the original row is restored to the database before continuing.
|
|
**
|
|
** <dt>SQLITE_CHANGESET_ABORT<dd>
|
|
** If this value is returned, any changes applied so far are rolled back
|
|
** and the call to sqlite3changeset_apply() returns SQLITE_ABORT.
|
|
** </dl>
|
|
*/
|
|
#define SQLITE_CHANGESET_OMIT 0
|
|
#define SQLITE_CHANGESET_REPLACE 1
|
|
#define SQLITE_CHANGESET_ABORT 2
|
|
|
|
/*
|
|
** CAPI3REF: Rebasing changesets
|
|
** EXPERIMENTAL
|
|
**
|
|
** Suppose there is a site hosting a database in state S0. And that
|
|
** modifications are made that move that database to state S1 and a
|
|
** changeset recorded (the "local" changeset). Then, a changeset based
|
|
** on S0 is received from another site (the "remote" changeset) and
|
|
** applied to the database. The database is then in state
|
|
** (S1+"remote"), where the exact state depends on any conflict
|
|
** resolution decisions (OMIT or REPLACE) made while applying "remote".
|
|
** Rebasing a changeset is to update it to take those conflict
|
|
** resolution decisions into account, so that the same conflicts
|
|
** do not have to be resolved elsewhere in the network.
|
|
**
|
|
** For example, if both the local and remote changesets contain an
|
|
** INSERT of the same key on "CREATE TABLE t1(a PRIMARY KEY, b)":
|
|
**
|
|
** local: INSERT INTO t1 VALUES(1, 'v1');
|
|
** remote: INSERT INTO t1 VALUES(1, 'v2');
|
|
**
|
|
** and the conflict resolution is REPLACE, then the INSERT change is
|
|
** removed from the local changeset (it was overridden). Or, if the
|
|
** conflict resolution was "OMIT", then the local changeset is modified
|
|
** to instead contain:
|
|
**
|
|
** UPDATE t1 SET b = 'v2' WHERE a=1;
|
|
**
|
|
** Changes within the local changeset are rebased as follows:
|
|
**
|
|
** <dl>
|
|
** <dt>Local INSERT<dd>
|
|
** This may only conflict with a remote INSERT. If the conflict
|
|
** resolution was OMIT, then add an UPDATE change to the rebased
|
|
** changeset. Or, if the conflict resolution was REPLACE, add
|
|
** nothing to the rebased changeset.
|
|
**
|
|
** <dt>Local DELETE<dd>
|
|
** This may conflict with a remote UPDATE or DELETE. In both cases the
|
|
** only possible resolution is OMIT. If the remote operation was a
|
|
** DELETE, then add no change to the rebased changeset. If the remote
|
|
** operation was an UPDATE, then the old.* fields of change are updated
|
|
** to reflect the new.* values in the UPDATE.
|
|
**
|
|
** <dt>Local UPDATE<dd>
|
|
** This may conflict with a remote UPDATE or DELETE. If it conflicts
|
|
** with a DELETE, and the conflict resolution was OMIT, then the update
|
|
** is changed into an INSERT. Any undefined values in the new.* record
|
|
** from the update change are filled in using the old.* values from
|
|
** the conflicting DELETE. Or, if the conflict resolution was REPLACE,
|
|
** the UPDATE change is simply omitted from the rebased changeset.
|
|
**
|
|
** If conflict is with a remote UPDATE and the resolution is OMIT, then
|
|
** the old.* values are rebased using the new.* values in the remote
|
|
** change. Or, if the resolution is REPLACE, then the change is copied
|
|
** into the rebased changeset with updates to columns also updated by
|
|
** the conflicting remote UPDATE removed. If this means no columns would
|
|
** be updated, the change is omitted.
|
|
** </dl>
|
|
**
|
|
** A local change may be rebased against multiple remote changes
|
|
** simultaneously. If a single key is modified by multiple remote
|
|
** changesets, they are combined as follows before the local changeset
|
|
** is rebased:
|
|
**
|
|
** <ul>
|
|
** <li> If there has been one or more REPLACE resolutions on a
|
|
** key, it is rebased according to a REPLACE.
|
|
**
|
|
** <li> If there have been no REPLACE resolutions on a key, then
|
|
** the local changeset is rebased according to the most recent
|
|
** of the OMIT resolutions.
|
|
** </ul>
|
|
**
|
|
** Note that conflict resolutions from multiple remote changesets are
|
|
** combined on a per-field basis, not per-row. This means that in the
|
|
** case of multiple remote UPDATE operations, some fields of a single
|
|
** local change may be rebased for REPLACE while others are rebased for
|
|
** OMIT.
|
|
**
|
|
** In order to rebase a local changeset, the remote changeset must first
|
|
** be applied to the local database using sqlite3changeset_apply_v2() and
|
|
** the buffer of rebase information captured. Then:
|
|
**
|
|
** <ol>
|
|
** <li> An sqlite3_rebaser object is created by calling
|
|
** sqlite3rebaser_create().
|
|
** <li> The new object is configured with the rebase buffer obtained from
|
|
** sqlite3changeset_apply_v2() by calling sqlite3rebaser_configure().
|
|
** If the local changeset is to be rebased against multiple remote
|
|
** changesets, then sqlite3rebaser_configure() should be called
|
|
** multiple times, in the same order that the multiple
|
|
** sqlite3changeset_apply_v2() calls were made.
|
|
** <li> Each local changeset is rebased by calling sqlite3rebaser_rebase().
|
|
** <li> The sqlite3_rebaser object is deleted by calling
|
|
** sqlite3rebaser_delete().
|
|
** </ol>
|
|
*/
|
|
typedef struct sqlite3_rebaser sqlite3_rebaser;
|
|
|
|
/*
|
|
** CAPI3REF: Create a changeset rebaser object.
|
|
** EXPERIMENTAL
|
|
**
|
|
** Allocate a new changeset rebaser object. If successful, set (*ppNew) to
|
|
** point to the new object and return SQLITE_OK. Otherwise, if an error
|
|
** occurs, return an SQLite error code (e.g. SQLITE_NOMEM) and set (*ppNew)
|
|
** to NULL.
|
|
*/
|
|
SQLITE_API int sqlite3rebaser_create(sqlite3_rebaser **ppNew);
|
|
|
|
/*
|
|
** CAPI3REF: Configure a changeset rebaser object.
|
|
** EXPERIMENTAL
|
|
**
|
|
** Configure the changeset rebaser object to rebase changesets according
|
|
** to the conflict resolutions described by buffer pRebase (size nRebase
|
|
** bytes), which must have been obtained from a previous call to
|
|
** sqlite3changeset_apply_v2().
|
|
*/
|
|
SQLITE_API int sqlite3rebaser_configure(
|
|
sqlite3_rebaser*,
|
|
int nRebase, const void *pRebase
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Rebase a changeset
|
|
** EXPERIMENTAL
|
|
**
|
|
** Argument pIn must point to a buffer containing a changeset nIn bytes
|
|
** in size. This function allocates and populates a buffer with a copy
|
|
** of the changeset rebased according to the configuration of the
|
|
** rebaser object passed as the first argument. If successful, (*ppOut)
|
|
** is set to point to the new buffer containing the rebased changeset and
|
|
** (*pnOut) to its size in bytes and SQLITE_OK returned. It is the
|
|
** responsibility of the caller to eventually free the new buffer using
|
|
** sqlite3_free(). Otherwise, if an error occurs, (*ppOut) and (*pnOut)
|
|
** are set to zero and an SQLite error code returned.
|
|
*/
|
|
SQLITE_API int sqlite3rebaser_rebase(
|
|
sqlite3_rebaser*,
|
|
int nIn, const void *pIn,
|
|
int *pnOut, void **ppOut
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Delete a changeset rebaser object.
|
|
** EXPERIMENTAL
|
|
**
|
|
** Delete the changeset rebaser object and all associated resources. There
|
|
** should be one call to this function for each successful invocation
|
|
** of sqlite3rebaser_create().
|
|
*/
|
|
SQLITE_API void sqlite3rebaser_delete(sqlite3_rebaser *p);
|
|
|
|
/*
|
|
** CAPI3REF: Streaming Versions of API functions.
|
|
**
|
|
** The six streaming API xxx_strm() functions serve similar purposes to the
|
|
** corresponding non-streaming API functions:
|
|
**
|
|
** <table border=1 style="margin-left:8ex;margin-right:8ex">
|
|
** <tr><th>Streaming function<th>Non-streaming equivalent</th>
|
|
** <tr><td>sqlite3changeset_apply_strm<td>[sqlite3changeset_apply]
|
|
** <tr><td>sqlite3changeset_apply_strm_v2<td>[sqlite3changeset_apply_v2]
|
|
** <tr><td>sqlite3changeset_concat_strm<td>[sqlite3changeset_concat]
|
|
** <tr><td>sqlite3changeset_invert_strm<td>[sqlite3changeset_invert]
|
|
** <tr><td>sqlite3changeset_start_strm<td>[sqlite3changeset_start]
|
|
** <tr><td>sqlite3session_changeset_strm<td>[sqlite3session_changeset]
|
|
** <tr><td>sqlite3session_patchset_strm<td>[sqlite3session_patchset]
|
|
** </table>
|
|
**
|
|
** Non-streaming functions that accept changesets (or patchsets) as input
|
|
** require that the entire changeset be stored in a single buffer in memory.
|
|
** Similarly, those that return a changeset or patchset do so by returning
|
|
** a pointer to a single large buffer allocated using sqlite3_malloc().
|
|
** Normally this is convenient. However, if an application running in a
|
|
** low-memory environment is required to handle very large changesets, the
|
|
** large contiguous memory allocations required can become onerous.
|
|
**
|
|
** In order to avoid this problem, instead of a single large buffer, input
|
|
** is passed to a streaming API functions by way of a callback function that
|
|
** the sessions module invokes to incrementally request input data as it is
|
|
** required. In all cases, a pair of API function parameters such as
|
|
**
|
|
** <pre>
|
|
** int nChangeset,
|
|
** void *pChangeset,
|
|
** </pre>
|
|
**
|
|
** Is replaced by:
|
|
**
|
|
** <pre>
|
|
** int (*xInput)(void *pIn, void *pData, int *pnData),
|
|
** void *pIn,
|
|
** </pre>
|
|
**
|
|
** Each time the xInput callback is invoked by the sessions module, the first
|
|
** argument passed is a copy of the supplied pIn context pointer. The second
|
|
** argument, pData, points to a buffer (*pnData) bytes in size. Assuming no
|
|
** error occurs the xInput method should copy up to (*pnData) bytes of data
|
|
** into the buffer and set (*pnData) to the actual number of bytes copied
|
|
** before returning SQLITE_OK. If the input is completely exhausted, (*pnData)
|
|
** should be set to zero to indicate this. Or, if an error occurs, an SQLite
|
|
** error code should be returned. In all cases, if an xInput callback returns
|
|
** an error, all processing is abandoned and the streaming API function
|
|
** returns a copy of the error code to the caller.
|
|
**
|
|
** In the case of sqlite3changeset_start_strm(), the xInput callback may be
|
|
** invoked by the sessions module at any point during the lifetime of the
|
|
** iterator. If such an xInput callback returns an error, the iterator enters
|
|
** an error state, whereby all subsequent calls to iterator functions
|
|
** immediately fail with the same error code as returned by xInput.
|
|
**
|
|
** Similarly, streaming API functions that return changesets (or patchsets)
|
|
** return them in chunks by way of a callback function instead of via a
|
|
** pointer to a single large buffer. In this case, a pair of parameters such
|
|
** as:
|
|
**
|
|
** <pre>
|
|
** int *pnChangeset,
|
|
** void **ppChangeset,
|
|
** </pre>
|
|
**
|
|
** Is replaced by:
|
|
**
|
|
** <pre>
|
|
** int (*xOutput)(void *pOut, const void *pData, int nData),
|
|
** void *pOut
|
|
** </pre>
|
|
**
|
|
** The xOutput callback is invoked zero or more times to return data to
|
|
** the application. The first parameter passed to each call is a copy of the
|
|
** pOut pointer supplied by the application. The second parameter, pData,
|
|
** points to a buffer nData bytes in size containing the chunk of output
|
|
** data being returned. If the xOutput callback successfully processes the
|
|
** supplied data, it should return SQLITE_OK to indicate success. Otherwise,
|
|
** it should return some other SQLite error code. In this case processing
|
|
** is immediately abandoned and the streaming API function returns a copy
|
|
** of the xOutput error code to the application.
|
|
**
|
|
** The sessions module never invokes an xOutput callback with the third
|
|
** parameter set to a value less than or equal to zero. Other than this,
|
|
** no guarantees are made as to the size of the chunks of data returned.
|
|
*/
|
|
SQLITE_API int sqlite3changeset_apply_strm(
|
|
sqlite3 *db, /* Apply change to "main" db of this handle */
|
|
int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */
|
|
void *pIn, /* First arg for xInput */
|
|
int(*xFilter)(
|
|
void *pCtx, /* Copy of sixth arg to _apply() */
|
|
const char *zTab /* Table name */
|
|
),
|
|
int(*xConflict)(
|
|
void *pCtx, /* Copy of sixth arg to _apply() */
|
|
int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
|
|
sqlite3_changeset_iter *p /* Handle describing change and conflict */
|
|
),
|
|
void *pCtx /* First argument passed to xConflict */
|
|
);
|
|
SQLITE_API int sqlite3changeset_apply_v2_strm(
|
|
sqlite3 *db, /* Apply change to "main" db of this handle */
|
|
int (*xInput)(void *pIn, void *pData, int *pnData), /* Input function */
|
|
void *pIn, /* First arg for xInput */
|
|
int(*xFilter)(
|
|
void *pCtx, /* Copy of sixth arg to _apply() */
|
|
const char *zTab /* Table name */
|
|
),
|
|
int(*xConflict)(
|
|
void *pCtx, /* Copy of sixth arg to _apply() */
|
|
int eConflict, /* DATA, MISSING, CONFLICT, CONSTRAINT */
|
|
sqlite3_changeset_iter *p /* Handle describing change and conflict */
|
|
),
|
|
void *pCtx, /* First argument passed to xConflict */
|
|
void **ppRebase, int *pnRebase,
|
|
int flags
|
|
);
|
|
SQLITE_API int sqlite3changeset_concat_strm(
|
|
int (*xInputA)(void *pIn, void *pData, int *pnData),
|
|
void *pInA,
|
|
int (*xInputB)(void *pIn, void *pData, int *pnData),
|
|
void *pInB,
|
|
int (*xOutput)(void *pOut, const void *pData, int nData),
|
|
void *pOut
|
|
);
|
|
SQLITE_API int sqlite3changeset_invert_strm(
|
|
int (*xInput)(void *pIn, void *pData, int *pnData),
|
|
void *pIn,
|
|
int (*xOutput)(void *pOut, const void *pData, int nData),
|
|
void *pOut
|
|
);
|
|
SQLITE_API int sqlite3changeset_start_strm(
|
|
sqlite3_changeset_iter **pp,
|
|
int (*xInput)(void *pIn, void *pData, int *pnData),
|
|
void *pIn
|
|
);
|
|
SQLITE_API int sqlite3changeset_start_v2_strm(
|
|
sqlite3_changeset_iter **pp,
|
|
int (*xInput)(void *pIn, void *pData, int *pnData),
|
|
void *pIn,
|
|
int flags
|
|
);
|
|
SQLITE_API int sqlite3session_changeset_strm(
|
|
sqlite3_session *pSession,
|
|
int (*xOutput)(void *pOut, const void *pData, int nData),
|
|
void *pOut
|
|
);
|
|
SQLITE_API int sqlite3session_patchset_strm(
|
|
sqlite3_session *pSession,
|
|
int (*xOutput)(void *pOut, const void *pData, int nData),
|
|
void *pOut
|
|
);
|
|
SQLITE_API int sqlite3changegroup_add_strm(sqlite3_changegroup*,
|
|
int (*xInput)(void *pIn, void *pData, int *pnData),
|
|
void *pIn
|
|
);
|
|
SQLITE_API int sqlite3changegroup_output_strm(sqlite3_changegroup*,
|
|
int (*xOutput)(void *pOut, const void *pData, int nData),
|
|
void *pOut
|
|
);
|
|
SQLITE_API int sqlite3rebaser_rebase_strm(
|
|
sqlite3_rebaser *pRebaser,
|
|
int (*xInput)(void *pIn, void *pData, int *pnData),
|
|
void *pIn,
|
|
int (*xOutput)(void *pOut, const void *pData, int nData),
|
|
void *pOut
|
|
);
|
|
|
|
/*
|
|
** CAPI3REF: Configure global parameters
|
|
**
|
|
** The sqlite3session_config() interface is used to make global configuration
|
|
** changes to the sessions module in order to tune it to the specific needs
|
|
** of the application.
|
|
**
|
|
** The sqlite3session_config() interface is not threadsafe. If it is invoked
|
|
** while any other thread is inside any other sessions method then the
|
|
** results are undefined. Furthermore, if it is invoked after any sessions
|
|
** related objects have been created, the results are also undefined.
|
|
**
|
|
** The first argument to the sqlite3session_config() function must be one
|
|
** of the SQLITE_SESSION_CONFIG_XXX constants defined below. The
|
|
** interpretation of the (void*) value passed as the second parameter and
|
|
** the effect of calling this function depends on the value of the first
|
|
** parameter.
|
|
**
|
|
** <dl>
|
|
** <dt>SQLITE_SESSION_CONFIG_STRMSIZE<dd>
|
|
** By default, the sessions module streaming interfaces attempt to input
|
|
** and output data in approximately 1 KiB chunks. This operand may be used
|
|
** to set and query the value of this configuration setting. The pointer
|
|
** passed as the second argument must point to a value of type (int).
|
|
** If this value is greater than 0, it is used as the new streaming data
|
|
** chunk size for both input and output. Before returning, the (int) value
|
|
** pointed to by pArg is set to the final value of the streaming interface
|
|
** chunk size.
|
|
** </dl>
|
|
**
|
|
** This function returns SQLITE_OK if successful, or an SQLite error code
|
|
** otherwise.
|
|
*/
|
|
SQLITE_API int sqlite3session_config(int op, void *pArg);
|
|
|
|
/*
|
|
** CAPI3REF: Values for sqlite3session_config().
|
|
*/
|
|
#define SQLITE_SESSION_CONFIG_STRMSIZE 1
|
|
|
|
/*
|
|
** Make sure we can call this stuff from C++.
|
|
*/
|
|
#if 0
|
|
}
|
|
#endif
|
|
|
|
#endif /* !defined(__SQLITESESSION_H_) && defined(SQLITE_ENABLE_SESSION) */
|
|
|
|
/******** End of sqlite3session.h *********/
|
|
/******** Begin file fts5.h *********/
|
|
/*
|
|
** 2014 May 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.
|
|
**
|
|
******************************************************************************
|
|
**
|
|
** Interfaces to extend FTS5. Using the interfaces defined in this file,
|
|
** FTS5 may be extended with:
|
|
**
|
|
** * custom tokenizers, and
|
|
** * custom auxiliary functions.
|
|
*/
|
|
|
|
|
|
#ifndef _FTS5_H
|
|
#define _FTS5_H
|
|
|
|
|
|
#if 0
|
|
extern "C" {
|
|
#endif
|
|
|
|
/*************************************************************************
|
|
** CUSTOM AUXILIARY FUNCTIONS
|
|
**
|
|
** Virtual table implementations may overload SQL functions by implementing
|
|
** the sqlite3_module.xFindFunction() method.
|
|
*/
|
|
|
|
typedef struct Fts5ExtensionApi Fts5ExtensionApi;
|
|
typedef struct Fts5Context Fts5Context;
|
|
typedef struct Fts5PhraseIter Fts5PhraseIter;
|
|
|
|
typedef void (*fts5_extension_function)(
|
|
const Fts5ExtensionApi *pApi, /* API offered by current FTS version */
|
|
Fts5Context *pFts, /* First arg to pass to pApi functions */
|
|
sqlite3_context *pCtx, /* Context for returning result/error */
|
|
int nVal, /* Number of values in apVal[] array */
|
|
sqlite3_value **apVal /* Array of trailing arguments */
|
|
);
|
|
|
|
struct Fts5PhraseIter {
|
|
const unsigned char *a;
|
|
const unsigned char *b;
|
|
};
|
|
|
|
/*
|
|
** EXTENSION API FUNCTIONS
|
|
**
|
|
** xUserData(pFts):
|
|
** Return a copy of the context pointer the extension function was
|
|
** registered with.
|
|
**
|
|
** xColumnTotalSize(pFts, iCol, pnToken):
|
|
** If parameter iCol is less than zero, set output variable *pnToken
|
|
** to the total number of tokens in the FTS5 table. Or, if iCol is
|
|
** non-negative but less than the number of columns in the table, return
|
|
** the total number of tokens in column iCol, considering all rows in
|
|
** the FTS5 table.
|
|
**
|
|
** If parameter iCol is greater than or equal to the number of columns
|
|
** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g.
|
|
** an OOM condition or IO error), an appropriate SQLite error code is
|
|
** returned.
|
|
**
|
|
** xColumnCount(pFts):
|
|
** Return the number of columns in the table.
|
|
**
|
|
** xColumnSize(pFts, iCol, pnToken):
|
|
** If parameter iCol is less than zero, set output variable *pnToken
|
|
** to the total number of tokens in the current row. Or, if iCol is
|
|
** non-negative but less than the number of columns in the table, set
|
|
** *pnToken to the number of tokens in column iCol of the current row.
|
|
**
|
|
** If parameter iCol is greater than or equal to the number of columns
|
|
** in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g.
|
|
** an OOM condition or IO error), an appropriate SQLite error code is
|
|
** returned.
|
|
**
|
|
** This function may be quite inefficient if used with an FTS5 table
|
|
** created with the "columnsize=0" option.
|
|
**
|
|
** xColumnText:
|
|
** If parameter iCol is less than zero, or greater than or equal to the
|
|
** number of columns in the table, SQLITE_RANGE is returned.
|
|
**
|
|
** Otherwise, this function attempts to retrieve the text of column iCol of
|
|
** the current document. If successful, (*pz) is set to point to a buffer
|
|
** containing the text in utf-8 encoding, (*pn) is set to the size in bytes
|
|
** (not characters) of the buffer and SQLITE_OK is returned. Otherwise,
|
|
** if an error occurs, an SQLite error code is returned and the final values
|
|
** of (*pz) and (*pn) are undefined.
|
|
**
|
|
** xPhraseCount:
|
|
** Returns the number of phrases in the current query expression.
|
|
**
|
|
** xPhraseSize:
|
|
** If parameter iCol is less than zero, or greater than or equal to the
|
|
** number of phrases in the current query, as returned by xPhraseCount,
|
|
** 0 is returned. Otherwise, this function returns the number of tokens in
|
|
** phrase iPhrase of the query. Phrases are numbered starting from zero.
|
|
**
|
|
** xInstCount:
|
|
** Set *pnInst to the total number of occurrences of all phrases within
|
|
** the query within the current row. Return SQLITE_OK if successful, or
|
|
** an error code (i.e. SQLITE_NOMEM) if an error occurs.
|
|
**
|
|
** This API can be quite slow if used with an FTS5 table created with the
|
|
** "detail=none" or "detail=column" option. If the FTS5 table is created
|
|
** with either "detail=none" or "detail=column" and "content=" option
|
|
** (i.e. if it is a contentless table), then this API always returns 0.
|
|
**
|
|
** xInst:
|
|
** Query for the details of phrase match iIdx within the current row.
|
|
** Phrase matches are numbered starting from zero, so the iIdx argument
|
|
** should be greater than or equal to zero and smaller than the value
|
|
** output by xInstCount(). If iIdx is less than zero or greater than
|
|
** or equal to the value returned by xInstCount(), SQLITE_RANGE is returned.
|
|
**
|
|
** Otherwise, output parameter *piPhrase is set to the phrase number, *piCol
|
|
** to the column in which it occurs and *piOff the token offset of the
|
|
** first token of the phrase. SQLITE_OK is returned if successful, or an
|
|
** error code (i.e. SQLITE_NOMEM) if an error occurs.
|
|
**
|
|
** This API can be quite slow if used with an FTS5 table created with the
|
|
** "detail=none" or "detail=column" option.
|
|
**
|
|
** xRowid:
|
|
** Returns the rowid of the current row.
|
|
**
|
|
** xTokenize:
|
|
** Tokenize text using the tokenizer belonging to the FTS5 table.
|
|
**
|
|
** xQueryPhrase(pFts5, iPhrase, pUserData, xCallback):
|
|
** This API function is used to query the FTS table for phrase iPhrase
|
|
** of the current query. Specifically, a query equivalent to:
|
|
**
|
|
** ... FROM ftstable WHERE ftstable MATCH $p ORDER BY rowid
|
|
**
|
|
** with $p set to a phrase equivalent to the phrase iPhrase of the
|
|
** current query is executed. Any column filter that applies to
|
|
** phrase iPhrase of the current query is included in $p. For each
|
|
** row visited, the callback function passed as the fourth argument
|
|
** is invoked. The context and API objects passed to the callback
|
|
** function may be used to access the properties of each matched row.
|
|
** Invoking Api.xUserData() returns a copy of the pointer passed as
|
|
** the third argument to pUserData.
|
|
**
|
|
** If parameter iPhrase is less than zero, or greater than or equal to
|
|
** the number of phrases in the query, as returned by xPhraseCount(),
|
|
** this function returns SQLITE_RANGE.
|
|
**
|
|
** If the callback function returns any value other than SQLITE_OK, the
|
|
** query is abandoned and the xQueryPhrase function returns immediately.
|
|
** If the returned value is SQLITE_DONE, xQueryPhrase returns SQLITE_OK.
|
|
** Otherwise, the error code is propagated upwards.
|
|
**
|
|
** If the query runs to completion without incident, SQLITE_OK is returned.
|
|
** Or, if some error occurs before the query completes or is aborted by
|
|
** the callback, an SQLite error code is returned.
|
|
**
|
|
**
|
|
** xSetAuxdata(pFts5, pAux, xDelete)
|
|
**
|
|
** Save the pointer passed as the second argument as the extension function's
|
|
** "auxiliary data". The pointer may then be retrieved by the current or any
|
|
** future invocation of the same fts5 extension function made as part of
|
|
** the same MATCH query using the xGetAuxdata() API.
|
|
**
|
|
** Each extension function is allocated a single auxiliary data slot for
|
|
** each FTS query (MATCH expression). If the extension function is invoked
|
|
** more than once for a single FTS query, then all invocations share a
|
|
** single auxiliary data context.
|
|
**
|
|
** If there is already an auxiliary data pointer when this function is
|
|
** invoked, then it is replaced by the new pointer. If an xDelete callback
|
|
** was specified along with the original pointer, it is invoked at this
|
|
** point.
|
|
**
|
|
** The xDelete callback, if one is specified, is also invoked on the
|
|
** auxiliary data pointer after the FTS5 query has finished.
|
|
**
|
|
** If an error (e.g. an OOM condition) occurs within this function,
|
|
** the auxiliary data is set to NULL and an error code returned. If the
|
|
** xDelete parameter was not NULL, it is invoked on the auxiliary data
|
|
** pointer before returning.
|
|
**
|
|
**
|
|
** xGetAuxdata(pFts5, bClear)
|
|
**
|
|
** Returns the current auxiliary data pointer for the fts5 extension
|
|
** function. See the xSetAuxdata() method for details.
|
|
**
|
|
** If the bClear argument is non-zero, then the auxiliary data is cleared
|
|
** (set to NULL) before this function returns. In this case the xDelete,
|
|
** if any, is not invoked.
|
|
**
|
|
**
|
|
** xRowCount(pFts5, pnRow)
|
|
**
|
|
** This function is used to retrieve the total number of rows in the table.
|
|
** In other words, the same value that would be returned by:
|
|
**
|
|
** SELECT count(*) FROM ftstable;
|
|
**
|
|
** xPhraseFirst()
|
|
** This function is used, along with type Fts5PhraseIter and the xPhraseNext
|
|
** method, to iterate through all instances of a single query phrase within
|
|
** the current row. This is the same information as is accessible via the
|
|
** xInstCount/xInst APIs. While the xInstCount/xInst APIs are more convenient
|
|
** to use, this API may be faster under some circumstances. To iterate
|
|
** through instances of phrase iPhrase, use the following code:
|
|
**
|
|
** Fts5PhraseIter iter;
|
|
** int iCol, iOff;
|
|
** for(pApi->xPhraseFirst(pFts, iPhrase, &iter, &iCol, &iOff);
|
|
** iCol>=0;
|
|
** pApi->xPhraseNext(pFts, &iter, &iCol, &iOff)
|
|
** ){
|
|
** // An instance of phrase iPhrase at offset iOff of column iCol
|
|
** }
|
|
**
|
|
** The Fts5PhraseIter structure is defined above. Applications should not
|
|
** modify this structure directly - it should only be used as shown above
|
|
** with the xPhraseFirst() and xPhraseNext() API methods (and by
|
|
** xPhraseFirstColumn() and xPhraseNextColumn() as illustrated below).
|
|
**
|
|
** This API can be quite slow if used with an FTS5 table created with the
|
|
** "detail=none" or "detail=column" option. If the FTS5 table is created
|
|
** with either "detail=none" or "detail=column" and "content=" option
|
|
** (i.e. if it is a contentless table), then this API always iterates
|
|
** through an empty set (all calls to xPhraseFirst() set iCol to -1).
|
|
**
|
|
** xPhraseNext()
|
|
** See xPhraseFirst above.
|
|
**
|
|
** xPhraseFirstColumn()
|
|
** This function and xPhraseNextColumn() are similar to the xPhraseFirst()
|
|
** and xPhraseNext() APIs described above. The difference is that instead
|
|
** of iterating through all instances of a phrase in the current row, these
|
|
** APIs are used to iterate through the set of columns in the current row
|
|
** that contain one or more instances of a specified phrase. For example:
|
|
**
|
|
** Fts5PhraseIter iter;
|
|
** int iCol;
|
|
** for(pApi->xPhraseFirstColumn(pFts, iPhrase, &iter, &iCol);
|
|
** iCol>=0;
|
|
** pApi->xPhraseNextColumn(pFts, &iter, &iCol)
|
|
** ){
|
|
** // Column iCol contains at least one instance of phrase iPhrase
|
|
** }
|
|
**
|
|
** This API can be quite slow if used with an FTS5 table created with the
|
|
** "detail=none" option. If the FTS5 table is created with either
|
|
** "detail=none" "content=" option (i.e. if it is a contentless table),
|
|
** then this API always iterates through an empty set (all calls to
|
|
** xPhraseFirstColumn() set iCol to -1).
|
|
**
|
|
** The information accessed using this API and its companion
|
|
** xPhraseFirstColumn() may also be obtained using xPhraseFirst/xPhraseNext
|
|
** (or xInst/xInstCount). The chief advantage of this API is that it is
|
|
** significantly more efficient than those alternatives when used with
|
|
** "detail=column" tables.
|
|
**
|
|
** xPhraseNextColumn()
|
|
** See xPhraseFirstColumn above.
|
|
**
|
|
** xQueryToken(pFts5, iPhrase, iToken, ppToken, pnToken)
|
|
** This is used to access token iToken of phrase iPhrase of the current
|
|
** query. Before returning, output parameter *ppToken is set to point
|
|
** to a buffer containing the requested token, and *pnToken to the
|
|
** size of this buffer in bytes.
|
|
**
|
|
** If iPhrase or iToken are less than zero, or if iPhrase is greater than
|
|
** or equal to the number of phrases in the query as reported by
|
|
** xPhraseCount(), or if iToken is equal to or greater than the number of
|
|
** tokens in the phrase, SQLITE_RANGE is returned and *ppToken and *pnToken
|
|
are both zeroed.
|
|
**
|
|
** The output text is not a copy of the query text that specified the
|
|
** token. It is the output of the tokenizer module. For tokendata=1
|
|
** tables, this includes any embedded 0x00 and trailing data.
|
|
**
|
|
** xInstToken(pFts5, iIdx, iToken, ppToken, pnToken)
|
|
** This is used to access token iToken of phrase hit iIdx within the
|
|
** current row. If iIdx is less than zero or greater than or equal to the
|
|
** value returned by xInstCount(), SQLITE_RANGE is returned. Otherwise,
|
|
** output variable (*ppToken) is set to point to a buffer containing the
|
|
** matching document token, and (*pnToken) to the size of that buffer in
|
|
** bytes. This API is not available if the specified token matches a
|
|
** prefix query term. In that case both output variables are always set
|
|
** to 0.
|
|
**
|
|
** The output text is not a copy of the document text that was tokenized.
|
|
** It is the output of the tokenizer module. For tokendata=1 tables, this
|
|
** includes any embedded 0x00 and trailing data.
|
|
**
|
|
** This API can be quite slow if used with an FTS5 table created with the
|
|
** "detail=none" or "detail=column" option.
|
|
*/
|
|
struct Fts5ExtensionApi {
|
|
int iVersion; /* Currently always set to 3 */
|
|
|
|
void *(*xUserData)(Fts5Context*);
|
|
|
|
int (*xColumnCount)(Fts5Context*);
|
|
int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow);
|
|
int (*xColumnTotalSize)(Fts5Context*, int iCol, sqlite3_int64 *pnToken);
|
|
|
|
int (*xTokenize)(Fts5Context*,
|
|
const char *pText, int nText, /* Text to tokenize */
|
|
void *pCtx, /* Context passed to xToken() */
|
|
int (*xToken)(void*, int, const char*, int, int, int) /* Callback */
|
|
);
|
|
|
|
int (*xPhraseCount)(Fts5Context*);
|
|
int (*xPhraseSize)(Fts5Context*, int iPhrase);
|
|
|
|
int (*xInstCount)(Fts5Context*, int *pnInst);
|
|
int (*xInst)(Fts5Context*, int iIdx, int *piPhrase, int *piCol, int *piOff);
|
|
|
|
sqlite3_int64 (*xRowid)(Fts5Context*);
|
|
int (*xColumnText)(Fts5Context*, int iCol, const char **pz, int *pn);
|
|
int (*xColumnSize)(Fts5Context*, int iCol, int *pnToken);
|
|
|
|
int (*xQueryPhrase)(Fts5Context*, int iPhrase, void *pUserData,
|
|
int(*)(const Fts5ExtensionApi*,Fts5Context*,void*)
|
|
);
|
|
int (*xSetAuxdata)(Fts5Context*, void *pAux, void(*xDelete)(void*));
|
|
void *(*xGetAuxdata)(Fts5Context*, int bClear);
|
|
|
|
int (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*);
|
|
void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff);
|
|
|
|
int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*);
|
|
void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol);
|
|
|
|
/* Below this point are iVersion>=3 only */
|
|
int (*xQueryToken)(Fts5Context*,
|
|
int iPhrase, int iToken,
|
|
const char **ppToken, int *pnToken
|
|
);
|
|
int (*xInstToken)(Fts5Context*, int iIdx, int iToken, const char**, int*);
|
|
};
|
|
|
|
/*
|
|
** CUSTOM AUXILIARY FUNCTIONS
|
|
*************************************************************************/
|
|
|
|
/*************************************************************************
|
|
** CUSTOM TOKENIZERS
|
|
**
|
|
** Applications may also register custom tokenizer types. A tokenizer
|
|
** is registered by providing fts5 with a populated instance of the
|
|
** following structure. All structure methods must be defined, setting
|
|
** any member of the fts5_tokenizer struct to NULL leads to undefined
|
|
** behaviour. The structure methods are expected to function as follows:
|
|
**
|
|
** xCreate:
|
|
** This function is used to allocate and initialize a tokenizer instance.
|
|
** A tokenizer instance is required to actually tokenize text.
|
|
**
|
|
** The first argument passed to this function is a copy of the (void*)
|
|
** pointer provided by the application when the fts5_tokenizer object
|
|
** was registered with FTS5 (the third argument to xCreateTokenizer()).
|
|
** The second and third arguments are an array of nul-terminated strings
|
|
** containing the tokenizer arguments, if any, specified following the
|
|
** tokenizer name as part of the CREATE VIRTUAL TABLE statement used
|
|
** to create the FTS5 table.
|
|
**
|
|
** The final argument is an output variable. If successful, (*ppOut)
|
|
** should be set to point to the new tokenizer handle and SQLITE_OK
|
|
** returned. If an error occurs, some value other than SQLITE_OK should
|
|
** be returned. In this case, fts5 assumes that the final value of *ppOut
|
|
** is undefined.
|
|
**
|
|
** xDelete:
|
|
** This function is invoked to delete a tokenizer handle previously
|
|
** allocated using xCreate(). Fts5 guarantees that this function will
|
|
** be invoked exactly once for each successful call to xCreate().
|
|
**
|
|
** xTokenize:
|
|
** This function is expected to tokenize the nText byte string indicated
|
|
** by argument pText. pText may or may not be nul-terminated. The first
|
|
** argument passed to this function is a pointer to an Fts5Tokenizer object
|
|
** returned by an earlier call to xCreate().
|
|
**
|
|
** The second argument indicates the reason that FTS5 is requesting
|
|
** tokenization of the supplied text. This is always one of the following
|
|
** four values:
|
|
**
|
|
** <ul><li> <b>FTS5_TOKENIZE_DOCUMENT</b> - A document is being inserted into
|
|
** or removed from the FTS table. The tokenizer is being invoked to
|
|
** determine the set of tokens to add to (or delete from) the
|
|
** FTS index.
|
|
**
|
|
** <li> <b>FTS5_TOKENIZE_QUERY</b> - A MATCH query is being executed
|
|
** against the FTS index. The tokenizer is being called to tokenize
|
|
** a bareword or quoted string specified as part of the query.
|
|
**
|
|
** <li> <b>(FTS5_TOKENIZE_QUERY | FTS5_TOKENIZE_PREFIX)</b> - Same as
|
|
** FTS5_TOKENIZE_QUERY, except that the bareword or quoted string is
|
|
** followed by a "*" character, indicating that the last token
|
|
** returned by the tokenizer will be treated as a token prefix.
|
|
**
|
|
** <li> <b>FTS5_TOKENIZE_AUX</b> - The tokenizer is being invoked to
|
|
** satisfy an fts5_api.xTokenize() request made by an auxiliary
|
|
** function. Or an fts5_api.xColumnSize() request made by the same
|
|
** on a columnsize=0 database.
|
|
** </ul>
|
|
**
|
|
** For each token in the input string, the supplied callback xToken() must
|
|
** be invoked. The first argument to it should be a copy of the pointer
|
|
** passed as the second argument to xTokenize(). The third and fourth
|
|
** arguments are a pointer to a buffer containing the token text, and the
|
|
** size of the token in bytes. The 4th and 5th arguments are the byte offsets
|
|
** of the first byte of and first byte immediately following the text from
|
|
** which the token is derived within the input.
|
|
**
|
|
** The second argument passed to the xToken() callback ("tflags") should
|
|
** normally be set to 0. The exception is if the tokenizer supports
|
|
** synonyms. In this case see the discussion below for details.
|
|
**
|
|
** FTS5 assumes the xToken() callback is invoked for each token in the
|
|
** order that they occur within the input text.
|
|
**
|
|
** If an xToken() callback returns any value other than SQLITE_OK, then
|
|
** the tokenization should be abandoned and the xTokenize() method should
|
|
** immediately return a copy of the xToken() return value. Or, if the
|
|
** input buffer is exhausted, xTokenize() should return SQLITE_OK. Finally,
|
|
** if an error occurs with the xTokenize() implementation itself, it
|
|
** may abandon the tokenization and return any error code other than
|
|
** SQLITE_OK or SQLITE_DONE.
|
|
**
|
|
** SYNONYM SUPPORT
|
|
**
|
|
** Custom tokenizers may also support synonyms. Consider a case in which a
|
|
** user wishes to query for a phrase such as "first place". Using the
|
|
** built-in tokenizers, the FTS5 query 'first + place' will match instances
|
|
** of "first place" within the document set, but not alternative forms
|
|
** such as "1st place". In some applications, it would be better to match
|
|
** all instances of "first place" or "1st place" regardless of which form
|
|
** the user specified in the MATCH query text.
|
|
**
|
|
** There are several ways to approach this in FTS5:
|
|
**
|
|
** <ol><li> By mapping all synonyms to a single token. In this case, using
|
|
** the above example, this means that the tokenizer returns the
|
|
** same token for inputs "first" and "1st". Say that token is in
|
|
** fact "first", so that when the user inserts the document "I won
|
|
** 1st place" entries are added to the index for tokens "i", "won",
|
|
** "first" and "place". If the user then queries for '1st + place',
|
|
** the tokenizer substitutes "first" for "1st" and the query works
|
|
** as expected.
|
|
**
|
|
** <li> By querying the index for all synonyms of each query term
|
|
** separately. In this case, when tokenizing query text, the
|
|
** tokenizer may provide multiple synonyms for a single term
|
|
** within the document. FTS5 then queries the index for each
|
|
** synonym individually. For example, faced with the query:
|
|
**
|
|
** <codeblock>
|
|
** ... MATCH 'first place'</codeblock>
|
|
**
|
|
** the tokenizer offers both "1st" and "first" as synonyms for the
|
|
** first token in the MATCH query and FTS5 effectively runs a query
|
|
** similar to:
|
|
**
|
|
** <codeblock>
|
|
** ... MATCH '(first OR 1st) place'</codeblock>
|
|
**
|
|
** except that, for the purposes of auxiliary functions, the query
|
|
** still appears to contain just two phrases - "(first OR 1st)"
|
|
** being treated as a single phrase.
|
|
**
|
|
** <li> By adding multiple synonyms for a single term to the FTS index.
|
|
** Using this method, when tokenizing document text, the tokenizer
|
|
** provides multiple synonyms for each token. So that when a
|
|
** document such as "I won first place" is tokenized, entries are
|
|
** added to the FTS index for "i", "won", "first", "1st" and
|
|
** "place".
|
|
**
|
|
** This way, even if the tokenizer does not provide synonyms
|
|
** when tokenizing query text (it should not - to do so would be
|
|
** inefficient), it doesn't matter if the user queries for
|
|
** 'first + place' or '1st + place', as there are entries in the
|
|
** FTS index corresponding to both forms of the first token.
|
|
** </ol>
|
|
**
|
|
** Whether it is parsing document or query text, any call to xToken that
|
|
** specifies a <i>tflags</i> argument with the FTS5_TOKEN_COLOCATED bit
|
|
** is considered to supply a synonym for the previous token. For example,
|
|
** when parsing the document "I won first place", a tokenizer that supports
|
|
** synonyms would call xToken() 5 times, as follows:
|
|
**
|
|
** <codeblock>
|
|
** xToken(pCtx, 0, "i", 1, 0, 1);
|
|
** xToken(pCtx, 0, "won", 3, 2, 5);
|
|
** xToken(pCtx, 0, "first", 5, 6, 11);
|
|
** xToken(pCtx, FTS5_TOKEN_COLOCATED, "1st", 3, 6, 11);
|
|
** xToken(pCtx, 0, "place", 5, 12, 17);
|
|
**</codeblock>
|
|
**
|
|
** It is an error to specify the FTS5_TOKEN_COLOCATED flag the first time
|
|
** xToken() is called. Multiple synonyms may be specified for a single token
|
|
** by making multiple calls to xToken(FTS5_TOKEN_COLOCATED) in sequence.
|
|
** There is no limit to the number of synonyms that may be provided for a
|
|
** single token.
|
|
**
|
|
** In many cases, method (1) above is the best approach. It does not add
|
|
** extra data to the FTS index or require FTS5 to query for multiple terms,
|
|
** so it is efficient in terms of disk space and query speed. However, it
|
|
** does not support prefix queries very well. If, as suggested above, the
|
|
** token "first" is substituted for "1st" by the tokenizer, then the query:
|
|
**
|
|
** <codeblock>
|
|
** ... MATCH '1s*'</codeblock>
|
|
**
|
|
** will not match documents that contain the token "1st" (as the tokenizer
|
|
** will probably not map "1s" to any prefix of "first").
|
|
**
|
|
** For full prefix support, method (3) may be preferred. In this case,
|
|
** because the index contains entries for both "first" and "1st", prefix
|
|
** queries such as 'fi*' or '1s*' will match correctly. However, because
|
|
** extra entries are added to the FTS index, this method uses more space
|
|
** within the database.
|
|
**
|
|
** Method (2) offers a midpoint between (1) and (3). Using this method,
|
|
** a query such as '1s*' will match documents that contain the literal
|
|
** token "1st", but not "first" (assuming the tokenizer is not able to
|
|
** provide synonyms for prefixes). However, a non-prefix query like '1st'
|
|
** will match against "1st" and "first". This method does not require
|
|
** extra disk space, as no extra entries are added to the FTS index.
|
|
** On the other hand, it may require more CPU cycles to run MATCH queries,
|
|
** as separate queries of the FTS index are required for each synonym.
|
|
**
|
|
** When using methods (2) or (3), it is important that the tokenizer only
|
|
** provide synonyms when tokenizing document text (method (3)) or query
|
|
** text (method (2)), not both. Doing so will not cause any errors, but is
|
|
** inefficient.
|
|
*/
|
|
typedef struct Fts5Tokenizer Fts5Tokenizer;
|
|
typedef struct fts5_tokenizer fts5_tokenizer;
|
|
struct fts5_tokenizer {
|
|
int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
|
|
void (*xDelete)(Fts5Tokenizer*);
|
|
int (*xTokenize)(Fts5Tokenizer*,
|
|
void *pCtx,
|
|
int flags, /* Mask of FTS5_TOKENIZE_* flags */
|
|
const char *pText, int nText,
|
|
int (*xToken)(
|
|
void *pCtx, /* Copy of 2nd argument to xTokenize() */
|
|
int tflags, /* Mask of FTS5_TOKEN_* flags */
|
|
const char *pToken, /* Pointer to buffer containing token */
|
|
int nToken, /* Size of token in bytes */
|
|
int iStart, /* Byte offset of token within input text */
|
|
int iEnd /* Byte offset of end of token within input text */
|
|
)
|
|
);
|
|
};
|
|
|
|
/* Flags that may be passed as the third argument to xTokenize() */
|
|
#define FTS5_TOKENIZE_QUERY 0x0001
|
|
#define FTS5_TOKENIZE_PREFIX 0x0002
|
|
#define FTS5_TOKENIZE_DOCUMENT 0x0004
|
|
#define FTS5_TOKENIZE_AUX 0x0008
|
|
|
|
/* Flags that may be passed by the tokenizer implementation back to FTS5
|
|
** as the third argument to the supplied xToken callback. */
|
|
#define FTS5_TOKEN_COLOCATED 0x0001 /* Same position as prev. token */
|
|
|
|
/*
|
|
** END OF CUSTOM TOKENIZERS
|
|
*************************************************************************/
|
|
|
|
/*************************************************************************
|
|
** FTS5 EXTENSION REGISTRATION API
|
|
*/
|
|
typedef struct fts5_api fts5_api;
|
|
struct fts5_api {
|
|
int iVersion; /* Currently always set to 2 */
|
|
|
|
/* Create a new tokenizer */
|
|
int (*xCreateTokenizer)(
|
|
fts5_api *pApi,
|
|
const char *zName,
|
|
void *pUserData,
|
|
fts5_tokenizer *pTokenizer,
|
|
void (*xDestroy)(void*)
|
|
);
|
|
|
|
/* Find an existing tokenizer */
|
|
int (*xFindTokenizer)(
|
|
fts5_api *pApi,
|
|
const char *zName,
|
|
void **ppUserData,
|
|
fts5_tokenizer *pTokenizer
|
|
);
|
|
|
|
/* Create a new auxiliary function */
|
|
int (*xCreateFunction)(
|
|
fts5_api *pApi,
|
|
const char *zName,
|
|
void *pUserData,
|
|
fts5_extension_function xFunction,
|
|
void (*xDestroy)(void*)
|
|
);
|
|
};
|
|
|
|
/*
|
|
** END OF REGISTRATION API
|
|
*************************************************************************/
|
|
|
|
#if 0
|
|
} /* end of the 'extern "C"' block */
|
|
#endif
|
|
|
|
#endif /* _FTS5_H */
|
|
|
|
/******** End of fts5.h *********/
|
|
|
|
/************** End of sqlite3.h *********************************************/
|
|
/************** Continuing where we left off in sqliteInt.h ******************/
|
|
|
|
/*
|
|
** Reuse the STATIC_LRU for mutex access to sqlite3_temp_directory.
|
|
*/
|
|
#define SQLITE_MUTEX_STATIC_TEMPDIR SQLITE_MUTEX_STATIC_VFS1
|
|
|
|
/*
|
|
** Include the configuration header output by 'configure' if we're using the
|
|
** autoconf-based build
|
|
*/
|
|
#if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H)
|
|
#include "sqlite_cfg.h"
|
|
#define SQLITECONFIG_H 1
|
|
#endif
|
|
|
|
/************** Include sqliteLimit.h in the middle of sqliteInt.h ***********/
|
|
/************** Begin file sqliteLimit.h *************************************/
|
|
/*
|
|
** 2007 May 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 defines various limits of what SQLite can process.
|
|
*/
|
|
|
|
/*
|
|
** The maximum length of a TEXT or BLOB in bytes. This also
|
|
** limits the size of a row in a table or index.
|
|
**
|
|
** The hard limit is the ability of a 32-bit signed integer
|
|
** to count the size: 2^31-1 or 2147483647.
|
|
*/
|
|
#ifndef SQLITE_MAX_LENGTH
|
|
# define SQLITE_MAX_LENGTH 1000000000
|
|
#endif
|
|
|
|
/*
|
|
** This is the maximum number of
|
|
**
|
|
** * Columns in a table
|
|
** * Columns in an index
|
|
** * Columns in a view
|
|
** * Terms in the SET clause of an UPDATE statement
|
|
** * Terms in the result set of a SELECT statement
|
|
** * Terms in the GROUP BY or ORDER BY clauses of a SELECT statement.
|
|
** * Terms in the VALUES clause of an INSERT statement
|
|
**
|
|
** The hard upper limit here is 32676. Most database people will
|
|
** tell you that in a well-normalized database, you usually should
|
|
** not have more than a dozen or so columns in any table. And if
|
|
** that is the case, there is no point in having more than a few
|
|
** dozen values in any of the other situations described above.
|
|
*/
|
|
#ifndef SQLITE_MAX_COLUMN
|
|
# define SQLITE_MAX_COLUMN 2000
|
|
#endif
|
|
|
|
/*
|
|
** The maximum length of a single SQL statement in bytes.
|
|
**
|
|
** It used to be the case that setting this value to zero would
|
|
** turn the limit off. That is no longer true. It is not possible
|
|
** to turn this limit off.
|
|
*/
|
|
#ifndef SQLITE_MAX_SQL_LENGTH
|
|
# define SQLITE_MAX_SQL_LENGTH 1000000000
|
|
#endif
|
|
|
|
/*
|
|
** The maximum depth of an expression tree. This is limited to
|
|
** some extent by SQLITE_MAX_SQL_LENGTH. But sometime you might
|
|
** want to place more severe limits on the complexity of an
|
|
** expression. A value of 0 means that there is no limit.
|
|
*/
|
|
#ifndef SQLITE_MAX_EXPR_DEPTH
|
|
# define SQLITE_MAX_EXPR_DEPTH 1000
|
|
#endif
|
|
|
|
/*
|
|
** The maximum number of terms in a compound SELECT statement.
|
|
** The code generator for compound SELECT statements does one
|
|
** level of recursion for each term. A stack overflow can result
|
|
** if the number of terms is too large. In practice, most SQL
|
|
** never has more than 3 or 4 terms. Use a value of 0 to disable
|
|
** any limit on the number of terms in a compound SELECT.
|
|
*/
|
|
#ifndef SQLITE_MAX_COMPOUND_SELECT
|
|
# define SQLITE_MAX_COMPOUND_SELECT 500
|
|
#endif
|
|
|
|
/*
|
|
** The maximum number of opcodes in a VDBE program.
|
|
** Not currently enforced.
|
|
*/
|
|
#ifndef SQLITE_MAX_VDBE_OP
|
|
# define SQLITE_MAX_VDBE_OP 250000000
|
|
#endif
|
|
|
|
/*
|
|
** The maximum number of arguments to an SQL function.
|
|
*/
|
|
#ifndef SQLITE_MAX_FUNCTION_ARG
|
|
# define SQLITE_MAX_FUNCTION_ARG 127
|
|
#endif
|
|
|
|
/*
|
|
** The suggested maximum number of in-memory pages to use for
|
|
** the main database table and for temporary tables.
|
|
**
|
|
** IMPLEMENTATION-OF: R-30185-15359 The default suggested cache size is -2000,
|
|
** which means the cache size is limited to 2048000 bytes of memory.
|
|
** IMPLEMENTATION-OF: R-48205-43578 The default suggested cache size can be
|
|
** altered using the SQLITE_DEFAULT_CACHE_SIZE compile-time options.
|
|
*/
|
|
#ifndef SQLITE_DEFAULT_CACHE_SIZE
|
|
# define SQLITE_DEFAULT_CACHE_SIZE -2000
|
|
#endif
|
|
|
|
/*
|
|
** The default number of frames to accumulate in the log file before
|
|
** checkpointing the database in WAL mode.
|
|
*/
|
|
#ifndef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
|
|
# define SQLITE_DEFAULT_WAL_AUTOCHECKPOINT 1000
|
|
#endif
|
|
|
|
/*
|
|
** The maximum number of attached databases. This must be between 0
|
|
** and 125. The upper bound of 125 is because the attached databases are
|
|
** counted using a signed 8-bit integer which has a maximum value of 127
|
|
** and we have to allow 2 extra counts for the "main" and "temp" databases.
|
|
*/
|
|
#ifndef SQLITE_MAX_ATTACHED
|
|
# define SQLITE_MAX_ATTACHED 10
|
|
#endif
|
|
|
|
|
|
/*
|
|
** The maximum value of a ?nnn wildcard that the parser will accept.
|
|
** If the value exceeds 32767 then extra space is required for the Expr
|
|
** structure. But otherwise, we believe that the number can be as large
|
|
** as a signed 32-bit integer can hold.
|
|
*/
|
|
#ifndef SQLITE_MAX_VARIABLE_NUMBER
|
|
# define SQLITE_MAX_VARIABLE_NUMBER 32766
|
|
#endif
|
|
|
|
/* Maximum page size. The upper bound on this value is 65536. This a limit
|
|
** imposed by the use of 16-bit offsets within each page.
|
|
**
|
|
** Earlier versions of SQLite allowed the user to change this value at
|
|
** compile time. This is no longer permitted, on the grounds that it creates
|
|
** a library that is technically incompatible with an SQLite library
|
|
** compiled with a different limit. If a process operating on a database
|
|
** with a page-size of 65536 bytes crashes, then an instance of SQLite
|
|
** compiled with the default page-size limit will not be able to rollback
|
|
** the aborted transaction. This could lead to database corruption.
|
|
*/
|
|
#ifdef SQLITE_MAX_PAGE_SIZE
|
|
# undef SQLITE_MAX_PAGE_SIZE
|
|
#endif
|
|
#define SQLITE_MAX_PAGE_SIZE 65536
|
|
|
|
|
|
/*
|
|
** The default size of a database page.
|
|
*/
|
|
#ifndef SQLITE_DEFAULT_PAGE_SIZE
|
|
# define SQLITE_DEFAULT_PAGE_SIZE 4096
|
|
#endif
|
|
#if SQLITE_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE
|
|
# undef SQLITE_DEFAULT_PAGE_SIZE
|
|
# define SQLITE_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE
|
|
#endif
|
|
|
|
/*
|
|
** Ordinarily, if no value is explicitly provided, SQLite creates databases
|
|
** with page size SQLITE_DEFAULT_PAGE_SIZE. However, based on certain
|
|
** device characteristics (sector-size and atomic write() support),
|
|
** SQLite may choose a larger value. This constant is the maximum value
|
|
** SQLite will choose on its own.
|
|
*/
|
|
#ifndef SQLITE_MAX_DEFAULT_PAGE_SIZE
|
|
# define SQLITE_MAX_DEFAULT_PAGE_SIZE 8192
|
|
#endif
|
|
#if SQLITE_MAX_DEFAULT_PAGE_SIZE>SQLITE_MAX_PAGE_SIZE
|
|
# undef SQLITE_MAX_DEFAULT_PAGE_SIZE
|
|
# define SQLITE_MAX_DEFAULT_PAGE_SIZE SQLITE_MAX_PAGE_SIZE
|
|
#endif
|
|
|
|
|
|
/*
|
|
** Maximum number of pages in one database file.
|
|
**
|
|
** This is really just the default value for the max_page_count pragma.
|
|
** This value can be lowered (or raised) at run-time using that the
|
|
** max_page_count macro.
|
|
*/
|
|
#ifndef SQLITE_MAX_PAGE_COUNT
|
|
# define SQLITE_MAX_PAGE_COUNT 0xfffffffe /* 4294967294 */
|
|
#endif
|
|
|
|
/*
|
|
** Maximum length (in bytes) of the pattern in a LIKE or GLOB
|
|
** operator.
|
|
*/
|
|
#ifndef SQLITE_MAX_LIKE_PATTERN_LENGTH
|
|
# define SQLITE_MAX_LIKE_PATTERN_LENGTH 50000
|
|
#endif
|
|
|
|
/*
|
|
** Maximum depth of recursion for triggers.
|
|
**
|
|
** A value of 1 means that a trigger program will not be able to itself
|
|
** fire any triggers. A value of 0 means that no trigger programs at all
|
|
** may be executed.
|
|
*/
|
|
#ifndef SQLITE_MAX_TRIGGER_DEPTH
|
|
# define SQLITE_MAX_TRIGGER_DEPTH 1000
|
|
#endif
|
|
|
|
/************** End of sqliteLimit.h *****************************************/
|
|
/************** Continuing where we left off in sqliteInt.h ******************/
|
|
|
|
/* Disable nuisance warnings on Borland compilers */
|
|
#if defined(__BORLANDC__)
|
|
#pragma warn -rch /* unreachable code */
|
|
#pragma warn -ccc /* Condition is always true or false */
|
|
#pragma warn -aus /* Assigned value is never used */
|
|
#pragma warn -csu /* Comparing signed and unsigned */
|
|
#pragma warn -spa /* Suspicious pointer arithmetic */
|
|
#endif
|
|
|
|
/*
|
|
** A few places in the code require atomic load/store of aligned
|
|
** integer values.
|
|
*/
|
|
#ifndef __has_extension
|
|
# define __has_extension(x) 0 /* compatibility with non-clang compilers */
|
|
#endif
|
|
#if GCC_VERSION>=4007000 || __has_extension(c_atomic)
|
|
# define SQLITE_ATOMIC_INTRINSICS 1
|
|
# define AtomicLoad(PTR) __atomic_load_n((PTR),__ATOMIC_RELAXED)
|
|
# define AtomicStore(PTR,VAL) __atomic_store_n((PTR),(VAL),__ATOMIC_RELAXED)
|
|
#else
|
|
# define SQLITE_ATOMIC_INTRINSICS 0
|
|
# define AtomicLoad(PTR) (*(PTR))
|
|
# define AtomicStore(PTR,VAL) (*(PTR) = (VAL))
|
|
#endif
|
|
|
|
/*
|
|
** Include standard header files as necessary
|
|
*/
|
|
#ifdef HAVE_STDINT_H
|
|
#include <stdint.h>
|
|
#endif
|
|
#ifdef HAVE_INTTYPES_H
|
|
#include <inttypes.h>
|
|
#endif
|
|
|
|
/*
|
|
** The following macros are used to cast pointers to integers and
|
|
** integers to pointers. The way you do this varies from one compiler
|
|
** to the next, so we have developed the following set of #if statements
|
|
** to generate appropriate macros for a wide range of compilers.
|
|
**
|
|
** The correct "ANSI" way to do this is to use the intptr_t type.
|
|
** Unfortunately, that typedef is not available on all compilers, or
|
|
** if it is available, it requires an #include of specific headers
|
|
** that vary from one machine to the next.
|
|
**
|
|
** Ticket #3860: The llvm-gcc-4.2 compiler from Apple chokes on
|
|
** the ((void*)&((char*)0)[X]) construct. But MSVC chokes on ((void*)(X)).
|
|
** So we have to define the macros in different ways depending on the
|
|
** compiler.
|
|
*/
|
|
#if defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */
|
|
# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X))
|
|
# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X))
|
|
#elif defined(__PTRDIFF_TYPE__) /* This case should work for GCC */
|
|
# define SQLITE_INT_TO_PTR(X) ((void*)(__PTRDIFF_TYPE__)(X))
|
|
# define SQLITE_PTR_TO_INT(X) ((int)(__PTRDIFF_TYPE__)(X))
|
|
#elif !defined(__GNUC__) /* Works for compilers other than LLVM */
|
|
# define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X])
|
|
# define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0))
|
|
#else /* Generates a warning - but it always works */
|
|
# define SQLITE_INT_TO_PTR(X) ((void*)(X))
|
|
# define SQLITE_PTR_TO_INT(X) ((int)(X))
|
|
#endif
|
|
|
|
/*
|
|
** Macros to hint to the compiler that a function should or should not be
|
|
** inlined.
|
|
*/
|
|
#if defined(__GNUC__)
|
|
# define SQLITE_NOINLINE __attribute__((noinline))
|
|
# define SQLITE_INLINE __attribute__((always_inline)) inline
|
|
#elif defined(_MSC_VER) && _MSC_VER>=1310
|
|
# define SQLITE_NOINLINE __declspec(noinline)
|
|
# define SQLITE_INLINE __forceinline
|
|
#else
|
|
# define SQLITE_NOINLINE
|
|
# define SQLITE_INLINE
|
|
#endif
|
|
#if defined(SQLITE_COVERAGE_TEST) || defined(__STRICT_ANSI__)
|
|
# undef SQLITE_INLINE
|
|
# define SQLITE_INLINE
|
|
#endif
|
|
|
|
/*
|
|
** Make sure that the compiler intrinsics we desire are enabled when
|
|
** compiling with an appropriate version of MSVC unless prevented by
|
|
** the SQLITE_DISABLE_INTRINSIC define.
|
|
*/
|
|
#if !defined(SQLITE_DISABLE_INTRINSIC)
|
|
# if defined(_MSC_VER) && _MSC_VER>=1400
|
|
# if !defined(_WIN32_WCE)
|
|
# include <intrin.h>
|
|
# pragma intrinsic(_byteswap_ushort)
|
|
# pragma intrinsic(_byteswap_ulong)
|
|
# pragma intrinsic(_byteswap_uint64)
|
|
# pragma intrinsic(_ReadWriteBarrier)
|
|
# else
|
|
# include <cmnintrin.h>
|
|
# endif
|
|
# endif
|
|
#endif
|
|
|
|
/*
|
|
** Enable SQLITE_USE_SEH by default on MSVC builds. Only omit
|
|
** SEH support if the -DSQLITE_OMIT_SEH option is given.
|
|
*/
|
|
#if defined(_MSC_VER) && !defined(SQLITE_OMIT_SEH)
|
|
# define SQLITE_USE_SEH 1
|
|
#else
|
|
# undef SQLITE_USE_SEH
|
|
#endif
|
|
|
|
/*
|
|
** Enable SQLITE_DIRECT_OVERFLOW_READ, unless the build explicitly
|
|
** disables it using -DSQLITE_DIRECT_OVERFLOW_READ=0
|
|
*/
|
|
#if defined(SQLITE_DIRECT_OVERFLOW_READ) && SQLITE_DIRECT_OVERFLOW_READ+1==1
|
|
/* Disable if -DSQLITE_DIRECT_OVERFLOW_READ=0 */
|
|
# undef SQLITE_DIRECT_OVERFLOW_READ
|
|
#else
|
|
/* In all other cases, enable */
|
|
# define SQLITE_DIRECT_OVERFLOW_READ 1
|
|
#endif
|
|
|
|
|
|
/*
|
|
** The SQLITE_THREADSAFE macro must be defined as 0, 1, or 2.
|
|
** 0 means mutexes are permanently disable and the library is never
|
|
** threadsafe. 1 means the library is serialized which is the highest
|
|
** level of threadsafety. 2 means the library is multithreaded - multiple
|
|
** threads can use SQLite as long as no two threads try to use the same
|
|
** database connection at the same time.
|
|
**
|
|
** Older versions of SQLite used an optional THREADSAFE macro.
|
|
** We support that for legacy.
|
|
**
|
|
** To ensure that the correct value of "THREADSAFE" is reported when querying
|
|
** for compile-time options at runtime (e.g. "PRAGMA compile_options"), this
|
|
** logic is partially replicated in ctime.c. If it is updated here, it should
|
|
** also be updated there.
|
|
*/
|
|
#if !defined(SQLITE_THREADSAFE)
|
|
# if defined(THREADSAFE)
|
|
# define SQLITE_THREADSAFE THREADSAFE
|
|
# else
|
|
# define SQLITE_THREADSAFE 1 /* IMP: R-07272-22309 */
|
|
# endif
|
|
#endif
|
|
|
|
/*
|
|
** Powersafe overwrite is on by default. But can be turned off using
|
|
** the -DSQLITE_POWERSAFE_OVERWRITE=0 command-line option.
|
|
*/
|
|
#ifndef SQLITE_POWERSAFE_OVERWRITE
|
|
# define SQLITE_POWERSAFE_OVERWRITE 1
|
|
#endif
|
|
|
|
/*
|
|
** EVIDENCE-OF: R-25715-37072 Memory allocation statistics are enabled by
|
|
** default unless SQLite is compiled with SQLITE_DEFAULT_MEMSTATUS=0 in
|
|
** which case memory allocation statistics are disabled by default.
|
|
*/
|
|
#if !defined(SQLITE_DEFAULT_MEMSTATUS)
|
|
# define SQLITE_DEFAULT_MEMSTATUS 1
|
|
#endif
|
|
|
|
/*
|
|
** Exactly one of the following macros must be defined in order to
|
|
** specify which memory allocation subsystem to use.
|
|
**
|
|
** SQLITE_SYSTEM_MALLOC // Use normal system malloc()
|
|
** SQLITE_WIN32_MALLOC // Use Win32 native heap API
|
|
** SQLITE_ZERO_MALLOC // Use a stub allocator that always fails
|
|
** SQLITE_MEMDEBUG // Debugging version of system malloc()
|
|
**
|
|
** On Windows, if the SQLITE_WIN32_MALLOC_VALIDATE macro is defined and the
|
|
** assert() macro is enabled, each call into the Win32 native heap subsystem
|
|
** will cause HeapValidate to be called. If heap validation should fail, an
|
|
** assertion will be triggered.
|
|
**
|
|
** If none of the above are defined, then set SQLITE_SYSTEM_MALLOC as
|
|
** the default.
|
|
*/
|
|
#if defined(SQLITE_SYSTEM_MALLOC) \
|
|
+ defined(SQLITE_WIN32_MALLOC) \
|
|
+ defined(SQLITE_ZERO_MALLOC) \
|
|
+ defined(SQLITE_MEMDEBUG)>1
|
|
# error "Two or more of the following compile-time configuration options\
|
|
are defined but at most one is allowed:\
|
|
SQLITE_SYSTEM_MALLOC, SQLITE_WIN32_MALLOC, SQLITE_MEMDEBUG,\
|
|
SQLITE_ZERO_MALLOC"
|
|
#endif
|
|
#if defined(SQLITE_SYSTEM_MALLOC) \
|
|
+ defined(SQLITE_WIN32_MALLOC) \
|
|
+ defined(SQLITE_ZERO_MALLOC) \
|
|
+ defined(SQLITE_MEMDEBUG)==0
|
|
# define SQLITE_SYSTEM_MALLOC 1
|
|
#endif
|
|
|
|
/*
|
|
** If SQLITE_MALLOC_SOFT_LIMIT is not zero, then try to keep the
|
|
** sizes of memory allocations below this value where possible.
|
|
*/
|
|
#if !defined(SQLITE_MALLOC_SOFT_LIMIT)
|
|
# define SQLITE_MALLOC_SOFT_LIMIT 1024
|
|
#endif
|
|
|
|
/*
|
|
** We need to define _XOPEN_SOURCE as follows in order to enable
|
|
** recursive mutexes on most Unix systems and fchmod() on OpenBSD.
|
|
** But _XOPEN_SOURCE define causes problems for Mac OS X, so omit
|
|
** it.
|
|
*/
|
|
#if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) && !defined(__APPLE__)
|
|
# define _XOPEN_SOURCE 600
|
|
#endif
|
|
|
|
/*
|
|
** NDEBUG and SQLITE_DEBUG are opposites. It should always be true that
|
|
** defined(NDEBUG)==!defined(SQLITE_DEBUG). If this is not currently true,
|
|
** make it true by defining or undefining NDEBUG.
|
|
**
|
|
** Setting NDEBUG makes the code smaller and faster by disabling the
|
|
** assert() statements in the code. So we want the default action
|
|
** to be for NDEBUG to be set and NDEBUG to be undefined only if SQLITE_DEBUG
|
|
** is set. Thus NDEBUG becomes an opt-in rather than an opt-out
|
|
** feature.
|
|
*/
|
|
#if !defined(NDEBUG) && !defined(SQLITE_DEBUG)
|
|
# define NDEBUG 1
|
|
#endif
|
|
#if defined(NDEBUG) && defined(SQLITE_DEBUG)
|
|
# undef NDEBUG
|
|
#endif
|
|
|
|
/*
|
|
** Enable SQLITE_ENABLE_EXPLAIN_COMMENTS if SQLITE_DEBUG is turned on.
|
|
*/
|
|
#if !defined(SQLITE_ENABLE_EXPLAIN_COMMENTS) && defined(SQLITE_DEBUG)
|
|
# define SQLITE_ENABLE_EXPLAIN_COMMENTS 1
|
|
#endif
|
|
|
|
/*
|
|
** The testcase() macro is used to aid in coverage testing. When
|
|
** doing coverage testing, the condition inside the argument to
|
|
** testcase() must be evaluated both true and false in order to
|
|
** get full branch coverage. The testcase() macro is inserted
|
|
** to help ensure adequate test coverage in places where simple
|
|
** condition/decision coverage is inadequate. For example, testcase()
|
|
** can be used to make sure boundary values are tested. For
|
|
** bitmask tests, testcase() can be used to make sure each bit
|
|
** is significant and used at least once. On switch statements
|
|
** where multiple cases go to the same block of code, testcase()
|
|
** can insure that all cases are evaluated.
|
|
*/
|
|
#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG)
|
|
# ifndef SQLITE_AMALGAMATION
|
|
extern unsigned int sqlite3CoverageCounter;
|
|
# endif
|
|
# define testcase(X) if( X ){ sqlite3CoverageCounter += (unsigned)__LINE__; }
|
|
#else
|
|
# define testcase(X)
|
|
#endif
|
|
|
|
/*
|
|
** The TESTONLY macro is used to enclose variable declarations or
|
|
** other bits of code that are needed to support the arguments
|
|
** within testcase() and assert() macros.
|
|
*/
|
|
#if !defined(NDEBUG) || defined(SQLITE_COVERAGE_TEST)
|
|
# define TESTONLY(X) X
|
|
#else
|
|
# define TESTONLY(X)
|
|
#endif
|
|
|
|
/*
|
|
** Sometimes we need a small amount of code such as a variable initialization
|
|
** to setup for a later assert() statement. We do not want this code to
|
|
** appear when assert() is disabled. The following macro is therefore
|
|
** used to contain that setup code. The "VVA" acronym stands for
|
|
** "Verification, Validation, and Accreditation". In other words, the
|
|
** code within VVA_ONLY() will only run during verification processes.
|
|
*/
|
|
#ifndef NDEBUG
|
|
# define VVA_ONLY(X) X
|
|
#else
|
|
# define VVA_ONLY(X)
|
|
#endif
|
|
|
|
/*
|
|
** Disable ALWAYS() and NEVER() (make them pass-throughs) for coverage
|
|
** and mutation testing
|
|
*/
|
|
#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
|
|
# define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
|
|
#endif
|
|
|
|
/*
|
|
** The ALWAYS and NEVER macros surround boolean expressions which
|
|
** are intended to always be true or false, respectively. Such
|
|
** expressions could be omitted from the code completely. But they
|
|
** are included in a few cases in order to enhance the resilience
|
|
** of SQLite to unexpected behavior - to make the code "self-healing"
|
|
** or "ductile" rather than being "brittle" and crashing at the first
|
|
** hint of unplanned behavior.
|
|
**
|
|
** In other words, ALWAYS and NEVER are added for defensive code.
|
|
**
|
|
** When doing coverage testing ALWAYS and NEVER are hard-coded to
|
|
** be true and false so that the unreachable code they specify will
|
|
** not be counted as untested code.
|
|
*/
|
|
#if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
|
|
# define ALWAYS(X) (1)
|
|
# define NEVER(X) (0)
|
|
#elif !defined(NDEBUG)
|
|
# define ALWAYS(X) ((X)?1:(assert(0),0))
|
|
# define NEVER(X) ((X)?(assert(0),1):0)
|
|
#else
|
|
# define ALWAYS(X) (X)
|
|
# define NEVER(X) (X)
|
|
#endif
|
|
|
|
/*
|
|
** Some conditionals are optimizations only. In other words, if the
|
|
** conditionals are replaced with a constant 1 (true) or 0 (false) then
|
|
** the correct answer is still obtained, though perhaps not as quickly.
|
|
**
|
|
** The following macros mark these optimizations conditionals.
|
|
*/
|
|
#if defined(SQLITE_MUTATION_TEST)
|
|
# define OK_IF_ALWAYS_TRUE(X) (1)
|
|
# define OK_IF_ALWAYS_FALSE(X) (0)
|
|
#else
|
|
# define OK_IF_ALWAYS_TRUE(X) (X)
|
|
# define OK_IF_ALWAYS_FALSE(X) (X)
|
|
#endif
|
|
|
|
/*
|
|
** Some malloc failures are only possible if SQLITE_TEST_REALLOC_STRESS is
|
|
** defined. We need to defend against those failures when testing with
|
|
** SQLITE_TEST_REALLOC_STRESS, but we don't want the unreachable branches
|
|
** during a normal build. The following macro can be used to disable tests
|
|
** that are always false except when SQLITE_TEST_REALLOC_STRESS is set.
|
|
*/
|
|
#if defined(SQLITE_TEST_REALLOC_STRESS)
|
|
# define ONLY_IF_REALLOC_STRESS(X) (X)
|
|
#elif !defined(NDEBUG)
|
|
# define ONLY_IF_REALLOC_STRESS(X) ((X)?(assert(0),1):0)
|
|
#else
|
|
# define ONLY_IF_REALLOC_STRESS(X) (0)
|
|
#endif
|
|
|
|
/*
|
|
** Declarations used for tracing the operating system interfaces.
|
|
*/
|
|
#if defined(SQLITE_FORCE_OS_TRACE) || defined(SQLITE_TEST) || \
|
|
(defined(SQLITE_DEBUG) && SQLITE_OS_WIN)
|
|
extern int sqlite3OSTrace;
|
|
# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
|
|
# define SQLITE_HAVE_OS_TRACE
|
|
#else
|
|
# define OSTRACE(X)
|
|
# undef SQLITE_HAVE_OS_TRACE
|
|
#endif
|
|
|
|
/*
|
|
** Is the sqlite3ErrName() function needed in the build? Currently,
|
|
** it is needed by "mutex_w32.c" (when debugging), "os_win.c" (when
|
|
** OSTRACE is enabled), and by several "test*.c" files (which are
|
|
** compiled using SQLITE_TEST).
|
|
*/
|
|
#if defined(SQLITE_HAVE_OS_TRACE) || defined(SQLITE_TEST) || \
|
|
(defined(SQLITE_DEBUG) && SQLITE_OS_WIN)
|
|
# define SQLITE_NEED_ERR_NAME
|
|
#else
|
|
# undef SQLITE_NEED_ERR_NAME
|
|
#endif
|
|
|
|
/*
|
|
** SQLITE_ENABLE_EXPLAIN_COMMENTS is incompatible with SQLITE_OMIT_EXPLAIN
|
|
*/
|
|
#ifdef SQLITE_OMIT_EXPLAIN
|
|
# undef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
|
#endif
|
|
|
|
/*
|
|
** SQLITE_OMIT_VIRTUALTABLE implies SQLITE_OMIT_ALTERTABLE
|
|
*/
|
|
#if defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_ALTERTABLE)
|
|
# define SQLITE_OMIT_ALTERTABLE
|
|
#endif
|
|
|
|
/*
|
|
** Return true (non-zero) if the input is an integer that is too large
|
|
** to fit in 32-bits. This macro is used inside of various testcase()
|
|
** macros to verify that we have tested SQLite for large-file support.
|
|
*/
|
|
#define IS_BIG_INT(X) (((X)&~(i64)0xffffffff)!=0)
|
|
|
|
/*
|
|
** The macro unlikely() is a hint that surrounds a boolean
|
|
** expression that is usually false. Macro likely() surrounds
|
|
** a boolean expression that is usually true. These hints could,
|
|
** in theory, be used by the compiler to generate better code, but
|
|
** currently they are just comments for human readers.
|
|
*/
|
|
#define likely(X) (X)
|
|
#define unlikely(X) (X)
|
|
|
|
/************** Include hash.h in the middle of sqliteInt.h ******************/
|
|
/************** Begin file hash.h ********************************************/
|
|
/*
|
|
** 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 implementation
|
|
** used in SQLite.
|
|
*/
|
|
#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, some of the "procedures" and "functions" for modifying and
|
|
** accessing this structure are really macros, so we can't really make
|
|
** this structure opaque.
|
|
**
|
|
** All elements of the hash table are on a single doubly-linked list.
|
|
** Hash.first points to the head of this list.
|
|
**
|
|
** There are Hash.htsize buckets. Each bucket points to a spot in
|
|
** the global doubly-linked list. The contents of the bucket are the
|
|
** element pointed to plus the next _ht.count-1 elements in the list.
|
|
**
|
|
** Hash.htsize and Hash.ht may be zero. In that case lookup is done
|
|
** by a linear search of the global list. For small tables, the
|
|
** Hash.ht table is never allocated because if there are few elements
|
|
** in the table, it is faster to do a linear search than to manage
|
|
** the hash table.
|
|
*/
|
|
struct Hash {
|
|
unsigned int htsize; /* Number of buckets in the hash table */
|
|
unsigned int count; /* Number of entries in this table */
|
|
HashElem *first; /* The first element of the array */
|
|
struct _ht { /* the hash table */
|
|
unsigned 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 */
|
|
const char *pKey; /* Key associated with this element */
|
|
};
|
|
|
|
/*
|
|
** Access routines. To delete, insert a NULL pointer.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3HashInit(Hash*);
|
|
SQLITE_PRIVATE void *sqlite3HashInsert(Hash*, const char *pKey, void *pData);
|
|
SQLITE_PRIVATE void *sqlite3HashFind(const Hash*, const char *pKey);
|
|
SQLITE_PRIVATE 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) // NOT USED */
|
|
/* #define sqliteHashKeysize(E) ((E)->nKey) // NOT USED */
|
|
|
|
/*
|
|
** Number of entries in a hash table
|
|
*/
|
|
#define sqliteHashCount(H) ((H)->count)
|
|
|
|
#endif /* SQLITE_HASH_H */
|
|
|
|
/************** End of hash.h ************************************************/
|
|
/************** Continuing where we left off in sqliteInt.h ******************/
|
|
/************** Include parse.h in the middle of sqliteInt.h *****************/
|
|
/************** Begin file parse.h *******************************************/
|
|
#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_SAVEPOINT 13
|
|
#define TK_RELEASE 14
|
|
#define TK_TO 15
|
|
#define TK_TABLE 16
|
|
#define TK_CREATE 17
|
|
#define TK_IF 18
|
|
#define TK_NOT 19
|
|
#define TK_EXISTS 20
|
|
#define TK_TEMP 21
|
|
#define TK_LP 22
|
|
#define TK_RP 23
|
|
#define TK_AS 24
|
|
#define TK_COMMA 25
|
|
#define TK_WITHOUT 26
|
|
#define TK_ABORT 27
|
|
#define TK_ACTION 28
|
|
#define TK_AFTER 29
|
|
#define TK_ANALYZE 30
|
|
#define TK_ASC 31
|
|
#define TK_ATTACH 32
|
|
#define TK_BEFORE 33
|
|
#define TK_BY 34
|
|
#define TK_CASCADE 35
|
|
#define TK_CAST 36
|
|
#define TK_CONFLICT 37
|
|
#define TK_DATABASE 38
|
|
#define TK_DESC 39
|
|
#define TK_DETACH 40
|
|
#define TK_EACH 41
|
|
#define TK_FAIL 42
|
|
#define TK_OR 43
|
|
#define TK_AND 44
|
|
#define TK_IS 45
|
|
#define TK_MATCH 46
|
|
#define TK_LIKE_KW 47
|
|
#define TK_BETWEEN 48
|
|
#define TK_IN 49
|
|
#define TK_ISNULL 50
|
|
#define TK_NOTNULL 51
|
|
#define TK_NE 52
|
|
#define TK_EQ 53
|
|
#define TK_GT 54
|
|
#define TK_LE 55
|
|
#define TK_LT 56
|
|
#define TK_GE 57
|
|
#define TK_ESCAPE 58
|
|
#define TK_ID 59
|
|
#define TK_COLUMNKW 60
|
|
#define TK_DO 61
|
|
#define TK_FOR 62
|
|
#define TK_IGNORE 63
|
|
#define TK_INITIALLY 64
|
|
#define TK_INSTEAD 65
|
|
#define TK_NO 66
|
|
#define TK_KEY 67
|
|
#define TK_OF 68
|
|
#define TK_OFFSET 69
|
|
#define TK_PRAGMA 70
|
|
#define TK_RAISE 71
|
|
#define TK_RECURSIVE 72
|
|
#define TK_REPLACE 73
|
|
#define TK_RESTRICT 74
|
|
#define TK_ROW 75
|
|
#define TK_ROWS 76
|
|
#define TK_TRIGGER 77
|
|
#define TK_VACUUM 78
|
|
#define TK_VIEW 79
|
|
#define TK_VIRTUAL 80
|
|
#define TK_WITH 81
|
|
#define TK_NULLS 82
|
|
#define TK_FIRST 83
|
|
#define TK_LAST 84
|
|
#define TK_CURRENT 85
|
|
#define TK_FOLLOWING 86
|
|
#define TK_PARTITION 87
|
|
#define TK_PRECEDING 88
|
|
#define TK_RANGE 89
|
|
#define TK_UNBOUNDED 90
|
|
#define TK_EXCLUDE 91
|
|
#define TK_GROUPS 92
|
|
#define TK_OTHERS 93
|
|
#define TK_TIES 94
|
|
#define TK_GENERATED 95
|
|
#define TK_ALWAYS 96
|
|
#define TK_MATERIALIZED 97
|
|
#define TK_REINDEX 98
|
|
#define TK_RENAME 99
|
|
#define TK_CTIME_KW 100
|
|
#define TK_ANY 101
|
|
#define TK_BITAND 102
|
|
#define TK_BITOR 103
|
|
#define TK_LSHIFT 104
|
|
#define TK_RSHIFT 105
|
|
#define TK_PLUS 106
|
|
#define TK_MINUS 107
|
|
#define TK_STAR 108
|
|
#define TK_SLASH 109
|
|
#define TK_REM 110
|
|
#define TK_CONCAT 111
|
|
#define TK_PTR 112
|
|
#define TK_COLLATE 113
|
|
#define TK_BITNOT 114
|
|
#define TK_ON 115
|
|
#define TK_INDEXED 116
|
|
#define TK_STRING 117
|
|
#define TK_JOIN_KW 118
|
|
#define TK_CONSTRAINT 119
|
|
#define TK_DEFAULT 120
|
|
#define TK_NULL 121
|
|
#define TK_PRIMARY 122
|
|
#define TK_UNIQUE 123
|
|
#define TK_CHECK 124
|
|
#define TK_REFERENCES 125
|
|
#define TK_AUTOINCR 126
|
|
#define TK_INSERT 127
|
|
#define TK_DELETE 128
|
|
#define TK_UPDATE 129
|
|
#define TK_SET 130
|
|
#define TK_DEFERRABLE 131
|
|
#define TK_FOREIGN 132
|
|
#define TK_DROP 133
|
|
#define TK_UNION 134
|
|
#define TK_ALL 135
|
|
#define TK_EXCEPT 136
|
|
#define TK_INTERSECT 137
|
|
#define TK_SELECT 138
|
|
#define TK_VALUES 139
|
|
#define TK_DISTINCT 140
|
|
#define TK_DOT 141
|
|
#define TK_FROM 142
|
|
#define TK_JOIN 143
|
|
#define TK_USING 144
|
|
#define TK_ORDER 145
|
|
#define TK_GROUP 146
|
|
#define TK_HAVING 147
|
|
#define TK_LIMIT 148
|
|
#define TK_WHERE 149
|
|
#define TK_RETURNING 150
|
|
#define TK_INTO 151
|
|
#define TK_NOTHING 152
|
|
#define TK_FLOAT 153
|
|
#define TK_BLOB 154
|
|
#define TK_INTEGER 155
|
|
#define TK_VARIABLE 156
|
|
#define TK_CASE 157
|
|
#define TK_WHEN 158
|
|
#define TK_THEN 159
|
|
#define TK_ELSE 160
|
|
#define TK_INDEX 161
|
|
#define TK_ALTER 162
|
|
#define TK_ADD 163
|
|
#define TK_WINDOW 164
|
|
#define TK_OVER 165
|
|
#define TK_FILTER 166
|
|
#define TK_COLUMN 167
|
|
#define TK_AGG_FUNCTION 168
|
|
#define TK_AGG_COLUMN 169
|
|
#define TK_TRUEFALSE 170
|
|
#define TK_ISNOT 171
|
|
#define TK_FUNCTION 172
|
|
#define TK_UMINUS 173
|
|
#define TK_UPLUS 174
|
|
#define TK_TRUTH 175
|
|
#define TK_REGISTER 176
|
|
#define TK_VECTOR 177
|
|
#define TK_SELECT_COLUMN 178
|
|
#define TK_IF_NULL_ROW 179
|
|
#define TK_ASTERISK 180
|
|
#define TK_SPAN 181
|
|
#define TK_ERROR 182
|
|
#define TK_SPACE 183
|
|
#define TK_ILLEGAL 184
|
|
|
|
/************** End of parse.h ***********************************************/
|
|
/************** Continuing where we left off in sqliteInt.h ******************/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#include <stddef.h>
|
|
|
|
/*
|
|
** Use a macro to replace memcpy() if compiled with SQLITE_INLINE_MEMCPY.
|
|
** This allows better measurements of where memcpy() is used when running
|
|
** cachegrind. But this macro version of memcpy() is very slow so it
|
|
** should not be used in production. This is a performance measurement
|
|
** hack only.
|
|
*/
|
|
#ifdef SQLITE_INLINE_MEMCPY
|
|
# define memcpy(D,S,N) {char*xxd=(char*)(D);const char*xxs=(const char*)(S);\
|
|
int xxn=(N);while(xxn-->0)*(xxd++)=*(xxs++);}
|
|
#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
|
|
# define float sqlite_int64
|
|
# define LONGDOUBLE_TYPE sqlite_int64
|
|
# ifndef SQLITE_BIG_DBL
|
|
# define SQLITE_BIG_DBL (((sqlite3_int64)1)<<50)
|
|
# endif
|
|
# define SQLITE_OMIT_DATETIME_FUNCS 1
|
|
# define SQLITE_OMIT_TRACE 1
|
|
# undef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
|
|
# undef SQLITE_HAVE_ISNAN
|
|
#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
|
|
|
|
/*
|
|
** 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 4
|
|
#endif
|
|
|
|
/*
|
|
** Determine whether triggers are recursive by default. This can be
|
|
** changed at run-time using a pragma.
|
|
*/
|
|
#ifndef SQLITE_DEFAULT_RECURSIVE_TRIGGERS
|
|
# define SQLITE_DEFAULT_RECURSIVE_TRIGGERS 0
|
|
#endif
|
|
|
|
/*
|
|
** Provide a default value for SQLITE_TEMP_STORE in case it is not specified
|
|
** on the command-line
|
|
*/
|
|
#ifndef SQLITE_TEMP_STORE
|
|
# define SQLITE_TEMP_STORE 1
|
|
#endif
|
|
|
|
/*
|
|
** If no value has been provided for SQLITE_MAX_WORKER_THREADS, or if
|
|
** SQLITE_TEMP_STORE is set to 3 (never use temporary files), set it
|
|
** to zero.
|
|
*/
|
|
#if SQLITE_TEMP_STORE==3 || SQLITE_THREADSAFE==0
|
|
# undef SQLITE_MAX_WORKER_THREADS
|
|
# define SQLITE_MAX_WORKER_THREADS 0
|
|
#endif
|
|
#ifndef SQLITE_MAX_WORKER_THREADS
|
|
# define SQLITE_MAX_WORKER_THREADS 8
|
|
#endif
|
|
#ifndef SQLITE_DEFAULT_WORKER_THREADS
|
|
# define SQLITE_DEFAULT_WORKER_THREADS 0
|
|
#endif
|
|
#if SQLITE_DEFAULT_WORKER_THREADS>SQLITE_MAX_WORKER_THREADS
|
|
# undef SQLITE_MAX_WORKER_THREADS
|
|
# define SQLITE_MAX_WORKER_THREADS SQLITE_DEFAULT_WORKER_THREADS
|
|
#endif
|
|
|
|
/*
|
|
** The default initial allocation for the pagecache when using separate
|
|
** pagecaches for each database connection. A positive number is the
|
|
** number of pages. A negative number N translations means that a buffer
|
|
** of -1024*N bytes is allocated and used for as many pages as it will hold.
|
|
**
|
|
** The default value of "20" was chosen to minimize the run-time of the
|
|
** speedtest1 test program with options: --shrink-memory --reprepare
|
|
*/
|
|
#ifndef SQLITE_DEFAULT_PCACHE_INITSZ
|
|
# define SQLITE_DEFAULT_PCACHE_INITSZ 20
|
|
#endif
|
|
|
|
/*
|
|
** Default value for the SQLITE_CONFIG_SORTERREF_SIZE option.
|
|
*/
|
|
#ifndef SQLITE_DEFAULT_SORTERREF_SIZE
|
|
# define SQLITE_DEFAULT_SORTERREF_SIZE 0x7fffffff
|
|
#endif
|
|
|
|
/*
|
|
** The compile-time options SQLITE_MMAP_READWRITE and
|
|
** SQLITE_ENABLE_BATCH_ATOMIC_WRITE are not compatible with one another.
|
|
** You must choose one or the other (or neither) but not both.
|
|
*/
|
|
#if defined(SQLITE_MMAP_READWRITE) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
|
|
#error Cannot use both SQLITE_MMAP_READWRITE and SQLITE_ENABLE_BATCH_ATOMIC_WRITE
|
|
#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
|
|
|
|
/*
|
|
** Macros to compute minimum and maximum of two numbers.
|
|
*/
|
|
#ifndef MIN
|
|
# define MIN(A,B) ((A)<(B)?(A):(B))
|
|
#endif
|
|
#ifndef MAX
|
|
# define MAX(A,B) ((A)>(B)?(A):(B))
|
|
#endif
|
|
|
|
/*
|
|
** Swap two objects of type TYPE.
|
|
*/
|
|
#define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;}
|
|
|
|
/*
|
|
** 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
|
|
# ifdef HAVE_UINT32_T
|
|
# define UINT32_TYPE uint32_t
|
|
# else
|
|
# define UINT32_TYPE unsigned int
|
|
# endif
|
|
#endif
|
|
#ifndef UINT16_TYPE
|
|
# ifdef HAVE_UINT16_T
|
|
# define UINT16_TYPE uint16_t
|
|
# else
|
|
# define UINT16_TYPE unsigned short int
|
|
# endif
|
|
#endif
|
|
#ifndef INT16_TYPE
|
|
# ifdef HAVE_INT16_T
|
|
# define INT16_TYPE int16_t
|
|
# else
|
|
# define INT16_TYPE short int
|
|
# endif
|
|
#endif
|
|
#ifndef UINT8_TYPE
|
|
# ifdef HAVE_UINT8_T
|
|
# define UINT8_TYPE uint8_t
|
|
# else
|
|
# define UINT8_TYPE unsigned char
|
|
# endif
|
|
#endif
|
|
#ifndef INT8_TYPE
|
|
# ifdef HAVE_INT8_T
|
|
# define INT8_TYPE int8_t
|
|
# else
|
|
# define INT8_TYPE signed char
|
|
# endif
|
|
#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 INT8_TYPE i8; /* 1-byte signed integer */
|
|
|
|
/*
|
|
** SQLITE_MAX_U32 is a u64 constant that is the maximum u64 value
|
|
** that can be stored in a u32 without loss of data. The value
|
|
** is 0x00000000ffffffff. But because of quirks of some compilers, we
|
|
** have to specify the value in the less intuitive manner shown:
|
|
*/
|
|
#define SQLITE_MAX_U32 ((((u64)1)<<32)-1)
|
|
|
|
/*
|
|
** The datatype used to store estimates of the number of rows in a
|
|
** table or index.
|
|
*/
|
|
typedef u64 tRowcnt;
|
|
|
|
/*
|
|
** Estimated quantities used for query planning are stored as 16-bit
|
|
** logarithms. For quantity X, the value stored is 10*log2(X). This
|
|
** gives a possible range of values of approximately 1.0e986 to 1e-986.
|
|
** But the allowed values are "grainy". Not every value is representable.
|
|
** For example, quantities 16 and 17 are both represented by a LogEst
|
|
** of 40. However, since LogEst quantities are suppose to be estimates,
|
|
** not exact values, this imprecision is not a problem.
|
|
**
|
|
** "LogEst" is short for "Logarithmic Estimate".
|
|
**
|
|
** Examples:
|
|
** 1 -> 0 20 -> 43 10000 -> 132
|
|
** 2 -> 10 25 -> 46 25000 -> 146
|
|
** 3 -> 16 100 -> 66 1000000 -> 199
|
|
** 4 -> 20 1000 -> 99 1048576 -> 200
|
|
** 10 -> 33 1024 -> 100 4294967296 -> 320
|
|
**
|
|
** The LogEst can be negative to indicate fractional values.
|
|
** Examples:
|
|
**
|
|
** 0.5 -> -10 0.1 -> -33 0.0625 -> -40
|
|
*/
|
|
typedef INT16_TYPE LogEst;
|
|
|
|
/*
|
|
** Set the SQLITE_PTRSIZE macro to the number of bytes in a pointer
|
|
*/
|
|
#ifndef SQLITE_PTRSIZE
|
|
# if defined(__SIZEOF_POINTER__)
|
|
# define SQLITE_PTRSIZE __SIZEOF_POINTER__
|
|
# elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \
|
|
defined(_M_ARM) || defined(__arm__) || defined(__x86) || \
|
|
(defined(__APPLE__) && defined(__POWERPC__)) || \
|
|
(defined(__TOS_AIX__) && !defined(__64BIT__))
|
|
# define SQLITE_PTRSIZE 4
|
|
# else
|
|
# define SQLITE_PTRSIZE 8
|
|
# endif
|
|
#endif
|
|
|
|
/* The uptr type is an unsigned integer large enough to hold a pointer
|
|
*/
|
|
#if defined(HAVE_STDINT_H)
|
|
typedef uintptr_t uptr;
|
|
#elif SQLITE_PTRSIZE==4
|
|
typedef u32 uptr;
|
|
#else
|
|
typedef u64 uptr;
|
|
#endif
|
|
|
|
/*
|
|
** The SQLITE_WITHIN(P,S,E) macro checks to see if pointer P points to
|
|
** something between S (inclusive) and E (exclusive).
|
|
**
|
|
** In other words, S is a buffer and E is a pointer to the first byte after
|
|
** the end of buffer S. This macro returns true if P points to something
|
|
** contained within the buffer S.
|
|
*/
|
|
#define SQLITE_WITHIN(P,S,E) (((uptr)(P)>=(uptr)(S))&&((uptr)(P)<(uptr)(E)))
|
|
|
|
/*
|
|
** P is one byte past the end of a large buffer. Return true if a span of bytes
|
|
** between S..E crosses the end of that buffer. In other words, return true
|
|
** if the sub-buffer S..E-1 overflows the buffer whose last byte is P-1.
|
|
**
|
|
** S is the start of the span. E is one byte past the end of end of span.
|
|
**
|
|
** P
|
|
** |-----------------| FALSE
|
|
** |-------|
|
|
** S E
|
|
**
|
|
** P
|
|
** |-----------------|
|
|
** |-------| TRUE
|
|
** S E
|
|
**
|
|
** P
|
|
** |-----------------|
|
|
** |-------| FALSE
|
|
** S E
|
|
*/
|
|
#define SQLITE_OVERFLOW(P,S,E) (((uptr)(S)<(uptr)(P))&&((uptr)(E)>(uptr)(P)))
|
|
|
|
/*
|
|
** Macros to determine whether the machine is big or little endian,
|
|
** and whether or not that determination is run-time or compile-time.
|
|
**
|
|
** For best performance, an attempt is made to guess at the byte-order
|
|
** using C-preprocessor macros. If that is unsuccessful, or if
|
|
** -DSQLITE_BYTEORDER=0 is set, then byte-order is determined
|
|
** at run-time.
|
|
**
|
|
** If you are building SQLite on some obscure platform for which the
|
|
** following ifdef magic does not work, you can always include either:
|
|
**
|
|
** -DSQLITE_BYTEORDER=1234
|
|
**
|
|
** or
|
|
**
|
|
** -DSQLITE_BYTEORDER=4321
|
|
**
|
|
** to cause the build to work for little-endian or big-endian processors,
|
|
** respectively.
|
|
*/
|
|
#ifndef SQLITE_BYTEORDER /* Replicate changes at tag-20230904a */
|
|
# if defined(__BYTE_ORDER__) && __BYTE_ORDER__==__ORDER_BIG_ENDIAN__
|
|
# define SQLITE_BYTEORDER 4321
|
|
# elif defined(__BYTE_ORDER__) && __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
|
|
# define SQLITE_BYTEORDER 1234
|
|
# elif defined(__BIG_ENDIAN__) && __BIG_ENDIAN__==1
|
|
# define SQLITE_BYTEORDER 4321
|
|
# elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \
|
|
defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
|
|
defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
|
|
defined(__ARMEL__) || defined(__AARCH64EL__) || defined(_M_ARM64)
|
|
# define SQLITE_BYTEORDER 1234
|
|
# elif defined(sparc) || defined(__ARMEB__) || defined(__AARCH64EB__)
|
|
# define SQLITE_BYTEORDER 4321
|
|
# else
|
|
# define SQLITE_BYTEORDER 0
|
|
# endif
|
|
#endif
|
|
#if SQLITE_BYTEORDER==4321
|
|
# define SQLITE_BIGENDIAN 1
|
|
# define SQLITE_LITTLEENDIAN 0
|
|
# define SQLITE_UTF16NATIVE SQLITE_UTF16BE
|
|
#elif SQLITE_BYTEORDER==1234
|
|
# define SQLITE_BIGENDIAN 0
|
|
# define SQLITE_LITTLEENDIAN 1
|
|
# define SQLITE_UTF16NATIVE SQLITE_UTF16LE
|
|
#else
|
|
# ifdef SQLITE_AMALGAMATION
|
|
const int sqlite3one = 1;
|
|
# else
|
|
extern const int sqlite3one;
|
|
# endif
|
|
# define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0)
|
|
# define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1)
|
|
# define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE)
|
|
#endif
|
|
|
|
/*
|
|
** Constants for the largest and smallest possible 64-bit signed integers.
|
|
** These macros are designed to work correctly on both 32-bit and 64-bit
|
|
** compilers.
|
|
*/
|
|
#define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32))
|
|
#define LARGEST_UINT64 (0xffffffff|(((u64)0xffffffff)<<32))
|
|
#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)
|
|
|
|
/*
|
|
** Round up a number to the next larger multiple of 8. This is used
|
|
** to force 8-byte alignment on 64-bit architectures.
|
|
**
|
|
** ROUND8() always does the rounding, for any argument.
|
|
**
|
|
** ROUND8P() assumes that the argument is already an integer number of
|
|
** pointers in size, and so it is a no-op on systems where the pointer
|
|
** size is 8.
|
|
*/
|
|
#define ROUND8(x) (((x)+7)&~7)
|
|
#if SQLITE_PTRSIZE==8
|
|
# define ROUND8P(x) (x)
|
|
#else
|
|
# define ROUND8P(x) (((x)+7)&~7)
|
|
#endif
|
|
|
|
/*
|
|
** Round down to the nearest multiple of 8
|
|
*/
|
|
#define ROUNDDOWN8(x) ((x)&~7)
|
|
|
|
/*
|
|
** Assert that the pointer X is aligned to an 8-byte boundary. This
|
|
** macro is used only within assert() to verify that the code gets
|
|
** all alignment restrictions correct.
|
|
**
|
|
** Except, if SQLITE_4_BYTE_ALIGNED_MALLOC is defined, then the
|
|
** underlying malloc() implementation might return us 4-byte aligned
|
|
** pointers. In that case, only verify 4-byte alignment.
|
|
*/
|
|
#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
|
|
# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&3)==0)
|
|
#else
|
|
# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&7)==0)
|
|
#endif
|
|
|
|
/*
|
|
** Disable MMAP on platforms where it is known to not work
|
|
*/
|
|
#if defined(__OpenBSD__) || defined(__QNXNTO__)
|
|
# undef SQLITE_MAX_MMAP_SIZE
|
|
# define SQLITE_MAX_MMAP_SIZE 0
|
|
#endif
|
|
|
|
/*
|
|
** Default maximum size of memory used by memory-mapped I/O in the VFS
|
|
*/
|
|
#ifdef __APPLE__
|
|
# include <TargetConditionals.h>
|
|
#endif
|
|
#ifndef SQLITE_MAX_MMAP_SIZE
|
|
# if defined(__linux__) \
|
|
|| defined(_WIN32) \
|
|
|| (defined(__APPLE__) && defined(__MACH__)) \
|
|
|| defined(__sun) \
|
|
|| defined(__FreeBSD__) \
|
|
|| defined(__DragonFly__)
|
|
# define SQLITE_MAX_MMAP_SIZE 0x7fff0000 /* 2147418112 */
|
|
# else
|
|
# define SQLITE_MAX_MMAP_SIZE 0
|
|
# endif
|
|
#endif
|
|
|
|
/*
|
|
** The default MMAP_SIZE is zero on all platforms. Or, even if a larger
|
|
** default MMAP_SIZE is specified at compile-time, make sure that it does
|
|
** not exceed the maximum mmap size.
|
|
*/
|
|
#ifndef SQLITE_DEFAULT_MMAP_SIZE
|
|
# define SQLITE_DEFAULT_MMAP_SIZE 0
|
|
#endif
|
|
#if SQLITE_DEFAULT_MMAP_SIZE>SQLITE_MAX_MMAP_SIZE
|
|
# undef SQLITE_DEFAULT_MMAP_SIZE
|
|
# define SQLITE_DEFAULT_MMAP_SIZE SQLITE_MAX_MMAP_SIZE
|
|
#endif
|
|
|
|
/*
|
|
** TREETRACE_ENABLED will be either 1 or 0 depending on whether or not
|
|
** the Abstract Syntax Tree tracing logic is turned on.
|
|
*/
|
|
#if !defined(SQLITE_AMALGAMATION)
|
|
SQLITE_PRIVATE u32 sqlite3TreeTrace;
|
|
#endif
|
|
#if defined(SQLITE_DEBUG) \
|
|
&& (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_SELECTTRACE) \
|
|
|| defined(SQLITE_ENABLE_TREETRACE))
|
|
# define TREETRACE_ENABLED 1
|
|
# define TREETRACE(K,P,S,X) \
|
|
if(sqlite3TreeTrace&(K)) \
|
|
sqlite3DebugPrintf("%u/%d/%p: ",(S)->selId,(P)->addrExplain,(S)),\
|
|
sqlite3DebugPrintf X
|
|
#else
|
|
# define TREETRACE(K,P,S,X)
|
|
# define TREETRACE_ENABLED 0
|
|
#endif
|
|
|
|
/* TREETRACE flag meanings:
|
|
**
|
|
** 0x00000001 Beginning and end of SELECT processing
|
|
** 0x00000002 WHERE clause processing
|
|
** 0x00000004 Query flattener
|
|
** 0x00000008 Result-set wildcard expansion
|
|
** 0x00000010 Query name resolution
|
|
** 0x00000020 Aggregate analysis
|
|
** 0x00000040 Window functions
|
|
** 0x00000080 Generated column names
|
|
** 0x00000100 Move HAVING terms into WHERE
|
|
** 0x00000200 Count-of-view optimization
|
|
** 0x00000400 Compound SELECT processing
|
|
** 0x00000800 Drop superfluous ORDER BY
|
|
** 0x00001000 LEFT JOIN simplifies to JOIN
|
|
** 0x00002000 Constant propagation
|
|
** 0x00004000 Push-down optimization
|
|
** 0x00008000 After all FROM-clause analysis
|
|
** 0x00010000 Beginning of DELETE/INSERT/UPDATE processing
|
|
** 0x00020000 Transform DISTINCT into GROUP BY
|
|
** 0x00040000 SELECT tree dump after all code has been generated
|
|
** 0x00080000 NOT NULL strength reduction
|
|
*/
|
|
|
|
/*
|
|
** Macros for "wheretrace"
|
|
*/
|
|
SQLITE_PRIVATE u32 sqlite3WhereTrace;
|
|
#if defined(SQLITE_DEBUG) \
|
|
&& (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
|
|
# define WHERETRACE(K,X) if(sqlite3WhereTrace&(K)) sqlite3DebugPrintf X
|
|
# define WHERETRACE_ENABLED 1
|
|
#else
|
|
# define WHERETRACE(K,X)
|
|
#endif
|
|
|
|
/*
|
|
** Bits for the sqlite3WhereTrace mask:
|
|
**
|
|
** (---any--) Top-level block structure
|
|
** 0x-------F High-level debug messages
|
|
** 0x----FFF- More detail
|
|
** 0xFFFF---- Low-level debug messages
|
|
**
|
|
** 0x00000001 Code generation
|
|
** 0x00000002 Solver
|
|
** 0x00000004 Solver costs
|
|
** 0x00000008 WhereLoop inserts
|
|
**
|
|
** 0x00000010 Display sqlite3_index_info xBestIndex calls
|
|
** 0x00000020 Range an equality scan metrics
|
|
** 0x00000040 IN operator decisions
|
|
** 0x00000080 WhereLoop cost adjustements
|
|
** 0x00000100
|
|
** 0x00000200 Covering index decisions
|
|
** 0x00000400 OR optimization
|
|
** 0x00000800 Index scanner
|
|
** 0x00001000 More details associated with code generation
|
|
** 0x00002000
|
|
** 0x00004000 Show all WHERE terms at key points
|
|
** 0x00008000 Show the full SELECT statement at key places
|
|
**
|
|
** 0x00010000 Show more detail when printing WHERE terms
|
|
** 0x00020000 Show WHERE terms returned from whereScanNext()
|
|
*/
|
|
|
|
|
|
/*
|
|
** 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 (*xBusyHandler)(void *,int); /* The busy callback */
|
|
void *pBusyArg; /* First arg to busy callback */
|
|
int nBusy; /* Incremented with each busy call */
|
|
};
|
|
|
|
/*
|
|
** Name of table that holds the database schema.
|
|
**
|
|
** The PREFERRED names are used wherever possible. But LEGACY is also
|
|
** used for backwards compatibility.
|
|
**
|
|
** 1. Queries can use either the PREFERRED or the LEGACY names
|
|
** 2. The sqlite3_set_authorizer() callback uses the LEGACY name
|
|
** 3. The PRAGMA table_list statement uses the PREFERRED name
|
|
**
|
|
** The LEGACY names are stored in the internal symbol hash table
|
|
** in support of (2). Names are translated using sqlite3PreferredTableName()
|
|
** for (3). The sqlite3FindTable() function takes care of translating
|
|
** names for (1).
|
|
**
|
|
** Note that "sqlite_temp_schema" can also be called "temp.sqlite_schema".
|
|
*/
|
|
#define LEGACY_SCHEMA_TABLE "sqlite_master"
|
|
#define LEGACY_TEMP_SCHEMA_TABLE "sqlite_temp_master"
|
|
#define PREFERRED_SCHEMA_TABLE "sqlite_schema"
|
|
#define PREFERRED_TEMP_SCHEMA_TABLE "sqlite_temp_schema"
|
|
|
|
|
|
/*
|
|
** The root-page of the schema table.
|
|
*/
|
|
#define SCHEMA_ROOT 1
|
|
|
|
/*
|
|
** The name of the schema table. The name is different for TEMP.
|
|
*/
|
|
#define SCHEMA_TABLE(x) \
|
|
((!OMIT_TEMPDB)&&(x==1)?LEGACY_TEMP_SCHEMA_TABLE:LEGACY_SCHEMA_TABLE)
|
|
|
|
/*
|
|
** A convenience macro that returns the number of elements in
|
|
** an array.
|
|
*/
|
|
#define ArraySize(X) ((int)(sizeof(X)/sizeof(X[0])))
|
|
|
|
/*
|
|
** Determine if the argument is a power of two
|
|
*/
|
|
#define IsPowerOfTwo(X) (((X)&((X)-1))==0)
|
|
|
|
/*
|
|
** The following value as a destructor means to use sqlite3DbFree().
|
|
** The sqlite3DbFree() routine requires two parameters instead of the
|
|
** one parameter that destructors normally want. So we have to introduce
|
|
** this magic value that the code knows to handle differently. Any
|
|
** pointer will work here as long as it is distinct from SQLITE_STATIC
|
|
** and SQLITE_TRANSIENT.
|
|
*/
|
|
#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3OomClear)
|
|
|
|
/*
|
|
** When SQLITE_OMIT_WSD is defined, it means that the target platform does
|
|
** not support Writable Static Data (WSD) such as global and static variables.
|
|
** All variables must either be on the stack or dynamically allocated from
|
|
** the heap. When WSD is unsupported, the variable declarations scattered
|
|
** throughout the SQLite code must become constants instead. The SQLITE_WSD
|
|
** macro is used for this purpose. And instead of referencing the variable
|
|
** directly, we use its constant as a key to lookup the run-time allocated
|
|
** buffer that holds real variable. The constant is also the initializer
|
|
** for the run-time allocated buffer.
|
|
**
|
|
** In the usual case where WSD is supported, the SQLITE_WSD and GLOBAL
|
|
** macros become no-ops and have zero performance impact.
|
|
*/
|
|
#ifdef SQLITE_OMIT_WSD
|
|
#define SQLITE_WSD const
|
|
#define GLOBAL(t,v) (*(t*)sqlite3_wsd_find((void*)&(v), sizeof(v)))
|
|
#define sqlite3GlobalConfig GLOBAL(struct Sqlite3Config, sqlite3Config)
|
|
SQLITE_API int sqlite3_wsd_init(int N, int J);
|
|
SQLITE_API void *sqlite3_wsd_find(void *K, int L);
|
|
#else
|
|
#define SQLITE_WSD
|
|
#define GLOBAL(t,v) v
|
|
#define sqlite3GlobalConfig sqlite3Config
|
|
#endif
|
|
|
|
/*
|
|
** The following macros are used to suppress compiler warnings and to
|
|
** make it clear to human readers when a function parameter is deliberately
|
|
** left unused within the body of a function. This usually happens when
|
|
** a function is called via a function pointer. For example the
|
|
** implementation of an SQL aggregate step callback may not use the
|
|
** parameter indicating the number of arguments passed to the aggregate,
|
|
** if it knows that this is enforced elsewhere.
|
|
**
|
|
** When a function parameter is not used at all within the body of a function,
|
|
** it is generally named "NotUsed" or "NotUsed2" to make things even clearer.
|
|
** However, these macros may also be used to suppress warnings related to
|
|
** parameters that may or may not be used depending on compilation options.
|
|
** For example those parameters only used in assert() statements. In these
|
|
** cases the parameters are named as per the usual conventions.
|
|
*/
|
|
#define UNUSED_PARAMETER(x) (void)(x)
|
|
#define UNUSED_PARAMETER2(x,y) UNUSED_PARAMETER(x),UNUSED_PARAMETER(y)
|
|
|
|
/*
|
|
** Forward references to structures
|
|
*/
|
|
typedef struct AggInfo AggInfo;
|
|
typedef struct AuthContext AuthContext;
|
|
typedef struct AutoincInfo AutoincInfo;
|
|
typedef struct Bitvec Bitvec;
|
|
typedef struct CollSeq CollSeq;
|
|
typedef struct Column Column;
|
|
typedef struct Cte Cte;
|
|
typedef struct CteUse CteUse;
|
|
typedef struct Db Db;
|
|
typedef struct DbClientData DbClientData;
|
|
typedef struct DbFixer DbFixer;
|
|
typedef struct Schema Schema;
|
|
typedef struct Expr Expr;
|
|
typedef struct ExprList ExprList;
|
|
typedef struct FKey FKey;
|
|
typedef struct FpDecode FpDecode;
|
|
typedef struct FuncDestructor FuncDestructor;
|
|
typedef struct FuncDef FuncDef;
|
|
typedef struct FuncDefHash FuncDefHash;
|
|
typedef struct IdList IdList;
|
|
typedef struct Index Index;
|
|
typedef struct IndexedExpr IndexedExpr;
|
|
typedef struct IndexSample IndexSample;
|
|
typedef struct KeyClass KeyClass;
|
|
typedef struct KeyInfo KeyInfo;
|
|
typedef struct Lookaside Lookaside;
|
|
typedef struct LookasideSlot LookasideSlot;
|
|
typedef struct Module Module;
|
|
typedef struct NameContext NameContext;
|
|
typedef struct OnOrUsing OnOrUsing;
|
|
typedef struct Parse Parse;
|
|
typedef struct ParseCleanup ParseCleanup;
|
|
typedef struct PreUpdate PreUpdate;
|
|
typedef struct PrintfArguments PrintfArguments;
|
|
typedef struct RCStr RCStr;
|
|
typedef struct RenameToken RenameToken;
|
|
typedef struct Returning Returning;
|
|
typedef struct RowSet RowSet;
|
|
typedef struct Savepoint Savepoint;
|
|
typedef struct Select Select;
|
|
typedef struct SQLiteThread SQLiteThread;
|
|
typedef struct SelectDest SelectDest;
|
|
typedef struct SrcItem SrcItem;
|
|
typedef struct SrcList SrcList;
|
|
typedef struct sqlite3_str StrAccum; /* Internal alias for sqlite3_str */
|
|
typedef struct Table Table;
|
|
typedef struct TableLock TableLock;
|
|
typedef struct Token Token;
|
|
typedef struct TreeView TreeView;
|
|
typedef struct Trigger Trigger;
|
|
typedef struct TriggerPrg TriggerPrg;
|
|
typedef struct TriggerStep TriggerStep;
|
|
typedef struct UnpackedRecord UnpackedRecord;
|
|
typedef struct Upsert Upsert;
|
|
typedef struct VTable VTable;
|
|
typedef struct VtabCtx VtabCtx;
|
|
typedef struct Walker Walker;
|
|
typedef struct WhereInfo WhereInfo;
|
|
typedef struct Window Window;
|
|
typedef struct With With;
|
|
|
|
|
|
/*
|
|
** The bitmask datatype defined below is used for various optimizations.
|
|
**
|
|
** Changing this from a 64-bit to a 32-bit type limits the number of
|
|
** tables in a join to 32 instead of 64. But it also reduces the size
|
|
** of the library by 738 bytes on ix86.
|
|
*/
|
|
#ifdef SQLITE_BITMASK_TYPE
|
|
typedef SQLITE_BITMASK_TYPE Bitmask;
|
|
#else
|
|
typedef u64 Bitmask;
|
|
#endif
|
|
|
|
/*
|
|
** The number of bits in a Bitmask. "BMS" means "BitMask Size".
|
|
*/
|
|
#define BMS ((int)(sizeof(Bitmask)*8))
|
|
|
|
/*
|
|
** A bit in a Bitmask
|
|
*/
|
|
#define MASKBIT(n) (((Bitmask)1)<<(n))
|
|
#define MASKBIT64(n) (((u64)1)<<(n))
|
|
#define MASKBIT32(n) (((unsigned int)1)<<(n))
|
|
#define SMASKBIT32(n) ((n)<=31?((unsigned int)1)<<(n):0)
|
|
#define ALLBITS ((Bitmask)-1)
|
|
#define TOPBIT (((Bitmask)1)<<(BMS-1))
|
|
|
|
/* A VList object records a mapping between parameters/variables/wildcards
|
|
** in the SQL statement (such as $abc, @pqr, or :xyz) and the integer
|
|
** variable number associated with that parameter. See the format description
|
|
** on the sqlite3VListAdd() routine for more information. A VList is really
|
|
** just an array of integers.
|
|
*/
|
|
typedef int VList;
|
|
|
|
/*
|
|
** Defer sourcing vdbe.h and btree.h until after the "u8" and
|
|
** "BusyHandler" typedefs. vdbe.h also requires a few of the opaque
|
|
** pointer types (i.e. FuncDef) defined above.
|
|
*/
|
|
/************** Include os.h in the middle of sqliteInt.h ********************/
|
|
/************** Begin file os.h **********************************************/
|
|
/*
|
|
** 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.
|
|
**
|
|
** This header file is #include-ed by sqliteInt.h and thus ends up
|
|
** being included by every source file.
|
|
*/
|
|
#ifndef _SQLITE_OS_H_
|
|
#define _SQLITE_OS_H_
|
|
|
|
/*
|
|
** Attempt to automatically detect the operating system and setup the
|
|
** necessary pre-processor macros for it.
|
|
*/
|
|
/************** Include os_setup.h in the middle of os.h *********************/
|
|
/************** Begin file os_setup.h ****************************************/
|
|
/*
|
|
** 2013 November 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 pre-processor directives related to operating system
|
|
** detection and/or setup.
|
|
*/
|
|
#ifndef SQLITE_OS_SETUP_H
|
|
#define SQLITE_OS_SETUP_H
|
|
|
|
/*
|
|
** Figure out if we are dealing with Unix, Windows, or some other operating
|
|
** system.
|
|
**
|
|
** After the following block of preprocess macros, all of
|
|
**
|
|
** SQLITE_OS_KV
|
|
** SQLITE_OS_OTHER
|
|
** SQLITE_OS_UNIX
|
|
** SQLITE_OS_WIN
|
|
**
|
|
** will defined to either 1 or 0. One of them will be 1. The others will be 0.
|
|
** If none of the macros are initially defined, then select either
|
|
** SQLITE_OS_UNIX or SQLITE_OS_WIN depending on the target platform.
|
|
**
|
|
** If SQLITE_OS_OTHER=1 is specified at compile-time, then the application
|
|
** must provide its own VFS implementation together with sqlite3_os_init()
|
|
** and sqlite3_os_end() routines.
|
|
*/
|
|
#if !defined(SQLITE_OS_KV) && !defined(SQLITE_OS_OTHER) && \
|
|
!defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_WIN)
|
|
# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \
|
|
defined(__MINGW32__) || defined(__BORLANDC__)
|
|
# define SQLITE_OS_WIN 1
|
|
# define SQLITE_OS_UNIX 0
|
|
# else
|
|
# define SQLITE_OS_WIN 0
|
|
# define SQLITE_OS_UNIX 1
|
|
# endif
|
|
#endif
|
|
#if SQLITE_OS_OTHER+1>1
|
|
# undef SQLITE_OS_KV
|
|
# define SQLITE_OS_KV 0
|
|
# undef SQLITE_OS_UNIX
|
|
# define SQLITE_OS_UNIX 0
|
|
# undef SQLITE_OS_WIN
|
|
# define SQLITE_OS_WIN 0
|
|
#endif
|
|
#if SQLITE_OS_KV+1>1
|
|
# undef SQLITE_OS_OTHER
|
|
# define SQLITE_OS_OTHER 0
|
|
# undef SQLITE_OS_UNIX
|
|
# define SQLITE_OS_UNIX 0
|
|
# undef SQLITE_OS_WIN
|
|
# define SQLITE_OS_WIN 0
|
|
# define SQLITE_OMIT_LOAD_EXTENSION 1
|
|
# define SQLITE_OMIT_WAL 1
|
|
# define SQLITE_OMIT_DEPRECATED 1
|
|
# undef SQLITE_TEMP_STORE
|
|
# define SQLITE_TEMP_STORE 3 /* Always use memory for temporary storage */
|
|
# define SQLITE_DQS 0
|
|
# define SQLITE_OMIT_SHARED_CACHE 1
|
|
# define SQLITE_OMIT_AUTOINIT 1
|
|
#endif
|
|
#if SQLITE_OS_UNIX+1>1
|
|
# undef SQLITE_OS_KV
|
|
# define SQLITE_OS_KV 0
|
|
# undef SQLITE_OS_OTHER
|
|
# define SQLITE_OS_OTHER 0
|
|
# undef SQLITE_OS_WIN
|
|
# define SQLITE_OS_WIN 0
|
|
#endif
|
|
#if SQLITE_OS_WIN+1>1
|
|
# undef SQLITE_OS_KV
|
|
# define SQLITE_OS_KV 0
|
|
# undef SQLITE_OS_OTHER
|
|
# define SQLITE_OS_OTHER 0
|
|
# undef SQLITE_OS_UNIX
|
|
# define SQLITE_OS_UNIX 0
|
|
#endif
|
|
|
|
|
|
#endif /* SQLITE_OS_SETUP_H */
|
|
|
|
/************** End of os_setup.h ********************************************/
|
|
/************** Continuing where we left off in os.h *************************/
|
|
|
|
/* If the SET_FULLSYNC macro is not defined above, then make it
|
|
** a no-op
|
|
*/
|
|
#ifndef SET_FULLSYNC
|
|
# define SET_FULLSYNC(x,y)
|
|
#endif
|
|
|
|
/* Maximum pathname length. Note: FILENAME_MAX defined by stdio.h
|
|
*/
|
|
#ifndef SQLITE_MAX_PATHLEN
|
|
# define SQLITE_MAX_PATHLEN FILENAME_MAX
|
|
#endif
|
|
|
|
/* Maximum number of symlinks that will be resolved while trying to
|
|
** expand a filename in xFullPathname() in the VFS.
|
|
*/
|
|
#ifndef SQLITE_MAX_SYMLINK
|
|
# define SQLITE_MAX_SYMLINK 200
|
|
#endif
|
|
|
|
/*
|
|
** The default size of a disk sector
|
|
*/
|
|
#ifndef SQLITE_DEFAULT_SECTOR_SIZE
|
|
# define SQLITE_DEFAULT_SECTOR_SIZE 4096
|
|
#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 -DSQLITE_TEMP_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 SQLITE_TEMP_FILE_PREFIX
|
|
# define SQLITE_TEMP_FILE_PREFIX "etilqs_"
|
|
#endif
|
|
|
|
/*
|
|
** 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.
|
|
**
|
|
** The same locking strategy and
|
|
** byte ranges are used for Unix. This leaves open the possibility 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.
|
|
**
|
|
*/
|
|
#ifdef SQLITE_OMIT_WSD
|
|
# define PENDING_BYTE (0x40000000)
|
|
#else
|
|
# define PENDING_BYTE sqlite3PendingByte
|
|
#endif
|
|
#define RESERVED_BYTE (PENDING_BYTE+1)
|
|
#define SHARED_FIRST (PENDING_BYTE+2)
|
|
#define SHARED_SIZE 510
|
|
|
|
/*
|
|
** Wrapper around OS specific sqlite3_os_init() function.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3OsInit(void);
|
|
|
|
/*
|
|
** Functions for accessing sqlite3_file methods
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3OsClose(sqlite3_file*);
|
|
SQLITE_PRIVATE int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset);
|
|
SQLITE_PRIVATE int sqlite3OsWrite(sqlite3_file*, const void*, int amt, i64 offset);
|
|
SQLITE_PRIVATE int sqlite3OsTruncate(sqlite3_file*, i64 size);
|
|
SQLITE_PRIVATE int sqlite3OsSync(sqlite3_file*, int);
|
|
SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file*, i64 *pSize);
|
|
SQLITE_PRIVATE int sqlite3OsLock(sqlite3_file*, int);
|
|
SQLITE_PRIVATE int sqlite3OsUnlock(sqlite3_file*, int);
|
|
SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut);
|
|
SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file*,int,void*);
|
|
SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file*,int,void*);
|
|
#define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0
|
|
SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id);
|
|
SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id);
|
|
#ifndef SQLITE_OMIT_WAL
|
|
SQLITE_PRIVATE int sqlite3OsShmMap(sqlite3_file *,int,int,int,void volatile **);
|
|
SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int, int, int);
|
|
SQLITE_PRIVATE void sqlite3OsShmBarrier(sqlite3_file *id);
|
|
SQLITE_PRIVATE int sqlite3OsShmUnmap(sqlite3_file *id, int);
|
|
#endif /* SQLITE_OMIT_WAL */
|
|
SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64, int, void **);
|
|
SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *, i64, void *);
|
|
|
|
|
|
/*
|
|
** Functions for accessing sqlite3_vfs methods
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *);
|
|
SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *, const char *, int);
|
|
SQLITE_PRIVATE int sqlite3OsAccess(sqlite3_vfs *, const char *, int, int *pResOut);
|
|
SQLITE_PRIVATE int sqlite3OsFullPathname(sqlite3_vfs *, const char *, int, char *);
|
|
#ifndef SQLITE_OMIT_LOAD_EXTENSION
|
|
SQLITE_PRIVATE void *sqlite3OsDlOpen(sqlite3_vfs *, const char *);
|
|
SQLITE_PRIVATE void sqlite3OsDlError(sqlite3_vfs *, int, char *);
|
|
SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *, void *, const char *))(void);
|
|
SQLITE_PRIVATE void sqlite3OsDlClose(sqlite3_vfs *, void *);
|
|
#endif /* SQLITE_OMIT_LOAD_EXTENSION */
|
|
SQLITE_PRIVATE int sqlite3OsRandomness(sqlite3_vfs *, int, char *);
|
|
SQLITE_PRIVATE int sqlite3OsSleep(sqlite3_vfs *, int);
|
|
SQLITE_PRIVATE int sqlite3OsGetLastError(sqlite3_vfs*);
|
|
SQLITE_PRIVATE int sqlite3OsCurrentTimeInt64(sqlite3_vfs *, sqlite3_int64*);
|
|
|
|
/*
|
|
** Convenience functions for opening and closing files using
|
|
** sqlite3_malloc() to obtain space for the file-handle structure.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3OsOpenMalloc(sqlite3_vfs *, const char *, sqlite3_file **, int,int*);
|
|
SQLITE_PRIVATE void sqlite3OsCloseFree(sqlite3_file *);
|
|
|
|
#endif /* _SQLITE_OS_H_ */
|
|
|
|
/************** End of os.h **************************************************/
|
|
/************** Continuing where we left off in sqliteInt.h ******************/
|
|
/************** Include pager.h in the middle of sqliteInt.h *****************/
|
|
/************** Begin file pager.h *******************************************/
|
|
/*
|
|
** 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.
|
|
*/
|
|
|
|
#ifndef SQLITE_PAGER_H
|
|
#define SQLITE_PAGER_H
|
|
|
|
/*
|
|
** Default maximum size for persistent journal files. A negative
|
|
** value means no limit. This value may be overridden using the
|
|
** sqlite3PagerJournalSizeLimit() API. See also "PRAGMA journal_size_limit".
|
|
*/
|
|
#ifndef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT
|
|
#define SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT -1
|
|
#endif
|
|
|
|
/*
|
|
** 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 u32 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;
|
|
|
|
/*
|
|
** Page number PAGER_SJ_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 super-journal name - there are no more pages to
|
|
** roll back. See comments for function writeSuperJournal() in pager.c
|
|
** for details.
|
|
*/
|
|
#define PAGER_SJ_PGNO_COMPUTED(x) ((Pgno)((PENDING_BYTE/((x)->pageSize))+1))
|
|
#define PAGER_SJ_PGNO(x) ((x)->lckPgno)
|
|
|
|
/*
|
|
** Allowed values for the flags parameter to sqlite3PagerOpen().
|
|
**
|
|
** NOTE: These values must match the corresponding BTREE_ values in btree.h.
|
|
*/
|
|
#define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */
|
|
#define PAGER_MEMORY 0x0002 /* In-memory database */
|
|
|
|
/*
|
|
** Valid values for the second argument to sqlite3PagerLockingMode().
|
|
*/
|
|
#define PAGER_LOCKINGMODE_QUERY -1
|
|
#define PAGER_LOCKINGMODE_NORMAL 0
|
|
#define PAGER_LOCKINGMODE_EXCLUSIVE 1
|
|
|
|
/*
|
|
** Numeric constants that encode the journalmode.
|
|
**
|
|
** The numeric values encoded here (other than PAGER_JOURNALMODE_QUERY)
|
|
** are exposed in the API via the "PRAGMA journal_mode" command and
|
|
** therefore cannot be changed without a compatibility break.
|
|
*/
|
|
#define PAGER_JOURNALMODE_QUERY (-1) /* Query the value of journalmode */
|
|
#define PAGER_JOURNALMODE_DELETE 0 /* Commit by deleting journal file */
|
|
#define PAGER_JOURNALMODE_PERSIST 1 /* Commit by zeroing journal header */
|
|
#define PAGER_JOURNALMODE_OFF 2 /* Journal omitted. */
|
|
#define PAGER_JOURNALMODE_TRUNCATE 3 /* Commit by truncating journal */
|
|
#define PAGER_JOURNALMODE_MEMORY 4 /* In-memory journal file */
|
|
#define PAGER_JOURNALMODE_WAL 5 /* Use write-ahead logging */
|
|
|
|
/*
|
|
** Flags that make up the mask passed to sqlite3PagerGet().
|
|
*/
|
|
#define PAGER_GET_NOCONTENT 0x01 /* Do not load data from disk */
|
|
#define PAGER_GET_READONLY 0x02 /* Read-only page is acceptable */
|
|
|
|
/*
|
|
** Flags for sqlite3PagerSetFlags()
|
|
**
|
|
** Value constraints (enforced via assert()):
|
|
** PAGER_FULLFSYNC == SQLITE_FullFSync
|
|
** PAGER_CKPT_FULLFSYNC == SQLITE_CkptFullFSync
|
|
** PAGER_CACHE_SPILL == SQLITE_CacheSpill
|
|
*/
|
|
#define PAGER_SYNCHRONOUS_OFF 0x01 /* PRAGMA synchronous=OFF */
|
|
#define PAGER_SYNCHRONOUS_NORMAL 0x02 /* PRAGMA synchronous=NORMAL */
|
|
#define PAGER_SYNCHRONOUS_FULL 0x03 /* PRAGMA synchronous=FULL */
|
|
#define PAGER_SYNCHRONOUS_EXTRA 0x04 /* PRAGMA synchronous=EXTRA */
|
|
#define PAGER_SYNCHRONOUS_MASK 0x07 /* Mask for four values above */
|
|
#define PAGER_FULLFSYNC 0x08 /* PRAGMA fullfsync=ON */
|
|
#define PAGER_CKPT_FULLFSYNC 0x10 /* PRAGMA checkpoint_fullfsync=ON */
|
|
#define PAGER_CACHESPILL 0x20 /* PRAGMA cache_spill=ON */
|
|
#define PAGER_FLAGS_MASK 0x38 /* All above except SYNCHRONOUS */
|
|
|
|
/*
|
|
** The remainder of this file contains the declarations of the functions
|
|
** that make up the Pager sub-system API. See source code comments for
|
|
** a detailed description of each routine.
|
|
*/
|
|
|
|
/* Open and close a Pager connection. */
|
|
SQLITE_PRIVATE int sqlite3PagerOpen(
|
|
sqlite3_vfs*,
|
|
Pager **ppPager,
|
|
const char*,
|
|
int,
|
|
int,
|
|
int,
|
|
void(*)(DbPage*)
|
|
);
|
|
SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3*);
|
|
SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
|
|
|
|
/* Functions used to configure a Pager object. */
|
|
SQLITE_PRIVATE void sqlite3PagerSetBusyHandler(Pager*, int(*)(void *), void *);
|
|
SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int);
|
|
SQLITE_PRIVATE Pgno sqlite3PagerMaxPageCount(Pager*, Pgno);
|
|
SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager*, int);
|
|
SQLITE_PRIVATE int sqlite3PagerSetSpillsize(Pager*, int);
|
|
SQLITE_PRIVATE void sqlite3PagerSetMmapLimit(Pager *, sqlite3_int64);
|
|
SQLITE_PRIVATE void sqlite3PagerShrink(Pager*);
|
|
SQLITE_PRIVATE void sqlite3PagerSetFlags(Pager*,unsigned);
|
|
SQLITE_PRIVATE int sqlite3PagerLockingMode(Pager *, int);
|
|
SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *, int);
|
|
SQLITE_PRIVATE int sqlite3PagerGetJournalMode(Pager*);
|
|
SQLITE_PRIVATE int sqlite3PagerOkToChangeJournalMode(Pager*);
|
|
SQLITE_PRIVATE i64 sqlite3PagerJournalSizeLimit(Pager *, i64);
|
|
SQLITE_PRIVATE sqlite3_backup **sqlite3PagerBackupPtr(Pager*);
|
|
SQLITE_PRIVATE int sqlite3PagerFlush(Pager*);
|
|
|
|
/* Functions used to obtain and release page references. */
|
|
SQLITE_PRIVATE int sqlite3PagerGet(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag);
|
|
SQLITE_PRIVATE DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno);
|
|
SQLITE_PRIVATE void sqlite3PagerRef(DbPage*);
|
|
SQLITE_PRIVATE void sqlite3PagerUnref(DbPage*);
|
|
SQLITE_PRIVATE void sqlite3PagerUnrefNotNull(DbPage*);
|
|
SQLITE_PRIVATE void sqlite3PagerUnrefPageOne(DbPage*);
|
|
|
|
/* Operations on page references. */
|
|
SQLITE_PRIVATE int sqlite3PagerWrite(DbPage*);
|
|
SQLITE_PRIVATE void sqlite3PagerDontWrite(DbPage*);
|
|
SQLITE_PRIVATE int sqlite3PagerMovepage(Pager*,DbPage*,Pgno,int);
|
|
SQLITE_PRIVATE int sqlite3PagerPageRefcount(DbPage*);
|
|
SQLITE_PRIVATE void *sqlite3PagerGetData(DbPage *);
|
|
SQLITE_PRIVATE void *sqlite3PagerGetExtra(DbPage *);
|
|
|
|
/* Functions used to manage pager transactions and savepoints. */
|
|
SQLITE_PRIVATE void sqlite3PagerPagecount(Pager*, int*);
|
|
SQLITE_PRIVATE int sqlite3PagerBegin(Pager*, int exFlag, int);
|
|
SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(Pager*,const char *zSuper, int);
|
|
SQLITE_PRIVATE int sqlite3PagerExclusiveLock(Pager*);
|
|
SQLITE_PRIVATE int sqlite3PagerSync(Pager *pPager, const char *zSuper);
|
|
SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager*);
|
|
SQLITE_PRIVATE int sqlite3PagerRollback(Pager*);
|
|
SQLITE_PRIVATE int sqlite3PagerOpenSavepoint(Pager *pPager, int n);
|
|
SQLITE_PRIVATE int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint);
|
|
SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager);
|
|
|
|
#ifndef SQLITE_OMIT_WAL
|
|
SQLITE_PRIVATE int sqlite3PagerCheckpoint(Pager *pPager, sqlite3*, int, int*, int*);
|
|
SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager);
|
|
SQLITE_PRIVATE int sqlite3PagerWalCallback(Pager *pPager);
|
|
SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
|
|
SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3*);
|
|
# ifdef SQLITE_ENABLE_SNAPSHOT
|
|
SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager*, sqlite3_snapshot **ppSnapshot);
|
|
SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager*, sqlite3_snapshot *pSnapshot);
|
|
SQLITE_PRIVATE int sqlite3PagerSnapshotRecover(Pager *pPager);
|
|
SQLITE_PRIVATE int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pSnapshot);
|
|
SQLITE_PRIVATE void sqlite3PagerSnapshotUnlock(Pager *pPager);
|
|
# endif
|
|
#endif
|
|
|
|
#if !defined(SQLITE_OMIT_WAL) && defined(SQLITE_ENABLE_SETLK_TIMEOUT)
|
|
SQLITE_PRIVATE int sqlite3PagerWalWriteLock(Pager*, int);
|
|
SQLITE_PRIVATE void sqlite3PagerWalDb(Pager*, sqlite3*);
|
|
#else
|
|
# define sqlite3PagerWalWriteLock(y,z) SQLITE_OK
|
|
# define sqlite3PagerWalDb(x,y)
|
|
#endif
|
|
|
|
#ifdef SQLITE_DIRECT_OVERFLOW_READ
|
|
SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno);
|
|
#endif
|
|
|
|
#ifdef SQLITE_ENABLE_ZIPVFS
|
|
SQLITE_PRIVATE int sqlite3PagerWalFramesize(Pager *pPager);
|
|
#endif
|
|
|
|
/* Functions used to query pager state and configuration. */
|
|
SQLITE_PRIVATE u8 sqlite3PagerIsreadonly(Pager*);
|
|
SQLITE_PRIVATE u32 sqlite3PagerDataVersion(Pager*);
|
|
#ifdef SQLITE_DEBUG
|
|
SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*);
|
|
#endif
|
|
SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*);
|
|
SQLITE_PRIVATE const char *sqlite3PagerFilename(const Pager*, int);
|
|
SQLITE_PRIVATE sqlite3_vfs *sqlite3PagerVfs(Pager*);
|
|
SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*);
|
|
SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager*);
|
|
SQLITE_PRIVATE const char *sqlite3PagerJournalname(Pager*);
|
|
SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager*);
|
|
SQLITE_PRIVATE int sqlite3PagerIsMemdb(Pager*);
|
|
SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, u64*);
|
|
SQLITE_PRIVATE void sqlite3PagerClearCache(Pager*);
|
|
SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *);
|
|
|
|
/* Functions used to truncate the database file. */
|
|
SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno);
|
|
|
|
SQLITE_PRIVATE void sqlite3PagerRekey(DbPage*, Pgno, u16);
|
|
|
|
/* Functions to support testing and debugging. */
|
|
#if !defined(NDEBUG) || defined(SQLITE_TEST)
|
|
SQLITE_PRIVATE Pgno sqlite3PagerPagenumber(DbPage*);
|
|
SQLITE_PRIVATE int sqlite3PagerIswriteable(DbPage*);
|
|
#endif
|
|
#ifdef SQLITE_TEST
|
|
SQLITE_PRIVATE int *sqlite3PagerStats(Pager*);
|
|
SQLITE_PRIVATE void sqlite3PagerRefdump(Pager*);
|
|
void disable_simulated_io_errors(void);
|
|
void enable_simulated_io_errors(void);
|
|
#else
|
|
# define disable_simulated_io_errors()
|
|
# define enable_simulated_io_errors()
|
|
#endif
|
|
|
|
#if defined(SQLITE_USE_SEH) && !defined(SQLITE_OMIT_WAL)
|
|
SQLITE_PRIVATE int sqlite3PagerWalSystemErrno(Pager*);
|
|
#endif
|
|
|
|
#endif /* SQLITE_PAGER_H */
|
|
|
|
/************** End of pager.h ***********************************************/
|
|
/************** Continuing where we left off in sqliteInt.h ******************/
|
|
/************** Include btree.h in the middle of sqliteInt.h *****************/
|
|
/************** Begin file btree.h *******************************************/
|
|
/*
|
|
** 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.
|
|
*/
|
|
#ifndef SQLITE_BTREE_H
|
|
#define SQLITE_BTREE_H
|
|
|
|
/* TODO: This definition is just included so other modules compile. It
|
|
** needs to be revisited.
|
|
*/
|
|
#define SQLITE_N_BTREE_META 16
|
|
|
|
/*
|
|
** 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;
|
|
typedef struct BtreePayload BtreePayload;
|
|
|
|
|
|
SQLITE_PRIVATE int sqlite3BtreeOpen(
|
|
sqlite3_vfs *pVfs, /* VFS to use with this b-tree */
|
|
const char *zFilename, /* Name of database file to open */
|
|
sqlite3 *db, /* Associated database connection */
|
|
Btree **ppBtree, /* Return open Btree* here */
|
|
int flags, /* Flags */
|
|
int vfsFlags /* Flags passed through to VFS open */
|
|
);
|
|
|
|
/* 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 create or use a rollback journal */
|
|
#define BTREE_MEMORY 2 /* This is an in-memory DB */
|
|
#define BTREE_SINGLE 4 /* The file contains at most 1 b-tree */
|
|
#define BTREE_UNORDERED 8 /* Use of a hash implementation is OK */
|
|
|
|
SQLITE_PRIVATE int sqlite3BtreeClose(Btree*);
|
|
SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree*,int);
|
|
SQLITE_PRIVATE int sqlite3BtreeSetSpillSize(Btree*,int);
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
SQLITE_PRIVATE int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64);
|
|
#endif
|
|
SQLITE_PRIVATE int sqlite3BtreeSetPagerFlags(Btree*,unsigned);
|
|
SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
|
|
SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*);
|
|
SQLITE_PRIVATE Pgno sqlite3BtreeMaxPageCount(Btree*,Pgno);
|
|
SQLITE_PRIVATE Pgno sqlite3BtreeLastPage(Btree*);
|
|
SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree*,int);
|
|
SQLITE_PRIVATE int sqlite3BtreeGetRequestedReserve(Btree*);
|
|
SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p);
|
|
SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int);
|
|
SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *);
|
|
SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int,int*);
|
|
SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree*, const char*);
|
|
SQLITE_PRIVATE int sqlite3BtreeCommitPhaseTwo(Btree*, int);
|
|
SQLITE_PRIVATE int sqlite3BtreeCommit(Btree*);
|
|
SQLITE_PRIVATE int sqlite3BtreeRollback(Btree*,int,int);
|
|
SQLITE_PRIVATE int sqlite3BtreeBeginStmt(Btree*,int);
|
|
SQLITE_PRIVATE int sqlite3BtreeCreateTable(Btree*, Pgno*, int flags);
|
|
SQLITE_PRIVATE int sqlite3BtreeTxnState(Btree*);
|
|
SQLITE_PRIVATE int sqlite3BtreeIsInBackup(Btree*);
|
|
|
|
SQLITE_PRIVATE void *sqlite3BtreeSchema(Btree *, int, void(*)(void *));
|
|
SQLITE_PRIVATE int sqlite3BtreeSchemaLocked(Btree *pBtree);
|
|
#ifndef SQLITE_OMIT_SHARED_CACHE
|
|
SQLITE_PRIVATE int sqlite3BtreeLockTable(Btree *pBtree, int iTab, u8 isWriteLock);
|
|
#endif
|
|
|
|
/* Savepoints are named, nestable SQL transactions mostly implemented */
|
|
/* in vdbe.c and pager.c See https://sqlite.org/lang_savepoint.html */
|
|
SQLITE_PRIVATE int sqlite3BtreeSavepoint(Btree *, int, int);
|
|
|
|
/* "Checkpoint" only refers to WAL. See https://sqlite.org/wal.html#ckpt */
|
|
#ifndef SQLITE_OMIT_WAL
|
|
SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree*, int, int *, int *);
|
|
#endif
|
|
|
|
SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *);
|
|
SQLITE_PRIVATE const char *sqlite3BtreeGetJournalname(Btree *);
|
|
SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *, Btree *);
|
|
|
|
SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *);
|
|
|
|
/* The flags parameter to sqlite3BtreeCreateTable can be the bitwise OR
|
|
** of the flags shown below.
|
|
**
|
|
** Every SQLite table must have either BTREE_INTKEY or BTREE_BLOBKEY set.
|
|
** With BTREE_INTKEY, the table key is a 64-bit integer and arbitrary data
|
|
** is stored in the leaves. (BTREE_INTKEY is used for SQL tables.) With
|
|
** BTREE_BLOBKEY, the key is an arbitrary BLOB and no content is stored
|
|
** anywhere - the key is the content. (BTREE_BLOBKEY is used for SQL
|
|
** indices.)
|
|
*/
|
|
#define BTREE_INTKEY 1 /* Table has only 64-bit signed integer keys */
|
|
#define BTREE_BLOBKEY 2 /* Table has keys only - no data */
|
|
|
|
SQLITE_PRIVATE int sqlite3BtreeDropTable(Btree*, int, int*);
|
|
SQLITE_PRIVATE int sqlite3BtreeClearTable(Btree*, int, i64*);
|
|
SQLITE_PRIVATE int sqlite3BtreeClearTableOfCursor(BtCursor*);
|
|
SQLITE_PRIVATE int sqlite3BtreeTripAllCursors(Btree*, int, int);
|
|
|
|
SQLITE_PRIVATE void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue);
|
|
SQLITE_PRIVATE int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
|
|
|
|
SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p);
|
|
|
|
/*
|
|
** The second parameter to sqlite3BtreeGetMeta or sqlite3BtreeUpdateMeta
|
|
** should be one of the following values. The integer values are assigned
|
|
** to constants so that the offset of the corresponding field in an
|
|
** SQLite database header may be found using the following formula:
|
|
**
|
|
** offset = 36 + (idx * 4)
|
|
**
|
|
** For example, the free-page-count field is located at byte offset 36 of
|
|
** the database file header. The incr-vacuum-flag field is located at
|
|
** byte offset 64 (== 36+4*7).
|
|
**
|
|
** The BTREE_DATA_VERSION value is not really a value stored in the header.
|
|
** It is a read-only number computed by the pager. But we merge it with
|
|
** the header value access routines since its access pattern is the same.
|
|
** Call it a "virtual meta value".
|
|
*/
|
|
#define BTREE_FREE_PAGE_COUNT 0
|
|
#define BTREE_SCHEMA_VERSION 1
|
|
#define BTREE_FILE_FORMAT 2
|
|
#define BTREE_DEFAULT_CACHE_SIZE 3
|
|
#define BTREE_LARGEST_ROOT_PAGE 4
|
|
#define BTREE_TEXT_ENCODING 5
|
|
#define BTREE_USER_VERSION 6
|
|
#define BTREE_INCR_VACUUM 7
|
|
#define BTREE_APPLICATION_ID 8
|
|
#define BTREE_DATA_VERSION 15 /* A virtual meta-value */
|
|
|
|
/*
|
|
** Kinds of hints that can be passed into the sqlite3BtreeCursorHint()
|
|
** interface.
|
|
**
|
|
** BTREE_HINT_RANGE (arguments: Expr*, Mem*)
|
|
**
|
|
** The first argument is an Expr* (which is guaranteed to be constant for
|
|
** the lifetime of the cursor) that defines constraints on which rows
|
|
** might be fetched with this cursor. The Expr* tree may contain
|
|
** TK_REGISTER nodes that refer to values stored in the array of registers
|
|
** passed as the second parameter. In other words, if Expr.op==TK_REGISTER
|
|
** then the value of the node is the value in Mem[pExpr.iTable]. Any
|
|
** TK_COLUMN node in the expression tree refers to the Expr.iColumn-th
|
|
** column of the b-tree of the cursor. The Expr tree will not contain
|
|
** any function calls nor subqueries nor references to b-trees other than
|
|
** the cursor being hinted.
|
|
**
|
|
** The design of the _RANGE hint is aid b-tree implementations that try
|
|
** to prefetch content from remote machines - to provide those
|
|
** implementations with limits on what needs to be prefetched and thereby
|
|
** reduce network bandwidth.
|
|
**
|
|
** Note that BTREE_HINT_FLAGS with BTREE_BULKLOAD is the only hint used by
|
|
** standard SQLite. The other hints are provided for extensions that use
|
|
** the SQLite parser and code generator but substitute their own storage
|
|
** engine.
|
|
*/
|
|
#define BTREE_HINT_RANGE 0 /* Range constraints on queries */
|
|
|
|
/*
|
|
** Values that may be OR'd together to form the argument to the
|
|
** BTREE_HINT_FLAGS hint for sqlite3BtreeCursorHint():
|
|
**
|
|
** The BTREE_BULKLOAD flag is set on index cursors when the index is going
|
|
** to be filled with content that is already in sorted order.
|
|
**
|
|
** The BTREE_SEEK_EQ flag is set on cursors that will get OP_SeekGE or
|
|
** OP_SeekLE opcodes for a range search, but where the range of entries
|
|
** selected will all have the same key. In other words, the cursor will
|
|
** be used only for equality key searches.
|
|
**
|
|
*/
|
|
#define BTREE_BULKLOAD 0x00000001 /* Used to full index in sorted order */
|
|
#define BTREE_SEEK_EQ 0x00000002 /* EQ seeks only - no range seeks */
|
|
|
|
/*
|
|
** Flags passed as the third argument to sqlite3BtreeCursor().
|
|
**
|
|
** For read-only cursors the wrFlag argument is always zero. For read-write
|
|
** cursors it may be set to either (BTREE_WRCSR|BTREE_FORDELETE) or just
|
|
** (BTREE_WRCSR). If the BTREE_FORDELETE bit is set, then the cursor will
|
|
** only be used by SQLite for the following:
|
|
**
|
|
** * to seek to and then delete specific entries, and/or
|
|
**
|
|
** * to read values that will be used to create keys that other
|
|
** BTREE_FORDELETE cursors will seek to and delete.
|
|
**
|
|
** The BTREE_FORDELETE flag is an optimization hint. It is not used by
|
|
** by this, the native b-tree engine of SQLite, but it is available to
|
|
** alternative storage engines that might be substituted in place of this
|
|
** b-tree system. For alternative storage engines in which a delete of
|
|
** the main table row automatically deletes corresponding index rows,
|
|
** the FORDELETE flag hint allows those alternative storage engines to
|
|
** skip a lot of work. Namely: FORDELETE cursors may treat all SEEK
|
|
** and DELETE operations as no-ops, and any READ operation against a
|
|
** FORDELETE cursor may return a null row: 0x01 0x00.
|
|
*/
|
|
#define BTREE_WRCSR 0x00000004 /* read-write cursor */
|
|
#define BTREE_FORDELETE 0x00000008 /* Cursor is for seek/delete only */
|
|
|
|
SQLITE_PRIVATE int sqlite3BtreeCursor(
|
|
Btree*, /* BTree containing table to open */
|
|
Pgno iTable, /* Index of root page */
|
|
int wrFlag, /* 1 for writing. 0 for read-only */
|
|
struct KeyInfo*, /* First argument to compare function */
|
|
BtCursor *pCursor /* Space to write cursor structure */
|
|
);
|
|
SQLITE_PRIVATE BtCursor *sqlite3BtreeFakeValidCursor(void);
|
|
SQLITE_PRIVATE int sqlite3BtreeCursorSize(void);
|
|
SQLITE_PRIVATE void sqlite3BtreeCursorZero(BtCursor*);
|
|
SQLITE_PRIVATE void sqlite3BtreeCursorHintFlags(BtCursor*, unsigned);
|
|
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
|
SQLITE_PRIVATE void sqlite3BtreeCursorHint(BtCursor*, int, ...);
|
|
#endif
|
|
|
|
SQLITE_PRIVATE int sqlite3BtreeCloseCursor(BtCursor*);
|
|
SQLITE_PRIVATE int sqlite3BtreeTableMoveto(
|
|
BtCursor*,
|
|
i64 intKey,
|
|
int bias,
|
|
int *pRes
|
|
);
|
|
SQLITE_PRIVATE int sqlite3BtreeIndexMoveto(
|
|
BtCursor*,
|
|
UnpackedRecord *pUnKey,
|
|
int *pRes
|
|
);
|
|
SQLITE_PRIVATE int sqlite3BtreeCursorHasMoved(BtCursor*);
|
|
SQLITE_PRIVATE int sqlite3BtreeCursorRestore(BtCursor*, int*);
|
|
SQLITE_PRIVATE int sqlite3BtreeDelete(BtCursor*, u8 flags);
|
|
|
|
/* Allowed flags for sqlite3BtreeDelete() and sqlite3BtreeInsert() */
|
|
#define BTREE_SAVEPOSITION 0x02 /* Leave cursor pointing at NEXT or PREV */
|
|
#define BTREE_AUXDELETE 0x04 /* not the primary delete operation */
|
|
#define BTREE_APPEND 0x08 /* Insert is likely an append */
|
|
#define BTREE_PREFORMAT 0x80 /* Inserted data is a preformated cell */
|
|
|
|
/* An instance of the BtreePayload object describes the content of a single
|
|
** entry in either an index or table btree.
|
|
**
|
|
** Index btrees (used for indexes and also WITHOUT ROWID tables) contain
|
|
** an arbitrary key and no data. These btrees have pKey,nKey set to the
|
|
** key and the pData,nData,nZero fields are uninitialized. The aMem,nMem
|
|
** fields give an array of Mem objects that are a decomposition of the key.
|
|
** The nMem field might be zero, indicating that no decomposition is available.
|
|
**
|
|
** Table btrees (used for rowid tables) contain an integer rowid used as
|
|
** the key and passed in the nKey field. The pKey field is zero.
|
|
** pData,nData hold the content of the new entry. nZero extra zero bytes
|
|
** are appended to the end of the content when constructing the entry.
|
|
** The aMem,nMem fields are uninitialized for table btrees.
|
|
**
|
|
** Field usage summary:
|
|
**
|
|
** Table BTrees Index Btrees
|
|
**
|
|
** pKey always NULL encoded key
|
|
** nKey the ROWID length of pKey
|
|
** pData data not used
|
|
** aMem not used decomposed key value
|
|
** nMem not used entries in aMem
|
|
** nData length of pData not used
|
|
** nZero extra zeros after pData not used
|
|
**
|
|
** This object is used to pass information into sqlite3BtreeInsert(). The
|
|
** same information used to be passed as five separate parameters. But placing
|
|
** the information into this object helps to keep the interface more
|
|
** organized and understandable, and it also helps the resulting code to
|
|
** run a little faster by using fewer registers for parameter passing.
|
|
*/
|
|
struct BtreePayload {
|
|
const void *pKey; /* Key content for indexes. NULL for tables */
|
|
sqlite3_int64 nKey; /* Size of pKey for indexes. PRIMARY KEY for tabs */
|
|
const void *pData; /* Data for tables. */
|
|
sqlite3_value *aMem; /* First of nMem value in the unpacked pKey */
|
|
u16 nMem; /* Number of aMem[] value. Might be zero */
|
|
int nData; /* Size of pData. 0 if none. */
|
|
int nZero; /* Extra zero data appended after pData,nData */
|
|
};
|
|
|
|
SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload,
|
|
int flags, int seekResult);
|
|
SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor*, int *pRes);
|
|
SQLITE_PRIVATE int sqlite3BtreeLast(BtCursor*, int *pRes);
|
|
SQLITE_PRIVATE int sqlite3BtreeNext(BtCursor*, int flags);
|
|
SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor*);
|
|
SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int flags);
|
|
SQLITE_PRIVATE i64 sqlite3BtreeIntegerKey(BtCursor*);
|
|
SQLITE_PRIVATE void sqlite3BtreeCursorPin(BtCursor*);
|
|
SQLITE_PRIVATE void sqlite3BtreeCursorUnpin(BtCursor*);
|
|
SQLITE_PRIVATE i64 sqlite3BtreeOffset(BtCursor*);
|
|
SQLITE_PRIVATE int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*);
|
|
SQLITE_PRIVATE const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt);
|
|
SQLITE_PRIVATE u32 sqlite3BtreePayloadSize(BtCursor*);
|
|
SQLITE_PRIVATE sqlite3_int64 sqlite3BtreeMaxRecordSize(BtCursor*);
|
|
|
|
SQLITE_PRIVATE int sqlite3BtreeIntegrityCheck(
|
|
sqlite3 *db, /* Database connection that is running the check */
|
|
Btree *p, /* The btree to be checked */
|
|
Pgno *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, /* OUT: Write number of errors seen to this variable */
|
|
char **pzOut /* OUT: Write the error message string here */
|
|
);
|
|
SQLITE_PRIVATE struct Pager *sqlite3BtreePager(Btree*);
|
|
SQLITE_PRIVATE i64 sqlite3BtreeRowCountEst(BtCursor*);
|
|
|
|
#ifndef SQLITE_OMIT_INCRBLOB
|
|
SQLITE_PRIVATE int sqlite3BtreePayloadChecked(BtCursor*, u32 offset, u32 amt, void*);
|
|
SQLITE_PRIVATE int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*);
|
|
SQLITE_PRIVATE void sqlite3BtreeIncrblobCursor(BtCursor *);
|
|
#endif
|
|
SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *);
|
|
SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBt, int iVersion);
|
|
SQLITE_PRIVATE int sqlite3BtreeCursorHasHint(BtCursor*, unsigned int mask);
|
|
SQLITE_PRIVATE int sqlite3BtreeIsReadonly(Btree *pBt);
|
|
SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void);
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
SQLITE_PRIVATE sqlite3_uint64 sqlite3BtreeSeekCount(Btree*);
|
|
#else
|
|
# define sqlite3BtreeSeekCount(X) 0
|
|
#endif
|
|
|
|
#ifndef NDEBUG
|
|
SQLITE_PRIVATE int sqlite3BtreeCursorIsValid(BtCursor*);
|
|
#endif
|
|
SQLITE_PRIVATE int sqlite3BtreeCursorIsValidNN(BtCursor*);
|
|
|
|
SQLITE_PRIVATE int sqlite3BtreeCount(sqlite3*, BtCursor*, i64*);
|
|
|
|
#ifdef SQLITE_TEST
|
|
SQLITE_PRIVATE int sqlite3BtreeCursorInfo(BtCursor*, int*, int);
|
|
SQLITE_PRIVATE void sqlite3BtreeCursorList(Btree*);
|
|
#endif
|
|
|
|
#ifndef SQLITE_OMIT_WAL
|
|
SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree*, int, int *, int *);
|
|
#endif
|
|
|
|
SQLITE_PRIVATE int sqlite3BtreeTransferRow(BtCursor*, BtCursor*, i64);
|
|
|
|
SQLITE_PRIVATE void sqlite3BtreeClearCache(Btree*);
|
|
|
|
/*
|
|
** If we are not using shared cache, then there is no need to
|
|
** use mutexes to access the BtShared structures. So make the
|
|
** Enter and Leave procedures no-ops.
|
|
*/
|
|
#ifndef SQLITE_OMIT_SHARED_CACHE
|
|
SQLITE_PRIVATE void sqlite3BtreeEnter(Btree*);
|
|
SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3*);
|
|
SQLITE_PRIVATE int sqlite3BtreeSharable(Btree*);
|
|
SQLITE_PRIVATE void sqlite3BtreeEnterCursor(BtCursor*);
|
|
SQLITE_PRIVATE int sqlite3BtreeConnectionCount(Btree*);
|
|
#else
|
|
# define sqlite3BtreeEnter(X)
|
|
# define sqlite3BtreeEnterAll(X)
|
|
# define sqlite3BtreeSharable(X) 0
|
|
# define sqlite3BtreeEnterCursor(X)
|
|
# define sqlite3BtreeConnectionCount(X) 1
|
|
#endif
|
|
|
|
#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE
|
|
SQLITE_PRIVATE void sqlite3BtreeLeave(Btree*);
|
|
SQLITE_PRIVATE void sqlite3BtreeLeaveCursor(BtCursor*);
|
|
SQLITE_PRIVATE void sqlite3BtreeLeaveAll(sqlite3*);
|
|
#ifndef NDEBUG
|
|
/* These routines are used inside assert() statements only. */
|
|
SQLITE_PRIVATE int sqlite3BtreeHoldsMutex(Btree*);
|
|
SQLITE_PRIVATE int sqlite3BtreeHoldsAllMutexes(sqlite3*);
|
|
SQLITE_PRIVATE int sqlite3SchemaMutexHeld(sqlite3*,int,Schema*);
|
|
#endif
|
|
#else
|
|
|
|
# define sqlite3BtreeLeave(X)
|
|
# define sqlite3BtreeLeaveCursor(X)
|
|
# define sqlite3BtreeLeaveAll(X)
|
|
|
|
# define sqlite3BtreeHoldsMutex(X) 1
|
|
# define sqlite3BtreeHoldsAllMutexes(X) 1
|
|
# define sqlite3SchemaMutexHeld(X,Y,Z) 1
|
|
#endif
|
|
|
|
|
|
#endif /* SQLITE_BTREE_H */
|
|
|
|
/************** End of btree.h ***********************************************/
|
|
/************** Continuing where we left off in sqliteInt.h ******************/
|
|
/************** Include vdbe.h in the middle of sqliteInt.h ******************/
|
|
/************** Begin file vdbe.h ********************************************/
|
|
/*
|
|
** 2001 September 15
|
|
**
|
|
** The author disclaims copyright to this source code. In place of
|
|
** a legal notice, here is a blessing:
|
|
**
|
|
** May you do good and not evil.
|
|
** May you find forgiveness for yourself and forgive others.
|
|
** May you share freely, never taking more than you give.
|
|
**
|
|
*************************************************************************
|
|
** Header file for the Virtual DataBase Engine (VDBE)
|
|
**
|
|
** This header defines the interface to the virtual database engine
|
|
** or VDBE. The VDBE implements an abstract machine that runs a
|
|
** simple program to access and modify the underlying database.
|
|
*/
|
|
#ifndef SQLITE_VDBE_H
|
|
#define SQLITE_VDBE_H
|
|
/* #include <stdio.h> */
|
|
|
|
/*
|
|
** A single VDBE is an opaque structure named "Vdbe". Only routines
|
|
** in the source file sqliteVdbe.c are allowed to see the insides
|
|
** of this structure.
|
|
*/
|
|
typedef struct Vdbe Vdbe;
|
|
|
|
/*
|
|
** The names of the following types declared in vdbeInt.h are required
|
|
** for the VdbeOp definition.
|
|
*/
|
|
typedef struct sqlite3_value Mem;
|
|
typedef struct SubProgram SubProgram;
|
|
|
|
/*
|
|
** A single instruction of the virtual machine has an opcode
|
|
** and as many as three operands. The instruction is recorded
|
|
** as an instance of the following structure:
|
|
*/
|
|
struct VdbeOp {
|
|
u8 opcode; /* What operation to perform */
|
|
signed char p4type; /* One of the P4_xxx constants for p4 */
|
|
u16 p5; /* Fifth parameter is an unsigned 16-bit integer */
|
|
int p1; /* First operand */
|
|
int p2; /* Second parameter (often the jump destination) */
|
|
int p3; /* The third parameter */
|
|
union p4union { /* fourth parameter */
|
|
int i; /* Integer value if p4type==P4_INT32 */
|
|
void *p; /* Generic pointer */
|
|
char *z; /* Pointer to data for string (char array) types */
|
|
i64 *pI64; /* Used when p4type is P4_INT64 */
|
|
double *pReal; /* Used when p4type is P4_REAL */
|
|
FuncDef *pFunc; /* Used when p4type is P4_FUNCDEF */
|
|
sqlite3_context *pCtx; /* Used when p4type is P4_FUNCCTX */
|
|
CollSeq *pColl; /* Used when p4type is P4_COLLSEQ */
|
|
Mem *pMem; /* Used when p4type is P4_MEM */
|
|
VTable *pVtab; /* Used when p4type is P4_VTAB */
|
|
KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */
|
|
u32 *ai; /* Used when p4type is P4_INTARRAY */
|
|
SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */
|
|
Table *pTab; /* Used when p4type is P4_TABLE */
|
|
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
|
Expr *pExpr; /* Used when p4type is P4_EXPR */
|
|
#endif
|
|
} p4;
|
|
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
|
char *zComment; /* Comment to improve readability */
|
|
#endif
|
|
#ifdef SQLITE_VDBE_COVERAGE
|
|
u32 iSrcLine; /* Source-code line that generated this opcode
|
|
** with flags in the upper 8 bits */
|
|
#endif
|
|
#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE)
|
|
u64 nExec;
|
|
u64 nCycle;
|
|
#endif
|
|
};
|
|
typedef struct VdbeOp VdbeOp;
|
|
|
|
|
|
/*
|
|
** A sub-routine used to implement a trigger program.
|
|
*/
|
|
struct SubProgram {
|
|
VdbeOp *aOp; /* Array of opcodes for sub-program */
|
|
int nOp; /* Elements in aOp[] */
|
|
int nMem; /* Number of memory cells required */
|
|
int nCsr; /* Number of cursors required */
|
|
u8 *aOnce; /* Array of OP_Once flags */
|
|
void *token; /* id that may be used to recursive triggers */
|
|
SubProgram *pNext; /* Next sub-program already visited */
|
|
};
|
|
|
|
/*
|
|
** A smaller version of VdbeOp used for the VdbeAddOpList() function because
|
|
** it takes up less space.
|
|
*/
|
|
struct VdbeOpList {
|
|
u8 opcode; /* What operation to perform */
|
|
signed char p1; /* First operand */
|
|
signed char p2; /* Second parameter (often the jump destination) */
|
|
signed char p3; /* Third parameter */
|
|
};
|
|
typedef struct VdbeOpList VdbeOpList;
|
|
|
|
/*
|
|
** Allowed values of VdbeOp.p4type
|
|
*/
|
|
#define P4_NOTUSED 0 /* The P4 parameter is not used */
|
|
#define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */
|
|
#define P4_STATIC (-1) /* Pointer to a static string */
|
|
#define P4_COLLSEQ (-2) /* P4 is a pointer to a CollSeq structure */
|
|
#define P4_INT32 (-3) /* P4 is a 32-bit signed integer */
|
|
#define P4_SUBPROGRAM (-4) /* P4 is a pointer to a SubProgram structure */
|
|
#define P4_TABLE (-5) /* P4 is a pointer to a Table structure */
|
|
/* Above do not own any resources. Must free those below */
|
|
#define P4_FREE_IF_LE (-6)
|
|
#define P4_DYNAMIC (-6) /* Pointer to memory from sqliteMalloc() */
|
|
#define P4_FUNCDEF (-7) /* P4 is a pointer to a FuncDef structure */
|
|
#define P4_KEYINFO (-8) /* P4 is a pointer to a KeyInfo structure */
|
|
#define P4_EXPR (-9) /* P4 is a pointer to an Expr tree */
|
|
#define P4_MEM (-10) /* P4 is a pointer to a Mem* structure */
|
|
#define P4_VTAB (-11) /* P4 is a pointer to an sqlite3_vtab structure */
|
|
#define P4_REAL (-12) /* P4 is a 64-bit floating point value */
|
|
#define P4_INT64 (-13) /* P4 is a 64-bit signed integer */
|
|
#define P4_INTARRAY (-14) /* P4 is a vector of 32-bit integers */
|
|
#define P4_FUNCCTX (-15) /* P4 is a pointer to an sqlite3_context object */
|
|
#define P4_TABLEREF (-16) /* Like P4_TABLE, but reference counted */
|
|
|
|
/* Error message codes for OP_Halt */
|
|
#define P5_ConstraintNotNull 1
|
|
#define P5_ConstraintUnique 2
|
|
#define P5_ConstraintCheck 3
|
|
#define P5_ConstraintFK 4
|
|
|
|
/*
|
|
** The Vdbe.aColName array contains 5n Mem structures, where n is the
|
|
** number of columns of data returned by the statement.
|
|
*/
|
|
#define COLNAME_NAME 0
|
|
#define COLNAME_DECLTYPE 1
|
|
#define COLNAME_DATABASE 2
|
|
#define COLNAME_TABLE 3
|
|
#define COLNAME_COLUMN 4
|
|
#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
|
# define COLNAME_N 5 /* Number of COLNAME_xxx symbols */
|
|
#else
|
|
# ifdef SQLITE_OMIT_DECLTYPE
|
|
# define COLNAME_N 1 /* Store only the name */
|
|
# else
|
|
# define COLNAME_N 2 /* Store the name and decltype */
|
|
# endif
|
|
#endif
|
|
|
|
/*
|
|
** The following macro converts a label returned by sqlite3VdbeMakeLabel()
|
|
** into an index into the Parse.aLabel[] array that contains the resolved
|
|
** address of that label.
|
|
*/
|
|
#define ADDR(X) (~(X))
|
|
|
|
/*
|
|
** The makefile scans the vdbe.c source file and creates the "opcodes.h"
|
|
** header file that defines a number for each opcode used by the VDBE.
|
|
*/
|
|
/************** Include opcodes.h in the middle of vdbe.h ********************/
|
|
/************** Begin file opcodes.h *****************************************/
|
|
/* Automatically generated. Do not edit */
|
|
/* See the tool/mkopcodeh.tcl script for details */
|
|
#define OP_Savepoint 0
|
|
#define OP_AutoCommit 1
|
|
#define OP_Transaction 2
|
|
#define OP_Checkpoint 3
|
|
#define OP_JournalMode 4
|
|
#define OP_Vacuum 5
|
|
#define OP_VFilter 6 /* jump, synopsis: iplan=r[P3] zplan='P4' */
|
|
#define OP_VUpdate 7 /* synopsis: data=r[P3@P2] */
|
|
#define OP_Init 8 /* jump, synopsis: Start at P2 */
|
|
#define OP_Goto 9 /* jump */
|
|
#define OP_Gosub 10 /* jump */
|
|
#define OP_InitCoroutine 11 /* jump */
|
|
#define OP_Yield 12 /* jump */
|
|
#define OP_MustBeInt 13 /* jump */
|
|
#define OP_Jump 14 /* jump */
|
|
#define OP_Once 15 /* jump */
|
|
#define OP_If 16 /* jump */
|
|
#define OP_IfNot 17 /* jump */
|
|
#define OP_IsType 18 /* jump, synopsis: if typeof(P1.P3) in P5 goto P2 */
|
|
#define OP_Not 19 /* same as TK_NOT, synopsis: r[P2]= !r[P1] */
|
|
#define OP_IfNullRow 20 /* jump, synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */
|
|
#define OP_SeekLT 21 /* jump, synopsis: key=r[P3@P4] */
|
|
#define OP_SeekLE 22 /* jump, synopsis: key=r[P3@P4] */
|
|
#define OP_SeekGE 23 /* jump, synopsis: key=r[P3@P4] */
|
|
#define OP_SeekGT 24 /* jump, synopsis: key=r[P3@P4] */
|
|
#define OP_IfNotOpen 25 /* jump, synopsis: if( !csr[P1] ) goto P2 */
|
|
#define OP_IfNoHope 26 /* jump, synopsis: key=r[P3@P4] */
|
|
#define OP_NoConflict 27 /* jump, synopsis: key=r[P3@P4] */
|
|
#define OP_NotFound 28 /* jump, synopsis: key=r[P3@P4] */
|
|
#define OP_Found 29 /* jump, synopsis: key=r[P3@P4] */
|
|
#define OP_SeekRowid 30 /* jump, synopsis: intkey=r[P3] */
|
|
#define OP_NotExists 31 /* jump, synopsis: intkey=r[P3] */
|
|
#define OP_Last 32 /* jump */
|
|
#define OP_IfSmaller 33 /* jump */
|
|
#define OP_SorterSort 34 /* jump */
|
|
#define OP_Sort 35 /* jump */
|
|
#define OP_Rewind 36 /* jump */
|
|
#define OP_SorterNext 37 /* jump */
|
|
#define OP_Prev 38 /* jump */
|
|
#define OP_Next 39 /* jump */
|
|
#define OP_IdxLE 40 /* jump, synopsis: key=r[P3@P4] */
|
|
#define OP_IdxGT 41 /* jump, synopsis: key=r[P3@P4] */
|
|
#define OP_IdxLT 42 /* jump, synopsis: key=r[P3@P4] */
|
|
#define OP_Or 43 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */
|
|
#define OP_And 44 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */
|
|
#define OP_IdxGE 45 /* jump, synopsis: key=r[P3@P4] */
|
|
#define OP_RowSetRead 46 /* jump, synopsis: r[P3]=rowset(P1) */
|
|
#define OP_RowSetTest 47 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */
|
|
#define OP_Program 48 /* jump */
|
|
#define OP_FkIfZero 49 /* jump, synopsis: if fkctr[P1]==0 goto P2 */
|
|
#define OP_IsNull 50 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
|
|
#define OP_NotNull 51 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
|
|
#define OP_Ne 52 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */
|
|
#define OP_Eq 53 /* jump, same as TK_EQ, synopsis: IF r[P3]==r[P1] */
|
|
#define OP_Gt 54 /* jump, same as TK_GT, synopsis: IF r[P3]>r[P1] */
|
|
#define OP_Le 55 /* jump, same as TK_LE, synopsis: IF r[P3]<=r[P1] */
|
|
#define OP_Lt 56 /* jump, same as TK_LT, synopsis: IF r[P3]<r[P1] */
|
|
#define OP_Ge 57 /* jump, same as TK_GE, synopsis: IF r[P3]>=r[P1] */
|
|
#define OP_ElseEq 58 /* jump, same as TK_ESCAPE */
|
|
#define OP_IfPos 59 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
|
|
#define OP_IfNotZero 60 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
|
|
#define OP_DecrJumpZero 61 /* jump, synopsis: if (--r[P1])==0 goto P2 */
|
|
#define OP_IncrVacuum 62 /* jump */
|
|
#define OP_VNext 63 /* jump */
|
|
#define OP_Filter 64 /* jump, synopsis: if key(P3@P4) not in filter(P1) goto P2 */
|
|
#define OP_PureFunc 65 /* synopsis: r[P3]=func(r[P2@NP]) */
|
|
#define OP_Function 66 /* synopsis: r[P3]=func(r[P2@NP]) */
|
|
#define OP_Return 67
|
|
#define OP_EndCoroutine 68
|
|
#define OP_HaltIfNull 69 /* synopsis: if r[P3]=null halt */
|
|
#define OP_Halt 70
|
|
#define OP_Integer 71 /* synopsis: r[P2]=P1 */
|
|
#define OP_Int64 72 /* synopsis: r[P2]=P4 */
|
|
#define OP_String 73 /* synopsis: r[P2]='P4' (len=P1) */
|
|
#define OP_BeginSubrtn 74 /* synopsis: r[P2]=NULL */
|
|
#define OP_Null 75 /* synopsis: r[P2..P3]=NULL */
|
|
#define OP_SoftNull 76 /* synopsis: r[P1]=NULL */
|
|
#define OP_Blob 77 /* synopsis: r[P2]=P4 (len=P1) */
|
|
#define OP_Variable 78 /* synopsis: r[P2]=parameter(P1,P4) */
|
|
#define OP_Move 79 /* synopsis: r[P2@P3]=r[P1@P3] */
|
|
#define OP_Copy 80 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */
|
|
#define OP_SCopy 81 /* synopsis: r[P2]=r[P1] */
|
|
#define OP_IntCopy 82 /* synopsis: r[P2]=r[P1] */
|
|
#define OP_FkCheck 83
|
|
#define OP_ResultRow 84 /* synopsis: output=r[P1@P2] */
|
|
#define OP_CollSeq 85
|
|
#define OP_AddImm 86 /* synopsis: r[P1]=r[P1]+P2 */
|
|
#define OP_RealAffinity 87
|
|
#define OP_Cast 88 /* synopsis: affinity(r[P1]) */
|
|
#define OP_Permutation 89
|
|
#define OP_Compare 90 /* synopsis: r[P1@P3] <-> r[P2@P3] */
|
|
#define OP_IsTrue 91 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */
|
|
#define OP_ZeroOrNull 92 /* synopsis: r[P2] = 0 OR NULL */
|
|
#define OP_Offset 93 /* synopsis: r[P3] = sqlite_offset(P1) */
|
|
#define OP_Column 94 /* synopsis: r[P3]=PX cursor P1 column P2 */
|
|
#define OP_TypeCheck 95 /* synopsis: typecheck(r[P1@P2]) */
|
|
#define OP_Affinity 96 /* synopsis: affinity(r[P1@P2]) */
|
|
#define OP_MakeRecord 97 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
|
|
#define OP_Count 98 /* synopsis: r[P2]=count() */
|
|
#define OP_ReadCookie 99
|
|
#define OP_SetCookie 100
|
|
#define OP_ReopenIdx 101 /* synopsis: root=P2 iDb=P3 */
|
|
#define OP_BitAnd 102 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
|
|
#define OP_BitOr 103 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
|
|
#define OP_ShiftLeft 104 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
|
|
#define OP_ShiftRight 105 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
|
|
#define OP_Add 106 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
|
|
#define OP_Subtract 107 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
|
|
#define OP_Multiply 108 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
|
|
#define OP_Divide 109 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
|
|
#define OP_Remainder 110 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
|
|
#define OP_Concat 111 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
|
|
#define OP_OpenRead 112 /* synopsis: root=P2 iDb=P3 */
|
|
#define OP_OpenWrite 113 /* synopsis: root=P2 iDb=P3 */
|
|
#define OP_BitNot 114 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
|
|
#define OP_OpenDup 115
|
|
#define OP_OpenAutoindex 116 /* synopsis: nColumn=P2 */
|
|
#define OP_String8 117 /* same as TK_STRING, synopsis: r[P2]='P4' */
|
|
#define OP_OpenEphemeral 118 /* synopsis: nColumn=P2 */
|
|
#define OP_SorterOpen 119
|
|
#define OP_SequenceTest 120 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
|
|
#define OP_OpenPseudo 121 /* synopsis: P3 columns in r[P2] */
|
|
#define OP_Close 122
|
|
#define OP_ColumnsUsed 123
|
|
#define OP_SeekScan 124 /* synopsis: Scan-ahead up to P1 rows */
|
|
#define OP_SeekHit 125 /* synopsis: set P2<=seekHit<=P3 */
|
|
#define OP_Sequence 126 /* synopsis: r[P2]=cursor[P1].ctr++ */
|
|
#define OP_NewRowid 127 /* synopsis: r[P2]=rowid */
|
|
#define OP_Insert 128 /* synopsis: intkey=r[P3] data=r[P2] */
|
|
#define OP_RowCell 129
|
|
#define OP_Delete 130
|
|
#define OP_ResetCount 131
|
|
#define OP_SorterCompare 132 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
|
|
#define OP_SorterData 133 /* synopsis: r[P2]=data */
|
|
#define OP_RowData 134 /* synopsis: r[P2]=data */
|
|
#define OP_Rowid 135 /* synopsis: r[P2]=PX rowid of P1 */
|
|
#define OP_NullRow 136
|
|
#define OP_SeekEnd 137
|
|
#define OP_IdxInsert 138 /* synopsis: key=r[P2] */
|
|
#define OP_SorterInsert 139 /* synopsis: key=r[P2] */
|
|
#define OP_IdxDelete 140 /* synopsis: key=r[P2@P3] */
|
|
#define OP_DeferredSeek 141 /* synopsis: Move P3 to P1.rowid if needed */
|
|
#define OP_IdxRowid 142 /* synopsis: r[P2]=rowid */
|
|
#define OP_FinishSeek 143
|
|
#define OP_Destroy 144
|
|
#define OP_Clear 145
|
|
#define OP_ResetSorter 146
|
|
#define OP_CreateBtree 147 /* synopsis: r[P2]=root iDb=P1 flags=P3 */
|
|
#define OP_SqlExec 148
|
|
#define OP_ParseSchema 149
|
|
#define OP_LoadAnalysis 150
|
|
#define OP_DropTable 151
|
|
#define OP_DropIndex 152
|
|
#define OP_Real 153 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
|
|
#define OP_DropTrigger 154
|
|
#define OP_IntegrityCk 155
|
|
#define OP_RowSetAdd 156 /* synopsis: rowset(P1)=r[P2] */
|
|
#define OP_Param 157
|
|
#define OP_FkCounter 158 /* synopsis: fkctr[P1]+=P2 */
|
|
#define OP_MemMax 159 /* synopsis: r[P1]=max(r[P1],r[P2]) */
|
|
#define OP_OffsetLimit 160 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
|
|
#define OP_AggInverse 161 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */
|
|
#define OP_AggStep 162 /* synopsis: accum=r[P3] step(r[P2@P5]) */
|
|
#define OP_AggStep1 163 /* synopsis: accum=r[P3] step(r[P2@P5]) */
|
|
#define OP_AggValue 164 /* synopsis: r[P3]=value N=P2 */
|
|
#define OP_AggFinal 165 /* synopsis: accum=r[P1] N=P2 */
|
|
#define OP_Expire 166
|
|
#define OP_CursorLock 167
|
|
#define OP_CursorUnlock 168
|
|
#define OP_TableLock 169 /* synopsis: iDb=P1 root=P2 write=P3 */
|
|
#define OP_VBegin 170
|
|
#define OP_VCreate 171
|
|
#define OP_VDestroy 172
|
|
#define OP_VOpen 173
|
|
#define OP_VCheck 174
|
|
#define OP_VInitIn 175 /* synopsis: r[P2]=ValueList(P1,P3) */
|
|
#define OP_VColumn 176 /* synopsis: r[P3]=vcolumn(P2) */
|
|
#define OP_VRename 177
|
|
#define OP_Pagecount 178
|
|
#define OP_MaxPgcnt 179
|
|
#define OP_ClrSubtype 180 /* synopsis: r[P1].subtype = 0 */
|
|
#define OP_GetSubtype 181 /* synopsis: r[P2] = r[P1].subtype */
|
|
#define OP_SetSubtype 182 /* synopsis: r[P2].subtype = r[P1] */
|
|
#define OP_FilterAdd 183 /* synopsis: filter(P1) += key(P3@P4) */
|
|
#define OP_Trace 184
|
|
#define OP_CursorHint 185
|
|
#define OP_ReleaseReg 186 /* synopsis: release r[P1@P2] mask P3 */
|
|
#define OP_Noop 187
|
|
#define OP_Explain 188
|
|
#define OP_Abortable 189
|
|
|
|
/* Properties such as "out2" or "jump" that are specified in
|
|
** comments following the "case" for each opcode in the vdbe.c
|
|
** are encoded into bitvectors as follows:
|
|
*/
|
|
#define OPFLG_JUMP 0x01 /* jump: P2 holds jmp target */
|
|
#define OPFLG_IN1 0x02 /* in1: P1 is an input */
|
|
#define OPFLG_IN2 0x04 /* in2: P2 is an input */
|
|
#define OPFLG_IN3 0x08 /* in3: P3 is an input */
|
|
#define OPFLG_OUT2 0x10 /* out2: P2 is an output */
|
|
#define OPFLG_OUT3 0x20 /* out3: P3 is an output */
|
|
#define OPFLG_NCYCLE 0x40 /* ncycle:Cycles count against P1 */
|
|
#define OPFLG_INITIALIZER {\
|
|
/* 0 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x41, 0x00,\
|
|
/* 8 */ 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x01, 0x01,\
|
|
/* 16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0x49, 0x49, 0x49,\
|
|
/* 24 */ 0x49, 0x01, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,\
|
|
/* 32 */ 0x41, 0x01, 0x41, 0x41, 0x41, 0x01, 0x41, 0x41,\
|
|
/* 40 */ 0x41, 0x41, 0x41, 0x26, 0x26, 0x41, 0x23, 0x0b,\
|
|
/* 48 */ 0x01, 0x01, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\
|
|
/* 56 */ 0x0b, 0x0b, 0x01, 0x03, 0x03, 0x03, 0x01, 0x41,\
|
|
/* 64 */ 0x01, 0x00, 0x00, 0x02, 0x02, 0x08, 0x00, 0x10,\
|
|
/* 72 */ 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10, 0x00,\
|
|
/* 80 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x02, 0x02,\
|
|
/* 88 */ 0x02, 0x00, 0x00, 0x12, 0x1e, 0x20, 0x40, 0x00,\
|
|
/* 96 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x40, 0x26, 0x26,\
|
|
/* 104 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,\
|
|
/* 112 */ 0x40, 0x00, 0x12, 0x40, 0x40, 0x10, 0x40, 0x00,\
|
|
/* 120 */ 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x10, 0x10,\
|
|
/* 128 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x50,\
|
|
/* 136 */ 0x00, 0x40, 0x04, 0x04, 0x00, 0x40, 0x50, 0x40,\
|
|
/* 144 */ 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\
|
|
/* 152 */ 0x00, 0x10, 0x00, 0x00, 0x06, 0x10, 0x00, 0x04,\
|
|
/* 160 */ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
|
|
/* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x50,\
|
|
/* 176 */ 0x40, 0x00, 0x10, 0x10, 0x02, 0x12, 0x12, 0x00,\
|
|
/* 184 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}
|
|
|
|
/* The resolve3P2Values() routine is able to run faster if it knows
|
|
** the value of the largest JUMP opcode. The smaller the maximum
|
|
** JUMP opcode the better, so the mkopcodeh.tcl script that
|
|
** generated this include file strives to group all JUMP opcodes
|
|
** together near the beginning of the list.
|
|
*/
|
|
#define SQLITE_MX_JUMP_OPCODE 64 /* Maximum JUMP opcode */
|
|
|
|
/************** End of opcodes.h *********************************************/
|
|
/************** Continuing where we left off in vdbe.h ***********************/
|
|
|
|
/*
|
|
** Additional non-public SQLITE_PREPARE_* flags
|
|
*/
|
|
#define SQLITE_PREPARE_SAVESQL 0x80 /* Preserve SQL text */
|
|
#define SQLITE_PREPARE_MASK 0x0f /* Mask of public flags */
|
|
|
|
/*
|
|
** Prototypes for the VDBE interface. See comments on the implementation
|
|
** for a description of what each of these routines does.
|
|
*/
|
|
SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse*);
|
|
SQLITE_PRIVATE Parse *sqlite3VdbeParser(Vdbe*);
|
|
SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe*,int);
|
|
SQLITE_PRIVATE int sqlite3VdbeAddOp1(Vdbe*,int,int);
|
|
SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe*,int,int,int);
|
|
SQLITE_PRIVATE int sqlite3VdbeGoto(Vdbe*,int);
|
|
SQLITE_PRIVATE int sqlite3VdbeLoadString(Vdbe*,int,const char*);
|
|
SQLITE_PRIVATE void sqlite3VdbeMultiLoad(Vdbe*,int,const char*,...);
|
|
SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int);
|
|
SQLITE_PRIVATE int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int);
|
|
SQLITE_PRIVATE int sqlite3VdbeAddOp4Dup8(Vdbe*,int,int,int,int,const u8*,int);
|
|
SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
|
|
SQLITE_PRIVATE int sqlite3VdbeAddFunctionCall(Parse*,int,int,int,int,const FuncDef*,int);
|
|
SQLITE_PRIVATE void sqlite3VdbeEndCoroutine(Vdbe*,int);
|
|
#if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS)
|
|
SQLITE_PRIVATE void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N);
|
|
SQLITE_PRIVATE void sqlite3VdbeVerifyNoResultRow(Vdbe *p);
|
|
#else
|
|
# define sqlite3VdbeVerifyNoMallocRequired(A,B)
|
|
# define sqlite3VdbeVerifyNoResultRow(A)
|
|
#endif
|
|
#if defined(SQLITE_DEBUG)
|
|
SQLITE_PRIVATE void sqlite3VdbeVerifyAbortable(Vdbe *p, int);
|
|
SQLITE_PRIVATE void sqlite3VdbeNoJumpsOutsideSubrtn(Vdbe*,int,int,int);
|
|
#else
|
|
# define sqlite3VdbeVerifyAbortable(A,B)
|
|
# define sqlite3VdbeNoJumpsOutsideSubrtn(A,B,C,D)
|
|
#endif
|
|
SQLITE_PRIVATE VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno);
|
|
#ifndef SQLITE_OMIT_EXPLAIN
|
|
SQLITE_PRIVATE int sqlite3VdbeExplain(Parse*,u8,const char*,...);
|
|
SQLITE_PRIVATE void sqlite3VdbeExplainPop(Parse*);
|
|
SQLITE_PRIVATE int sqlite3VdbeExplainParent(Parse*);
|
|
# define ExplainQueryPlan(P) sqlite3VdbeExplain P
|
|
# ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
|
# define ExplainQueryPlan2(V,P) (V = sqlite3VdbeExplain P)
|
|
# else
|
|
# define ExplainQueryPlan2(V,P) ExplainQueryPlan(P)
|
|
# endif
|
|
# define ExplainQueryPlanPop(P) sqlite3VdbeExplainPop(P)
|
|
# define ExplainQueryPlanParent(P) sqlite3VdbeExplainParent(P)
|
|
#else
|
|
# define ExplainQueryPlan(P)
|
|
# define ExplainQueryPlan2(V,P)
|
|
# define ExplainQueryPlanPop(P)
|
|
# define ExplainQueryPlanParent(P) 0
|
|
# define sqlite3ExplainBreakpoint(A,B) /*no-op*/
|
|
#endif
|
|
#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_EXPLAIN)
|
|
SQLITE_PRIVATE void sqlite3ExplainBreakpoint(const char*,const char*);
|
|
#else
|
|
# define sqlite3ExplainBreakpoint(A,B) /*no-op*/
|
|
#endif
|
|
SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*, int, char*, u16);
|
|
SQLITE_PRIVATE void sqlite3VdbeChangeOpcode(Vdbe*, int addr, u8);
|
|
SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1);
|
|
SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
|
|
SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, int addr, int P3);
|
|
SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u16 P5);
|
|
SQLITE_PRIVATE void sqlite3VdbeTypeofColumn(Vdbe*, int);
|
|
SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr);
|
|
SQLITE_PRIVATE void sqlite3VdbeJumpHereOrPopInst(Vdbe*, int addr);
|
|
SQLITE_PRIVATE int sqlite3VdbeChangeToNoop(Vdbe*, int addr);
|
|
SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe*, u8 op);
|
|
#ifdef SQLITE_DEBUG
|
|
SQLITE_PRIVATE void sqlite3VdbeReleaseRegisters(Parse*,int addr, int n, u32 mask, int);
|
|
#else
|
|
# define sqlite3VdbeReleaseRegisters(P,A,N,M,F)
|
|
#endif
|
|
SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
|
|
SQLITE_PRIVATE void sqlite3VdbeAppendP4(Vdbe*, void *pP4, int p4type);
|
|
SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse*, Index*);
|
|
SQLITE_PRIVATE void sqlite3VdbeUsesBtree(Vdbe*, int);
|
|
SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
|
|
SQLITE_PRIVATE VdbeOp *sqlite3VdbeGetLastOp(Vdbe*);
|
|
SQLITE_PRIVATE int sqlite3VdbeMakeLabel(Parse*);
|
|
SQLITE_PRIVATE void sqlite3VdbeRunOnlyOnce(Vdbe*);
|
|
SQLITE_PRIVATE void sqlite3VdbeReusable(Vdbe*);
|
|
SQLITE_PRIVATE void sqlite3VdbeDelete(Vdbe*);
|
|
SQLITE_PRIVATE void sqlite3VdbeMakeReady(Vdbe*,Parse*);
|
|
SQLITE_PRIVATE int sqlite3VdbeFinalize(Vdbe*);
|
|
SQLITE_PRIVATE void sqlite3VdbeResolveLabel(Vdbe*, int);
|
|
SQLITE_PRIVATE int sqlite3VdbeCurrentAddr(Vdbe*);
|
|
#ifdef SQLITE_DEBUG
|
|
SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *, int);
|
|
#endif
|
|
SQLITE_PRIVATE void sqlite3VdbeResetStepResult(Vdbe*);
|
|
SQLITE_PRIVATE void sqlite3VdbeRewind(Vdbe*);
|
|
SQLITE_PRIVATE int sqlite3VdbeReset(Vdbe*);
|
|
SQLITE_PRIVATE void sqlite3VdbeSetNumCols(Vdbe*,int);
|
|
SQLITE_PRIVATE int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, void(*)(void*));
|
|
SQLITE_PRIVATE void sqlite3VdbeCountChanges(Vdbe*);
|
|
SQLITE_PRIVATE sqlite3 *sqlite3VdbeDb(Vdbe*);
|
|
SQLITE_PRIVATE u8 sqlite3VdbePrepareFlags(Vdbe*);
|
|
SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, u8);
|
|
#ifdef SQLITE_ENABLE_NORMALIZE
|
|
SQLITE_PRIVATE void sqlite3VdbeAddDblquoteStr(sqlite3*,Vdbe*,const char*);
|
|
SQLITE_PRIVATE int sqlite3VdbeUsesDoubleQuotedString(Vdbe*,const char*);
|
|
#endif
|
|
SQLITE_PRIVATE void sqlite3VdbeSwap(Vdbe*,Vdbe*);
|
|
SQLITE_PRIVATE VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*);
|
|
SQLITE_PRIVATE sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe*, int, u8);
|
|
SQLITE_PRIVATE void sqlite3VdbeSetVarmask(Vdbe*, int);
|
|
#ifndef SQLITE_OMIT_TRACE
|
|
SQLITE_PRIVATE char *sqlite3VdbeExpandSql(Vdbe*, const char*);
|
|
#endif
|
|
SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
|
|
SQLITE_PRIVATE int sqlite3BlobCompare(const Mem*, const Mem*);
|
|
|
|
SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
|
|
SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
|
|
SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(int, const void *, UnpackedRecord *, int);
|
|
SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo*);
|
|
|
|
typedef int (*RecordCompare)(int,const void*,UnpackedRecord*);
|
|
SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);
|
|
|
|
SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
|
|
SQLITE_PRIVATE int sqlite3VdbeHasSubProgram(Vdbe*);
|
|
|
|
SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context*);
|
|
#ifdef SQLITE_ENABLE_BYTECODE_VTAB
|
|
SQLITE_PRIVATE int sqlite3VdbeBytecodeVtabInit(sqlite3*);
|
|
#endif
|
|
|
|
/* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on
|
|
** each VDBE opcode.
|
|
**
|
|
** Use the SQLITE_ENABLE_MODULE_COMMENTS macro to see some extra no-op
|
|
** comments in VDBE programs that show key decision points in the code
|
|
** generator.
|
|
*/
|
|
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
|
SQLITE_PRIVATE void sqlite3VdbeComment(Vdbe*, const char*, ...);
|
|
# define VdbeComment(X) sqlite3VdbeComment X
|
|
SQLITE_PRIVATE void sqlite3VdbeNoopComment(Vdbe*, const char*, ...);
|
|
# define VdbeNoopComment(X) sqlite3VdbeNoopComment X
|
|
# ifdef SQLITE_ENABLE_MODULE_COMMENTS
|
|
# define VdbeModuleComment(X) sqlite3VdbeNoopComment X
|
|
# else
|
|
# define VdbeModuleComment(X)
|
|
# endif
|
|
#else
|
|
# define VdbeComment(X)
|
|
# define VdbeNoopComment(X)
|
|
# define VdbeModuleComment(X)
|
|
#endif
|
|
|
|
/*
|
|
** The VdbeCoverage macros are used to set a coverage testing point
|
|
** for VDBE branch instructions. The coverage testing points are line
|
|
** numbers in the sqlite3.c source file. VDBE branch coverage testing
|
|
** only works with an amalgamation build. That's ok since a VDBE branch
|
|
** coverage build designed for testing the test suite only. No application
|
|
** should ever ship with VDBE branch coverage measuring turned on.
|
|
**
|
|
** VdbeCoverage(v) // Mark the previously coded instruction
|
|
** // as a branch
|
|
**
|
|
** VdbeCoverageIf(v, conditional) // Mark previous if conditional true
|
|
**
|
|
** VdbeCoverageAlwaysTaken(v) // Previous branch is always taken
|
|
**
|
|
** VdbeCoverageNeverTaken(v) // Previous branch is never taken
|
|
**
|
|
** VdbeCoverageNeverNull(v) // Previous three-way branch is only
|
|
** // taken on the first two ways. The
|
|
** // NULL option is not possible
|
|
**
|
|
** VdbeCoverageEqNe(v) // Previous OP_Jump is only interested
|
|
** // in distinguishing equal and not-equal.
|
|
**
|
|
** Every VDBE branch operation must be tagged with one of the macros above.
|
|
** If not, then when "make test" is run with -DSQLITE_VDBE_COVERAGE and
|
|
** -DSQLITE_DEBUG then an ALWAYS() will fail in the vdbeTakeBranch()
|
|
** routine in vdbe.c, alerting the developer to the missed tag.
|
|
**
|
|
** During testing, the test application will invoke
|
|
** sqlite3_test_control(SQLITE_TESTCTRL_VDBE_COVERAGE,...) to set a callback
|
|
** routine that is invoked as each bytecode branch is taken. The callback
|
|
** contains the sqlite3.c source line number of the VdbeCoverage macro and
|
|
** flags to indicate whether or not the branch was taken. The test application
|
|
** is responsible for keeping track of this and reporting byte-code branches
|
|
** that are never taken.
|
|
**
|
|
** See the VdbeBranchTaken() macro and vdbeTakeBranch() function in the
|
|
** vdbe.c source file for additional information.
|
|
*/
|
|
#ifdef SQLITE_VDBE_COVERAGE
|
|
SQLITE_PRIVATE void sqlite3VdbeSetLineNumber(Vdbe*,int);
|
|
# define VdbeCoverage(v) sqlite3VdbeSetLineNumber(v,__LINE__)
|
|
# define VdbeCoverageIf(v,x) if(x)sqlite3VdbeSetLineNumber(v,__LINE__)
|
|
# define VdbeCoverageAlwaysTaken(v) \
|
|
sqlite3VdbeSetLineNumber(v,__LINE__|0x5000000);
|
|
# define VdbeCoverageNeverTaken(v) \
|
|
sqlite3VdbeSetLineNumber(v,__LINE__|0x6000000);
|
|
# define VdbeCoverageNeverNull(v) \
|
|
sqlite3VdbeSetLineNumber(v,__LINE__|0x4000000);
|
|
# define VdbeCoverageNeverNullIf(v,x) \
|
|
if(x)sqlite3VdbeSetLineNumber(v,__LINE__|0x4000000);
|
|
# define VdbeCoverageEqNe(v) \
|
|
sqlite3VdbeSetLineNumber(v,__LINE__|0x8000000);
|
|
# define VDBE_OFFSET_LINENO(x) (__LINE__+x)
|
|
#else
|
|
# define VdbeCoverage(v)
|
|
# define VdbeCoverageIf(v,x)
|
|
# define VdbeCoverageAlwaysTaken(v)
|
|
# define VdbeCoverageNeverTaken(v)
|
|
# define VdbeCoverageNeverNull(v)
|
|
# define VdbeCoverageNeverNullIf(v,x)
|
|
# define VdbeCoverageEqNe(v)
|
|
# define VDBE_OFFSET_LINENO(x) 0
|
|
#endif
|
|
|
|
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
|
SQLITE_PRIVATE void sqlite3VdbeScanStatus(Vdbe*, int, int, int, LogEst, const char*);
|
|
SQLITE_PRIVATE void sqlite3VdbeScanStatusRange(Vdbe*, int, int, int);
|
|
SQLITE_PRIVATE void sqlite3VdbeScanStatusCounters(Vdbe*, int, int, int);
|
|
#else
|
|
# define sqlite3VdbeScanStatus(a,b,c,d,e,f)
|
|
# define sqlite3VdbeScanStatusRange(a,b,c,d)
|
|
# define sqlite3VdbeScanStatusCounters(a,b,c,d)
|
|
#endif
|
|
|
|
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
|
|
SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE*, int, VdbeOp*);
|
|
#endif
|
|
|
|
#if defined(SQLITE_ENABLE_CURSOR_HINTS) && defined(SQLITE_DEBUG)
|
|
SQLITE_PRIVATE int sqlite3CursorRangeHintExprCheck(Walker *pWalker, Expr *pExpr);
|
|
#endif
|
|
|
|
#endif /* SQLITE_VDBE_H */
|
|
|
|
/************** End of vdbe.h ************************************************/
|
|
/************** Continuing where we left off in sqliteInt.h ******************/
|
|
/************** Include pcache.h in the middle of sqliteInt.h ****************/
|
|
/************** Begin file pcache.h ******************************************/
|
|
/*
|
|
** 2008 August 05
|
|
**
|
|
** 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.
|
|
*/
|
|
|
|
#ifndef _PCACHE_H_
|
|
|
|
typedef struct PgHdr PgHdr;
|
|
typedef struct PCache PCache;
|
|
|
|
/*
|
|
** Every page in the cache is controlled by an instance of the following
|
|
** structure.
|
|
*/
|
|
struct PgHdr {
|
|
sqlite3_pcache_page *pPage; /* Pcache object page handle */
|
|
void *pData; /* Page data */
|
|
void *pExtra; /* Extra content */
|
|
PCache *pCache; /* PRIVATE: Cache that owns this page */
|
|
PgHdr *pDirty; /* Transient list of dirty sorted by pgno */
|
|
Pager *pPager; /* The pager this page is part of */
|
|
Pgno pgno; /* Page number for this page */
|
|
#ifdef SQLITE_CHECK_PAGES
|
|
u32 pageHash; /* Hash of page content */
|
|
#endif
|
|
u16 flags; /* PGHDR flags defined below */
|
|
|
|
/**********************************************************************
|
|
** Elements above, except pCache, are public. All that follow are
|
|
** private to pcache.c and should not be accessed by other modules.
|
|
** pCache is grouped with the public elements for efficiency.
|
|
*/
|
|
i64 nRef; /* Number of users of this page */
|
|
PgHdr *pDirtyNext; /* Next element in list of dirty pages */
|
|
PgHdr *pDirtyPrev; /* Previous element in list of dirty pages */
|
|
/* NB: pDirtyNext and pDirtyPrev are undefined if the
|
|
** PgHdr object is not dirty */
|
|
};
|
|
|
|
/* Bit values for PgHdr.flags */
|
|
#define PGHDR_CLEAN 0x001 /* Page not on the PCache.pDirty list */
|
|
#define PGHDR_DIRTY 0x002 /* Page is on the PCache.pDirty list */
|
|
#define PGHDR_WRITEABLE 0x004 /* Journaled and ready to modify */
|
|
#define PGHDR_NEED_SYNC 0x008 /* Fsync the rollback journal before
|
|
** writing this page to the database */
|
|
#define PGHDR_DONT_WRITE 0x010 /* Do not write content to disk */
|
|
#define PGHDR_MMAP 0x020 /* This is an mmap page object */
|
|
|
|
#define PGHDR_WAL_APPEND 0x040 /* Appended to wal file */
|
|
|
|
/* Initialize and shutdown the page cache subsystem */
|
|
SQLITE_PRIVATE int sqlite3PcacheInitialize(void);
|
|
SQLITE_PRIVATE void sqlite3PcacheShutdown(void);
|
|
|
|
/* Page cache buffer management:
|
|
** These routines implement SQLITE_CONFIG_PAGECACHE.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *, int sz, int n);
|
|
|
|
/* Create a new pager cache.
|
|
** Under memory stress, invoke xStress to try to make pages clean.
|
|
** Only clean and unpinned pages can be reclaimed.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3PcacheOpen(
|
|
int szPage, /* Size of every page */
|
|
int szExtra, /* Extra space associated with each page */
|
|
int bPurgeable, /* True if pages are on backing store */
|
|
int (*xStress)(void*, PgHdr*), /* Call to try to make pages clean */
|
|
void *pStress, /* Argument to xStress */
|
|
PCache *pToInit /* Preallocated space for the PCache */
|
|
);
|
|
|
|
/* Modify the page-size after the cache has been created. */
|
|
SQLITE_PRIVATE int sqlite3PcacheSetPageSize(PCache *, int);
|
|
|
|
/* Return the size in bytes of a PCache object. Used to preallocate
|
|
** storage space.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3PcacheSize(void);
|
|
|
|
/* One release per successful fetch. Page is pinned until released.
|
|
** Reference counted.
|
|
*/
|
|
SQLITE_PRIVATE sqlite3_pcache_page *sqlite3PcacheFetch(PCache*, Pgno, int createFlag);
|
|
SQLITE_PRIVATE int sqlite3PcacheFetchStress(PCache*, Pgno, sqlite3_pcache_page**);
|
|
SQLITE_PRIVATE PgHdr *sqlite3PcacheFetchFinish(PCache*, Pgno, sqlite3_pcache_page *pPage);
|
|
SQLITE_PRIVATE void sqlite3PcacheRelease(PgHdr*);
|
|
|
|
SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr*); /* Remove page from cache */
|
|
SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr*); /* Make sure page is marked dirty */
|
|
SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr*); /* Mark a single page as clean */
|
|
SQLITE_PRIVATE void sqlite3PcacheCleanAll(PCache*); /* Mark all dirty list pages as clean */
|
|
SQLITE_PRIVATE void sqlite3PcacheClearWritable(PCache*);
|
|
|
|
/* Change a page number. Used by incr-vacuum. */
|
|
SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr*, Pgno);
|
|
|
|
/* Remove all pages with pgno>x. Reset the cache if x==0 */
|
|
SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache*, Pgno x);
|
|
|
|
/* Get a list of all dirty pages in the cache, sorted by page number */
|
|
SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache*);
|
|
|
|
/* Reset and close the cache object */
|
|
SQLITE_PRIVATE void sqlite3PcacheClose(PCache*);
|
|
|
|
/* Clear flags from pages of the page cache */
|
|
SQLITE_PRIVATE void sqlite3PcacheClearSyncFlags(PCache *);
|
|
|
|
/* Discard the contents of the cache */
|
|
SQLITE_PRIVATE void sqlite3PcacheClear(PCache*);
|
|
|
|
/* Return the total number of outstanding page references */
|
|
SQLITE_PRIVATE i64 sqlite3PcacheRefCount(PCache*);
|
|
|
|
/* Increment the reference count of an existing page */
|
|
SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr*);
|
|
|
|
SQLITE_PRIVATE i64 sqlite3PcachePageRefcount(PgHdr*);
|
|
|
|
/* Return the total number of pages stored in the cache */
|
|
SQLITE_PRIVATE int sqlite3PcachePagecount(PCache*);
|
|
|
|
#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
|
|
/* Iterate through all dirty pages currently stored in the cache. This
|
|
** interface is only available if SQLITE_CHECK_PAGES is defined when the
|
|
** library is built.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *));
|
|
#endif
|
|
|
|
#if defined(SQLITE_DEBUG)
|
|
/* Check invariants on a PgHdr object */
|
|
SQLITE_PRIVATE int sqlite3PcachePageSanity(PgHdr*);
|
|
#endif
|
|
|
|
/* Set and get the suggested cache-size for the specified pager-cache.
|
|
**
|
|
** If no global maximum is configured, then the system attempts to limit
|
|
** the total number of pages cached by purgeable pager-caches to the sum
|
|
** of the suggested cache-sizes.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3PcacheSetCachesize(PCache *, int);
|
|
#ifdef SQLITE_TEST
|
|
SQLITE_PRIVATE int sqlite3PcacheGetCachesize(PCache *);
|
|
#endif
|
|
|
|
/* Set or get the suggested spill-size for the specified pager-cache.
|
|
**
|
|
** The spill-size is the minimum number of pages in cache before the cache
|
|
** will attempt to spill dirty pages by calling xStress.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3PcacheSetSpillsize(PCache *, int);
|
|
|
|
/* Free up as much memory as possible from the page cache */
|
|
SQLITE_PRIVATE void sqlite3PcacheShrink(PCache*);
|
|
|
|
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
|
/* Try to return memory used by the pcache module to the main memory heap */
|
|
SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int);
|
|
#endif
|
|
|
|
#ifdef SQLITE_TEST
|
|
SQLITE_PRIVATE void sqlite3PcacheStats(int*,int*,int*,int*);
|
|
#endif
|
|
|
|
SQLITE_PRIVATE void sqlite3PCacheSetDefault(void);
|
|
|
|
/* Return the header size */
|
|
SQLITE_PRIVATE int sqlite3HeaderSizePcache(void);
|
|
SQLITE_PRIVATE int sqlite3HeaderSizePcache1(void);
|
|
|
|
/* Number of dirty pages as a percentage of the configured cache size */
|
|
SQLITE_PRIVATE int sqlite3PCachePercentDirty(PCache*);
|
|
|
|
#ifdef SQLITE_DIRECT_OVERFLOW_READ
|
|
SQLITE_PRIVATE int sqlite3PCacheIsDirty(PCache *pCache);
|
|
#endif
|
|
|
|
#endif /* _PCACHE_H_ */
|
|
|
|
/************** End of pcache.h **********************************************/
|
|
/************** Continuing where we left off in sqliteInt.h ******************/
|
|
/************** Include mutex.h in the middle of sqliteInt.h *****************/
|
|
/************** Begin file mutex.h *******************************************/
|
|
/*
|
|
** 2007 August 28
|
|
**
|
|
** 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 common header for all mutex implementations.
|
|
** The sqliteInt.h header #includes this file so that it is available
|
|
** to all source files. We break it out in an effort to keep the code
|
|
** better organized.
|
|
**
|
|
** NOTE: source files should *not* #include this header file directly.
|
|
** Source files should #include the sqliteInt.h file and let that file
|
|
** include this one indirectly.
|
|
*/
|
|
|
|
|
|
/*
|
|
** Figure out what version of the code to use. The choices are
|
|
**
|
|
** SQLITE_MUTEX_OMIT No mutex logic. Not even stubs. The
|
|
** mutexes implementation cannot be overridden
|
|
** at start-time.
|
|
**
|
|
** SQLITE_MUTEX_NOOP For single-threaded applications. No
|
|
** mutual exclusion is provided. But this
|
|
** implementation can be overridden at
|
|
** start-time.
|
|
**
|
|
** SQLITE_MUTEX_PTHREADS For multi-threaded applications on Unix.
|
|
**
|
|
** SQLITE_MUTEX_W32 For multi-threaded applications on Win32.
|
|
*/
|
|
#if !SQLITE_THREADSAFE
|
|
# define SQLITE_MUTEX_OMIT
|
|
#endif
|
|
#if SQLITE_THREADSAFE && !defined(SQLITE_MUTEX_NOOP)
|
|
# if SQLITE_OS_UNIX
|
|
# define SQLITE_MUTEX_PTHREADS
|
|
# elif SQLITE_OS_WIN
|
|
# define SQLITE_MUTEX_W32
|
|
# else
|
|
# define SQLITE_MUTEX_NOOP
|
|
# endif
|
|
#endif
|
|
|
|
#ifdef SQLITE_MUTEX_OMIT
|
|
/*
|
|
** If this is a no-op implementation, implement everything as macros.
|
|
*/
|
|
#define sqlite3_mutex_alloc(X) ((sqlite3_mutex*)8)
|
|
#define sqlite3_mutex_free(X)
|
|
#define sqlite3_mutex_enter(X)
|
|
#define sqlite3_mutex_try(X) SQLITE_OK
|
|
#define sqlite3_mutex_leave(X)
|
|
#define sqlite3_mutex_held(X) ((void)(X),1)
|
|
#define sqlite3_mutex_notheld(X) ((void)(X),1)
|
|
#define sqlite3MutexAlloc(X) ((sqlite3_mutex*)8)
|
|
#define sqlite3MutexInit() SQLITE_OK
|
|
#define sqlite3MutexEnd()
|
|
#define MUTEX_LOGIC(X)
|
|
#else
|
|
#define MUTEX_LOGIC(X) X
|
|
SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*);
|
|
#endif /* defined(SQLITE_MUTEX_OMIT) */
|
|
|
|
/************** End of mutex.h ***********************************************/
|
|
/************** Continuing where we left off in sqliteInt.h ******************/
|
|
|
|
/* The SQLITE_EXTRA_DURABLE compile-time option used to set the default
|
|
** synchronous setting to EXTRA. It is no longer supported.
|
|
*/
|
|
#ifdef SQLITE_EXTRA_DURABLE
|
|
# warning Use SQLITE_DEFAULT_SYNCHRONOUS=3 instead of SQLITE_EXTRA_DURABLE
|
|
# define SQLITE_DEFAULT_SYNCHRONOUS 3
|
|
#endif
|
|
|
|
/*
|
|
** Default synchronous levels.
|
|
**
|
|
** Note that (for historical reasons) the PAGER_SYNCHRONOUS_* macros differ
|
|
** from the SQLITE_DEFAULT_SYNCHRONOUS value by 1.
|
|
**
|
|
** PAGER_SYNCHRONOUS DEFAULT_SYNCHRONOUS
|
|
** OFF 1 0
|
|
** NORMAL 2 1
|
|
** FULL 3 2
|
|
** EXTRA 4 3
|
|
**
|
|
** The "PRAGMA synchronous" statement also uses the zero-based numbers.
|
|
** In other words, the zero-based numbers are used for all external interfaces
|
|
** and the one-based values are used internally.
|
|
*/
|
|
#ifndef SQLITE_DEFAULT_SYNCHRONOUS
|
|
# define SQLITE_DEFAULT_SYNCHRONOUS 2
|
|
#endif
|
|
#ifndef SQLITE_DEFAULT_WAL_SYNCHRONOUS
|
|
# define SQLITE_DEFAULT_WAL_SYNCHRONOUS SQLITE_DEFAULT_SYNCHRONOUS
|
|
#endif
|
|
|
|
/*
|
|
** 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 *zDbSName; /* Name of this database. (schema name, not filename) */
|
|
Btree *pBt; /* The B*Tree structure for this database file */
|
|
u8 safety_level; /* How aggressive at syncing data to disk */
|
|
u8 bSyncSet; /* True if "PRAGMA synchronous=N" has been run */
|
|
Schema *pSchema; /* Pointer to database schema (possibly shared) */
|
|
};
|
|
|
|
/*
|
|
** An instance of the following structure stores a database schema.
|
|
**
|
|
** Most Schema objects are associated with a Btree. The exception is
|
|
** the Schema for the TEMP database (sqlite3.aDb[1]) which is free-standing.
|
|
** In shared cache mode, a single Schema object can be shared by multiple
|
|
** Btrees that refer to the same underlying BtShared object.
|
|
**
|
|
** Schema objects are automatically deallocated when the last Btree that
|
|
** references them is destroyed. The TEMP Schema is manually freed by
|
|
** sqlite3_close().
|
|
*
|
|
** A thread must be holding a mutex on the corresponding Btree in order
|
|
** to access Schema content. This implies that the thread must also be
|
|
** holding a mutex on the sqlite3 connection pointer that owns the Btree.
|
|
** For a TEMP Schema, only the connection mutex is required.
|
|
*/
|
|
struct Schema {
|
|
int schema_cookie; /* Database schema version number for this file */
|
|
int iGeneration; /* Generation counter. Incremented with each change */
|
|
Hash tblHash; /* All tables indexed by name */
|
|
Hash idxHash; /* All (named) indices indexed by name */
|
|
Hash trigHash; /* All triggers indexed by name */
|
|
Hash fkeyHash; /* All foreign keys by referenced table name */
|
|
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 schemaFlags; /* Flags associated with this schema */
|
|
int cache_size; /* Number of pages to use in the cache */
|
|
};
|
|
|
|
/*
|
|
** These macros can be used to test, set, or clear bits in the
|
|
** Db.pSchema->flags field.
|
|
*/
|
|
#define DbHasProperty(D,I,P) (((D)->aDb[I].pSchema->schemaFlags&(P))==(P))
|
|
#define DbHasAnyProperty(D,I,P) (((D)->aDb[I].pSchema->schemaFlags&(P))!=0)
|
|
#define DbSetProperty(D,I,P) (D)->aDb[I].pSchema->schemaFlags|=(P)
|
|
#define DbClearProperty(D,I,P) (D)->aDb[I].pSchema->schemaFlags&=~(P)
|
|
|
|
/*
|
|
** Allowed values for the DB.pSchema->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_ResetWanted 0x0008 /* Reset the schema when nSchemaLock==0 */
|
|
|
|
/*
|
|
** The number of different kinds of things that can be limited
|
|
** using the sqlite3_limit() interface.
|
|
*/
|
|
#define SQLITE_N_LIMIT (SQLITE_LIMIT_WORKER_THREADS+1)
|
|
|
|
/*
|
|
** Lookaside malloc is a set of fixed-size buffers that can be used
|
|
** to satisfy small transient memory allocation requests for objects
|
|
** associated with a particular database connection. The use of
|
|
** lookaside malloc provides a significant performance enhancement
|
|
** (approx 10%) by avoiding numerous malloc/free requests while parsing
|
|
** SQL statements.
|
|
**
|
|
** The Lookaside structure holds configuration information about the
|
|
** lookaside malloc subsystem. Each available memory allocation in
|
|
** the lookaside subsystem is stored on a linked list of LookasideSlot
|
|
** objects.
|
|
**
|
|
** Lookaside allocations are only allowed for objects that are associated
|
|
** with a particular database connection. Hence, schema information cannot
|
|
** be stored in lookaside because in shared cache mode the schema information
|
|
** is shared by multiple database connections. Therefore, while parsing
|
|
** schema information, the Lookaside.bEnabled flag is cleared so that
|
|
** lookaside allocations are not used to construct the schema objects.
|
|
**
|
|
** New lookaside allocations are only allowed if bDisable==0. When
|
|
** bDisable is greater than zero, sz is set to zero which effectively
|
|
** disables lookaside without adding a new test for the bDisable flag
|
|
** in a performance-critical path. sz should be set by to szTrue whenever
|
|
** bDisable changes back to zero.
|
|
**
|
|
** Lookaside buffers are initially held on the pInit list. As they are
|
|
** used and freed, they are added back to the pFree list. New allocations
|
|
** come off of pFree first, then pInit as a fallback. This dual-list
|
|
** allows use to compute a high-water mark - the maximum number of allocations
|
|
** outstanding at any point in the past - by subtracting the number of
|
|
** allocations on the pInit list from the total number of allocations.
|
|
**
|
|
** Enhancement on 2019-12-12: Two-size-lookaside
|
|
** The default lookaside configuration is 100 slots of 1200 bytes each.
|
|
** The larger slot sizes are important for performance, but they waste
|
|
** a lot of space, as most lookaside allocations are less than 128 bytes.
|
|
** The two-size-lookaside enhancement breaks up the lookaside allocation
|
|
** into two pools: One of 128-byte slots and the other of the default size
|
|
** (1200-byte) slots. Allocations are filled from the small-pool first,
|
|
** failing over to the full-size pool if that does not work. Thus more
|
|
** lookaside slots are available while also using less memory.
|
|
** This enhancement can be omitted by compiling with
|
|
** SQLITE_OMIT_TWOSIZE_LOOKASIDE.
|
|
*/
|
|
struct Lookaside {
|
|
u32 bDisable; /* Only operate the lookaside when zero */
|
|
u16 sz; /* Size of each buffer in bytes */
|
|
u16 szTrue; /* True value of sz, even if disabled */
|
|
u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */
|
|
u32 nSlot; /* Number of lookaside slots allocated */
|
|
u32 anStat[3]; /* 0: hits. 1: size misses. 2: full misses */
|
|
LookasideSlot *pInit; /* List of buffers not previously used */
|
|
LookasideSlot *pFree; /* List of available buffers */
|
|
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
|
LookasideSlot *pSmallInit; /* List of small buffers not previously used */
|
|
LookasideSlot *pSmallFree; /* List of available small buffers */
|
|
void *pMiddle; /* First byte past end of full-size buffers and
|
|
** the first byte of LOOKASIDE_SMALL buffers */
|
|
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
|
|
void *pStart; /* First byte of available memory space */
|
|
void *pEnd; /* First byte past end of available space */
|
|
void *pTrueEnd; /* True value of pEnd, when db->pnBytesFreed!=0 */
|
|
};
|
|
struct LookasideSlot {
|
|
LookasideSlot *pNext; /* Next buffer in the list of free buffers */
|
|
};
|
|
|
|
#define DisableLookaside db->lookaside.bDisable++;db->lookaside.sz=0
|
|
#define EnableLookaside db->lookaside.bDisable--;\
|
|
db->lookaside.sz=db->lookaside.bDisable?0:db->lookaside.szTrue
|
|
|
|
/* Size of the smaller allocations in two-size lookaside */
|
|
#ifdef SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
|
# define LOOKASIDE_SMALL 0
|
|
#else
|
|
# define LOOKASIDE_SMALL 128
|
|
#endif
|
|
|
|
/*
|
|
** A hash table for built-in function definitions. (Application-defined
|
|
** functions use a regular table table from hash.h.)
|
|
**
|
|
** Hash each FuncDef structure into one of the FuncDefHash.a[] slots.
|
|
** Collisions are on the FuncDef.u.pHash chain. Use the SQLITE_FUNC_HASH()
|
|
** macro to compute a hash on the function name.
|
|
*/
|
|
#define SQLITE_FUNC_HASH_SZ 23
|
|
struct FuncDefHash {
|
|
FuncDef *a[SQLITE_FUNC_HASH_SZ]; /* Hash table for functions */
|
|
};
|
|
#define SQLITE_FUNC_HASH(C,L) (((C)+(L))%SQLITE_FUNC_HASH_SZ)
|
|
|
|
#ifdef SQLITE_USER_AUTHENTICATION
|
|
/*
|
|
** Information held in the "sqlite3" database connection object and used
|
|
** to manage user authentication.
|
|
*/
|
|
typedef struct sqlite3_userauth sqlite3_userauth;
|
|
struct sqlite3_userauth {
|
|
u8 authLevel; /* Current authentication level */
|
|
int nAuthPW; /* Size of the zAuthPW in bytes */
|
|
char *zAuthPW; /* Password used to authenticate */
|
|
char *zAuthUser; /* User name used to authenticate */
|
|
};
|
|
|
|
/* Allowed values for sqlite3_userauth.authLevel */
|
|
#define UAUTH_Unknown 0 /* Authentication not yet checked */
|
|
#define UAUTH_Fail 1 /* User authentication failed */
|
|
#define UAUTH_User 2 /* Authenticated as a normal user */
|
|
#define UAUTH_Admin 3 /* Authenticated as an administrator */
|
|
|
|
/* Functions used only by user authorization logic */
|
|
SQLITE_PRIVATE int sqlite3UserAuthTable(const char*);
|
|
SQLITE_PRIVATE int sqlite3UserAuthCheckLogin(sqlite3*,const char*,u8*);
|
|
SQLITE_PRIVATE void sqlite3UserAuthInit(sqlite3*);
|
|
SQLITE_PRIVATE void sqlite3CryptFunc(sqlite3_context*,int,sqlite3_value**);
|
|
|
|
#endif /* SQLITE_USER_AUTHENTICATION */
|
|
|
|
/*
|
|
** typedef for the authorization callback function.
|
|
*/
|
|
#ifdef SQLITE_USER_AUTHENTICATION
|
|
typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*,
|
|
const char*, const char*);
|
|
#else
|
|
typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*,
|
|
const char*);
|
|
#endif
|
|
|
|
#ifndef SQLITE_OMIT_DEPRECATED
|
|
/* This is an extra SQLITE_TRACE macro that indicates "legacy" tracing
|
|
** in the style of sqlite3_trace()
|
|
*/
|
|
#define SQLITE_TRACE_LEGACY 0x40 /* Use the legacy xTrace */
|
|
#define SQLITE_TRACE_XPROFILE 0x80 /* Use the legacy xProfile */
|
|
#else
|
|
#define SQLITE_TRACE_LEGACY 0
|
|
#define SQLITE_TRACE_XPROFILE 0
|
|
#endif /* SQLITE_OMIT_DEPRECATED */
|
|
#define SQLITE_TRACE_NONLEGACY_MASK 0x0f /* Normal flags */
|
|
|
|
/*
|
|
** Maximum number of sqlite3.aDb[] entries. This is the number of attached
|
|
** databases plus 2 for "main" and "temp".
|
|
*/
|
|
#define SQLITE_MAX_DB (SQLITE_MAX_ATTACHED+2)
|
|
|
|
/*
|
|
** Each database connection is an instance of the following structure.
|
|
*/
|
|
struct sqlite3 {
|
|
sqlite3_vfs *pVfs; /* OS Interface */
|
|
struct Vdbe *pVdbe; /* List of active virtual machines */
|
|
CollSeq *pDfltColl; /* BINARY collseq for the database encoding */
|
|
sqlite3_mutex *mutex; /* Connection mutex */
|
|
Db *aDb; /* All backends */
|
|
int nDb; /* Number of backends currently in use */
|
|
u32 mDbFlags; /* flags recording internal state */
|
|
u64 flags; /* flags settable by pragmas. See below */
|
|
i64 lastRowid; /* ROWID of most recent insert (see above) */
|
|
i64 szMmap; /* Default mmap_size setting */
|
|
u32 nSchemaLock; /* Do not reset the schema when non-zero */
|
|
unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */
|
|
int errCode; /* Most recent error code (SQLITE_*) */
|
|
int errByteOffset; /* Byte offset of error in SQL statement */
|
|
int errMask; /* & result codes with this before returning */
|
|
int iSysErrno; /* Errno value from last system error */
|
|
u32 dbOptFlags; /* Flags to enable/disable optimizations */
|
|
u8 enc; /* Text encoding */
|
|
u8 autoCommit; /* The auto-commit flag. */
|
|
u8 temp_store; /* 1: file 2: memory 0: default */
|
|
u8 mallocFailed; /* True if we have seen a malloc failure */
|
|
u8 bBenignMalloc; /* Do not require OOMs if true */
|
|
u8 dfltLockMode; /* Default locking-mode for attached dbs */
|
|
signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */
|
|
u8 suppressErr; /* Do not issue error messages if true */
|
|
u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */
|
|
u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */
|
|
u8 mTrace; /* zero or more SQLITE_TRACE flags */
|
|
u8 noSharedCache; /* True if no shared-cache backends */
|
|
u8 nSqlExec; /* Number of pending OP_SqlExec opcodes */
|
|
u8 eOpenState; /* Current condition of the connection */
|
|
int nextPagesize; /* Pagesize after VACUUM if >0 */
|
|
i64 nChange; /* Value returned by sqlite3_changes() */
|
|
i64 nTotalChange; /* Value returned by sqlite3_total_changes() */
|
|
int aLimit[SQLITE_N_LIMIT]; /* Limits */
|
|
int nMaxSorterMmap; /* Maximum size of regions mapped by sorter */
|
|
struct sqlite3InitInfo { /* Information used during initialization */
|
|
Pgno newTnum; /* Rootpage of table being initialized */
|
|
u8 iDb; /* Which db file is being initialized */
|
|
u8 busy; /* TRUE if currently initializing */
|
|
unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */
|
|
unsigned imposterTable : 1; /* Building an imposter table */
|
|
unsigned reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */
|
|
const char **azInit; /* "type", "name", and "tbl_name" columns */
|
|
} init;
|
|
int nVdbeActive; /* Number of VDBEs currently running */
|
|
int nVdbeRead; /* Number of active VDBEs that read or write */
|
|
int nVdbeWrite; /* Number of active VDBEs that read and write */
|
|
int nVdbeExec; /* Number of nested calls to VdbeExec() */
|
|
int nVDestroy; /* Number of active OP_VDestroy operations */
|
|
int nExtension; /* Number of loaded extensions */
|
|
void **aExtension; /* Array of shared library handles */
|
|
union {
|
|
void (*xLegacy)(void*,const char*); /* mTrace==SQLITE_TRACE_LEGACY */
|
|
int (*xV2)(u32,void*,void*,void*); /* All other mTrace values */
|
|
} trace;
|
|
void *pTraceArg; /* Argument to the trace function */
|
|
#ifndef SQLITE_OMIT_DEPRECATED
|
|
void (*xProfile)(void*,const char*,u64); /* Profiling function */
|
|
void *pProfileArg; /* Argument to profile function */
|
|
#endif
|
|
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 *pAutovacPagesArg; /* Client argument to autovac_pages */
|
|
void (*xAutovacDestr)(void*); /* Destructor for pAutovacPAgesArg */
|
|
unsigned int (*xAutovacPages)(void*,const char*,u32,u32,u32);
|
|
Parse *pParse; /* Current parse */
|
|
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
|
|
void *pPreUpdateArg; /* First argument to xPreUpdateCallback */
|
|
void (*xPreUpdateCallback)( /* Registered using sqlite3_preupdate_hook() */
|
|
void*,sqlite3*,int,char const*,char const*,sqlite3_int64,sqlite3_int64
|
|
);
|
|
PreUpdate *pPreUpdate; /* Context for active pre-update callback */
|
|
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
|
|
#ifndef SQLITE_OMIT_WAL
|
|
int (*xWalCallback)(void *, sqlite3 *, const char *, int);
|
|
void *pWalArg;
|
|
#endif
|
|
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 */
|
|
union {
|
|
volatile int isInterrupted; /* True if sqlite3_interrupt has been called */
|
|
double notUsed1; /* Spacer */
|
|
} u1;
|
|
Lookaside lookaside; /* Lookaside malloc configuration */
|
|
#ifndef SQLITE_OMIT_AUTHORIZATION
|
|
sqlite3_xauth xAuth; /* 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 */
|
|
unsigned nProgressOps; /* Number of opcodes for progress callback */
|
|
#endif
|
|
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
|
int nVTrans; /* Allocated size of aVTrans */
|
|
Hash aModule; /* populated by sqlite3_create_module() */
|
|
VtabCtx *pVtabCtx; /* Context for active vtab connect/create */
|
|
VTable **aVTrans; /* Virtual tables with open transactions */
|
|
VTable *pDisconnect; /* Disconnect these in next sqlite3_prepare() */
|
|
#endif
|
|
Hash aFunc; /* Hash table of connection functions */
|
|
Hash aCollSeq; /* All collating sequences */
|
|
BusyHandler busyHandler; /* Busy callback */
|
|
Db aDbStatic[2]; /* Static space for the 2 default backends */
|
|
Savepoint *pSavepoint; /* List of active savepoints */
|
|
int nAnalysisLimit; /* Number of index rows to ANALYZE */
|
|
int busyTimeout; /* Busy handler timeout, in msec */
|
|
int nSavepoint; /* Number of non-transaction savepoints */
|
|
int nStatement; /* Number of nested statement-transactions */
|
|
i64 nDeferredCons; /* Net deferred constraints this transaction. */
|
|
i64 nDeferredImmCons; /* Net deferred immediate constraints */
|
|
int *pnBytesFreed; /* If not NULL, increment this in DbFree() */
|
|
DbClientData *pDbData; /* sqlite3_set_clientdata() content */
|
|
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
|
|
/* The following variables are all protected by the STATIC_MAIN
|
|
** mutex, not by sqlite3.mutex. They are used by code in notify.c.
|
|
**
|
|
** When X.pUnlockConnection==Y, that means that X is waiting for Y to
|
|
** unlock so that it can proceed.
|
|
**
|
|
** When X.pBlockingConnection==Y, that means that something that X tried
|
|
** tried to do recently failed with an SQLITE_LOCKED error due to locks
|
|
** held by Y.
|
|
*/
|
|
sqlite3 *pBlockingConnection; /* Connection that caused SQLITE_LOCKED */
|
|
sqlite3 *pUnlockConnection; /* Connection to watch for unlock */
|
|
void *pUnlockArg; /* Argument to xUnlockNotify */
|
|
void (*xUnlockNotify)(void **, int); /* Unlock notify callback */
|
|
sqlite3 *pNextBlocked; /* Next in list of all blocked connections */
|
|
#endif
|
|
#ifdef SQLITE_USER_AUTHENTICATION
|
|
sqlite3_userauth auth; /* User authentication information */
|
|
#endif
|
|
};
|
|
|
|
/*
|
|
** A macro to discover the encoding of a database.
|
|
*/
|
|
#define SCHEMA_ENC(db) ((db)->aDb[0].pSchema->enc)
|
|
#define ENC(db) ((db)->enc)
|
|
|
|
/*
|
|
** A u64 constant where the lower 32 bits are all zeros. Only the
|
|
** upper 32 bits are included in the argument. Necessary because some
|
|
** C-compilers still do not accept LL integer literals.
|
|
*/
|
|
#define HI(X) ((u64)(X)<<32)
|
|
|
|
/*
|
|
** Possible values for the sqlite3.flags.
|
|
**
|
|
** Value constraints (enforced via assert()):
|
|
** SQLITE_FullFSync == PAGER_FULLFSYNC
|
|
** SQLITE_CkptFullFSync == PAGER_CKPT_FULLFSYNC
|
|
** SQLITE_CacheSpill == PAGER_CACHE_SPILL
|
|
*/
|
|
#define SQLITE_WriteSchema 0x00000001 /* OK to update SQLITE_SCHEMA */
|
|
#define SQLITE_LegacyFileFmt 0x00000002 /* Create new databases in format 1 */
|
|
#define SQLITE_FullColNames 0x00000004 /* Show full column names on SELECT */
|
|
#define SQLITE_FullFSync 0x00000008 /* Use full fsync on the backend */
|
|
#define SQLITE_CkptFullFSync 0x00000010 /* Use full fsync for checkpoint */
|
|
#define SQLITE_CacheSpill 0x00000020 /* OK to spill pager cache */
|
|
#define SQLITE_ShortColNames 0x00000040 /* Show short columns names */
|
|
#define SQLITE_TrustedSchema 0x00000080 /* Allow unsafe functions and
|
|
** vtabs in the schema definition */
|
|
#define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */
|
|
/* result set is empty */
|
|
#define SQLITE_IgnoreChecks 0x00000200 /* Do not enforce check constraints */
|
|
#define SQLITE_StmtScanStatus 0x00000400 /* Enable stmt_scanstats() counters */
|
|
#define SQLITE_NoCkptOnClose 0x00000800 /* No checkpoint on close()/DETACH */
|
|
#define SQLITE_ReverseOrder 0x00001000 /* Reverse unordered SELECTs */
|
|
#define SQLITE_RecTriggers 0x00002000 /* Enable recursive triggers */
|
|
#define SQLITE_ForeignKeys 0x00004000 /* Enforce foreign key constraints */
|
|
#define SQLITE_AutoIndex 0x00008000 /* Enable automatic indexes */
|
|
#define SQLITE_LoadExtension 0x00010000 /* Enable load_extension */
|
|
#define SQLITE_LoadExtFunc 0x00020000 /* Enable load_extension() SQL func */
|
|
#define SQLITE_EnableTrigger 0x00040000 /* True to enable triggers */
|
|
#define SQLITE_DeferFKs 0x00080000 /* Defer all FK constraints */
|
|
#define SQLITE_QueryOnly 0x00100000 /* Disable database changes */
|
|
#define SQLITE_CellSizeCk 0x00200000 /* Check btree cell sizes on load */
|
|
#define SQLITE_Fts3Tokenizer 0x00400000 /* Enable fts3_tokenizer(2) */
|
|
#define SQLITE_EnableQPSG 0x00800000 /* Query Planner Stability Guarantee*/
|
|
#define SQLITE_TriggerEQP 0x01000000 /* Show trigger EXPLAIN QUERY PLAN */
|
|
#define SQLITE_ResetDatabase 0x02000000 /* Reset the database */
|
|
#define SQLITE_LegacyAlter 0x04000000 /* Legacy ALTER TABLE behaviour */
|
|
#define SQLITE_NoSchemaError 0x08000000 /* Do not report schema parse errors*/
|
|
#define SQLITE_Defensive 0x10000000 /* Input SQL is likely hostile */
|
|
#define SQLITE_DqsDDL 0x20000000 /* dbl-quoted strings allowed in DDL*/
|
|
#define SQLITE_DqsDML 0x40000000 /* dbl-quoted strings allowed in DML*/
|
|
#define SQLITE_EnableView 0x80000000 /* Enable the use of views */
|
|
#define SQLITE_CountRows HI(0x00001) /* Count rows changed by INSERT, */
|
|
/* DELETE, or UPDATE and return */
|
|
/* the count using a callback. */
|
|
#define SQLITE_CorruptRdOnly HI(0x00002) /* Prohibit writes due to error */
|
|
#define SQLITE_ReadUncommit HI(0x00004) /* READ UNCOMMITTED in shared-cache */
|
|
#define SQLITE_FkNoAction HI(0x00008) /* Treat all FK as NO ACTION */
|
|
|
|
/* Flags used only if debugging */
|
|
#ifdef SQLITE_DEBUG
|
|
#define SQLITE_SqlTrace HI(0x0100000) /* Debug print SQL as it executes */
|
|
#define SQLITE_VdbeListing HI(0x0200000) /* Debug listings of VDBE progs */
|
|
#define SQLITE_VdbeTrace HI(0x0400000) /* True to trace VDBE execution */
|
|
#define SQLITE_VdbeAddopTrace HI(0x0800000) /* Trace sqlite3VdbeAddOp() calls */
|
|
#define SQLITE_VdbeEQP HI(0x1000000) /* Debug EXPLAIN QUERY PLAN */
|
|
#define SQLITE_ParserTrace HI(0x2000000) /* PRAGMA parser_trace=ON */
|
|
#endif
|
|
|
|
/*
|
|
** Allowed values for sqlite3.mDbFlags
|
|
*/
|
|
#define DBFLAG_SchemaChange 0x0001 /* Uncommitted Hash table changes */
|
|
#define DBFLAG_PreferBuiltin 0x0002 /* Preference to built-in funcs */
|
|
#define DBFLAG_Vacuum 0x0004 /* Currently in a VACUUM */
|
|
#define DBFLAG_VacuumInto 0x0008 /* Currently running VACUUM INTO */
|
|
#define DBFLAG_SchemaKnownOk 0x0010 /* Schema is known to be valid */
|
|
#define DBFLAG_InternalFunc 0x0020 /* Allow use of internal functions */
|
|
#define DBFLAG_EncodingFixed 0x0040 /* No longer possible to change enc. */
|
|
|
|
/*
|
|
** Bits of the sqlite3.dbOptFlags field that are used by the
|
|
** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to
|
|
** selectively disable various optimizations.
|
|
*/
|
|
#define SQLITE_QueryFlattener 0x00000001 /* Query flattening */
|
|
#define SQLITE_WindowFunc 0x00000002 /* Use xInverse for window functions */
|
|
#define SQLITE_GroupByOrder 0x00000004 /* GROUPBY cover of ORDERBY */
|
|
#define SQLITE_FactorOutConst 0x00000008 /* Constant factoring */
|
|
#define SQLITE_DistinctOpt 0x00000010 /* DISTINCT using indexes */
|
|
#define SQLITE_CoverIdxScan 0x00000020 /* Covering index scans */
|
|
#define SQLITE_OrderByIdxJoin 0x00000040 /* ORDER BY of joins via index */
|
|
#define SQLITE_Transitive 0x00000080 /* Transitive constraints */
|
|
#define SQLITE_OmitNoopJoin 0x00000100 /* Omit unused tables in joins */
|
|
#define SQLITE_CountOfView 0x00000200 /* The count-of-view optimization */
|
|
#define SQLITE_CursorHints 0x00000400 /* Add OP_CursorHint opcodes */
|
|
#define SQLITE_Stat4 0x00000800 /* Use STAT4 data */
|
|
/* TH3 expects this value ^^^^^^^^^^ to be 0x0000800. Don't change it */
|
|
#define SQLITE_PushDown 0x00001000 /* The push-down optimization */
|
|
#define SQLITE_SimplifyJoin 0x00002000 /* Convert LEFT JOIN to JOIN */
|
|
#define SQLITE_SkipScan 0x00004000 /* Skip-scans */
|
|
#define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */
|
|
#define SQLITE_MinMaxOpt 0x00010000 /* The min/max optimization */
|
|
#define SQLITE_SeekScan 0x00020000 /* The OP_SeekScan optimization */
|
|
#define SQLITE_OmitOrderBy 0x00040000 /* Omit pointless ORDER BY */
|
|
/* TH3 expects this value ^^^^^^^^^^ to be 0x40000. Coordinate any change */
|
|
#define SQLITE_BloomFilter 0x00080000 /* Use a Bloom filter on searches */
|
|
#define SQLITE_BloomPulldown 0x00100000 /* Run Bloom filters early */
|
|
#define SQLITE_BalancedMerge 0x00200000 /* Balance multi-way merges */
|
|
#define SQLITE_ReleaseReg 0x00400000 /* Use OP_ReleaseReg for testing */
|
|
#define SQLITE_FlttnUnionAll 0x00800000 /* Disable the UNION ALL flattener */
|
|
/* TH3 expects this value ^^^^^^^^^^ See flatten04.test */
|
|
#define SQLITE_IndexedExpr 0x01000000 /* Pull exprs from index when able */
|
|
#define SQLITE_Coroutines 0x02000000 /* Co-routines for subqueries */
|
|
#define SQLITE_NullUnusedCols 0x04000000 /* NULL unused columns in subqueries */
|
|
#define SQLITE_OnePass 0x08000000 /* Single-pass DELETE and UPDATE */
|
|
#define SQLITE_AllOpts 0xffffffff /* All optimizations */
|
|
|
|
/*
|
|
** Macros for testing whether or not optimizations are enabled or disabled.
|
|
*/
|
|
#define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0)
|
|
#define OptimizationEnabled(db, mask) (((db)->dbOptFlags&(mask))==0)
|
|
|
|
/*
|
|
** Return true if it OK to factor constant expressions into the initialization
|
|
** code. The argument is a Parse object for the code generator.
|
|
*/
|
|
#define ConstFactorOk(P) ((P)->okConstFactor)
|
|
|
|
/* Possible values for the sqlite3.eOpenState field.
|
|
** The numbers are randomly selected such that a minimum of three bits must
|
|
** change to convert any number to another or to zero
|
|
*/
|
|
#define SQLITE_STATE_OPEN 0x76 /* Database is open */
|
|
#define SQLITE_STATE_CLOSED 0xce /* Database is closed */
|
|
#define SQLITE_STATE_SICK 0xba /* Error and awaiting close */
|
|
#define SQLITE_STATE_BUSY 0x6d /* Database currently in use */
|
|
#define SQLITE_STATE_ERROR 0xd5 /* An SQLITE_MISUSE error occurred */
|
|
#define SQLITE_STATE_ZOMBIE 0xa7 /* Close with last statement close */
|
|
|
|
/*
|
|
** Each SQL function is defined by an instance of the following
|
|
** structure. For global built-in functions (ex: substr(), max(), count())
|
|
** a pointer to this structure is held in the sqlite3BuiltinFunctions object.
|
|
** For per-connection application-defined functions, a pointer to this
|
|
** structure is held in the db->aHash hash table.
|
|
**
|
|
** The u.pHash field is used by the global built-ins. The u.pDestructor
|
|
** field is used by per-connection app-def functions.
|
|
*/
|
|
struct FuncDef {
|
|
i8 nArg; /* Number of arguments. -1 means unlimited */
|
|
u32 funcFlags; /* Some combination of SQLITE_FUNC_* */
|
|
void *pUserData; /* User data parameter */
|
|
FuncDef *pNext; /* Next function with same name */
|
|
void (*xSFunc)(sqlite3_context*,int,sqlite3_value**); /* func or agg-step */
|
|
void (*xFinalize)(sqlite3_context*); /* Agg finalizer */
|
|
void (*xValue)(sqlite3_context*); /* Current agg value */
|
|
void (*xInverse)(sqlite3_context*,int,sqlite3_value**); /* inverse agg-step */
|
|
const char *zName; /* SQL name of the function. */
|
|
union {
|
|
FuncDef *pHash; /* Next with a different name but the same hash */
|
|
FuncDestructor *pDestructor; /* Reference counted destructor function */
|
|
} u; /* pHash if SQLITE_FUNC_BUILTIN, pDestructor otherwise */
|
|
};
|
|
|
|
/*
|
|
** This structure encapsulates a user-function destructor callback (as
|
|
** configured using create_function_v2()) and a reference counter. When
|
|
** create_function_v2() is called to create a function with a destructor,
|
|
** a single object of this type is allocated. FuncDestructor.nRef is set to
|
|
** the number of FuncDef objects created (either 1 or 3, depending on whether
|
|
** or not the specified encoding is SQLITE_ANY). The FuncDef.pDestructor
|
|
** member of each of the new FuncDef objects is set to point to the allocated
|
|
** FuncDestructor.
|
|
**
|
|
** Thereafter, when one of the FuncDef objects is deleted, the reference
|
|
** count on this object is decremented. When it reaches 0, the destructor
|
|
** is invoked and the FuncDestructor structure freed.
|
|
*/
|
|
struct FuncDestructor {
|
|
int nRef;
|
|
void (*xDestroy)(void *);
|
|
void *pUserData;
|
|
};
|
|
|
|
/*
|
|
** Possible values for FuncDef.flags. Note that the _LENGTH and _TYPEOF
|
|
** values must correspond to OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG. And
|
|
** SQLITE_FUNC_CONSTANT must be the same as SQLITE_DETERMINISTIC. There
|
|
** are assert() statements in the code to verify this.
|
|
**
|
|
** Value constraints (enforced via assert()):
|
|
** SQLITE_FUNC_MINMAX == NC_MinMaxAgg == SF_MinMaxAgg
|
|
** SQLITE_FUNC_ANYORDER == NC_OrderAgg == SF_OrderByReqd
|
|
** SQLITE_FUNC_LENGTH == OPFLAG_LENGTHARG
|
|
** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG
|
|
** SQLITE_FUNC_BYTELEN == OPFLAG_BYTELENARG
|
|
** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API
|
|
** SQLITE_FUNC_DIRECT == SQLITE_DIRECTONLY from the API
|
|
** SQLITE_FUNC_UNSAFE == SQLITE_INNOCUOUS -- opposite meanings!!!
|
|
** SQLITE_FUNC_ENCMASK depends on SQLITE_UTF* macros in the API
|
|
**
|
|
** Note that even though SQLITE_FUNC_UNSAFE and SQLITE_INNOCUOUS have the
|
|
** same bit value, their meanings are inverted. SQLITE_FUNC_UNSAFE is
|
|
** used internally and if set means that the function has side effects.
|
|
** SQLITE_INNOCUOUS is used by application code and means "not unsafe".
|
|
** See multiple instances of tag-20230109-1.
|
|
*/
|
|
#define SQLITE_FUNC_ENCMASK 0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */
|
|
#define SQLITE_FUNC_LIKE 0x0004 /* Candidate for the LIKE optimization */
|
|
#define SQLITE_FUNC_CASE 0x0008 /* Case-sensitive LIKE-type function */
|
|
#define SQLITE_FUNC_EPHEM 0x0010 /* Ephemeral. Delete with VDBE */
|
|
#define SQLITE_FUNC_NEEDCOLL 0x0020 /* sqlite3GetFuncCollSeq() might be called*/
|
|
#define SQLITE_FUNC_LENGTH 0x0040 /* Built-in length() function */
|
|
#define SQLITE_FUNC_TYPEOF 0x0080 /* Built-in typeof() function */
|
|
#define SQLITE_FUNC_BYTELEN 0x00c0 /* Built-in octet_length() function */
|
|
#define SQLITE_FUNC_COUNT 0x0100 /* Built-in count(*) aggregate */
|
|
/* 0x0200 -- available for reuse */
|
|
#define SQLITE_FUNC_UNLIKELY 0x0400 /* Built-in unlikely() function */
|
|
#define SQLITE_FUNC_CONSTANT 0x0800 /* Constant inputs give a constant output */
|
|
#define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */
|
|
#define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a
|
|
** single query - might change over time */
|
|
#define SQLITE_FUNC_TEST 0x4000 /* Built-in testing functions */
|
|
#define SQLITE_FUNC_RUNONLY 0x8000 /* Cannot be used by valueFromFunction */
|
|
#define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */
|
|
#define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */
|
|
#define SQLITE_FUNC_DIRECT 0x00080000 /* Not for use in TRIGGERs or VIEWs */
|
|
/* SQLITE_SUBTYPE 0x00100000 // Consumer of subtypes */
|
|
#define SQLITE_FUNC_UNSAFE 0x00200000 /* Function has side effects */
|
|
#define SQLITE_FUNC_INLINE 0x00400000 /* Functions implemented in-line */
|
|
#define SQLITE_FUNC_BUILTIN 0x00800000 /* This is a built-in function */
|
|
/* SQLITE_RESULT_SUBTYPE 0x01000000 // Generator of subtypes */
|
|
#define SQLITE_FUNC_ANYORDER 0x08000000 /* count/min/max aggregate */
|
|
|
|
/* Identifier numbers for each in-line function */
|
|
#define INLINEFUNC_coalesce 0
|
|
#define INLINEFUNC_implies_nonnull_row 1
|
|
#define INLINEFUNC_expr_implies_expr 2
|
|
#define INLINEFUNC_expr_compare 3
|
|
#define INLINEFUNC_affinity 4
|
|
#define INLINEFUNC_iif 5
|
|
#define INLINEFUNC_sqlite_offset 6
|
|
#define INLINEFUNC_unlikely 99 /* Default case */
|
|
|
|
/*
|
|
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
|
|
** used to create the initializers for the FuncDef structures.
|
|
**
|
|
** FUNCTION(zName, nArg, iArg, bNC, xFunc)
|
|
** Used to create a scalar function definition of a function zName
|
|
** implemented by C function xFunc that accepts nArg arguments. The
|
|
** value passed as iArg is cast to a (void*) and made available
|
|
** as the user-data (sqlite3_user_data()) for the function. If
|
|
** argument bNC is true, then the SQLITE_FUNC_NEEDCOLL flag is set.
|
|
**
|
|
** VFUNCTION(zName, nArg, iArg, bNC, xFunc)
|
|
** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag.
|
|
**
|
|
** SFUNCTION(zName, nArg, iArg, bNC, xFunc)
|
|
** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag and
|
|
** adds the SQLITE_DIRECTONLY flag.
|
|
**
|
|
** INLINE_FUNC(zName, nArg, iFuncId, mFlags)
|
|
** zName is the name of a function that is implemented by in-line
|
|
** byte code rather than by the usual callbacks. The iFuncId
|
|
** parameter determines the function id. The mFlags parameter is
|
|
** optional SQLITE_FUNC_ flags for this function.
|
|
**
|
|
** TEST_FUNC(zName, nArg, iFuncId, mFlags)
|
|
** zName is the name of a test-only function implemented by in-line
|
|
** byte code rather than by the usual callbacks. The iFuncId
|
|
** parameter determines the function id. The mFlags parameter is
|
|
** optional SQLITE_FUNC_ flags for this function.
|
|
**
|
|
** DFUNCTION(zName, nArg, iArg, bNC, xFunc)
|
|
** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag and
|
|
** adds the SQLITE_FUNC_SLOCHNG flag. Used for date & time functions
|
|
** and functions like sqlite_version() that can change, but not during
|
|
** a single query. The iArg is ignored. The user-data is always set
|
|
** to a NULL pointer. The bNC parameter is not used.
|
|
**
|
|
** MFUNCTION(zName, nArg, xPtr, xFunc)
|
|
** For math-library functions. xPtr is an arbitrary pointer.
|
|
**
|
|
** PURE_DATE(zName, nArg, iArg, bNC, xFunc)
|
|
** Used for "pure" date/time functions, this macro is like DFUNCTION
|
|
** except that it does set the SQLITE_FUNC_CONSTANT flags. iArg is
|
|
** ignored and the user-data for these functions is set to an
|
|
** arbitrary non-NULL pointer. The bNC parameter is not used.
|
|
**
|
|
** AGGREGATE(zName, nArg, iArg, bNC, xStep, xFinal)
|
|
** Used to create an aggregate function definition implemented by
|
|
** the C functions xStep and xFinal. The first four parameters
|
|
** are interpreted in the same way as the first 4 parameters to
|
|
** FUNCTION().
|
|
**
|
|
** WAGGREGATE(zName, nArg, iArg, xStep, xFinal, xValue, xInverse)
|
|
** Used to create an aggregate function definition implemented by
|
|
** the C functions xStep and xFinal. The first four parameters
|
|
** are interpreted in the same way as the first 4 parameters to
|
|
** FUNCTION().
|
|
**
|
|
** LIKEFUNC(zName, nArg, pArg, flags)
|
|
** Used to create a scalar function definition of a function zName
|
|
** that accepts nArg arguments and is implemented by a call to C
|
|
** function likeFunc. Argument pArg is cast to a (void *) and made
|
|
** available as the function user-data (sqlite3_user_data()). The
|
|
** FuncDef.flags variable is set to the value passed as the flags
|
|
** parameter.
|
|
*/
|
|
#define FUNCTION(zName, nArg, iArg, bNC, xFunc) \
|
|
{nArg, SQLITE_FUNC_BUILTIN|\
|
|
SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
|
|
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
|
|
#define VFUNCTION(zName, nArg, iArg, bNC, xFunc) \
|
|
{nArg, SQLITE_FUNC_BUILTIN|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
|
|
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
|
|
#define SFUNCTION(zName, nArg, iArg, bNC, xFunc) \
|
|
{nArg, SQLITE_FUNC_BUILTIN|SQLITE_UTF8|SQLITE_DIRECTONLY|SQLITE_FUNC_UNSAFE, \
|
|
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
|
|
#define MFUNCTION(zName, nArg, xPtr, xFunc) \
|
|
{nArg, SQLITE_FUNC_BUILTIN|SQLITE_FUNC_CONSTANT|SQLITE_UTF8, \
|
|
xPtr, 0, xFunc, 0, 0, 0, #zName, {0} }
|
|
#define JFUNCTION(zName, nArg, bUseCache, bWS, bRS, bJsonB, iArg, xFunc) \
|
|
{nArg, SQLITE_FUNC_BUILTIN|SQLITE_DETERMINISTIC|SQLITE_FUNC_CONSTANT|\
|
|
SQLITE_UTF8|((bUseCache)*SQLITE_FUNC_RUNONLY)|\
|
|
((bRS)*SQLITE_SUBTYPE)|((bWS)*SQLITE_RESULT_SUBTYPE), \
|
|
SQLITE_INT_TO_PTR(iArg|((bJsonB)*JSON_BLOB)),0,xFunc,0, 0, 0, #zName, {0} }
|
|
#define INLINE_FUNC(zName, nArg, iArg, mFlags) \
|
|
{nArg, SQLITE_FUNC_BUILTIN|\
|
|
SQLITE_UTF8|SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \
|
|
SQLITE_INT_TO_PTR(iArg), 0, noopFunc, 0, 0, 0, #zName, {0} }
|
|
#define TEST_FUNC(zName, nArg, iArg, mFlags) \
|
|
{nArg, SQLITE_FUNC_BUILTIN|\
|
|
SQLITE_UTF8|SQLITE_FUNC_INTERNAL|SQLITE_FUNC_TEST| \
|
|
SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \
|
|
SQLITE_INT_TO_PTR(iArg), 0, noopFunc, 0, 0, 0, #zName, {0} }
|
|
#define DFUNCTION(zName, nArg, iArg, bNC, xFunc) \
|
|
{nArg, SQLITE_FUNC_BUILTIN|SQLITE_FUNC_SLOCHNG|SQLITE_UTF8, \
|
|
0, 0, xFunc, 0, 0, 0, #zName, {0} }
|
|
#define PURE_DATE(zName, nArg, iArg, bNC, xFunc) \
|
|
{nArg, SQLITE_FUNC_BUILTIN|\
|
|
SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \
|
|
(void*)&sqlite3Config, 0, xFunc, 0, 0, 0, #zName, {0} }
|
|
#define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \
|
|
{nArg, SQLITE_FUNC_BUILTIN|\
|
|
SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\
|
|
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
|
|
#define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \
|
|
{nArg, SQLITE_FUNC_BUILTIN|\
|
|
SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
|
|
pArg, 0, xFunc, 0, 0, 0, #zName, }
|
|
#define LIKEFUNC(zName, nArg, arg, flags) \
|
|
{nArg, SQLITE_FUNC_BUILTIN|SQLITE_FUNC_CONSTANT|SQLITE_UTF8|flags, \
|
|
(void *)arg, 0, likeFunc, 0, 0, 0, #zName, {0} }
|
|
#define WAGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue, xInverse, f) \
|
|
{nArg, SQLITE_FUNC_BUILTIN|SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|f, \
|
|
SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,xInverse,#zName, {0}}
|
|
#define INTERNAL_FUNCTION(zName, nArg, xFunc) \
|
|
{nArg, SQLITE_FUNC_BUILTIN|\
|
|
SQLITE_FUNC_INTERNAL|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \
|
|
0, 0, xFunc, 0, 0, 0, #zName, {0} }
|
|
|
|
|
|
/*
|
|
** All current savepoints are stored in a linked list starting at
|
|
** sqlite3.pSavepoint. The first element in the list is the most recently
|
|
** opened savepoint. Savepoints are added to the list by the vdbe
|
|
** OP_Savepoint instruction.
|
|
*/
|
|
struct Savepoint {
|
|
char *zName; /* Savepoint name (nul-terminated) */
|
|
i64 nDeferredCons; /* Number of deferred fk violations */
|
|
i64 nDeferredImmCons; /* Number of deferred imm fk. */
|
|
Savepoint *pNext; /* Parent savepoint (if any) */
|
|
};
|
|
|
|
/*
|
|
** The following are used as the second parameter to sqlite3Savepoint(),
|
|
** and as the P1 argument to the OP_Savepoint instruction.
|
|
*/
|
|
#define SAVEPOINT_BEGIN 0
|
|
#define SAVEPOINT_RELEASE 1
|
|
#define SAVEPOINT_ROLLBACK 2
|
|
|
|
|
|
/*
|
|
** 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() */
|
|
int nRefModule; /* Number of pointers to this object */
|
|
void *pAux; /* pAux passed to create_module() */
|
|
void (*xDestroy)(void *); /* Module destructor function */
|
|
Table *pEpoTab; /* Eponymous table for this module */
|
|
};
|
|
|
|
/*
|
|
** Information about each column of an SQL table is held in an instance
|
|
** of the Column structure, in the Table.aCol[] array.
|
|
**
|
|
** Definitions:
|
|
**
|
|
** "table column index" This is the index of the column in the
|
|
** Table.aCol[] array, and also the index of
|
|
** the column in the original CREATE TABLE stmt.
|
|
**
|
|
** "storage column index" This is the index of the column in the
|
|
** record BLOB generated by the OP_MakeRecord
|
|
** opcode. The storage column index is less than
|
|
** or equal to the table column index. It is
|
|
** equal if and only if there are no VIRTUAL
|
|
** columns to the left.
|
|
**
|
|
** Notes on zCnName:
|
|
** The zCnName field stores the name of the column, the datatype of the
|
|
** column, and the collating sequence for the column, in that order, all in
|
|
** a single allocation. Each string is 0x00 terminated. The datatype
|
|
** is only included if the COLFLAG_HASTYPE bit of colFlags is set and the
|
|
** collating sequence name is only included if the COLFLAG_HASCOLL bit is
|
|
** set.
|
|
*/
|
|
struct Column {
|
|
char *zCnName; /* Name of this column */
|
|
unsigned notNull :4; /* An OE_ code for handling a NOT NULL constraint */
|
|
unsigned eCType :4; /* One of the standard types */
|
|
char affinity; /* One of the SQLITE_AFF_... values */
|
|
u8 szEst; /* Est size of value in this column. sizeof(INT)==1 */
|
|
u8 hName; /* Column name hash for faster lookup */
|
|
u16 iDflt; /* 1-based index of DEFAULT. 0 means "none" */
|
|
u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */
|
|
};
|
|
|
|
/* Allowed values for Column.eCType.
|
|
**
|
|
** Values must match entries in the global constant arrays
|
|
** sqlite3StdTypeLen[] and sqlite3StdType[]. Each value is one more
|
|
** than the offset into these arrays for the corresponding name.
|
|
** Adjust the SQLITE_N_STDTYPE value if adding or removing entries.
|
|
*/
|
|
#define COLTYPE_CUSTOM 0 /* Type appended to zName */
|
|
#define COLTYPE_ANY 1
|
|
#define COLTYPE_BLOB 2
|
|
#define COLTYPE_INT 3
|
|
#define COLTYPE_INTEGER 4
|
|
#define COLTYPE_REAL 5
|
|
#define COLTYPE_TEXT 6
|
|
#define SQLITE_N_STDTYPE 6 /* Number of standard types */
|
|
|
|
/* Allowed values for Column.colFlags.
|
|
**
|
|
** Constraints:
|
|
** TF_HasVirtual == COLFLAG_VIRTUAL
|
|
** TF_HasStored == COLFLAG_STORED
|
|
** TF_HasHidden == COLFLAG_HIDDEN
|
|
*/
|
|
#define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */
|
|
#define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */
|
|
#define COLFLAG_HASTYPE 0x0004 /* Type name follows column name */
|
|
#define COLFLAG_UNIQUE 0x0008 /* Column def contains "UNIQUE" or "PK" */
|
|
#define COLFLAG_SORTERREF 0x0010 /* Use sorter-refs with this column */
|
|
#define COLFLAG_VIRTUAL 0x0020 /* GENERATED ALWAYS AS ... VIRTUAL */
|
|
#define COLFLAG_STORED 0x0040 /* GENERATED ALWAYS AS ... STORED */
|
|
#define COLFLAG_NOTAVAIL 0x0080 /* STORED column not yet calculated */
|
|
#define COLFLAG_BUSY 0x0100 /* Blocks recursion on GENERATED columns */
|
|
#define COLFLAG_HASCOLL 0x0200 /* Has collating sequence name in zCnName */
|
|
#define COLFLAG_NOEXPAND 0x0400 /* Omit this column when expanding "*" */
|
|
#define COLFLAG_GENERATED 0x0060 /* Combo: _STORED, _VIRTUAL */
|
|
#define COLFLAG_NOINSERT 0x0062 /* Combo: _HIDDEN, _STORED, _VIRTUAL */
|
|
|
|
/*
|
|
** 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.
|
|
**
|
|
** If CollSeq.xCmp is 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() */
|
|
void *pUser; /* First argument to xCmp() */
|
|
int (*xCmp)(void*,int, const void*, int, const void*);
|
|
void (*xDel)(void*); /* Destructor for pUser */
|
|
};
|
|
|
|
/*
|
|
** 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 */
|
|
#define SQLITE_SO_UNDEFINED -1 /* No sort order specified */
|
|
|
|
/*
|
|
** 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 numbering 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 P4 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. And the BLOB type is first.
|
|
*/
|
|
#define SQLITE_AFF_NONE 0x40 /* '@' */
|
|
#define SQLITE_AFF_BLOB 0x41 /* 'A' */
|
|
#define SQLITE_AFF_TEXT 0x42 /* 'B' */
|
|
#define SQLITE_AFF_NUMERIC 0x43 /* 'C' */
|
|
#define SQLITE_AFF_INTEGER 0x44 /* 'D' */
|
|
#define SQLITE_AFF_REAL 0x45 /* 'E' */
|
|
#define SQLITE_AFF_FLEXNUM 0x46 /* 'F' */
|
|
|
|
#define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC)
|
|
|
|
/*
|
|
** The SQLITE_AFF_MASK values masks off the significant bits of an
|
|
** affinity value.
|
|
*/
|
|
#define SQLITE_AFF_MASK 0x47
|
|
|
|
/*
|
|
** Additional bit values that can be ORed with an affinity without
|
|
** changing the affinity.
|
|
**
|
|
** The SQLITE_NOTNULL flag is a combination of NULLEQ and JUMPIFNULL.
|
|
** It causes an assert() to fire if either operand to a comparison
|
|
** operator is NULL. It is added to certain comparison operators to
|
|
** prove that the operands are always NOT NULL.
|
|
*/
|
|
#define SQLITE_JUMPIFNULL 0x10 /* jumps if either operand is NULL */
|
|
#define SQLITE_NULLEQ 0x80 /* NULL=NULL */
|
|
#define SQLITE_NOTNULL 0x90 /* Assert that operands are never NULL */
|
|
|
|
/*
|
|
** An object of this type is created for each virtual table present in
|
|
** the database schema.
|
|
**
|
|
** If the database schema is shared, then there is one instance of this
|
|
** structure for each database connection (sqlite3*) that uses the shared
|
|
** schema. This is because each database connection requires its own unique
|
|
** instance of the sqlite3_vtab* handle used to access the virtual table
|
|
** implementation. sqlite3_vtab* handles can not be shared between
|
|
** database connections, even when the rest of the in-memory database
|
|
** schema is shared, as the implementation often stores the database
|
|
** connection handle passed to it via the xConnect() or xCreate() method
|
|
** during initialization internally. This database connection handle may
|
|
** then be used by the virtual table implementation to access real tables
|
|
** within the database. So that they appear as part of the callers
|
|
** transaction, these accesses need to be made via the same database
|
|
** connection as that used to execute SQL operations on the virtual table.
|
|
**
|
|
** All VTable objects that correspond to a single table in a shared
|
|
** database schema are initially stored in a linked-list pointed to by
|
|
** the Table.pVTable member variable of the corresponding Table object.
|
|
** When an sqlite3_prepare() operation is required to access the virtual
|
|
** table, it searches the list for the VTable that corresponds to the
|
|
** database connection doing the preparing so as to use the correct
|
|
** sqlite3_vtab* handle in the compiled query.
|
|
**
|
|
** When an in-memory Table object is deleted (for example when the
|
|
** schema is being reloaded for some reason), the VTable objects are not
|
|
** deleted and the sqlite3_vtab* handles are not xDisconnect()ed
|
|
** immediately. Instead, they are moved from the Table.pVTable list to
|
|
** another linked list headed by the sqlite3.pDisconnect member of the
|
|
** corresponding sqlite3 structure. They are then deleted/xDisconnected
|
|
** next time a statement is prepared using said sqlite3*. This is done
|
|
** to avoid deadlock issues involving multiple sqlite3.mutex mutexes.
|
|
** Refer to comments above function sqlite3VtabUnlockList() for an
|
|
** explanation as to why it is safe to add an entry to an sqlite3.pDisconnect
|
|
** list without holding the corresponding sqlite3.mutex mutex.
|
|
**
|
|
** The memory for objects of this type is always allocated by
|
|
** sqlite3DbMalloc(), using the connection handle stored in VTable.db as
|
|
** the first argument.
|
|
*/
|
|
struct VTable {
|
|
sqlite3 *db; /* Database connection associated with this table */
|
|
Module *pMod; /* Pointer to module implementation */
|
|
sqlite3_vtab *pVtab; /* Pointer to vtab instance */
|
|
int nRef; /* Number of pointers to this structure */
|
|
u8 bConstraint; /* True if constraints are supported */
|
|
u8 bAllSchemas; /* True if might use any attached schema */
|
|
u8 eVtabRisk; /* Riskiness of allowing hacker access */
|
|
int iSavepoint; /* Depth of the SAVEPOINT stack */
|
|
VTable *pNext; /* Next in linked list (see above) */
|
|
};
|
|
|
|
/* Allowed values for VTable.eVtabRisk
|
|
*/
|
|
#define SQLITE_VTABRISK_Low 0
|
|
#define SQLITE_VTABRISK_Normal 1
|
|
#define SQLITE_VTABRISK_High 2
|
|
|
|
/*
|
|
** The schema for each SQL table, virtual table, and view is represented
|
|
** in memory by an instance of the following structure.
|
|
*/
|
|
struct Table {
|
|
char *zName; /* Name of the table or view */
|
|
Column *aCol; /* Information about each column */
|
|
Index *pIndex; /* List of SQL indexes on this table. */
|
|
char *zColAff; /* String defining the affinity of each column */
|
|
ExprList *pCheck; /* All CHECK constraints */
|
|
/* ... also used as column name list in a VIEW */
|
|
Pgno tnum; /* Root BTree page for this table */
|
|
u32 nTabRef; /* Number of pointers to this Table */
|
|
u32 tabFlags; /* Mask of TF_* values */
|
|
i16 iPKey; /* If not negative, use aCol[iPKey] as the rowid */
|
|
i16 nCol; /* Number of columns in this table */
|
|
i16 nNVCol; /* Number of columns that are not VIRTUAL */
|
|
LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */
|
|
LogEst szTabRow; /* Estimated size of each table row in bytes */
|
|
#ifdef SQLITE_ENABLE_COSTMULT
|
|
LogEst costMult; /* Cost multiplier for using this table */
|
|
#endif
|
|
u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
|
|
u8 eTabType; /* 0: normal, 1: virtual, 2: view */
|
|
union {
|
|
struct { /* Used by ordinary tables: */
|
|
int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */
|
|
FKey *pFKey; /* Linked list of all foreign keys in this table */
|
|
ExprList *pDfltList; /* DEFAULT clauses on various columns.
|
|
** Or the AS clause for generated columns. */
|
|
} tab;
|
|
struct { /* Used by views: */
|
|
Select *pSelect; /* View definition */
|
|
} view;
|
|
struct { /* Used by virtual tables only: */
|
|
int nArg; /* Number of arguments to the module */
|
|
char **azArg; /* 0: module 1: schema 2: vtab name 3...: args */
|
|
VTable *p; /* List of VTable objects. */
|
|
} vtab;
|
|
} u;
|
|
Trigger *pTrigger; /* List of triggers on this object */
|
|
Schema *pSchema; /* Schema that contains this table */
|
|
};
|
|
|
|
/*
|
|
** Allowed values for Table.tabFlags.
|
|
**
|
|
** TF_OOOHidden applies to tables or view that have hidden columns that are
|
|
** followed by non-hidden columns. Example: "CREATE VIRTUAL TABLE x USING
|
|
** vtab1(a HIDDEN, b);". Since "b" is a non-hidden column but "a" is hidden,
|
|
** the TF_OOOHidden attribute would apply in this case. Such tables require
|
|
** special handling during INSERT processing. The "OOO" means "Out Of Order".
|
|
**
|
|
** Constraints:
|
|
**
|
|
** TF_HasVirtual == COLFLAG_VIRTUAL
|
|
** TF_HasStored == COLFLAG_STORED
|
|
** TF_HasHidden == COLFLAG_HIDDEN
|
|
*/
|
|
#define TF_Readonly 0x00000001 /* Read-only system table */
|
|
#define TF_HasHidden 0x00000002 /* Has one or more hidden columns */
|
|
#define TF_HasPrimaryKey 0x00000004 /* Table has a primary key */
|
|
#define TF_Autoincrement 0x00000008 /* Integer primary key is autoincrement */
|
|
#define TF_HasStat1 0x00000010 /* nRowLogEst set from sqlite_stat1 */
|
|
#define TF_HasVirtual 0x00000020 /* Has one or more VIRTUAL columns */
|
|
#define TF_HasStored 0x00000040 /* Has one or more STORED columns */
|
|
#define TF_HasGenerated 0x00000060 /* Combo: HasVirtual + HasStored */
|
|
#define TF_WithoutRowid 0x00000080 /* No rowid. PRIMARY KEY is the key */
|
|
#define TF_StatsUsed 0x00000100 /* Query planner decisions affected by
|
|
** Index.aiRowLogEst[] values */
|
|
#define TF_NoVisibleRowid 0x00000200 /* No user-visible "rowid" column */
|
|
#define TF_OOOHidden 0x00000400 /* Out-of-Order hidden columns */
|
|
#define TF_HasNotNull 0x00000800 /* Contains NOT NULL constraints */
|
|
#define TF_Shadow 0x00001000 /* True for a shadow table */
|
|
#define TF_HasStat4 0x00002000 /* STAT4 info available for this table */
|
|
#define TF_Ephemeral 0x00004000 /* An ephemeral table */
|
|
#define TF_Eponymous 0x00008000 /* An eponymous virtual table */
|
|
#define TF_Strict 0x00010000 /* STRICT mode */
|
|
|
|
/*
|
|
** Allowed values for Table.eTabType
|
|
*/
|
|
#define TABTYP_NORM 0 /* Ordinary table */
|
|
#define TABTYP_VTAB 1 /* Virtual table */
|
|
#define TABTYP_VIEW 2 /* A view */
|
|
|
|
#define IsView(X) ((X)->eTabType==TABTYP_VIEW)
|
|
#define IsOrdinaryTable(X) ((X)->eTabType==TABTYP_NORM)
|
|
|
|
/*
|
|
** 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)->eTabType==TABTYP_VTAB)
|
|
# define ExprIsVtab(X) \
|
|
((X)->op==TK_COLUMN && (X)->y.pTab->eTabType==TABTYP_VTAB)
|
|
#else
|
|
# define IsVirtual(X) 0
|
|
# define ExprIsVtab(X) 0
|
|
#endif
|
|
|
|
/*
|
|
** Macros to determine if a column is hidden. IsOrdinaryHiddenColumn()
|
|
** only works for non-virtual tables (ordinary tables and views) and is
|
|
** always false unless SQLITE_ENABLE_HIDDEN_COLUMNS is defined. The
|
|
** IsHiddenColumn() macro is general purpose.
|
|
*/
|
|
#if defined(SQLITE_ENABLE_HIDDEN_COLUMNS)
|
|
# define IsHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0)
|
|
# define IsOrdinaryHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0)
|
|
#elif !defined(SQLITE_OMIT_VIRTUALTABLE)
|
|
# define IsHiddenColumn(X) (((X)->colFlags & COLFLAG_HIDDEN)!=0)
|
|
# define IsOrdinaryHiddenColumn(X) 0
|
|
#else
|
|
# define IsHiddenColumn(X) 0
|
|
# define IsOrdinaryHiddenColumn(X) 0
|
|
#endif
|
|
|
|
|
|
/* Does the table have a rowid */
|
|
#define HasRowid(X) (((X)->tabFlags & TF_WithoutRowid)==0)
|
|
#define VisibleRowid(X) (((X)->tabFlags & TF_NoVisibleRowid)==0)
|
|
|
|
/* Macro is true if the SQLITE_ALLOW_ROWID_IN_VIEW (mis-)feature is
|
|
** available. By default, this macro is false
|
|
*/
|
|
#ifndef SQLITE_ALLOW_ROWID_IN_VIEW
|
|
# define ViewCanHaveRowid 0
|
|
#else
|
|
# define ViewCanHaveRowid (sqlite3Config.mNoVisibleRowid==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".
|
|
** Equivalent names:
|
|
**
|
|
** from-table == child-table
|
|
** to-table == parent-table
|
|
**
|
|
** 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 existence of the to-table is not checked.
|
|
**
|
|
** The list of all parents for child Table X is held at X.pFKey.
|
|
**
|
|
** A list of all children for a table named Z (which might not even exist)
|
|
** is held in Schema.fkeyHash with a hash key of Z.
|
|
*/
|
|
struct FKey {
|
|
Table *pFrom; /* Table containing the REFERENCES clause (aka: Child) */
|
|
FKey *pNextFrom; /* Next FKey with the same in pFrom. Next parent of pFrom */
|
|
char *zTo; /* Name of table that the key points to (aka: Parent) */
|
|
FKey *pNextTo; /* Next with the same zTo. Next child of zTo. */
|
|
FKey *pPrevTo; /* Previous with the same zTo */
|
|
int nCol; /* Number of columns in this key */
|
|
/* EV: R-30323-21917 */
|
|
u8 isDeferred; /* True if constraint checking is deferred till COMMIT */
|
|
u8 aAction[2]; /* ON DELETE and ON UPDATE actions, respectively */
|
|
Trigger *apTrigger[2];/* Triggers for aAction[] actions */
|
|
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 NULL use PRIMARY KEY */
|
|
} aCol[1]; /* One entry for each of nCol columns */
|
|
};
|
|
|
|
/*
|
|
** SQLite supports many different ways to resolve a constraint
|
|
** 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.
|
|
** UPDATE applies to insert operations only and means that the insert
|
|
** is omitted and the DO UPDATE clause of an upsert is run instead.
|
|
**
|
|
** RESTRICT, SETNULL, SETDFLT, 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. SETDFLT means that the foreign key is set
|
|
** to its default value. CASCADE means that a DELETE or UPDATE of the
|
|
** referenced table row is propagated into the row that holds the
|
|
** foreign key.
|
|
**
|
|
** The OE_Default value is a place holder that means to use whatever
|
|
** conflict resolution algorithm is required from context.
|
|
**
|
|
** The following symbolic values are used to record which type
|
|
** of conflict resolution 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_Update 6 /* Process as a DO UPDATE in an upsert */
|
|
#define OE_Restrict 7 /* OE_Abort for IMMEDIATE, OE_Rollback for DEFERRED */
|
|
#define OE_SetNull 8 /* Set the foreign key value to NULL */
|
|
#define OE_SetDflt 9 /* Set the foreign key value to its default */
|
|
#define OE_Cascade 10 /* Cascade the changes */
|
|
#define OE_Default 11 /* 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.
|
|
**
|
|
** Note that aSortOrder[] and aColl[] have nField+1 slots. There
|
|
** are nField slots for the columns of an index then one extra slot
|
|
** for the rowid at the end.
|
|
*/
|
|
struct KeyInfo {
|
|
u32 nRef; /* Number of references to this KeyInfo object */
|
|
u8 enc; /* Text encoding - one of the SQLITE_UTF* values */
|
|
u16 nKeyField; /* Number of key columns in the index */
|
|
u16 nAllField; /* Total columns, including key plus others */
|
|
sqlite3 *db; /* The database connection */
|
|
u8 *aSortFlags; /* Sort order for each column. */
|
|
CollSeq *aColl[1]; /* Collating sequence for each term of the key */
|
|
};
|
|
|
|
/*
|
|
** Allowed bit values for entries in the KeyInfo.aSortFlags[] array.
|
|
*/
|
|
#define KEYINFO_ORDER_DESC 0x01 /* DESC sort order */
|
|
#define KEYINFO_ORDER_BIGNULL 0x02 /* NULL is larger than any other value */
|
|
|
|
/*
|
|
** This object holds a record which has been parsed out into individual
|
|
** fields, for the purposes of doing a comparison.
|
|
**
|
|
** A record is an object that contains one or more fields of data.
|
|
** Records are used to store the content of a table row and to store
|
|
** the key of an index. A blob encoding of a record is created by
|
|
** the OP_MakeRecord opcode of the VDBE and is disassembled by the
|
|
** OP_Column opcode.
|
|
**
|
|
** An instance of this object serves as a "key" for doing a search on
|
|
** an index b+tree. The goal of the search is to find the entry that
|
|
** is closed to the key described by this object. This object might hold
|
|
** just a prefix of the key. The number of fields is given by
|
|
** pKeyInfo->nField.
|
|
**
|
|
** The r1 and r2 fields are the values to return if this key is less than
|
|
** or greater than a key in the btree, respectively. These are normally
|
|
** -1 and +1 respectively, but might be inverted to +1 and -1 if the b-tree
|
|
** is in DESC order.
|
|
**
|
|
** The key comparison functions actually return default_rc when they find
|
|
** an equals comparison. default_rc can be -1, 0, or +1. If there are
|
|
** multiple entries in the b-tree with the same key (when only looking
|
|
** at the first pKeyInfo->nFields,) then default_rc can be set to -1 to
|
|
** cause the search to find the last match, or +1 to cause the search to
|
|
** find the first match.
|
|
**
|
|
** The key comparison functions will set eqSeen to true if they ever
|
|
** get and equal results when comparing this structure to a b-tree record.
|
|
** When default_rc!=0, the search might end up on the record immediately
|
|
** before the first match or immediately after the last match. The
|
|
** eqSeen field will indicate whether or not an exact match exists in the
|
|
** b-tree.
|
|
*/
|
|
struct UnpackedRecord {
|
|
KeyInfo *pKeyInfo; /* Collation and sort-order information */
|
|
Mem *aMem; /* Values */
|
|
union {
|
|
char *z; /* Cache of aMem[0].z for vdbeRecordCompareString() */
|
|
i64 i; /* Cache of aMem[0].u.i for vdbeRecordCompareInt() */
|
|
} u;
|
|
int n; /* Cache of aMem[0].n used by vdbeRecordCompareString() */
|
|
u16 nField; /* Number of entries in apMem[] */
|
|
i8 default_rc; /* Comparison result if keys are equal */
|
|
u8 errCode; /* Error detected by xRecordCompare (CORRUPT or NOMEM) */
|
|
i8 r1; /* Value to return if (lhs < rhs) */
|
|
i8 r2; /* Value to return if (lhs > rhs) */
|
|
u8 eqSeen; /* True if an equality comparison has been seen */
|
|
};
|
|
|
|
|
|
/*
|
|
** 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 indicates which conflict resolution
|
|
** algorithm to employ when an attempt is made to insert a non-unique
|
|
** element.
|
|
**
|
|
** The colNotIdxed bitmask is used in combination with SrcItem.colUsed
|
|
** for a fast test to see if an index can serve as a covering index.
|
|
** colNotIdxed has a 1 bit for every column of the original table that
|
|
** is *not* available in the index. Thus the expression
|
|
** "colUsed & colNotIdxed" will be non-zero if the index is not a
|
|
** covering index. The most significant bit of of colNotIdxed will always
|
|
** be true (note-20221022-a). If a column beyond the 63rd column of the
|
|
** table is used, the "colUsed & colNotIdxed" test will always be non-zero
|
|
** and we have to assume either that the index is not covering, or use
|
|
** an alternative (slower) algorithm to determine whether or not
|
|
** the index is covering.
|
|
**
|
|
** While parsing a CREATE TABLE or CREATE INDEX statement in order to
|
|
** generate VDBE code (as opposed to parsing one read from an sqlite_schema
|
|
** table as part of parsing an existing database schema), transient instances
|
|
** of this structure may be created. In this case the Index.tnum variable is
|
|
** used to store the address of a VDBE instruction, not a database page
|
|
** number (it cannot - the database page is not allocated until the VDBE
|
|
** program is executed). See convertToWithoutRowidTable() for details.
|
|
*/
|
|
struct Index {
|
|
char *zName; /* Name of this index */
|
|
i16 *aiColumn; /* Which columns are used by this index. 1st is 0 */
|
|
LogEst *aiRowLogEst; /* From ANALYZE: Est. rows selected by each column */
|
|
Table *pTable; /* The SQL table being indexed */
|
|
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; /* for each column: True==DESC, False==ASC */
|
|
const char **azColl; /* Array of collation sequence names for index */
|
|
Expr *pPartIdxWhere; /* WHERE clause for partial indices */
|
|
ExprList *aColExpr; /* Column expressions */
|
|
Pgno tnum; /* DB Page containing root of this index */
|
|
LogEst szIdxRow; /* Estimated average row size in bytes */
|
|
u16 nKeyCol; /* Number of columns forming the key */
|
|
u16 nColumn; /* Number of columns stored in the index */
|
|
u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
|
|
unsigned idxType:2; /* 0:Normal 1:UNIQUE, 2:PRIMARY KEY, 3:IPK */
|
|
unsigned bUnordered:1; /* Use this index for == or IN queries only */
|
|
unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */
|
|
unsigned isResized:1; /* True if resizeIndexObject() has been called */
|
|
unsigned isCovering:1; /* True if this is a covering index */
|
|
unsigned noSkipScan:1; /* Do not try to use skip-scan if true */
|
|
unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */
|
|
unsigned bLowQual:1; /* sqlite_stat1 says this is a low-quality index */
|
|
unsigned bNoQuery:1; /* Do not use this index to optimize queries */
|
|
unsigned bAscKeyBug:1; /* True if the bba7b69f9849b5bf bug applies */
|
|
unsigned bHasVCol:1; /* Index references one or more VIRTUAL columns */
|
|
unsigned bHasExpr:1; /* Index contains an expression, either a literal
|
|
** expression, or a reference to a VIRTUAL column */
|
|
#ifdef SQLITE_ENABLE_STAT4
|
|
int nSample; /* Number of elements in aSample[] */
|
|
int mxSample; /* Number of slots allocated to aSample[] */
|
|
int nSampleCol; /* Size of IndexSample.anEq[] and so on */
|
|
tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */
|
|
IndexSample *aSample; /* Samples of the left-most key */
|
|
tRowcnt *aiRowEst; /* Non-logarithmic stat1 data for this index */
|
|
tRowcnt nRowEst0; /* Non-logarithmic number of rows in the index */
|
|
#endif
|
|
Bitmask colNotIdxed; /* Unindexed columns in pTab */
|
|
};
|
|
|
|
/*
|
|
** Allowed values for Index.idxType
|
|
*/
|
|
#define SQLITE_IDXTYPE_APPDEF 0 /* Created using CREATE INDEX */
|
|
#define SQLITE_IDXTYPE_UNIQUE 1 /* Implements a UNIQUE constraint */
|
|
#define SQLITE_IDXTYPE_PRIMARYKEY 2 /* Is the PRIMARY KEY for the table */
|
|
#define SQLITE_IDXTYPE_IPK 3 /* INTEGER PRIMARY KEY index */
|
|
|
|
/* Return true if index X is a PRIMARY KEY index */
|
|
#define IsPrimaryKeyIndex(X) ((X)->idxType==SQLITE_IDXTYPE_PRIMARYKEY)
|
|
|
|
/* Return true if index X is a UNIQUE index */
|
|
#define IsUniqueIndex(X) ((X)->onError!=OE_None)
|
|
|
|
/* The Index.aiColumn[] values are normally positive integer. But
|
|
** there are some negative values that have special meaning:
|
|
*/
|
|
#define XN_ROWID (-1) /* Indexed column is the rowid */
|
|
#define XN_EXPR (-2) /* Indexed column is an expression */
|
|
|
|
/*
|
|
** Each sample stored in the sqlite_stat4 table is represented in memory
|
|
** using a structure of this type. See documentation at the top of the
|
|
** analyze.c source file for additional information.
|
|
*/
|
|
struct IndexSample {
|
|
void *p; /* Pointer to sampled record */
|
|
int n; /* Size of record in bytes */
|
|
tRowcnt *anEq; /* Est. number of rows where the key equals this sample */
|
|
tRowcnt *anLt; /* Est. number of rows where key is less than this sample */
|
|
tRowcnt *anDLt; /* Est. number of distinct keys less than this sample */
|
|
};
|
|
|
|
/*
|
|
** Possible values to use within the flags argument to sqlite3GetToken().
|
|
*/
|
|
#define SQLITE_TOKEN_QUOTED 0x1 /* Token is a quoted identifier. */
|
|
#define SQLITE_TOKEN_KEYWORD 0x2 /* Token is a keyword. */
|
|
|
|
/*
|
|
** Each token coming out of the lexer is an instance of
|
|
** this structure. Tokens are also used as part of an expression.
|
|
**
|
|
** The memory that "z" points to is owned by other objects. Take care
|
|
** that the owner of the "z" string does not deallocate the string before
|
|
** the Token goes out of scope! Very often, the "z" points to some place
|
|
** in the middle of the Parse.zSql text. But it might also point to a
|
|
** static string.
|
|
*/
|
|
struct Token {
|
|
const char *z; /* Text of the token. Not NULL-terminated! */
|
|
unsigned int n; /* 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.iAgg 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 */
|
|
u16 nSortingColumn; /* Number of columns in the sorting index */
|
|
int sortingIdx; /* Cursor number of the sorting index */
|
|
int sortingIdxPTab; /* Cursor number of pseudo-table */
|
|
int iFirstReg; /* First register in range for aCol[] and aFunc[] */
|
|
ExprList *pGroupBy; /* The group by clause */
|
|
struct AggInfo_col { /* For each column used in source tables */
|
|
Table *pTab; /* Source table */
|
|
Expr *pCExpr; /* The original expression */
|
|
int iTable; /* Cursor number of the source table */
|
|
i16 iColumn; /* Column number within the source table */
|
|
i16 iSorterColumn; /* Column number in the sorting index */
|
|
} *aCol;
|
|
int nColumn; /* Number of used entries in 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 *pFExpr; /* Expression encoding the function */
|
|
FuncDef *pFunc; /* The aggregate function implementation */
|
|
int iDistinct; /* Ephemeral table used to enforce DISTINCT */
|
|
int iDistAddr; /* Address of OP_OpenEphemeral */
|
|
int iOBTab; /* Ephemeral table to implement ORDER BY */
|
|
u8 bOBPayload; /* iOBTab has payload columns separate from key */
|
|
u8 bOBUnique; /* Enforce uniqueness on iOBTab keys */
|
|
u8 bUseSubtype; /* Transfer subtype info through sorter */
|
|
} *aFunc;
|
|
int nFunc; /* Number of entries in aFunc[] */
|
|
u32 selId; /* Select to which this AggInfo belongs */
|
|
#ifdef SQLITE_DEBUG
|
|
Select *pSelect; /* SELECT statement that this AggInfo supports */
|
|
#endif
|
|
};
|
|
|
|
/*
|
|
** Macros to compute aCol[] and aFunc[] register numbers.
|
|
**
|
|
** These macros should not be used prior to the call to
|
|
** assignAggregateRegisters() that computes the value of pAggInfo->iFirstReg.
|
|
** The assert()s that are part of this macro verify that constraint.
|
|
*/
|
|
#define AggInfoColumnReg(A,I) (assert((A)->iFirstReg),(A)->iFirstReg+(I))
|
|
#define AggInfoFuncReg(A,I) \
|
|
(assert((A)->iFirstReg),(A)->iFirstReg+(A)->nColumn+(I))
|
|
|
|
/*
|
|
** The datatype ynVar is a signed integer, either 16-bit or 32-bit.
|
|
** Usually it is 16-bits. But if SQLITE_MAX_VARIABLE_NUMBER is greater
|
|
** than 32767 we have to make it 32-bit. 16-bit is preferred because
|
|
** it uses less memory in the Expr object, which is a big memory user
|
|
** in systems with lots of prepared statements. And few applications
|
|
** need more than about 10 or 20 variables. But some extreme users want
|
|
** to have prepared statements with over 32766 variables, and for them
|
|
** the option is available (at compile-time).
|
|
*/
|
|
#if SQLITE_MAX_VARIABLE_NUMBER<32767
|
|
typedef i16 ynVar;
|
|
#else
|
|
typedef int ynVar;
|
|
#endif
|
|
|
|
/*
|
|
** 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.
|
|
**
|
|
** If the expression is an SQL literal (TK_INTEGER, TK_FLOAT, TK_BLOB,
|
|
** or TK_STRING), then Expr.u.zToken contains the text of the SQL literal. If
|
|
** the expression is a variable (TK_VARIABLE), then Expr.u.zToken contains the
|
|
** variable name. Finally, if the expression is an SQL function (TK_FUNCTION),
|
|
** then Expr.u.zToken contains the name of the function.
|
|
**
|
|
** Expr.pRight and Expr.pLeft are the left and right subexpressions of a
|
|
** binary operator. Either or both may be NULL.
|
|
**
|
|
** Expr.x.pList is a list of arguments if the expression is an SQL function,
|
|
** a CASE expression or an IN expression of the form "<lhs> IN (<y>, <z>...)".
|
|
** Expr.x.pSelect is used if the expression is a sub-select or an expression of
|
|
** the form "<lhs> IN (SELECT ...)". If the EP_xIsSelect bit is set in the
|
|
** Expr.flags mask, then Expr.x.pSelect is valid. Otherwise, Expr.x.pList is
|
|
** valid.
|
|
**
|
|
** 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 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.
|
|
**
|
|
** 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.
|
|
**
|
|
** ALLOCATION NOTES:
|
|
**
|
|
** Expr objects can use a lot of memory space in database schema. To
|
|
** help reduce memory requirements, sometimes an Expr object will be
|
|
** truncated. And to reduce the number of memory allocations, sometimes
|
|
** two or more Expr objects will be stored in a single memory allocation,
|
|
** together with Expr.u.zToken strings.
|
|
**
|
|
** If the EP_Reduced and EP_TokenOnly flags are set when
|
|
** an Expr object is truncated. When EP_Reduced is set, then all
|
|
** the child Expr objects in the Expr.pLeft and Expr.pRight subtrees
|
|
** are contained within the same memory allocation. Note, however, that
|
|
** the subtrees in Expr.x.pList or Expr.x.pSelect are always separately
|
|
** allocated, regardless of whether or not EP_Reduced is set.
|
|
*/
|
|
struct Expr {
|
|
u8 op; /* Operation performed by this node */
|
|
char affExpr; /* affinity, or RAISE type */
|
|
u8 op2; /* TK_REGISTER/TK_TRUTH: original value of Expr.op
|
|
** TK_COLUMN: the value of p5 for OP_Column
|
|
** TK_AGG_FUNCTION: nesting depth
|
|
** TK_FUNCTION: NC_SelfRef flag if needs OP_PureFunc */
|
|
#ifdef SQLITE_DEBUG
|
|
u8 vvaFlags; /* Verification flags. */
|
|
#endif
|
|
u32 flags; /* Various flags. EP_* See below */
|
|
union {
|
|
char *zToken; /* Token value. Zero terminated and dequoted */
|
|
int iValue; /* Non-negative integer value if EP_IntValue */
|
|
} u;
|
|
|
|
/* If the EP_TokenOnly flag is set in the Expr.flags mask, then no
|
|
** space is allocated for the fields below this point. An attempt to
|
|
** access them will result in a segfault or malfunction.
|
|
*********************************************************************/
|
|
|
|
Expr *pLeft; /* Left subnode */
|
|
Expr *pRight; /* Right subnode */
|
|
union {
|
|
ExprList *pList; /* op = IN, EXISTS, SELECT, CASE, FUNCTION, BETWEEN */
|
|
Select *pSelect; /* EP_xIsSelect and op = IN, EXISTS, SELECT */
|
|
} x;
|
|
|
|
/* If the EP_Reduced flag is set in the Expr.flags mask, then no
|
|
** space is allocated for the fields below this point. An attempt to
|
|
** access them will result in a segfault or malfunction.
|
|
*********************************************************************/
|
|
|
|
#if SQLITE_MAX_EXPR_DEPTH>0
|
|
int nHeight; /* Height of the tree headed by this node */
|
|
#endif
|
|
int iTable; /* TK_COLUMN: cursor number of table holding column
|
|
** TK_REGISTER: register number
|
|
** TK_TRIGGER: 1 -> new, 0 -> old
|
|
** EP_Unlikely: 134217728 times likelihood
|
|
** TK_IN: ephemeral table holding RHS
|
|
** TK_SELECT_COLUMN: Number of columns on the LHS
|
|
** TK_SELECT: 1st register of result vector */
|
|
ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid.
|
|
** TK_VARIABLE: variable number (always >= 1).
|
|
** TK_SELECT_COLUMN: column of the result vector */
|
|
i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
|
|
union {
|
|
int iJoin; /* If EP_OuterON or EP_InnerON, the right table */
|
|
int iOfst; /* else: start of token from start of statement */
|
|
} w;
|
|
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
|
|
union {
|
|
Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL
|
|
** for a column of an index on an expression */
|
|
Window *pWin; /* EP_WinFunc: Window/Filter defn for a function */
|
|
struct { /* TK_IN, TK_SELECT, and TK_EXISTS */
|
|
int iAddr; /* Subroutine entry address */
|
|
int regReturn; /* Register used to hold return address */
|
|
} sub;
|
|
} y;
|
|
};
|
|
|
|
/* The following are the meanings of bits in the Expr.flags field.
|
|
** Value restrictions:
|
|
**
|
|
** EP_Agg == NC_HasAgg == SF_HasAgg
|
|
** EP_Win == NC_HasWin
|
|
*/
|
|
#define EP_OuterON 0x000001 /* Originates in ON/USING clause of outer join */
|
|
#define EP_InnerON 0x000002 /* Originates in ON/USING of an inner join */
|
|
#define EP_Distinct 0x000004 /* Aggregate function with DISTINCT keyword */
|
|
#define EP_HasFunc 0x000008 /* Contains one or more functions of any kind */
|
|
#define EP_Agg 0x000010 /* Contains one or more aggregate functions */
|
|
#define EP_FixedCol 0x000020 /* TK_Column with a known fixed value */
|
|
#define EP_VarSelect 0x000040 /* pSelect is correlated, not constant */
|
|
#define EP_DblQuoted 0x000080 /* token.z was originally in "..." */
|
|
#define EP_InfixFunc 0x000100 /* True for an infix function: LIKE, GLOB, etc */
|
|
#define EP_Collate 0x000200 /* Tree contains a TK_COLLATE operator */
|
|
#define EP_Commuted 0x000400 /* Comparison operator has been commuted */
|
|
#define EP_IntValue 0x000800 /* Integer value contained in u.iValue */
|
|
#define EP_xIsSelect 0x001000 /* x.pSelect is valid (otherwise x.pList is) */
|
|
#define EP_Skip 0x002000 /* Operator does not contribute to affinity */
|
|
#define EP_Reduced 0x004000 /* Expr struct EXPR_REDUCEDSIZE bytes only */
|
|
#define EP_Win 0x008000 /* Contains window functions */
|
|
#define EP_TokenOnly 0x010000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
|
|
#define EP_FullSize 0x020000 /* Expr structure must remain full sized */
|
|
#define EP_IfNullRow 0x040000 /* The TK_IF_NULL_ROW opcode */
|
|
#define EP_Unlikely 0x080000 /* unlikely() or likelihood() function */
|
|
#define EP_ConstFunc 0x100000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */
|
|
#define EP_CanBeNull 0x200000 /* Can be null despite NOT NULL constraint */
|
|
#define EP_Subquery 0x400000 /* Tree contains a TK_SELECT operator */
|
|
#define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */
|
|
#define EP_WinFunc 0x1000000 /* TK_FUNCTION with Expr.y.pWin set */
|
|
#define EP_Subrtn 0x2000000 /* Uses Expr.y.sub. TK_IN, _SELECT, or _EXISTS */
|
|
#define EP_Quoted 0x4000000 /* TK_ID was originally quoted */
|
|
#define EP_Static 0x8000000 /* Held in memory not obtained from malloc() */
|
|
#define EP_IsTrue 0x10000000 /* Always has boolean value of TRUE */
|
|
#define EP_IsFalse 0x20000000 /* Always has boolean value of FALSE */
|
|
#define EP_FromDDL 0x40000000 /* Originates from sqlite_schema */
|
|
/* 0x80000000 // Available */
|
|
|
|
/* The EP_Propagate mask is a set of properties that automatically propagate
|
|
** upwards into parent nodes.
|
|
*/
|
|
#define EP_Propagate (EP_Collate|EP_Subquery|EP_HasFunc)
|
|
|
|
/* Macros can be used to test, set, or clear bits in the
|
|
** Expr.flags field.
|
|
*/
|
|
#define ExprHasProperty(E,P) (((E)->flags&(P))!=0)
|
|
#define ExprHasAllProperty(E,P) (((E)->flags&(P))==(P))
|
|
#define ExprSetProperty(E,P) (E)->flags|=(P)
|
|
#define ExprClearProperty(E,P) (E)->flags&=~(P)
|
|
#define ExprAlwaysTrue(E) (((E)->flags&(EP_OuterON|EP_IsTrue))==EP_IsTrue)
|
|
#define ExprAlwaysFalse(E) (((E)->flags&(EP_OuterON|EP_IsFalse))==EP_IsFalse)
|
|
#define ExprIsFullSize(E) (((E)->flags&(EP_Reduced|EP_TokenOnly))==0)
|
|
|
|
/* Macros used to ensure that the correct members of unions are accessed
|
|
** in Expr.
|
|
*/
|
|
#define ExprUseUToken(E) (((E)->flags&EP_IntValue)==0)
|
|
#define ExprUseUValue(E) (((E)->flags&EP_IntValue)!=0)
|
|
#define ExprUseWOfst(E) (((E)->flags&(EP_InnerON|EP_OuterON))==0)
|
|
#define ExprUseWJoin(E) (((E)->flags&(EP_InnerON|EP_OuterON))!=0)
|
|
#define ExprUseXList(E) (((E)->flags&EP_xIsSelect)==0)
|
|
#define ExprUseXSelect(E) (((E)->flags&EP_xIsSelect)!=0)
|
|
#define ExprUseYTab(E) (((E)->flags&(EP_WinFunc|EP_Subrtn))==0)
|
|
#define ExprUseYWin(E) (((E)->flags&EP_WinFunc)!=0)
|
|
#define ExprUseYSub(E) (((E)->flags&EP_Subrtn)!=0)
|
|
|
|
/* Flags for use with Expr.vvaFlags
|
|
*/
|
|
#define EP_NoReduce 0x01 /* Cannot EXPRDUP_REDUCE this Expr */
|
|
#define EP_Immutable 0x02 /* Do not change this Expr node */
|
|
|
|
/* The ExprSetVVAProperty() macro is used for Verification, Validation,
|
|
** and Accreditation only. It works like ExprSetProperty() during VVA
|
|
** processes but is a no-op for delivery.
|
|
*/
|
|
#ifdef SQLITE_DEBUG
|
|
# define ExprSetVVAProperty(E,P) (E)->vvaFlags|=(P)
|
|
# define ExprHasVVAProperty(E,P) (((E)->vvaFlags&(P))!=0)
|
|
# define ExprClearVVAProperties(E) (E)->vvaFlags = 0
|
|
#else
|
|
# define ExprSetVVAProperty(E,P)
|
|
# define ExprHasVVAProperty(E,P) 0
|
|
# define ExprClearVVAProperties(E)
|
|
#endif
|
|
|
|
/*
|
|
** Macros to determine the number of bytes required by a normal Expr
|
|
** struct, an Expr struct with the EP_Reduced flag set in Expr.flags
|
|
** and an Expr struct with the EP_TokenOnly flag set.
|
|
*/
|
|
#define EXPR_FULLSIZE sizeof(Expr) /* Full size */
|
|
#define EXPR_REDUCEDSIZE offsetof(Expr,iTable) /* Common features */
|
|
#define EXPR_TOKENONLYSIZE offsetof(Expr,pLeft) /* Fewer features */
|
|
|
|
/*
|
|
** Flags passed to the sqlite3ExprDup() function. See the header comment
|
|
** above sqlite3ExprDup() for details.
|
|
*/
|
|
#define EXPRDUP_REDUCE 0x0001 /* Used reduced-size Expr nodes */
|
|
|
|
/*
|
|
** True if the expression passed as an argument was a function with
|
|
** an OVER() clause (a window function).
|
|
*/
|
|
#ifdef SQLITE_OMIT_WINDOWFUNC
|
|
# define IsWindowFunc(p) 0
|
|
#else
|
|
# define IsWindowFunc(p) ( \
|
|
ExprHasProperty((p), EP_WinFunc) && p->y.pWin->eFrmType!=TK_FILTER \
|
|
)
|
|
#endif
|
|
|
|
/*
|
|
** A list of expressions. Each expression may optionally have a
|
|
** name. An expr/name combination can be used in several ways, such
|
|
** as the list of "expr AS ID" fields following a "SELECT" or in the
|
|
** list of "ID = expr" items in an UPDATE. A list of expressions can
|
|
** also be used as the argument to a function, in which case the a.zName
|
|
** field is not used.
|
|
**
|
|
** In order to try to keep memory usage down, the Expr.a.zEName field
|
|
** is used for multiple purposes:
|
|
**
|
|
** eEName Usage
|
|
** ---------- -------------------------
|
|
** ENAME_NAME (1) the AS of result set column
|
|
** (2) COLUMN= of an UPDATE
|
|
**
|
|
** ENAME_TAB DB.TABLE.NAME used to resolve names
|
|
** of subqueries
|
|
**
|
|
** ENAME_SPAN Text of the original result set
|
|
** expression.
|
|
*/
|
|
struct ExprList {
|
|
int nExpr; /* Number of expressions on the list */
|
|
int nAlloc; /* Number of a[] slots allocated */
|
|
struct ExprList_item { /* For each expression in the list */
|
|
Expr *pExpr; /* The parse tree for this expression */
|
|
char *zEName; /* Token associated with this expression */
|
|
struct {
|
|
u8 sortFlags; /* Mask of KEYINFO_ORDER_* flags */
|
|
unsigned eEName :2; /* Meaning of zEName */
|
|
unsigned done :1; /* Indicates when processing is finished */
|
|
unsigned reusable :1; /* Constant expression is reusable */
|
|
unsigned bSorterRef :1; /* Defer evaluation until after sorting */
|
|
unsigned bNulls :1; /* True if explicit "NULLS FIRST/LAST" */
|
|
unsigned bUsed :1; /* This column used in a SF_NestedFrom subquery */
|
|
unsigned bUsingTerm:1; /* Term from the USING clause of a NestedFrom */
|
|
unsigned bNoExpand: 1; /* Term is an auxiliary in NestedFrom and should
|
|
** not be expanded by "*" in parent queries */
|
|
} fg;
|
|
union {
|
|
struct { /* Used by any ExprList other than Parse.pConsExpr */
|
|
u16 iOrderByCol; /* For ORDER BY, column number in result set */
|
|
u16 iAlias; /* Index into Parse.aAlias[] for zName */
|
|
} x;
|
|
int iConstExprReg; /* Register in which Expr value is cached. Used only
|
|
** by Parse.pConstExpr */
|
|
} u;
|
|
} a[1]; /* One slot for each expression in the list */
|
|
};
|
|
|
|
/*
|
|
** Allowed values for Expr.a.eEName
|
|
*/
|
|
#define ENAME_NAME 0 /* The AS clause of a result set */
|
|
#define ENAME_SPAN 1 /* Complete text of the result set expression */
|
|
#define ENAME_TAB 2 /* "DB.TABLE.NAME" for the result set */
|
|
#define ENAME_ROWID 3 /* "DB.TABLE._rowid_" for * expansion of rowid */
|
|
|
|
/*
|
|
** An instance of this structure can hold a simple list of identifiers,
|
|
** such as the list "a,b,c" in the following statements:
|
|
**
|
|
** INSERT INTO t(a,b,c) VALUES ...;
|
|
** CREATE INDEX idx ON t(a,b,c);
|
|
** CREATE TRIGGER trig BEFORE UPDATE ON t(a,b,c) ...;
|
|
**
|
|
** The IdList.a.idx field is used when the IdList represents the list of
|
|
** column names after a table name in an INSERT statement. In the statement
|
|
**
|
|
** INSERT INTO t(a,b,c) ...
|
|
**
|
|
** If "a" is the k-th column of table "t", then IdList.a[0].idx==k.
|
|
*/
|
|
struct IdList {
|
|
int nId; /* Number of identifiers on the list */
|
|
u8 eU4; /* Which element of a.u4 is valid */
|
|
struct IdList_item {
|
|
char *zName; /* Name of the identifier */
|
|
union {
|
|
int idx; /* Index in some Table.aCol[] of a column named zName */
|
|
Expr *pExpr; /* Expr to implement a USING variable -- NOT USED */
|
|
} u4;
|
|
} a[1];
|
|
};
|
|
|
|
/*
|
|
** Allowed values for IdList.eType, which determines which value of the a.u4
|
|
** is valid.
|
|
*/
|
|
#define EU4_NONE 0 /* Does not use IdList.a.u4 */
|
|
#define EU4_IDX 1 /* Uses IdList.a.u4.idx */
|
|
#define EU4_EXPR 2 /* Uses IdList.a.u4.pExpr -- NOT CURRENTLY USED */
|
|
|
|
/*
|
|
** The SrcItem object represents a single term in the FROM clause of a query.
|
|
** The SrcList object is mostly an array of SrcItems.
|
|
**
|
|
** The jointype starts out showing the join type between the current table
|
|
** and the next table on the list. The parser builds the list this way.
|
|
** But sqlite3SrcListShiftJoinType() later shifts the jointypes so that each
|
|
** jointype expresses the join between the table and the previous table.
|
|
**
|
|
** In the colUsed field, the high-order bit (bit 63) is set if the table
|
|
** contains more than 63 columns and the 64-th or later column is used.
|
|
**
|
|
** Union member validity:
|
|
**
|
|
** u1.zIndexedBy fg.isIndexedBy && !fg.isTabFunc
|
|
** u1.pFuncArg fg.isTabFunc && !fg.isIndexedBy
|
|
** u2.pIBIndex fg.isIndexedBy && !fg.isCte
|
|
** u2.pCteUse fg.isCte && !fg.isIndexedBy
|
|
*/
|
|
struct SrcItem {
|
|
Schema *pSchema; /* Schema to which this item is fixed */
|
|
char *zDatabase; /* Name of database holding this table */
|
|
char *zName; /* Name of the table */
|
|
char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */
|
|
Table *pTab; /* An SQL table corresponding to zName */
|
|
Select *pSelect; /* A SELECT statement used in place of a table name */
|
|
int addrFillSub; /* Address of subroutine to manifest a subquery */
|
|
int regReturn; /* Register holding return address of addrFillSub */
|
|
int regResult; /* Registers holding results of a co-routine */
|
|
struct {
|
|
u8 jointype; /* Type of join between this table and the previous */
|
|
unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */
|
|
unsigned isIndexedBy :1; /* True if there is an INDEXED BY clause */
|
|
unsigned isTabFunc :1; /* True if table-valued-function syntax */
|
|
unsigned isCorrelated :1; /* True if sub-query is correlated */
|
|
unsigned isMaterialized:1; /* This is a materialized view */
|
|
unsigned viaCoroutine :1; /* Implemented as a co-routine */
|
|
unsigned isRecursive :1; /* True for recursive reference in WITH */
|
|
unsigned fromDDL :1; /* Comes from sqlite_schema */
|
|
unsigned isCte :1; /* This is a CTE */
|
|
unsigned notCte :1; /* This item may not match a CTE */
|
|
unsigned isUsing :1; /* u3.pUsing is valid */
|
|
unsigned isOn :1; /* u3.pOn was once valid and non-NULL */
|
|
unsigned isSynthUsing :1; /* u3.pUsing is synthesized from NATURAL */
|
|
unsigned isNestedFrom :1; /* pSelect is a SF_NestedFrom subquery */
|
|
} fg;
|
|
int iCursor; /* The VDBE cursor number used to access this table */
|
|
union {
|
|
Expr *pOn; /* fg.isUsing==0 => The ON clause of a join */
|
|
IdList *pUsing; /* fg.isUsing==1 => The USING clause of a join */
|
|
} u3;
|
|
Bitmask colUsed; /* Bit N set if column N used. Details above for N>62 */
|
|
union {
|
|
char *zIndexedBy; /* Identifier from "INDEXED BY <zIndex>" clause */
|
|
ExprList *pFuncArg; /* Arguments to table-valued-function */
|
|
} u1;
|
|
union {
|
|
Index *pIBIndex; /* Index structure corresponding to u1.zIndexedBy */
|
|
CteUse *pCteUse; /* CTE Usage info when fg.isCte is true */
|
|
} u2;
|
|
};
|
|
|
|
/*
|
|
** The OnOrUsing object represents either an ON clause or a USING clause.
|
|
** It can never be both at the same time, but it can be neither.
|
|
*/
|
|
struct OnOrUsing {
|
|
Expr *pOn; /* The ON clause of a join */
|
|
IdList *pUsing; /* The USING clause of a join */
|
|
};
|
|
|
|
/*
|
|
** This object represents one or more tables that are the source of
|
|
** content for an SQL statement. For example, a single SrcList object
|
|
** is used to hold the FROM clause of a SELECT statement. SrcList also
|
|
** represents the target tables for DELETE, INSERT, and UPDATE statements.
|
|
**
|
|
*/
|
|
struct SrcList {
|
|
int nSrc; /* Number of tables or subqueries in the FROM clause */
|
|
u32 nAlloc; /* Number of entries allocated in a[] below */
|
|
SrcItem a[1]; /* One entry for each identifier on the list */
|
|
};
|
|
|
|
/*
|
|
** Permitted values of the SrcList.a.jointype field
|
|
*/
|
|
#define JT_INNER 0x01 /* Any kind of inner or cross join */
|
|
#define JT_CROSS 0x02 /* Explicit use of the CROSS keyword */
|
|
#define JT_NATURAL 0x04 /* True for a "natural" join */
|
|
#define JT_LEFT 0x08 /* Left outer join */
|
|
#define JT_RIGHT 0x10 /* Right outer join */
|
|
#define JT_OUTER 0x20 /* The "OUTER" keyword is present */
|
|
#define JT_LTORJ 0x40 /* One of the LEFT operands of a RIGHT JOIN
|
|
** Mnemonic: Left Table Of Right Join */
|
|
#define JT_ERROR 0x80 /* unknown or unsupported join type */
|
|
|
|
/*
|
|
** Flags appropriate for the wctrlFlags parameter of sqlite3WhereBegin()
|
|
** and the WhereInfo.wctrlFlags member.
|
|
**
|
|
** Value constraints (enforced via assert()):
|
|
** WHERE_USE_LIMIT == SF_FixedLimit
|
|
*/
|
|
#define WHERE_ORDERBY_NORMAL 0x0000 /* No-op */
|
|
#define WHERE_ORDERBY_MIN 0x0001 /* ORDER BY processing for min() func */
|
|
#define WHERE_ORDERBY_MAX 0x0002 /* ORDER BY processing for max() func */
|
|
#define WHERE_ONEPASS_DESIRED 0x0004 /* Want to do one-pass UPDATE/DELETE */
|
|
#define WHERE_ONEPASS_MULTIROW 0x0008 /* ONEPASS is ok with multiple rows */
|
|
#define WHERE_DUPLICATES_OK 0x0010 /* Ok to return a row more than once */
|
|
#define WHERE_OR_SUBCLAUSE 0x0020 /* Processing a sub-WHERE as part of
|
|
** the OR optimization */
|
|
#define WHERE_GROUPBY 0x0040 /* pOrderBy is really a GROUP BY */
|
|
#define WHERE_DISTINCTBY 0x0080 /* pOrderby is really a DISTINCT clause */
|
|
#define WHERE_WANT_DISTINCT 0x0100 /* All output needs to be distinct */
|
|
#define WHERE_SORTBYGROUP 0x0200 /* Support sqlite3WhereIsSorted() */
|
|
#define WHERE_AGG_DISTINCT 0x0400 /* Query is "SELECT agg(DISTINCT ...)" */
|
|
#define WHERE_ORDERBY_LIMIT 0x0800 /* ORDERBY+LIMIT on the inner loop */
|
|
#define WHERE_RIGHT_JOIN 0x1000 /* Processing a RIGHT JOIN */
|
|
/* 0x2000 not currently used */
|
|
#define WHERE_USE_LIMIT 0x4000 /* Use the LIMIT in cost estimates */
|
|
/* 0x8000 not currently used */
|
|
|
|
/* Allowed return values from sqlite3WhereIsDistinct()
|
|
*/
|
|
#define WHERE_DISTINCT_NOOP 0 /* DISTINCT keyword not used */
|
|
#define WHERE_DISTINCT_UNIQUE 1 /* No duplicates */
|
|
#define WHERE_DISTINCT_ORDERED 2 /* All duplicates are adjacent */
|
|
#define WHERE_DISTINCT_UNORDERED 3 /* Duplicates are scattered */
|
|
|
|
/*
|
|
** A NameContext defines a context in which to resolve table and column
|
|
** names. The context consists of a list of tables (the pSrcList) field and
|
|
** a list of named expression (pEList). The named expression list may
|
|
** be NULL. The pSrc corresponds to the FROM clause of a SELECT or
|
|
** to the table being operated on by INSERT, UPDATE, or DELETE. The
|
|
** pEList corresponds to the result set of a SELECT and is NULL for
|
|
** other statements.
|
|
**
|
|
** NameContexts can be nested. When resolving names, the inner-most
|
|
** context is searched first. If no match is found, the next outer
|
|
** context is checked. If there is still no match, the next context
|
|
** is checked. This process continues until either a match is found
|
|
** or all contexts are check. When a match is found, the nRef member of
|
|
** the context containing the match is incremented.
|
|
**
|
|
** Each subquery gets a new NameContext. The pNext field points to the
|
|
** NameContext in the parent query. Thus the process of scanning the
|
|
** NameContext list corresponds to searching through successively outer
|
|
** subqueries looking for a match.
|
|
*/
|
|
struct NameContext {
|
|
Parse *pParse; /* The parser */
|
|
SrcList *pSrcList; /* One or more tables used to resolve names */
|
|
union {
|
|
ExprList *pEList; /* Optional list of result-set columns */
|
|
AggInfo *pAggInfo; /* Information about aggregates at this level */
|
|
Upsert *pUpsert; /* ON CONFLICT clause information from an upsert */
|
|
int iBaseReg; /* For TK_REGISTER when parsing RETURNING */
|
|
} uNC;
|
|
NameContext *pNext; /* Next outer name context. NULL for outermost */
|
|
int nRef; /* Number of names resolved by this context */
|
|
int nNcErr; /* Number of errors encountered while resolving names */
|
|
int ncFlags; /* Zero or more NC_* flags defined below */
|
|
u32 nNestedSelect; /* Number of nested selects using this NC */
|
|
Select *pWinSelect; /* SELECT statement for any window functions */
|
|
};
|
|
|
|
/*
|
|
** Allowed values for the NameContext, ncFlags field.
|
|
**
|
|
** Value constraints (all checked via assert()):
|
|
** NC_HasAgg == SF_HasAgg == EP_Agg
|
|
** NC_MinMaxAgg == SF_MinMaxAgg == SQLITE_FUNC_MINMAX
|
|
** NC_OrderAgg == SF_OrderByReqd == SQLITE_FUNC_ANYORDER
|
|
** NC_HasWin == EP_Win
|
|
**
|
|
*/
|
|
#define NC_AllowAgg 0x000001 /* Aggregate functions are allowed here */
|
|
#define NC_PartIdx 0x000002 /* True if resolving a partial index WHERE */
|
|
#define NC_IsCheck 0x000004 /* True if resolving a CHECK constraint */
|
|
#define NC_GenCol 0x000008 /* True for a GENERATED ALWAYS AS clause */
|
|
#define NC_HasAgg 0x000010 /* One or more aggregate functions seen */
|
|
#define NC_IdxExpr 0x000020 /* True if resolving columns of CREATE INDEX */
|
|
#define NC_SelfRef 0x00002e /* Combo: PartIdx, isCheck, GenCol, and IdxExpr */
|
|
#define NC_Subquery 0x000040 /* A subquery has been seen */
|
|
#define NC_UEList 0x000080 /* True if uNC.pEList is used */
|
|
#define NC_UAggInfo 0x000100 /* True if uNC.pAggInfo is used */
|
|
#define NC_UUpsert 0x000200 /* True if uNC.pUpsert is used */
|
|
#define NC_UBaseReg 0x000400 /* True if uNC.iBaseReg is used */
|
|
#define NC_MinMaxAgg 0x001000 /* min/max aggregates seen. See note above */
|
|
#define NC_Complex 0x002000 /* True if a function or subquery seen */
|
|
#define NC_AllowWin 0x004000 /* Window functions are allowed here */
|
|
#define NC_HasWin 0x008000 /* One or more window functions seen */
|
|
#define NC_IsDDL 0x010000 /* Resolving names in a CREATE statement */
|
|
#define NC_InAggFunc 0x020000 /* True if analyzing arguments to an agg func */
|
|
#define NC_FromDDL 0x040000 /* SQL text comes from sqlite_schema */
|
|
#define NC_NoSelect 0x080000 /* Do not descend into sub-selects */
|
|
#define NC_Where 0x100000 /* Processing WHERE clause of a SELECT */
|
|
#define NC_OrderAgg 0x8000000 /* Has an aggregate other than count/min/max */
|
|
|
|
/*
|
|
** An instance of the following object describes a single ON CONFLICT
|
|
** clause in an upsert.
|
|
**
|
|
** The pUpsertTarget field is only set if the ON CONFLICT clause includes
|
|
** conflict-target clause. (In "ON CONFLICT(a,b)" the "(a,b)" is the
|
|
** conflict-target clause.) The pUpsertTargetWhere is the optional
|
|
** WHERE clause used to identify partial unique indexes.
|
|
**
|
|
** pUpsertSet is the list of column=expr terms of the UPDATE statement.
|
|
** The pUpsertSet field is NULL for a ON CONFLICT DO NOTHING. The
|
|
** pUpsertWhere is the WHERE clause for the UPDATE and is NULL if the
|
|
** WHERE clause is omitted.
|
|
*/
|
|
struct Upsert {
|
|
ExprList *pUpsertTarget; /* Optional description of conflict target */
|
|
Expr *pUpsertTargetWhere; /* WHERE clause for partial index targets */
|
|
ExprList *pUpsertSet; /* The SET clause from an ON CONFLICT UPDATE */
|
|
Expr *pUpsertWhere; /* WHERE clause for the ON CONFLICT UPDATE */
|
|
Upsert *pNextUpsert; /* Next ON CONFLICT clause in the list */
|
|
u8 isDoUpdate; /* True for DO UPDATE. False for DO NOTHING */
|
|
u8 isDup; /* True if 2nd or later with same pUpsertIdx */
|
|
/* Above this point is the parse tree for the ON CONFLICT clauses.
|
|
** The next group of fields stores intermediate data. */
|
|
void *pToFree; /* Free memory when deleting the Upsert object */
|
|
/* All fields above are owned by the Upsert object and must be freed
|
|
** when the Upsert is destroyed. The fields below are used to transfer
|
|
** information from the INSERT processing down into the UPDATE processing
|
|
** while generating code. The fields below are owned by the INSERT
|
|
** statement and will be freed by INSERT processing. */
|
|
Index *pUpsertIdx; /* UNIQUE constraint specified by pUpsertTarget */
|
|
SrcList *pUpsertSrc; /* Table to be updated */
|
|
int regData; /* First register holding array of VALUES */
|
|
int iDataCur; /* Index of the data cursor */
|
|
int iIdxCur; /* Index of the first index cursor */
|
|
};
|
|
|
|
/*
|
|
** An instance of the following structure contains all information
|
|
** needed to generate code for a single SELECT statement.
|
|
**
|
|
** See the header comment on the computeLimitRegisters() routine for a
|
|
** detailed description of the meaning of the iLimit and iOffset fields.
|
|
**
|
|
** addrOpenEphm[] entries contain the address of OP_OpenEphemeral opcodes.
|
|
** These addresses must be stored so that we can go back and fill in
|
|
** the P4_KEYINFO and P2 parameters later. Neither the KeyInfo nor
|
|
** the number of columns in P2 can be computed at the same time
|
|
** as the OP_OpenEphm instruction is coded because not
|
|
** enough information about the compound query is known at that point.
|
|
** The KeyInfo for addrOpenTran[0] and [1] contains collating sequences
|
|
** for the result set. The KeyInfo for addrOpenEphm[2] contains collating
|
|
** sequences for the ORDER BY clause.
|
|
*/
|
|
struct Select {
|
|
u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
|
|
LogEst nSelectRow; /* Estimated number of result rows */
|
|
u32 selFlags; /* Various SF_* values */
|
|
int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */
|
|
u32 selId; /* Unique identifier number for this SELECT */
|
|
int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */
|
|
ExprList *pEList; /* The fields of the result */
|
|
SrcList *pSrc; /* The FROM clause */
|
|
Expr *pWhere; /* The WHERE clause */
|
|
ExprList *pGroupBy; /* The GROUP BY clause */
|
|
Expr *pHaving; /* The HAVING clause */
|
|
ExprList *pOrderBy; /* The ORDER BY clause */
|
|
Select *pPrior; /* Prior select in a compound select statement */
|
|
Select *pNext; /* Next select to the left in a compound */
|
|
Expr *pLimit; /* LIMIT expression. NULL means not used. */
|
|
With *pWith; /* WITH clause attached to this select. Or NULL. */
|
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
Window *pWin; /* List of window functions */
|
|
Window *pWinDefn; /* List of named window definitions */
|
|
#endif
|
|
};
|
|
|
|
/*
|
|
** Allowed values for Select.selFlags. The "SF" prefix stands for
|
|
** "Select Flag".
|
|
**
|
|
** Value constraints (all checked via assert())
|
|
** SF_HasAgg == NC_HasAgg
|
|
** SF_MinMaxAgg == NC_MinMaxAgg == SQLITE_FUNC_MINMAX
|
|
** SF_OrderByReqd == NC_OrderAgg == SQLITE_FUNC_ANYORDER
|
|
** SF_FixedLimit == WHERE_USE_LIMIT
|
|
*/
|
|
#define SF_Distinct 0x0000001 /* Output should be DISTINCT */
|
|
#define SF_All 0x0000002 /* Includes the ALL keyword */
|
|
#define SF_Resolved 0x0000004 /* Identifiers have been resolved */
|
|
#define SF_Aggregate 0x0000008 /* Contains agg functions or a GROUP BY */
|
|
#define SF_HasAgg 0x0000010 /* Contains aggregate functions */
|
|
#define SF_UsesEphemeral 0x0000020 /* Uses the OpenEphemeral opcode */
|
|
#define SF_Expanded 0x0000040 /* sqlite3SelectExpand() called on this */
|
|
#define SF_HasTypeInfo 0x0000080 /* FROM subqueries have Table metadata */
|
|
#define SF_Compound 0x0000100 /* Part of a compound query */
|
|
#define SF_Values 0x0000200 /* Synthesized from VALUES clause */
|
|
#define SF_MultiValue 0x0000400 /* Single VALUES term with multiple rows */
|
|
#define SF_NestedFrom 0x0000800 /* Part of a parenthesized FROM clause */
|
|
#define SF_MinMaxAgg 0x0001000 /* Aggregate containing min() or max() */
|
|
#define SF_Recursive 0x0002000 /* The recursive part of a recursive CTE */
|
|
#define SF_FixedLimit 0x0004000 /* nSelectRow set by a constant LIMIT */
|
|
#define SF_MaybeConvert 0x0008000 /* Need convertCompoundSelectToSubquery() */
|
|
#define SF_Converted 0x0010000 /* By convertCompoundSelectToSubquery() */
|
|
#define SF_IncludeHidden 0x0020000 /* Include hidden columns in output */
|
|
#define SF_ComplexResult 0x0040000 /* Result contains subquery or function */
|
|
#define SF_WhereBegin 0x0080000 /* Really a WhereBegin() call. Debug Only */
|
|
#define SF_WinRewrite 0x0100000 /* Window function rewrite accomplished */
|
|
#define SF_View 0x0200000 /* SELECT statement is a view */
|
|
#define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */
|
|
#define SF_UFSrcCheck 0x0800000 /* Check pSrc as required by UPDATE...FROM */
|
|
#define SF_PushDown 0x1000000 /* SELECT has be modified by push-down opt */
|
|
#define SF_MultiPart 0x2000000 /* Has multiple incompatible PARTITIONs */
|
|
#define SF_CopyCte 0x4000000 /* SELECT statement is a copy of a CTE */
|
|
#define SF_OrderByReqd 0x8000000 /* The ORDER BY clause may not be omitted */
|
|
#define SF_UpdateFrom 0x10000000 /* Query originates with UPDATE FROM */
|
|
|
|
/* True if S exists and has SF_NestedFrom */
|
|
#define IsNestedFrom(S) ((S)!=0 && ((S)->selFlags&SF_NestedFrom)!=0)
|
|
|
|
/*
|
|
** The results of a SELECT can be distributed in several ways, as defined
|
|
** by one of the following macros. The "SRT" prefix means "SELECT Result
|
|
** Type".
|
|
**
|
|
** SRT_Union Store results as a key in a temporary index
|
|
** identified by pDest->iSDParm.
|
|
**
|
|
** SRT_Except Remove results from the temporary index pDest->iSDParm.
|
|
**
|
|
** SRT_Exists Store a 1 in memory cell pDest->iSDParm if the result
|
|
** set is not empty.
|
|
**
|
|
** SRT_Discard Throw the results away. This is used by SELECT
|
|
** statements within triggers whose only purpose is
|
|
** the side-effects of functions.
|
|
**
|
|
** SRT_Output Generate a row of output (using the OP_ResultRow
|
|
** opcode) for each row in the result set.
|
|
**
|
|
** SRT_Mem Only valid if the result is a single column.
|
|
** Store the first column of the first result row
|
|
** in register pDest->iSDParm then abandon the rest
|
|
** of the query. This destination implies "LIMIT 1".
|
|
**
|
|
** SRT_Set The result must be a single column. Store each
|
|
** row of result as the key in table pDest->iSDParm.
|
|
** Apply the affinity pDest->affSdst before storing
|
|
** results. Used to implement "IN (SELECT ...)".
|
|
**
|
|
** SRT_EphemTab Create an temporary table pDest->iSDParm and store
|
|
** the result there. The cursor is left open after
|
|
** returning. This is like SRT_Table except that
|
|
** this destination uses OP_OpenEphemeral to create
|
|
** the table first.
|
|
**
|
|
** SRT_Coroutine Generate a co-routine that returns a new row of
|
|
** results each time it is invoked. The entry point
|
|
** of the co-routine is stored in register pDest->iSDParm
|
|
** and the result row is stored in pDest->nDest registers
|
|
** starting with pDest->iSdst.
|
|
**
|
|
** SRT_Table Store results in temporary table pDest->iSDParm.
|
|
** SRT_Fifo This is like SRT_EphemTab except that the table
|
|
** is assumed to already be open. SRT_Fifo has
|
|
** the additional property of being able to ignore
|
|
** the ORDER BY clause.
|
|
**
|
|
** SRT_DistFifo Store results in a temporary table pDest->iSDParm.
|
|
** But also use temporary table pDest->iSDParm+1 as
|
|
** a record of all prior results and ignore any duplicate
|
|
** rows. Name means: "Distinct Fifo".
|
|
**
|
|
** SRT_Queue Store results in priority queue pDest->iSDParm (really
|
|
** an index). Append a sequence number so that all entries
|
|
** are distinct.
|
|
**
|
|
** SRT_DistQueue Store results in priority queue pDest->iSDParm only if
|
|
** the same record has never been stored before. The
|
|
** index at pDest->iSDParm+1 hold all prior stores.
|
|
**
|
|
** SRT_Upfrom Store results in the temporary table already opened by
|
|
** pDest->iSDParm. If (pDest->iSDParm<0), then the temp
|
|
** table is an intkey table - in this case the first
|
|
** column returned by the SELECT is used as the integer
|
|
** key. If (pDest->iSDParm>0), then the table is an index
|
|
** table. (pDest->iSDParm) is the number of key columns in
|
|
** each index record in this case.
|
|
*/
|
|
#define SRT_Union 1 /* Store result as keys in an index */
|
|
#define SRT_Except 2 /* Remove result from a UNION index */
|
|
#define SRT_Exists 3 /* Store 1 if the result is not empty */
|
|
#define SRT_Discard 4 /* Do not save the results anywhere */
|
|
#define SRT_DistFifo 5 /* Like SRT_Fifo, but unique results only */
|
|
#define SRT_DistQueue 6 /* Like SRT_Queue, but unique results only */
|
|
|
|
/* The DISTINCT clause is ignored for all of the above. Not that
|
|
** IgnorableDistinct() implies IgnorableOrderby() */
|
|
#define IgnorableDistinct(X) ((X->eDest)<=SRT_DistQueue)
|
|
|
|
#define SRT_Queue 7 /* Store result in an queue */
|
|
#define SRT_Fifo 8 /* Store result as data with an automatic rowid */
|
|
|
|
/* The ORDER BY clause is ignored for all of the above */
|
|
#define IgnorableOrderby(X) ((X->eDest)<=SRT_Fifo)
|
|
|
|
#define SRT_Output 9 /* Output each row of result */
|
|
#define SRT_Mem 10 /* Store result in a memory cell */
|
|
#define SRT_Set 11 /* Store results as keys in an index */
|
|
#define SRT_EphemTab 12 /* Create transient tab and store like SRT_Table */
|
|
#define SRT_Coroutine 13 /* Generate a single row of result */
|
|
#define SRT_Table 14 /* Store result as data with an automatic rowid */
|
|
#define SRT_Upfrom 15 /* Store result as data with rowid */
|
|
|
|
/*
|
|
** An instance of this object describes where to put of the results of
|
|
** a SELECT statement.
|
|
*/
|
|
struct SelectDest {
|
|
u8 eDest; /* How to dispose of the results. One of SRT_* above. */
|
|
int iSDParm; /* A parameter used by the eDest disposal method */
|
|
int iSDParm2; /* A second parameter for the eDest disposal method */
|
|
int iSdst; /* Base register where results are written */
|
|
int nSdst; /* Number of registers allocated */
|
|
char *zAffSdst; /* Affinity used for SRT_Set */
|
|
ExprList *pOrderBy; /* Key columns for SRT_Queue and SRT_DistQueue */
|
|
};
|
|
|
|
/*
|
|
** During code generation of statements that do inserts into AUTOINCREMENT
|
|
** tables, the following information is attached to the Table.u.autoInc.p
|
|
** pointer of each autoincrement table to record some side information that
|
|
** the code generator needs. We have to keep per-table autoincrement
|
|
** information in case inserts are done within triggers. Triggers do not
|
|
** normally coordinate their activities, but we do need to coordinate the
|
|
** loading and saving of autoincrement information.
|
|
*/
|
|
struct AutoincInfo {
|
|
AutoincInfo *pNext; /* Next info block in a list of them all */
|
|
Table *pTab; /* Table this info block refers to */
|
|
int iDb; /* Index in sqlite3.aDb[] of database holding pTab */
|
|
int regCtr; /* Memory register holding the rowid counter */
|
|
};
|
|
|
|
/*
|
|
** At least one instance of the following structure is created for each
|
|
** trigger that may be fired while parsing an INSERT, UPDATE or DELETE
|
|
** statement. All such objects are stored in the linked list headed at
|
|
** Parse.pTriggerPrg and deleted once statement compilation has been
|
|
** completed.
|
|
**
|
|
** A Vdbe sub-program that implements the body and WHEN clause of trigger
|
|
** TriggerPrg.pTrigger, assuming a default ON CONFLICT clause of
|
|
** TriggerPrg.orconf, is stored in the TriggerPrg.pProgram variable.
|
|
** The Parse.pTriggerPrg list never contains two entries with the same
|
|
** values for both pTrigger and orconf.
|
|
**
|
|
** The TriggerPrg.aColmask[0] variable is set to a mask of old.* columns
|
|
** accessed (or set to 0 for triggers fired as a result of INSERT
|
|
** statements). Similarly, the TriggerPrg.aColmask[1] variable is set to
|
|
** a mask of new.* columns used by the program.
|
|
*/
|
|
struct TriggerPrg {
|
|
Trigger *pTrigger; /* Trigger this program was coded from */
|
|
TriggerPrg *pNext; /* Next entry in Parse.pTriggerPrg list */
|
|
SubProgram *pProgram; /* Program implementing pTrigger/orconf */
|
|
int orconf; /* Default ON CONFLICT policy */
|
|
u32 aColmask[2]; /* Masks of old.*, new.* columns accessed */
|
|
};
|
|
|
|
/*
|
|
** The yDbMask datatype for the bitmask of all attached databases.
|
|
*/
|
|
#if SQLITE_MAX_ATTACHED>30
|
|
typedef unsigned char yDbMask[(SQLITE_MAX_ATTACHED+9)/8];
|
|
# define DbMaskTest(M,I) (((M)[(I)/8]&(1<<((I)&7)))!=0)
|
|
# define DbMaskZero(M) memset((M),0,sizeof(M))
|
|
# define DbMaskSet(M,I) (M)[(I)/8]|=(1<<((I)&7))
|
|
# define DbMaskAllZero(M) sqlite3DbMaskAllZero(M)
|
|
# define DbMaskNonZero(M) (sqlite3DbMaskAllZero(M)==0)
|
|
#else
|
|
typedef unsigned int yDbMask;
|
|
# define DbMaskTest(M,I) (((M)&(((yDbMask)1)<<(I)))!=0)
|
|
# define DbMaskZero(M) ((M)=0)
|
|
# define DbMaskSet(M,I) ((M)|=(((yDbMask)1)<<(I)))
|
|
# define DbMaskAllZero(M) ((M)==0)
|
|
# define DbMaskNonZero(M) ((M)!=0)
|
|
#endif
|
|
|
|
/*
|
|
** For each index X that has as one of its arguments either an expression
|
|
** or the name of a virtual generated column, and if X is in scope such that
|
|
** the value of the expression can simply be read from the index, then
|
|
** there is an instance of this object on the Parse.pIdxExpr list.
|
|
**
|
|
** During code generation, while generating code to evaluate expressions,
|
|
** this list is consulted and if a matching expression is found, the value
|
|
** is read from the index rather than being recomputed.
|
|
*/
|
|
struct IndexedExpr {
|
|
Expr *pExpr; /* The expression contained in the index */
|
|
int iDataCur; /* The data cursor associated with the index */
|
|
int iIdxCur; /* The index cursor */
|
|
int iIdxCol; /* The index column that contains value of pExpr */
|
|
u8 bMaybeNullRow; /* True if we need an OP_IfNullRow check */
|
|
u8 aff; /* Affinity of the pExpr expression */
|
|
IndexedExpr *pIENext; /* Next in a list of all indexed expressions */
|
|
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
|
const char *zIdxName; /* Name of index, used only for bytecode comments */
|
|
#endif
|
|
};
|
|
|
|
/*
|
|
** An instance of the ParseCleanup object specifies an operation that
|
|
** should be performed after parsing to deallocation resources obtained
|
|
** during the parse and which are no longer needed.
|
|
*/
|
|
struct ParseCleanup {
|
|
ParseCleanup *pNext; /* Next cleanup task */
|
|
void *pPtr; /* Pointer to object to deallocate */
|
|
void (*xCleanup)(sqlite3*,void*); /* Deallocation routine */
|
|
};
|
|
|
|
/*
|
|
** An SQL parser context. A copy of this structure is passed through
|
|
** the parser and down into all the parser action routine in order to
|
|
** carry around information that is global to the entire parse.
|
|
**
|
|
** The structure is divided into two parts. When the parser and code
|
|
** generate call themselves recursively, the first part of the structure
|
|
** is constant but the second part is reset at the beginning and end of
|
|
** each recursion.
|
|
**
|
|
** The nTableLock and aTableLock variables are only used if the shared-cache
|
|
** feature is enabled (if sqlite3Tsd()->useSharedData is true). They are
|
|
** used to store the set of table-locks required by the statement being
|
|
** compiled. Function sqlite3TableLock() is used to add entries to the
|
|
** list.
|
|
*/
|
|
struct Parse {
|
|
sqlite3 *db; /* The main database structure */
|
|
char *zErrMsg; /* An error message */
|
|
Vdbe *pVdbe; /* An engine for executing database bytecode */
|
|
int rc; /* Return code from execution */
|
|
u8 colNamesSet; /* TRUE after OP_ColumnName has been issued to pVdbe */
|
|
u8 checkSchema; /* Causes schema cookie check after an error */
|
|
u8 nested; /* Number of nested calls to the parser/code generator */
|
|
u8 nTempReg; /* Number of temporary registers in aTempReg[] */
|
|
u8 isMultiWrite; /* True if statement may modify/insert multiple rows */
|
|
u8 mayAbort; /* True if statement may throw an ABORT exception */
|
|
u8 hasCompound; /* Need to invoke convertCompoundSelectToSubquery() */
|
|
u8 okConstFactor; /* OK to factor out constants */
|
|
u8 disableLookaside; /* Number of times lookaside has been disabled */
|
|
u8 prepFlags; /* SQLITE_PREPARE_* flags */
|
|
u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */
|
|
#if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST)
|
|
u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */
|
|
#endif
|
|
#ifdef SQLITE_DEBUG
|
|
u8 ifNotExists; /* Might be true if IF NOT EXISTS. Assert()s only */
|
|
#endif
|
|
int nRangeReg; /* Size of the temporary register block */
|
|
int iRangeReg; /* First register in temporary register block */
|
|
int nErr; /* Number of errors seen */
|
|
int nTab; /* Number of previously allocated VDBE cursors */
|
|
int nMem; /* Number of memory cells used so far */
|
|
int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */
|
|
int iSelfTab; /* Table associated with an index on expr, or negative
|
|
** of the base register during check-constraint eval */
|
|
int nLabel; /* The *negative* of the number of labels used */
|
|
int nLabelAlloc; /* Number of slots in aLabel */
|
|
int *aLabel; /* Space to hold the labels */
|
|
ExprList *pConstExpr;/* Constant expressions */
|
|
IndexedExpr *pIdxEpr;/* List of expressions used by active indexes */
|
|
IndexedExpr *pIdxPartExpr; /* Exprs constrained by index WHERE clauses */
|
|
Token constraintName;/* Name of the constraint currently being parsed */
|
|
yDbMask writeMask; /* Start a write transaction on these databases */
|
|
yDbMask cookieMask; /* Bitmask of schema verified databases */
|
|
int regRowid; /* Register holding rowid of CREATE TABLE entry */
|
|
int regRoot; /* Register holding root page number for new objects */
|
|
int nMaxArg; /* Max args passed to user function by sub-program */
|
|
int nSelect; /* Number of SELECT stmts. Counter for Select.selId */
|
|
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
|
|
u32 nProgressSteps; /* xProgress steps taken during sqlite3_prepare() */
|
|
#endif
|
|
#ifndef SQLITE_OMIT_SHARED_CACHE
|
|
int nTableLock; /* Number of locks in aTableLock */
|
|
TableLock *aTableLock; /* Required table locks for shared-cache mode */
|
|
#endif
|
|
AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */
|
|
Parse *pToplevel; /* Parse structure for main program (or NULL) */
|
|
Table *pTriggerTab; /* Table triggers are being coded for */
|
|
TriggerPrg *pTriggerPrg; /* Linked list of coded triggers */
|
|
ParseCleanup *pCleanup; /* List of cleanup operations to run after parse */
|
|
union {
|
|
int addrCrTab; /* Address of OP_CreateBtree on CREATE TABLE */
|
|
Returning *pReturning; /* The RETURNING clause */
|
|
} u1;
|
|
u32 oldmask; /* Mask of old.* columns referenced */
|
|
u32 newmask; /* Mask of new.* columns referenced */
|
|
LogEst nQueryLoop; /* Est number of iterations of a query (10*log2(N)) */
|
|
u8 eTriggerOp; /* TK_UPDATE, TK_INSERT or TK_DELETE */
|
|
u8 bReturning; /* Coding a RETURNING trigger */
|
|
u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */
|
|
u8 disableTriggers; /* True to disable triggers */
|
|
|
|
/**************************************************************************
|
|
** Fields above must be initialized to zero. The fields that follow,
|
|
** down to the beginning of the recursive section, do not need to be
|
|
** initialized as they will be set before being used. The boundary is
|
|
** determined by offsetof(Parse,aTempReg).
|
|
**************************************************************************/
|
|
|
|
int aTempReg[8]; /* Holding area for temporary registers */
|
|
Parse *pOuterParse; /* Outer Parse object when nested */
|
|
Token sNameToken; /* Token with unqualified schema object name */
|
|
|
|
/************************************************************************
|
|
** Above is constant between recursions. Below is reset before and after
|
|
** each recursion. The boundary between these two regions is determined
|
|
** using offsetof(Parse,sLastToken) so the sLastToken field must be the
|
|
** first field in the recursive region.
|
|
************************************************************************/
|
|
|
|
Token sLastToken; /* The last token parsed */
|
|
ynVar nVar; /* Number of '?' variables seen in the SQL so far */
|
|
u8 iPkSortOrder; /* ASC or DESC for INTEGER PRIMARY KEY */
|
|
u8 explain; /* True if the EXPLAIN flag is found on the query */
|
|
u8 eParseMode; /* PARSE_MODE_XXX constant */
|
|
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
|
int nVtabLock; /* Number of virtual tables to lock */
|
|
#endif
|
|
int nHeight; /* Expression tree height of current sub-select */
|
|
#ifndef SQLITE_OMIT_EXPLAIN
|
|
int addrExplain; /* Address of current OP_Explain opcode */
|
|
#endif
|
|
VList *pVList; /* Mapping between variable names and numbers */
|
|
Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */
|
|
const char *zTail; /* All SQL text past the last semicolon parsed */
|
|
Table *pNewTable; /* A table being constructed by CREATE TABLE */
|
|
Index *pNewIndex; /* An index being constructed by CREATE INDEX.
|
|
** Also used to hold redundant UNIQUE constraints
|
|
** during a RENAME COLUMN */
|
|
Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */
|
|
const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */
|
|
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
|
Token sArg; /* Complete text of a module argument */
|
|
Table **apVtabLock; /* Pointer to virtual tables needing locking */
|
|
#endif
|
|
With *pWith; /* Current WITH clause, or NULL */
|
|
#ifndef SQLITE_OMIT_ALTERTABLE
|
|
RenameToken *pRename; /* Tokens subject to renaming by ALTER TABLE */
|
|
#endif
|
|
};
|
|
|
|
/* Allowed values for Parse.eParseMode
|
|
*/
|
|
#define PARSE_MODE_NORMAL 0
|
|
#define PARSE_MODE_DECLARE_VTAB 1
|
|
#define PARSE_MODE_RENAME 2
|
|
#define PARSE_MODE_UNMAP 3
|
|
|
|
/*
|
|
** Sizes and pointers of various parts of the Parse object.
|
|
*/
|
|
#define PARSE_HDR(X) (((char*)(X))+offsetof(Parse,zErrMsg))
|
|
#define PARSE_HDR_SZ (offsetof(Parse,aTempReg)-offsetof(Parse,zErrMsg)) /* Recursive part w/o aColCache*/
|
|
#define PARSE_RECURSE_SZ offsetof(Parse,sLastToken) /* Recursive part */
|
|
#define PARSE_TAIL_SZ (sizeof(Parse)-PARSE_RECURSE_SZ) /* Non-recursive part */
|
|
#define PARSE_TAIL(X) (((char*)(X))+PARSE_RECURSE_SZ) /* Pointer to tail */
|
|
|
|
/*
|
|
** Return true if currently inside an sqlite3_declare_vtab() call.
|
|
*/
|
|
#ifdef SQLITE_OMIT_VIRTUALTABLE
|
|
#define IN_DECLARE_VTAB 0
|
|
#else
|
|
#define IN_DECLARE_VTAB (pParse->eParseMode==PARSE_MODE_DECLARE_VTAB)
|
|
#endif
|
|
|
|
#if defined(SQLITE_OMIT_ALTERTABLE)
|
|
#define IN_RENAME_OBJECT 0
|
|
#else
|
|
#define IN_RENAME_OBJECT (pParse->eParseMode>=PARSE_MODE_RENAME)
|
|
#endif
|
|
|
|
#if defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_OMIT_ALTERTABLE)
|
|
#define IN_SPECIAL_PARSE 0
|
|
#else
|
|
#define IN_SPECIAL_PARSE (pParse->eParseMode!=PARSE_MODE_NORMAL)
|
|
#endif
|
|
|
|
/*
|
|
** An instance of the following structure can be declared on a stack and used
|
|
** to save the Parse.zAuthContext value so that it can be restored later.
|
|
*/
|
|
struct AuthContext {
|
|
const char *zAuthContext; /* Put saved Parse.zAuthContext here */
|
|
Parse *pParse; /* The Parse structure */
|
|
};
|
|
|
|
/*
|
|
** Bitfield flags for P5 value in various opcodes.
|
|
**
|
|
** Value constraints (enforced via assert()):
|
|
** OPFLAG_LENGTHARG == SQLITE_FUNC_LENGTH
|
|
** OPFLAG_TYPEOFARG == SQLITE_FUNC_TYPEOF
|
|
** OPFLAG_BULKCSR == BTREE_BULKLOAD
|
|
** OPFLAG_SEEKEQ == BTREE_SEEK_EQ
|
|
** OPFLAG_FORDELETE == BTREE_FORDELETE
|
|
** OPFLAG_SAVEPOSITION == BTREE_SAVEPOSITION
|
|
** OPFLAG_AUXDELETE == BTREE_AUXDELETE
|
|
*/
|
|
#define OPFLAG_NCHANGE 0x01 /* OP_Insert: Set to update db->nChange */
|
|
/* Also used in P2 (not P5) of OP_Delete */
|
|
#define OPFLAG_NOCHNG 0x01 /* OP_VColumn nochange for UPDATE */
|
|
#define OPFLAG_EPHEM 0x01 /* OP_Column: Ephemeral output is ok */
|
|
#define OPFLAG_LASTROWID 0x20 /* Set to update db->lastRowid */
|
|
#define OPFLAG_ISUPDATE 0x04 /* This OP_Insert is an sql UPDATE */
|
|
#define OPFLAG_APPEND 0x08 /* This is likely to be an append */
|
|
#define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */
|
|
#define OPFLAG_ISNOOP 0x40 /* OP_Delete does pre-update-hook only */
|
|
#define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */
|
|
#define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */
|
|
#define OPFLAG_BYTELENARG 0xc0 /* OP_Column only for octet_length() */
|
|
#define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */
|
|
#define OPFLAG_SEEKEQ 0x02 /* OP_Open** cursor uses EQ seek only */
|
|
#define OPFLAG_FORDELETE 0x08 /* OP_Open should use BTREE_FORDELETE */
|
|
#define OPFLAG_P2ISREG 0x10 /* P2 to OP_Open** is a register number */
|
|
#define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */
|
|
#define OPFLAG_SAVEPOSITION 0x02 /* OP_Delete/Insert: save cursor pos */
|
|
#define OPFLAG_AUXDELETE 0x04 /* OP_Delete: index in a DELETE op */
|
|
#define OPFLAG_NOCHNG_MAGIC 0x6d /* OP_MakeRecord: serialtype 10 is ok */
|
|
#define OPFLAG_PREFORMAT 0x80 /* OP_Insert uses preformatted cell */
|
|
|
|
/*
|
|
** Each trigger present in the database schema is stored as an instance of
|
|
** struct Trigger.
|
|
**
|
|
** Pointers to instances of struct Trigger are stored in two ways.
|
|
** 1. In the "trigHash" hash table (part of the sqlite3* that represents the
|
|
** database). This allows Trigger structures to be retrieved by name.
|
|
** 2. All triggers associated with a single table form a linked list, using the
|
|
** pNext member of struct Trigger. A pointer to the first element of the
|
|
** linked list is stored as the "pTrigger" member of the associated
|
|
** struct Table.
|
|
**
|
|
** The "step_list" member points to the first element of a linked list
|
|
** containing the SQL statements specified as the trigger program.
|
|
*/
|
|
struct Trigger {
|
|
char *zName; /* The name of the trigger */
|
|
char *table; /* The table or view to which the trigger applies */
|
|
u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT */
|
|
u8 tr_tm; /* One of TRIGGER_BEFORE, TRIGGER_AFTER */
|
|
u8 bReturning; /* This trigger implements a RETURNING clause */
|
|
Expr *pWhen; /* The WHEN clause of the expression (may be NULL) */
|
|
IdList *pColumns; /* If this is an UPDATE OF <column-list> trigger,
|
|
the <column-list> is stored here */
|
|
Schema *pSchema; /* Schema containing the trigger */
|
|
Schema *pTabSchema; /* Schema containing the table */
|
|
TriggerStep *step_list; /* Link list of trigger program steps */
|
|
Trigger *pNext; /* Next trigger associated with the table */
|
|
};
|
|
|
|
/*
|
|
** A trigger is either a BEFORE or an AFTER trigger. The following constants
|
|
** determine which.
|
|
**
|
|
** If there are multiple triggers, you might of some BEFORE and some AFTER.
|
|
** In that cases, the constants below can be ORed together.
|
|
*/
|
|
#define TRIGGER_BEFORE 1
|
|
#define TRIGGER_AFTER 2
|
|
|
|
/*
|
|
** An instance of struct TriggerStep is used to store a single SQL statement
|
|
** that is a part of a trigger-program.
|
|
**
|
|
** Instances of struct TriggerStep are stored in a singly linked list (linked
|
|
** using the "pNext" member) referenced by the "step_list" member of the
|
|
** associated struct Trigger instance. The first element of the linked list is
|
|
** the first step of the trigger-program.
|
|
**
|
|
** The "op" member indicates whether this is a "DELETE", "INSERT", "UPDATE" or
|
|
** "SELECT" statement. The meanings of the other members is determined by the
|
|
** value of "op" as follows:
|
|
**
|
|
** (op == TK_INSERT)
|
|
** orconf -> stores the ON CONFLICT algorithm
|
|
** pSelect -> The content to be inserted - either a SELECT statement or
|
|
** a VALUES clause.
|
|
** zTarget -> Dequoted name of the table to insert into.
|
|
** pIdList -> If this is an INSERT INTO ... (<column-names>) VALUES ...
|
|
** statement, then this stores the column-names to be
|
|
** inserted into.
|
|
** pUpsert -> The ON CONFLICT clauses for an Upsert
|
|
**
|
|
** (op == TK_DELETE)
|
|
** zTarget -> Dequoted name of the table to delete from.
|
|
** pWhere -> The WHERE clause of the DELETE statement if one is specified.
|
|
** Otherwise NULL.
|
|
**
|
|
** (op == TK_UPDATE)
|
|
** zTarget -> Dequoted name of the table to update.
|
|
** pWhere -> The WHERE clause of the UPDATE statement if one is specified.
|
|
** Otherwise NULL.
|
|
** pExprList -> A list of the columns to update and the expressions to update
|
|
** them to. See sqlite3Update() documentation of "pChanges"
|
|
** argument.
|
|
**
|
|
** (op == TK_SELECT)
|
|
** pSelect -> The SELECT statement
|
|
**
|
|
** (op == TK_RETURNING)
|
|
** pExprList -> The list of expressions that follow the RETURNING keyword.
|
|
**
|
|
*/
|
|
struct TriggerStep {
|
|
u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT,
|
|
** or TK_RETURNING */
|
|
u8 orconf; /* OE_Rollback etc. */
|
|
Trigger *pTrig; /* The trigger that this step is a part of */
|
|
Select *pSelect; /* SELECT statement or RHS of INSERT INTO SELECT ... */
|
|
char *zTarget; /* Target table for DELETE, UPDATE, INSERT */
|
|
SrcList *pFrom; /* FROM clause for UPDATE statement (if any) */
|
|
Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */
|
|
ExprList *pExprList; /* SET clause for UPDATE, or RETURNING clause */
|
|
IdList *pIdList; /* Column names for INSERT */
|
|
Upsert *pUpsert; /* Upsert clauses on an INSERT */
|
|
char *zSpan; /* Original SQL text of this command */
|
|
TriggerStep *pNext; /* Next in the link-list */
|
|
TriggerStep *pLast; /* Last element in link-list. Valid for 1st elem only */
|
|
};
|
|
|
|
/*
|
|
** Information about a RETURNING clause
|
|
*/
|
|
struct Returning {
|
|
Parse *pParse; /* The parse that includes the RETURNING clause */
|
|
ExprList *pReturnEL; /* List of expressions to return */
|
|
Trigger retTrig; /* The transient trigger that implements RETURNING */
|
|
TriggerStep retTStep; /* The trigger step */
|
|
int iRetCur; /* Transient table holding RETURNING results */
|
|
int nRetCol; /* Number of in pReturnEL after expansion */
|
|
int iRetReg; /* Register array for holding a row of RETURNING */
|
|
char zName[40]; /* Name of trigger: "sqlite_returning_%p" */
|
|
};
|
|
|
|
/*
|
|
** An objected used to accumulate the text of a string where we
|
|
** do not necessarily know how big the string will be in the end.
|
|
*/
|
|
struct sqlite3_str {
|
|
sqlite3 *db; /* Optional database for lookaside. Can be NULL */
|
|
char *zText; /* The string collected so far */
|
|
u32 nAlloc; /* Amount of space allocated in zText */
|
|
u32 mxAlloc; /* Maximum allowed allocation. 0 for no malloc usage */
|
|
u32 nChar; /* Length of the string so far */
|
|
u8 accError; /* SQLITE_NOMEM or SQLITE_TOOBIG */
|
|
u8 printfFlags; /* SQLITE_PRINTF flags below */
|
|
};
|
|
#define SQLITE_PRINTF_INTERNAL 0x01 /* Internal-use-only converters allowed */
|
|
#define SQLITE_PRINTF_SQLFUNC 0x02 /* SQL function arguments to VXPrintf */
|
|
#define SQLITE_PRINTF_MALLOCED 0x04 /* True if xText is allocated space */
|
|
|
|
#define isMalloced(X) (((X)->printfFlags & SQLITE_PRINTF_MALLOCED)!=0)
|
|
|
|
/*
|
|
** The following object is the header for an "RCStr" or "reference-counted
|
|
** string". An RCStr is passed around and used like any other char*
|
|
** that has been dynamically allocated. The important interface
|
|
** differences:
|
|
**
|
|
** 1. RCStr strings are reference counted. They are deallocated
|
|
** when the reference count reaches zero.
|
|
**
|
|
** 2. Use sqlite3RCStrUnref() to free an RCStr string rather than
|
|
** sqlite3_free()
|
|
**
|
|
** 3. Make a (read-only) copy of a read-only RCStr string using
|
|
** sqlite3RCStrRef().
|
|
**
|
|
** "String" is in the name, but an RCStr object can also be used to hold
|
|
** binary data.
|
|
*/
|
|
struct RCStr {
|
|
u64 nRCRef; /* Number of references */
|
|
/* Total structure size should be a multiple of 8 bytes for alignment */
|
|
};
|
|
|
|
/*
|
|
** A pointer to this structure is used to communicate information
|
|
** from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback.
|
|
*/
|
|
typedef struct {
|
|
sqlite3 *db; /* The database being initialized */
|
|
char **pzErrMsg; /* Error message stored here */
|
|
int iDb; /* 0 for main database. 1 for TEMP, 2.. for ATTACHed */
|
|
int rc; /* Result code stored here */
|
|
u32 mInitFlags; /* Flags controlling error messages */
|
|
u32 nInitRow; /* Number of rows processed */
|
|
Pgno mxPage; /* Maximum page number. 0 for no limit. */
|
|
} InitData;
|
|
|
|
/*
|
|
** Allowed values for mInitFlags
|
|
*/
|
|
#define INITFLAG_AlterMask 0x0003 /* Types of ALTER */
|
|
#define INITFLAG_AlterRename 0x0001 /* Reparse after a RENAME */
|
|
#define INITFLAG_AlterDrop 0x0002 /* Reparse after a DROP COLUMN */
|
|
#define INITFLAG_AlterAdd 0x0003 /* Reparse after an ADD COLUMN */
|
|
|
|
/* Tuning parameters are set using SQLITE_TESTCTRL_TUNE and are controlled
|
|
** on debug-builds of the CLI using ".testctrl tune ID VALUE". Tuning
|
|
** parameters are for temporary use during development, to help find
|
|
** optimal values for parameters in the query planner. The should not
|
|
** be used on trunk check-ins. They are a temporary mechanism available
|
|
** for transient development builds only.
|
|
**
|
|
** Tuning parameters are numbered starting with 1.
|
|
*/
|
|
#define SQLITE_NTUNE 6 /* Should be zero for all trunk check-ins */
|
|
#ifdef SQLITE_DEBUG
|
|
# define Tuning(X) (sqlite3Config.aTune[(X)-1])
|
|
#else
|
|
# define Tuning(X) 0
|
|
#endif
|
|
|
|
/*
|
|
** Structure containing global configuration data for the SQLite library.
|
|
**
|
|
** This structure also contains some state information.
|
|
*/
|
|
struct Sqlite3Config {
|
|
int bMemstat; /* True to enable memory status */
|
|
u8 bCoreMutex; /* True to enable core mutexing */
|
|
u8 bFullMutex; /* True to enable full mutexing */
|
|
u8 bOpenUri; /* True to interpret filenames as URIs */
|
|
u8 bUseCis; /* Use covering indices for full-scans */
|
|
u8 bSmallMalloc; /* Avoid large memory allocations if true */
|
|
u8 bExtraSchemaChecks; /* Verify type,name,tbl_name in schema */
|
|
u8 bUseLongDouble; /* Make use of long double */
|
|
#ifdef SQLITE_DEBUG
|
|
u8 bJsonSelfcheck; /* Double-check JSON parsing */
|
|
#endif
|
|
int mxStrlen; /* Maximum string length */
|
|
int neverCorrupt; /* Database is always well-formed */
|
|
int szLookaside; /* Default lookaside buffer size */
|
|
int nLookaside; /* Default lookaside buffer count */
|
|
int nStmtSpill; /* Stmt-journal spill-to-disk threshold */
|
|
sqlite3_mem_methods m; /* Low-level memory allocation interface */
|
|
sqlite3_mutex_methods mutex; /* Low-level mutex interface */
|
|
sqlite3_pcache_methods2 pcache2; /* Low-level page-cache interface */
|
|
void *pHeap; /* Heap storage space */
|
|
int nHeap; /* Size of pHeap[] */
|
|
int mnReq, mxReq; /* Min and max heap requests sizes */
|
|
sqlite3_int64 szMmap; /* mmap() space per open file */
|
|
sqlite3_int64 mxMmap; /* Maximum value for szMmap */
|
|
void *pPage; /* Page cache memory */
|
|
int szPage; /* Size of each page in pPage[] */
|
|
int nPage; /* Number of pages in pPage[] */
|
|
int mxParserStack; /* maximum depth of the parser stack */
|
|
int sharedCacheEnabled; /* true if shared-cache mode enabled */
|
|
u32 szPma; /* Maximum Sorter PMA size */
|
|
/* The above might be initialized to non-zero. The following need to always
|
|
** initially be zero, however. */
|
|
int isInit; /* True after initialization has finished */
|
|
int inProgress; /* True while initialization in progress */
|
|
int isMutexInit; /* True after mutexes are initialized */
|
|
int isMallocInit; /* True after malloc is initialized */
|
|
int isPCacheInit; /* True after malloc is initialized */
|
|
int nRefInitMutex; /* Number of users of pInitMutex */
|
|
sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */
|
|
void (*xLog)(void*,int,const char*); /* Function for logging */
|
|
void *pLogArg; /* First argument to xLog() */
|
|
#ifdef SQLITE_ENABLE_SQLLOG
|
|
void(*xSqllog)(void*,sqlite3*,const char*, int);
|
|
void *pSqllogArg;
|
|
#endif
|
|
#ifdef SQLITE_VDBE_COVERAGE
|
|
/* The following callback (if not NULL) is invoked on every VDBE branch
|
|
** operation. Set the callback using SQLITE_TESTCTRL_VDBE_COVERAGE.
|
|
*/
|
|
void (*xVdbeBranch)(void*,unsigned iSrcLine,u8 eThis,u8 eMx); /* Callback */
|
|
void *pVdbeBranchArg; /* 1st argument */
|
|
#endif
|
|
#ifndef SQLITE_OMIT_DESERIALIZE
|
|
sqlite3_int64 mxMemdbSize; /* Default max memdb size */
|
|
#endif
|
|
#ifndef SQLITE_UNTESTABLE
|
|
int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */
|
|
#endif
|
|
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
|
u32 mNoVisibleRowid; /* TF_NoVisibleRowid if the ROWID_IN_VIEW
|
|
** feature is disabled. 0 if rowids can
|
|
** occur in views. */
|
|
#endif
|
|
int bLocaltimeFault; /* True to fail localtime() calls */
|
|
int (*xAltLocaltime)(const void*,void*); /* Alternative localtime() routine */
|
|
int iOnceResetThreshold; /* When to reset OP_Once counters */
|
|
u32 szSorterRef; /* Min size in bytes to use sorter-refs */
|
|
unsigned int iPrngSeed; /* Alternative fixed seed for the PRNG */
|
|
/* vvvv--- must be last ---vvv */
|
|
#ifdef SQLITE_DEBUG
|
|
sqlite3_int64 aTune[SQLITE_NTUNE]; /* Tuning parameters */
|
|
#endif
|
|
};
|
|
|
|
/*
|
|
** This macro is used inside of assert() statements to indicate that
|
|
** the assert is only valid on a well-formed database. Instead of:
|
|
**
|
|
** assert( X );
|
|
**
|
|
** One writes:
|
|
**
|
|
** assert( X || CORRUPT_DB );
|
|
**
|
|
** CORRUPT_DB is true during normal operation. CORRUPT_DB does not indicate
|
|
** that the database is definitely corrupt, only that it might be corrupt.
|
|
** For most test cases, CORRUPT_DB is set to false using a special
|
|
** sqlite3_test_control(). This enables assert() statements to prove
|
|
** things that are always true for well-formed databases.
|
|
*/
|
|
#define CORRUPT_DB (sqlite3Config.neverCorrupt==0)
|
|
|
|
/*
|
|
** Context pointer passed down through the tree-walk.
|
|
*/
|
|
struct Walker {
|
|
Parse *pParse; /* Parser context. */
|
|
int (*xExprCallback)(Walker*, Expr*); /* Callback for expressions */
|
|
int (*xSelectCallback)(Walker*,Select*); /* Callback for SELECTs */
|
|
void (*xSelectCallback2)(Walker*,Select*);/* Second callback for SELECTs */
|
|
int walkerDepth; /* Number of subqueries */
|
|
u16 eCode; /* A small processing code */
|
|
u16 mWFlags; /* Use-dependent flags */
|
|
union { /* Extra data for callback */
|
|
NameContext *pNC; /* Naming context */
|
|
int n; /* A counter */
|
|
int iCur; /* A cursor number */
|
|
SrcList *pSrcList; /* FROM clause */
|
|
struct CCurHint *pCCurHint; /* Used by codeCursorHint() */
|
|
struct RefSrcList *pRefSrcList; /* sqlite3ReferencesSrcList() */
|
|
int *aiCol; /* array of column indexes */
|
|
struct IdxCover *pIdxCover; /* Check for index coverage */
|
|
ExprList *pGroupBy; /* GROUP BY clause */
|
|
Select *pSelect; /* HAVING to WHERE clause ctx */
|
|
struct WindowRewrite *pRewrite; /* Window rewrite context */
|
|
struct WhereConst *pConst; /* WHERE clause constants */
|
|
struct RenameCtx *pRename; /* RENAME COLUMN context */
|
|
struct Table *pTab; /* Table of generated column */
|
|
struct CoveringIndexCheck *pCovIdxCk; /* Check for covering index */
|
|
SrcItem *pSrcItem; /* A single FROM clause item */
|
|
DbFixer *pFix; /* See sqlite3FixSelect() */
|
|
Mem *aMem; /* See sqlite3BtreeCursorHint() */
|
|
} u;
|
|
};
|
|
|
|
/*
|
|
** The following structure contains information used by the sqliteFix...
|
|
** routines as they walk the parse tree to make database references
|
|
** explicit.
|
|
*/
|
|
struct DbFixer {
|
|
Parse *pParse; /* The parsing context. Error messages written here */
|
|
Walker w; /* Walker object */
|
|
Schema *pSchema; /* Fix items to this schema */
|
|
u8 bTemp; /* True for TEMP schema entries */
|
|
const char *zDb; /* Make sure all objects are contained in this database */
|
|
const char *zType; /* Type of the container - used for error messages */
|
|
const Token *pName; /* Name of the container - used for error messages */
|
|
};
|
|
|
|
/* Forward declarations */
|
|
SQLITE_PRIVATE int sqlite3WalkExpr(Walker*, Expr*);
|
|
SQLITE_PRIVATE int sqlite3WalkExprNN(Walker*, Expr*);
|
|
SQLITE_PRIVATE int sqlite3WalkExprList(Walker*, ExprList*);
|
|
SQLITE_PRIVATE int sqlite3WalkSelect(Walker*, Select*);
|
|
SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker*, Select*);
|
|
SQLITE_PRIVATE int sqlite3WalkSelectFrom(Walker*, Select*);
|
|
SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker*, Expr*);
|
|
SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker*, Select*);
|
|
SQLITE_PRIVATE int sqlite3SelectWalkFail(Walker*, Select*);
|
|
SQLITE_PRIVATE int sqlite3WalkerDepthIncrease(Walker*,Select*);
|
|
SQLITE_PRIVATE void sqlite3WalkerDepthDecrease(Walker*,Select*);
|
|
SQLITE_PRIVATE void sqlite3WalkWinDefnDummyCallback(Walker*,Select*);
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
SQLITE_PRIVATE void sqlite3SelectWalkAssert2(Walker*, Select*);
|
|
#endif
|
|
|
|
#ifndef SQLITE_OMIT_CTE
|
|
SQLITE_PRIVATE void sqlite3SelectPopWith(Walker*, Select*);
|
|
#else
|
|
# define sqlite3SelectPopWith 0
|
|
#endif
|
|
|
|
/*
|
|
** Return code from the parse-tree walking primitives and their
|
|
** callbacks.
|
|
*/
|
|
#define WRC_Continue 0 /* Continue down into children */
|
|
#define WRC_Prune 1 /* Omit children but continue walking siblings */
|
|
#define WRC_Abort 2 /* Abandon the tree walk */
|
|
|
|
/*
|
|
** A single common table expression
|
|
*/
|
|
struct Cte {
|
|
char *zName; /* Name of this CTE */
|
|
ExprList *pCols; /* List of explicit column names, or NULL */
|
|
Select *pSelect; /* The definition of this CTE */
|
|
const char *zCteErr; /* Error message for circular references */
|
|
CteUse *pUse; /* Usage information for this CTE */
|
|
u8 eM10d; /* The MATERIALIZED flag */
|
|
};
|
|
|
|
/*
|
|
** Allowed values for the materialized flag (eM10d):
|
|
*/
|
|
#define M10d_Yes 0 /* AS MATERIALIZED */
|
|
#define M10d_Any 1 /* Not specified. Query planner's choice */
|
|
#define M10d_No 2 /* AS NOT MATERIALIZED */
|
|
|
|
/*
|
|
** An instance of the With object represents a WITH clause containing
|
|
** one or more CTEs (common table expressions).
|
|
*/
|
|
struct With {
|
|
int nCte; /* Number of CTEs in the WITH clause */
|
|
int bView; /* Belongs to the outermost Select of a view */
|
|
With *pOuter; /* Containing WITH clause, or NULL */
|
|
Cte a[1]; /* For each CTE in the WITH clause.... */
|
|
};
|
|
|
|
/*
|
|
** The Cte object is not guaranteed to persist for the entire duration
|
|
** of code generation. (The query flattener or other parser tree
|
|
** edits might delete it.) The following object records information
|
|
** about each Common Table Expression that must be preserved for the
|
|
** duration of the parse.
|
|
**
|
|
** The CteUse objects are freed using sqlite3ParserAddCleanup() rather
|
|
** than sqlite3SelectDelete(), which is what enables them to persist
|
|
** until the end of code generation.
|
|
*/
|
|
struct CteUse {
|
|
int nUse; /* Number of users of this CTE */
|
|
int addrM9e; /* Start of subroutine to compute materialization */
|
|
int regRtn; /* Return address register for addrM9e subroutine */
|
|
int iCur; /* Ephemeral table holding the materialization */
|
|
LogEst nRowEst; /* Estimated number of rows in the table */
|
|
u8 eM10d; /* The MATERIALIZED flag */
|
|
};
|
|
|
|
|
|
/* Client data associated with sqlite3_set_clientdata() and
|
|
** sqlite3_get_clientdata().
|
|
*/
|
|
struct DbClientData {
|
|
DbClientData *pNext; /* Next in a linked list */
|
|
void *pData; /* The data */
|
|
void (*xDestructor)(void*); /* Destructor. Might be NULL */
|
|
char zName[1]; /* Name of this client data. MUST BE LAST */
|
|
};
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
/*
|
|
** An instance of the TreeView object is used for printing the content of
|
|
** data structures on sqlite3DebugPrintf() using a tree-like view.
|
|
*/
|
|
struct TreeView {
|
|
int iLevel; /* Which level of the tree we are on */
|
|
u8 bLine[100]; /* Draw vertical in column i if bLine[i] is true */
|
|
};
|
|
#endif /* SQLITE_DEBUG */
|
|
|
|
/*
|
|
** This object is used in various ways, most (but not all) related to window
|
|
** functions.
|
|
**
|
|
** (1) A single instance of this structure is attached to the
|
|
** the Expr.y.pWin field for each window function in an expression tree.
|
|
** This object holds the information contained in the OVER clause,
|
|
** plus additional fields used during code generation.
|
|
**
|
|
** (2) All window functions in a single SELECT form a linked-list
|
|
** attached to Select.pWin. The Window.pFunc and Window.pExpr
|
|
** fields point back to the expression that is the window function.
|
|
**
|
|
** (3) The terms of the WINDOW clause of a SELECT are instances of this
|
|
** object on a linked list attached to Select.pWinDefn.
|
|
**
|
|
** (4) For an aggregate function with a FILTER clause, an instance
|
|
** of this object is stored in Expr.y.pWin with eFrmType set to
|
|
** TK_FILTER. In this case the only field used is Window.pFilter.
|
|
**
|
|
** The uses (1) and (2) are really the same Window object that just happens
|
|
** to be accessible in two different ways. Use case (3) are separate objects.
|
|
*/
|
|
struct Window {
|
|
char *zName; /* Name of window (may be NULL) */
|
|
char *zBase; /* Name of base window for chaining (may be NULL) */
|
|
ExprList *pPartition; /* PARTITION BY clause */
|
|
ExprList *pOrderBy; /* ORDER BY clause */
|
|
u8 eFrmType; /* TK_RANGE, TK_GROUPS, TK_ROWS, or 0 */
|
|
u8 eStart; /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */
|
|
u8 eEnd; /* UNBOUNDED, CURRENT, PRECEDING or FOLLOWING */
|
|
u8 bImplicitFrame; /* True if frame was implicitly specified */
|
|
u8 eExclude; /* TK_NO, TK_CURRENT, TK_TIES, TK_GROUP, or 0 */
|
|
Expr *pStart; /* Expression for "<expr> PRECEDING" */
|
|
Expr *pEnd; /* Expression for "<expr> FOLLOWING" */
|
|
Window **ppThis; /* Pointer to this object in Select.pWin list */
|
|
Window *pNextWin; /* Next window function belonging to this SELECT */
|
|
Expr *pFilter; /* The FILTER expression */
|
|
FuncDef *pWFunc; /* The function */
|
|
int iEphCsr; /* Partition buffer or Peer buffer */
|
|
int regAccum; /* Accumulator */
|
|
int regResult; /* Interim result */
|
|
int csrApp; /* Function cursor (used by min/max) */
|
|
int regApp; /* Function register (also used by min/max) */
|
|
int regPart; /* Array of registers for PARTITION BY values */
|
|
Expr *pOwner; /* Expression object this window is attached to */
|
|
int nBufferCol; /* Number of columns in buffer table */
|
|
int iArgCol; /* Offset of first argument for this function */
|
|
int regOne; /* Register containing constant value 1 */
|
|
int regStartRowid;
|
|
int regEndRowid;
|
|
u8 bExprArgs; /* Defer evaluation of window function arguments
|
|
** due to the SQLITE_SUBTYPE flag */
|
|
};
|
|
|
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
SQLITE_PRIVATE void sqlite3WindowDelete(sqlite3*, Window*);
|
|
SQLITE_PRIVATE void sqlite3WindowUnlinkFromSelect(Window*);
|
|
SQLITE_PRIVATE void sqlite3WindowListDelete(sqlite3 *db, Window *p);
|
|
SQLITE_PRIVATE Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*, u8);
|
|
SQLITE_PRIVATE void sqlite3WindowAttach(Parse*, Expr*, Window*);
|
|
SQLITE_PRIVATE void sqlite3WindowLink(Select *pSel, Window *pWin);
|
|
SQLITE_PRIVATE int sqlite3WindowCompare(const Parse*, const Window*, const Window*, int);
|
|
SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse*, Select*);
|
|
SQLITE_PRIVATE void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int);
|
|
SQLITE_PRIVATE int sqlite3WindowRewrite(Parse*, Select*);
|
|
SQLITE_PRIVATE void sqlite3WindowUpdate(Parse*, Window*, Window*, FuncDef*);
|
|
SQLITE_PRIVATE Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p);
|
|
SQLITE_PRIVATE Window *sqlite3WindowListDup(sqlite3 *db, Window *p);
|
|
SQLITE_PRIVATE void sqlite3WindowFunctions(void);
|
|
SQLITE_PRIVATE void sqlite3WindowChain(Parse*, Window*, Window*);
|
|
SQLITE_PRIVATE Window *sqlite3WindowAssemble(Parse*, Window*, ExprList*, ExprList*, Token*);
|
|
#else
|
|
# define sqlite3WindowDelete(a,b)
|
|
# define sqlite3WindowFunctions()
|
|
# define sqlite3WindowAttach(a,b,c)
|
|
#endif
|
|
|
|
/*
|
|
** Assuming zIn points to the first byte of a UTF-8 character,
|
|
** advance zIn to point to the first byte of the next UTF-8 character.
|
|
*/
|
|
#define SQLITE_SKIP_UTF8(zIn) { \
|
|
if( (*(zIn++))>=0xc0 ){ \
|
|
while( (*zIn & 0xc0)==0x80 ){ zIn++; } \
|
|
} \
|
|
}
|
|
|
|
/*
|
|
** The SQLITE_*_BKPT macros are substitutes for the error codes with
|
|
** the same name but without the _BKPT suffix. These macros invoke
|
|
** routines that report the line-number on which the error originated
|
|
** using sqlite3_log(). The routines also provide a convenient place
|
|
** to set a debugger breakpoint.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3ReportError(int iErr, int lineno, const char *zType);
|
|
SQLITE_PRIVATE int sqlite3CorruptError(int);
|
|
SQLITE_PRIVATE int sqlite3MisuseError(int);
|
|
SQLITE_PRIVATE int sqlite3CantopenError(int);
|
|
#define SQLITE_CORRUPT_BKPT sqlite3CorruptError(__LINE__)
|
|
#define SQLITE_MISUSE_BKPT sqlite3MisuseError(__LINE__)
|
|
#define SQLITE_CANTOPEN_BKPT sqlite3CantopenError(__LINE__)
|
|
#ifdef SQLITE_DEBUG
|
|
SQLITE_PRIVATE int sqlite3NomemError(int);
|
|
SQLITE_PRIVATE int sqlite3IoerrnomemError(int);
|
|
# define SQLITE_NOMEM_BKPT sqlite3NomemError(__LINE__)
|
|
# define SQLITE_IOERR_NOMEM_BKPT sqlite3IoerrnomemError(__LINE__)
|
|
#else
|
|
# define SQLITE_NOMEM_BKPT SQLITE_NOMEM
|
|
# define SQLITE_IOERR_NOMEM_BKPT SQLITE_IOERR_NOMEM
|
|
#endif
|
|
#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_CORRUPT_PGNO)
|
|
SQLITE_PRIVATE int sqlite3CorruptPgnoError(int,Pgno);
|
|
# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptPgnoError(__LINE__,(P))
|
|
#else
|
|
# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptError(__LINE__)
|
|
#endif
|
|
|
|
/*
|
|
** FTS3 and FTS4 both require virtual table support
|
|
*/
|
|
#if defined(SQLITE_OMIT_VIRTUALTABLE)
|
|
# undef SQLITE_ENABLE_FTS3
|
|
# undef SQLITE_ENABLE_FTS4
|
|
#endif
|
|
|
|
/*
|
|
** FTS4 is really an extension for FTS3. It is enabled using the
|
|
** SQLITE_ENABLE_FTS3 macro. But to avoid confusion we also call
|
|
** the SQLITE_ENABLE_FTS4 macro to serve as an alias for SQLITE_ENABLE_FTS3.
|
|
*/
|
|
#if defined(SQLITE_ENABLE_FTS4) && !defined(SQLITE_ENABLE_FTS3)
|
|
# define SQLITE_ENABLE_FTS3 1
|
|
#endif
|
|
|
|
/*
|
|
** The ctype.h header is needed for non-ASCII systems. It is also
|
|
** needed by FTS3 when FTS3 is included in the amalgamation.
|
|
*/
|
|
#if !defined(SQLITE_ASCII) || \
|
|
(defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_AMALGAMATION))
|
|
# include <ctype.h>
|
|
#endif
|
|
|
|
/*
|
|
** The following macros mimic the standard library functions toupper(),
|
|
** isspace(), isalnum(), isdigit() and isxdigit(), respectively. The
|
|
** sqlite versions only work for ASCII characters, regardless of locale.
|
|
*/
|
|
#ifdef SQLITE_ASCII
|
|
# define sqlite3Toupper(x) ((x)&~(sqlite3CtypeMap[(unsigned char)(x)]&0x20))
|
|
# define sqlite3Isspace(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x01)
|
|
# define sqlite3Isalnum(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x06)
|
|
# define sqlite3Isalpha(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x02)
|
|
# define sqlite3Isdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x04)
|
|
# define sqlite3Isxdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x08)
|
|
# define sqlite3Tolower(x) (sqlite3UpperToLower[(unsigned char)(x)])
|
|
# define sqlite3Isquote(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x80)
|
|
# define sqlite3JsonId1(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x42)
|
|
# define sqlite3JsonId2(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x46)
|
|
#else
|
|
# define sqlite3Toupper(x) toupper((unsigned char)(x))
|
|
# define sqlite3Isspace(x) isspace((unsigned char)(x))
|
|
# define sqlite3Isalnum(x) isalnum((unsigned char)(x))
|
|
# define sqlite3Isalpha(x) isalpha((unsigned char)(x))
|
|
# define sqlite3Isdigit(x) isdigit((unsigned char)(x))
|
|
# define sqlite3Isxdigit(x) isxdigit((unsigned char)(x))
|
|
# define sqlite3Tolower(x) tolower((unsigned char)(x))
|
|
# define sqlite3Isquote(x) ((x)=='"'||(x)=='\''||(x)=='['||(x)=='`')
|
|
# define sqlite3JsonId1(x) (sqlite3IsIdChar(x)&&(x)<'0')
|
|
# define sqlite3JsonId2(x) sqlite3IsIdChar(x)
|
|
#endif
|
|
SQLITE_PRIVATE int sqlite3IsIdChar(u8);
|
|
|
|
/*
|
|
** Internal function prototypes
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3StrICmp(const char*,const char*);
|
|
SQLITE_PRIVATE int sqlite3Strlen30(const char*);
|
|
#define sqlite3Strlen30NN(C) (strlen(C)&0x3fffffff)
|
|
SQLITE_PRIVATE char *sqlite3ColumnType(Column*,char*);
|
|
#define sqlite3StrNICmp sqlite3_strnicmp
|
|
|
|
SQLITE_PRIVATE int sqlite3MallocInit(void);
|
|
SQLITE_PRIVATE void sqlite3MallocEnd(void);
|
|
SQLITE_PRIVATE void *sqlite3Malloc(u64);
|
|
SQLITE_PRIVATE void *sqlite3MallocZero(u64);
|
|
SQLITE_PRIVATE void *sqlite3DbMallocZero(sqlite3*, u64);
|
|
SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3*, u64);
|
|
SQLITE_PRIVATE void *sqlite3DbMallocRawNN(sqlite3*, u64);
|
|
SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3*,const char*);
|
|
SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3*,const char*, u64);
|
|
SQLITE_PRIVATE char *sqlite3DbSpanDup(sqlite3*,const char*,const char*);
|
|
SQLITE_PRIVATE void *sqlite3Realloc(void*, u64);
|
|
SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *, void *, u64);
|
|
SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *, void *, u64);
|
|
SQLITE_PRIVATE void sqlite3DbFree(sqlite3*, void*);
|
|
SQLITE_PRIVATE void sqlite3DbFreeNN(sqlite3*, void*);
|
|
SQLITE_PRIVATE void sqlite3DbNNFreeNN(sqlite3*, void*);
|
|
SQLITE_PRIVATE int sqlite3MallocSize(const void*);
|
|
SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3*, const void*);
|
|
SQLITE_PRIVATE void *sqlite3PageMalloc(int);
|
|
SQLITE_PRIVATE void sqlite3PageFree(void*);
|
|
SQLITE_PRIVATE void sqlite3MemSetDefault(void);
|
|
#ifndef SQLITE_UNTESTABLE
|
|
SQLITE_PRIVATE void sqlite3BenignMallocHooks(void (*)(void), void (*)(void));
|
|
#endif
|
|
SQLITE_PRIVATE int sqlite3HeapNearlyFull(void);
|
|
|
|
/*
|
|
** On systems with ample stack space and that support alloca(), make
|
|
** use of alloca() to obtain space for large automatic objects. By default,
|
|
** obtain space from malloc().
|
|
**
|
|
** The alloca() routine never returns NULL. This will cause code paths
|
|
** that deal with sqlite3StackAlloc() failures to be unreachable.
|
|
*/
|
|
#ifdef SQLITE_USE_ALLOCA
|
|
# define sqlite3StackAllocRaw(D,N) alloca(N)
|
|
# define sqlite3StackAllocRawNN(D,N) alloca(N)
|
|
# define sqlite3StackFree(D,P)
|
|
# define sqlite3StackFreeNN(D,P)
|
|
#else
|
|
# define sqlite3StackAllocRaw(D,N) sqlite3DbMallocRaw(D,N)
|
|
# define sqlite3StackAllocRawNN(D,N) sqlite3DbMallocRawNN(D,N)
|
|
# define sqlite3StackFree(D,P) sqlite3DbFree(D,P)
|
|
# define sqlite3StackFreeNN(D,P) sqlite3DbFreeNN(D,P)
|
|
#endif
|
|
|
|
/* Do not allow both MEMSYS5 and MEMSYS3 to be defined together. If they
|
|
** are, disable MEMSYS3
|
|
*/
|
|
#ifdef SQLITE_ENABLE_MEMSYS5
|
|
SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys5(void);
|
|
#undef SQLITE_ENABLE_MEMSYS3
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_MEMSYS3
|
|
SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys3(void);
|
|
#endif
|
|
|
|
|
|
#ifndef SQLITE_MUTEX_OMIT
|
|
SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void);
|
|
SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3NoopMutex(void);
|
|
SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int);
|
|
SQLITE_PRIVATE int sqlite3MutexInit(void);
|
|
SQLITE_PRIVATE int sqlite3MutexEnd(void);
|
|
#endif
|
|
#if !defined(SQLITE_MUTEX_OMIT) && !defined(SQLITE_MUTEX_NOOP)
|
|
SQLITE_PRIVATE void sqlite3MemoryBarrier(void);
|
|
#else
|
|
# define sqlite3MemoryBarrier()
|
|
#endif
|
|
|
|
SQLITE_PRIVATE sqlite3_int64 sqlite3StatusValue(int);
|
|
SQLITE_PRIVATE void sqlite3StatusUp(int, int);
|
|
SQLITE_PRIVATE void sqlite3StatusDown(int, int);
|
|
SQLITE_PRIVATE void sqlite3StatusHighwater(int, int);
|
|
SQLITE_PRIVATE int sqlite3LookasideUsed(sqlite3*,int*);
|
|
|
|
/* Access to mutexes used by sqlite3_status() */
|
|
SQLITE_PRIVATE sqlite3_mutex *sqlite3Pcache1Mutex(void);
|
|
SQLITE_PRIVATE sqlite3_mutex *sqlite3MallocMutex(void);
|
|
|
|
#if defined(SQLITE_ENABLE_MULTITHREADED_CHECKS) && !defined(SQLITE_MUTEX_OMIT)
|
|
SQLITE_PRIVATE void sqlite3MutexWarnOnContention(sqlite3_mutex*);
|
|
#else
|
|
# define sqlite3MutexWarnOnContention(x)
|
|
#endif
|
|
|
|
#ifndef SQLITE_OMIT_FLOATING_POINT
|
|
# define EXP754 (((u64)0x7ff)<<52)
|
|
# define MAN754 ((((u64)1)<<52)-1)
|
|
# define IsNaN(X) (((X)&EXP754)==EXP754 && ((X)&MAN754)!=0)
|
|
# define IsOvfl(X) (((X)&EXP754)==EXP754)
|
|
SQLITE_PRIVATE int sqlite3IsNaN(double);
|
|
SQLITE_PRIVATE int sqlite3IsOverflow(double);
|
|
#else
|
|
# define IsNaN(X) 0
|
|
# define sqlite3IsNaN(X) 0
|
|
# define sqlite3IsOVerflow(X) 0
|
|
#endif
|
|
|
|
/*
|
|
** An instance of the following structure holds information about SQL
|
|
** functions arguments that are the parameters to the printf() function.
|
|
*/
|
|
struct PrintfArguments {
|
|
int nArg; /* Total number of arguments */
|
|
int nUsed; /* Number of arguments used so far */
|
|
sqlite3_value **apArg; /* The argument values */
|
|
};
|
|
|
|
/*
|
|
** An instance of this object receives the decoding of a floating point
|
|
** value into an approximate decimal representation.
|
|
*/
|
|
struct FpDecode {
|
|
char sign; /* '+' or '-' */
|
|
char isSpecial; /* 1: Infinity 2: NaN */
|
|
int n; /* Significant digits in the decode */
|
|
int iDP; /* Location of the decimal point */
|
|
char *z; /* Start of significant digits */
|
|
char zBuf[24]; /* Storage for significant digits */
|
|
};
|
|
|
|
SQLITE_PRIVATE void sqlite3FpDecode(FpDecode*,double,int,int);
|
|
SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3*,const char*, ...);
|
|
SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
|
|
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
|
|
SQLITE_PRIVATE void sqlite3DebugPrintf(const char*, ...);
|
|
#endif
|
|
#if defined(SQLITE_TEST)
|
|
SQLITE_PRIVATE void *sqlite3TestTextToPtr(const char*);
|
|
#endif
|
|
|
|
#if defined(SQLITE_DEBUG)
|
|
SQLITE_PRIVATE void sqlite3TreeViewLine(TreeView*, const char *zFormat, ...);
|
|
SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView*, const Expr*, u8);
|
|
SQLITE_PRIVATE void sqlite3TreeViewBareExprList(TreeView*, const ExprList*, const char*);
|
|
SQLITE_PRIVATE void sqlite3TreeViewExprList(TreeView*, const ExprList*, u8, const char*);
|
|
SQLITE_PRIVATE void sqlite3TreeViewBareIdList(TreeView*, const IdList*, const char*);
|
|
SQLITE_PRIVATE void sqlite3TreeViewIdList(TreeView*, const IdList*, u8, const char*);
|
|
SQLITE_PRIVATE void sqlite3TreeViewColumnList(TreeView*, const Column*, int, u8);
|
|
SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView*, const SrcList*);
|
|
SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView*, const Select*, u8);
|
|
SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView*, const With*, u8);
|
|
SQLITE_PRIVATE void sqlite3TreeViewUpsert(TreeView*, const Upsert*, u8);
|
|
#if TREETRACE_ENABLED
|
|
SQLITE_PRIVATE void sqlite3TreeViewDelete(const With*, const SrcList*, const Expr*,
|
|
const ExprList*,const Expr*, const Trigger*);
|
|
SQLITE_PRIVATE void sqlite3TreeViewInsert(const With*, const SrcList*,
|
|
const IdList*, const Select*, const ExprList*,
|
|
int, const Upsert*, const Trigger*);
|
|
SQLITE_PRIVATE void sqlite3TreeViewUpdate(const With*, const SrcList*, const ExprList*,
|
|
const Expr*, int, const ExprList*, const Expr*,
|
|
const Upsert*, const Trigger*);
|
|
#endif
|
|
#ifndef SQLITE_OMIT_TRIGGER
|
|
SQLITE_PRIVATE void sqlite3TreeViewTriggerStep(TreeView*, const TriggerStep*, u8, u8);
|
|
SQLITE_PRIVATE void sqlite3TreeViewTrigger(TreeView*, const Trigger*, u8, u8);
|
|
#endif
|
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView*, const Window*, u8);
|
|
SQLITE_PRIVATE void sqlite3TreeViewWinFunc(TreeView*, const Window*, u8);
|
|
#endif
|
|
SQLITE_PRIVATE void sqlite3ShowExpr(const Expr*);
|
|
SQLITE_PRIVATE void sqlite3ShowExprList(const ExprList*);
|
|
SQLITE_PRIVATE void sqlite3ShowIdList(const IdList*);
|
|
SQLITE_PRIVATE void sqlite3ShowSrcList(const SrcList*);
|
|
SQLITE_PRIVATE void sqlite3ShowSelect(const Select*);
|
|
SQLITE_PRIVATE void sqlite3ShowWith(const With*);
|
|
SQLITE_PRIVATE void sqlite3ShowUpsert(const Upsert*);
|
|
#ifndef SQLITE_OMIT_TRIGGER
|
|
SQLITE_PRIVATE void sqlite3ShowTriggerStep(const TriggerStep*);
|
|
SQLITE_PRIVATE void sqlite3ShowTriggerStepList(const TriggerStep*);
|
|
SQLITE_PRIVATE void sqlite3ShowTrigger(const Trigger*);
|
|
SQLITE_PRIVATE void sqlite3ShowTriggerList(const Trigger*);
|
|
#endif
|
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
SQLITE_PRIVATE void sqlite3ShowWindow(const Window*);
|
|
SQLITE_PRIVATE void sqlite3ShowWinFunc(const Window*);
|
|
#endif
|
|
#endif
|
|
|
|
SQLITE_PRIVATE void sqlite3SetString(char **, sqlite3*, const char*);
|
|
SQLITE_PRIVATE void sqlite3ProgressCheck(Parse*);
|
|
SQLITE_PRIVATE void sqlite3ErrorMsg(Parse*, const char*, ...);
|
|
SQLITE_PRIVATE int sqlite3ErrorToParser(sqlite3*,int);
|
|
SQLITE_PRIVATE void sqlite3Dequote(char*);
|
|
SQLITE_PRIVATE void sqlite3DequoteExpr(Expr*);
|
|
SQLITE_PRIVATE void sqlite3DequoteToken(Token*);
|
|
SQLITE_PRIVATE void sqlite3TokenInit(Token*,char*);
|
|
SQLITE_PRIVATE int sqlite3KeywordCode(const unsigned char*, int);
|
|
SQLITE_PRIVATE int sqlite3RunParser(Parse*, const char*);
|
|
SQLITE_PRIVATE void sqlite3FinishCoding(Parse*);
|
|
SQLITE_PRIVATE int sqlite3GetTempReg(Parse*);
|
|
SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse*,int);
|
|
SQLITE_PRIVATE int sqlite3GetTempRange(Parse*,int);
|
|
SQLITE_PRIVATE void sqlite3ReleaseTempRange(Parse*,int,int);
|
|
SQLITE_PRIVATE void sqlite3ClearTempRegCache(Parse*);
|
|
SQLITE_PRIVATE void sqlite3TouchRegister(Parse*,int);
|
|
#if defined(SQLITE_ENABLE_STAT4) || defined(SQLITE_DEBUG)
|
|
SQLITE_PRIVATE int sqlite3FirstAvailableRegister(Parse*,int);
|
|
#endif
|
|
#ifdef SQLITE_DEBUG
|
|
SQLITE_PRIVATE int sqlite3NoTempsInRange(Parse*,int,int);
|
|
#endif
|
|
SQLITE_PRIVATE Expr *sqlite3ExprAlloc(sqlite3*,int,const Token*,int);
|
|
SQLITE_PRIVATE Expr *sqlite3Expr(sqlite3*,int,const char*);
|
|
SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*);
|
|
SQLITE_PRIVATE Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*);
|
|
SQLITE_PRIVATE void sqlite3PExprAddSelect(Parse*, Expr*, Select*);
|
|
SQLITE_PRIVATE Expr *sqlite3ExprAnd(Parse*,Expr*, Expr*);
|
|
SQLITE_PRIVATE Expr *sqlite3ExprSimplifiedAndOr(Expr*);
|
|
SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, const Token*, int);
|
|
SQLITE_PRIVATE void sqlite3ExprAddFunctionOrderBy(Parse*,Expr*,ExprList*);
|
|
SQLITE_PRIVATE void sqlite3ExprOrderByAggregateError(Parse*,Expr*);
|
|
SQLITE_PRIVATE void sqlite3ExprFunctionUsable(Parse*,const Expr*,const FuncDef*);
|
|
SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
|
|
SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*);
|
|
SQLITE_PRIVATE void sqlite3ExprDeleteGeneric(sqlite3*,void*);
|
|
SQLITE_PRIVATE void sqlite3ExprDeferredDelete(Parse*, Expr*);
|
|
SQLITE_PRIVATE void sqlite3ExprUnmapAndDelete(Parse*, Expr*);
|
|
SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
|
|
SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
|
|
SQLITE_PRIVATE Select *sqlite3ExprListToValues(Parse*, int, ExprList*);
|
|
SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int,int);
|
|
SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,const Token*,int);
|
|
SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*);
|
|
SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*);
|
|
SQLITE_PRIVATE void sqlite3ExprListDeleteGeneric(sqlite3*,void*);
|
|
SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList*);
|
|
SQLITE_PRIVATE int sqlite3IndexHasDuplicateRootPage(Index*);
|
|
SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**);
|
|
SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**);
|
|
SQLITE_PRIVATE int sqlite3InitOne(sqlite3*, int, char**, u32);
|
|
SQLITE_PRIVATE void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
|
|
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
|
SQLITE_PRIVATE Module *sqlite3PragmaVtabRegister(sqlite3*,const char *zName);
|
|
#endif
|
|
SQLITE_PRIVATE void sqlite3ResetAllSchemasOfConnection(sqlite3*);
|
|
SQLITE_PRIVATE void sqlite3ResetOneSchema(sqlite3*,int);
|
|
SQLITE_PRIVATE void sqlite3CollapseDatabaseArray(sqlite3*);
|
|
SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*);
|
|
SQLITE_PRIVATE void sqlite3ColumnSetExpr(Parse*,Table*,Column*,Expr*);
|
|
SQLITE_PRIVATE Expr *sqlite3ColumnExpr(Table*,Column*);
|
|
SQLITE_PRIVATE void sqlite3ColumnSetColl(sqlite3*,Column*,const char*zColl);
|
|
SQLITE_PRIVATE const char *sqlite3ColumnColl(Column*);
|
|
SQLITE_PRIVATE void sqlite3DeleteColumnNames(sqlite3*,Table*);
|
|
SQLITE_PRIVATE void sqlite3GenerateColumnNames(Parse *pParse, Select *pSelect);
|
|
SQLITE_PRIVATE int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**);
|
|
SQLITE_PRIVATE void sqlite3SubqueryColumnTypes(Parse*,Table*,Select*,char);
|
|
SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*,char);
|
|
SQLITE_PRIVATE void sqlite3OpenSchemaTable(Parse *, int);
|
|
SQLITE_PRIVATE Index *sqlite3PrimaryKeyIndex(Table*);
|
|
SQLITE_PRIVATE i16 sqlite3TableColumnToIndex(Index*, i16);
|
|
#ifdef SQLITE_OMIT_GENERATED_COLUMNS
|
|
# define sqlite3TableColumnToStorage(T,X) (X) /* No-op pass-through */
|
|
# define sqlite3StorageColumnToTable(T,X) (X) /* No-op pass-through */
|
|
#else
|
|
SQLITE_PRIVATE i16 sqlite3TableColumnToStorage(Table*, i16);
|
|
SQLITE_PRIVATE i16 sqlite3StorageColumnToTable(Table*, i16);
|
|
#endif
|
|
SQLITE_PRIVATE void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int);
|
|
#if SQLITE_ENABLE_HIDDEN_COLUMNS
|
|
SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table*, Column*);
|
|
#else
|
|
# define sqlite3ColumnPropertiesFromName(T,C) /* no-op */
|
|
#endif
|
|
SQLITE_PRIVATE void sqlite3AddColumn(Parse*,Token,Token);
|
|
SQLITE_PRIVATE void sqlite3AddNotNull(Parse*, int);
|
|
SQLITE_PRIVATE void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int);
|
|
SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*, const char*, const char*);
|
|
SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,Expr*,const char*,const char*);
|
|
SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*);
|
|
SQLITE_PRIVATE void sqlite3AddGenerated(Parse*,Expr*,Token*);
|
|
SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,u32,Select*);
|
|
SQLITE_PRIVATE void sqlite3AddReturning(Parse*,ExprList*);
|
|
SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*,
|
|
sqlite3_vfs**,char**,char **);
|
|
#define sqlite3CodecQueryParameters(A,B,C) 0
|
|
SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3*,const char*);
|
|
|
|
#ifdef SQLITE_UNTESTABLE
|
|
# define sqlite3FaultSim(X) SQLITE_OK
|
|
#else
|
|
SQLITE_PRIVATE int sqlite3FaultSim(int);
|
|
#endif
|
|
|
|
SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32);
|
|
SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec*, u32);
|
|
SQLITE_PRIVATE int sqlite3BitvecTestNotNull(Bitvec*, u32);
|
|
SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec*, u32);
|
|
SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec*, u32, void*);
|
|
SQLITE_PRIVATE void sqlite3BitvecDestroy(Bitvec*);
|
|
SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec*);
|
|
#ifndef SQLITE_UNTESTABLE
|
|
SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int,int*);
|
|
#endif
|
|
|
|
SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3*);
|
|
SQLITE_PRIVATE void sqlite3RowSetDelete(void*);
|
|
SQLITE_PRIVATE void sqlite3RowSetClear(void*);
|
|
SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet*, i64);
|
|
SQLITE_PRIVATE int sqlite3RowSetTest(RowSet*, int iBatch, i64);
|
|
SQLITE_PRIVATE int sqlite3RowSetNext(RowSet*, i64*);
|
|
|
|
SQLITE_PRIVATE void sqlite3CreateView(Parse*,Token*,Token*,Token*,ExprList*,Select*,int,int);
|
|
|
|
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
|
|
SQLITE_PRIVATE int sqlite3ViewGetColumnNames(Parse*,Table*);
|
|
#else
|
|
# define sqlite3ViewGetColumnNames(A,B) 0
|
|
#endif
|
|
|
|
#if SQLITE_MAX_ATTACHED>30
|
|
SQLITE_PRIVATE int sqlite3DbMaskAllZero(yDbMask);
|
|
#endif
|
|
SQLITE_PRIVATE void sqlite3DropTable(Parse*, SrcList*, int, int);
|
|
SQLITE_PRIVATE void sqlite3CodeDropTable(Parse*, Table*, int, int);
|
|
SQLITE_PRIVATE void sqlite3DeleteTable(sqlite3*, Table*);
|
|
SQLITE_PRIVATE void sqlite3DeleteTableGeneric(sqlite3*, void*);
|
|
SQLITE_PRIVATE void sqlite3FreeIndex(sqlite3*, Index*);
|
|
#ifndef SQLITE_OMIT_AUTOINCREMENT
|
|
SQLITE_PRIVATE void sqlite3AutoincrementBegin(Parse *pParse);
|
|
SQLITE_PRIVATE void sqlite3AutoincrementEnd(Parse *pParse);
|
|
#else
|
|
# define sqlite3AutoincrementBegin(X)
|
|
# define sqlite3AutoincrementEnd(X)
|
|
#endif
|
|
SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int, Upsert*);
|
|
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
|
SQLITE_PRIVATE void sqlite3ComputeGeneratedColumns(Parse*, int, Table*);
|
|
#endif
|
|
SQLITE_PRIVATE void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*);
|
|
SQLITE_PRIVATE IdList *sqlite3IdListAppend(Parse*, IdList*, Token*);
|
|
SQLITE_PRIVATE int sqlite3IdListIndex(IdList*,const char*);
|
|
SQLITE_PRIVATE SrcList *sqlite3SrcListEnlarge(Parse*, SrcList*, int, int);
|
|
SQLITE_PRIVATE SrcList *sqlite3SrcListAppendList(Parse *pParse, SrcList *p1, SrcList *p2);
|
|
SQLITE_PRIVATE SrcList *sqlite3SrcListAppend(Parse*, SrcList*, Token*, Token*);
|
|
SQLITE_PRIVATE SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*,
|
|
Token*, Select*, OnOrUsing*);
|
|
SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *);
|
|
SQLITE_PRIVATE void sqlite3SrcListFuncArgs(Parse*, SrcList*, ExprList*);
|
|
SQLITE_PRIVATE int sqlite3IndexedByLookup(Parse *, SrcItem *);
|
|
SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(Parse*,SrcList*);
|
|
SQLITE_PRIVATE void sqlite3SrcListAssignCursors(Parse*, SrcList*);
|
|
SQLITE_PRIVATE void sqlite3IdListDelete(sqlite3*, IdList*);
|
|
SQLITE_PRIVATE void sqlite3ClearOnOrUsing(sqlite3*, OnOrUsing*);
|
|
SQLITE_PRIVATE void sqlite3SrcListDelete(sqlite3*, SrcList*);
|
|
SQLITE_PRIVATE Index *sqlite3AllocateIndexObject(sqlite3*,i16,int,char**);
|
|
SQLITE_PRIVATE void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
|
|
Expr*, int, int, u8);
|
|
SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int);
|
|
SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*);
|
|
SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
|
|
Expr*,ExprList*,u32,Expr*);
|
|
SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*);
|
|
SQLITE_PRIVATE void sqlite3SelectDeleteGeneric(sqlite3*,void*);
|
|
SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*);
|
|
SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, Trigger*);
|
|
SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
|
|
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
|
|
SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,char*);
|
|
#endif
|
|
SQLITE_PRIVATE void sqlite3CodeChangeCount(Vdbe*,int,const char*);
|
|
SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*, ExprList*, Expr*);
|
|
SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*,Expr*,int,ExprList*,Expr*,
|
|
Upsert*);
|
|
SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,
|
|
ExprList*,Select*,u16,int);
|
|
SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo*);
|
|
SQLITE_PRIVATE LogEst sqlite3WhereOutputRowCount(WhereInfo*);
|
|
SQLITE_PRIVATE int sqlite3WhereIsDistinct(WhereInfo*);
|
|
SQLITE_PRIVATE int sqlite3WhereIsOrdered(WhereInfo*);
|
|
SQLITE_PRIVATE int sqlite3WhereOrderByLimitOptLabel(WhereInfo*);
|
|
SQLITE_PRIVATE void sqlite3WhereMinMaxOptEarlyOut(Vdbe*,WhereInfo*);
|
|
SQLITE_PRIVATE int sqlite3WhereIsSorted(WhereInfo*);
|
|
SQLITE_PRIVATE int sqlite3WhereContinueLabel(WhereInfo*);
|
|
SQLITE_PRIVATE int sqlite3WhereBreakLabel(WhereInfo*);
|
|
SQLITE_PRIVATE int sqlite3WhereOkOnePass(WhereInfo*, int*);
|
|
#define ONEPASS_OFF 0 /* Use of ONEPASS not allowed */
|
|
#define ONEPASS_SINGLE 1 /* ONEPASS valid for a single row update */
|
|
#define ONEPASS_MULTI 2 /* ONEPASS is valid for multiple rows */
|
|
SQLITE_PRIVATE int sqlite3WhereUsesDeferredSeek(WhereInfo*);
|
|
SQLITE_PRIVATE void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int);
|
|
SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
|
|
SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
|
|
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
|
|
SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int);
|
|
#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
|
SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn(Parse*, Table*, Column*, int);
|
|
#endif
|
|
SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, Expr*, int);
|
|
SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse*, Expr*, int);
|
|
SQLITE_PRIVATE int sqlite3ExprCodeRunJustOnce(Parse*, Expr*, int);
|
|
SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
|
|
SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse*, Expr*, int);
|
|
SQLITE_PRIVATE int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int, u8);
|
|
#define SQLITE_ECEL_DUP 0x01 /* Deep, not shallow copies */
|
|
#define SQLITE_ECEL_FACTOR 0x02 /* Factor out constant terms */
|
|
#define SQLITE_ECEL_REF 0x04 /* Use ExprList.u.x.iOrderByCol */
|
|
#define SQLITE_ECEL_OMITREF 0x08 /* Omit if ExprList.u.x.iOrderByCol */
|
|
SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
|
|
SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
|
|
SQLITE_PRIVATE void sqlite3ExprIfFalseDup(Parse*, Expr*, int, int);
|
|
SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3*,const char*, const char*);
|
|
#define LOCATE_VIEW 0x01
|
|
#define LOCATE_NOERR 0x02
|
|
SQLITE_PRIVATE Table *sqlite3LocateTable(Parse*,u32 flags,const char*, const char*);
|
|
SQLITE_PRIVATE const char *sqlite3PreferredTableName(const char*);
|
|
SQLITE_PRIVATE Table *sqlite3LocateTableItem(Parse*,u32 flags,SrcItem *);
|
|
SQLITE_PRIVATE Index *sqlite3FindIndex(sqlite3*,const char*, const char*);
|
|
SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*);
|
|
SQLITE_PRIVATE void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*);
|
|
SQLITE_PRIVATE void sqlite3Vacuum(Parse*,Token*,Expr*);
|
|
SQLITE_PRIVATE int sqlite3RunVacuum(char**, sqlite3*, int, sqlite3_value*);
|
|
SQLITE_PRIVATE char *sqlite3NameFromToken(sqlite3*, const Token*);
|
|
SQLITE_PRIVATE int sqlite3ExprCompare(const Parse*,const Expr*,const Expr*, int);
|
|
SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr*,Expr*,int);
|
|
SQLITE_PRIVATE int sqlite3ExprListCompare(const ExprList*,const ExprList*, int);
|
|
SQLITE_PRIVATE int sqlite3ExprImpliesExpr(const Parse*,const Expr*,const Expr*, int);
|
|
SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr*,int,int);
|
|
SQLITE_PRIVATE void sqlite3AggInfoPersistWalkerInit(Walker*,Parse*);
|
|
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
|
|
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
|
|
SQLITE_PRIVATE int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx);
|
|
SQLITE_PRIVATE int sqlite3ReferencesSrcList(Parse*, Expr*, SrcList*);
|
|
SQLITE_PRIVATE Vdbe *sqlite3GetVdbe(Parse*);
|
|
#ifndef SQLITE_UNTESTABLE
|
|
SQLITE_PRIVATE void sqlite3PrngSaveState(void);
|
|
SQLITE_PRIVATE void sqlite3PrngRestoreState(void);
|
|
#endif
|
|
SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3*,int);
|
|
SQLITE_PRIVATE void sqlite3CodeVerifySchema(Parse*, int);
|
|
SQLITE_PRIVATE void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb);
|
|
SQLITE_PRIVATE void sqlite3BeginTransaction(Parse*, int);
|
|
SQLITE_PRIVATE void sqlite3EndTransaction(Parse*,int);
|
|
SQLITE_PRIVATE void sqlite3Savepoint(Parse*, int, Token*);
|
|
SQLITE_PRIVATE void sqlite3CloseSavepoints(sqlite3 *);
|
|
SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3*);
|
|
SQLITE_PRIVATE u32 sqlite3IsTrueOrFalse(const char*);
|
|
SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr*);
|
|
SQLITE_PRIVATE int sqlite3ExprTruthValue(const Expr*);
|
|
SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr*);
|
|
SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr*);
|
|
SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*, u8);
|
|
SQLITE_PRIVATE int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*);
|
|
SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr*,int);
|
|
SQLITE_PRIVATE int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int);
|
|
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
|
SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*);
|
|
#endif
|
|
SQLITE_PRIVATE int sqlite3ExprIsInteger(const Expr*, int*);
|
|
SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*);
|
|
SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
|
|
SQLITE_PRIVATE int sqlite3IsRowid(const char*);
|
|
SQLITE_PRIVATE const char *sqlite3RowidAlias(Table *pTab);
|
|
SQLITE_PRIVATE void sqlite3GenerateRowDelete(
|
|
Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int);
|
|
SQLITE_PRIVATE void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int);
|
|
SQLITE_PRIVATE int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int);
|
|
SQLITE_PRIVATE void sqlite3ResolvePartIdxLabel(Parse*,int);
|
|
SQLITE_PRIVATE int sqlite3ExprReferencesUpdatedColumn(Expr*,int*,int);
|
|
SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,
|
|
u8,u8,int,int*,int*,Upsert*);
|
|
#ifdef SQLITE_ENABLE_NULL_TRIM
|
|
SQLITE_PRIVATE void sqlite3SetMakeRecordP5(Vdbe*,Table*);
|
|
#else
|
|
# define sqlite3SetMakeRecordP5(A,B)
|
|
#endif
|
|
SQLITE_PRIVATE void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int);
|
|
SQLITE_PRIVATE int sqlite3OpenTableAndIndices(Parse*, Table*, int, u8, int, u8*, int*, int*);
|
|
SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse*, int, int);
|
|
SQLITE_PRIVATE void sqlite3MultiWrite(Parse*);
|
|
SQLITE_PRIVATE void sqlite3MayAbort(Parse*);
|
|
SQLITE_PRIVATE void sqlite3HaltConstraint(Parse*, int, int, char*, i8, u8);
|
|
SQLITE_PRIVATE void sqlite3UniqueConstraint(Parse*, int, Index*);
|
|
SQLITE_PRIVATE void sqlite3RowidConstraint(Parse*, int, Table*);
|
|
SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3*,const Expr*,int);
|
|
SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3*,const ExprList*,int);
|
|
SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,const SrcList*,int);
|
|
SQLITE_PRIVATE IdList *sqlite3IdListDup(sqlite3*,const IdList*);
|
|
SQLITE_PRIVATE Select *sqlite3SelectDup(sqlite3*,const Select*,int);
|
|
SQLITE_PRIVATE FuncDef *sqlite3FunctionSearch(int,const char*);
|
|
SQLITE_PRIVATE void sqlite3InsertBuiltinFuncs(FuncDef*,int);
|
|
SQLITE_PRIVATE FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8);
|
|
SQLITE_PRIVATE void sqlite3QuoteValue(StrAccum*,sqlite3_value*);
|
|
SQLITE_PRIVATE void sqlite3RegisterBuiltinFunctions(void);
|
|
SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void);
|
|
SQLITE_PRIVATE void sqlite3RegisterJsonFunctions(void);
|
|
SQLITE_PRIVATE void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3*);
|
|
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && !defined(SQLITE_OMIT_JSON)
|
|
SQLITE_PRIVATE int sqlite3JsonTableFunctions(sqlite3*);
|
|
#endif
|
|
SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3*);
|
|
SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3*);
|
|
SQLITE_PRIVATE void sqlite3ChangeCookie(Parse*, int);
|
|
SQLITE_PRIVATE With *sqlite3WithDup(sqlite3 *db, With *p);
|
|
|
|
#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
|
|
SQLITE_PRIVATE void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int);
|
|
#endif
|
|
|
|
#ifndef SQLITE_OMIT_TRIGGER
|
|
SQLITE_PRIVATE void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*,
|
|
Expr*,int, int);
|
|
SQLITE_PRIVATE void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*);
|
|
SQLITE_PRIVATE void sqlite3DropTrigger(Parse*, SrcList*, int);
|
|
SQLITE_PRIVATE void sqlite3DropTriggerPtr(Parse*, Trigger*);
|
|
SQLITE_PRIVATE Trigger *sqlite3TriggersExist(Parse *, Table*, int, ExprList*, int *pMask);
|
|
SQLITE_PRIVATE Trigger *sqlite3TriggerList(Parse *, Table *);
|
|
SQLITE_PRIVATE void sqlite3CodeRowTrigger(Parse*, Trigger *, int, ExprList*, int, Table *,
|
|
int, int, int);
|
|
SQLITE_PRIVATE void sqlite3CodeRowTriggerDirect(Parse *, Trigger *, Table *, int, int, int);
|
|
void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*);
|
|
SQLITE_PRIVATE void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*);
|
|
SQLITE_PRIVATE TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*,
|
|
const char*,const char*);
|
|
SQLITE_PRIVATE TriggerStep *sqlite3TriggerInsertStep(Parse*,Token*, IdList*,
|
|
Select*,u8,Upsert*,
|
|
const char*,const char*);
|
|
SQLITE_PRIVATE TriggerStep *sqlite3TriggerUpdateStep(Parse*,Token*,SrcList*,ExprList*,
|
|
Expr*, u8, const char*,const char*);
|
|
SQLITE_PRIVATE TriggerStep *sqlite3TriggerDeleteStep(Parse*,Token*, Expr*,
|
|
const char*,const char*);
|
|
SQLITE_PRIVATE void sqlite3DeleteTrigger(sqlite3*, Trigger*);
|
|
SQLITE_PRIVATE void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
|
|
SQLITE_PRIVATE u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int);
|
|
SQLITE_PRIVATE SrcList *sqlite3TriggerStepSrc(Parse*, TriggerStep*);
|
|
# define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p))
|
|
# define sqlite3IsToplevel(p) ((p)->pToplevel==0)
|
|
#else
|
|
# define sqlite3TriggersExist(B,C,D,E,F) 0
|
|
# define sqlite3DeleteTrigger(A,B)
|
|
# define sqlite3DropTriggerPtr(A,B)
|
|
# define sqlite3UnlinkAndDeleteTrigger(A,B,C)
|
|
# define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I)
|
|
# define sqlite3CodeRowTriggerDirect(A,B,C,D,E,F)
|
|
# define sqlite3TriggerList(X, Y) 0
|
|
# define sqlite3ParseToplevel(p) p
|
|
# define sqlite3IsToplevel(p) 1
|
|
# define sqlite3TriggerColmask(A,B,C,D,E,F,G) 0
|
|
# define sqlite3TriggerStepSrc(A,B) 0
|
|
#endif
|
|
|
|
SQLITE_PRIVATE int sqlite3JoinType(Parse*, Token*, Token*, Token*);
|
|
SQLITE_PRIVATE int sqlite3ColumnIndex(Table *pTab, const char *zCol);
|
|
SQLITE_PRIVATE void sqlite3SrcItemColumnUsed(SrcItem*,int);
|
|
SQLITE_PRIVATE void sqlite3SetJoinExpr(Expr*,int,u32);
|
|
SQLITE_PRIVATE void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int);
|
|
SQLITE_PRIVATE void sqlite3DeferForeignKey(Parse*, int);
|
|
#ifndef SQLITE_OMIT_AUTHORIZATION
|
|
SQLITE_PRIVATE void sqlite3AuthRead(Parse*,Expr*,Schema*,SrcList*);
|
|
SQLITE_PRIVATE int sqlite3AuthCheck(Parse*,int, const char*, const char*, const char*);
|
|
SQLITE_PRIVATE void sqlite3AuthContextPush(Parse*, AuthContext*, const char*);
|
|
SQLITE_PRIVATE void sqlite3AuthContextPop(AuthContext*);
|
|
SQLITE_PRIVATE int sqlite3AuthReadCol(Parse*, const char *, const char *, int);
|
|
#else
|
|
# define sqlite3AuthRead(a,b,c,d)
|
|
# define sqlite3AuthCheck(a,b,c,d,e) SQLITE_OK
|
|
# define sqlite3AuthContextPush(a,b,c)
|
|
# define sqlite3AuthContextPop(a) ((void)(a))
|
|
#endif
|
|
SQLITE_PRIVATE int sqlite3DbIsNamed(sqlite3 *db, int iDb, const char *zName);
|
|
SQLITE_PRIVATE void sqlite3Attach(Parse*, Expr*, Expr*, Expr*);
|
|
SQLITE_PRIVATE void sqlite3Detach(Parse*, Expr*);
|
|
SQLITE_PRIVATE void sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*);
|
|
SQLITE_PRIVATE int sqlite3FixSrcList(DbFixer*, SrcList*);
|
|
SQLITE_PRIVATE int sqlite3FixSelect(DbFixer*, Select*);
|
|
SQLITE_PRIVATE int sqlite3FixExpr(DbFixer*, Expr*);
|
|
SQLITE_PRIVATE int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
|
|
|
|
SQLITE_PRIVATE int sqlite3RealSameAsInt(double,sqlite3_int64);
|
|
SQLITE_PRIVATE i64 sqlite3RealToI64(double);
|
|
SQLITE_PRIVATE int sqlite3Int64ToText(i64,char*);
|
|
SQLITE_PRIVATE int sqlite3AtoF(const char *z, double*, int, u8);
|
|
SQLITE_PRIVATE int sqlite3GetInt32(const char *, int*);
|
|
SQLITE_PRIVATE int sqlite3GetUInt32(const char*, u32*);
|
|
SQLITE_PRIVATE int sqlite3Atoi(const char*);
|
|
#ifndef SQLITE_OMIT_UTF16
|
|
SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *pData, int nChar);
|
|
#endif
|
|
SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *pData, int nByte);
|
|
SQLITE_PRIVATE u32 sqlite3Utf8Read(const u8**);
|
|
SQLITE_PRIVATE int sqlite3Utf8ReadLimited(const u8*, int, u32*);
|
|
SQLITE_PRIVATE LogEst sqlite3LogEst(u64);
|
|
SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst,LogEst);
|
|
SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double);
|
|
SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst);
|
|
SQLITE_PRIVATE VList *sqlite3VListAdd(sqlite3*,VList*,const char*,int,int);
|
|
SQLITE_PRIVATE const char *sqlite3VListNumToName(VList*,int);
|
|
SQLITE_PRIVATE int sqlite3VListNameToNum(VList*,const char*,int);
|
|
|
|
/*
|
|
** 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.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3PutVarint(unsigned char*, u64);
|
|
SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *, u64 *);
|
|
SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *, u32 *);
|
|
SQLITE_PRIVATE int sqlite3VarintLen(u64 v);
|
|
|
|
/*
|
|
** The common case is for a varint to be a single byte. They following
|
|
** macros handle the common case without a procedure call, but then call
|
|
** the procedure for larger varints.
|
|
*/
|
|
#define getVarint32(A,B) \
|
|
(u8)((*(A)<(u8)0x80)?((B)=(u32)*(A)),1:sqlite3GetVarint32((A),(u32 *)&(B)))
|
|
#define getVarint32NR(A,B) \
|
|
B=(u32)*(A);if(B>=0x80)sqlite3GetVarint32((A),(u32*)&(B))
|
|
#define putVarint32(A,B) \
|
|
(u8)(((u32)(B)<(u32)0x80)?(*(A)=(unsigned char)(B)),1:\
|
|
sqlite3PutVarint((A),(B)))
|
|
#define getVarint sqlite3GetVarint
|
|
#define putVarint sqlite3PutVarint
|
|
|
|
|
|
SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(sqlite3*, Index*);
|
|
SQLITE_PRIVATE char *sqlite3TableAffinityStr(sqlite3*,const Table*);
|
|
SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe*, Table*, int);
|
|
SQLITE_PRIVATE char sqlite3CompareAffinity(const Expr *pExpr, char aff2);
|
|
SQLITE_PRIVATE int sqlite3IndexAffinityOk(const Expr *pExpr, char idx_affinity);
|
|
SQLITE_PRIVATE char sqlite3TableColumnAffinity(const Table*,int);
|
|
SQLITE_PRIVATE char sqlite3ExprAffinity(const Expr *pExpr);
|
|
SQLITE_PRIVATE int sqlite3ExprDataType(const Expr *pExpr);
|
|
SQLITE_PRIVATE int sqlite3Atoi64(const char*, i64*, int, u8);
|
|
SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char*, i64*);
|
|
SQLITE_PRIVATE void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...);
|
|
SQLITE_PRIVATE void sqlite3Error(sqlite3*,int);
|
|
SQLITE_PRIVATE void sqlite3ErrorClear(sqlite3*);
|
|
SQLITE_PRIVATE void sqlite3SystemError(sqlite3*,int);
|
|
SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
|
|
SQLITE_PRIVATE u8 sqlite3HexToInt(int h);
|
|
SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
|
|
|
|
#if defined(SQLITE_NEED_ERR_NAME)
|
|
SQLITE_PRIVATE const char *sqlite3ErrName(int);
|
|
#endif
|
|
|
|
#ifndef SQLITE_OMIT_DESERIALIZE
|
|
SQLITE_PRIVATE int sqlite3MemdbInit(void);
|
|
SQLITE_PRIVATE int sqlite3IsMemdb(const sqlite3_vfs*);
|
|
#else
|
|
# define sqlite3IsMemdb(X) 0
|
|
#endif
|
|
|
|
SQLITE_PRIVATE const char *sqlite3ErrStr(int);
|
|
SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse);
|
|
SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
|
|
SQLITE_PRIVATE int sqlite3IsBinary(const CollSeq*);
|
|
SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
|
|
SQLITE_PRIVATE void sqlite3SetTextEncoding(sqlite3 *db, u8);
|
|
SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr);
|
|
SQLITE_PRIVATE CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, const Expr *pExpr);
|
|
SQLITE_PRIVATE int sqlite3ExprCollSeqMatch(Parse*,const Expr*,const Expr*);
|
|
SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(const Parse *pParse, Expr*, const Token*, int);
|
|
SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(const Parse*,Expr*,const char*);
|
|
SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*);
|
|
SQLITE_PRIVATE Expr *sqlite3ExprSkipCollateAndLikely(Expr*);
|
|
SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *);
|
|
SQLITE_PRIVATE int sqlite3WritableSchema(sqlite3*);
|
|
SQLITE_PRIVATE int sqlite3CheckObjectName(Parse*, const char*,const char*,const char*);
|
|
SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, i64);
|
|
SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64);
|
|
SQLITE_PRIVATE int sqlite3SubInt64(i64*,i64);
|
|
SQLITE_PRIVATE int sqlite3MulInt64(i64*,i64);
|
|
SQLITE_PRIVATE int sqlite3AbsInt32(int);
|
|
#ifdef SQLITE_ENABLE_8_3_NAMES
|
|
SQLITE_PRIVATE void sqlite3FileSuffix3(const char*, char*);
|
|
#else
|
|
# define sqlite3FileSuffix3(X,Y)
|
|
#endif
|
|
SQLITE_PRIVATE u8 sqlite3GetBoolean(const char *z,u8);
|
|
|
|
SQLITE_PRIVATE const void *sqlite3ValueText(sqlite3_value*, u8);
|
|
SQLITE_PRIVATE int sqlite3ValueIsOfClass(const sqlite3_value*, void(*)(void*));
|
|
SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value*, u8);
|
|
SQLITE_PRIVATE void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8,
|
|
void(*)(void*));
|
|
SQLITE_PRIVATE void sqlite3ValueSetNull(sqlite3_value*);
|
|
SQLITE_PRIVATE void sqlite3ValueFree(sqlite3_value*);
|
|
#ifndef SQLITE_UNTESTABLE
|
|
SQLITE_PRIVATE void sqlite3ResultIntReal(sqlite3_context*);
|
|
#endif
|
|
SQLITE_PRIVATE sqlite3_value *sqlite3ValueNew(sqlite3 *);
|
|
#ifndef SQLITE_OMIT_UTF16
|
|
SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8);
|
|
#endif
|
|
SQLITE_PRIVATE int sqlite3ValueFromExpr(sqlite3 *, const Expr *, u8, u8, sqlite3_value **);
|
|
SQLITE_PRIVATE void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
|
|
#ifndef SQLITE_AMALGAMATION
|
|
SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[];
|
|
SQLITE_PRIVATE const char sqlite3StrBINARY[];
|
|
SQLITE_PRIVATE const unsigned char sqlite3StdTypeLen[];
|
|
SQLITE_PRIVATE const char sqlite3StdTypeAffinity[];
|
|
SQLITE_PRIVATE const char *sqlite3StdType[];
|
|
SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[];
|
|
SQLITE_PRIVATE const unsigned char *sqlite3aLTb;
|
|
SQLITE_PRIVATE const unsigned char *sqlite3aEQb;
|
|
SQLITE_PRIVATE const unsigned char *sqlite3aGTb;
|
|
SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[];
|
|
SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config;
|
|
SQLITE_PRIVATE FuncDefHash sqlite3BuiltinFunctions;
|
|
#ifndef SQLITE_OMIT_WSD
|
|
SQLITE_PRIVATE int sqlite3PendingByte;
|
|
#endif
|
|
#endif /* SQLITE_AMALGAMATION */
|
|
#ifdef VDBE_PROFILE
|
|
SQLITE_PRIVATE sqlite3_uint64 sqlite3NProfileCnt;
|
|
#endif
|
|
SQLITE_PRIVATE void sqlite3RootPageMoved(sqlite3*, int, Pgno, Pgno);
|
|
SQLITE_PRIVATE void sqlite3Reindex(Parse*, Token*, Token*);
|
|
SQLITE_PRIVATE void sqlite3AlterFunctions(void);
|
|
SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
|
|
SQLITE_PRIVATE void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*);
|
|
SQLITE_PRIVATE int sqlite3GetToken(const unsigned char *, int *);
|
|
SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...);
|
|
SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*, int);
|
|
SQLITE_PRIVATE void sqlite3CodeRhsOfIN(Parse*, Expr*, int);
|
|
SQLITE_PRIVATE int sqlite3CodeSubselect(Parse*, Expr*);
|
|
SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*);
|
|
SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse*, SrcItem*);
|
|
SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p);
|
|
SQLITE_PRIVATE int sqlite3MatchEName(
|
|
const struct ExprList_item*,
|
|
const char*,
|
|
const char*,
|
|
const char*,
|
|
int*
|
|
);
|
|
SQLITE_PRIVATE Bitmask sqlite3ExprColUsed(Expr*);
|
|
SQLITE_PRIVATE u8 sqlite3StrIHash(const char*);
|
|
SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*);
|
|
SQLITE_PRIVATE int sqlite3ResolveExprListNames(NameContext*, ExprList*);
|
|
SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
|
|
SQLITE_PRIVATE int sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*);
|
|
SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
|
|
SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
|
|
SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *, Token *);
|
|
SQLITE_PRIVATE void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
|
|
SQLITE_PRIVATE void sqlite3AlterDropColumn(Parse*, SrcList*, const Token*);
|
|
SQLITE_PRIVATE const void *sqlite3RenameTokenMap(Parse*, const void*, const Token*);
|
|
SQLITE_PRIVATE void sqlite3RenameTokenRemap(Parse*, const void *pTo, const void *pFrom);
|
|
SQLITE_PRIVATE void sqlite3RenameExprUnmap(Parse*, Expr*);
|
|
SQLITE_PRIVATE void sqlite3RenameExprlistUnmap(Parse*, ExprList*);
|
|
SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
|
|
SQLITE_PRIVATE char sqlite3AffinityType(const char*, Column*);
|
|
SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*);
|
|
SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*);
|
|
SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*);
|
|
SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *, const char *);
|
|
SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB);
|
|
SQLITE_PRIVATE void sqlite3DeleteIndexSamples(sqlite3*,Index*);
|
|
SQLITE_PRIVATE void sqlite3DefaultRowEst(Index*);
|
|
SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3*, int);
|
|
SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*);
|
|
SQLITE_PRIVATE void sqlite3SchemaClear(void *);
|
|
SQLITE_PRIVATE Schema *sqlite3SchemaGet(sqlite3 *, Btree *);
|
|
SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *);
|
|
SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoAlloc(sqlite3*,int,int);
|
|
SQLITE_PRIVATE void sqlite3KeyInfoUnref(KeyInfo*);
|
|
SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoRef(KeyInfo*);
|
|
SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse*, Index*);
|
|
SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoFromExprList(Parse*, ExprList*, int, int);
|
|
SQLITE_PRIVATE const char *sqlite3SelectOpName(int);
|
|
SQLITE_PRIVATE int sqlite3HasExplicitNulls(Parse*, ExprList*);
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
SQLITE_PRIVATE int sqlite3KeyInfoIsWriteable(KeyInfo*);
|
|
#endif
|
|
SQLITE_PRIVATE int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *,
|
|
void (*)(sqlite3_context*,int,sqlite3_value **),
|
|
void (*)(sqlite3_context*,int,sqlite3_value **),
|
|
void (*)(sqlite3_context*),
|
|
void (*)(sqlite3_context*),
|
|
void (*)(sqlite3_context*,int,sqlite3_value **),
|
|
FuncDestructor *pDestructor
|
|
);
|
|
SQLITE_PRIVATE void sqlite3NoopDestructor(void*);
|
|
SQLITE_PRIVATE void *sqlite3OomFault(sqlite3*);
|
|
SQLITE_PRIVATE void sqlite3OomClear(sqlite3*);
|
|
SQLITE_PRIVATE int sqlite3ApiExit(sqlite3 *db, int);
|
|
SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *);
|
|
|
|
SQLITE_PRIVATE char *sqlite3RCStrRef(char*);
|
|
SQLITE_PRIVATE void sqlite3RCStrUnref(void*);
|
|
SQLITE_PRIVATE char *sqlite3RCStrNew(u64);
|
|
SQLITE_PRIVATE char *sqlite3RCStrResize(char*,u64);
|
|
|
|
SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int);
|
|
SQLITE_PRIVATE int sqlite3StrAccumEnlarge(StrAccum*, i64);
|
|
SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum*);
|
|
SQLITE_PRIVATE void sqlite3StrAccumSetError(StrAccum*, u8);
|
|
SQLITE_PRIVATE void sqlite3ResultStrAccum(sqlite3_context*,StrAccum*);
|
|
SQLITE_PRIVATE void sqlite3SelectDestInit(SelectDest*,int,int);
|
|
SQLITE_PRIVATE Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int);
|
|
SQLITE_PRIVATE void sqlite3RecordErrorByteOffset(sqlite3*,const char*);
|
|
SQLITE_PRIVATE void sqlite3RecordErrorOffsetOfExpr(sqlite3*,const Expr*);
|
|
|
|
SQLITE_PRIVATE void sqlite3BackupRestart(sqlite3_backup *);
|
|
SQLITE_PRIVATE void sqlite3BackupUpdate(sqlite3_backup *, Pgno, const u8 *);
|
|
|
|
#ifndef SQLITE_OMIT_SUBQUERY
|
|
SQLITE_PRIVATE int sqlite3ExprCheckIN(Parse*, Expr*);
|
|
#else
|
|
# define sqlite3ExprCheckIN(x,y) SQLITE_OK
|
|
#endif
|
|
|
|
#ifdef SQLITE_ENABLE_STAT4
|
|
SQLITE_PRIVATE int sqlite3Stat4ProbeSetValue(
|
|
Parse*,Index*,UnpackedRecord**,Expr*,int,int,int*);
|
|
SQLITE_PRIVATE int sqlite3Stat4ValueFromExpr(Parse*, Expr*, u8, sqlite3_value**);
|
|
SQLITE_PRIVATE void sqlite3Stat4ProbeFree(UnpackedRecord*);
|
|
SQLITE_PRIVATE int sqlite3Stat4Column(sqlite3*, const void*, int, int, sqlite3_value**);
|
|
SQLITE_PRIVATE char sqlite3IndexColumnAffinity(sqlite3*, Index*, int);
|
|
#endif
|
|
|
|
/*
|
|
** The interface to the LEMON-generated parser
|
|
*/
|
|
#ifndef SQLITE_AMALGAMATION
|
|
SQLITE_PRIVATE void *sqlite3ParserAlloc(void*(*)(u64), Parse*);
|
|
SQLITE_PRIVATE void sqlite3ParserFree(void*, void(*)(void*));
|
|
#endif
|
|
SQLITE_PRIVATE void sqlite3Parser(void*, int, Token);
|
|
SQLITE_PRIVATE int sqlite3ParserFallback(int);
|
|
#ifdef YYTRACKMAXSTACKDEPTH
|
|
SQLITE_PRIVATE int sqlite3ParserStackPeak(void*);
|
|
#endif
|
|
|
|
SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3*);
|
|
#ifndef SQLITE_OMIT_LOAD_EXTENSION
|
|
SQLITE_PRIVATE void sqlite3CloseExtensions(sqlite3*);
|
|
#else
|
|
# define sqlite3CloseExtensions(X)
|
|
#endif
|
|
|
|
#ifndef SQLITE_OMIT_SHARED_CACHE
|
|
SQLITE_PRIVATE void sqlite3TableLock(Parse *, int, Pgno, u8, const char *);
|
|
#else
|
|
#define sqlite3TableLock(v,w,x,y,z)
|
|
#endif
|
|
|
|
#ifdef SQLITE_TEST
|
|
SQLITE_PRIVATE int sqlite3Utf8To8(unsigned char*);
|
|
#endif
|
|
|
|
#ifdef SQLITE_OMIT_VIRTUALTABLE
|
|
# define sqlite3VtabClear(D,T)
|
|
# define sqlite3VtabSync(X,Y) SQLITE_OK
|
|
# define sqlite3VtabRollback(X)
|
|
# define sqlite3VtabCommit(X)
|
|
# define sqlite3VtabInSync(db) 0
|
|
# define sqlite3VtabLock(X)
|
|
# define sqlite3VtabUnlock(X)
|
|
# define sqlite3VtabModuleUnref(D,X)
|
|
# define sqlite3VtabUnlockList(X)
|
|
# define sqlite3VtabSavepoint(X, Y, Z) SQLITE_OK
|
|
# define sqlite3GetVTable(X,Y) ((VTable*)0)
|
|
#else
|
|
SQLITE_PRIVATE void sqlite3VtabClear(sqlite3 *db, Table*);
|
|
SQLITE_PRIVATE void sqlite3VtabDisconnect(sqlite3 *db, Table *p);
|
|
SQLITE_PRIVATE int sqlite3VtabSync(sqlite3 *db, Vdbe*);
|
|
SQLITE_PRIVATE int sqlite3VtabRollback(sqlite3 *db);
|
|
SQLITE_PRIVATE int sqlite3VtabCommit(sqlite3 *db);
|
|
SQLITE_PRIVATE void sqlite3VtabLock(VTable *);
|
|
SQLITE_PRIVATE void sqlite3VtabUnlock(VTable *);
|
|
SQLITE_PRIVATE void sqlite3VtabModuleUnref(sqlite3*,Module*);
|
|
SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3*);
|
|
SQLITE_PRIVATE int sqlite3VtabSavepoint(sqlite3 *, int, int);
|
|
SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*);
|
|
SQLITE_PRIVATE VTable *sqlite3GetVTable(sqlite3*, Table*);
|
|
SQLITE_PRIVATE Module *sqlite3VtabCreateModule(
|
|
sqlite3*,
|
|
const char*,
|
|
const sqlite3_module*,
|
|
void*,
|
|
void(*)(void*)
|
|
);
|
|
# define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
|
|
#endif
|
|
SQLITE_PRIVATE int sqlite3ReadOnlyShadowTables(sqlite3 *db);
|
|
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
|
SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName);
|
|
SQLITE_PRIVATE int sqlite3IsShadowTableOf(sqlite3*,Table*,const char*);
|
|
SQLITE_PRIVATE void sqlite3MarkAllShadowTablesOf(sqlite3*, Table*);
|
|
#else
|
|
# define sqlite3ShadowTableName(A,B) 0
|
|
# define sqlite3IsShadowTableOf(A,B,C) 0
|
|
# define sqlite3MarkAllShadowTablesOf(A,B)
|
|
#endif
|
|
SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse*,Module*);
|
|
SQLITE_PRIVATE void sqlite3VtabEponymousTableClear(sqlite3*,Module*);
|
|
SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*);
|
|
SQLITE_PRIVATE void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*, int);
|
|
SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse*, Token*);
|
|
SQLITE_PRIVATE void sqlite3VtabArgInit(Parse*);
|
|
SQLITE_PRIVATE void sqlite3VtabArgExtend(Parse*, Token*);
|
|
SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **);
|
|
SQLITE_PRIVATE int sqlite3VtabCallConnect(Parse*, Table*);
|
|
SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3*, int, const char *);
|
|
SQLITE_PRIVATE int sqlite3VtabBegin(sqlite3 *, VTable *);
|
|
|
|
SQLITE_PRIVATE FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
|
|
SQLITE_PRIVATE void sqlite3VtabUsesAllSchemas(Parse*);
|
|
SQLITE_PRIVATE sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*);
|
|
SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
|
|
SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
|
|
SQLITE_PRIVATE void sqlite3ParseObjectInit(Parse*,sqlite3*);
|
|
SQLITE_PRIVATE void sqlite3ParseObjectReset(Parse*);
|
|
SQLITE_PRIVATE void *sqlite3ParserAddCleanup(Parse*,void(*)(sqlite3*,void*),void*);
|
|
#ifdef SQLITE_ENABLE_NORMALIZE
|
|
SQLITE_PRIVATE char *sqlite3Normalize(Vdbe*, const char*);
|
|
#endif
|
|
SQLITE_PRIVATE int sqlite3Reprepare(Vdbe*);
|
|
SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
|
|
SQLITE_PRIVATE CollSeq *sqlite3ExprCompareCollSeq(Parse*,const Expr*);
|
|
SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, const Expr*, const Expr*);
|
|
SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3*);
|
|
SQLITE_PRIVATE const char *sqlite3JournalModename(int);
|
|
#ifndef SQLITE_OMIT_WAL
|
|
SQLITE_PRIVATE int sqlite3Checkpoint(sqlite3*, int, int, int*, int*);
|
|
SQLITE_PRIVATE int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int);
|
|
#endif
|
|
#ifndef SQLITE_OMIT_CTE
|
|
SQLITE_PRIVATE Cte *sqlite3CteNew(Parse*,Token*,ExprList*,Select*,u8);
|
|
SQLITE_PRIVATE void sqlite3CteDelete(sqlite3*,Cte*);
|
|
SQLITE_PRIVATE With *sqlite3WithAdd(Parse*,With*,Cte*);
|
|
SQLITE_PRIVATE void sqlite3WithDelete(sqlite3*,With*);
|
|
SQLITE_PRIVATE void sqlite3WithDeleteGeneric(sqlite3*,void*);
|
|
SQLITE_PRIVATE With *sqlite3WithPush(Parse*, With*, u8);
|
|
#else
|
|
# define sqlite3CteNew(P,T,E,S) ((void*)0)
|
|
# define sqlite3CteDelete(D,C)
|
|
# define sqlite3CteWithAdd(P,W,C) ((void*)0)
|
|
# define sqlite3WithDelete(x,y)
|
|
# define sqlite3WithPush(x,y,z) ((void*)0)
|
|
#endif
|
|
#ifndef SQLITE_OMIT_UPSERT
|
|
SQLITE_PRIVATE Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*,Upsert*);
|
|
SQLITE_PRIVATE void sqlite3UpsertDelete(sqlite3*,Upsert*);
|
|
SQLITE_PRIVATE Upsert *sqlite3UpsertDup(sqlite3*,Upsert*);
|
|
SQLITE_PRIVATE int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*,Upsert*);
|
|
SQLITE_PRIVATE void sqlite3UpsertDoUpdate(Parse*,Upsert*,Table*,Index*,int);
|
|
SQLITE_PRIVATE Upsert *sqlite3UpsertOfIndex(Upsert*,Index*);
|
|
SQLITE_PRIVATE int sqlite3UpsertNextIsIPK(Upsert*);
|
|
#else
|
|
#define sqlite3UpsertNew(u,v,w,x,y,z) ((Upsert*)0)
|
|
#define sqlite3UpsertDelete(x,y)
|
|
#define sqlite3UpsertDup(x,y) ((Upsert*)0)
|
|
#define sqlite3UpsertOfIndex(x,y) ((Upsert*)0)
|
|
#define sqlite3UpsertNextIsIPK(x) 0
|
|
#endif
|
|
|
|
|
|
/* Declarations for functions in fkey.c. All of these are replaced by
|
|
** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign
|
|
** key functionality is available. If OMIT_TRIGGER is defined but
|
|
** OMIT_FOREIGN_KEY is not, only some of the functions are no-oped. In
|
|
** this case foreign keys are parsed, but no other functionality is
|
|
** provided (enforcement of FK constraints requires the triggers sub-system).
|
|
*/
|
|
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
|
|
SQLITE_PRIVATE void sqlite3FkCheck(Parse*, Table*, int, int, int*, int);
|
|
SQLITE_PRIVATE void sqlite3FkDropTable(Parse*, SrcList *, Table*);
|
|
SQLITE_PRIVATE void sqlite3FkActions(Parse*, Table*, ExprList*, int, int*, int);
|
|
SQLITE_PRIVATE int sqlite3FkRequired(Parse*, Table*, int*, int);
|
|
SQLITE_PRIVATE u32 sqlite3FkOldmask(Parse*, Table*);
|
|
SQLITE_PRIVATE FKey *sqlite3FkReferences(Table *);
|
|
SQLITE_PRIVATE void sqlite3FkClearTriggerCache(sqlite3*,int);
|
|
#else
|
|
#define sqlite3FkActions(a,b,c,d,e,f)
|
|
#define sqlite3FkCheck(a,b,c,d,e,f)
|
|
#define sqlite3FkDropTable(a,b,c)
|
|
#define sqlite3FkOldmask(a,b) 0
|
|
#define sqlite3FkRequired(a,b,c,d) 0
|
|
#define sqlite3FkReferences(a) 0
|
|
#define sqlite3FkClearTriggerCache(a,b)
|
|
#endif
|
|
#ifndef SQLITE_OMIT_FOREIGN_KEY
|
|
SQLITE_PRIVATE void sqlite3FkDelete(sqlite3 *, Table*);
|
|
SQLITE_PRIVATE int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**);
|
|
#else
|
|
#define sqlite3FkDelete(a,b)
|
|
#define sqlite3FkLocateIndex(a,b,c,d,e)
|
|
#endif
|
|
|
|
|
|
/*
|
|
** Available fault injectors. Should be numbered beginning with 0.
|
|
*/
|
|
#define SQLITE_FAULTINJECTOR_MALLOC 0
|
|
#define SQLITE_FAULTINJECTOR_COUNT 1
|
|
|
|
/*
|
|
** The interface to the code in fault.c used for identifying "benign"
|
|
** malloc failures. This is only present if SQLITE_UNTESTABLE
|
|
** is not defined.
|
|
*/
|
|
#ifndef SQLITE_UNTESTABLE
|
|
SQLITE_PRIVATE void sqlite3BeginBenignMalloc(void);
|
|
SQLITE_PRIVATE void sqlite3EndBenignMalloc(void);
|
|
#else
|
|
#define sqlite3BeginBenignMalloc()
|
|
#define sqlite3EndBenignMalloc()
|
|
#endif
|
|
|
|
/*
|
|
** Allowed return values from sqlite3FindInIndex()
|
|
*/
|
|
#define IN_INDEX_ROWID 1 /* Search the rowid of the table */
|
|
#define IN_INDEX_EPH 2 /* Search an ephemeral b-tree */
|
|
#define IN_INDEX_INDEX_ASC 3 /* Existing index ASCENDING */
|
|
#define IN_INDEX_INDEX_DESC 4 /* Existing index DESCENDING */
|
|
#define IN_INDEX_NOOP 5 /* No table available. Use comparisons */
|
|
/*
|
|
** Allowed flags for the 3rd parameter to sqlite3FindInIndex().
|
|
*/
|
|
#define IN_INDEX_NOOP_OK 0x0001 /* OK to return IN_INDEX_NOOP */
|
|
#define IN_INDEX_MEMBERSHIP 0x0002 /* IN operator used for membership test */
|
|
#define IN_INDEX_LOOP 0x0004 /* IN operator used as a loop */
|
|
SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, u32, int*, int*, int*);
|
|
|
|
SQLITE_PRIVATE int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int);
|
|
SQLITE_PRIVATE int sqlite3JournalSize(sqlite3_vfs *);
|
|
#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
|
|
|| defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
|
|
SQLITE_PRIVATE int sqlite3JournalCreate(sqlite3_file *);
|
|
#endif
|
|
|
|
SQLITE_PRIVATE int sqlite3JournalIsInMemory(sqlite3_file *p);
|
|
SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *);
|
|
|
|
SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p);
|
|
#if SQLITE_MAX_EXPR_DEPTH>0
|
|
SQLITE_PRIVATE int sqlite3SelectExprHeight(const Select *);
|
|
SQLITE_PRIVATE int sqlite3ExprCheckHeight(Parse*, int);
|
|
#else
|
|
#define sqlite3SelectExprHeight(x) 0
|
|
#define sqlite3ExprCheckHeight(x,y)
|
|
#endif
|
|
SQLITE_PRIVATE void sqlite3ExprSetErrorOffset(Expr*,int);
|
|
|
|
SQLITE_PRIVATE u32 sqlite3Get4byte(const u8*);
|
|
SQLITE_PRIVATE void sqlite3Put4byte(u8*, u32);
|
|
|
|
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
|
|
SQLITE_PRIVATE void sqlite3ConnectionBlocked(sqlite3 *, sqlite3 *);
|
|
SQLITE_PRIVATE void sqlite3ConnectionUnlocked(sqlite3 *db);
|
|
SQLITE_PRIVATE void sqlite3ConnectionClosed(sqlite3 *db);
|
|
#else
|
|
#define sqlite3ConnectionBlocked(x,y)
|
|
#define sqlite3ConnectionUnlocked(x)
|
|
#define sqlite3ConnectionClosed(x)
|
|
#endif
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
SQLITE_PRIVATE void sqlite3ParserTrace(FILE*, char *);
|
|
#endif
|
|
#if defined(YYCOVERAGE)
|
|
SQLITE_PRIVATE int sqlite3ParserCoverage(FILE*);
|
|
#endif
|
|
|
|
/*
|
|
** If the SQLITE_ENABLE IOTRACE exists then the global variable
|
|
** sqlite3IoTrace is a pointer to a printf-like routine used to
|
|
** print I/O tracing messages.
|
|
*/
|
|
#ifdef SQLITE_ENABLE_IOTRACE
|
|
# define IOTRACE(A) if( sqlite3IoTrace ){ sqlite3IoTrace A; }
|
|
SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe*);
|
|
SQLITE_API SQLITE_EXTERN void (SQLITE_CDECL *sqlite3IoTrace)(const char*,...);
|
|
#else
|
|
# define IOTRACE(A)
|
|
# define sqlite3VdbeIOTraceSql(X)
|
|
#endif
|
|
|
|
/*
|
|
** These routines are available for the mem2.c debugging memory allocator
|
|
** only. They are used to verify that different "types" of memory
|
|
** allocations are properly tracked by the system.
|
|
**
|
|
** sqlite3MemdebugSetType() sets the "type" of an allocation to one of
|
|
** the MEMTYPE_* macros defined below. The type must be a bitmask with
|
|
** a single bit set.
|
|
**
|
|
** sqlite3MemdebugHasType() returns true if any of the bits in its second
|
|
** argument match the type set by the previous sqlite3MemdebugSetType().
|
|
** sqlite3MemdebugHasType() is intended for use inside assert() statements.
|
|
**
|
|
** sqlite3MemdebugNoType() returns true if none of the bits in its second
|
|
** argument match the type set by the previous sqlite3MemdebugSetType().
|
|
**
|
|
** Perhaps the most important point is the difference between MEMTYPE_HEAP
|
|
** and MEMTYPE_LOOKASIDE. If an allocation is MEMTYPE_LOOKASIDE, that means
|
|
** it might have been allocated by lookaside, except the allocation was
|
|
** too large or lookaside was already full. It is important to verify
|
|
** that allocations that might have been satisfied by lookaside are not
|
|
** passed back to non-lookaside free() routines. Asserts such as the
|
|
** example above are placed on the non-lookaside free() routines to verify
|
|
** this constraint.
|
|
**
|
|
** All of this is no-op for a production build. It only comes into
|
|
** play when the SQLITE_MEMDEBUG compile-time option is used.
|
|
*/
|
|
#ifdef SQLITE_MEMDEBUG
|
|
SQLITE_PRIVATE void sqlite3MemdebugSetType(void*,u8);
|
|
SQLITE_PRIVATE int sqlite3MemdebugHasType(const void*,u8);
|
|
SQLITE_PRIVATE int sqlite3MemdebugNoType(const void*,u8);
|
|
#else
|
|
# define sqlite3MemdebugSetType(X,Y) /* no-op */
|
|
# define sqlite3MemdebugHasType(X,Y) 1
|
|
# define sqlite3MemdebugNoType(X,Y) 1
|
|
#endif
|
|
#define MEMTYPE_HEAP 0x01 /* General heap allocations */
|
|
#define MEMTYPE_LOOKASIDE 0x02 /* Heap that might have been lookaside */
|
|
#define MEMTYPE_PCACHE 0x04 /* Page cache allocations */
|
|
|
|
/*
|
|
** Threading interface
|
|
*/
|
|
#if SQLITE_MAX_WORKER_THREADS>0
|
|
SQLITE_PRIVATE int sqlite3ThreadCreate(SQLiteThread**,void*(*)(void*),void*);
|
|
SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread*, void**);
|
|
#endif
|
|
|
|
#if defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)
|
|
SQLITE_PRIVATE int sqlite3DbpageRegister(sqlite3*);
|
|
#endif
|
|
#if defined(SQLITE_ENABLE_DBSTAT_VTAB) || defined(SQLITE_TEST)
|
|
SQLITE_PRIVATE int sqlite3DbstatRegister(sqlite3*);
|
|
#endif
|
|
|
|
SQLITE_PRIVATE int sqlite3ExprVectorSize(const Expr *pExpr);
|
|
SQLITE_PRIVATE int sqlite3ExprIsVector(const Expr *pExpr);
|
|
SQLITE_PRIVATE Expr *sqlite3VectorFieldSubexpr(Expr*, int);
|
|
SQLITE_PRIVATE Expr *sqlite3ExprForVectorField(Parse*,Expr*,int,int);
|
|
SQLITE_PRIVATE void sqlite3VectorErrorMsg(Parse*, Expr*);
|
|
|
|
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
|
|
SQLITE_PRIVATE const char **sqlite3CompileOptions(int *pnOpt);
|
|
#endif
|
|
|
|
#if SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL)
|
|
SQLITE_PRIVATE int sqlite3KvvfsInit(void);
|
|
#endif
|
|
|
|
#if defined(VDBE_PROFILE) \
|
|
|| defined(SQLITE_PERFORMANCE_TRACE) \
|
|
|| defined(SQLITE_ENABLE_STMT_SCANSTATUS)
|
|
SQLITE_PRIVATE sqlite3_uint64 sqlite3Hwtime(void);
|
|
#endif
|
|
|
|
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
|
# define IS_STMT_SCANSTATUS(db) (db->flags & SQLITE_StmtScanStatus)
|
|
#else
|
|
# define IS_STMT_SCANSTATUS(db) 0
|
|
#endif
|
|
|
|
#endif /* SQLITEINT_H */
|
|
|
|
/************** End of sqliteInt.h *******************************************/
|
|
/************** Begin file os_common.h ***************************************/
|
|
/*
|
|
** 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.
|
|
*/
|
|
#ifndef _OS_COMMON_H_
|
|
#define _OS_COMMON_H_
|
|
|
|
/*
|
|
** 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
|
|
|
|
/*
|
|
** Macros for performance tracing. Normally turned off. Only works
|
|
** on i486 hardware.
|
|
*/
|
|
#ifdef SQLITE_PERFORMANCE_TRACE
|
|
|
|
static sqlite_uint64 g_start;
|
|
static sqlite_uint64 g_elapsed;
|
|
#define TIMER_START g_start=sqlite3Hwtime()
|
|
#define TIMER_END g_elapsed=sqlite3Hwtime()-g_start
|
|
#define TIMER_ELAPSED g_elapsed
|
|
#else
|
|
#define TIMER_START
|
|
#define TIMER_END
|
|
#define TIMER_ELAPSED ((sqlite_uint64)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.
|
|
*/
|
|
#if defined(SQLITE_TEST)
|
|
SQLITE_API extern int sqlite3_io_error_hit;
|
|
SQLITE_API extern int sqlite3_io_error_hardhit;
|
|
SQLITE_API extern int sqlite3_io_error_pending;
|
|
SQLITE_API extern int sqlite3_io_error_persist;
|
|
SQLITE_API extern int sqlite3_io_error_benign;
|
|
SQLITE_API extern int sqlite3_diskfull_pending;
|
|
SQLITE_API extern int sqlite3_diskfull;
|
|
#define SimulateIOErrorBenign(X) sqlite3_io_error_benign=(X)
|
|
#define SimulateIOError(CODE) \
|
|
if( (sqlite3_io_error_persist && sqlite3_io_error_hit) \
|
|
|| sqlite3_io_error_pending-- == 1 ) \
|
|
{ local_ioerr(); CODE; }
|
|
static void local_ioerr(){
|
|
IOTRACE(("IOERR\n"));
|
|
sqlite3_io_error_hit++;
|
|
if( !sqlite3_io_error_benign ) sqlite3_io_error_hardhit++;
|
|
}
|
|
#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 SimulateIOErrorBenign(X)
|
|
#define SimulateIOError(A)
|
|
#define SimulateDiskfullError(A)
|
|
#endif /* defined(SQLITE_TEST) */
|
|
|
|
/*
|
|
** When testing, keep a count of the number of open files.
|
|
*/
|
|
#if defined(SQLITE_TEST)
|
|
SQLITE_API extern int sqlite3_open_file_count;
|
|
#define OpenCounter(X) sqlite3_open_file_count+=(X)
|
|
#else
|
|
#define OpenCounter(X)
|
|
#endif /* defined(SQLITE_TEST) */
|
|
|
|
#endif /* !defined(_OS_COMMON_H_) */
|
|
|
|
/************** End of os_common.h *******************************************/
|
|
/************** Begin file ctime.c *******************************************/
|
|
/* DO NOT EDIT!
|
|
** This file is automatically generated by the script in the canonical
|
|
** SQLite source tree at tool/mkctimec.tcl.
|
|
**
|
|
** To modify this header, edit any of the various lists in that script
|
|
** which specify categories of generated conditionals in this file.
|
|
*/
|
|
|
|
/*
|
|
** 2010 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 implements routines used to report what compile-time options
|
|
** SQLite was built with.
|
|
*/
|
|
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS /* IMP: R-16824-07538 */
|
|
|
|
/*
|
|
** Include the configuration header output by 'configure' if we're using the
|
|
** autoconf-based build
|
|
*/
|
|
#if defined(_HAVE_SQLITE_CONFIG_H) && !defined(SQLITECONFIG_H)
|
|
/* #include "sqlite_cfg.h" */
|
|
#define SQLITECONFIG_H 1
|
|
#endif
|
|
|
|
/* These macros are provided to "stringify" the value of the define
|
|
** for those options in which the value is meaningful. */
|
|
#define CTIMEOPT_VAL_(opt) #opt
|
|
#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
|
|
|
|
/* Like CTIMEOPT_VAL, but especially for SQLITE_DEFAULT_LOOKASIDE. This
|
|
** option requires a separate macro because legal values contain a single
|
|
** comma. e.g. (-DSQLITE_DEFAULT_LOOKASIDE="100,100") */
|
|
#define CTIMEOPT_VAL2_(opt1,opt2) #opt1 "," #opt2
|
|
#define CTIMEOPT_VAL2(opt) CTIMEOPT_VAL2_(opt)
|
|
/* #include "sqliteInt.h" */
|
|
|
|
/*
|
|
** An array of names of all compile-time options. This array should
|
|
** be sorted A-Z.
|
|
**
|
|
** This array looks large, but in a typical installation actually uses
|
|
** only a handful of compile-time options, so most times this array is usually
|
|
** rather short and uses little memory space.
|
|
*/
|
|
static const char * const sqlite3azCompileOpt[] = {
|
|
|
|
#ifdef SQLITE_32BIT_ROWID
|
|
"32BIT_ROWID",
|
|
#endif
|
|
#ifdef SQLITE_4_BYTE_ALIGNED_MALLOC
|
|
"4_BYTE_ALIGNED_MALLOC",
|
|
#endif
|
|
#ifdef SQLITE_ALLOW_COVERING_INDEX_SCAN
|
|
# if SQLITE_ALLOW_COVERING_INDEX_SCAN != 1
|
|
"ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN),
|
|
# endif
|
|
#endif
|
|
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
|
"ALLOW_ROWID_IN_VIEW",
|
|
#endif
|
|
#ifdef SQLITE_ALLOW_URI_AUTHORITY
|
|
"ALLOW_URI_AUTHORITY",
|
|
#endif
|
|
#ifdef SQLITE_ATOMIC_INTRINSICS
|
|
"ATOMIC_INTRINSICS=" CTIMEOPT_VAL(SQLITE_ATOMIC_INTRINSICS),
|
|
#endif
|
|
#ifdef SQLITE_BITMASK_TYPE
|
|
"BITMASK_TYPE=" CTIMEOPT_VAL(SQLITE_BITMASK_TYPE),
|
|
#endif
|
|
#ifdef SQLITE_BUG_COMPATIBLE_20160819
|
|
"BUG_COMPATIBLE_20160819",
|
|
#endif
|
|
#ifdef SQLITE_CASE_SENSITIVE_LIKE
|
|
"CASE_SENSITIVE_LIKE",
|
|
#endif
|
|
#ifdef SQLITE_CHECK_PAGES
|
|
"CHECK_PAGES",
|
|
#endif
|
|
#if defined(__clang__) && defined(__clang_major__)
|
|
"COMPILER=clang-" CTIMEOPT_VAL(__clang_major__) "."
|
|
CTIMEOPT_VAL(__clang_minor__) "."
|
|
CTIMEOPT_VAL(__clang_patchlevel__),
|
|
#elif defined(_MSC_VER)
|
|
"COMPILER=msvc-" CTIMEOPT_VAL(_MSC_VER),
|
|
#elif defined(__GNUC__) && defined(__VERSION__)
|
|
"COMPILER=gcc-" __VERSION__,
|
|
#endif
|
|
#ifdef SQLITE_COVERAGE_TEST
|
|
"COVERAGE_TEST",
|
|
#endif
|
|
#ifdef SQLITE_DEBUG
|
|
"DEBUG",
|
|
#endif
|
|
#ifdef SQLITE_DEFAULT_AUTOMATIC_INDEX
|
|
"DEFAULT_AUTOMATIC_INDEX",
|
|
#endif
|
|
#ifdef SQLITE_DEFAULT_AUTOVACUUM
|
|
"DEFAULT_AUTOVACUUM",
|
|
#endif
|
|
#ifdef SQLITE_DEFAULT_CACHE_SIZE
|
|
"DEFAULT_CACHE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_CACHE_SIZE),
|
|
#endif
|
|
#ifdef SQLITE_DEFAULT_CKPTFULLFSYNC
|
|
"DEFAULT_CKPTFULLFSYNC",
|
|
#endif
|
|
#ifdef SQLITE_DEFAULT_FILE_FORMAT
|
|
"DEFAULT_FILE_FORMAT=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_FORMAT),
|
|
#endif
|
|
#ifdef SQLITE_DEFAULT_FILE_PERMISSIONS
|
|
"DEFAULT_FILE_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_PERMISSIONS),
|
|
#endif
|
|
#ifdef SQLITE_DEFAULT_FOREIGN_KEYS
|
|
"DEFAULT_FOREIGN_KEYS",
|
|
#endif
|
|
#ifdef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT
|
|
"DEFAULT_JOURNAL_SIZE_LIMIT=" CTIMEOPT_VAL(SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT),
|
|
#endif
|
|
#ifdef SQLITE_DEFAULT_LOCKING_MODE
|
|
"DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
|
|
#endif
|
|
#ifdef SQLITE_DEFAULT_LOOKASIDE
|
|
"DEFAULT_LOOKASIDE=" CTIMEOPT_VAL2(SQLITE_DEFAULT_LOOKASIDE),
|
|
#endif
|
|
#ifdef SQLITE_DEFAULT_MEMSTATUS
|
|
# if SQLITE_DEFAULT_MEMSTATUS != 1
|
|
"DEFAULT_MEMSTATUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_MEMSTATUS),
|
|
# endif
|
|
#endif
|
|
#ifdef SQLITE_DEFAULT_MMAP_SIZE
|
|
"DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
|
|
#endif
|
|
#ifdef SQLITE_DEFAULT_PAGE_SIZE
|
|
"DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_PAGE_SIZE),
|
|
#endif
|
|
#ifdef SQLITE_DEFAULT_PCACHE_INITSZ
|
|
"DEFAULT_PCACHE_INITSZ=" CTIMEOPT_VAL(SQLITE_DEFAULT_PCACHE_INITSZ),
|
|
#endif
|
|
#ifdef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
|
|
"DEFAULT_PROXYDIR_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_PROXYDIR_PERMISSIONS),
|
|
#endif
|
|
#ifdef SQLITE_DEFAULT_RECURSIVE_TRIGGERS
|
|
"DEFAULT_RECURSIVE_TRIGGERS",
|
|
#endif
|
|
#ifdef SQLITE_DEFAULT_ROWEST
|
|
"DEFAULT_ROWEST=" CTIMEOPT_VAL(SQLITE_DEFAULT_ROWEST),
|
|
#endif
|
|
#ifdef SQLITE_DEFAULT_SECTOR_SIZE
|
|
"DEFAULT_SECTOR_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_SECTOR_SIZE),
|
|
#endif
|
|
#ifdef SQLITE_DEFAULT_SYNCHRONOUS
|
|
"DEFAULT_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_SYNCHRONOUS),
|
|
#endif
|
|
#ifdef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
|
|
"DEFAULT_WAL_AUTOCHECKPOINT=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_AUTOCHECKPOINT),
|
|
#endif
|
|
#ifdef SQLITE_DEFAULT_WAL_SYNCHRONOUS
|
|
"DEFAULT_WAL_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_SYNCHRONOUS),
|
|
#endif
|
|
#ifdef SQLITE_DEFAULT_WORKER_THREADS
|
|
"DEFAULT_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WORKER_THREADS),
|
|
#endif
|
|
#ifdef SQLITE_DIRECT_OVERFLOW_READ
|
|
"DIRECT_OVERFLOW_READ",
|
|
#endif
|
|
#ifdef SQLITE_DISABLE_DIRSYNC
|
|
"DISABLE_DIRSYNC",
|
|
#endif
|
|
#ifdef SQLITE_DISABLE_FTS3_UNICODE
|
|
"DISABLE_FTS3_UNICODE",
|
|
#endif
|
|
#ifdef SQLITE_DISABLE_FTS4_DEFERRED
|
|
"DISABLE_FTS4_DEFERRED",
|
|
#endif
|
|
#ifdef SQLITE_DISABLE_INTRINSIC
|
|
"DISABLE_INTRINSIC",
|
|
#endif
|
|
#ifdef SQLITE_DISABLE_LFS
|
|
"DISABLE_LFS",
|
|
#endif
|
|
#ifdef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
|
|
"DISABLE_PAGECACHE_OVERFLOW_STATS",
|
|
#endif
|
|
#ifdef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
|
|
"DISABLE_SKIPAHEAD_DISTINCT",
|
|
#endif
|
|
#ifdef SQLITE_DQS
|
|
"DQS=" CTIMEOPT_VAL(SQLITE_DQS),
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_8_3_NAMES
|
|
"ENABLE_8_3_NAMES=" CTIMEOPT_VAL(SQLITE_ENABLE_8_3_NAMES),
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
|
"ENABLE_API_ARMOR",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
|
|
"ENABLE_ATOMIC_WRITE",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
|
|
"ENABLE_BATCH_ATOMIC_WRITE",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_BYTECODE_VTAB
|
|
"ENABLE_BYTECODE_VTAB",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_CEROD
|
|
"ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD),
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
|
"ENABLE_COLUMN_METADATA",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
|
|
"ENABLE_COLUMN_USED_MASK",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_COSTMULT
|
|
"ENABLE_COSTMULT",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
|
"ENABLE_CURSOR_HINTS",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_DBPAGE_VTAB
|
|
"ENABLE_DBPAGE_VTAB",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_DBSTAT_VTAB
|
|
"ENABLE_DBSTAT_VTAB",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT
|
|
"ENABLE_EXPENSIVE_ASSERT",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
|
"ENABLE_EXPLAIN_COMMENTS",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_FTS3
|
|
"ENABLE_FTS3",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_FTS3_PARENTHESIS
|
|
"ENABLE_FTS3_PARENTHESIS",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_FTS3_TOKENIZER
|
|
"ENABLE_FTS3_TOKENIZER",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_FTS4
|
|
"ENABLE_FTS4",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_FTS5
|
|
"ENABLE_FTS5",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_GEOPOLY
|
|
"ENABLE_GEOPOLY",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_HIDDEN_COLUMNS
|
|
"ENABLE_HIDDEN_COLUMNS",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_ICU
|
|
"ENABLE_ICU",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_IOTRACE
|
|
"ENABLE_IOTRACE",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_LOAD_EXTENSION
|
|
"ENABLE_LOAD_EXTENSION",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_LOCKING_STYLE
|
|
"ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_MATH_FUNCTIONS
|
|
"ENABLE_MATH_FUNCTIONS",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
|
"ENABLE_MEMORY_MANAGEMENT",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_MEMSYS3
|
|
"ENABLE_MEMSYS3",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_MEMSYS5
|
|
"ENABLE_MEMSYS5",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_MULTIPLEX
|
|
"ENABLE_MULTIPLEX",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_NORMALIZE
|
|
"ENABLE_NORMALIZE",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_NULL_TRIM
|
|
"ENABLE_NULL_TRIM",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
|
|
"ENABLE_OFFSET_SQL_FUNC",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_OVERSIZE_CELL_CHECK
|
|
"ENABLE_OVERSIZE_CELL_CHECK",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
|
|
"ENABLE_PREUPDATE_HOOK",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_QPSG
|
|
"ENABLE_QPSG",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_RBU
|
|
"ENABLE_RBU",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_RTREE
|
|
"ENABLE_RTREE",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_SESSION
|
|
"ENABLE_SESSION",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_SNAPSHOT
|
|
"ENABLE_SNAPSHOT",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
|
|
"ENABLE_SORTER_REFERENCES",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_SQLLOG
|
|
"ENABLE_SQLLOG",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_STAT4
|
|
"ENABLE_STAT4",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_STMTVTAB
|
|
"ENABLE_STMTVTAB",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
|
"ENABLE_STMT_SCANSTATUS",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_TREETRACE
|
|
"ENABLE_TREETRACE",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
|
|
"ENABLE_UNKNOWN_SQL_FUNCTION",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
|
|
"ENABLE_UNLOCK_NOTIFY",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
|
|
"ENABLE_UPDATE_DELETE_LIMIT",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_URI_00_ERROR
|
|
"ENABLE_URI_00_ERROR",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_VFSTRACE
|
|
"ENABLE_VFSTRACE",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_WHERETRACE
|
|
"ENABLE_WHERETRACE",
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_ZIPVFS
|
|
"ENABLE_ZIPVFS",
|
|
#endif
|
|
#ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS
|
|
"EXPLAIN_ESTIMATED_ROWS",
|
|
#endif
|
|
#ifdef SQLITE_EXTRA_AUTOEXT
|
|
"EXTRA_AUTOEXT=" CTIMEOPT_VAL(SQLITE_EXTRA_AUTOEXT),
|
|
#endif
|
|
#ifdef SQLITE_EXTRA_IFNULLROW
|
|
"EXTRA_IFNULLROW",
|
|
#endif
|
|
#ifdef SQLITE_EXTRA_INIT
|
|
"EXTRA_INIT=" CTIMEOPT_VAL(SQLITE_EXTRA_INIT),
|
|
#endif
|
|
#ifdef SQLITE_EXTRA_SHUTDOWN
|
|
"EXTRA_SHUTDOWN=" CTIMEOPT_VAL(SQLITE_EXTRA_SHUTDOWN),
|
|
#endif
|
|
#ifdef SQLITE_FTS3_MAX_EXPR_DEPTH
|
|
"FTS3_MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_FTS3_MAX_EXPR_DEPTH),
|
|
#endif
|
|
#ifdef SQLITE_FTS5_ENABLE_TEST_MI
|
|
"FTS5_ENABLE_TEST_MI",
|
|
#endif
|
|
#ifdef SQLITE_FTS5_NO_WITHOUT_ROWID
|
|
"FTS5_NO_WITHOUT_ROWID",
|
|
#endif
|
|
#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
|
|
"HAVE_ISNAN",
|
|
#endif
|
|
#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
|
|
# if SQLITE_HOMEGROWN_RECURSIVE_MUTEX != 1
|
|
"HOMEGROWN_RECURSIVE_MUTEX=" CTIMEOPT_VAL(SQLITE_HOMEGROWN_RECURSIVE_MUTEX),
|
|
# endif
|
|
#endif
|
|
#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS
|
|
"IGNORE_AFP_LOCK_ERRORS",
|
|
#endif
|
|
#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
|
|
"IGNORE_FLOCK_LOCK_ERRORS",
|
|
#endif
|
|
#ifdef SQLITE_INLINE_MEMCPY
|
|
"INLINE_MEMCPY",
|
|
#endif
|
|
#ifdef SQLITE_INT64_TYPE
|
|
"INT64_TYPE",
|
|
#endif
|
|
#ifdef SQLITE_INTEGRITY_CHECK_ERROR_MAX
|
|
"INTEGRITY_CHECK_ERROR_MAX=" CTIMEOPT_VAL(SQLITE_INTEGRITY_CHECK_ERROR_MAX),
|
|
#endif
|
|
#ifdef SQLITE_LEGACY_JSON_VALID
|
|
"LEGACY_JSON_VALID",
|
|
#endif
|
|
#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
|
"LIKE_DOESNT_MATCH_BLOBS",
|
|
#endif
|
|
#ifdef SQLITE_LOCK_TRACE
|
|
"LOCK_TRACE",
|
|
#endif
|
|
#ifdef SQLITE_LOG_CACHE_SPILL
|
|
"LOG_CACHE_SPILL",
|
|
#endif
|
|
#ifdef SQLITE_MALLOC_SOFT_LIMIT
|
|
"MALLOC_SOFT_LIMIT=" CTIMEOPT_VAL(SQLITE_MALLOC_SOFT_LIMIT),
|
|
#endif
|
|
#ifdef SQLITE_MAX_ATTACHED
|
|
"MAX_ATTACHED=" CTIMEOPT_VAL(SQLITE_MAX_ATTACHED),
|
|
#endif
|
|
#ifdef SQLITE_MAX_COLUMN
|
|
"MAX_COLUMN=" CTIMEOPT_VAL(SQLITE_MAX_COLUMN),
|
|
#endif
|
|
#ifdef SQLITE_MAX_COMPOUND_SELECT
|
|
"MAX_COMPOUND_SELECT=" CTIMEOPT_VAL(SQLITE_MAX_COMPOUND_SELECT),
|
|
#endif
|
|
#ifdef SQLITE_MAX_DEFAULT_PAGE_SIZE
|
|
"MAX_DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_DEFAULT_PAGE_SIZE),
|
|
#endif
|
|
#ifdef SQLITE_MAX_EXPR_DEPTH
|
|
"MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_EXPR_DEPTH),
|
|
#endif
|
|
#ifdef SQLITE_MAX_FUNCTION_ARG
|
|
"MAX_FUNCTION_ARG=" CTIMEOPT_VAL(SQLITE_MAX_FUNCTION_ARG),
|
|
#endif
|
|
#ifdef SQLITE_MAX_LENGTH
|
|
"MAX_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LENGTH),
|
|
#endif
|
|
#ifdef SQLITE_MAX_LIKE_PATTERN_LENGTH
|
|
"MAX_LIKE_PATTERN_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LIKE_PATTERN_LENGTH),
|
|
#endif
|
|
#ifdef SQLITE_MAX_MEMORY
|
|
"MAX_MEMORY=" CTIMEOPT_VAL(SQLITE_MAX_MEMORY),
|
|
#endif
|
|
#ifdef SQLITE_MAX_MMAP_SIZE
|
|
"MAX_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE),
|
|
#endif
|
|
#ifdef SQLITE_MAX_MMAP_SIZE_
|
|
"MAX_MMAP_SIZE_=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE_),
|
|
#endif
|
|
#ifdef SQLITE_MAX_PAGE_COUNT
|
|
"MAX_PAGE_COUNT=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_COUNT),
|
|
#endif
|
|
#ifdef SQLITE_MAX_PAGE_SIZE
|
|
"MAX_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_SIZE),
|
|
#endif
|
|
#ifdef SQLITE_MAX_SCHEMA_RETRY
|
|
"MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
|
|
#endif
|
|
#ifdef SQLITE_MAX_SQL_LENGTH
|
|
"MAX_SQL_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_SQL_LENGTH),
|
|
#endif
|
|
#ifdef SQLITE_MAX_TRIGGER_DEPTH
|
|
"MAX_TRIGGER_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_TRIGGER_DEPTH),
|
|
#endif
|
|
#ifdef SQLITE_MAX_VARIABLE_NUMBER
|
|
"MAX_VARIABLE_NUMBER=" CTIMEOPT_VAL(SQLITE_MAX_VARIABLE_NUMBER),
|
|
#endif
|
|
#ifdef SQLITE_MAX_VDBE_OP
|
|
"MAX_VDBE_OP=" CTIMEOPT_VAL(SQLITE_MAX_VDBE_OP),
|
|
#endif
|
|
#ifdef SQLITE_MAX_WORKER_THREADS
|
|
"MAX_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_MAX_WORKER_THREADS),
|
|
#endif
|
|
#ifdef SQLITE_MEMDEBUG
|
|
"MEMDEBUG",
|
|
#endif
|
|
#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
|
|
"MIXED_ENDIAN_64BIT_FLOAT",
|
|
#endif
|
|
#ifdef SQLITE_MMAP_READWRITE
|
|
"MMAP_READWRITE",
|
|
#endif
|
|
#ifdef SQLITE_MUTEX_NOOP
|
|
"MUTEX_NOOP",
|
|
#endif
|
|
#ifdef SQLITE_MUTEX_OMIT
|
|
"MUTEX_OMIT",
|
|
#endif
|
|
#ifdef SQLITE_MUTEX_PTHREADS
|
|
"MUTEX_PTHREADS",
|
|
#endif
|
|
#ifdef SQLITE_MUTEX_W32
|
|
"MUTEX_W32",
|
|
#endif
|
|
#ifdef SQLITE_NEED_ERR_NAME
|
|
"NEED_ERR_NAME",
|
|
#endif
|
|
#ifdef SQLITE_NO_SYNC
|
|
"NO_SYNC",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_ALTERTABLE
|
|
"OMIT_ALTERTABLE",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_ANALYZE
|
|
"OMIT_ANALYZE",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_ATTACH
|
|
"OMIT_ATTACH",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_AUTHORIZATION
|
|
"OMIT_AUTHORIZATION",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_AUTOINCREMENT
|
|
"OMIT_AUTOINCREMENT",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_AUTOINIT
|
|
"OMIT_AUTOINIT",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_AUTOMATIC_INDEX
|
|
"OMIT_AUTOMATIC_INDEX",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_AUTORESET
|
|
"OMIT_AUTORESET",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_AUTOVACUUM
|
|
"OMIT_AUTOVACUUM",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION
|
|
"OMIT_BETWEEN_OPTIMIZATION",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_BLOB_LITERAL
|
|
"OMIT_BLOB_LITERAL",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_CAST
|
|
"OMIT_CAST",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_CHECK
|
|
"OMIT_CHECK",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_COMPLETE
|
|
"OMIT_COMPLETE",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_COMPOUND_SELECT
|
|
"OMIT_COMPOUND_SELECT",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_CONFLICT_CLAUSE
|
|
"OMIT_CONFLICT_CLAUSE",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_CTE
|
|
"OMIT_CTE",
|
|
#endif
|
|
#if defined(SQLITE_OMIT_DATETIME_FUNCS) || defined(SQLITE_OMIT_FLOATING_POINT)
|
|
"OMIT_DATETIME_FUNCS",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_DECLTYPE
|
|
"OMIT_DECLTYPE",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_DEPRECATED
|
|
"OMIT_DEPRECATED",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_DESERIALIZE
|
|
"OMIT_DESERIALIZE",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_DISKIO
|
|
"OMIT_DISKIO",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_EXPLAIN
|
|
"OMIT_EXPLAIN",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_FLAG_PRAGMAS
|
|
"OMIT_FLAG_PRAGMAS",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_FLOATING_POINT
|
|
"OMIT_FLOATING_POINT",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_FOREIGN_KEY
|
|
"OMIT_FOREIGN_KEY",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_GET_TABLE
|
|
"OMIT_GET_TABLE",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_HEX_INTEGER
|
|
"OMIT_HEX_INTEGER",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_INCRBLOB
|
|
"OMIT_INCRBLOB",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_INTEGRITY_CHECK
|
|
"OMIT_INTEGRITY_CHECK",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_INTROSPECTION_PRAGMAS
|
|
"OMIT_INTROSPECTION_PRAGMAS",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_JSON
|
|
"OMIT_JSON",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION
|
|
"OMIT_LIKE_OPTIMIZATION",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_LOAD_EXTENSION
|
|
"OMIT_LOAD_EXTENSION",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_LOCALTIME
|
|
"OMIT_LOCALTIME",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_LOOKASIDE
|
|
"OMIT_LOOKASIDE",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_MEMORYDB
|
|
"OMIT_MEMORYDB",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_OR_OPTIMIZATION
|
|
"OMIT_OR_OPTIMIZATION",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_PAGER_PRAGMAS
|
|
"OMIT_PAGER_PRAGMAS",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_PARSER_TRACE
|
|
"OMIT_PARSER_TRACE",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_POPEN
|
|
"OMIT_POPEN",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_PRAGMA
|
|
"OMIT_PRAGMA",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
|
|
"OMIT_PROGRESS_CALLBACK",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_QUICKBALANCE
|
|
"OMIT_QUICKBALANCE",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_REINDEX
|
|
"OMIT_REINDEX",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS
|
|
"OMIT_SCHEMA_PRAGMAS",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
|
|
"OMIT_SCHEMA_VERSION_PRAGMAS",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_SEH
|
|
"OMIT_SEH",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_SHARED_CACHE
|
|
"OMIT_SHARED_CACHE",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_SHUTDOWN_DIRECTORIES
|
|
"OMIT_SHUTDOWN_DIRECTORIES",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_SUBQUERY
|
|
"OMIT_SUBQUERY",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_TCL_VARIABLE
|
|
"OMIT_TCL_VARIABLE",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_TEMPDB
|
|
"OMIT_TEMPDB",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_TEST_CONTROL
|
|
"OMIT_TEST_CONTROL",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_TRACE
|
|
# if SQLITE_OMIT_TRACE != 1
|
|
"OMIT_TRACE=" CTIMEOPT_VAL(SQLITE_OMIT_TRACE),
|
|
# endif
|
|
#endif
|
|
#ifdef SQLITE_OMIT_TRIGGER
|
|
"OMIT_TRIGGER",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_TRUNCATE_OPTIMIZATION
|
|
"OMIT_TRUNCATE_OPTIMIZATION",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_UTF16
|
|
"OMIT_UTF16",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_VACUUM
|
|
"OMIT_VACUUM",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_VIEW
|
|
"OMIT_VIEW",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_VIRTUALTABLE
|
|
"OMIT_VIRTUALTABLE",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_WAL
|
|
"OMIT_WAL",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_WSD
|
|
"OMIT_WSD",
|
|
#endif
|
|
#ifdef SQLITE_OMIT_XFER_OPT
|
|
"OMIT_XFER_OPT",
|
|
#endif
|
|
#ifdef SQLITE_PERFORMANCE_TRACE
|
|
"PERFORMANCE_TRACE",
|
|
#endif
|
|
#ifdef SQLITE_POWERSAFE_OVERWRITE
|
|
# if SQLITE_POWERSAFE_OVERWRITE != 1
|
|
"POWERSAFE_OVERWRITE=" CTIMEOPT_VAL(SQLITE_POWERSAFE_OVERWRITE),
|
|
# endif
|
|
#endif
|
|
#ifdef SQLITE_PREFER_PROXY_LOCKING
|
|
"PREFER_PROXY_LOCKING",
|
|
#endif
|
|
#ifdef SQLITE_PROXY_DEBUG
|
|
"PROXY_DEBUG",
|
|
#endif
|
|
#ifdef SQLITE_REVERSE_UNORDERED_SELECTS
|
|
"REVERSE_UNORDERED_SELECTS",
|
|
#endif
|
|
#ifdef SQLITE_RTREE_INT_ONLY
|
|
"RTREE_INT_ONLY",
|
|
#endif
|
|
#ifdef SQLITE_SECURE_DELETE
|
|
"SECURE_DELETE",
|
|
#endif
|
|
#ifdef SQLITE_SMALL_STACK
|
|
"SMALL_STACK",
|
|
#endif
|
|
#ifdef SQLITE_SORTER_PMASZ
|
|
"SORTER_PMASZ=" CTIMEOPT_VAL(SQLITE_SORTER_PMASZ),
|
|
#endif
|
|
#ifdef SQLITE_SOUNDEX
|
|
"SOUNDEX",
|
|
#endif
|
|
#ifdef SQLITE_STAT4_SAMPLES
|
|
"STAT4_SAMPLES=" CTIMEOPT_VAL(SQLITE_STAT4_SAMPLES),
|
|
#endif
|
|
#ifdef SQLITE_STMTJRNL_SPILL
|
|
"STMTJRNL_SPILL=" CTIMEOPT_VAL(SQLITE_STMTJRNL_SPILL),
|
|
#endif
|
|
#ifdef SQLITE_SUBSTR_COMPATIBILITY
|
|
"SUBSTR_COMPATIBILITY",
|
|
#endif
|
|
#if (!defined(SQLITE_WIN32_MALLOC) \
|
|
&& !defined(SQLITE_ZERO_MALLOC) \
|
|
&& !defined(SQLITE_MEMDEBUG) \
|
|
) || defined(SQLITE_SYSTEM_MALLOC)
|
|
"SYSTEM_MALLOC",
|
|
#endif
|
|
#ifdef SQLITE_TCL
|
|
"TCL",
|
|
#endif
|
|
#ifdef SQLITE_TEMP_STORE
|
|
"TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
|
|
#endif
|
|
#ifdef SQLITE_TEST
|
|
"TEST",
|
|
#endif
|
|
#if defined(SQLITE_THREADSAFE)
|
|
"THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
|
|
#elif defined(THREADSAFE)
|
|
"THREADSAFE=" CTIMEOPT_VAL(THREADSAFE),
|
|
#else
|
|
"THREADSAFE=1",
|
|
#endif
|
|
#ifdef SQLITE_UNLINK_AFTER_CLOSE
|
|
"UNLINK_AFTER_CLOSE",
|
|
#endif
|
|
#ifdef SQLITE_UNTESTABLE
|
|
"UNTESTABLE",
|
|
#endif
|
|
#ifdef SQLITE_USER_AUTHENTICATION
|
|
"USER_AUTHENTICATION",
|
|
#endif
|
|
#ifdef SQLITE_USE_ALLOCA
|
|
"USE_ALLOCA",
|
|
#endif
|
|
#ifdef SQLITE_USE_FCNTL_TRACE
|
|
"USE_FCNTL_TRACE",
|
|
#endif
|
|
#ifdef SQLITE_USE_URI
|
|
"USE_URI",
|
|
#endif
|
|
#ifdef SQLITE_VDBE_COVERAGE
|
|
"VDBE_COVERAGE",
|
|
#endif
|
|
#ifdef SQLITE_WIN32_MALLOC
|
|
"WIN32_MALLOC",
|
|
#endif
|
|
#ifdef SQLITE_ZERO_MALLOC
|
|
"ZERO_MALLOC",
|
|
#endif
|
|
|
|
} ;
|
|
|
|
SQLITE_PRIVATE const char **sqlite3CompileOptions(int *pnOpt){
|
|
*pnOpt = sizeof(sqlite3azCompileOpt) / sizeof(sqlite3azCompileOpt[0]);
|
|
return (const char**)sqlite3azCompileOpt;
|
|
}
|
|
|
|
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
|
|
|
|
/************** End of ctime.c ***********************************************/
|
|
/************** Begin file global.c ******************************************/
|
|
/*
|
|
** 2008 June 13
|
|
**
|
|
** The author disclaims copyright to this source code. In place of
|
|
** a legal notice, here is a blessing:
|
|
**
|
|
** May you do good and not evil.
|
|
** May you find forgiveness for yourself and forgive others.
|
|
** May you share freely, never taking more than you give.
|
|
**
|
|
*************************************************************************
|
|
**
|
|
** This file contains definitions of global variables and constants.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
|
|
/* An array to map all upper-case characters into their corresponding
|
|
** lower-case character.
|
|
**
|
|
** SQLite only considers US-ASCII (or EBCDIC) characters. We do not
|
|
** handle case conversions for the UTF character set since the tables
|
|
** involved are nearly as big or bigger than SQLite itself.
|
|
*/
|
|
SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[] = {
|
|
#ifdef SQLITE_ASCII
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
|
|
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
|
|
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
|
|
54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103,
|
|
104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,
|
|
122, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104,105,106,107,
|
|
108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,
|
|
126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
|
|
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,
|
|
162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,
|
|
180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,
|
|
198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,
|
|
216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,
|
|
234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,
|
|
252,253,254,255,
|
|
#endif
|
|
#ifdef SQLITE_EBCDIC
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 0x */
|
|
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 1x */
|
|
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, /* 2x */
|
|
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 3x */
|
|
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, /* 4x */
|
|
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, /* 5x */
|
|
96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, /* 6x */
|
|
112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, /* 7x */
|
|
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, /* 8x */
|
|
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, /* 9x */
|
|
160,161,162,163,164,165,166,167,168,169,170,171,140,141,142,175, /* Ax */
|
|
176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, /* Bx */
|
|
192,129,130,131,132,133,134,135,136,137,202,203,204,205,206,207, /* Cx */
|
|
208,145,146,147,148,149,150,151,152,153,218,219,220,221,222,223, /* Dx */
|
|
224,225,162,163,164,165,166,167,168,169,234,235,236,237,238,239, /* Ex */
|
|
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, /* Fx */
|
|
#endif
|
|
/* All of the upper-to-lower conversion data is above. The following
|
|
** 18 integers are completely unrelated. They are appended to the
|
|
** sqlite3UpperToLower[] array to avoid UBSAN warnings. Here's what is
|
|
** going on:
|
|
**
|
|
** The SQL comparison operators (<>, =, >, <=, <, and >=) are implemented
|
|
** by invoking sqlite3MemCompare(A,B) which compares values A and B and
|
|
** returns negative, zero, or positive if A is less then, equal to, or
|
|
** greater than B, respectively. Then the true false results is found by
|
|
** consulting sqlite3aLTb[opcode], sqlite3aEQb[opcode], or
|
|
** sqlite3aGTb[opcode] depending on whether the result of compare(A,B)
|
|
** is negative, zero, or positive, where opcode is the specific opcode.
|
|
** The only works because the comparison opcodes are consecutive and in
|
|
** this order: NE EQ GT LE LT GE. Various assert()s throughout the code
|
|
** ensure that is the case.
|
|
**
|
|
** These elements must be appended to another array. Otherwise the
|
|
** index (here shown as [256-OP_Ne]) would be out-of-bounds and thus
|
|
** be undefined behavior. That's goofy, but the C-standards people thought
|
|
** it was a good idea, so here we are.
|
|
*/
|
|
/* NE EQ GT LE LT GE */
|
|
1, 0, 0, 1, 1, 0, /* aLTb[]: Use when compare(A,B) less than zero */
|
|
0, 1, 0, 1, 0, 1, /* aEQb[]: Use when compare(A,B) equals zero */
|
|
1, 0, 1, 0, 0, 1 /* aGTb[]: Use when compare(A,B) greater than zero*/
|
|
};
|
|
SQLITE_PRIVATE const unsigned char *sqlite3aLTb = &sqlite3UpperToLower[256-OP_Ne];
|
|
SQLITE_PRIVATE const unsigned char *sqlite3aEQb = &sqlite3UpperToLower[256+6-OP_Ne];
|
|
SQLITE_PRIVATE const unsigned char *sqlite3aGTb = &sqlite3UpperToLower[256+12-OP_Ne];
|
|
|
|
/*
|
|
** The following 256 byte lookup table is used to support SQLites built-in
|
|
** equivalents to the following standard library functions:
|
|
**
|
|
** isspace() 0x01
|
|
** isalpha() 0x02
|
|
** isdigit() 0x04
|
|
** isalnum() 0x06
|
|
** isxdigit() 0x08
|
|
** toupper() 0x20
|
|
** SQLite identifier character 0x40 $, _, or non-ascii
|
|
** Quote character 0x80
|
|
**
|
|
** Bit 0x20 is set if the mapped character requires translation to upper
|
|
** case. i.e. if the character is a lower-case ASCII character.
|
|
** If x is a lower-case ASCII character, then its upper-case equivalent
|
|
** is (x - 0x20). Therefore toupper() can be implemented as:
|
|
**
|
|
** (x & ~(map[x]&0x20))
|
|
**
|
|
** The equivalent of tolower() is implemented using the sqlite3UpperToLower[]
|
|
** array. tolower() is used more often than toupper() by SQLite.
|
|
**
|
|
** Bit 0x40 is set if the character is non-alphanumeric and can be used in an
|
|
** SQLite identifier. Identifiers are alphanumerics, "_", "$", and any
|
|
** non-ASCII UTF character. Hence the test for whether or not a character is
|
|
** part of an identifier is 0x46.
|
|
*/
|
|
SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = {
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00..07 ........ */
|
|
0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, /* 08..0f ........ */
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 10..17 ........ */
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 18..1f ........ */
|
|
0x01, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x80, /* 20..27 !"#$%&' */
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 28..2f ()*+,-./ */
|
|
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, /* 30..37 01234567 */
|
|
0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 38..3f 89:;<=>? */
|
|
|
|
0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x02, /* 40..47 @ABCDEFG */
|
|
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 48..4f HIJKLMNO */
|
|
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, /* 50..57 PQRSTUVW */
|
|
0x02, 0x02, 0x02, 0x80, 0x00, 0x00, 0x00, 0x40, /* 58..5f XYZ[\]^_ */
|
|
0x80, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x22, /* 60..67 `abcdefg */
|
|
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /* 68..6f hijklmno */
|
|
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, /* 70..77 pqrstuvw */
|
|
0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, /* 78..7f xyz{|}~. */
|
|
|
|
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 80..87 ........ */
|
|
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 88..8f ........ */
|
|
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 90..97 ........ */
|
|
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* 98..9f ........ */
|
|
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* a0..a7 ........ */
|
|
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* a8..af ........ */
|
|
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* b0..b7 ........ */
|
|
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* b8..bf ........ */
|
|
|
|
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* c0..c7 ........ */
|
|
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* c8..cf ........ */
|
|
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* d0..d7 ........ */
|
|
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* d8..df ........ */
|
|
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* e0..e7 ........ */
|
|
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* e8..ef ........ */
|
|
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* f0..f7 ........ */
|
|
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 /* f8..ff ........ */
|
|
};
|
|
|
|
/* EVIDENCE-OF: R-02982-34736 In order to maintain full backwards
|
|
** compatibility for legacy applications, the URI filename capability is
|
|
** disabled by default.
|
|
**
|
|
** EVIDENCE-OF: R-38799-08373 URI filenames can be enabled or disabled
|
|
** using the SQLITE_USE_URI=1 or SQLITE_USE_URI=0 compile-time options.
|
|
**
|
|
** EVIDENCE-OF: R-43642-56306 By default, URI handling is globally
|
|
** disabled. The default value may be changed by compiling with the
|
|
** SQLITE_USE_URI symbol defined.
|
|
*/
|
|
#ifndef SQLITE_USE_URI
|
|
# define SQLITE_USE_URI 0
|
|
#endif
|
|
|
|
/* EVIDENCE-OF: R-38720-18127 The default setting is determined by the
|
|
** SQLITE_ALLOW_COVERING_INDEX_SCAN compile-time option, or is "on" if
|
|
** that compile-time option is omitted.
|
|
*/
|
|
#if !defined(SQLITE_ALLOW_COVERING_INDEX_SCAN)
|
|
# define SQLITE_ALLOW_COVERING_INDEX_SCAN 1
|
|
#else
|
|
# if !SQLITE_ALLOW_COVERING_INDEX_SCAN
|
|
# error "Compile-time disabling of covering index scan using the\
|
|
-DSQLITE_ALLOW_COVERING_INDEX_SCAN=0 option is deprecated.\
|
|
Contact SQLite developers if this is a problem for you, and\
|
|
delete this #error macro to continue with your build."
|
|
# endif
|
|
#endif
|
|
|
|
/* The minimum PMA size is set to this value multiplied by the database
|
|
** page size in bytes.
|
|
*/
|
|
#ifndef SQLITE_SORTER_PMASZ
|
|
# define SQLITE_SORTER_PMASZ 250
|
|
#endif
|
|
|
|
/* Statement journals spill to disk when their size exceeds the following
|
|
** threshold (in bytes). 0 means that statement journals are created and
|
|
** written to disk immediately (the default behavior for SQLite versions
|
|
** before 3.12.0). -1 means always keep the entire statement journal in
|
|
** memory. (The statement journal is also always held entirely in memory
|
|
** if journal_mode=MEMORY or if temp_store=MEMORY, regardless of this
|
|
** setting.)
|
|
*/
|
|
#ifndef SQLITE_STMTJRNL_SPILL
|
|
# define SQLITE_STMTJRNL_SPILL (64*1024)
|
|
#endif
|
|
|
|
/*
|
|
** The default lookaside-configuration, the format "SZ,N". SZ is the
|
|
** number of bytes in each lookaside slot (should be a multiple of 8)
|
|
** and N is the number of slots. The lookaside-configuration can be
|
|
** changed as start-time using sqlite3_config(SQLITE_CONFIG_LOOKASIDE)
|
|
** or at run-time for an individual database connection using
|
|
** sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE);
|
|
**
|
|
** With the two-size-lookaside enhancement, less lookaside is required.
|
|
** The default configuration of 1200,40 actually provides 30 1200-byte slots
|
|
** and 93 128-byte slots, which is more lookaside than is available
|
|
** using the older 1200,100 configuration without two-size-lookaside.
|
|
*/
|
|
#ifndef SQLITE_DEFAULT_LOOKASIDE
|
|
# ifdef SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
|
# define SQLITE_DEFAULT_LOOKASIDE 1200,100 /* 120KB of memory */
|
|
# else
|
|
# define SQLITE_DEFAULT_LOOKASIDE 1200,40 /* 48KB of memory */
|
|
# endif
|
|
#endif
|
|
|
|
|
|
/* The default maximum size of an in-memory database created using
|
|
** sqlite3_deserialize()
|
|
*/
|
|
#ifndef SQLITE_MEMDB_DEFAULT_MAXSIZE
|
|
# define SQLITE_MEMDB_DEFAULT_MAXSIZE 1073741824
|
|
#endif
|
|
|
|
/*
|
|
** The following singleton contains the global configuration for
|
|
** the SQLite library.
|
|
*/
|
|
SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config = {
|
|
SQLITE_DEFAULT_MEMSTATUS, /* bMemstat */
|
|
1, /* bCoreMutex */
|
|
SQLITE_THREADSAFE==1, /* bFullMutex */
|
|
SQLITE_USE_URI, /* bOpenUri */
|
|
SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */
|
|
0, /* bSmallMalloc */
|
|
1, /* bExtraSchemaChecks */
|
|
sizeof(LONGDOUBLE_TYPE)>8, /* bUseLongDouble */
|
|
#ifdef SQLITE_DEBUG
|
|
0, /* bJsonSelfcheck */
|
|
#endif
|
|
0x7ffffffe, /* mxStrlen */
|
|
0, /* neverCorrupt */
|
|
SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */
|
|
SQLITE_STMTJRNL_SPILL, /* nStmtSpill */
|
|
{0,0,0,0,0,0,0,0}, /* m */
|
|
{0,0,0,0,0,0,0,0,0}, /* mutex */
|
|
{0,0,0,0,0,0,0,0,0,0,0,0,0},/* pcache2 */
|
|
(void*)0, /* pHeap */
|
|
0, /* nHeap */
|
|
0, 0, /* mnHeap, mxHeap */
|
|
SQLITE_DEFAULT_MMAP_SIZE, /* szMmap */
|
|
SQLITE_MAX_MMAP_SIZE, /* mxMmap */
|
|
(void*)0, /* pPage */
|
|
0, /* szPage */
|
|
SQLITE_DEFAULT_PCACHE_INITSZ, /* nPage */
|
|
0, /* mxParserStack */
|
|
0, /* sharedCacheEnabled */
|
|
SQLITE_SORTER_PMASZ, /* szPma */
|
|
/* All the rest should always be initialized to zero */
|
|
0, /* isInit */
|
|
0, /* inProgress */
|
|
0, /* isMutexInit */
|
|
0, /* isMallocInit */
|
|
0, /* isPCacheInit */
|
|
0, /* nRefInitMutex */
|
|
0, /* pInitMutex */
|
|
0, /* xLog */
|
|
0, /* pLogArg */
|
|
#ifdef SQLITE_ENABLE_SQLLOG
|
|
0, /* xSqllog */
|
|
0, /* pSqllogArg */
|
|
#endif
|
|
#ifdef SQLITE_VDBE_COVERAGE
|
|
0, /* xVdbeBranch */
|
|
0, /* pVbeBranchArg */
|
|
#endif
|
|
#ifndef SQLITE_OMIT_DESERIALIZE
|
|
SQLITE_MEMDB_DEFAULT_MAXSIZE, /* mxMemdbSize */
|
|
#endif
|
|
#ifndef SQLITE_UNTESTABLE
|
|
0, /* xTestCallback */
|
|
#endif
|
|
#ifdef SQLITE_ALLOW_ROWID_IN_VIEW
|
|
0, /* mNoVisibleRowid. 0 == allow rowid-in-view */
|
|
#endif
|
|
0, /* bLocaltimeFault */
|
|
0, /* xAltLocaltime */
|
|
0x7ffffffe, /* iOnceResetThreshold */
|
|
SQLITE_DEFAULT_SORTERREF_SIZE, /* szSorterRef */
|
|
0, /* iPrngSeed */
|
|
#ifdef SQLITE_DEBUG
|
|
{0,0,0,0,0,0}, /* aTune */
|
|
#endif
|
|
};
|
|
|
|
/*
|
|
** Hash table for global functions - functions common to all
|
|
** database connections. After initialization, this table is
|
|
** read-only.
|
|
*/
|
|
SQLITE_PRIVATE FuncDefHash sqlite3BuiltinFunctions;
|
|
|
|
#if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_DEBUG)
|
|
/*
|
|
** Counter used for coverage testing. Does not come into play for
|
|
** release builds.
|
|
**
|
|
** Access to this global variable is not mutex protected. This might
|
|
** result in TSAN warnings. But as the variable does not exist in
|
|
** release builds, that should not be a concern.
|
|
*/
|
|
SQLITE_PRIVATE unsigned int sqlite3CoverageCounter;
|
|
#endif /* SQLITE_COVERAGE_TEST || SQLITE_DEBUG */
|
|
|
|
#ifdef VDBE_PROFILE
|
|
/*
|
|
** The following performance counter can be used in place of
|
|
** sqlite3Hwtime() for profiling. This is a no-op on standard builds.
|
|
*/
|
|
SQLITE_PRIVATE sqlite3_uint64 sqlite3NProfileCnt = 0;
|
|
#endif
|
|
|
|
/*
|
|
** The value of the "pending" byte must be 0x40000000 (1 byte past the
|
|
** 1-gibabyte boundary) in a compatible database. SQLite never uses
|
|
** the database page that contains the pending byte. It never attempts
|
|
** to read or write that page. The pending byte page is set aside
|
|
** for use by the VFS layers as space for managing file locks.
|
|
**
|
|
** During testing, it is often desirable to move the pending byte to
|
|
** a different position in the file. This allows code that has to
|
|
** deal with the pending byte to run on files that are much smaller
|
|
** than 1 GiB. The sqlite3_test_control() interface can be used to
|
|
** move the pending byte.
|
|
**
|
|
** IMPORTANT: Changing the pending byte to any value other than
|
|
** 0x40000000 results in an incompatible database file format!
|
|
** Changing the pending byte during operation will result in undefined
|
|
** and incorrect behavior.
|
|
*/
|
|
#ifndef SQLITE_OMIT_WSD
|
|
SQLITE_PRIVATE int sqlite3PendingByte = 0x40000000;
|
|
#endif
|
|
|
|
/*
|
|
** Tracing flags set by SQLITE_TESTCTRL_TRACEFLAGS.
|
|
*/
|
|
SQLITE_PRIVATE u32 sqlite3TreeTrace = 0;
|
|
SQLITE_PRIVATE u32 sqlite3WhereTrace = 0;
|
|
|
|
/* #include "opcodes.h" */
|
|
/*
|
|
** Properties of opcodes. The OPFLG_INITIALIZER macro is
|
|
** created by mkopcodeh.awk during compilation. Data is obtained
|
|
** from the comments following the "case OP_xxxx:" statements in
|
|
** the vdbe.c file.
|
|
*/
|
|
SQLITE_PRIVATE const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER;
|
|
|
|
/*
|
|
** Name of the default collating sequence
|
|
*/
|
|
SQLITE_PRIVATE const char sqlite3StrBINARY[] = "BINARY";
|
|
|
|
/*
|
|
** Standard typenames. These names must match the COLTYPE_* definitions.
|
|
** Adjust the SQLITE_N_STDTYPE value if adding or removing entries.
|
|
**
|
|
** sqlite3StdType[] The actual names of the datatypes.
|
|
**
|
|
** sqlite3StdTypeLen[] The length (in bytes) of each entry
|
|
** in sqlite3StdType[].
|
|
**
|
|
** sqlite3StdTypeAffinity[] The affinity associated with each entry
|
|
** in sqlite3StdType[].
|
|
*/
|
|
SQLITE_PRIVATE const unsigned char sqlite3StdTypeLen[] = { 3, 4, 3, 7, 4, 4 };
|
|
SQLITE_PRIVATE const char sqlite3StdTypeAffinity[] = {
|
|
SQLITE_AFF_NUMERIC,
|
|
SQLITE_AFF_BLOB,
|
|
SQLITE_AFF_INTEGER,
|
|
SQLITE_AFF_INTEGER,
|
|
SQLITE_AFF_REAL,
|
|
SQLITE_AFF_TEXT
|
|
};
|
|
SQLITE_PRIVATE const char *sqlite3StdType[] = {
|
|
"ANY",
|
|
"BLOB",
|
|
"INT",
|
|
"INTEGER",
|
|
"REAL",
|
|
"TEXT"
|
|
};
|
|
|
|
/************** End of global.c **********************************************/
|
|
/************** Begin file status.c ******************************************/
|
|
/*
|
|
** 2008 June 18
|
|
**
|
|
** 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 module implements the sqlite3_status() interface and related
|
|
** functionality.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
/************** Include vdbeInt.h in the middle of status.c ******************/
|
|
/************** Begin file vdbeInt.h *****************************************/
|
|
/*
|
|
** 2003 September 6
|
|
**
|
|
** The author disclaims copyright to this source code. In place of
|
|
** a legal notice, here is a blessing:
|
|
**
|
|
** May you do good and not evil.
|
|
** May you find forgiveness for yourself and forgive others.
|
|
** May you share freely, never taking more than you give.
|
|
**
|
|
*************************************************************************
|
|
** This is the header file for information that is private to the
|
|
** VDBE. This information used to all be at the top of the single
|
|
** source code file "vdbe.c". When that file became too big (over
|
|
** 6000 lines long) it was split up into several smaller files and
|
|
** this header information was factored out.
|
|
*/
|
|
#ifndef SQLITE_VDBEINT_H
|
|
#define SQLITE_VDBEINT_H
|
|
|
|
/*
|
|
** The maximum number of times that a statement will try to reparse
|
|
** itself before giving up and returning SQLITE_SCHEMA.
|
|
*/
|
|
#ifndef SQLITE_MAX_SCHEMA_RETRY
|
|
# define SQLITE_MAX_SCHEMA_RETRY 50
|
|
#endif
|
|
|
|
/*
|
|
** VDBE_DISPLAY_P4 is true or false depending on whether or not the
|
|
** "explain" P4 display logic is enabled.
|
|
*/
|
|
#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \
|
|
|| defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) \
|
|
|| defined(SQLITE_ENABLE_BYTECODE_VTAB)
|
|
# define VDBE_DISPLAY_P4 1
|
|
#else
|
|
# define VDBE_DISPLAY_P4 0
|
|
#endif
|
|
|
|
/*
|
|
** SQL is translated into a sequence of instructions to be
|
|
** executed by a virtual machine. Each instruction is an instance
|
|
** of the following structure.
|
|
*/
|
|
typedef struct VdbeOp Op;
|
|
|
|
/*
|
|
** Boolean values
|
|
*/
|
|
typedef unsigned Bool;
|
|
|
|
/* Opaque type used by code in vdbesort.c */
|
|
typedef struct VdbeSorter VdbeSorter;
|
|
|
|
/* Elements of the linked list at Vdbe.pAuxData */
|
|
typedef struct AuxData AuxData;
|
|
|
|
/* A cache of large TEXT or BLOB values in a VdbeCursor */
|
|
typedef struct VdbeTxtBlbCache VdbeTxtBlbCache;
|
|
|
|
/* Types of VDBE cursors */
|
|
#define CURTYPE_BTREE 0
|
|
#define CURTYPE_SORTER 1
|
|
#define CURTYPE_VTAB 2
|
|
#define CURTYPE_PSEUDO 3
|
|
|
|
/*
|
|
** A VdbeCursor is an superclass (a wrapper) for various cursor objects:
|
|
**
|
|
** * A b-tree cursor
|
|
** - In the main database or in an ephemeral database
|
|
** - On either an index or a table
|
|
** * A sorter
|
|
** * A virtual table
|
|
** * A one-row "pseudotable" stored in a single register
|
|
*/
|
|
typedef struct VdbeCursor VdbeCursor;
|
|
struct VdbeCursor {
|
|
u8 eCurType; /* One of the CURTYPE_* values above */
|
|
i8 iDb; /* Index of cursor database in db->aDb[] */
|
|
u8 nullRow; /* True if pointing to a row with no data */
|
|
u8 deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
|
|
u8 isTable; /* True for rowid tables. False for indexes */
|
|
#ifdef SQLITE_DEBUG
|
|
u8 seekOp; /* Most recent seek operation on this cursor */
|
|
u8 wrFlag; /* The wrFlag argument to sqlite3BtreeCursor() */
|
|
#endif
|
|
Bool isEphemeral:1; /* True for an ephemeral table */
|
|
Bool useRandomRowid:1; /* Generate new record numbers semi-randomly */
|
|
Bool isOrdered:1; /* True if the table is not BTREE_UNORDERED */
|
|
Bool noReuse:1; /* OpenEphemeral may not reuse this cursor */
|
|
Bool colCache:1; /* pCache pointer is initialized and non-NULL */
|
|
u16 seekHit; /* See the OP_SeekHit and OP_IfNoHope opcodes */
|
|
union { /* pBtx for isEphermeral. pAltMap otherwise */
|
|
Btree *pBtx; /* Separate file holding temporary table */
|
|
u32 *aAltMap; /* Mapping from table to index column numbers */
|
|
} ub;
|
|
i64 seqCount; /* Sequence counter */
|
|
|
|
/* Cached OP_Column parse information is only valid if cacheStatus matches
|
|
** Vdbe.cacheCtr. Vdbe.cacheCtr will never take on the value of
|
|
** CACHE_STALE (0) and so setting cacheStatus=CACHE_STALE guarantees that
|
|
** the cache is out of date. */
|
|
u32 cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */
|
|
int seekResult; /* Result of previous sqlite3BtreeMoveto() or 0
|
|
** if there have been no prior seeks on the cursor. */
|
|
/* seekResult does not distinguish between "no seeks have ever occurred
|
|
** on this cursor" and "the most recent seek was an exact match".
|
|
** For CURTYPE_PSEUDO, seekResult is the register holding the record */
|
|
|
|
/* When a new VdbeCursor is allocated, only the fields above are zeroed.
|
|
** The fields that follow are uninitialized, and must be individually
|
|
** initialized prior to first use. */
|
|
VdbeCursor *pAltCursor; /* Associated index cursor from which to read */
|
|
union {
|
|
BtCursor *pCursor; /* CURTYPE_BTREE or _PSEUDO. Btree cursor */
|
|
sqlite3_vtab_cursor *pVCur; /* CURTYPE_VTAB. Vtab cursor */
|
|
VdbeSorter *pSorter; /* CURTYPE_SORTER. Sorter object */
|
|
} uc;
|
|
KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */
|
|
u32 iHdrOffset; /* Offset to next unparsed byte of the header */
|
|
Pgno pgnoRoot; /* Root page of the open btree cursor */
|
|
i16 nField; /* Number of fields in the header */
|
|
u16 nHdrParsed; /* Number of header fields parsed so far */
|
|
i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
|
|
u32 *aOffset; /* Pointer to aType[nField] */
|
|
const u8 *aRow; /* Data for the current row, if all on one page */
|
|
u32 payloadSize; /* Total number of bytes in the record */
|
|
u32 szRow; /* Byte available in aRow */
|
|
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
|
|
u64 maskUsed; /* Mask of columns used by this cursor */
|
|
#endif
|
|
VdbeTxtBlbCache *pCache; /* Cache of large TEXT or BLOB values */
|
|
|
|
/* 2*nField extra array elements allocated for aType[], beyond the one
|
|
** static element declared in the structure. nField total array slots for
|
|
** aType[] and nField+1 array slots for aOffset[] */
|
|
u32 aType[1]; /* Type values record decode. MUST BE LAST */
|
|
};
|
|
|
|
/* Return true if P is a null-only cursor
|
|
*/
|
|
#define IsNullCursor(P) \
|
|
((P)->eCurType==CURTYPE_PSEUDO && (P)->nullRow && (P)->seekResult==0)
|
|
|
|
/*
|
|
** A value for VdbeCursor.cacheStatus that means the cache is always invalid.
|
|
*/
|
|
#define CACHE_STALE 0
|
|
|
|
/*
|
|
** Large TEXT or BLOB values can be slow to load, so we want to avoid
|
|
** loading them more than once. For that reason, large TEXT and BLOB values
|
|
** can be stored in a cache defined by this object, and attached to the
|
|
** VdbeCursor using the pCache field.
|
|
*/
|
|
struct VdbeTxtBlbCache {
|
|
char *pCValue; /* A RCStr buffer to hold the value */
|
|
i64 iOffset; /* File offset of the row being cached */
|
|
int iCol; /* Column for which the cache is valid */
|
|
u32 cacheStatus; /* Vdbe.cacheCtr value */
|
|
u32 colCacheCtr; /* Column cache counter */
|
|
};
|
|
|
|
/*
|
|
** When a sub-program is executed (OP_Program), a structure of this type
|
|
** is allocated to store the current value of the program counter, as
|
|
** well as the current memory cell array and various other frame specific
|
|
** values stored in the Vdbe struct. When the sub-program is finished,
|
|
** these values are copied back to the Vdbe from the VdbeFrame structure,
|
|
** restoring the state of the VM to as it was before the sub-program
|
|
** began executing.
|
|
**
|
|
** The memory for a VdbeFrame object is allocated and managed by a memory
|
|
** cell in the parent (calling) frame. When the memory cell is deleted or
|
|
** overwritten, the VdbeFrame object is not freed immediately. Instead, it
|
|
** is linked into the Vdbe.pDelFrame list. The contents of the Vdbe.pDelFrame
|
|
** list is deleted when the VM is reset in VdbeHalt(). The reason for doing
|
|
** this instead of deleting the VdbeFrame immediately is to avoid recursive
|
|
** calls to sqlite3VdbeMemRelease() when the memory cells belonging to the
|
|
** child frame are released.
|
|
**
|
|
** The currently executing frame is stored in Vdbe.pFrame. Vdbe.pFrame is
|
|
** set to NULL if the currently executing frame is the main program.
|
|
*/
|
|
typedef struct VdbeFrame VdbeFrame;
|
|
struct VdbeFrame {
|
|
Vdbe *v; /* VM this frame belongs to */
|
|
VdbeFrame *pParent; /* Parent of this frame, or NULL if parent is main */
|
|
Op *aOp; /* Program instructions for parent frame */
|
|
Mem *aMem; /* Array of memory cells for parent frame */
|
|
VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */
|
|
u8 *aOnce; /* Bitmask used by OP_Once */
|
|
void *token; /* Copy of SubProgram.token */
|
|
i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */
|
|
AuxData *pAuxData; /* Linked list of auxdata allocations */
|
|
#if SQLITE_DEBUG
|
|
u32 iFrameMagic; /* magic number for sanity checking */
|
|
#endif
|
|
int nCursor; /* Number of entries in apCsr */
|
|
int pc; /* Program Counter in parent (calling) frame */
|
|
int nOp; /* Size of aOp array */
|
|
int nMem; /* Number of entries in aMem */
|
|
int nChildMem; /* Number of memory cells for child frame */
|
|
int nChildCsr; /* Number of cursors for child frame */
|
|
i64 nChange; /* Statement changes (Vdbe.nChange) */
|
|
i64 nDbChange; /* Value of db->nChange */
|
|
};
|
|
|
|
/* Magic number for sanity checking on VdbeFrame objects */
|
|
#define SQLITE_FRAME_MAGIC 0x879fb71e
|
|
|
|
/*
|
|
** Return a pointer to the array of registers allocated for use
|
|
** by a VdbeFrame.
|
|
*/
|
|
#define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))])
|
|
|
|
/*
|
|
** Internally, the vdbe manipulates nearly all SQL values as Mem
|
|
** structures. Each Mem struct may cache multiple representations (string,
|
|
** integer etc.) of the same value.
|
|
*/
|
|
struct sqlite3_value {
|
|
union MemValue {
|
|
double r; /* Real value used when MEM_Real is set in flags */
|
|
i64 i; /* Integer value used when MEM_Int is set in flags */
|
|
int nZero; /* Extra zero bytes when MEM_Zero and MEM_Blob set */
|
|
const char *zPType; /* Pointer type when MEM_Term|MEM_Subtype|MEM_Null */
|
|
FuncDef *pDef; /* Used only when flags==MEM_Agg */
|
|
} u;
|
|
char *z; /* String or BLOB value */
|
|
int n; /* Number of characters in string value, excluding '\0' */
|
|
u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
|
|
u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
|
|
u8 eSubtype; /* Subtype for this value */
|
|
/* ShallowCopy only needs to copy the information above */
|
|
sqlite3 *db; /* The associated database connection */
|
|
int szMalloc; /* Size of the zMalloc allocation */
|
|
u32 uTemp; /* Transient storage for serial_type in OP_MakeRecord */
|
|
char *zMalloc; /* Space to hold MEM_Str or MEM_Blob if szMalloc>0 */
|
|
void (*xDel)(void*);/* Destructor for Mem.z - only valid if MEM_Dyn */
|
|
#ifdef SQLITE_DEBUG
|
|
Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */
|
|
u16 mScopyFlags; /* flags value immediately after the shallow copy */
|
|
#endif
|
|
};
|
|
|
|
/*
|
|
** Size of struct Mem not including the Mem.zMalloc member or anything that
|
|
** follows.
|
|
*/
|
|
#define MEMCELLSIZE offsetof(Mem,db)
|
|
|
|
/* One or more of the following flags are set to indicate the
|
|
** representations of the value stored in the Mem struct.
|
|
**
|
|
** * MEM_Null An SQL NULL value
|
|
**
|
|
** * MEM_Null|MEM_Zero An SQL NULL with the virtual table
|
|
** UPDATE no-change flag set
|
|
**
|
|
** * MEM_Null|MEM_Term| An SQL NULL, but also contains a
|
|
** MEM_Subtype pointer accessible using
|
|
** sqlite3_value_pointer().
|
|
**
|
|
** * MEM_Null|MEM_Cleared Special SQL NULL that compares non-equal
|
|
** to other NULLs even using the IS operator.
|
|
**
|
|
** * MEM_Str A string, stored in Mem.z with
|
|
** length Mem.n. Zero-terminated if
|
|
** MEM_Term is set. This flag is
|
|
** incompatible with MEM_Blob and
|
|
** MEM_Null, but can appear with MEM_Int,
|
|
** MEM_Real, and MEM_IntReal.
|
|
**
|
|
** * MEM_Blob A blob, stored in Mem.z length Mem.n.
|
|
** Incompatible with MEM_Str, MEM_Null,
|
|
** MEM_Int, MEM_Real, and MEM_IntReal.
|
|
**
|
|
** * MEM_Blob|MEM_Zero A blob in Mem.z of length Mem.n plus
|
|
** MEM.u.i extra 0x00 bytes at the end.
|
|
**
|
|
** * MEM_Int Integer stored in Mem.u.i.
|
|
**
|
|
** * MEM_Real Real stored in Mem.u.r.
|
|
**
|
|
** * MEM_IntReal Real stored as an integer in Mem.u.i.
|
|
**
|
|
** If the MEM_Null flag is set, then the value is an SQL NULL value.
|
|
** For a pointer type created using sqlite3_bind_pointer() or
|
|
** sqlite3_result_pointer() the MEM_Term and MEM_Subtype flags are also set.
|
|
**
|
|
** If the MEM_Str flag is set then Mem.z points at a string representation.
|
|
** Usually this is encoded in the same unicode encoding as the main
|
|
** database (see below for exceptions). If the MEM_Term flag is also
|
|
** set, then the string is nul terminated. The MEM_Int and MEM_Real
|
|
** flags may coexist with the MEM_Str flag.
|
|
*/
|
|
#define MEM_Undefined 0x0000 /* Value is undefined */
|
|
#define MEM_Null 0x0001 /* Value is NULL (or a pointer) */
|
|
#define MEM_Str 0x0002 /* Value is a string */
|
|
#define MEM_Int 0x0004 /* Value is an integer */
|
|
#define MEM_Real 0x0008 /* Value is a real number */
|
|
#define MEM_Blob 0x0010 /* Value is a BLOB */
|
|
#define MEM_IntReal 0x0020 /* MEM_Int that stringifies like MEM_Real */
|
|
#define MEM_AffMask 0x003f /* Mask of affinity bits */
|
|
|
|
/* Extra bits that modify the meanings of the core datatypes above
|
|
*/
|
|
#define MEM_FromBind 0x0040 /* Value originates from sqlite3_bind() */
|
|
/* 0x0080 // Available */
|
|
#define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */
|
|
#define MEM_Term 0x0200 /* String in Mem.z is zero terminated */
|
|
#define MEM_Zero 0x0400 /* Mem.i contains count of 0s appended to blob */
|
|
#define MEM_Subtype 0x0800 /* Mem.eSubtype is valid */
|
|
#define MEM_TypeMask 0x0dbf /* Mask of type bits */
|
|
|
|
/* Bits that determine the storage for Mem.z for a string or blob or
|
|
** aggregate accumulator.
|
|
*/
|
|
#define MEM_Dyn 0x1000 /* Need to call Mem.xDel() on Mem.z */
|
|
#define MEM_Static 0x2000 /* Mem.z points to a static string */
|
|
#define MEM_Ephem 0x4000 /* Mem.z points to an ephemeral string */
|
|
#define MEM_Agg 0x8000 /* Mem.z points to an agg function context */
|
|
|
|
/* Return TRUE if Mem X contains dynamically allocated content - anything
|
|
** that needs to be deallocated to avoid a leak.
|
|
*/
|
|
#define VdbeMemDynamic(X) \
|
|
(((X)->flags&(MEM_Agg|MEM_Dyn))!=0)
|
|
|
|
/*
|
|
** Clear any existing type flags from a Mem and replace them with f
|
|
*/
|
|
#define MemSetTypeFlag(p, f) \
|
|
((p)->flags = ((p)->flags&~(MEM_TypeMask|MEM_Zero))|f)
|
|
|
|
/*
|
|
** True if Mem X is a NULL-nochng type.
|
|
*/
|
|
#define MemNullNochng(X) \
|
|
(((X)->flags&MEM_TypeMask)==(MEM_Null|MEM_Zero) \
|
|
&& (X)->n==0 && (X)->u.nZero==0)
|
|
|
|
/*
|
|
** Return true if a memory cell has been initialized and is valid.
|
|
** is for use inside assert() statements only.
|
|
**
|
|
** A Memory cell is initialized if at least one of the
|
|
** MEM_Null, MEM_Str, MEM_Int, MEM_Real, MEM_Blob, or MEM_IntReal bits
|
|
** is set. It is "undefined" if all those bits are zero.
|
|
*/
|
|
#ifdef SQLITE_DEBUG
|
|
#define memIsValid(M) ((M)->flags & MEM_AffMask)!=0
|
|
#endif
|
|
|
|
/*
|
|
** Each auxiliary data pointer stored by a user defined function
|
|
** implementation calling sqlite3_set_auxdata() is stored in an instance
|
|
** of this structure. All such structures associated with a single VM
|
|
** are stored in a linked list headed at Vdbe.pAuxData. All are destroyed
|
|
** when the VM is halted (if not before).
|
|
*/
|
|
struct AuxData {
|
|
int iAuxOp; /* Instruction number of OP_Function opcode */
|
|
int iAuxArg; /* Index of function argument. */
|
|
void *pAux; /* Aux data pointer */
|
|
void (*xDeleteAux)(void*); /* Destructor for the aux data */
|
|
AuxData *pNextAux; /* Next element in list */
|
|
};
|
|
|
|
/*
|
|
** The "context" argument for an installable function. A pointer to an
|
|
** instance of this structure is the first argument to the routines used
|
|
** implement the SQL functions.
|
|
**
|
|
** There is a typedef for this structure in sqlite.h. So all routines,
|
|
** even the public interface to SQLite, can use a pointer to this structure.
|
|
** But this file is the only place where the internal details of this
|
|
** structure are known.
|
|
**
|
|
** This structure is defined inside of vdbeInt.h because it uses substructures
|
|
** (Mem) which are only defined there.
|
|
*/
|
|
struct sqlite3_context {
|
|
Mem *pOut; /* The return value is stored here */
|
|
FuncDef *pFunc; /* Pointer to function information */
|
|
Mem *pMem; /* Memory cell used to store aggregate context */
|
|
Vdbe *pVdbe; /* The VM that owns this context */
|
|
int iOp; /* Instruction number of OP_Function */
|
|
int isError; /* Error code returned by the function. */
|
|
u8 enc; /* Encoding to use for results */
|
|
u8 skipFlag; /* Skip accumulator loading if true */
|
|
u8 argc; /* Number of arguments */
|
|
sqlite3_value *argv[1]; /* Argument set */
|
|
};
|
|
|
|
/* A bitfield type for use inside of structures. Always follow with :N where
|
|
** N is the number of bits.
|
|
*/
|
|
typedef unsigned bft; /* Bit Field Type */
|
|
|
|
/* The ScanStatus object holds a single value for the
|
|
** sqlite3_stmt_scanstatus() interface.
|
|
**
|
|
** aAddrRange[]:
|
|
** This array is used by ScanStatus elements associated with EQP
|
|
** notes that make an SQLITE_SCANSTAT_NCYCLE value available. It is
|
|
** an array of up to 3 ranges of VM addresses for which the Vdbe.anCycle[]
|
|
** values should be summed to calculate the NCYCLE value. Each pair of
|
|
** integer addresses is a start and end address (both inclusive) for a range
|
|
** instructions. A start value of 0 indicates an empty range.
|
|
*/
|
|
typedef struct ScanStatus ScanStatus;
|
|
struct ScanStatus {
|
|
int addrExplain; /* OP_Explain for loop */
|
|
int aAddrRange[6];
|
|
int addrLoop; /* Address of "loops" counter */
|
|
int addrVisit; /* Address of "rows visited" counter */
|
|
int iSelectID; /* The "Select-ID" for this loop */
|
|
LogEst nEst; /* Estimated output rows per loop */
|
|
char *zName; /* Name of table or index */
|
|
};
|
|
|
|
/* The DblquoteStr object holds the text of a double-quoted
|
|
** string for a prepared statement. A linked list of these objects
|
|
** is constructed during statement parsing and is held on Vdbe.pDblStr.
|
|
** When computing a normalized SQL statement for an SQL statement, that
|
|
** list is consulted for each double-quoted identifier to see if the
|
|
** identifier should really be a string literal.
|
|
*/
|
|
typedef struct DblquoteStr DblquoteStr;
|
|
struct DblquoteStr {
|
|
DblquoteStr *pNextStr; /* Next string literal in the list */
|
|
char z[8]; /* Dequoted value for the string */
|
|
};
|
|
|
|
/*
|
|
** An instance of the virtual machine. This structure contains the complete
|
|
** state of the virtual machine.
|
|
**
|
|
** The "sqlite3_stmt" structure pointer that is returned by sqlite3_prepare()
|
|
** is really a pointer to an instance of this structure.
|
|
*/
|
|
struct Vdbe {
|
|
sqlite3 *db; /* The database connection that owns this statement */
|
|
Vdbe **ppVPrev,*pVNext; /* Linked list of VDBEs with the same Vdbe.db */
|
|
Parse *pParse; /* Parsing context used to create this Vdbe */
|
|
ynVar nVar; /* Number of entries in aVar[] */
|
|
int nMem; /* Number of memory locations currently allocated */
|
|
int nCursor; /* Number of slots in apCsr[] */
|
|
u32 cacheCtr; /* VdbeCursor row cache generation counter */
|
|
int pc; /* The program counter */
|
|
int rc; /* Value to return */
|
|
i64 nChange; /* Number of db changes made since last reset */
|
|
int iStatement; /* Statement number (or 0 if has no opened stmt) */
|
|
i64 iCurrentTime; /* Value of julianday('now') for this statement */
|
|
i64 nFkConstraint; /* Number of imm. FK constraints this VM */
|
|
i64 nStmtDefCons; /* Number of def. constraints when stmt started */
|
|
i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */
|
|
Mem *aMem; /* The memory locations */
|
|
Mem **apArg; /* Arguments to currently executing user function */
|
|
VdbeCursor **apCsr; /* One element of this array for each open cursor */
|
|
Mem *aVar; /* Values for the OP_Variable opcode. */
|
|
|
|
/* When allocating a new Vdbe object, all of the fields below should be
|
|
** initialized to zero or NULL */
|
|
|
|
Op *aOp; /* Space to hold the virtual machine's program */
|
|
int nOp; /* Number of instructions in the program */
|
|
int nOpAlloc; /* Slots allocated for aOp[] */
|
|
Mem *aColName; /* Column names to return */
|
|
Mem *pResultRow; /* Current output row */
|
|
char *zErrMsg; /* Error message written here */
|
|
VList *pVList; /* Name of variables */
|
|
#ifndef SQLITE_OMIT_TRACE
|
|
i64 startTime; /* Time when query started - used for profiling */
|
|
#endif
|
|
#ifdef SQLITE_DEBUG
|
|
int rcApp; /* errcode set by sqlite3_result_error_code() */
|
|
u32 nWrite; /* Number of write operations that have occurred */
|
|
#endif
|
|
u16 nResColumn; /* Number of columns in one row of the result set */
|
|
u16 nResAlloc; /* Column slots allocated to aColName[] */
|
|
u8 errorAction; /* Recovery action to do in case of an error */
|
|
u8 minWriteFileFormat; /* Minimum file format for writable database files */
|
|
u8 prepFlags; /* SQLITE_PREPARE_* flags */
|
|
u8 eVdbeState; /* On of the VDBE_*_STATE values */
|
|
bft expired:2; /* 1: recompile VM immediately 2: when convenient */
|
|
bft explain:2; /* 0: normal, 1: EXPLAIN, 2: EXPLAIN QUERY PLAN */
|
|
bft changeCntOn:1; /* True to update the change-counter */
|
|
bft usesStmtJournal:1; /* True if uses a statement journal */
|
|
bft readOnly:1; /* True for statements that do not write */
|
|
bft bIsReader:1; /* True for statements that read */
|
|
bft haveEqpOps:1; /* Bytecode supports EXPLAIN QUERY PLAN */
|
|
yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */
|
|
yDbMask lockMask; /* Subset of btreeMask that requires a lock */
|
|
u32 aCounter[9]; /* Counters used by sqlite3_stmt_status() */
|
|
char *zSql; /* Text of the SQL statement that generated this */
|
|
#ifdef SQLITE_ENABLE_NORMALIZE
|
|
char *zNormSql; /* Normalization of the associated SQL statement */
|
|
DblquoteStr *pDblStr; /* List of double-quoted string literals */
|
|
#endif
|
|
void *pFree; /* Free this when deleting the vdbe */
|
|
VdbeFrame *pFrame; /* Parent frame */
|
|
VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */
|
|
int nFrame; /* Number of frames in pFrame list */
|
|
u32 expmask; /* Binding to these vars invalidates VM */
|
|
SubProgram *pProgram; /* Linked list of all sub-programs used by VM */
|
|
AuxData *pAuxData; /* Linked list of auxdata allocations */
|
|
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
|
int nScan; /* Entries in aScan[] */
|
|
ScanStatus *aScan; /* Scan definitions for sqlite3_stmt_scanstatus() */
|
|
#endif
|
|
};
|
|
|
|
/*
|
|
** The following are allowed values for Vdbe.eVdbeState
|
|
*/
|
|
#define VDBE_INIT_STATE 0 /* Prepared statement under construction */
|
|
#define VDBE_READY_STATE 1 /* Ready to run but not yet started */
|
|
#define VDBE_RUN_STATE 2 /* Run in progress */
|
|
#define VDBE_HALT_STATE 3 /* Finished. Need reset() or finalize() */
|
|
|
|
/*
|
|
** Structure used to store the context required by the
|
|
** sqlite3_preupdate_*() API functions.
|
|
*/
|
|
struct PreUpdate {
|
|
Vdbe *v;
|
|
VdbeCursor *pCsr; /* Cursor to read old values from */
|
|
int op; /* One of SQLITE_INSERT, UPDATE, DELETE */
|
|
u8 *aRecord; /* old.* database record */
|
|
KeyInfo keyinfo;
|
|
UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */
|
|
UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */
|
|
int iNewReg; /* Register for new.* values */
|
|
int iBlobWrite; /* Value returned by preupdate_blobwrite() */
|
|
i64 iKey1; /* First key value passed to hook */
|
|
i64 iKey2; /* Second key value passed to hook */
|
|
Mem *aNew; /* Array of new.* values */
|
|
Table *pTab; /* Schema object being updated */
|
|
Index *pPk; /* PK index if pTab is WITHOUT ROWID */
|
|
};
|
|
|
|
/*
|
|
** An instance of this object is used to pass an vector of values into
|
|
** OP_VFilter, the xFilter method of a virtual table. The vector is the
|
|
** set of values on the right-hand side of an IN constraint.
|
|
**
|
|
** The value as passed into xFilter is an sqlite3_value with a "pointer"
|
|
** type, such as is generated by sqlite3_result_pointer() and read by
|
|
** sqlite3_value_pointer. Such values have MEM_Term|MEM_Subtype|MEM_Null
|
|
** and a subtype of 'p'. The sqlite3_vtab_in_first() and _next() interfaces
|
|
** know how to use this object to step through all the values in the
|
|
** right operand of the IN constraint.
|
|
*/
|
|
typedef struct ValueList ValueList;
|
|
struct ValueList {
|
|
BtCursor *pCsr; /* An ephemeral table holding all values */
|
|
sqlite3_value *pOut; /* Register to hold each decoded output value */
|
|
};
|
|
|
|
/* Size of content associated with serial types that fit into a
|
|
** single-byte varint.
|
|
*/
|
|
#ifndef SQLITE_AMALGAMATION
|
|
SQLITE_PRIVATE const u8 sqlite3SmallTypeSizes[];
|
|
#endif
|
|
|
|
/*
|
|
** Function prototypes
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3VdbeError(Vdbe*, const char *, ...);
|
|
SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*);
|
|
SQLITE_PRIVATE void sqlite3VdbeFreeCursorNN(Vdbe*,VdbeCursor*);
|
|
void sqliteVdbePopStack(Vdbe*,int);
|
|
SQLITE_PRIVATE int SQLITE_NOINLINE sqlite3VdbeHandleMovedCursor(VdbeCursor *p);
|
|
SQLITE_PRIVATE int SQLITE_NOINLINE sqlite3VdbeFinishMoveto(VdbeCursor*);
|
|
SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor*);
|
|
SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32);
|
|
SQLITE_PRIVATE u8 sqlite3VdbeOneByteSerialTypeLen(u8);
|
|
#ifdef SQLITE_MIXED_ENDIAN_64BIT_FLOAT
|
|
SQLITE_PRIVATE u64 sqlite3FloatSwap(u64 in);
|
|
# define swapMixedEndianFloat(X) X = sqlite3FloatSwap(X)
|
|
#else
|
|
# define swapMixedEndianFloat(X)
|
|
#endif
|
|
SQLITE_PRIVATE void sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
|
|
SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(sqlite3*, AuxData**, int, int);
|
|
|
|
int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
|
|
SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(sqlite3*,VdbeCursor*,UnpackedRecord*,int*);
|
|
SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor*, i64*);
|
|
SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*);
|
|
#if !defined(SQLITE_OMIT_EXPLAIN) || defined(SQLITE_ENABLE_BYTECODE_VTAB)
|
|
SQLITE_PRIVATE int sqlite3VdbeNextOpcode(Vdbe*,Mem*,int,int*,int*,Op**);
|
|
SQLITE_PRIVATE char *sqlite3VdbeDisplayP4(sqlite3*,Op*);
|
|
#endif
|
|
#if defined(SQLITE_ENABLE_EXPLAIN_COMMENTS)
|
|
SQLITE_PRIVATE char *sqlite3VdbeDisplayComment(sqlite3*,const Op*,const char*);
|
|
#endif
|
|
#if !defined(SQLITE_OMIT_EXPLAIN)
|
|
SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*);
|
|
#endif
|
|
SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*);
|
|
SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *, int);
|
|
SQLITE_PRIVATE int sqlite3VdbeMemTooBig(Mem*);
|
|
SQLITE_PRIVATE int sqlite3VdbeMemCopy(Mem*, const Mem*);
|
|
SQLITE_PRIVATE void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int);
|
|
SQLITE_PRIVATE void sqlite3VdbeMemMove(Mem*, Mem*);
|
|
SQLITE_PRIVATE int sqlite3VdbeMemNulTerminate(Mem*);
|
|
SQLITE_PRIVATE int sqlite3VdbeMemSetStr(Mem*, const char*, i64, u8, void(*)(void*));
|
|
SQLITE_PRIVATE void sqlite3VdbeMemSetInt64(Mem*, i64);
|
|
#ifdef SQLITE_OMIT_FLOATING_POINT
|
|
# define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64
|
|
#else
|
|
SQLITE_PRIVATE void sqlite3VdbeMemSetDouble(Mem*, double);
|
|
#endif
|
|
SQLITE_PRIVATE void sqlite3VdbeMemSetPointer(Mem*, void*, const char*, void(*)(void*));
|
|
SQLITE_PRIVATE void sqlite3VdbeMemInit(Mem*,sqlite3*,u16);
|
|
SQLITE_PRIVATE void sqlite3VdbeMemSetNull(Mem*);
|
|
#ifndef SQLITE_OMIT_INCRBLOB
|
|
SQLITE_PRIVATE void sqlite3VdbeMemSetZeroBlob(Mem*,int);
|
|
#else
|
|
SQLITE_PRIVATE int sqlite3VdbeMemSetZeroBlob(Mem*,int);
|
|
#endif
|
|
#ifdef SQLITE_DEBUG
|
|
SQLITE_PRIVATE int sqlite3VdbeMemIsRowSet(const Mem*);
|
|
#endif
|
|
SQLITE_PRIVATE int sqlite3VdbeMemSetRowSet(Mem*);
|
|
SQLITE_PRIVATE void sqlite3VdbeMemZeroTerminateIfAble(Mem*);
|
|
SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem*);
|
|
SQLITE_PRIVATE int sqlite3VdbeMemStringify(Mem*, u8, u8);
|
|
SQLITE_PRIVATE int sqlite3IntFloatCompare(i64,double);
|
|
SQLITE_PRIVATE i64 sqlite3VdbeIntValue(const Mem*);
|
|
SQLITE_PRIVATE int sqlite3VdbeMemIntegerify(Mem*);
|
|
SQLITE_PRIVATE double sqlite3VdbeRealValue(Mem*);
|
|
SQLITE_PRIVATE int sqlite3VdbeBooleanValue(Mem*, int ifNull);
|
|
SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*);
|
|
SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*);
|
|
SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*);
|
|
SQLITE_PRIVATE int sqlite3VdbeMemCast(Mem*,u8,u8);
|
|
SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,Mem*);
|
|
SQLITE_PRIVATE int sqlite3VdbeMemFromBtreeZeroOffset(BtCursor*,u32,Mem*);
|
|
SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p);
|
|
SQLITE_PRIVATE void sqlite3VdbeMemReleaseMalloc(Mem*p);
|
|
SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
|
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
SQLITE_PRIVATE int sqlite3VdbeMemAggValue(Mem*, Mem*, FuncDef*);
|
|
#endif
|
|
#if !defined(SQLITE_OMIT_EXPLAIN) || defined(SQLITE_ENABLE_BYTECODE_VTAB)
|
|
SQLITE_PRIVATE const char *sqlite3OpcodeName(int);
|
|
#endif
|
|
SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
|
|
SQLITE_PRIVATE int sqlite3VdbeMemClearAndResize(Mem *pMem, int n);
|
|
SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *, int);
|
|
#ifdef SQLITE_DEBUG
|
|
SQLITE_PRIVATE int sqlite3VdbeFrameIsValid(VdbeFrame*);
|
|
#endif
|
|
SQLITE_PRIVATE void sqlite3VdbeFrameMemDel(void*); /* Destructor on Mem */
|
|
SQLITE_PRIVATE void sqlite3VdbeFrameDelete(VdbeFrame*); /* Actually deletes the Frame */
|
|
SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *);
|
|
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
|
|
SQLITE_PRIVATE void sqlite3VdbePreUpdateHook(
|
|
Vdbe*,VdbeCursor*,int,const char*,Table*,i64,int,int);
|
|
#endif
|
|
SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p);
|
|
|
|
SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, int, VdbeCursor *);
|
|
SQLITE_PRIVATE void sqlite3VdbeSorterReset(sqlite3 *, VdbeSorter *);
|
|
SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
|
|
SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
|
|
SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *);
|
|
SQLITE_PRIVATE int sqlite3VdbeSorterRewind(const VdbeCursor *, int *);
|
|
SQLITE_PRIVATE int sqlite3VdbeSorterWrite(const VdbeCursor *, Mem *);
|
|
SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *);
|
|
|
|
SQLITE_PRIVATE void sqlite3VdbeValueListFree(void*);
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
SQLITE_PRIVATE void sqlite3VdbeIncrWriteCounter(Vdbe*, VdbeCursor*);
|
|
SQLITE_PRIVATE void sqlite3VdbeAssertAbortable(Vdbe*);
|
|
#else
|
|
# define sqlite3VdbeIncrWriteCounter(V,C)
|
|
# define sqlite3VdbeAssertAbortable(V)
|
|
#endif
|
|
|
|
#if !defined(SQLITE_OMIT_SHARED_CACHE)
|
|
SQLITE_PRIVATE void sqlite3VdbeEnter(Vdbe*);
|
|
#else
|
|
# define sqlite3VdbeEnter(X)
|
|
#endif
|
|
|
|
#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
|
|
SQLITE_PRIVATE void sqlite3VdbeLeave(Vdbe*);
|
|
#else
|
|
# define sqlite3VdbeLeave(X)
|
|
#endif
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe*,Mem*);
|
|
SQLITE_PRIVATE int sqlite3VdbeCheckMemInvariants(Mem*);
|
|
#endif
|
|
|
|
#ifndef SQLITE_OMIT_FOREIGN_KEY
|
|
SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *, int);
|
|
#else
|
|
# define sqlite3VdbeCheckFk(p,i) 0
|
|
#endif
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
SQLITE_PRIVATE void sqlite3VdbePrintSql(Vdbe*);
|
|
SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, StrAccum *pStr);
|
|
#endif
|
|
#ifndef SQLITE_OMIT_UTF16
|
|
SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem*, u8);
|
|
SQLITE_PRIVATE int sqlite3VdbeMemHandleBom(Mem *pMem);
|
|
#endif
|
|
|
|
#ifndef SQLITE_OMIT_INCRBLOB
|
|
SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *);
|
|
#define ExpandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0)
|
|
#else
|
|
#define sqlite3VdbeMemExpandBlob(x) SQLITE_OK
|
|
#define ExpandBlob(P) SQLITE_OK
|
|
#endif
|
|
|
|
#endif /* !defined(SQLITE_VDBEINT_H) */
|
|
|
|
/************** End of vdbeInt.h *********************************************/
|
|
/************** Continuing where we left off in status.c *********************/
|
|
|
|
/*
|
|
** Variables in which to record status information.
|
|
*/
|
|
#if SQLITE_PTRSIZE>4
|
|
typedef sqlite3_int64 sqlite3StatValueType;
|
|
#else
|
|
typedef u32 sqlite3StatValueType;
|
|
#endif
|
|
typedef struct sqlite3StatType sqlite3StatType;
|
|
static SQLITE_WSD struct sqlite3StatType {
|
|
sqlite3StatValueType nowValue[10]; /* Current value */
|
|
sqlite3StatValueType mxValue[10]; /* Maximum value */
|
|
} sqlite3Stat = { {0,}, {0,} };
|
|
|
|
/*
|
|
** Elements of sqlite3Stat[] are protected by either the memory allocator
|
|
** mutex, or by the pcache1 mutex. The following array determines which.
|
|
*/
|
|
static const char statMutex[] = {
|
|
0, /* SQLITE_STATUS_MEMORY_USED */
|
|
1, /* SQLITE_STATUS_PAGECACHE_USED */
|
|
1, /* SQLITE_STATUS_PAGECACHE_OVERFLOW */
|
|
0, /* SQLITE_STATUS_SCRATCH_USED */
|
|
0, /* SQLITE_STATUS_SCRATCH_OVERFLOW */
|
|
0, /* SQLITE_STATUS_MALLOC_SIZE */
|
|
0, /* SQLITE_STATUS_PARSER_STACK */
|
|
1, /* SQLITE_STATUS_PAGECACHE_SIZE */
|
|
0, /* SQLITE_STATUS_SCRATCH_SIZE */
|
|
0, /* SQLITE_STATUS_MALLOC_COUNT */
|
|
};
|
|
|
|
|
|
/* The "wsdStat" macro will resolve to the status information
|
|
** state vector. If writable static data is unsupported on the target,
|
|
** we have to locate the state vector at run-time. In the more common
|
|
** case where writable static data is supported, wsdStat can refer directly
|
|
** to the "sqlite3Stat" state vector declared above.
|
|
*/
|
|
#ifdef SQLITE_OMIT_WSD
|
|
# define wsdStatInit sqlite3StatType *x = &GLOBAL(sqlite3StatType,sqlite3Stat)
|
|
# define wsdStat x[0]
|
|
#else
|
|
# define wsdStatInit
|
|
# define wsdStat sqlite3Stat
|
|
#endif
|
|
|
|
/*
|
|
** Return the current value of a status parameter. The caller must
|
|
** be holding the appropriate mutex.
|
|
*/
|
|
SQLITE_PRIVATE sqlite3_int64 sqlite3StatusValue(int op){
|
|
wsdStatInit;
|
|
assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
|
|
assert( op>=0 && op<ArraySize(statMutex) );
|
|
assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
|
|
: sqlite3MallocMutex()) );
|
|
return wsdStat.nowValue[op];
|
|
}
|
|
|
|
/*
|
|
** Add N to the value of a status record. The caller must hold the
|
|
** appropriate mutex. (Locking is checked by assert()).
|
|
**
|
|
** The StatusUp() routine can accept positive or negative values for N.
|
|
** The value of N is added to the current status value and the high-water
|
|
** mark is adjusted if necessary.
|
|
**
|
|
** The StatusDown() routine lowers the current value by N. The highwater
|
|
** mark is unchanged. N must be non-negative for StatusDown().
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3StatusUp(int op, int N){
|
|
wsdStatInit;
|
|
assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
|
|
assert( op>=0 && op<ArraySize(statMutex) );
|
|
assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
|
|
: sqlite3MallocMutex()) );
|
|
wsdStat.nowValue[op] += N;
|
|
if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
|
|
wsdStat.mxValue[op] = wsdStat.nowValue[op];
|
|
}
|
|
}
|
|
SQLITE_PRIVATE void sqlite3StatusDown(int op, int N){
|
|
wsdStatInit;
|
|
assert( N>=0 );
|
|
assert( op>=0 && op<ArraySize(statMutex) );
|
|
assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
|
|
: sqlite3MallocMutex()) );
|
|
assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
|
|
wsdStat.nowValue[op] -= N;
|
|
}
|
|
|
|
/*
|
|
** Adjust the highwater mark if necessary.
|
|
** The caller must hold the appropriate mutex.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3StatusHighwater(int op, int X){
|
|
sqlite3StatValueType newValue;
|
|
wsdStatInit;
|
|
assert( X>=0 );
|
|
newValue = (sqlite3StatValueType)X;
|
|
assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
|
|
assert( op>=0 && op<ArraySize(statMutex) );
|
|
assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
|
|
: sqlite3MallocMutex()) );
|
|
assert( op==SQLITE_STATUS_MALLOC_SIZE
|
|
|| op==SQLITE_STATUS_PAGECACHE_SIZE
|
|
|| op==SQLITE_STATUS_PARSER_STACK );
|
|
if( newValue>wsdStat.mxValue[op] ){
|
|
wsdStat.mxValue[op] = newValue;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Query status information.
|
|
*/
|
|
SQLITE_API int sqlite3_status64(
|
|
int op,
|
|
sqlite3_int64 *pCurrent,
|
|
sqlite3_int64 *pHighwater,
|
|
int resetFlag
|
|
){
|
|
sqlite3_mutex *pMutex;
|
|
wsdStatInit;
|
|
if( op<0 || op>=ArraySize(wsdStat.nowValue) ){
|
|
return SQLITE_MISUSE_BKPT;
|
|
}
|
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
|
if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT;
|
|
#endif
|
|
pMutex = statMutex[op] ? sqlite3Pcache1Mutex() : sqlite3MallocMutex();
|
|
sqlite3_mutex_enter(pMutex);
|
|
*pCurrent = wsdStat.nowValue[op];
|
|
*pHighwater = wsdStat.mxValue[op];
|
|
if( resetFlag ){
|
|
wsdStat.mxValue[op] = wsdStat.nowValue[op];
|
|
}
|
|
sqlite3_mutex_leave(pMutex);
|
|
(void)pMutex; /* Prevent warning when SQLITE_THREADSAFE=0 */
|
|
return SQLITE_OK;
|
|
}
|
|
SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
|
|
sqlite3_int64 iCur = 0, iHwtr = 0;
|
|
int rc;
|
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
|
if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT;
|
|
#endif
|
|
rc = sqlite3_status64(op, &iCur, &iHwtr, resetFlag);
|
|
if( rc==0 ){
|
|
*pCurrent = (int)iCur;
|
|
*pHighwater = (int)iHwtr;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Return the number of LookasideSlot elements on the linked list
|
|
*/
|
|
static u32 countLookasideSlots(LookasideSlot *p){
|
|
u32 cnt = 0;
|
|
while( p ){
|
|
p = p->pNext;
|
|
cnt++;
|
|
}
|
|
return cnt;
|
|
}
|
|
|
|
/*
|
|
** Count the number of slots of lookaside memory that are outstanding
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3LookasideUsed(sqlite3 *db, int *pHighwater){
|
|
u32 nInit = countLookasideSlots(db->lookaside.pInit);
|
|
u32 nFree = countLookasideSlots(db->lookaside.pFree);
|
|
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
|
nInit += countLookasideSlots(db->lookaside.pSmallInit);
|
|
nFree += countLookasideSlots(db->lookaside.pSmallFree);
|
|
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
|
|
if( pHighwater ) *pHighwater = db->lookaside.nSlot - nInit;
|
|
return db->lookaside.nSlot - (nInit+nFree);
|
|
}
|
|
|
|
/*
|
|
** Query status information for a single database connection
|
|
*/
|
|
SQLITE_API int sqlite3_db_status(
|
|
sqlite3 *db, /* The database connection whose status is desired */
|
|
int op, /* Status verb */
|
|
int *pCurrent, /* Write current value here */
|
|
int *pHighwater, /* Write high-water mark here */
|
|
int resetFlag /* Reset high-water mark if true */
|
|
){
|
|
int rc = SQLITE_OK; /* Return code */
|
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
|
if( !sqlite3SafetyCheckOk(db) || pCurrent==0|| pHighwater==0 ){
|
|
return SQLITE_MISUSE_BKPT;
|
|
}
|
|
#endif
|
|
sqlite3_mutex_enter(db->mutex);
|
|
switch( op ){
|
|
case SQLITE_DBSTATUS_LOOKASIDE_USED: {
|
|
*pCurrent = sqlite3LookasideUsed(db, pHighwater);
|
|
if( resetFlag ){
|
|
LookasideSlot *p = db->lookaside.pFree;
|
|
if( p ){
|
|
while( p->pNext ) p = p->pNext;
|
|
p->pNext = db->lookaside.pInit;
|
|
db->lookaside.pInit = db->lookaside.pFree;
|
|
db->lookaside.pFree = 0;
|
|
}
|
|
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
|
p = db->lookaside.pSmallFree;
|
|
if( p ){
|
|
while( p->pNext ) p = p->pNext;
|
|
p->pNext = db->lookaside.pSmallInit;
|
|
db->lookaside.pSmallInit = db->lookaside.pSmallFree;
|
|
db->lookaside.pSmallFree = 0;
|
|
}
|
|
#endif
|
|
}
|
|
break;
|
|
}
|
|
|
|
case SQLITE_DBSTATUS_LOOKASIDE_HIT:
|
|
case SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE:
|
|
case SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL: {
|
|
testcase( op==SQLITE_DBSTATUS_LOOKASIDE_HIT );
|
|
testcase( op==SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE );
|
|
testcase( op==SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL );
|
|
assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)>=0 );
|
|
assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)<3 );
|
|
*pCurrent = 0;
|
|
*pHighwater = db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT];
|
|
if( resetFlag ){
|
|
db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT] = 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
/*
|
|
** Return an approximation for the amount of memory currently used
|
|
** by all pagers associated with the given database connection. The
|
|
** highwater mark is meaningless and is returned as zero.
|
|
*/
|
|
case SQLITE_DBSTATUS_CACHE_USED_SHARED:
|
|
case SQLITE_DBSTATUS_CACHE_USED: {
|
|
int totalUsed = 0;
|
|
int i;
|
|
sqlite3BtreeEnterAll(db);
|
|
for(i=0; i<db->nDb; i++){
|
|
Btree *pBt = db->aDb[i].pBt;
|
|
if( pBt ){
|
|
Pager *pPager = sqlite3BtreePager(pBt);
|
|
int nByte = sqlite3PagerMemUsed(pPager);
|
|
if( op==SQLITE_DBSTATUS_CACHE_USED_SHARED ){
|
|
nByte = nByte / sqlite3BtreeConnectionCount(pBt);
|
|
}
|
|
totalUsed += nByte;
|
|
}
|
|
}
|
|
sqlite3BtreeLeaveAll(db);
|
|
*pCurrent = totalUsed;
|
|
*pHighwater = 0;
|
|
break;
|
|
}
|
|
|
|
/*
|
|
** *pCurrent gets an accurate estimate of the amount of memory used
|
|
** to store the schema for all databases (main, temp, and any ATTACHed
|
|
** databases. *pHighwater is set to zero.
|
|
*/
|
|
case SQLITE_DBSTATUS_SCHEMA_USED: {
|
|
int i; /* Used to iterate through schemas */
|
|
int nByte = 0; /* Used to accumulate return value */
|
|
|
|
sqlite3BtreeEnterAll(db);
|
|
db->pnBytesFreed = &nByte;
|
|
assert( db->lookaside.pEnd==db->lookaside.pTrueEnd );
|
|
db->lookaside.pEnd = db->lookaside.pStart;
|
|
for(i=0; i<db->nDb; i++){
|
|
Schema *pSchema = db->aDb[i].pSchema;
|
|
if( ALWAYS(pSchema!=0) ){
|
|
HashElem *p;
|
|
|
|
nByte += sqlite3GlobalConfig.m.xRoundup(sizeof(HashElem)) * (
|
|
pSchema->tblHash.count
|
|
+ pSchema->trigHash.count
|
|
+ pSchema->idxHash.count
|
|
+ pSchema->fkeyHash.count
|
|
);
|
|
nByte += sqlite3_msize(pSchema->tblHash.ht);
|
|
nByte += sqlite3_msize(pSchema->trigHash.ht);
|
|
nByte += sqlite3_msize(pSchema->idxHash.ht);
|
|
nByte += sqlite3_msize(pSchema->fkeyHash.ht);
|
|
|
|
for(p=sqliteHashFirst(&pSchema->trigHash); p; p=sqliteHashNext(p)){
|
|
sqlite3DeleteTrigger(db, (Trigger*)sqliteHashData(p));
|
|
}
|
|
for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){
|
|
sqlite3DeleteTable(db, (Table *)sqliteHashData(p));
|
|
}
|
|
}
|
|
}
|
|
db->pnBytesFreed = 0;
|
|
db->lookaside.pEnd = db->lookaside.pTrueEnd;
|
|
sqlite3BtreeLeaveAll(db);
|
|
|
|
*pHighwater = 0;
|
|
*pCurrent = nByte;
|
|
break;
|
|
}
|
|
|
|
/*
|
|
** *pCurrent gets an accurate estimate of the amount of memory used
|
|
** to store all prepared statements.
|
|
** *pHighwater is set to zero.
|
|
*/
|
|
case SQLITE_DBSTATUS_STMT_USED: {
|
|
struct Vdbe *pVdbe; /* Used to iterate through VMs */
|
|
int nByte = 0; /* Used to accumulate return value */
|
|
|
|
db->pnBytesFreed = &nByte;
|
|
assert( db->lookaside.pEnd==db->lookaside.pTrueEnd );
|
|
db->lookaside.pEnd = db->lookaside.pStart;
|
|
for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pVNext){
|
|
sqlite3VdbeDelete(pVdbe);
|
|
}
|
|
db->lookaside.pEnd = db->lookaside.pTrueEnd;
|
|
db->pnBytesFreed = 0;
|
|
|
|
*pHighwater = 0; /* IMP: R-64479-57858 */
|
|
*pCurrent = nByte;
|
|
|
|
break;
|
|
}
|
|
|
|
/*
|
|
** Set *pCurrent to the total cache hits or misses encountered by all
|
|
** pagers the database handle is connected to. *pHighwater is always set
|
|
** to zero.
|
|
*/
|
|
case SQLITE_DBSTATUS_CACHE_SPILL:
|
|
op = SQLITE_DBSTATUS_CACHE_WRITE+1;
|
|
/* no break */ deliberate_fall_through
|
|
case SQLITE_DBSTATUS_CACHE_HIT:
|
|
case SQLITE_DBSTATUS_CACHE_MISS:
|
|
case SQLITE_DBSTATUS_CACHE_WRITE:{
|
|
int i;
|
|
u64 nRet = 0;
|
|
assert( SQLITE_DBSTATUS_CACHE_MISS==SQLITE_DBSTATUS_CACHE_HIT+1 );
|
|
assert( SQLITE_DBSTATUS_CACHE_WRITE==SQLITE_DBSTATUS_CACHE_HIT+2 );
|
|
|
|
for(i=0; i<db->nDb; i++){
|
|
if( db->aDb[i].pBt ){
|
|
Pager *pPager = sqlite3BtreePager(db->aDb[i].pBt);
|
|
sqlite3PagerCacheStat(pPager, op, resetFlag, &nRet);
|
|
}
|
|
}
|
|
*pHighwater = 0; /* IMP: R-42420-56072 */
|
|
/* IMP: R-54100-20147 */
|
|
/* IMP: R-29431-39229 */
|
|
*pCurrent = (int)nRet & 0x7fffffff;
|
|
break;
|
|
}
|
|
|
|
/* Set *pCurrent to non-zero if there are unresolved deferred foreign
|
|
** key constraints. Set *pCurrent to zero if all foreign key constraints
|
|
** have been satisfied. The *pHighwater is always set to zero.
|
|
*/
|
|
case SQLITE_DBSTATUS_DEFERRED_FKS: {
|
|
*pHighwater = 0; /* IMP: R-11967-56545 */
|
|
*pCurrent = db->nDeferredImmCons>0 || db->nDeferredCons>0;
|
|
break;
|
|
}
|
|
|
|
default: {
|
|
rc = SQLITE_ERROR;
|
|
}
|
|
}
|
|
sqlite3_mutex_leave(db->mutex);
|
|
return rc;
|
|
}
|
|
|
|
/************** End of status.c **********************************************/
|
|
/************** Begin file date.c ********************************************/
|
|
/*
|
|
** 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.
|
|
**
|
|
** 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 implementation 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
|
|
** ISBN 0-943396-61-1
|
|
** Willmann-Bell, Inc
|
|
** Richmond, Virginia (USA)
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
/* #include <stdlib.h> */
|
|
/* #include <assert.h> */
|
|
#include <time.h>
|
|
|
|
#ifndef SQLITE_OMIT_DATETIME_FUNCS
|
|
|
|
/*
|
|
** The MSVC CRT on Windows CE may not have a localtime() function.
|
|
** So declare a substitute. The substitute function itself is
|
|
** defined in "os_win.c".
|
|
*/
|
|
#if !defined(SQLITE_OMIT_LOCALTIME) && defined(_WIN32_WCE) && \
|
|
(!defined(SQLITE_MSVC_LOCALTIME_API) || !SQLITE_MSVC_LOCALTIME_API)
|
|
struct tm *__cdecl localtime(const time_t *);
|
|
#endif
|
|
|
|
/*
|
|
** A structure for holding a single date and time.
|
|
*/
|
|
typedef struct DateTime DateTime;
|
|
struct DateTime {
|
|
sqlite3_int64 iJD; /* The julian day number times 86400000 */
|
|
int Y, M, D; /* Year, month, and day */
|
|
int h, m; /* Hour and minutes */
|
|
int tz; /* Timezone offset in minutes */
|
|
double s; /* Seconds */
|
|
char validJD; /* True (1) if iJD is valid */
|
|
char rawS; /* Raw numeric value stored in s */
|
|
char validYMD; /* True (1) if Y,M,D are valid */
|
|
char validHMS; /* True (1) if h,m,s are valid */
|
|
char validTZ; /* True (1) if tz is valid */
|
|
char tzSet; /* Timezone was set explicitly */
|
|
char isError; /* An overflow has occurred */
|
|
char useSubsec; /* Display subsecond precision */
|
|
};
|
|
|
|
|
|
/*
|
|
** Convert zDate into one or more integers according to the conversion
|
|
** specifier zFormat.
|
|
**
|
|
** zFormat[] contains 4 characters for each integer converted, except for
|
|
** the last integer which is specified by three characters. The meaning
|
|
** of a four-character format specifiers ABCD is:
|
|
**
|
|
** A: number of digits to convert. Always "2" or "4".
|
|
** B: minimum value. Always "0" or "1".
|
|
** C: maximum value, decoded as:
|
|
** a: 12
|
|
** b: 14
|
|
** c: 24
|
|
** d: 31
|
|
** e: 59
|
|
** f: 9999
|
|
** D: the separator character, or \000 to indicate this is the
|
|
** last number to convert.
|
|
**
|
|
** Example: To translate an ISO-8601 date YYYY-MM-DD, the format would
|
|
** be "40f-21a-20c". The "40f-" indicates the 4-digit year followed by "-".
|
|
** The "21a-" indicates the 2-digit month followed by "-". The "20c" indicates
|
|
** the 2-digit day which is the last integer in the set.
|
|
**
|
|
** The function returns the number of successful conversions.
|
|
*/
|
|
static int getDigits(const char *zDate, const char *zFormat, ...){
|
|
/* The aMx[] array translates the 3rd character of each format
|
|
** spec into a max size: a b c d e f */
|
|
static const u16 aMx[] = { 12, 14, 24, 31, 59, 14712 };
|
|
va_list ap;
|
|
int cnt = 0;
|
|
char nextC;
|
|
va_start(ap, zFormat);
|
|
do{
|
|
char N = zFormat[0] - '0';
|
|
char min = zFormat[1] - '0';
|
|
int val = 0;
|
|
u16 max;
|
|
|
|
assert( zFormat[2]>='a' && zFormat[2]<='f' );
|
|
max = aMx[zFormat[2] - 'a'];
|
|
nextC = zFormat[3];
|
|
val = 0;
|
|
while( N-- ){
|
|
if( !sqlite3Isdigit(*zDate) ){
|
|
goto end_getDigits;
|
|
}
|
|
val = val*10 + *zDate - '0';
|
|
zDate++;
|
|
}
|
|
if( val<(int)min || val>(int)max || (nextC!=0 && nextC!=*zDate) ){
|
|
goto end_getDigits;
|
|
}
|
|
*va_arg(ap,int*) = val;
|
|
zDate++;
|
|
cnt++;
|
|
zFormat += 4;
|
|
}while( nextC );
|
|
end_getDigits:
|
|
va_end(ap);
|
|
return cnt;
|
|
}
|
|
|
|
/*
|
|
** Parse a timezone extension on the end of a date-time.
|
|
** The extension is of the form:
|
|
**
|
|
** (+/-)HH:MM
|
|
**
|
|
** Or the "zulu" notation:
|
|
**
|
|
** Z
|
|
**
|
|
** If the parse is successful, write the number of minutes
|
|
** of change in p->tz and return 0. If a parser error occurs,
|
|
** return non-zero.
|
|
**
|
|
** A missing specifier is not considered an error.
|
|
*/
|
|
static int parseTimezone(const char *zDate, DateTime *p){
|
|
int sgn = 0;
|
|
int nHr, nMn;
|
|
int c;
|
|
while( sqlite3Isspace(*zDate) ){ zDate++; }
|
|
p->tz = 0;
|
|
c = *zDate;
|
|
if( c=='-' ){
|
|
sgn = -1;
|
|
}else if( c=='+' ){
|
|
sgn = +1;
|
|
}else if( c=='Z' || c=='z' ){
|
|
zDate++;
|
|
goto zulu_time;
|
|
}else{
|
|
return c!=0;
|
|
}
|
|
zDate++;
|
|
if( getDigits(zDate, "20b:20e", &nHr, &nMn)!=2 ){
|
|
return 1;
|
|
}
|
|
zDate += 5;
|
|
p->tz = sgn*(nMn + nHr*60);
|
|
zulu_time:
|
|
while( sqlite3Isspace(*zDate) ){ zDate++; }
|
|
p->tzSet = 1;
|
|
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, "20c:20e", &h, &m)!=2 ){
|
|
return 1;
|
|
}
|
|
zDate += 5;
|
|
if( *zDate==':' ){
|
|
zDate++;
|
|
if( getDigits(zDate, "20e", &s)!=1 ){
|
|
return 1;
|
|
}
|
|
zDate += 2;
|
|
if( *zDate=='.' && sqlite3Isdigit(zDate[1]) ){
|
|
double rScale = 1.0;
|
|
zDate++;
|
|
while( sqlite3Isdigit(*zDate) ){
|
|
ms = ms*10.0 + *zDate - '0';
|
|
rScale *= 10.0;
|
|
zDate++;
|
|
}
|
|
ms /= rScale;
|
|
}
|
|
}else{
|
|
s = 0;
|
|
}
|
|
p->validJD = 0;
|
|
p->rawS = 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)?1:0;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
** Put the DateTime object into its error state.
|
|
*/
|
|
static void datetimeError(DateTime *p){
|
|
memset(p, 0, sizeof(*p));
|
|
p->isError = 1;
|
|
}
|
|
|
|
/*
|
|
** 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( Y<-4713 || Y>9999 || p->rawS ){
|
|
datetimeError(p);
|
|
return;
|
|
}
|
|
if( M<=2 ){
|
|
Y--;
|
|
M += 12;
|
|
}
|
|
A = Y/100;
|
|
B = 2 - A + (A/4);
|
|
X1 = 36525*(Y+4716)/100;
|
|
X2 = 306001*(M+1)/10000;
|
|
p->iJD = (sqlite3_int64)((X1 + X2 + D + B - 1524.5 ) * 86400000);
|
|
p->validJD = 1;
|
|
if( p->validHMS ){
|
|
p->iJD += p->h*3600000 + p->m*60000 + (sqlite3_int64)(p->s*1000 + 0.5);
|
|
if( p->validTZ ){
|
|
p->iJD -= p->tz*60000;
|
|
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, "40f-21a-21d", &Y, &M, &D)!=3 ){
|
|
return 1;
|
|
}
|
|
zDate += 10;
|
|
while( sqlite3Isspace(*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;
|
|
}
|
|
|
|
/*
|
|
** Set the time to the current time reported by the VFS.
|
|
**
|
|
** Return the number of errors.
|
|
*/
|
|
static int setDateTimeToCurrent(sqlite3_context *context, DateTime *p){
|
|
p->iJD = sqlite3StmtCurrentTime(context);
|
|
if( p->iJD>0 ){
|
|
p->validJD = 1;
|
|
return 0;
|
|
}else{
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Input "r" is a numeric quantity which might be a julian day number,
|
|
** or the number of seconds since 1970. If the value if r is within
|
|
** range of a julian day number, install it as such and set validJD.
|
|
** If the value is a valid unix timestamp, put it in p->s and set p->rawS.
|
|
*/
|
|
static void setRawDateNumber(DateTime *p, double r){
|
|
p->s = r;
|
|
p->rawS = 1;
|
|
if( r>=0.0 && r<5373484.5 ){
|
|
p->iJD = (sqlite3_int64)(r*86400000.0 + 0.5);
|
|
p->validJD = 1;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** 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(
|
|
sqlite3_context *context,
|
|
const char *zDate,
|
|
DateTime *p
|
|
){
|
|
double r;
|
|
if( parseYyyyMmDd(zDate,p)==0 ){
|
|
return 0;
|
|
}else if( parseHhMmSs(zDate, p)==0 ){
|
|
return 0;
|
|
}else if( sqlite3StrICmp(zDate,"now")==0 && sqlite3NotPureFunc(context) ){
|
|
return setDateTimeToCurrent(context, p);
|
|
}else if( sqlite3AtoF(zDate, &r, sqlite3Strlen30(zDate), SQLITE_UTF8)>0 ){
|
|
setRawDateNumber(p, r);
|
|
return 0;
|
|
}else if( (sqlite3StrICmp(zDate,"subsec")==0
|
|
|| sqlite3StrICmp(zDate,"subsecond")==0)
|
|
&& sqlite3NotPureFunc(context) ){
|
|
p->useSubsec = 1;
|
|
return setDateTimeToCurrent(context, p);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/* The julian day number for 9999-12-31 23:59:59.999 is 5373484.4999999.
|
|
** Multiplying this by 86400000 gives 464269060799999 as the maximum value
|
|
** for DateTime.iJD.
|
|
**
|
|
** But some older compilers (ex: gcc 4.2.1 on older Macs) cannot deal with
|
|
** such a large integer literal, so we have to encode it.
|
|
*/
|
|
#define INT_464269060799999 ((((i64)0x1a640)<<32)|0x1072fdff)
|
|
|
|
/*
|
|
** Return TRUE if the given julian day number is within range.
|
|
**
|
|
** The input is the JulianDay times 86400000.
|
|
*/
|
|
static int validJulianDay(sqlite3_int64 iJD){
|
|
return iJD>=0 && iJD<=INT_464269060799999;
|
|
}
|
|
|
|
/*
|
|
** 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 if( !validJulianDay(p->iJD) ){
|
|
datetimeError(p);
|
|
return;
|
|
}else{
|
|
Z = (int)((p->iJD + 43200000)/86400000);
|
|
A = (int)((Z - 1867216.25)/36524.25);
|
|
A = Z + 1 + A - (A/4);
|
|
B = A + 1524;
|
|
C = (int)((B - 122.1)/365.25);
|
|
D = (36525*(C&32767))/100;
|
|
E = (int)((B-D)/30.6001);
|
|
X1 = (int)(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 day_ms, day_min; /* milliseconds, minutes into the day */
|
|
if( p->validHMS ) return;
|
|
computeJD(p);
|
|
day_ms = (int)((p->iJD + 43200000) % 86400000);
|
|
p->s = (day_ms % 60000)/1000.0;
|
|
day_min = day_ms/60000;
|
|
p->m = day_min % 60;
|
|
p->h = day_min / 60;
|
|
p->rawS = 0;
|
|
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;
|
|
}
|
|
|
|
#ifndef SQLITE_OMIT_LOCALTIME
|
|
/*
|
|
** On recent Windows platforms, the localtime_s() function is available
|
|
** as part of the "Secure CRT". It is essentially equivalent to
|
|
** localtime_r() available under most POSIX platforms, except that the
|
|
** order of the parameters is reversed.
|
|
**
|
|
** See http://msdn.microsoft.com/en-us/library/a442x3ye(VS.80).aspx.
|
|
**
|
|
** If the user has not indicated to use localtime_r() or localtime_s()
|
|
** already, check for an MSVC build environment that provides
|
|
** localtime_s().
|
|
*/
|
|
#if !HAVE_LOCALTIME_R && !HAVE_LOCALTIME_S \
|
|
&& defined(_MSC_VER) && defined(_CRT_INSECURE_DEPRECATE)
|
|
#undef HAVE_LOCALTIME_S
|
|
#define HAVE_LOCALTIME_S 1
|
|
#endif
|
|
|
|
/*
|
|
** The following routine implements the rough equivalent of localtime_r()
|
|
** using whatever operating-system specific localtime facility that
|
|
** is available. This routine returns 0 on success and
|
|
** non-zero on any kind of error.
|
|
**
|
|
** If the sqlite3GlobalConfig.bLocaltimeFault variable is non-zero then this
|
|
** routine will always fail. If bLocaltimeFault is nonzero and
|
|
** sqlite3GlobalConfig.xAltLocaltime is not NULL, then xAltLocaltime() is
|
|
** invoked in place of the OS-defined localtime() function.
|
|
**
|
|
** EVIDENCE-OF: R-62172-00036 In this implementation, the standard C
|
|
** library function localtime_r() is used to assist in the calculation of
|
|
** local time.
|
|
*/
|
|
static int osLocaltime(time_t *t, struct tm *pTm){
|
|
int rc;
|
|
#if !HAVE_LOCALTIME_R && !HAVE_LOCALTIME_S
|
|
struct tm *pX;
|
|
#if SQLITE_THREADSAFE>0
|
|
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN);
|
|
#endif
|
|
sqlite3_mutex_enter(mutex);
|
|
pX = localtime(t);
|
|
#ifndef SQLITE_UNTESTABLE
|
|
if( sqlite3GlobalConfig.bLocaltimeFault ){
|
|
if( sqlite3GlobalConfig.xAltLocaltime!=0
|
|
&& 0==sqlite3GlobalConfig.xAltLocaltime((const void*)t,(void*)pTm)
|
|
){
|
|
pX = pTm;
|
|
}else{
|
|
pX = 0;
|
|
}
|
|
}
|
|
#endif
|
|
if( pX ) *pTm = *pX;
|
|
#if SQLITE_THREADSAFE>0
|
|
sqlite3_mutex_leave(mutex);
|
|
#endif
|
|
rc = pX==0;
|
|
#else
|
|
#ifndef SQLITE_UNTESTABLE
|
|
if( sqlite3GlobalConfig.bLocaltimeFault ){
|
|
if( sqlite3GlobalConfig.xAltLocaltime!=0 ){
|
|
return sqlite3GlobalConfig.xAltLocaltime((const void*)t,(void*)pTm);
|
|
}else{
|
|
return 1;
|
|
}
|
|
}
|
|
#endif
|
|
#if HAVE_LOCALTIME_R
|
|
rc = localtime_r(t, pTm)==0;
|
|
#else
|
|
rc = localtime_s(pTm, t);
|
|
#endif /* HAVE_LOCALTIME_R */
|
|
#endif /* HAVE_LOCALTIME_R || HAVE_LOCALTIME_S */
|
|
return rc;
|
|
}
|
|
#endif /* SQLITE_OMIT_LOCALTIME */
|
|
|
|
|
|
#ifndef SQLITE_OMIT_LOCALTIME
|
|
/*
|
|
** Assuming the input DateTime is UTC, move it to its localtime equivalent.
|
|
*/
|
|
static int toLocaltime(
|
|
DateTime *p, /* Date at which to calculate offset */
|
|
sqlite3_context *pCtx /* Write error here if one occurs */
|
|
){
|
|
time_t t;
|
|
struct tm sLocal;
|
|
int iYearDiff;
|
|
|
|
/* Initialize the contents of sLocal to avoid a compiler warning. */
|
|
memset(&sLocal, 0, sizeof(sLocal));
|
|
|
|
computeJD(p);
|
|
if( p->iJD<2108667600*(i64)100000 /* 1970-01-01 */
|
|
|| p->iJD>2130141456*(i64)100000 /* 2038-01-18 */
|
|
){
|
|
/* EVIDENCE-OF: R-55269-29598 The localtime_r() C function normally only
|
|
** works for years between 1970 and 2037. For dates outside this range,
|
|
** SQLite attempts to map the year into an equivalent year within this
|
|
** range, do the calculation, then map the year back.
|
|
*/
|
|
DateTime x = *p;
|
|
computeYMD_HMS(&x);
|
|
iYearDiff = (2000 + x.Y%4) - x.Y;
|
|
x.Y += iYearDiff;
|
|
x.validJD = 0;
|
|
computeJD(&x);
|
|
t = (time_t)(x.iJD/1000 - 21086676*(i64)10000);
|
|
}else{
|
|
iYearDiff = 0;
|
|
t = (time_t)(p->iJD/1000 - 21086676*(i64)10000);
|
|
}
|
|
if( osLocaltime(&t, &sLocal) ){
|
|
sqlite3_result_error(pCtx, "local time unavailable", -1);
|
|
return SQLITE_ERROR;
|
|
}
|
|
p->Y = sLocal.tm_year + 1900 - iYearDiff;
|
|
p->M = sLocal.tm_mon + 1;
|
|
p->D = sLocal.tm_mday;
|
|
p->h = sLocal.tm_hour;
|
|
p->m = sLocal.tm_min;
|
|
p->s = sLocal.tm_sec + (p->iJD%1000)*0.001;
|
|
p->validYMD = 1;
|
|
p->validHMS = 1;
|
|
p->validJD = 0;
|
|
p->rawS = 0;
|
|
p->validTZ = 0;
|
|
p->isError = 0;
|
|
return SQLITE_OK;
|
|
}
|
|
#endif /* SQLITE_OMIT_LOCALTIME */
|
|
|
|
/*
|
|
** The following table defines various date transformations of the form
|
|
**
|
|
** 'NNN days'
|
|
**
|
|
** Where NNN is an arbitrary floating-point number and "days" can be one
|
|
** of several units of time.
|
|
*/
|
|
static const struct {
|
|
u8 nName; /* Length of the name */
|
|
char zName[7]; /* Name of the transformation */
|
|
float rLimit; /* Maximum NNN value for this transform */
|
|
float rXform; /* Constant used for this transform */
|
|
} aXformType[] = {
|
|
{ 6, "second", 4.6427e+14, 1.0 },
|
|
{ 6, "minute", 7.7379e+12, 60.0 },
|
|
{ 4, "hour", 1.2897e+11, 3600.0 },
|
|
{ 3, "day", 5373485.0, 86400.0 },
|
|
{ 5, "month", 176546.0, 2592000.0 },
|
|
{ 4, "year", 14713.0, 31536000.0 },
|
|
};
|
|
|
|
/*
|
|
** If the DateTime p is raw number, try to figure out if it is
|
|
** a julian day number of a unix timestamp. Set the p value
|
|
** appropriately.
|
|
*/
|
|
static void autoAdjustDate(DateTime *p){
|
|
if( !p->rawS || p->validJD ){
|
|
p->rawS = 0;
|
|
}else if( p->s>=-21086676*(i64)10000 /* -4713-11-24 12:00:00 */
|
|
&& p->s<=(25340230*(i64)10000)+799 /* 9999-12-31 23:59:59 */
|
|
){
|
|
double r = p->s*1000.0 + 210866760000000.0;
|
|
clearYMD_HMS_TZ(p);
|
|
p->iJD = (sqlite3_int64)(r + 0.5);
|
|
p->validJD = 1;
|
|
p->rawS = 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** 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. If the error
|
|
** is in a system call (i.e. localtime()), then an error message is written
|
|
** to context pCtx. If the error is an unrecognized modifier, no error is
|
|
** written to pCtx.
|
|
*/
|
|
static int parseModifier(
|
|
sqlite3_context *pCtx, /* Function context */
|
|
const char *z, /* The text of the modifier */
|
|
int n, /* Length of zMod in bytes */
|
|
DateTime *p, /* The date/time value to be modified */
|
|
int idx /* Parameter index of the modifier */
|
|
){
|
|
int rc = 1;
|
|
double r;
|
|
switch(sqlite3UpperToLower[(u8)z[0]] ){
|
|
case 'a': {
|
|
/*
|
|
** auto
|
|
**
|
|
** If rawS is available, then interpret as a julian day number, or
|
|
** a unix timestamp, depending on its magnitude.
|
|
*/
|
|
if( sqlite3_stricmp(z, "auto")==0 ){
|
|
if( idx>1 ) return 1; /* IMP: R-33611-57934 */
|
|
autoAdjustDate(p);
|
|
rc = 0;
|
|
}
|
|
break;
|
|
}
|
|
case 'j': {
|
|
/*
|
|
** julianday
|
|
**
|
|
** Always interpret the prior number as a julian-day value. If this
|
|
** is not the first modifier, or if the prior argument is not a numeric
|
|
** value in the allowed range of julian day numbers understood by
|
|
** SQLite (0..5373484.5) then the result will be NULL.
|
|
*/
|
|
if( sqlite3_stricmp(z, "julianday")==0 ){
|
|
if( idx>1 ) return 1; /* IMP: R-31176-64601 */
|
|
if( p->validJD && p->rawS ){
|
|
rc = 0;
|
|
p->rawS = 0;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
#ifndef SQLITE_OMIT_LOCALTIME
|
|
case 'l': {
|
|
/* localtime
|
|
**
|
|
** Assuming the current time value is UTC (a.k.a. GMT), shift it to
|
|
** show local time.
|
|
*/
|
|
if( sqlite3_stricmp(z, "localtime")==0 && sqlite3NotPureFunc(pCtx) ){
|
|
rc = toLocaltime(p, pCtx);
|
|
}
|
|
break;
|
|
}
|
|
#endif
|
|
case 'u': {
|
|
/*
|
|
** unixepoch
|
|
**
|
|
** Treat the current value of p->s as the number of
|
|
** seconds since 1970. Convert to a real julian day number.
|
|
*/
|
|
if( sqlite3_stricmp(z, "unixepoch")==0 && p->rawS ){
|
|
if( idx>1 ) return 1; /* IMP: R-49255-55373 */
|
|
r = p->s*1000.0 + 210866760000000.0;
|
|
if( r>=0.0 && r<464269060800000.0 ){
|
|
clearYMD_HMS_TZ(p);
|
|
p->iJD = (sqlite3_int64)(r + 0.5);
|
|
p->validJD = 1;
|
|
p->rawS = 0;
|
|
rc = 0;
|
|
}
|
|
}
|
|
#ifndef SQLITE_OMIT_LOCALTIME
|
|
else if( sqlite3_stricmp(z, "utc")==0 && sqlite3NotPureFunc(pCtx) ){
|
|
if( p->tzSet==0 ){
|
|
i64 iOrigJD; /* Original localtime */
|
|
i64 iGuess; /* Guess at the corresponding utc time */
|
|
int cnt = 0; /* Safety to prevent infinite loop */
|
|
i64 iErr; /* Guess is off by this much */
|
|
|
|
computeJD(p);
|
|
iGuess = iOrigJD = p->iJD;
|
|
iErr = 0;
|
|
do{
|
|
DateTime new;
|
|
memset(&new, 0, sizeof(new));
|
|
iGuess -= iErr;
|
|
new.iJD = iGuess;
|
|
new.validJD = 1;
|
|
rc = toLocaltime(&new, pCtx);
|
|
if( rc ) return rc;
|
|
computeJD(&new);
|
|
iErr = new.iJD - iOrigJD;
|
|
}while( iErr && cnt++<3 );
|
|
memset(p, 0, sizeof(*p));
|
|
p->iJD = iGuess;
|
|
p->validJD = 1;
|
|
p->tzSet = 1;
|
|
}
|
|
rc = SQLITE_OK;
|
|
}
|
|
#endif
|
|
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( sqlite3_strnicmp(z, "weekday ", 8)==0
|
|
&& sqlite3AtoF(&z[8], &r, sqlite3Strlen30(&z[8]), SQLITE_UTF8)>0
|
|
&& r>=0.0 && r<7.0 && (n=(int)r)==r ){
|
|
sqlite3_int64 Z;
|
|
computeYMD_HMS(p);
|
|
p->validTZ = 0;
|
|
p->validJD = 0;
|
|
computeJD(p);
|
|
Z = ((p->iJD + 129600000)/86400000) % 7;
|
|
if( Z>n ) Z -= 7;
|
|
p->iJD += (n - Z)*86400000;
|
|
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.
|
|
**
|
|
** subsecond
|
|
** subsec
|
|
**
|
|
** Show subsecond precision in the output of datetime() and
|
|
** unixepoch() and strftime('%s').
|
|
*/
|
|
if( sqlite3_strnicmp(z, "start of ", 9)!=0 ){
|
|
if( sqlite3_stricmp(z, "subsec")==0
|
|
|| sqlite3_stricmp(z, "subsecond")==0
|
|
){
|
|
p->useSubsec = 1;
|
|
rc = 0;
|
|
}
|
|
break;
|
|
}
|
|
if( !p->validJD && !p->validYMD && !p->validHMS ) break;
|
|
z += 9;
|
|
computeYMD(p);
|
|
p->validHMS = 1;
|
|
p->h = p->m = 0;
|
|
p->s = 0.0;
|
|
p->rawS = 0;
|
|
p->validTZ = 0;
|
|
p->validJD = 0;
|
|
if( sqlite3_stricmp(z,"month")==0 ){
|
|
p->D = 1;
|
|
rc = 0;
|
|
}else if( sqlite3_stricmp(z,"year")==0 ){
|
|
p->M = 1;
|
|
p->D = 1;
|
|
rc = 0;
|
|
}else if( sqlite3_stricmp(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': {
|
|
double rRounder;
|
|
int i;
|
|
int Y,M,D,h,m,x;
|
|
const char *z2 = z;
|
|
char z0 = z[0];
|
|
for(n=1; z[n]; n++){
|
|
if( z[n]==':' ) break;
|
|
if( sqlite3Isspace(z[n]) ) break;
|
|
if( z[n]=='-' ){
|
|
if( n==5 && getDigits(&z[1], "40f", &Y)==1 ) break;
|
|
if( n==6 && getDigits(&z[1], "50f", &Y)==1 ) break;
|
|
}
|
|
}
|
|
if( sqlite3AtoF(z, &r, n, SQLITE_UTF8)<=0 ){
|
|
assert( rc==1 );
|
|
break;
|
|
}
|
|
if( z[n]=='-' ){
|
|
/* A modifier of the form (+|-)YYYY-MM-DD adds or subtracts the
|
|
** specified number of years, months, and days. MM is limited to
|
|
** the range 0-11 and DD is limited to 0-30.
|
|
*/
|
|
if( z0!='+' && z0!='-' ) break; /* Must start with +/- */
|
|
if( n==5 ){
|
|
if( getDigits(&z[1], "40f-20a-20d", &Y, &M, &D)!=3 ) break;
|
|
}else{
|
|
assert( n==6 );
|
|
if( getDigits(&z[1], "50f-20a-20d", &Y, &M, &D)!=3 ) break;
|
|
z++;
|
|
}
|
|
if( M>=12 ) break; /* M range 0..11 */
|
|
if( D>=31 ) break; /* D range 0..30 */
|
|
computeYMD_HMS(p);
|
|
p->validJD = 0;
|
|
if( z0=='-' ){
|
|
p->Y -= Y;
|
|
p->M -= M;
|
|
D = -D;
|
|
}else{
|
|
p->Y += Y;
|
|
p->M += M;
|
|
}
|
|
x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
|
|
p->Y += x;
|
|
p->M -= x*12;
|
|
computeJD(p);
|
|
p->validHMS = 0;
|
|
p->validYMD = 0;
|
|
p->iJD += (i64)D*86400000;
|
|
if( z[11]==0 ){
|
|
rc = 0;
|
|
break;
|
|
}
|
|
if( sqlite3Isspace(z[11])
|
|
&& getDigits(&z[12], "20c:20e", &h, &m)==2
|
|
){
|
|
z2 = &z[12];
|
|
n = 2;
|
|
}else{
|
|
break;
|
|
}
|
|
}
|
|
if( z2[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.
|
|
*/
|
|
|
|
DateTime tx;
|
|
sqlite3_int64 day;
|
|
if( !sqlite3Isdigit(*z2) ) z2++;
|
|
memset(&tx, 0, sizeof(tx));
|
|
if( parseHhMmSs(z2, &tx) ) break;
|
|
computeJD(&tx);
|
|
tx.iJD -= 43200000;
|
|
day = tx.iJD/86400000;
|
|
tx.iJD -= day*86400000;
|
|
if( z0=='-' ) tx.iJD = -tx.iJD;
|
|
computeJD(p);
|
|
clearYMD_HMS_TZ(p);
|
|
p->iJD += tx.iJD;
|
|
rc = 0;
|
|
break;
|
|
}
|
|
|
|
/* If control reaches this point, it means the transformation is
|
|
** one of the forms like "+NNN days". */
|
|
z += n;
|
|
while( sqlite3Isspace(*z) ) z++;
|
|
n = sqlite3Strlen30(z);
|
|
if( n>10 || n<3 ) break;
|
|
if( sqlite3UpperToLower[(u8)z[n-1]]=='s' ) n--;
|
|
computeJD(p);
|
|
assert( rc==1 );
|
|
rRounder = r<0 ? -0.5 : +0.5;
|
|
for(i=0; i<ArraySize(aXformType); i++){
|
|
if( aXformType[i].nName==n
|
|
&& sqlite3_strnicmp(aXformType[i].zName, z, n)==0
|
|
&& r>-aXformType[i].rLimit && r<aXformType[i].rLimit
|
|
){
|
|
switch( i ){
|
|
case 4: { /* Special processing to add months */
|
|
assert( strcmp(aXformType[i].zName,"month")==0 );
|
|
computeYMD_HMS(p);
|
|
p->M += (int)r;
|
|
x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
|
|
p->Y += x;
|
|
p->M -= x*12;
|
|
p->validJD = 0;
|
|
r -= (int)r;
|
|
break;
|
|
}
|
|
case 5: { /* Special processing to add years */
|
|
int y = (int)r;
|
|
assert( strcmp(aXformType[i].zName,"year")==0 );
|
|
computeYMD_HMS(p);
|
|
p->Y += y;
|
|
p->validJD = 0;
|
|
r -= (int)r;
|
|
break;
|
|
}
|
|
}
|
|
computeJD(p);
|
|
p->iJD += (sqlite3_int64)(r*1000.0*aXformType[i].rXform + rRounder);
|
|
rc = 0;
|
|
break;
|
|
}
|
|
}
|
|
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.
|
|
**
|
|
** If there are zero parameters (if even argv[0] is undefined)
|
|
** then assume a default value of "now" for argv[0].
|
|
*/
|
|
static int isDate(
|
|
sqlite3_context *context,
|
|
int argc,
|
|
sqlite3_value **argv,
|
|
DateTime *p
|
|
){
|
|
int i, n;
|
|
const unsigned char *z;
|
|
int eType;
|
|
memset(p, 0, sizeof(*p));
|
|
if( argc==0 ){
|
|
if( !sqlite3NotPureFunc(context) ) return 1;
|
|
return setDateTimeToCurrent(context, p);
|
|
}
|
|
if( (eType = sqlite3_value_type(argv[0]))==SQLITE_FLOAT
|
|
|| eType==SQLITE_INTEGER ){
|
|
setRawDateNumber(p, sqlite3_value_double(argv[0]));
|
|
}else{
|
|
z = sqlite3_value_text(argv[0]);
|
|
if( !z || parseDateOrTime(context, (char*)z, p) ){
|
|
return 1;
|
|
}
|
|
}
|
|
for(i=1; i<argc; i++){
|
|
z = sqlite3_value_text(argv[i]);
|
|
n = sqlite3_value_bytes(argv[i]);
|
|
if( z==0 || parseModifier(context, (char*)z, n, p, i) ) return 1;
|
|
}
|
|
computeJD(p);
|
|
if( p->isError || !validJulianDay(p->iJD) ) return 1;
|
|
if( argc==1 && p->validYMD && p->D>28 ){
|
|
/* Make sure a YYYY-MM-DD is normalized.
|
|
** Example: 2023-02-31 -> 2023-03-03 */
|
|
assert( p->validJD );
|
|
p->validYMD = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
** The following routines implement the various date and time functions
|
|
** of SQLite.
|
|
*/
|
|
|
|
/*
|
|
** julianday( TIMESTRING, MOD, MOD, ...)
|
|
**
|
|
** Return the julian day number of the date specified in the arguments
|
|
*/
|
|
static void juliandayFunc(
|
|
sqlite3_context *context,
|
|
int argc,
|
|
sqlite3_value **argv
|
|
){
|
|
DateTime x;
|
|
if( isDate(context, argc, argv, &x)==0 ){
|
|
computeJD(&x);
|
|
sqlite3_result_double(context, x.iJD/86400000.0);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** unixepoch( TIMESTRING, MOD, MOD, ...)
|
|
**
|
|
** Return the number of seconds (including fractional seconds) since
|
|
** the unix epoch of 1970-01-01 00:00:00 GMT.
|
|
*/
|
|
static void unixepochFunc(
|
|
sqlite3_context *context,
|
|
int argc,
|
|
sqlite3_value **argv
|
|
){
|
|
DateTime x;
|
|
if( isDate(context, argc, argv, &x)==0 ){
|
|
computeJD(&x);
|
|
if( x.useSubsec ){
|
|
sqlite3_result_double(context, (x.iJD - 21086676*(i64)10000000)/1000.0);
|
|
}else{
|
|
sqlite3_result_int64(context, x.iJD/1000 - 21086676*(i64)10000);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** datetime( TIMESTRING, MOD, MOD, ...)
|
|
**
|
|
** Return YYYY-MM-DD HH:MM:SS
|
|
*/
|
|
static void datetimeFunc(
|
|
sqlite3_context *context,
|
|
int argc,
|
|
sqlite3_value **argv
|
|
){
|
|
DateTime x;
|
|
if( isDate(context, argc, argv, &x)==0 ){
|
|
int Y, s, n;
|
|
char zBuf[32];
|
|
computeYMD_HMS(&x);
|
|
Y = x.Y;
|
|
if( Y<0 ) Y = -Y;
|
|
zBuf[1] = '0' + (Y/1000)%10;
|
|
zBuf[2] = '0' + (Y/100)%10;
|
|
zBuf[3] = '0' + (Y/10)%10;
|
|
zBuf[4] = '0' + (Y)%10;
|
|
zBuf[5] = '-';
|
|
zBuf[6] = '0' + (x.M/10)%10;
|
|
zBuf[7] = '0' + (x.M)%10;
|
|
zBuf[8] = '-';
|
|
zBuf[9] = '0' + (x.D/10)%10;
|
|
zBuf[10] = '0' + (x.D)%10;
|
|
zBuf[11] = ' ';
|
|
zBuf[12] = '0' + (x.h/10)%10;
|
|
zBuf[13] = '0' + (x.h)%10;
|
|
zBuf[14] = ':';
|
|
zBuf[15] = '0' + (x.m/10)%10;
|
|
zBuf[16] = '0' + (x.m)%10;
|
|
zBuf[17] = ':';
|
|
if( x.useSubsec ){
|
|
s = (int)(1000.0*x.s + 0.5);
|
|
zBuf[18] = '0' + (s/10000)%10;
|
|
zBuf[19] = '0' + (s/1000)%10;
|
|
zBuf[20] = '.';
|
|
zBuf[21] = '0' + (s/100)%10;
|
|
zBuf[22] = '0' + (s/10)%10;
|
|
zBuf[23] = '0' + (s)%10;
|
|
zBuf[24] = 0;
|
|
n = 24;
|
|
}else{
|
|
s = (int)x.s;
|
|
zBuf[18] = '0' + (s/10)%10;
|
|
zBuf[19] = '0' + (s)%10;
|
|
zBuf[20] = 0;
|
|
n = 20;
|
|
}
|
|
if( x.Y<0 ){
|
|
zBuf[0] = '-';
|
|
sqlite3_result_text(context, zBuf, n, SQLITE_TRANSIENT);
|
|
}else{
|
|
sqlite3_result_text(context, &zBuf[1], n-1, SQLITE_TRANSIENT);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** time( TIMESTRING, MOD, MOD, ...)
|
|
**
|
|
** Return HH:MM:SS
|
|
*/
|
|
static void timeFunc(
|
|
sqlite3_context *context,
|
|
int argc,
|
|
sqlite3_value **argv
|
|
){
|
|
DateTime x;
|
|
if( isDate(context, argc, argv, &x)==0 ){
|
|
int s, n;
|
|
char zBuf[16];
|
|
computeHMS(&x);
|
|
zBuf[0] = '0' + (x.h/10)%10;
|
|
zBuf[1] = '0' + (x.h)%10;
|
|
zBuf[2] = ':';
|
|
zBuf[3] = '0' + (x.m/10)%10;
|
|
zBuf[4] = '0' + (x.m)%10;
|
|
zBuf[5] = ':';
|
|
if( x.useSubsec ){
|
|
s = (int)(1000.0*x.s + 0.5);
|
|
zBuf[6] = '0' + (s/10000)%10;
|
|
zBuf[7] = '0' + (s/1000)%10;
|
|
zBuf[8] = '.';
|
|
zBuf[9] = '0' + (s/100)%10;
|
|
zBuf[10] = '0' + (s/10)%10;
|
|
zBuf[11] = '0' + (s)%10;
|
|
zBuf[12] = 0;
|
|
n = 12;
|
|
}else{
|
|
s = (int)x.s;
|
|
zBuf[6] = '0' + (s/10)%10;
|
|
zBuf[7] = '0' + (s)%10;
|
|
zBuf[8] = 0;
|
|
n = 8;
|
|
}
|
|
sqlite3_result_text(context, zBuf, n, SQLITE_TRANSIENT);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** date( TIMESTRING, MOD, MOD, ...)
|
|
**
|
|
** Return YYYY-MM-DD
|
|
*/
|
|
static void dateFunc(
|
|
sqlite3_context *context,
|
|
int argc,
|
|
sqlite3_value **argv
|
|
){
|
|
DateTime x;
|
|
if( isDate(context, argc, argv, &x)==0 ){
|
|
int Y;
|
|
char zBuf[16];
|
|
computeYMD(&x);
|
|
Y = x.Y;
|
|
if( Y<0 ) Y = -Y;
|
|
zBuf[1] = '0' + (Y/1000)%10;
|
|
zBuf[2] = '0' + (Y/100)%10;
|
|
zBuf[3] = '0' + (Y/10)%10;
|
|
zBuf[4] = '0' + (Y)%10;
|
|
zBuf[5] = '-';
|
|
zBuf[6] = '0' + (x.M/10)%10;
|
|
zBuf[7] = '0' + (x.M)%10;
|
|
zBuf[8] = '-';
|
|
zBuf[9] = '0' + (x.D/10)%10;
|
|
zBuf[10] = '0' + (x.D)%10;
|
|
zBuf[11] = 0;
|
|
if( x.Y<0 ){
|
|
zBuf[0] = '-';
|
|
sqlite3_result_text(context, zBuf, 11, SQLITE_TRANSIENT);
|
|
}else{
|
|
sqlite3_result_text(context, &zBuf[1], 10, SQLITE_TRANSIENT);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** strftime( FORMAT, TIMESTRING, MOD, MOD, ...)
|
|
**
|
|
** Return a string described by FORMAT. Conversions as follows:
|
|
**
|
|
** %d day of month
|
|
** %f ** fractional seconds SS.SSS
|
|
** %H hour 00-24
|
|
** %j day of year 000-366
|
|
** %J ** julian day number
|
|
** %m month 01-12
|
|
** %M minute 00-59
|
|
** %s seconds since 1970-01-01
|
|
** %S seconds 00-59
|
|
** %w day of week 0-6 Sunday==0
|
|
** %W week of year 00-53
|
|
** %Y year 0000-9999
|
|
** %% %
|
|
*/
|
|
static void strftimeFunc(
|
|
sqlite3_context *context,
|
|
int argc,
|
|
sqlite3_value **argv
|
|
){
|
|
DateTime x;
|
|
size_t i,j;
|
|
sqlite3 *db;
|
|
const char *zFmt;
|
|
sqlite3_str sRes;
|
|
|
|
|
|
if( argc==0 ) return;
|
|
zFmt = (const char*)sqlite3_value_text(argv[0]);
|
|
if( zFmt==0 || isDate(context, argc-1, argv+1, &x) ) return;
|
|
db = sqlite3_context_db_handle(context);
|
|
sqlite3StrAccumInit(&sRes, 0, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
|
|
|
|
computeJD(&x);
|
|
computeYMD_HMS(&x);
|
|
for(i=j=0; zFmt[i]; i++){
|
|
char cf;
|
|
if( zFmt[i]!='%' ) continue;
|
|
if( j<i ) sqlite3_str_append(&sRes, zFmt+j, (int)(i-j));
|
|
i++;
|
|
j = i + 1;
|
|
cf = zFmt[i];
|
|
switch( cf ){
|
|
case 'd': /* Fall thru */
|
|
case 'e': {
|
|
sqlite3_str_appendf(&sRes, cf=='d' ? "%02d" : "%2d", x.D);
|
|
break;
|
|
}
|
|
case 'f': {
|
|
double s = x.s;
|
|
if( s>59.999 ) s = 59.999;
|
|
sqlite3_str_appendf(&sRes, "%06.3f", s);
|
|
break;
|
|
}
|
|
case 'F': {
|
|
sqlite3_str_appendf(&sRes, "%04d-%02d-%02d", x.Y, x.M, x.D);
|
|
break;
|
|
}
|
|
case 'H':
|
|
case 'k': {
|
|
sqlite3_str_appendf(&sRes, cf=='H' ? "%02d" : "%2d", x.h);
|
|
break;
|
|
}
|
|
case 'I': /* Fall thru */
|
|
case 'l': {
|
|
int h = x.h;
|
|
if( h>12 ) h -= 12;
|
|
if( h==0 ) h = 12;
|
|
sqlite3_str_appendf(&sRes, cf=='I' ? "%02d" : "%2d", h);
|
|
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 = (int)((x.iJD-y.iJD+43200000)/86400000);
|
|
if( cf=='W' ){
|
|
int wd; /* 0=Monday, 1=Tuesday, ... 6=Sunday */
|
|
wd = (int)(((x.iJD+43200000)/86400000)%7);
|
|
sqlite3_str_appendf(&sRes,"%02d",(nDay+7-wd)/7);
|
|
}else{
|
|
sqlite3_str_appendf(&sRes,"%03d",nDay+1);
|
|
}
|
|
break;
|
|
}
|
|
case 'J': {
|
|
sqlite3_str_appendf(&sRes,"%.16g",x.iJD/86400000.0);
|
|
break;
|
|
}
|
|
case 'm': {
|
|
sqlite3_str_appendf(&sRes,"%02d",x.M);
|
|
break;
|
|
}
|
|
case 'M': {
|
|
sqlite3_str_appendf(&sRes,"%02d",x.m);
|
|
break;
|
|
}
|
|
case 'p': /* Fall thru */
|
|
case 'P': {
|
|
if( x.h>=12 ){
|
|
sqlite3_str_append(&sRes, cf=='p' ? "PM" : "pm", 2);
|
|
}else{
|
|
sqlite3_str_append(&sRes, cf=='p' ? "AM" : "am", 2);
|
|
}
|
|
break;
|
|
}
|
|
case 'R': {
|
|
sqlite3_str_appendf(&sRes, "%02d:%02d", x.h, x.m);
|
|
break;
|
|
}
|
|
case 's': {
|
|
if( x.useSubsec ){
|
|
sqlite3_str_appendf(&sRes,"%.3f",
|
|
(x.iJD - 21086676*(i64)10000000)/1000.0);
|
|
}else{
|
|
i64 iS = (i64)(x.iJD/1000 - 21086676*(i64)10000);
|
|
sqlite3_str_appendf(&sRes,"%lld",iS);
|
|
}
|
|
break;
|
|
}
|
|
case 'S': {
|
|
sqlite3_str_appendf(&sRes,"%02d",(int)x.s);
|
|
break;
|
|
}
|
|
case 'T': {
|
|
sqlite3_str_appendf(&sRes,"%02d:%02d:%02d", x.h, x.m, (int)x.s);
|
|
break;
|
|
}
|
|
case 'u': /* Fall thru */
|
|
case 'w': {
|
|
char c = (char)(((x.iJD+129600000)/86400000) % 7) + '0';
|
|
if( c=='0' && cf=='u' ) c = '7';
|
|
sqlite3_str_appendchar(&sRes, 1, c);
|
|
break;
|
|
}
|
|
case 'Y': {
|
|
sqlite3_str_appendf(&sRes,"%04d",x.Y);
|
|
break;
|
|
}
|
|
case '%': {
|
|
sqlite3_str_appendchar(&sRes, 1, '%');
|
|
break;
|
|
}
|
|
default: {
|
|
sqlite3_str_reset(&sRes);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
if( j<i ) sqlite3_str_append(&sRes, zFmt+j, (int)(i-j));
|
|
sqlite3ResultStrAccum(context, &sRes);
|
|
}
|
|
|
|
/*
|
|
** current_time()
|
|
**
|
|
** This function returns the same value as time('now').
|
|
*/
|
|
static void ctimeFunc(
|
|
sqlite3_context *context,
|
|
int NotUsed,
|
|
sqlite3_value **NotUsed2
|
|
){
|
|
UNUSED_PARAMETER2(NotUsed, NotUsed2);
|
|
timeFunc(context, 0, 0);
|
|
}
|
|
|
|
/*
|
|
** current_date()
|
|
**
|
|
** This function returns the same value as date('now').
|
|
*/
|
|
static void cdateFunc(
|
|
sqlite3_context *context,
|
|
int NotUsed,
|
|
sqlite3_value **NotUsed2
|
|
){
|
|
UNUSED_PARAMETER2(NotUsed, NotUsed2);
|
|
dateFunc(context, 0, 0);
|
|
}
|
|
|
|
/*
|
|
** timediff(DATE1, DATE2)
|
|
**
|
|
** Return the amount of time that must be added to DATE2 in order to
|
|
** convert it into DATE2. The time difference format is:
|
|
**
|
|
** +YYYY-MM-DD HH:MM:SS.SSS
|
|
**
|
|
** The initial "+" becomes "-" if DATE1 occurs before DATE2. For
|
|
** date/time values A and B, the following invariant should hold:
|
|
**
|
|
** datetime(A) == (datetime(B, timediff(A,B))
|
|
**
|
|
** Both DATE arguments must be either a julian day number, or an
|
|
** ISO-8601 string. The unix timestamps are not supported by this
|
|
** routine.
|
|
*/
|
|
static void timediffFunc(
|
|
sqlite3_context *context,
|
|
int NotUsed1,
|
|
sqlite3_value **argv
|
|
){
|
|
char sign;
|
|
int Y, M;
|
|
DateTime d1, d2;
|
|
sqlite3_str sRes;
|
|
UNUSED_PARAMETER(NotUsed1);
|
|
if( isDate(context, 1, &argv[0], &d1) ) return;
|
|
if( isDate(context, 1, &argv[1], &d2) ) return;
|
|
computeYMD_HMS(&d1);
|
|
computeYMD_HMS(&d2);
|
|
if( d1.iJD>=d2.iJD ){
|
|
sign = '+';
|
|
Y = d1.Y - d2.Y;
|
|
if( Y ){
|
|
d2.Y = d1.Y;
|
|
d2.validJD = 0;
|
|
computeJD(&d2);
|
|
}
|
|
M = d1.M - d2.M;
|
|
if( M<0 ){
|
|
Y--;
|
|
M += 12;
|
|
}
|
|
if( M!=0 ){
|
|
d2.M = d1.M;
|
|
d2.validJD = 0;
|
|
computeJD(&d2);
|
|
}
|
|
while( d1.iJD<d2.iJD ){
|
|
M--;
|
|
if( M<0 ){
|
|
M = 11;
|
|
Y--;
|
|
}
|
|
d2.M--;
|
|
if( d2.M<1 ){
|
|
d2.M = 12;
|
|
d2.Y--;
|
|
}
|
|
d2.validJD = 0;
|
|
computeJD(&d2);
|
|
}
|
|
d1.iJD -= d2.iJD;
|
|
d1.iJD += (u64)1486995408 * (u64)100000;
|
|
}else /* d1<d2 */{
|
|
sign = '-';
|
|
Y = d2.Y - d1.Y;
|
|
if( Y ){
|
|
d2.Y = d1.Y;
|
|
d2.validJD = 0;
|
|
computeJD(&d2);
|
|
}
|
|
M = d2.M - d1.M;
|
|
if( M<0 ){
|
|
Y--;
|
|
M += 12;
|
|
}
|
|
if( M!=0 ){
|
|
d2.M = d1.M;
|
|
d2.validJD = 0;
|
|
computeJD(&d2);
|
|
}
|
|
while( d1.iJD>d2.iJD ){
|
|
M--;
|
|
if( M<0 ){
|
|
M = 11;
|
|
Y--;
|
|
}
|
|
d2.M++;
|
|
if( d2.M>12 ){
|
|
d2.M = 1;
|
|
d2.Y++;
|
|
}
|
|
d2.validJD = 0;
|
|
computeJD(&d2);
|
|
}
|
|
d1.iJD = d2.iJD - d1.iJD;
|
|
d1.iJD += (u64)1486995408 * (u64)100000;
|
|
}
|
|
d1.validYMD = 0;
|
|
d1.validHMS = 0;
|
|
d1.validTZ = 0;
|
|
computeYMD_HMS(&d1);
|
|
sqlite3StrAccumInit(&sRes, 0, 0, 0, 100);
|
|
sqlite3_str_appendf(&sRes, "%c%04d-%02d-%02d %02d:%02d:%06.3f",
|
|
sign, Y, M, d1.D-1, d1.h, d1.m, d1.s);
|
|
sqlite3ResultStrAccum(context, &sRes);
|
|
}
|
|
|
|
|
|
/*
|
|
** current_timestamp()
|
|
**
|
|
** This function returns the same value as datetime('now').
|
|
*/
|
|
static void ctimestampFunc(
|
|
sqlite3_context *context,
|
|
int NotUsed,
|
|
sqlite3_value **NotUsed2
|
|
){
|
|
UNUSED_PARAMETER2(NotUsed, NotUsed2);
|
|
datetimeFunc(context, 0, 0);
|
|
}
|
|
#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);
|
|
sqlite3_int64 iT;
|
|
struct tm *pTm;
|
|
struct tm sNow;
|
|
char zBuf[20];
|
|
|
|
UNUSED_PARAMETER(argc);
|
|
UNUSED_PARAMETER(argv);
|
|
|
|
iT = sqlite3StmtCurrentTime(context);
|
|
if( iT<=0 ) return;
|
|
t = iT/1000 - 10000*(sqlite3_int64)21086676;
|
|
#if HAVE_GMTIME_R
|
|
pTm = gmtime_r(&t, &sNow);
|
|
#else
|
|
sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN));
|
|
pTm = gmtime(&t);
|
|
if( pTm ) memcpy(&sNow, pTm, sizeof(sNow));
|
|
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN));
|
|
#endif
|
|
if( pTm ){
|
|
strftime(zBuf, 20, zFormat, &sNow);
|
|
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.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3RegisterDateTimeFunctions(void){
|
|
static FuncDef aDateTimeFuncs[] = {
|
|
#ifndef SQLITE_OMIT_DATETIME_FUNCS
|
|
PURE_DATE(julianday, -1, 0, 0, juliandayFunc ),
|
|
PURE_DATE(unixepoch, -1, 0, 0, unixepochFunc ),
|
|
PURE_DATE(date, -1, 0, 0, dateFunc ),
|
|
PURE_DATE(time, -1, 0, 0, timeFunc ),
|
|
PURE_DATE(datetime, -1, 0, 0, datetimeFunc ),
|
|
PURE_DATE(strftime, -1, 0, 0, strftimeFunc ),
|
|
PURE_DATE(timediff, 2, 0, 0, timediffFunc ),
|
|
DFUNCTION(current_time, 0, 0, 0, ctimeFunc ),
|
|
DFUNCTION(current_timestamp, 0, 0, 0, ctimestampFunc),
|
|
DFUNCTION(current_date, 0, 0, 0, cdateFunc ),
|
|
#else
|
|
STR_FUNCTION(current_time, 0, "%H:%M:%S", 0, currentTimeFunc),
|
|
STR_FUNCTION(current_date, 0, "%Y-%m-%d", 0, currentTimeFunc),
|
|
STR_FUNCTION(current_timestamp, 0, "%Y-%m-%d %H:%M:%S", 0, currentTimeFunc),
|
|
#endif
|
|
};
|
|
sqlite3InsertBuiltinFuncs(aDateTimeFuncs, ArraySize(aDateTimeFuncs));
|
|
}
|
|
|
|
/************** End of date.c ************************************************/
|
|
/************** Begin file os.c **********************************************/
|
|
/*
|
|
** 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.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
|
|
/*
|
|
** 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.
|
|
*/
|
|
#if defined(SQLITE_TEST)
|
|
SQLITE_API int sqlite3_io_error_hit = 0; /* Total number of I/O Errors */
|
|
SQLITE_API int sqlite3_io_error_hardhit = 0; /* Number of non-benign errors */
|
|
SQLITE_API int sqlite3_io_error_pending = 0; /* Count down to first I/O error */
|
|
SQLITE_API int sqlite3_io_error_persist = 0; /* True if I/O errors persist */
|
|
SQLITE_API int sqlite3_io_error_benign = 0; /* True if errors are benign */
|
|
SQLITE_API int sqlite3_diskfull_pending = 0;
|
|
SQLITE_API int sqlite3_diskfull = 0;
|
|
#endif /* defined(SQLITE_TEST) */
|
|
|
|
/*
|
|
** When testing, also keep a count of the number of open files.
|
|
*/
|
|
#if defined(SQLITE_TEST)
|
|
SQLITE_API int sqlite3_open_file_count = 0;
|
|
#endif /* defined(SQLITE_TEST) */
|
|
|
|
/*
|
|
** The default SQLite sqlite3_vfs implementations do not allocate
|
|
** memory (actually, os_unix.c allocates a small amount of memory
|
|
** from within OsOpen()), but some third-party implementations may.
|
|
** So we test the effects of a malloc() failing and the sqlite3OsXXX()
|
|
** function returning SQLITE_IOERR_NOMEM using the DO_OS_MALLOC_TEST macro.
|
|
**
|
|
** The following functions are instrumented for malloc() failure
|
|
** testing:
|
|
**
|
|
** sqlite3OsRead()
|
|
** sqlite3OsWrite()
|
|
** sqlite3OsSync()
|
|
** sqlite3OsFileSize()
|
|
** sqlite3OsLock()
|
|
** sqlite3OsCheckReservedLock()
|
|
** sqlite3OsFileControl()
|
|
** sqlite3OsShmMap()
|
|
** sqlite3OsOpen()
|
|
** sqlite3OsDelete()
|
|
** sqlite3OsAccess()
|
|
** sqlite3OsFullPathname()
|
|
**
|
|
*/
|
|
#if defined(SQLITE_TEST)
|
|
SQLITE_API int sqlite3_memdebug_vfs_oom_test = 1;
|
|
#define DO_OS_MALLOC_TEST(x) \
|
|
if (sqlite3_memdebug_vfs_oom_test && (!x || !sqlite3JournalIsInMemory(x))) { \
|
|
void *pTstAlloc = sqlite3Malloc(10); \
|
|
if (!pTstAlloc) return SQLITE_IOERR_NOMEM_BKPT; \
|
|
sqlite3_free(pTstAlloc); \
|
|
}
|
|
#else
|
|
#define DO_OS_MALLOC_TEST(x)
|
|
#endif
|
|
|
|
/*
|
|
** The following routines are convenience wrappers around methods
|
|
** of the sqlite3_file 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.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3OsClose(sqlite3_file *pId){
|
|
if( pId->pMethods ){
|
|
pId->pMethods->xClose(pId);
|
|
pId->pMethods = 0;
|
|
}
|
|
}
|
|
SQLITE_PRIVATE int sqlite3OsRead(sqlite3_file *id, void *pBuf, int amt, i64 offset){
|
|
DO_OS_MALLOC_TEST(id);
|
|
return id->pMethods->xRead(id, pBuf, amt, offset);
|
|
}
|
|
SQLITE_PRIVATE int sqlite3OsWrite(sqlite3_file *id, const void *pBuf, int amt, i64 offset){
|
|
DO_OS_MALLOC_TEST(id);
|
|
return id->pMethods->xWrite(id, pBuf, amt, offset);
|
|
}
|
|
SQLITE_PRIVATE int sqlite3OsTruncate(sqlite3_file *id, i64 size){
|
|
return id->pMethods->xTruncate(id, size);
|
|
}
|
|
SQLITE_PRIVATE int sqlite3OsSync(sqlite3_file *id, int flags){
|
|
DO_OS_MALLOC_TEST(id);
|
|
return flags ? id->pMethods->xSync(id, flags) : SQLITE_OK;
|
|
}
|
|
SQLITE_PRIVATE int sqlite3OsFileSize(sqlite3_file *id, i64 *pSize){
|
|
DO_OS_MALLOC_TEST(id);
|
|
return id->pMethods->xFileSize(id, pSize);
|
|
}
|
|
SQLITE_PRIVATE int sqlite3OsLock(sqlite3_file *id, int lockType){
|
|
DO_OS_MALLOC_TEST(id);
|
|
assert( lockType>=SQLITE_LOCK_SHARED && lockType<=SQLITE_LOCK_EXCLUSIVE );
|
|
return id->pMethods->xLock(id, lockType);
|
|
}
|
|
SQLITE_PRIVATE int sqlite3OsUnlock(sqlite3_file *id, int lockType){
|
|
assert( lockType==SQLITE_LOCK_NONE || lockType==SQLITE_LOCK_SHARED );
|
|
return id->pMethods->xUnlock(id, lockType);
|
|
}
|
|
SQLITE_PRIVATE int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut){
|
|
DO_OS_MALLOC_TEST(id);
|
|
return id->pMethods->xCheckReservedLock(id, pResOut);
|
|
}
|
|
|
|
/*
|
|
** Use sqlite3OsFileControl() when we are doing something that might fail
|
|
** and we need to know about the failures. Use sqlite3OsFileControlHint()
|
|
** when simply tossing information over the wall to the VFS and we do not
|
|
** really care if the VFS receives and understands the information since it
|
|
** is only a hint and can be safely ignored. The sqlite3OsFileControlHint()
|
|
** routine has no return value since the return value would be meaningless.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3OsFileControl(sqlite3_file *id, int op, void *pArg){
|
|
if( id->pMethods==0 ) return SQLITE_NOTFOUND;
|
|
#ifdef SQLITE_TEST
|
|
if( op!=SQLITE_FCNTL_COMMIT_PHASETWO
|
|
&& op!=SQLITE_FCNTL_LOCK_TIMEOUT
|
|
&& op!=SQLITE_FCNTL_CKPT_DONE
|
|
&& op!=SQLITE_FCNTL_CKPT_START
|
|
){
|
|
/* Faults are not injected into COMMIT_PHASETWO because, assuming SQLite
|
|
** is using a regular VFS, it is called after the corresponding
|
|
** transaction has been committed. Injecting a fault at this point
|
|
** confuses the test scripts - the COMMIT command returns SQLITE_NOMEM
|
|
** but the transaction is committed anyway.
|
|
**
|
|
** The core must call OsFileControl() though, not OsFileControlHint(),
|
|
** as if a custom VFS (e.g. zipvfs) returns an error here, it probably
|
|
** means the commit really has failed and an error should be returned
|
|
** to the user.
|
|
**
|
|
** The CKPT_DONE and CKPT_START file-controls are write-only signals
|
|
** to the cksumvfs. Their return code is meaningless and is ignored
|
|
** by the SQLite core, so there is no point in simulating OOMs for them.
|
|
*/
|
|
DO_OS_MALLOC_TEST(id);
|
|
}
|
|
#endif
|
|
return id->pMethods->xFileControl(id, op, pArg);
|
|
}
|
|
SQLITE_PRIVATE void sqlite3OsFileControlHint(sqlite3_file *id, int op, void *pArg){
|
|
if( id->pMethods ) (void)id->pMethods->xFileControl(id, op, pArg);
|
|
}
|
|
|
|
SQLITE_PRIVATE int sqlite3OsSectorSize(sqlite3_file *id){
|
|
int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize;
|
|
return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE);
|
|
}
|
|
SQLITE_PRIVATE int sqlite3OsDeviceCharacteristics(sqlite3_file *id){
|
|
if( NEVER(id->pMethods==0) ) return 0;
|
|
return id->pMethods->xDeviceCharacteristics(id);
|
|
}
|
|
#ifndef SQLITE_OMIT_WAL
|
|
SQLITE_PRIVATE int sqlite3OsShmLock(sqlite3_file *id, int offset, int n, int flags){
|
|
return id->pMethods->xShmLock(id, offset, n, flags);
|
|
}
|
|
SQLITE_PRIVATE void sqlite3OsShmBarrier(sqlite3_file *id){
|
|
id->pMethods->xShmBarrier(id);
|
|
}
|
|
SQLITE_PRIVATE int sqlite3OsShmUnmap(sqlite3_file *id, int deleteFlag){
|
|
return id->pMethods->xShmUnmap(id, deleteFlag);
|
|
}
|
|
SQLITE_PRIVATE int sqlite3OsShmMap(
|
|
sqlite3_file *id, /* Database file handle */
|
|
int iPage,
|
|
int pgsz,
|
|
int bExtend, /* True to extend file if necessary */
|
|
void volatile **pp /* OUT: Pointer to mapping */
|
|
){
|
|
DO_OS_MALLOC_TEST(id);
|
|
return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp);
|
|
}
|
|
#endif /* SQLITE_OMIT_WAL */
|
|
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
/* The real implementation of xFetch and xUnfetch */
|
|
SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){
|
|
DO_OS_MALLOC_TEST(id);
|
|
return id->pMethods->xFetch(id, iOff, iAmt, pp);
|
|
}
|
|
SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){
|
|
return id->pMethods->xUnfetch(id, iOff, p);
|
|
}
|
|
#else
|
|
/* No-op stubs to use when memory-mapped I/O is disabled */
|
|
SQLITE_PRIVATE int sqlite3OsFetch(sqlite3_file *id, i64 iOff, int iAmt, void **pp){
|
|
*pp = 0;
|
|
return SQLITE_OK;
|
|
}
|
|
SQLITE_PRIVATE int sqlite3OsUnfetch(sqlite3_file *id, i64 iOff, void *p){
|
|
return SQLITE_OK;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
** The next group of routines are convenience wrappers around the
|
|
** VFS methods.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3OsOpen(
|
|
sqlite3_vfs *pVfs,
|
|
const char *zPath,
|
|
sqlite3_file *pFile,
|
|
int flags,
|
|
int *pFlagsOut
|
|
){
|
|
int rc;
|
|
DO_OS_MALLOC_TEST(0);
|
|
/* 0x87f7f is a mask of SQLITE_OPEN_ flags that are valid to be passed
|
|
** down into the VFS layer. Some SQLITE_OPEN_ flags (for example,
|
|
** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
|
|
** reaching the VFS. */
|
|
assert( zPath || (flags & SQLITE_OPEN_EXCLUSIVE) );
|
|
rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x1087f7f, pFlagsOut);
|
|
assert( rc==SQLITE_OK || pFile->pMethods==0 );
|
|
return rc;
|
|
}
|
|
SQLITE_PRIVATE int sqlite3OsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
|
|
DO_OS_MALLOC_TEST(0);
|
|
assert( dirSync==0 || dirSync==1 );
|
|
return pVfs->xDelete!=0 ? pVfs->xDelete(pVfs, zPath, dirSync) : SQLITE_OK;
|
|
}
|
|
SQLITE_PRIVATE int sqlite3OsAccess(
|
|
sqlite3_vfs *pVfs,
|
|
const char *zPath,
|
|
int flags,
|
|
int *pResOut
|
|
){
|
|
DO_OS_MALLOC_TEST(0);
|
|
return pVfs->xAccess(pVfs, zPath, flags, pResOut);
|
|
}
|
|
SQLITE_PRIVATE int sqlite3OsFullPathname(
|
|
sqlite3_vfs *pVfs,
|
|
const char *zPath,
|
|
int nPathOut,
|
|
char *zPathOut
|
|
){
|
|
DO_OS_MALLOC_TEST(0);
|
|
zPathOut[0] = 0;
|
|
return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut);
|
|
}
|
|
#ifndef SQLITE_OMIT_LOAD_EXTENSION
|
|
SQLITE_PRIVATE void *sqlite3OsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
|
|
assert( zPath!=0 );
|
|
assert( strlen(zPath)<=SQLITE_MAX_PATHLEN ); /* tag-20210611-1 */
|
|
return pVfs->xDlOpen(pVfs, zPath);
|
|
}
|
|
SQLITE_PRIVATE void sqlite3OsDlError(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
|
|
pVfs->xDlError(pVfs, nByte, zBufOut);
|
|
}
|
|
SQLITE_PRIVATE void (*sqlite3OsDlSym(sqlite3_vfs *pVfs, void *pHdle, const char *zSym))(void){
|
|
return pVfs->xDlSym(pVfs, pHdle, zSym);
|
|
}
|
|
SQLITE_PRIVATE void sqlite3OsDlClose(sqlite3_vfs *pVfs, void *pHandle){
|
|
pVfs->xDlClose(pVfs, pHandle);
|
|
}
|
|
#endif /* SQLITE_OMIT_LOAD_EXTENSION */
|
|
SQLITE_PRIVATE int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
|
|
if( sqlite3Config.iPrngSeed ){
|
|
memset(zBufOut, 0, nByte);
|
|
if( ALWAYS(nByte>(signed)sizeof(unsigned)) ) nByte = sizeof(unsigned int);
|
|
memcpy(zBufOut, &sqlite3Config.iPrngSeed, nByte);
|
|
return SQLITE_OK;
|
|
}else{
|
|
return pVfs->xRandomness(pVfs, nByte, zBufOut);
|
|
}
|
|
|
|
}
|
|
SQLITE_PRIVATE int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){
|
|
return pVfs->xSleep(pVfs, nMicro);
|
|
}
|
|
SQLITE_PRIVATE int sqlite3OsGetLastError(sqlite3_vfs *pVfs){
|
|
return pVfs->xGetLastError ? pVfs->xGetLastError(pVfs, 0, 0) : 0;
|
|
}
|
|
SQLITE_PRIVATE int sqlite3OsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
|
|
int rc;
|
|
/* IMPLEMENTATION-OF: R-49045-42493 SQLite will use the xCurrentTimeInt64()
|
|
** method to get the current date and time if that method is available
|
|
** (if iVersion is 2 or greater and the function pointer is not NULL) and
|
|
** will fall back to xCurrentTime() if xCurrentTimeInt64() is
|
|
** unavailable.
|
|
*/
|
|
if( pVfs->iVersion>=2 && pVfs->xCurrentTimeInt64 ){
|
|
rc = pVfs->xCurrentTimeInt64(pVfs, pTimeOut);
|
|
}else{
|
|
double r;
|
|
rc = pVfs->xCurrentTime(pVfs, &r);
|
|
*pTimeOut = (sqlite3_int64)(r*86400000.0);
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
SQLITE_PRIVATE int sqlite3OsOpenMalloc(
|
|
sqlite3_vfs *pVfs,
|
|
const char *zFile,
|
|
sqlite3_file **ppFile,
|
|
int flags,
|
|
int *pOutFlags
|
|
){
|
|
int rc;
|
|
sqlite3_file *pFile;
|
|
pFile = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile);
|
|
if( pFile ){
|
|
rc = sqlite3OsOpen(pVfs, zFile, pFile, flags, pOutFlags);
|
|
if( rc!=SQLITE_OK ){
|
|
sqlite3_free(pFile);
|
|
*ppFile = 0;
|
|
}else{
|
|
*ppFile = pFile;
|
|
}
|
|
}else{
|
|
*ppFile = 0;
|
|
rc = SQLITE_NOMEM_BKPT;
|
|
}
|
|
assert( *ppFile!=0 || rc!=SQLITE_OK );
|
|
return rc;
|
|
}
|
|
SQLITE_PRIVATE void sqlite3OsCloseFree(sqlite3_file *pFile){
|
|
assert( pFile );
|
|
sqlite3OsClose(pFile);
|
|
sqlite3_free(pFile);
|
|
}
|
|
|
|
/*
|
|
** This function is a wrapper around the OS specific implementation of
|
|
** sqlite3_os_init(). The purpose of the wrapper is to provide the
|
|
** ability to simulate a malloc failure, so that the handling of an
|
|
** error in sqlite3_os_init() by the upper layers can be tested.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3OsInit(void){
|
|
void *p = sqlite3_malloc(10);
|
|
if( p==0 ) return SQLITE_NOMEM_BKPT;
|
|
sqlite3_free(p);
|
|
return sqlite3_os_init();
|
|
}
|
|
|
|
/*
|
|
** The list of all registered VFS implementations.
|
|
*/
|
|
static sqlite3_vfs * SQLITE_WSD vfsList = 0;
|
|
#define vfsList GLOBAL(sqlite3_vfs *, vfsList)
|
|
|
|
/*
|
|
** Locate a VFS by name. If no name is given, simply return the
|
|
** first VFS on the list.
|
|
*/
|
|
SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){
|
|
sqlite3_vfs *pVfs = 0;
|
|
#if SQLITE_THREADSAFE
|
|
sqlite3_mutex *mutex;
|
|
#endif
|
|
#ifndef SQLITE_OMIT_AUTOINIT
|
|
int rc = sqlite3_initialize();
|
|
if( rc ) return 0;
|
|
#endif
|
|
#if SQLITE_THREADSAFE
|
|
mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN);
|
|
#endif
|
|
sqlite3_mutex_enter(mutex);
|
|
for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){
|
|
if( zVfs==0 ) break;
|
|
if( strcmp(zVfs, pVfs->zName)==0 ) break;
|
|
}
|
|
sqlite3_mutex_leave(mutex);
|
|
return pVfs;
|
|
}
|
|
|
|
/*
|
|
** Unlink a VFS from the linked list
|
|
*/
|
|
static void vfsUnlink(sqlite3_vfs *pVfs){
|
|
assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN)) );
|
|
if( pVfs==0 ){
|
|
/* No-op */
|
|
}else if( vfsList==pVfs ){
|
|
vfsList = pVfs->pNext;
|
|
}else if( vfsList ){
|
|
sqlite3_vfs *p = vfsList;
|
|
while( p->pNext && p->pNext!=pVfs ){
|
|
p = p->pNext;
|
|
}
|
|
if( p->pNext==pVfs ){
|
|
p->pNext = pVfs->pNext;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Register a VFS with the system. It is harmless to register the same
|
|
** VFS multiple times. The new VFS becomes the default if makeDflt is
|
|
** true.
|
|
*/
|
|
SQLITE_API int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){
|
|
MUTEX_LOGIC(sqlite3_mutex *mutex;)
|
|
#ifndef SQLITE_OMIT_AUTOINIT
|
|
int rc = sqlite3_initialize();
|
|
if( rc ) return rc;
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
|
if( pVfs==0 ) return SQLITE_MISUSE_BKPT;
|
|
#endif
|
|
|
|
MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); )
|
|
sqlite3_mutex_enter(mutex);
|
|
vfsUnlink(pVfs);
|
|
if( makeDflt || vfsList==0 ){
|
|
pVfs->pNext = vfsList;
|
|
vfsList = pVfs;
|
|
}else{
|
|
pVfs->pNext = vfsList->pNext;
|
|
vfsList->pNext = pVfs;
|
|
}
|
|
assert(vfsList);
|
|
sqlite3_mutex_leave(mutex);
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Unregister a VFS so that it is no longer accessible.
|
|
*/
|
|
SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){
|
|
MUTEX_LOGIC(sqlite3_mutex *mutex;)
|
|
#ifndef SQLITE_OMIT_AUTOINIT
|
|
int rc = sqlite3_initialize();
|
|
if( rc ) return rc;
|
|
#endif
|
|
MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); )
|
|
sqlite3_mutex_enter(mutex);
|
|
vfsUnlink(pVfs);
|
|
sqlite3_mutex_leave(mutex);
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/************** End of os.c **************************************************/
|
|
/************** Begin file fault.c *******************************************/
|
|
/*
|
|
** 2008 Jan 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 to support the concept of "benign"
|
|
** malloc failures (when the xMalloc() or xRealloc() method of the
|
|
** sqlite3_mem_methods structure fails to allocate a block of memory
|
|
** and returns 0).
|
|
**
|
|
** Most malloc failures are non-benign. After they occur, SQLite
|
|
** abandons the current operation and returns an error code (usually
|
|
** SQLITE_NOMEM) to the user. However, sometimes a fault is not necessarily
|
|
** fatal. For example, if a malloc fails while resizing a hash table, this
|
|
** is completely recoverable simply by not carrying out the resize. The
|
|
** hash table will continue to function normally. So a malloc failure
|
|
** during a hash table resize is a benign fault.
|
|
*/
|
|
|
|
/* #include "sqliteInt.h" */
|
|
|
|
#ifndef SQLITE_UNTESTABLE
|
|
|
|
/*
|
|
** Global variables.
|
|
*/
|
|
typedef struct BenignMallocHooks BenignMallocHooks;
|
|
static SQLITE_WSD struct BenignMallocHooks {
|
|
void (*xBenignBegin)(void);
|
|
void (*xBenignEnd)(void);
|
|
} sqlite3Hooks = { 0, 0 };
|
|
|
|
/* The "wsdHooks" macro will resolve to the appropriate BenignMallocHooks
|
|
** structure. If writable static data is unsupported on the target,
|
|
** we have to locate the state vector at run-time. In the more common
|
|
** case where writable static data is supported, wsdHooks can refer directly
|
|
** to the "sqlite3Hooks" state vector declared above.
|
|
*/
|
|
#ifdef SQLITE_OMIT_WSD
|
|
# define wsdHooksInit \
|
|
BenignMallocHooks *x = &GLOBAL(BenignMallocHooks,sqlite3Hooks)
|
|
# define wsdHooks x[0]
|
|
#else
|
|
# define wsdHooksInit
|
|
# define wsdHooks sqlite3Hooks
|
|
#endif
|
|
|
|
|
|
/*
|
|
** Register hooks to call when sqlite3BeginBenignMalloc() and
|
|
** sqlite3EndBenignMalloc() are called, respectively.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3BenignMallocHooks(
|
|
void (*xBenignBegin)(void),
|
|
void (*xBenignEnd)(void)
|
|
){
|
|
wsdHooksInit;
|
|
wsdHooks.xBenignBegin = xBenignBegin;
|
|
wsdHooks.xBenignEnd = xBenignEnd;
|
|
}
|
|
|
|
/*
|
|
** This (sqlite3EndBenignMalloc()) is called by SQLite code to indicate that
|
|
** subsequent malloc failures are benign. A call to sqlite3EndBenignMalloc()
|
|
** indicates that subsequent malloc failures are non-benign.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3BeginBenignMalloc(void){
|
|
wsdHooksInit;
|
|
if( wsdHooks.xBenignBegin ){
|
|
wsdHooks.xBenignBegin();
|
|
}
|
|
}
|
|
SQLITE_PRIVATE void sqlite3EndBenignMalloc(void){
|
|
wsdHooksInit;
|
|
if( wsdHooks.xBenignEnd ){
|
|
wsdHooks.xBenignEnd();
|
|
}
|
|
}
|
|
|
|
#endif /* #ifndef SQLITE_UNTESTABLE */
|
|
|
|
/************** End of fault.c ***********************************************/
|
|
/************** Begin file mem0.c ********************************************/
|
|
/*
|
|
** 2008 October 28
|
|
**
|
|
** 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 a no-op memory allocation drivers for use when
|
|
** SQLITE_ZERO_MALLOC is defined. The allocation drivers implemented
|
|
** here always fail. SQLite will not operate with these drivers. These
|
|
** are merely placeholders. Real drivers must be substituted using
|
|
** sqlite3_config() before SQLite will operate.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
|
|
/*
|
|
** This version of the memory allocator is the default. It is
|
|
** used when no other memory allocator is specified using compile-time
|
|
** macros.
|
|
*/
|
|
#ifdef SQLITE_ZERO_MALLOC
|
|
|
|
/*
|
|
** No-op versions of all memory allocation routines
|
|
*/
|
|
static void *sqlite3MemMalloc(int nByte){ return 0; }
|
|
static void sqlite3MemFree(void *pPrior){ return; }
|
|
static void *sqlite3MemRealloc(void *pPrior, int nByte){ return 0; }
|
|
static int sqlite3MemSize(void *pPrior){ return 0; }
|
|
static int sqlite3MemRoundup(int n){ return n; }
|
|
static int sqlite3MemInit(void *NotUsed){ return SQLITE_OK; }
|
|
static void sqlite3MemShutdown(void *NotUsed){ return; }
|
|
|
|
/*
|
|
** This routine is the only routine in this file with external linkage.
|
|
**
|
|
** Populate the low-level memory allocation function pointers in
|
|
** sqlite3GlobalConfig.m with pointers to the routines in this file.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3MemSetDefault(void){
|
|
static const sqlite3_mem_methods defaultMethods = {
|
|
sqlite3MemMalloc,
|
|
sqlite3MemFree,
|
|
sqlite3MemRealloc,
|
|
sqlite3MemSize,
|
|
sqlite3MemRoundup,
|
|
sqlite3MemInit,
|
|
sqlite3MemShutdown,
|
|
0
|
|
};
|
|
sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
|
|
}
|
|
|
|
#endif /* SQLITE_ZERO_MALLOC */
|
|
|
|
/************** End of mem0.c ************************************************/
|
|
/************** Begin file mem1.c ********************************************/
|
|
/*
|
|
** 2007 August 14
|
|
**
|
|
** 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 low-level memory allocation drivers for when
|
|
** SQLite will use the standard C-library malloc/realloc/free interface
|
|
** to obtain the memory it needs.
|
|
**
|
|
** This file contains implementations of the low-level memory allocation
|
|
** routines specified in the sqlite3_mem_methods object. The content of
|
|
** this file is only used if SQLITE_SYSTEM_MALLOC is defined. The
|
|
** SQLITE_SYSTEM_MALLOC macro is defined automatically if neither the
|
|
** SQLITE_MEMDEBUG nor the SQLITE_WIN32_MALLOC macros are defined. The
|
|
** default configuration is to use memory allocation routines in this
|
|
** file.
|
|
**
|
|
** C-preprocessor macro summary:
|
|
**
|
|
** HAVE_MALLOC_USABLE_SIZE The configure script sets this symbol if
|
|
** the malloc_usable_size() interface exists
|
|
** on the target platform. Or, this symbol
|
|
** can be set manually, if desired.
|
|
** If an equivalent interface exists by
|
|
** a different name, using a separate -D
|
|
** option to rename it.
|
|
**
|
|
** SQLITE_WITHOUT_ZONEMALLOC Some older macs lack support for the zone
|
|
** memory allocator. Set this symbol to enable
|
|
** building on older macs.
|
|
**
|
|
** SQLITE_WITHOUT_MSIZE Set this symbol to disable the use of
|
|
** _msize() on windows systems. This might
|
|
** be necessary when compiling for Delphi,
|
|
** for example.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
|
|
/*
|
|
** This version of the memory allocator is the default. It is
|
|
** used when no other memory allocator is specified using compile-time
|
|
** macros.
|
|
*/
|
|
#ifdef SQLITE_SYSTEM_MALLOC
|
|
#if defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC)
|
|
|
|
/*
|
|
** Use the zone allocator available on apple products unless the
|
|
** SQLITE_WITHOUT_ZONEMALLOC symbol is defined.
|
|
*/
|
|
#include <sys/sysctl.h>
|
|
#include <malloc/malloc.h>
|
|
#ifdef SQLITE_MIGHT_BE_SINGLE_CORE
|
|
#include <libkern/OSAtomic.h>
|
|
#endif /* SQLITE_MIGHT_BE_SINGLE_CORE */
|
|
static malloc_zone_t* _sqliteZone_;
|
|
#define SQLITE_MALLOC(x) malloc_zone_malloc(_sqliteZone_, (x))
|
|
#define SQLITE_FREE(x) malloc_zone_free(_sqliteZone_, (x));
|
|
#define SQLITE_REALLOC(x,y) malloc_zone_realloc(_sqliteZone_, (x), (y))
|
|
#define SQLITE_MALLOCSIZE(x) \
|
|
(_sqliteZone_ ? _sqliteZone_->size(_sqliteZone_,x) : malloc_size(x))
|
|
|
|
#else /* if not __APPLE__ */
|
|
|
|
/*
|
|
** Use standard C library malloc and free on non-Apple systems.
|
|
** Also used by Apple systems if SQLITE_WITHOUT_ZONEMALLOC is defined.
|
|
*/
|
|
#define SQLITE_MALLOC(x) malloc(x)
|
|
#define SQLITE_FREE(x) free(x)
|
|
#define SQLITE_REALLOC(x,y) realloc((x),(y))
|
|
|
|
/*
|
|
** The malloc.h header file is needed for malloc_usable_size() function
|
|
** on some systems (e.g. Linux).
|
|
*/
|
|
#if HAVE_MALLOC_H && HAVE_MALLOC_USABLE_SIZE
|
|
# define SQLITE_USE_MALLOC_H 1
|
|
# define SQLITE_USE_MALLOC_USABLE_SIZE 1
|
|
/*
|
|
** The MSVCRT has malloc_usable_size(), but it is called _msize(). The
|
|
** use of _msize() is automatic, but can be disabled by compiling with
|
|
** -DSQLITE_WITHOUT_MSIZE. Using the _msize() function also requires
|
|
** the malloc.h header file.
|
|
*/
|
|
#elif defined(_MSC_VER) && !defined(SQLITE_WITHOUT_MSIZE)
|
|
# define SQLITE_USE_MALLOC_H
|
|
# define SQLITE_USE_MSIZE
|
|
#endif
|
|
|
|
/*
|
|
** Include the malloc.h header file, if necessary. Also set define macro
|
|
** SQLITE_MALLOCSIZE to the appropriate function name, which is _msize()
|
|
** for MSVC and malloc_usable_size() for most other systems (e.g. Linux).
|
|
** The memory size function can always be overridden manually by defining
|
|
** the macro SQLITE_MALLOCSIZE to the desired function name.
|
|
*/
|
|
#if defined(SQLITE_USE_MALLOC_H)
|
|
# include <malloc.h>
|
|
# if defined(SQLITE_USE_MALLOC_USABLE_SIZE)
|
|
# if !defined(SQLITE_MALLOCSIZE)
|
|
# define SQLITE_MALLOCSIZE(x) malloc_usable_size(x)
|
|
# endif
|
|
# elif defined(SQLITE_USE_MSIZE)
|
|
# if !defined(SQLITE_MALLOCSIZE)
|
|
# define SQLITE_MALLOCSIZE _msize
|
|
# endif
|
|
# endif
|
|
#endif /* defined(SQLITE_USE_MALLOC_H) */
|
|
|
|
#endif /* __APPLE__ or not __APPLE__ */
|
|
|
|
/*
|
|
** Like malloc(), but remember the size of the allocation
|
|
** so that we can find it later using sqlite3MemSize().
|
|
**
|
|
** For this low-level routine, we are guaranteed that nByte>0 because
|
|
** cases of nByte<=0 will be intercepted and dealt with by higher level
|
|
** routines.
|
|
*/
|
|
static void *sqlite3MemMalloc(int nByte){
|
|
#ifdef SQLITE_MALLOCSIZE
|
|
void *p;
|
|
testcase( ROUND8(nByte)==nByte );
|
|
p = SQLITE_MALLOC( nByte );
|
|
if( p==0 ){
|
|
testcase( sqlite3GlobalConfig.xLog!=0 );
|
|
sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
|
|
}
|
|
return p;
|
|
#else
|
|
sqlite3_int64 *p;
|
|
assert( nByte>0 );
|
|
testcase( ROUND8(nByte)!=nByte );
|
|
p = SQLITE_MALLOC( nByte+8 );
|
|
if( p ){
|
|
p[0] = nByte;
|
|
p++;
|
|
}else{
|
|
testcase( sqlite3GlobalConfig.xLog!=0 );
|
|
sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
|
|
}
|
|
return (void *)p;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
** Like free() but works for allocations obtained from sqlite3MemMalloc()
|
|
** or sqlite3MemRealloc().
|
|
**
|
|
** For this low-level routine, we already know that pPrior!=0 since
|
|
** cases where pPrior==0 will have been intercepted and dealt with
|
|
** by higher-level routines.
|
|
*/
|
|
static void sqlite3MemFree(void *pPrior){
|
|
#ifdef SQLITE_MALLOCSIZE
|
|
SQLITE_FREE(pPrior);
|
|
#else
|
|
sqlite3_int64 *p = (sqlite3_int64*)pPrior;
|
|
assert( pPrior!=0 );
|
|
p--;
|
|
SQLITE_FREE(p);
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
** Report the allocated size of a prior return from xMalloc()
|
|
** or xRealloc().
|
|
*/
|
|
static int sqlite3MemSize(void *pPrior){
|
|
#ifdef SQLITE_MALLOCSIZE
|
|
assert( pPrior!=0 );
|
|
return (int)SQLITE_MALLOCSIZE(pPrior);
|
|
#else
|
|
sqlite3_int64 *p;
|
|
assert( pPrior!=0 );
|
|
p = (sqlite3_int64*)pPrior;
|
|
p--;
|
|
return (int)p[0];
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
** Like realloc(). Resize an allocation previously obtained from
|
|
** sqlite3MemMalloc().
|
|
**
|
|
** For this low-level interface, we know that pPrior!=0. Cases where
|
|
** pPrior==0 while have been intercepted by higher-level routine and
|
|
** redirected to xMalloc. Similarly, we know that nByte>0 because
|
|
** cases where nByte<=0 will have been intercepted by higher-level
|
|
** routines and redirected to xFree.
|
|
*/
|
|
static void *sqlite3MemRealloc(void *pPrior, int nByte){
|
|
#ifdef SQLITE_MALLOCSIZE
|
|
void *p = SQLITE_REALLOC(pPrior, nByte);
|
|
if( p==0 ){
|
|
testcase( sqlite3GlobalConfig.xLog!=0 );
|
|
sqlite3_log(SQLITE_NOMEM,
|
|
"failed memory resize %u to %u bytes",
|
|
SQLITE_MALLOCSIZE(pPrior), nByte);
|
|
}
|
|
return p;
|
|
#else
|
|
sqlite3_int64 *p = (sqlite3_int64*)pPrior;
|
|
assert( pPrior!=0 && nByte>0 );
|
|
assert( nByte==ROUND8(nByte) ); /* EV: R-46199-30249 */
|
|
p--;
|
|
p = SQLITE_REALLOC(p, nByte+8 );
|
|
if( p ){
|
|
p[0] = nByte;
|
|
p++;
|
|
}else{
|
|
testcase( sqlite3GlobalConfig.xLog!=0 );
|
|
sqlite3_log(SQLITE_NOMEM,
|
|
"failed memory resize %u to %u bytes",
|
|
sqlite3MemSize(pPrior), nByte);
|
|
}
|
|
return (void*)p;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
** Round up a request size to the next valid allocation size.
|
|
*/
|
|
static int sqlite3MemRoundup(int n){
|
|
return ROUND8(n);
|
|
}
|
|
|
|
/*
|
|
** Initialize this module.
|
|
*/
|
|
static int sqlite3MemInit(void *NotUsed){
|
|
#if defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC)
|
|
int cpuCount;
|
|
size_t len;
|
|
if( _sqliteZone_ ){
|
|
return SQLITE_OK;
|
|
}
|
|
len = sizeof(cpuCount);
|
|
/* One usually wants to use hw.activecpu for MT decisions, but not here */
|
|
sysctlbyname("hw.ncpu", &cpuCount, &len, NULL, 0);
|
|
if( cpuCount>1 ){
|
|
/* defer MT decisions to system malloc */
|
|
_sqliteZone_ = malloc_default_zone();
|
|
}else{
|
|
/* only 1 core, use our own zone to contention over global locks,
|
|
** e.g. we have our own dedicated locks */
|
|
_sqliteZone_ = malloc_create_zone(4096, 0);
|
|
malloc_set_zone_name(_sqliteZone_, "Sqlite_Heap");
|
|
}
|
|
#endif /* defined(__APPLE__) && !defined(SQLITE_WITHOUT_ZONEMALLOC) */
|
|
UNUSED_PARAMETER(NotUsed);
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Deinitialize this module.
|
|
*/
|
|
static void sqlite3MemShutdown(void *NotUsed){
|
|
UNUSED_PARAMETER(NotUsed);
|
|
return;
|
|
}
|
|
|
|
/*
|
|
** This routine is the only routine in this file with external linkage.
|
|
**
|
|
** Populate the low-level memory allocation function pointers in
|
|
** sqlite3GlobalConfig.m with pointers to the routines in this file.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3MemSetDefault(void){
|
|
static const sqlite3_mem_methods defaultMethods = {
|
|
sqlite3MemMalloc,
|
|
sqlite3MemFree,
|
|
sqlite3MemRealloc,
|
|
sqlite3MemSize,
|
|
sqlite3MemRoundup,
|
|
sqlite3MemInit,
|
|
sqlite3MemShutdown,
|
|
0
|
|
};
|
|
sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
|
|
}
|
|
|
|
#endif /* SQLITE_SYSTEM_MALLOC */
|
|
|
|
/************** End of mem1.c ************************************************/
|
|
/************** Begin file mem2.c ********************************************/
|
|
/*
|
|
** 2007 August 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 low-level memory allocation drivers for when
|
|
** SQLite will use the standard C-library malloc/realloc/free interface
|
|
** to obtain the memory it needs while adding lots of additional debugging
|
|
** information to each allocation in order to help detect and fix memory
|
|
** leaks and memory usage errors.
|
|
**
|
|
** This file contains implementations of the low-level memory allocation
|
|
** routines specified in the sqlite3_mem_methods object.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
|
|
/*
|
|
** This version of the memory allocator is used only if the
|
|
** SQLITE_MEMDEBUG macro is defined
|
|
*/
|
|
#ifdef SQLITE_MEMDEBUG
|
|
|
|
/*
|
|
** The backtrace functionality is only available with GLIBC
|
|
*/
|
|
#ifdef __GLIBC__
|
|
extern int backtrace(void**,int);
|
|
extern void backtrace_symbols_fd(void*const*,int,int);
|
|
#else
|
|
# define backtrace(A,B) 1
|
|
# define backtrace_symbols_fd(A,B,C)
|
|
#endif
|
|
/* #include <stdio.h> */
|
|
|
|
/*
|
|
** Each memory allocation looks like this:
|
|
**
|
|
** ------------------------------------------------------------------------
|
|
** | Title | backtrace pointers | MemBlockHdr | allocation | EndGuard |
|
|
** ------------------------------------------------------------------------
|
|
**
|
|
** The application code sees only a pointer to the allocation. We have
|
|
** to back up from the allocation pointer to find the MemBlockHdr. The
|
|
** MemBlockHdr tells us the size of the allocation and the number of
|
|
** backtrace pointers. There is also a guard word at the end of the
|
|
** MemBlockHdr.
|
|
*/
|
|
struct MemBlockHdr {
|
|
i64 iSize; /* Size of this allocation */
|
|
struct MemBlockHdr *pNext, *pPrev; /* Linked list of all unfreed memory */
|
|
char nBacktrace; /* Number of backtraces on this alloc */
|
|
char nBacktraceSlots; /* Available backtrace slots */
|
|
u8 nTitle; /* Bytes of title; includes '\0' */
|
|
u8 eType; /* Allocation type code */
|
|
int iForeGuard; /* Guard word for sanity */
|
|
};
|
|
|
|
/*
|
|
** Guard words
|
|
*/
|
|
#define FOREGUARD 0x80F5E153
|
|
#define REARGUARD 0xE4676B53
|
|
|
|
/*
|
|
** Number of malloc size increments to track.
|
|
*/
|
|
#define NCSIZE 1000
|
|
|
|
/*
|
|
** All of the static variables used by this module are collected
|
|
** into a single structure named "mem". This is to keep the
|
|
** static variables organized and to reduce namespace pollution
|
|
** when this module is combined with other in the amalgamation.
|
|
*/
|
|
static struct {
|
|
|
|
/*
|
|
** Mutex to control access to the memory allocation subsystem.
|
|
*/
|
|
sqlite3_mutex *mutex;
|
|
|
|
/*
|
|
** Head and tail of a linked list of all outstanding allocations
|
|
*/
|
|
struct MemBlockHdr *pFirst;
|
|
struct MemBlockHdr *pLast;
|
|
|
|
/*
|
|
** The number of levels of backtrace to save in new allocations.
|
|
*/
|
|
int nBacktrace;
|
|
void (*xBacktrace)(int, int, void **);
|
|
|
|
/*
|
|
** Title text to insert in front of each block
|
|
*/
|
|
int nTitle; /* Bytes of zTitle to save. Includes '\0' and padding */
|
|
char zTitle[100]; /* The title text */
|
|
|
|
/*
|
|
** sqlite3MallocDisallow() increments the following counter.
|
|
** sqlite3MallocAllow() decrements it.
|
|
*/
|
|
int disallow; /* Do not allow memory allocation */
|
|
|
|
/*
|
|
** Gather statistics on the sizes of memory allocations.
|
|
** nAlloc[i] is the number of allocation attempts of i*8
|
|
** bytes. i==NCSIZE is the number of allocation attempts for
|
|
** sizes more than NCSIZE*8 bytes.
|
|
*/
|
|
int nAlloc[NCSIZE]; /* Total number of allocations */
|
|
int nCurrent[NCSIZE]; /* Current number of allocations */
|
|
int mxCurrent[NCSIZE]; /* Highwater mark for nCurrent */
|
|
|
|
} mem;
|
|
|
|
|
|
/*
|
|
** Adjust memory usage statistics
|
|
*/
|
|
static void adjustStats(int iSize, int increment){
|
|
int i = ROUND8(iSize)/8;
|
|
if( i>NCSIZE-1 ){
|
|
i = NCSIZE - 1;
|
|
}
|
|
if( increment>0 ){
|
|
mem.nAlloc[i]++;
|
|
mem.nCurrent[i]++;
|
|
if( mem.nCurrent[i]>mem.mxCurrent[i] ){
|
|
mem.mxCurrent[i] = mem.nCurrent[i];
|
|
}
|
|
}else{
|
|
mem.nCurrent[i]--;
|
|
assert( mem.nCurrent[i]>=0 );
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Given an allocation, find the MemBlockHdr for that allocation.
|
|
**
|
|
** This routine checks the guards at either end of the allocation and
|
|
** if they are incorrect it asserts.
|
|
*/
|
|
static struct MemBlockHdr *sqlite3MemsysGetHeader(const void *pAllocation){
|
|
struct MemBlockHdr *p;
|
|
int *pInt;
|
|
u8 *pU8;
|
|
int nReserve;
|
|
|
|
p = (struct MemBlockHdr*)pAllocation;
|
|
p--;
|
|
assert( p->iForeGuard==(int)FOREGUARD );
|
|
nReserve = ROUND8(p->iSize);
|
|
pInt = (int*)pAllocation;
|
|
pU8 = (u8*)pAllocation;
|
|
assert( pInt[nReserve/sizeof(int)]==(int)REARGUARD );
|
|
/* This checks any of the "extra" bytes allocated due
|
|
** to rounding up to an 8 byte boundary to ensure
|
|
** they haven't been overwritten.
|
|
*/
|
|
while( nReserve-- > p->iSize ) assert( pU8[nReserve]==0x65 );
|
|
return p;
|
|
}
|
|
|
|
/*
|
|
** Return the number of bytes currently allocated at address p.
|
|
*/
|
|
static int sqlite3MemSize(void *p){
|
|
struct MemBlockHdr *pHdr;
|
|
if( !p ){
|
|
return 0;
|
|
}
|
|
pHdr = sqlite3MemsysGetHeader(p);
|
|
return (int)pHdr->iSize;
|
|
}
|
|
|
|
/*
|
|
** Initialize the memory allocation subsystem.
|
|
*/
|
|
static int sqlite3MemInit(void *NotUsed){
|
|
UNUSED_PARAMETER(NotUsed);
|
|
assert( (sizeof(struct MemBlockHdr)&7) == 0 );
|
|
if( !sqlite3GlobalConfig.bMemstat ){
|
|
/* If memory status is enabled, then the malloc.c wrapper will already
|
|
** hold the STATIC_MEM mutex when the routines here are invoked. */
|
|
mem.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
|
|
}
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Deinitialize the memory allocation subsystem.
|
|
*/
|
|
static void sqlite3MemShutdown(void *NotUsed){
|
|
UNUSED_PARAMETER(NotUsed);
|
|
mem.mutex = 0;
|
|
}
|
|
|
|
/*
|
|
** Round up a request size to the next valid allocation size.
|
|
*/
|
|
static int sqlite3MemRoundup(int n){
|
|
return ROUND8(n);
|
|
}
|
|
|
|
/*
|
|
** Fill a buffer with pseudo-random bytes. This is used to preset
|
|
** the content of a new memory allocation to unpredictable values and
|
|
** to clear the content of a freed allocation to unpredictable values.
|
|
*/
|
|
static void randomFill(char *pBuf, int nByte){
|
|
unsigned int x, y, r;
|
|
x = SQLITE_PTR_TO_INT(pBuf);
|
|
y = nByte | 1;
|
|
while( nByte >= 4 ){
|
|
x = (x>>1) ^ (-(int)(x&1) & 0xd0000001);
|
|
y = y*1103515245 + 12345;
|
|
r = x ^ y;
|
|
*(int*)pBuf = r;
|
|
pBuf += 4;
|
|
nByte -= 4;
|
|
}
|
|
while( nByte-- > 0 ){
|
|
x = (x>>1) ^ (-(int)(x&1) & 0xd0000001);
|
|
y = y*1103515245 + 12345;
|
|
r = x ^ y;
|
|
*(pBuf++) = r & 0xff;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Allocate nByte bytes of memory.
|
|
*/
|
|
static void *sqlite3MemMalloc(int nByte){
|
|
struct MemBlockHdr *pHdr;
|
|
void **pBt;
|
|
char *z;
|
|
int *pInt;
|
|
void *p = 0;
|
|
int totalSize;
|
|
int nReserve;
|
|
sqlite3_mutex_enter(mem.mutex);
|
|
assert( mem.disallow==0 );
|
|
nReserve = ROUND8(nByte);
|
|
totalSize = nReserve + sizeof(*pHdr) + sizeof(int) +
|
|
mem.nBacktrace*sizeof(void*) + mem.nTitle;
|
|
p = malloc(totalSize);
|
|
if( p ){
|
|
z = p;
|
|
pBt = (void**)&z[mem.nTitle];
|
|
pHdr = (struct MemBlockHdr*)&pBt[mem.nBacktrace];
|
|
pHdr->pNext = 0;
|
|
pHdr->pPrev = mem.pLast;
|
|
if( mem.pLast ){
|
|
mem.pLast->pNext = pHdr;
|
|
}else{
|
|
mem.pFirst = pHdr;
|
|
}
|
|
mem.pLast = pHdr;
|
|
pHdr->iForeGuard = FOREGUARD;
|
|
pHdr->eType = MEMTYPE_HEAP;
|
|
pHdr->nBacktraceSlots = mem.nBacktrace;
|
|
pHdr->nTitle = mem.nTitle;
|
|
if( mem.nBacktrace ){
|
|
void *aAddr[40];
|
|
pHdr->nBacktrace = backtrace(aAddr, mem.nBacktrace+1)-1;
|
|
memcpy(pBt, &aAddr[1], pHdr->nBacktrace*sizeof(void*));
|
|
assert(pBt[0]);
|
|
if( mem.xBacktrace ){
|
|
mem.xBacktrace(nByte, pHdr->nBacktrace-1, &aAddr[1]);
|
|
}
|
|
}else{
|
|
pHdr->nBacktrace = 0;
|
|
}
|
|
if( mem.nTitle ){
|
|
memcpy(z, mem.zTitle, mem.nTitle);
|
|
}
|
|
pHdr->iSize = nByte;
|
|
adjustStats(nByte, +1);
|
|
pInt = (int*)&pHdr[1];
|
|
pInt[nReserve/sizeof(int)] = REARGUARD;
|
|
randomFill((char*)pInt, nByte);
|
|
memset(((char*)pInt)+nByte, 0x65, nReserve-nByte);
|
|
p = (void*)pInt;
|
|
}
|
|
sqlite3_mutex_leave(mem.mutex);
|
|
return p;
|
|
}
|
|
|
|
/*
|
|
** Free memory.
|
|
*/
|
|
static void sqlite3MemFree(void *pPrior){
|
|
struct MemBlockHdr *pHdr;
|
|
void **pBt;
|
|
char *z;
|
|
assert( sqlite3GlobalConfig.bMemstat || sqlite3GlobalConfig.bCoreMutex==0
|
|
|| mem.mutex!=0 );
|
|
pHdr = sqlite3MemsysGetHeader(pPrior);
|
|
pBt = (void**)pHdr;
|
|
pBt -= pHdr->nBacktraceSlots;
|
|
sqlite3_mutex_enter(mem.mutex);
|
|
if( pHdr->pPrev ){
|
|
assert( pHdr->pPrev->pNext==pHdr );
|
|
pHdr->pPrev->pNext = pHdr->pNext;
|
|
}else{
|
|
assert( mem.pFirst==pHdr );
|
|
mem.pFirst = pHdr->pNext;
|
|
}
|
|
if( pHdr->pNext ){
|
|
assert( pHdr->pNext->pPrev==pHdr );
|
|
pHdr->pNext->pPrev = pHdr->pPrev;
|
|
}else{
|
|
assert( mem.pLast==pHdr );
|
|
mem.pLast = pHdr->pPrev;
|
|
}
|
|
z = (char*)pBt;
|
|
z -= pHdr->nTitle;
|
|
adjustStats((int)pHdr->iSize, -1);
|
|
randomFill(z, sizeof(void*)*pHdr->nBacktraceSlots + sizeof(*pHdr) +
|
|
(int)pHdr->iSize + sizeof(int) + pHdr->nTitle);
|
|
free(z);
|
|
sqlite3_mutex_leave(mem.mutex);
|
|
}
|
|
|
|
/*
|
|
** Change the size of an existing memory allocation.
|
|
**
|
|
** For this debugging implementation, we *always* make a copy of the
|
|
** allocation into a new place in memory. In this way, if the
|
|
** higher level code is using pointer to the old allocation, it is
|
|
** much more likely to break and we are much more liking to find
|
|
** the error.
|
|
*/
|
|
static void *sqlite3MemRealloc(void *pPrior, int nByte){
|
|
struct MemBlockHdr *pOldHdr;
|
|
void *pNew;
|
|
assert( mem.disallow==0 );
|
|
assert( (nByte & 7)==0 ); /* EV: R-46199-30249 */
|
|
pOldHdr = sqlite3MemsysGetHeader(pPrior);
|
|
pNew = sqlite3MemMalloc(nByte);
|
|
if( pNew ){
|
|
memcpy(pNew, pPrior, (int)(nByte<pOldHdr->iSize ? nByte : pOldHdr->iSize));
|
|
if( nByte>pOldHdr->iSize ){
|
|
randomFill(&((char*)pNew)[pOldHdr->iSize], nByte - (int)pOldHdr->iSize);
|
|
}
|
|
sqlite3MemFree(pPrior);
|
|
}
|
|
return pNew;
|
|
}
|
|
|
|
/*
|
|
** Populate the low-level memory allocation function pointers in
|
|
** sqlite3GlobalConfig.m with pointers to the routines in this file.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3MemSetDefault(void){
|
|
static const sqlite3_mem_methods defaultMethods = {
|
|
sqlite3MemMalloc,
|
|
sqlite3MemFree,
|
|
sqlite3MemRealloc,
|
|
sqlite3MemSize,
|
|
sqlite3MemRoundup,
|
|
sqlite3MemInit,
|
|
sqlite3MemShutdown,
|
|
0
|
|
};
|
|
sqlite3_config(SQLITE_CONFIG_MALLOC, &defaultMethods);
|
|
}
|
|
|
|
/*
|
|
** Set the "type" of an allocation.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3MemdebugSetType(void *p, u8 eType){
|
|
if( p && sqlite3GlobalConfig.m.xFree==sqlite3MemFree ){
|
|
struct MemBlockHdr *pHdr;
|
|
pHdr = sqlite3MemsysGetHeader(p);
|
|
assert( pHdr->iForeGuard==FOREGUARD );
|
|
pHdr->eType = eType;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Return TRUE if the mask of type in eType matches the type of the
|
|
** allocation p. Also return true if p==NULL.
|
|
**
|
|
** This routine is designed for use within an assert() statement, to
|
|
** verify the type of an allocation. For example:
|
|
**
|
|
** assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3MemdebugHasType(const void *p, u8 eType){
|
|
int rc = 1;
|
|
if( p && sqlite3GlobalConfig.m.xFree==sqlite3MemFree ){
|
|
struct MemBlockHdr *pHdr;
|
|
pHdr = sqlite3MemsysGetHeader(p);
|
|
assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */
|
|
if( (pHdr->eType&eType)==0 ){
|
|
rc = 0;
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Return TRUE if the mask of type in eType matches no bits of the type of the
|
|
** allocation p. Also return true if p==NULL.
|
|
**
|
|
** This routine is designed for use within an assert() statement, to
|
|
** verify the type of an allocation. For example:
|
|
**
|
|
** assert( sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3MemdebugNoType(const void *p, u8 eType){
|
|
int rc = 1;
|
|
if( p && sqlite3GlobalConfig.m.xFree==sqlite3MemFree ){
|
|
struct MemBlockHdr *pHdr;
|
|
pHdr = sqlite3MemsysGetHeader(p);
|
|
assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */
|
|
if( (pHdr->eType&eType)!=0 ){
|
|
rc = 0;
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Set the number of backtrace levels kept for each allocation.
|
|
** A value of zero turns off backtracing. The number is always rounded
|
|
** up to a multiple of 2.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3MemdebugBacktrace(int depth){
|
|
if( depth<0 ){ depth = 0; }
|
|
if( depth>20 ){ depth = 20; }
|
|
depth = (depth+1)&0xfe;
|
|
mem.nBacktrace = depth;
|
|
}
|
|
|
|
SQLITE_PRIVATE void sqlite3MemdebugBacktraceCallback(void (*xBacktrace)(int, int, void **)){
|
|
mem.xBacktrace = xBacktrace;
|
|
}
|
|
|
|
/*
|
|
** Set the title string for subsequent allocations.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3MemdebugSettitle(const char *zTitle){
|
|
unsigned int n = sqlite3Strlen30(zTitle) + 1;
|
|
sqlite3_mutex_enter(mem.mutex);
|
|
if( n>=sizeof(mem.zTitle) ) n = sizeof(mem.zTitle)-1;
|
|
memcpy(mem.zTitle, zTitle, n);
|
|
mem.zTitle[n] = 0;
|
|
mem.nTitle = ROUND8(n);
|
|
sqlite3_mutex_leave(mem.mutex);
|
|
}
|
|
|
|
SQLITE_PRIVATE void sqlite3MemdebugSync(){
|
|
struct MemBlockHdr *pHdr;
|
|
for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){
|
|
void **pBt = (void**)pHdr;
|
|
pBt -= pHdr->nBacktraceSlots;
|
|
mem.xBacktrace((int)pHdr->iSize, pHdr->nBacktrace-1, &pBt[1]);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Open the file indicated and write a log of all unfreed memory
|
|
** allocations into that log.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3MemdebugDump(const char *zFilename){
|
|
FILE *out;
|
|
struct MemBlockHdr *pHdr;
|
|
void **pBt;
|
|
int i;
|
|
out = fopen(zFilename, "w");
|
|
if( out==0 ){
|
|
fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
|
|
zFilename);
|
|
return;
|
|
}
|
|
for(pHdr=mem.pFirst; pHdr; pHdr=pHdr->pNext){
|
|
char *z = (char*)pHdr;
|
|
z -= pHdr->nBacktraceSlots*sizeof(void*) + pHdr->nTitle;
|
|
fprintf(out, "**** %lld bytes at %p from %s ****\n",
|
|
pHdr->iSize, &pHdr[1], pHdr->nTitle ? z : "???");
|
|
if( pHdr->nBacktrace ){
|
|
fflush(out);
|
|
pBt = (void**)pHdr;
|
|
pBt -= pHdr->nBacktraceSlots;
|
|
backtrace_symbols_fd(pBt, pHdr->nBacktrace, fileno(out));
|
|
fprintf(out, "\n");
|
|
}
|
|
}
|
|
fprintf(out, "COUNTS:\n");
|
|
for(i=0; i<NCSIZE-1; i++){
|
|
if( mem.nAlloc[i] ){
|
|
fprintf(out, " %5d: %10d %10d %10d\n",
|
|
i*8, mem.nAlloc[i], mem.nCurrent[i], mem.mxCurrent[i]);
|
|
}
|
|
}
|
|
if( mem.nAlloc[NCSIZE-1] ){
|
|
fprintf(out, " %5d: %10d %10d %10d\n",
|
|
NCSIZE*8-8, mem.nAlloc[NCSIZE-1],
|
|
mem.nCurrent[NCSIZE-1], mem.mxCurrent[NCSIZE-1]);
|
|
}
|
|
fclose(out);
|
|
}
|
|
|
|
/*
|
|
** Return the number of times sqlite3MemMalloc() has been called.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3MemdebugMallocCount(){
|
|
int i;
|
|
int nTotal = 0;
|
|
for(i=0; i<NCSIZE; i++){
|
|
nTotal += mem.nAlloc[i];
|
|
}
|
|
return nTotal;
|
|
}
|
|
|
|
|
|
#endif /* SQLITE_MEMDEBUG */
|
|
|
|
/************** End of mem2.c ************************************************/
|
|
/************** Begin file mem3.c ********************************************/
|
|
/*
|
|
** 2007 October 14
|
|
**
|
|
** 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 a memory
|
|
** allocation subsystem for use by SQLite.
|
|
**
|
|
** This version of the memory allocation subsystem omits all
|
|
** use of malloc(). The SQLite user supplies a block of memory
|
|
** before calling sqlite3_initialize() from which allocations
|
|
** are made and returned by the xMalloc() and xRealloc()
|
|
** implementations. Once sqlite3_initialize() has been called,
|
|
** the amount of memory available to SQLite is fixed and cannot
|
|
** be changed.
|
|
**
|
|
** This version of the memory allocation subsystem is included
|
|
** in the build only if SQLITE_ENABLE_MEMSYS3 is defined.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
|
|
/*
|
|
** This version of the memory allocator is only built into the library
|
|
** SQLITE_ENABLE_MEMSYS3 is defined. Defining this symbol does not
|
|
** mean that the library will use a memory-pool by default, just that
|
|
** it is available. The mempool allocator is activated by calling
|
|
** sqlite3_config().
|
|
*/
|
|
#ifdef SQLITE_ENABLE_MEMSYS3
|
|
|
|
/*
|
|
** Maximum size (in Mem3Blocks) of a "small" chunk.
|
|
*/
|
|
#define MX_SMALL 10
|
|
|
|
|
|
/*
|
|
** Number of freelist hash slots
|
|
*/
|
|
#define N_HASH 61
|
|
|
|
/*
|
|
** A memory allocation (also called a "chunk") consists of two or
|
|
** more blocks where each block is 8 bytes. The first 8 bytes are
|
|
** a header that is not returned to the user.
|
|
**
|
|
** A chunk is two or more blocks that is either checked out or
|
|
** free. The first block has format u.hdr. u.hdr.size4x is 4 times the
|
|
** size of the allocation in blocks if the allocation is free.
|
|
** The u.hdr.size4x&1 bit is true if the chunk is checked out and
|
|
** false if the chunk is on the freelist. The u.hdr.size4x&2 bit
|
|
** is true if the previous chunk is checked out and false if the
|
|
** previous chunk is free. The u.hdr.prevSize field is the size of
|
|
** the previous chunk in blocks if the previous chunk is on the
|
|
** freelist. If the previous chunk is checked out, then
|
|
** u.hdr.prevSize can be part of the data for that chunk and should
|
|
** not be read or written.
|
|
**
|
|
** We often identify a chunk by its index in mem3.aPool[]. When
|
|
** this is done, the chunk index refers to the second block of
|
|
** the chunk. In this way, the first chunk has an index of 1.
|
|
** A chunk index of 0 means "no such chunk" and is the equivalent
|
|
** of a NULL pointer.
|
|
**
|
|
** The second block of free chunks is of the form u.list. The
|
|
** two fields form a double-linked list of chunks of related sizes.
|
|
** Pointers to the head of the list are stored in mem3.aiSmall[]
|
|
** for smaller chunks and mem3.aiHash[] for larger chunks.
|
|
**
|
|
** The second block of a chunk is user data if the chunk is checked
|
|
** out. If a chunk is checked out, the user data may extend into
|
|
** the u.hdr.prevSize value of the following chunk.
|
|
*/
|
|
typedef struct Mem3Block Mem3Block;
|
|
struct Mem3Block {
|
|
union {
|
|
struct {
|
|
u32 prevSize; /* Size of previous chunk in Mem3Block elements */
|
|
u32 size4x; /* 4x the size of current chunk in Mem3Block elements */
|
|
} hdr;
|
|
struct {
|
|
u32 next; /* Index in mem3.aPool[] of next free chunk */
|
|
u32 prev; /* Index in mem3.aPool[] of previous free chunk */
|
|
} list;
|
|
} u;
|
|
};
|
|
|
|
/*
|
|
** All of the static variables used by this module are collected
|
|
** into a single structure named "mem3". This is to keep the
|
|
** static variables organized and to reduce namespace pollution
|
|
** when this module is combined with other in the amalgamation.
|
|
*/
|
|
static SQLITE_WSD struct Mem3Global {
|
|
/*
|
|
** Memory available for allocation. nPool is the size of the array
|
|
** (in Mem3Blocks) pointed to by aPool less 2.
|
|
*/
|
|
u32 nPool;
|
|
Mem3Block *aPool;
|
|
|
|
/*
|
|
** True if we are evaluating an out-of-memory callback.
|
|
*/
|
|
int alarmBusy;
|
|
|
|
/*
|
|
** Mutex to control access to the memory allocation subsystem.
|
|
*/
|
|
sqlite3_mutex *mutex;
|
|
|
|
/*
|
|
** The minimum amount of free space that we have seen.
|
|
*/
|
|
u32 mnKeyBlk;
|
|
|
|
/*
|
|
** iKeyBlk is the index of the key chunk. Most new allocations
|
|
** occur off of this chunk. szKeyBlk is the size (in Mem3Blocks)
|
|
** of the current key chunk. iKeyBlk is 0 if there is no key chunk.
|
|
** The key chunk is not in either the aiHash[] or aiSmall[].
|
|
*/
|
|
u32 iKeyBlk;
|
|
u32 szKeyBlk;
|
|
|
|
/*
|
|
** Array of lists of free blocks according to the block size
|
|
** for smaller chunks, or a hash on the block size for larger
|
|
** chunks.
|
|
*/
|
|
u32 aiSmall[MX_SMALL-1]; /* For sizes 2 through MX_SMALL, inclusive */
|
|
u32 aiHash[N_HASH]; /* For sizes MX_SMALL+1 and larger */
|
|
} mem3 = { 97535575 };
|
|
|
|
#define mem3 GLOBAL(struct Mem3Global, mem3)
|
|
|
|
/*
|
|
** Unlink the chunk at mem3.aPool[i] from list it is currently
|
|
** on. *pRoot is the list that i is a member of.
|
|
*/
|
|
static void memsys3UnlinkFromList(u32 i, u32 *pRoot){
|
|
u32 next = mem3.aPool[i].u.list.next;
|
|
u32 prev = mem3.aPool[i].u.list.prev;
|
|
assert( sqlite3_mutex_held(mem3.mutex) );
|
|
if( prev==0 ){
|
|
*pRoot = next;
|
|
}else{
|
|
mem3.aPool[prev].u.list.next = next;
|
|
}
|
|
if( next ){
|
|
mem3.aPool[next].u.list.prev = prev;
|
|
}
|
|
mem3.aPool[i].u.list.next = 0;
|
|
mem3.aPool[i].u.list.prev = 0;
|
|
}
|
|
|
|
/*
|
|
** Unlink the chunk at index i from
|
|
** whatever list is currently a member of.
|
|
*/
|
|
static void memsys3Unlink(u32 i){
|
|
u32 size, hash;
|
|
assert( sqlite3_mutex_held(mem3.mutex) );
|
|
assert( (mem3.aPool[i-1].u.hdr.size4x & 1)==0 );
|
|
assert( i>=1 );
|
|
size = mem3.aPool[i-1].u.hdr.size4x/4;
|
|
assert( size==mem3.aPool[i+size-1].u.hdr.prevSize );
|
|
assert( size>=2 );
|
|
if( size <= MX_SMALL ){
|
|
memsys3UnlinkFromList(i, &mem3.aiSmall[size-2]);
|
|
}else{
|
|
hash = size % N_HASH;
|
|
memsys3UnlinkFromList(i, &mem3.aiHash[hash]);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Link the chunk at mem3.aPool[i] so that is on the list rooted
|
|
** at *pRoot.
|
|
*/
|
|
static void memsys3LinkIntoList(u32 i, u32 *pRoot){
|
|
assert( sqlite3_mutex_held(mem3.mutex) );
|
|
mem3.aPool[i].u.list.next = *pRoot;
|
|
mem3.aPool[i].u.list.prev = 0;
|
|
if( *pRoot ){
|
|
mem3.aPool[*pRoot].u.list.prev = i;
|
|
}
|
|
*pRoot = i;
|
|
}
|
|
|
|
/*
|
|
** Link the chunk at index i into either the appropriate
|
|
** small chunk list, or into the large chunk hash table.
|
|
*/
|
|
static void memsys3Link(u32 i){
|
|
u32 size, hash;
|
|
assert( sqlite3_mutex_held(mem3.mutex) );
|
|
assert( i>=1 );
|
|
assert( (mem3.aPool[i-1].u.hdr.size4x & 1)==0 );
|
|
size = mem3.aPool[i-1].u.hdr.size4x/4;
|
|
assert( size==mem3.aPool[i+size-1].u.hdr.prevSize );
|
|
assert( size>=2 );
|
|
if( size <= MX_SMALL ){
|
|
memsys3LinkIntoList(i, &mem3.aiSmall[size-2]);
|
|
}else{
|
|
hash = size % N_HASH;
|
|
memsys3LinkIntoList(i, &mem3.aiHash[hash]);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** If the STATIC_MEM mutex is not already held, obtain it now. The mutex
|
|
** will already be held (obtained by code in malloc.c) if
|
|
** sqlite3GlobalConfig.bMemStat is true.
|
|
*/
|
|
static void memsys3Enter(void){
|
|
if( sqlite3GlobalConfig.bMemstat==0 && mem3.mutex==0 ){
|
|
mem3.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
|
|
}
|
|
sqlite3_mutex_enter(mem3.mutex);
|
|
}
|
|
static void memsys3Leave(void){
|
|
sqlite3_mutex_leave(mem3.mutex);
|
|
}
|
|
|
|
/*
|
|
** Called when we are unable to satisfy an allocation of nBytes.
|
|
*/
|
|
static void memsys3OutOfMemory(int nByte){
|
|
if( !mem3.alarmBusy ){
|
|
mem3.alarmBusy = 1;
|
|
assert( sqlite3_mutex_held(mem3.mutex) );
|
|
sqlite3_mutex_leave(mem3.mutex);
|
|
sqlite3_release_memory(nByte);
|
|
sqlite3_mutex_enter(mem3.mutex);
|
|
mem3.alarmBusy = 0;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
** Chunk i is a free chunk that has been unlinked. Adjust its
|
|
** size parameters for check-out and return a pointer to the
|
|
** user portion of the chunk.
|
|
*/
|
|
static void *memsys3Checkout(u32 i, u32 nBlock){
|
|
u32 x;
|
|
assert( sqlite3_mutex_held(mem3.mutex) );
|
|
assert( i>=1 );
|
|
assert( mem3.aPool[i-1].u.hdr.size4x/4==nBlock );
|
|
assert( mem3.aPool[i+nBlock-1].u.hdr.prevSize==nBlock );
|
|
x = mem3.aPool[i-1].u.hdr.size4x;
|
|
mem3.aPool[i-1].u.hdr.size4x = nBlock*4 | 1 | (x&2);
|
|
mem3.aPool[i+nBlock-1].u.hdr.prevSize = nBlock;
|
|
mem3.aPool[i+nBlock-1].u.hdr.size4x |= 2;
|
|
return &mem3.aPool[i];
|
|
}
|
|
|
|
/*
|
|
** Carve a piece off of the end of the mem3.iKeyBlk free chunk.
|
|
** Return a pointer to the new allocation. Or, if the key chunk
|
|
** is not large enough, return 0.
|
|
*/
|
|
static void *memsys3FromKeyBlk(u32 nBlock){
|
|
assert( sqlite3_mutex_held(mem3.mutex) );
|
|
assert( mem3.szKeyBlk>=nBlock );
|
|
if( nBlock>=mem3.szKeyBlk-1 ){
|
|
/* Use the entire key chunk */
|
|
void *p = memsys3Checkout(mem3.iKeyBlk, mem3.szKeyBlk);
|
|
mem3.iKeyBlk = 0;
|
|
mem3.szKeyBlk = 0;
|
|
mem3.mnKeyBlk = 0;
|
|
return p;
|
|
}else{
|
|
/* Split the key block. Return the tail. */
|
|
u32 newi, x;
|
|
newi = mem3.iKeyBlk + mem3.szKeyBlk - nBlock;
|
|
assert( newi > mem3.iKeyBlk+1 );
|
|
mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.prevSize = nBlock;
|
|
mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.size4x |= 2;
|
|
mem3.aPool[newi-1].u.hdr.size4x = nBlock*4 + 1;
|
|
mem3.szKeyBlk -= nBlock;
|
|
mem3.aPool[newi-1].u.hdr.prevSize = mem3.szKeyBlk;
|
|
x = mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x & 2;
|
|
mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x = mem3.szKeyBlk*4 | x;
|
|
if( mem3.szKeyBlk < mem3.mnKeyBlk ){
|
|
mem3.mnKeyBlk = mem3.szKeyBlk;
|
|
}
|
|
return (void*)&mem3.aPool[newi];
|
|
}
|
|
}
|
|
|
|
/*
|
|
** *pRoot is the head of a list of free chunks of the same size
|
|
** or same size hash. In other words, *pRoot is an entry in either
|
|
** mem3.aiSmall[] or mem3.aiHash[].
|
|
**
|
|
** This routine examines all entries on the given list and tries
|
|
** to coalesce each entries with adjacent free chunks.
|
|
**
|
|
** If it sees a chunk that is larger than mem3.iKeyBlk, it replaces
|
|
** the current mem3.iKeyBlk with the new larger chunk. In order for
|
|
** this mem3.iKeyBlk replacement to work, the key chunk must be
|
|
** linked into the hash tables. That is not the normal state of
|
|
** affairs, of course. The calling routine must link the key
|
|
** chunk before invoking this routine, then must unlink the (possibly
|
|
** changed) key chunk once this routine has finished.
|
|
*/
|
|
static void memsys3Merge(u32 *pRoot){
|
|
u32 iNext, prev, size, i, x;
|
|
|
|
assert( sqlite3_mutex_held(mem3.mutex) );
|
|
for(i=*pRoot; i>0; i=iNext){
|
|
iNext = mem3.aPool[i].u.list.next;
|
|
size = mem3.aPool[i-1].u.hdr.size4x;
|
|
assert( (size&1)==0 );
|
|
if( (size&2)==0 ){
|
|
memsys3UnlinkFromList(i, pRoot);
|
|
assert( i > mem3.aPool[i-1].u.hdr.prevSize );
|
|
prev = i - mem3.aPool[i-1].u.hdr.prevSize;
|
|
if( prev==iNext ){
|
|
iNext = mem3.aPool[prev].u.list.next;
|
|
}
|
|
memsys3Unlink(prev);
|
|
size = i + size/4 - prev;
|
|
x = mem3.aPool[prev-1].u.hdr.size4x & 2;
|
|
mem3.aPool[prev-1].u.hdr.size4x = size*4 | x;
|
|
mem3.aPool[prev+size-1].u.hdr.prevSize = size;
|
|
memsys3Link(prev);
|
|
i = prev;
|
|
}else{
|
|
size /= 4;
|
|
}
|
|
if( size>mem3.szKeyBlk ){
|
|
mem3.iKeyBlk = i;
|
|
mem3.szKeyBlk = size;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Return a block of memory of at least nBytes in size.
|
|
** Return NULL if unable.
|
|
**
|
|
** This function assumes that the necessary mutexes, if any, are
|
|
** already held by the caller. Hence "Unsafe".
|
|
*/
|
|
static void *memsys3MallocUnsafe(int nByte){
|
|
u32 i;
|
|
u32 nBlock;
|
|
u32 toFree;
|
|
|
|
assert( sqlite3_mutex_held(mem3.mutex) );
|
|
assert( sizeof(Mem3Block)==8 );
|
|
if( nByte<=12 ){
|
|
nBlock = 2;
|
|
}else{
|
|
nBlock = (nByte + 11)/8;
|
|
}
|
|
assert( nBlock>=2 );
|
|
|
|
/* STEP 1:
|
|
** Look for an entry of the correct size in either the small
|
|
** chunk table or in the large chunk hash table. This is
|
|
** successful most of the time (about 9 times out of 10).
|
|
*/
|
|
if( nBlock <= MX_SMALL ){
|
|
i = mem3.aiSmall[nBlock-2];
|
|
if( i>0 ){
|
|
memsys3UnlinkFromList(i, &mem3.aiSmall[nBlock-2]);
|
|
return memsys3Checkout(i, nBlock);
|
|
}
|
|
}else{
|
|
int hash = nBlock % N_HASH;
|
|
for(i=mem3.aiHash[hash]; i>0; i=mem3.aPool[i].u.list.next){
|
|
if( mem3.aPool[i-1].u.hdr.size4x/4==nBlock ){
|
|
memsys3UnlinkFromList(i, &mem3.aiHash[hash]);
|
|
return memsys3Checkout(i, nBlock);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* STEP 2:
|
|
** Try to satisfy the allocation by carving a piece off of the end
|
|
** of the key chunk. This step usually works if step 1 fails.
|
|
*/
|
|
if( mem3.szKeyBlk>=nBlock ){
|
|
return memsys3FromKeyBlk(nBlock);
|
|
}
|
|
|
|
|
|
/* STEP 3:
|
|
** Loop through the entire memory pool. Coalesce adjacent free
|
|
** chunks. Recompute the key chunk as the largest free chunk.
|
|
** Then try again to satisfy the allocation by carving a piece off
|
|
** of the end of the key chunk. This step happens very
|
|
** rarely (we hope!)
|
|
*/
|
|
for(toFree=nBlock*16; toFree<(mem3.nPool*16); toFree *= 2){
|
|
memsys3OutOfMemory(toFree);
|
|
if( mem3.iKeyBlk ){
|
|
memsys3Link(mem3.iKeyBlk);
|
|
mem3.iKeyBlk = 0;
|
|
mem3.szKeyBlk = 0;
|
|
}
|
|
for(i=0; i<N_HASH; i++){
|
|
memsys3Merge(&mem3.aiHash[i]);
|
|
}
|
|
for(i=0; i<MX_SMALL-1; i++){
|
|
memsys3Merge(&mem3.aiSmall[i]);
|
|
}
|
|
if( mem3.szKeyBlk ){
|
|
memsys3Unlink(mem3.iKeyBlk);
|
|
if( mem3.szKeyBlk>=nBlock ){
|
|
return memsys3FromKeyBlk(nBlock);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* If none of the above worked, then we fail. */
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
** Free an outstanding memory allocation.
|
|
**
|
|
** This function assumes that the necessary mutexes, if any, are
|
|
** already held by the caller. Hence "Unsafe".
|
|
*/
|
|
static void memsys3FreeUnsafe(void *pOld){
|
|
Mem3Block *p = (Mem3Block*)pOld;
|
|
int i;
|
|
u32 size, x;
|
|
assert( sqlite3_mutex_held(mem3.mutex) );
|
|
assert( p>mem3.aPool && p<&mem3.aPool[mem3.nPool] );
|
|
i = p - mem3.aPool;
|
|
assert( (mem3.aPool[i-1].u.hdr.size4x&1)==1 );
|
|
size = mem3.aPool[i-1].u.hdr.size4x/4;
|
|
assert( i+size<=mem3.nPool+1 );
|
|
mem3.aPool[i-1].u.hdr.size4x &= ~1;
|
|
mem3.aPool[i+size-1].u.hdr.prevSize = size;
|
|
mem3.aPool[i+size-1].u.hdr.size4x &= ~2;
|
|
memsys3Link(i);
|
|
|
|
/* Try to expand the key using the newly freed chunk */
|
|
if( mem3.iKeyBlk ){
|
|
while( (mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x&2)==0 ){
|
|
size = mem3.aPool[mem3.iKeyBlk-1].u.hdr.prevSize;
|
|
mem3.iKeyBlk -= size;
|
|
mem3.szKeyBlk += size;
|
|
memsys3Unlink(mem3.iKeyBlk);
|
|
x = mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x & 2;
|
|
mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x = mem3.szKeyBlk*4 | x;
|
|
mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.prevSize = mem3.szKeyBlk;
|
|
}
|
|
x = mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x & 2;
|
|
while( (mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.size4x&1)==0 ){
|
|
memsys3Unlink(mem3.iKeyBlk+mem3.szKeyBlk);
|
|
mem3.szKeyBlk += mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.size4x/4;
|
|
mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x = mem3.szKeyBlk*4 | x;
|
|
mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.prevSize = mem3.szKeyBlk;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Return the size of an outstanding allocation, in bytes. The
|
|
** size returned omits the 8-byte header overhead. This only
|
|
** works for chunks that are currently checked out.
|
|
*/
|
|
static int memsys3Size(void *p){
|
|
Mem3Block *pBlock;
|
|
assert( p!=0 );
|
|
pBlock = (Mem3Block*)p;
|
|
assert( (pBlock[-1].u.hdr.size4x&1)!=0 );
|
|
return (pBlock[-1].u.hdr.size4x&~3)*2 - 4;
|
|
}
|
|
|
|
/*
|
|
** Round up a request size to the next valid allocation size.
|
|
*/
|
|
static int memsys3Roundup(int n){
|
|
if( n<=12 ){
|
|
return 12;
|
|
}else{
|
|
return ((n+11)&~7) - 4;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Allocate nBytes of memory.
|
|
*/
|
|
static void *memsys3Malloc(int nBytes){
|
|
sqlite3_int64 *p;
|
|
assert( nBytes>0 ); /* malloc.c filters out 0 byte requests */
|
|
memsys3Enter();
|
|
p = memsys3MallocUnsafe(nBytes);
|
|
memsys3Leave();
|
|
return (void*)p;
|
|
}
|
|
|
|
/*
|
|
** Free memory.
|
|
*/
|
|
static void memsys3Free(void *pPrior){
|
|
assert( pPrior );
|
|
memsys3Enter();
|
|
memsys3FreeUnsafe(pPrior);
|
|
memsys3Leave();
|
|
}
|
|
|
|
/*
|
|
** Change the size of an existing memory allocation
|
|
*/
|
|
static void *memsys3Realloc(void *pPrior, int nBytes){
|
|
int nOld;
|
|
void *p;
|
|
if( pPrior==0 ){
|
|
return sqlite3_malloc(nBytes);
|
|
}
|
|
if( nBytes<=0 ){
|
|
sqlite3_free(pPrior);
|
|
return 0;
|
|
}
|
|
nOld = memsys3Size(pPrior);
|
|
if( nBytes<=nOld && nBytes>=nOld-128 ){
|
|
return pPrior;
|
|
}
|
|
memsys3Enter();
|
|
p = memsys3MallocUnsafe(nBytes);
|
|
if( p ){
|
|
if( nOld<nBytes ){
|
|
memcpy(p, pPrior, nOld);
|
|
}else{
|
|
memcpy(p, pPrior, nBytes);
|
|
}
|
|
memsys3FreeUnsafe(pPrior);
|
|
}
|
|
memsys3Leave();
|
|
return p;
|
|
}
|
|
|
|
/*
|
|
** Initialize this module.
|
|
*/
|
|
static int memsys3Init(void *NotUsed){
|
|
UNUSED_PARAMETER(NotUsed);
|
|
if( !sqlite3GlobalConfig.pHeap ){
|
|
return SQLITE_ERROR;
|
|
}
|
|
|
|
/* Store a pointer to the memory block in global structure mem3. */
|
|
assert( sizeof(Mem3Block)==8 );
|
|
mem3.aPool = (Mem3Block *)sqlite3GlobalConfig.pHeap;
|
|
mem3.nPool = (sqlite3GlobalConfig.nHeap / sizeof(Mem3Block)) - 2;
|
|
|
|
/* Initialize the key block. */
|
|
mem3.szKeyBlk = mem3.nPool;
|
|
mem3.mnKeyBlk = mem3.szKeyBlk;
|
|
mem3.iKeyBlk = 1;
|
|
mem3.aPool[0].u.hdr.size4x = (mem3.szKeyBlk<<2) + 2;
|
|
mem3.aPool[mem3.nPool].u.hdr.prevSize = mem3.nPool;
|
|
mem3.aPool[mem3.nPool].u.hdr.size4x = 1;
|
|
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Deinitialize this module.
|
|
*/
|
|
static void memsys3Shutdown(void *NotUsed){
|
|
UNUSED_PARAMETER(NotUsed);
|
|
mem3.mutex = 0;
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
** Open the file indicated and write a log of all unfreed memory
|
|
** allocations into that log.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3Memsys3Dump(const char *zFilename){
|
|
#ifdef SQLITE_DEBUG
|
|
FILE *out;
|
|
u32 i, j;
|
|
u32 size;
|
|
if( zFilename==0 || zFilename[0]==0 ){
|
|
out = stdout;
|
|
}else{
|
|
out = fopen(zFilename, "w");
|
|
if( out==0 ){
|
|
fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
|
|
zFilename);
|
|
return;
|
|
}
|
|
}
|
|
memsys3Enter();
|
|
fprintf(out, "CHUNKS:\n");
|
|
for(i=1; i<=mem3.nPool; i+=size/4){
|
|
size = mem3.aPool[i-1].u.hdr.size4x;
|
|
if( size/4<=1 ){
|
|
fprintf(out, "%p size error\n", &mem3.aPool[i]);
|
|
assert( 0 );
|
|
break;
|
|
}
|
|
if( (size&1)==0 && mem3.aPool[i+size/4-1].u.hdr.prevSize!=size/4 ){
|
|
fprintf(out, "%p tail size does not match\n", &mem3.aPool[i]);
|
|
assert( 0 );
|
|
break;
|
|
}
|
|
if( ((mem3.aPool[i+size/4-1].u.hdr.size4x&2)>>1)!=(size&1) ){
|
|
fprintf(out, "%p tail checkout bit is incorrect\n", &mem3.aPool[i]);
|
|
assert( 0 );
|
|
break;
|
|
}
|
|
if( size&1 ){
|
|
fprintf(out, "%p %6d bytes checked out\n", &mem3.aPool[i], (size/4)*8-8);
|
|
}else{
|
|
fprintf(out, "%p %6d bytes free%s\n", &mem3.aPool[i], (size/4)*8-8,
|
|
i==mem3.iKeyBlk ? " **key**" : "");
|
|
}
|
|
}
|
|
for(i=0; i<MX_SMALL-1; i++){
|
|
if( mem3.aiSmall[i]==0 ) continue;
|
|
fprintf(out, "small(%2d):", i);
|
|
for(j = mem3.aiSmall[i]; j>0; j=mem3.aPool[j].u.list.next){
|
|
fprintf(out, " %p(%d)", &mem3.aPool[j],
|
|
(mem3.aPool[j-1].u.hdr.size4x/4)*8-8);
|
|
}
|
|
fprintf(out, "\n");
|
|
}
|
|
for(i=0; i<N_HASH; i++){
|
|
if( mem3.aiHash[i]==0 ) continue;
|
|
fprintf(out, "hash(%2d):", i);
|
|
for(j = mem3.aiHash[i]; j>0; j=mem3.aPool[j].u.list.next){
|
|
fprintf(out, " %p(%d)", &mem3.aPool[j],
|
|
(mem3.aPool[j-1].u.hdr.size4x/4)*8-8);
|
|
}
|
|
fprintf(out, "\n");
|
|
}
|
|
fprintf(out, "key=%d\n", mem3.iKeyBlk);
|
|
fprintf(out, "nowUsed=%d\n", mem3.nPool*8 - mem3.szKeyBlk*8);
|
|
fprintf(out, "mxUsed=%d\n", mem3.nPool*8 - mem3.mnKeyBlk*8);
|
|
sqlite3_mutex_leave(mem3.mutex);
|
|
if( out==stdout ){
|
|
fflush(stdout);
|
|
}else{
|
|
fclose(out);
|
|
}
|
|
#else
|
|
UNUSED_PARAMETER(zFilename);
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
** This routine is the only routine in this file with external
|
|
** linkage.
|
|
**
|
|
** Populate the low-level memory allocation function pointers in
|
|
** sqlite3GlobalConfig.m with pointers to the routines in this file. The
|
|
** arguments specify the block of memory to manage.
|
|
**
|
|
** This routine is only called by sqlite3_config(), and therefore
|
|
** is not required to be threadsafe (it is not).
|
|
*/
|
|
SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys3(void){
|
|
static const sqlite3_mem_methods mempoolMethods = {
|
|
memsys3Malloc,
|
|
memsys3Free,
|
|
memsys3Realloc,
|
|
memsys3Size,
|
|
memsys3Roundup,
|
|
memsys3Init,
|
|
memsys3Shutdown,
|
|
0
|
|
};
|
|
return &mempoolMethods;
|
|
}
|
|
|
|
#endif /* SQLITE_ENABLE_MEMSYS3 */
|
|
|
|
/************** End of mem3.c ************************************************/
|
|
/************** Begin file mem5.c ********************************************/
|
|
/*
|
|
** 2007 October 14
|
|
**
|
|
** 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 a memory
|
|
** allocation subsystem for use by SQLite.
|
|
**
|
|
** This version of the memory allocation subsystem omits all
|
|
** use of malloc(). The application gives SQLite a block of memory
|
|
** before calling sqlite3_initialize() from which allocations
|
|
** are made and returned by the xMalloc() and xRealloc()
|
|
** implementations. Once sqlite3_initialize() has been called,
|
|
** the amount of memory available to SQLite is fixed and cannot
|
|
** be changed.
|
|
**
|
|
** This version of the memory allocation subsystem is included
|
|
** in the build only if SQLITE_ENABLE_MEMSYS5 is defined.
|
|
**
|
|
** This memory allocator uses the following algorithm:
|
|
**
|
|
** 1. All memory allocation sizes are rounded up to a power of 2.
|
|
**
|
|
** 2. If two adjacent free blocks are the halves of a larger block,
|
|
** then the two blocks are coalesced into the single larger block.
|
|
**
|
|
** 3. New memory is allocated from the first available free block.
|
|
**
|
|
** This algorithm is described in: J. M. Robson. "Bounds for Some Functions
|
|
** Concerning Dynamic Storage Allocation". Journal of the Association for
|
|
** Computing Machinery, Volume 21, Number 8, July 1974, pages 491-499.
|
|
**
|
|
** Let n be the size of the largest allocation divided by the minimum
|
|
** allocation size (after rounding all sizes up to a power of 2.) Let M
|
|
** be the maximum amount of memory ever outstanding at one time. Let
|
|
** N be the total amount of memory available for allocation. Robson
|
|
** proved that this memory allocator will never breakdown due to
|
|
** fragmentation as long as the following constraint holds:
|
|
**
|
|
** N >= M*(1 + log2(n)/2) - n + 1
|
|
**
|
|
** The sqlite3_status() logic tracks the maximum values of n and M so
|
|
** that an application can, at any time, verify this constraint.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
|
|
/*
|
|
** This version of the memory allocator is used only when
|
|
** SQLITE_ENABLE_MEMSYS5 is defined.
|
|
*/
|
|
#ifdef SQLITE_ENABLE_MEMSYS5
|
|
|
|
/*
|
|
** A minimum allocation is an instance of the following structure.
|
|
** Larger allocations are an array of these structures where the
|
|
** size of the array is a power of 2.
|
|
**
|
|
** The size of this object must be a power of two. That fact is
|
|
** verified in memsys5Init().
|
|
*/
|
|
typedef struct Mem5Link Mem5Link;
|
|
struct Mem5Link {
|
|
int next; /* Index of next free chunk */
|
|
int prev; /* Index of previous free chunk */
|
|
};
|
|
|
|
/*
|
|
** Maximum size of any allocation is ((1<<LOGMAX)*mem5.szAtom). Since
|
|
** mem5.szAtom is always at least 8 and 32-bit integers are used,
|
|
** it is not actually possible to reach this limit.
|
|
*/
|
|
#define LOGMAX 30
|
|
|
|
/*
|
|
** Masks used for mem5.aCtrl[] elements.
|
|
*/
|
|
#define CTRL_LOGSIZE 0x1f /* Log2 Size of this block */
|
|
#define CTRL_FREE 0x20 /* True if not checked out */
|
|
|
|
/*
|
|
** All of the static variables used by this module are collected
|
|
** into a single structure named "mem5". This is to keep the
|
|
** static variables organized and to reduce namespace pollution
|
|
** when this module is combined with other in the amalgamation.
|
|
*/
|
|
static SQLITE_WSD struct Mem5Global {
|
|
/*
|
|
** Memory available for allocation
|
|
*/
|
|
int szAtom; /* Smallest possible allocation in bytes */
|
|
int nBlock; /* Number of szAtom sized blocks in zPool */
|
|
u8 *zPool; /* Memory available to be allocated */
|
|
|
|
/*
|
|
** Mutex to control access to the memory allocation subsystem.
|
|
*/
|
|
sqlite3_mutex *mutex;
|
|
|
|
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
|
/*
|
|
** Performance statistics
|
|
*/
|
|
u64 nAlloc; /* Total number of calls to malloc */
|
|
u64 totalAlloc; /* Total of all malloc calls - includes internal frag */
|
|
u64 totalExcess; /* Total internal fragmentation */
|
|
u32 currentOut; /* Current checkout, including internal fragmentation */
|
|
u32 currentCount; /* Current number of distinct checkouts */
|
|
u32 maxOut; /* Maximum instantaneous currentOut */
|
|
u32 maxCount; /* Maximum instantaneous currentCount */
|
|
u32 maxRequest; /* Largest allocation (exclusive of internal frag) */
|
|
#endif
|
|
|
|
/*
|
|
** Lists of free blocks. aiFreelist[0] is a list of free blocks of
|
|
** size mem5.szAtom. aiFreelist[1] holds blocks of size szAtom*2.
|
|
** aiFreelist[2] holds free blocks of size szAtom*4. And so forth.
|
|
*/
|
|
int aiFreelist[LOGMAX+1];
|
|
|
|
/*
|
|
** Space for tracking which blocks are checked out and the size
|
|
** of each block. One byte per block.
|
|
*/
|
|
u8 *aCtrl;
|
|
|
|
} mem5;
|
|
|
|
/*
|
|
** Access the static variable through a macro for SQLITE_OMIT_WSD.
|
|
*/
|
|
#define mem5 GLOBAL(struct Mem5Global, mem5)
|
|
|
|
/*
|
|
** Assuming mem5.zPool is divided up into an array of Mem5Link
|
|
** structures, return a pointer to the idx-th such link.
|
|
*/
|
|
#define MEM5LINK(idx) ((Mem5Link *)(&mem5.zPool[(idx)*mem5.szAtom]))
|
|
|
|
/*
|
|
** Unlink the chunk at mem5.aPool[i] from list it is currently
|
|
** on. It should be found on mem5.aiFreelist[iLogsize].
|
|
*/
|
|
static void memsys5Unlink(int i, int iLogsize){
|
|
int next, prev;
|
|
assert( i>=0 && i<mem5.nBlock );
|
|
assert( iLogsize>=0 && iLogsize<=LOGMAX );
|
|
assert( (mem5.aCtrl[i] & CTRL_LOGSIZE)==iLogsize );
|
|
|
|
next = MEM5LINK(i)->next;
|
|
prev = MEM5LINK(i)->prev;
|
|
if( prev<0 ){
|
|
mem5.aiFreelist[iLogsize] = next;
|
|
}else{
|
|
MEM5LINK(prev)->next = next;
|
|
}
|
|
if( next>=0 ){
|
|
MEM5LINK(next)->prev = prev;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Link the chunk at mem5.aPool[i] so that is on the iLogsize
|
|
** free list.
|
|
*/
|
|
static void memsys5Link(int i, int iLogsize){
|
|
int x;
|
|
assert( sqlite3_mutex_held(mem5.mutex) );
|
|
assert( i>=0 && i<mem5.nBlock );
|
|
assert( iLogsize>=0 && iLogsize<=LOGMAX );
|
|
assert( (mem5.aCtrl[i] & CTRL_LOGSIZE)==iLogsize );
|
|
|
|
x = MEM5LINK(i)->next = mem5.aiFreelist[iLogsize];
|
|
MEM5LINK(i)->prev = -1;
|
|
if( x>=0 ){
|
|
assert( x<mem5.nBlock );
|
|
MEM5LINK(x)->prev = i;
|
|
}
|
|
mem5.aiFreelist[iLogsize] = i;
|
|
}
|
|
|
|
/*
|
|
** Obtain or release the mutex needed to access global data structures.
|
|
*/
|
|
static void memsys5Enter(void){
|
|
sqlite3_mutex_enter(mem5.mutex);
|
|
}
|
|
static void memsys5Leave(void){
|
|
sqlite3_mutex_leave(mem5.mutex);
|
|
}
|
|
|
|
/*
|
|
** Return the size of an outstanding allocation, in bytes.
|
|
** This only works for chunks that are currently checked out.
|
|
*/
|
|
static int memsys5Size(void *p){
|
|
int iSize, i;
|
|
assert( p!=0 );
|
|
i = (int)(((u8 *)p-mem5.zPool)/mem5.szAtom);
|
|
assert( i>=0 && i<mem5.nBlock );
|
|
iSize = mem5.szAtom * (1 << (mem5.aCtrl[i]&CTRL_LOGSIZE));
|
|
return iSize;
|
|
}
|
|
|
|
/*
|
|
** Return a block of memory of at least nBytes in size.
|
|
** Return NULL if unable. Return NULL if nBytes==0.
|
|
**
|
|
** The caller guarantees that nByte is positive.
|
|
**
|
|
** The caller has obtained a mutex prior to invoking this
|
|
** routine so there is never any chance that two or more
|
|
** threads can be in this routine at the same time.
|
|
*/
|
|
static void *memsys5MallocUnsafe(int nByte){
|
|
int i; /* Index of a mem5.aPool[] slot */
|
|
int iBin; /* Index into mem5.aiFreelist[] */
|
|
int iFullSz; /* Size of allocation rounded up to power of 2 */
|
|
int iLogsize; /* Log2 of iFullSz/POW2_MIN */
|
|
|
|
/* nByte must be a positive */
|
|
assert( nByte>0 );
|
|
|
|
/* No more than 1GiB per allocation */
|
|
if( nByte > 0x40000000 ) return 0;
|
|
|
|
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
|
/* Keep track of the maximum allocation request. Even unfulfilled
|
|
** requests are counted */
|
|
if( (u32)nByte>mem5.maxRequest ){
|
|
mem5.maxRequest = nByte;
|
|
}
|
|
#endif
|
|
|
|
|
|
/* Round nByte up to the next valid power of two */
|
|
for(iFullSz=mem5.szAtom,iLogsize=0; iFullSz<nByte; iFullSz*=2,iLogsize++){}
|
|
|
|
/* Make sure mem5.aiFreelist[iLogsize] contains at least one free
|
|
** block. If not, then split a block of the next larger power of
|
|
** two in order to create a new free block of size iLogsize.
|
|
*/
|
|
for(iBin=iLogsize; iBin<=LOGMAX && mem5.aiFreelist[iBin]<0; iBin++){}
|
|
if( iBin>LOGMAX ){
|
|
testcase( sqlite3GlobalConfig.xLog!=0 );
|
|
sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes", nByte);
|
|
return 0;
|
|
}
|
|
i = mem5.aiFreelist[iBin];
|
|
memsys5Unlink(i, iBin);
|
|
while( iBin>iLogsize ){
|
|
int newSize;
|
|
|
|
iBin--;
|
|
newSize = 1 << iBin;
|
|
mem5.aCtrl[i+newSize] = CTRL_FREE | iBin;
|
|
memsys5Link(i+newSize, iBin);
|
|
}
|
|
mem5.aCtrl[i] = iLogsize;
|
|
|
|
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
|
/* Update allocator performance statistics. */
|
|
mem5.nAlloc++;
|
|
mem5.totalAlloc += iFullSz;
|
|
mem5.totalExcess += iFullSz - nByte;
|
|
mem5.currentCount++;
|
|
mem5.currentOut += iFullSz;
|
|
if( mem5.maxCount<mem5.currentCount ) mem5.maxCount = mem5.currentCount;
|
|
if( mem5.maxOut<mem5.currentOut ) mem5.maxOut = mem5.currentOut;
|
|
#endif
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
/* Make sure the allocated memory does not assume that it is set to zero
|
|
** or retains a value from a previous allocation */
|
|
memset(&mem5.zPool[i*mem5.szAtom], 0xAA, iFullSz);
|
|
#endif
|
|
|
|
/* Return a pointer to the allocated memory. */
|
|
return (void*)&mem5.zPool[i*mem5.szAtom];
|
|
}
|
|
|
|
/*
|
|
** Free an outstanding memory allocation.
|
|
*/
|
|
static void memsys5FreeUnsafe(void *pOld){
|
|
u32 size, iLogsize;
|
|
int iBlock;
|
|
|
|
/* Set iBlock to the index of the block pointed to by pOld in
|
|
** the array of mem5.szAtom byte blocks pointed to by mem5.zPool.
|
|
*/
|
|
iBlock = (int)(((u8 *)pOld-mem5.zPool)/mem5.szAtom);
|
|
|
|
/* Check that the pointer pOld points to a valid, non-free block. */
|
|
assert( iBlock>=0 && iBlock<mem5.nBlock );
|
|
assert( ((u8 *)pOld-mem5.zPool)%mem5.szAtom==0 );
|
|
assert( (mem5.aCtrl[iBlock] & CTRL_FREE)==0 );
|
|
|
|
iLogsize = mem5.aCtrl[iBlock] & CTRL_LOGSIZE;
|
|
size = 1<<iLogsize;
|
|
assert( iBlock+size-1<(u32)mem5.nBlock );
|
|
|
|
mem5.aCtrl[iBlock] |= CTRL_FREE;
|
|
mem5.aCtrl[iBlock+size-1] |= CTRL_FREE;
|
|
|
|
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
|
assert( mem5.currentCount>0 );
|
|
assert( mem5.currentOut>=(size*mem5.szAtom) );
|
|
mem5.currentCount--;
|
|
mem5.currentOut -= size*mem5.szAtom;
|
|
assert( mem5.currentOut>0 || mem5.currentCount==0 );
|
|
assert( mem5.currentCount>0 || mem5.currentOut==0 );
|
|
#endif
|
|
|
|
mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize;
|
|
while( ALWAYS(iLogsize<LOGMAX) ){
|
|
int iBuddy;
|
|
if( (iBlock>>iLogsize) & 1 ){
|
|
iBuddy = iBlock - size;
|
|
assert( iBuddy>=0 );
|
|
}else{
|
|
iBuddy = iBlock + size;
|
|
if( iBuddy>=mem5.nBlock ) break;
|
|
}
|
|
if( mem5.aCtrl[iBuddy]!=(CTRL_FREE | iLogsize) ) break;
|
|
memsys5Unlink(iBuddy, iLogsize);
|
|
iLogsize++;
|
|
if( iBuddy<iBlock ){
|
|
mem5.aCtrl[iBuddy] = CTRL_FREE | iLogsize;
|
|
mem5.aCtrl[iBlock] = 0;
|
|
iBlock = iBuddy;
|
|
}else{
|
|
mem5.aCtrl[iBlock] = CTRL_FREE | iLogsize;
|
|
mem5.aCtrl[iBuddy] = 0;
|
|
}
|
|
size *= 2;
|
|
}
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
/* Overwrite freed memory with the 0x55 bit pattern to verify that it is
|
|
** not used after being freed */
|
|
memset(&mem5.zPool[iBlock*mem5.szAtom], 0x55, size);
|
|
#endif
|
|
|
|
memsys5Link(iBlock, iLogsize);
|
|
}
|
|
|
|
/*
|
|
** Allocate nBytes of memory.
|
|
*/
|
|
static void *memsys5Malloc(int nBytes){
|
|
sqlite3_int64 *p = 0;
|
|
if( nBytes>0 ){
|
|
memsys5Enter();
|
|
p = memsys5MallocUnsafe(nBytes);
|
|
memsys5Leave();
|
|
}
|
|
return (void*)p;
|
|
}
|
|
|
|
/*
|
|
** Free memory.
|
|
**
|
|
** The outer layer memory allocator prevents this routine from
|
|
** being called with pPrior==0.
|
|
*/
|
|
static void memsys5Free(void *pPrior){
|
|
assert( pPrior!=0 );
|
|
memsys5Enter();
|
|
memsys5FreeUnsafe(pPrior);
|
|
memsys5Leave();
|
|
}
|
|
|
|
/*
|
|
** Change the size of an existing memory allocation.
|
|
**
|
|
** The outer layer memory allocator prevents this routine from
|
|
** being called with pPrior==0.
|
|
**
|
|
** nBytes is always a value obtained from a prior call to
|
|
** memsys5Round(). Hence nBytes is always a non-negative power
|
|
** of two. If nBytes==0 that means that an oversize allocation
|
|
** (an allocation larger than 0x40000000) was requested and this
|
|
** routine should return 0 without freeing pPrior.
|
|
*/
|
|
static void *memsys5Realloc(void *pPrior, int nBytes){
|
|
int nOld;
|
|
void *p;
|
|
assert( pPrior!=0 );
|
|
assert( (nBytes&(nBytes-1))==0 ); /* EV: R-46199-30249 */
|
|
assert( nBytes>=0 );
|
|
if( nBytes==0 ){
|
|
return 0;
|
|
}
|
|
nOld = memsys5Size(pPrior);
|
|
if( nBytes<=nOld ){
|
|
return pPrior;
|
|
}
|
|
p = memsys5Malloc(nBytes);
|
|
if( p ){
|
|
memcpy(p, pPrior, nOld);
|
|
memsys5Free(pPrior);
|
|
}
|
|
return p;
|
|
}
|
|
|
|
/*
|
|
** Round up a request size to the next valid allocation size. If
|
|
** the allocation is too large to be handled by this allocation system,
|
|
** return 0.
|
|
**
|
|
** All allocations must be a power of two and must be expressed by a
|
|
** 32-bit signed integer. Hence the largest allocation is 0x40000000
|
|
** or 1073741824 bytes.
|
|
*/
|
|
static int memsys5Roundup(int n){
|
|
int iFullSz;
|
|
if( n<=mem5.szAtom*2 ){
|
|
if( n<=mem5.szAtom ) return mem5.szAtom;
|
|
return mem5.szAtom*2;
|
|
}
|
|
if( n>0x10000000 ){
|
|
if( n>0x40000000 ) return 0;
|
|
if( n>0x20000000 ) return 0x40000000;
|
|
return 0x20000000;
|
|
}
|
|
for(iFullSz=mem5.szAtom*8; iFullSz<n; iFullSz *= 4);
|
|
if( (iFullSz/2)>=(i64)n ) return iFullSz/2;
|
|
return iFullSz;
|
|
}
|
|
|
|
/*
|
|
** Return the ceiling of the logarithm base 2 of iValue.
|
|
**
|
|
** Examples: memsys5Log(1) -> 0
|
|
** memsys5Log(2) -> 1
|
|
** memsys5Log(4) -> 2
|
|
** memsys5Log(5) -> 3
|
|
** memsys5Log(8) -> 3
|
|
** memsys5Log(9) -> 4
|
|
*/
|
|
static int memsys5Log(int iValue){
|
|
int iLog;
|
|
for(iLog=0; (iLog<(int)((sizeof(int)*8)-1)) && (1<<iLog)<iValue; iLog++);
|
|
return iLog;
|
|
}
|
|
|
|
/*
|
|
** Initialize the memory allocator.
|
|
**
|
|
** This routine is not threadsafe. The caller must be holding a mutex
|
|
** to prevent multiple threads from entering at the same time.
|
|
*/
|
|
static int memsys5Init(void *NotUsed){
|
|
int ii; /* Loop counter */
|
|
int nByte; /* Number of bytes of memory available to this allocator */
|
|
u8 *zByte; /* Memory usable by this allocator */
|
|
int nMinLog; /* Log base 2 of minimum allocation size in bytes */
|
|
int iOffset; /* An offset into mem5.aCtrl[] */
|
|
|
|
UNUSED_PARAMETER(NotUsed);
|
|
|
|
/* For the purposes of this routine, disable the mutex */
|
|
mem5.mutex = 0;
|
|
|
|
/* The size of a Mem5Link object must be a power of two. Verify that
|
|
** this is case.
|
|
*/
|
|
assert( (sizeof(Mem5Link)&(sizeof(Mem5Link)-1))==0 );
|
|
|
|
nByte = sqlite3GlobalConfig.nHeap;
|
|
zByte = (u8*)sqlite3GlobalConfig.pHeap;
|
|
assert( zByte!=0 ); /* sqlite3_config() does not allow otherwise */
|
|
|
|
/* boundaries on sqlite3GlobalConfig.mnReq are enforced in sqlite3_config() */
|
|
nMinLog = memsys5Log(sqlite3GlobalConfig.mnReq);
|
|
mem5.szAtom = (1<<nMinLog);
|
|
while( (int)sizeof(Mem5Link)>mem5.szAtom ){
|
|
mem5.szAtom = mem5.szAtom << 1;
|
|
}
|
|
|
|
mem5.nBlock = (nByte / (mem5.szAtom+sizeof(u8)));
|
|
mem5.zPool = zByte;
|
|
mem5.aCtrl = (u8 *)&mem5.zPool[mem5.nBlock*mem5.szAtom];
|
|
|
|
for(ii=0; ii<=LOGMAX; ii++){
|
|
mem5.aiFreelist[ii] = -1;
|
|
}
|
|
|
|
iOffset = 0;
|
|
for(ii=LOGMAX; ii>=0; ii--){
|
|
int nAlloc = (1<<ii);
|
|
if( (iOffset+nAlloc)<=mem5.nBlock ){
|
|
mem5.aCtrl[iOffset] = ii | CTRL_FREE;
|
|
memsys5Link(iOffset, ii);
|
|
iOffset += nAlloc;
|
|
}
|
|
assert((iOffset+nAlloc)>mem5.nBlock);
|
|
}
|
|
|
|
/* If a mutex is required for normal operation, allocate one */
|
|
if( sqlite3GlobalConfig.bMemstat==0 ){
|
|
mem5.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
|
|
}
|
|
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Deinitialize this module.
|
|
*/
|
|
static void memsys5Shutdown(void *NotUsed){
|
|
UNUSED_PARAMETER(NotUsed);
|
|
mem5.mutex = 0;
|
|
return;
|
|
}
|
|
|
|
#ifdef SQLITE_TEST
|
|
/*
|
|
** Open the file indicated and write a log of all unfreed memory
|
|
** allocations into that log.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3Memsys5Dump(const char *zFilename){
|
|
FILE *out;
|
|
int i, j, n;
|
|
int nMinLog;
|
|
|
|
if( zFilename==0 || zFilename[0]==0 ){
|
|
out = stdout;
|
|
}else{
|
|
out = fopen(zFilename, "w");
|
|
if( out==0 ){
|
|
fprintf(stderr, "** Unable to output memory debug output log: %s **\n",
|
|
zFilename);
|
|
return;
|
|
}
|
|
}
|
|
memsys5Enter();
|
|
nMinLog = memsys5Log(mem5.szAtom);
|
|
for(i=0; i<=LOGMAX && i+nMinLog<32; i++){
|
|
for(n=0, j=mem5.aiFreelist[i]; j>=0; j = MEM5LINK(j)->next, n++){}
|
|
fprintf(out, "freelist items of size %d: %d\n", mem5.szAtom << i, n);
|
|
}
|
|
fprintf(out, "mem5.nAlloc = %llu\n", mem5.nAlloc);
|
|
fprintf(out, "mem5.totalAlloc = %llu\n", mem5.totalAlloc);
|
|
fprintf(out, "mem5.totalExcess = %llu\n", mem5.totalExcess);
|
|
fprintf(out, "mem5.currentOut = %u\n", mem5.currentOut);
|
|
fprintf(out, "mem5.currentCount = %u\n", mem5.currentCount);
|
|
fprintf(out, "mem5.maxOut = %u\n", mem5.maxOut);
|
|
fprintf(out, "mem5.maxCount = %u\n", mem5.maxCount);
|
|
fprintf(out, "mem5.maxRequest = %u\n", mem5.maxRequest);
|
|
memsys5Leave();
|
|
if( out==stdout ){
|
|
fflush(stdout);
|
|
}else{
|
|
fclose(out);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
** This routine is the only routine in this file with external
|
|
** linkage. It returns a pointer to a static sqlite3_mem_methods
|
|
** struct populated with the memsys5 methods.
|
|
*/
|
|
SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetMemsys5(void){
|
|
static const sqlite3_mem_methods memsys5Methods = {
|
|
memsys5Malloc,
|
|
memsys5Free,
|
|
memsys5Realloc,
|
|
memsys5Size,
|
|
memsys5Roundup,
|
|
memsys5Init,
|
|
memsys5Shutdown,
|
|
0
|
|
};
|
|
return &memsys5Methods;
|
|
}
|
|
|
|
#endif /* SQLITE_ENABLE_MEMSYS5 */
|
|
|
|
/************** End of mem5.c ************************************************/
|
|
/************** Begin file mutex.c *******************************************/
|
|
/*
|
|
** 2007 August 14
|
|
**
|
|
** 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 mutexes.
|
|
**
|
|
** This file contains code that is common across all mutex implementations.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
|
|
#if defined(SQLITE_DEBUG) && !defined(SQLITE_MUTEX_OMIT)
|
|
/*
|
|
** For debugging purposes, record when the mutex subsystem is initialized
|
|
** and uninitialized so that we can assert() if there is an attempt to
|
|
** allocate a mutex while the system is uninitialized.
|
|
*/
|
|
static SQLITE_WSD int mutexIsInit = 0;
|
|
#endif /* SQLITE_DEBUG && !defined(SQLITE_MUTEX_OMIT) */
|
|
|
|
|
|
#ifndef SQLITE_MUTEX_OMIT
|
|
|
|
#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
|
|
/*
|
|
** This block (enclosed by SQLITE_ENABLE_MULTITHREADED_CHECKS) contains
|
|
** the implementation of a wrapper around the system default mutex
|
|
** implementation (sqlite3DefaultMutex()).
|
|
**
|
|
** Most calls are passed directly through to the underlying default
|
|
** mutex implementation. Except, if a mutex is configured by calling
|
|
** sqlite3MutexWarnOnContention() on it, then if contention is ever
|
|
** encountered within xMutexEnter() a warning is emitted via sqlite3_log().
|
|
**
|
|
** This type of mutex is used as the database handle mutex when testing
|
|
** apps that usually use SQLITE_CONFIG_MULTITHREAD mode.
|
|
*/
|
|
|
|
/*
|
|
** Type for all mutexes used when SQLITE_ENABLE_MULTITHREADED_CHECKS
|
|
** is defined. Variable CheckMutex.mutex is a pointer to the real mutex
|
|
** allocated by the system mutex implementation. Variable iType is usually set
|
|
** to the type of mutex requested - SQLITE_MUTEX_RECURSIVE, SQLITE_MUTEX_FAST
|
|
** or one of the static mutex identifiers. Or, if this is a recursive mutex
|
|
** that has been configured using sqlite3MutexWarnOnContention(), it is
|
|
** set to SQLITE_MUTEX_WARNONCONTENTION.
|
|
*/
|
|
typedef struct CheckMutex CheckMutex;
|
|
struct CheckMutex {
|
|
int iType;
|
|
sqlite3_mutex *mutex;
|
|
};
|
|
|
|
#define SQLITE_MUTEX_WARNONCONTENTION (-1)
|
|
|
|
/*
|
|
** Pointer to real mutex methods object used by the CheckMutex
|
|
** implementation. Set by checkMutexInit().
|
|
*/
|
|
static SQLITE_WSD const sqlite3_mutex_methods *pGlobalMutexMethods;
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
static int checkMutexHeld(sqlite3_mutex *p){
|
|
return pGlobalMutexMethods->xMutexHeld(((CheckMutex*)p)->mutex);
|
|
}
|
|
static int checkMutexNotheld(sqlite3_mutex *p){
|
|
return pGlobalMutexMethods->xMutexNotheld(((CheckMutex*)p)->mutex);
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
** Initialize and deinitialize the mutex subsystem.
|
|
*/
|
|
static int checkMutexInit(void){
|
|
pGlobalMutexMethods = sqlite3DefaultMutex();
|
|
return SQLITE_OK;
|
|
}
|
|
static int checkMutexEnd(void){
|
|
pGlobalMutexMethods = 0;
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Allocate a mutex.
|
|
*/
|
|
static sqlite3_mutex *checkMutexAlloc(int iType){
|
|
static CheckMutex staticMutexes[] = {
|
|
{2, 0}, {3, 0}, {4, 0}, {5, 0},
|
|
{6, 0}, {7, 0}, {8, 0}, {9, 0},
|
|
{10, 0}, {11, 0}, {12, 0}, {13, 0}
|
|
};
|
|
CheckMutex *p = 0;
|
|
|
|
assert( SQLITE_MUTEX_RECURSIVE==1 && SQLITE_MUTEX_FAST==0 );
|
|
if( iType<2 ){
|
|
p = sqlite3MallocZero(sizeof(CheckMutex));
|
|
if( p==0 ) return 0;
|
|
p->iType = iType;
|
|
}else{
|
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
|
if( iType-2>=ArraySize(staticMutexes) ){
|
|
(void)SQLITE_MISUSE_BKPT;
|
|
return 0;
|
|
}
|
|
#endif
|
|
p = &staticMutexes[iType-2];
|
|
}
|
|
|
|
if( p->mutex==0 ){
|
|
p->mutex = pGlobalMutexMethods->xMutexAlloc(iType);
|
|
if( p->mutex==0 ){
|
|
if( iType<2 ){
|
|
sqlite3_free(p);
|
|
}
|
|
p = 0;
|
|
}
|
|
}
|
|
|
|
return (sqlite3_mutex*)p;
|
|
}
|
|
|
|
/*
|
|
** Free a mutex.
|
|
*/
|
|
static void checkMutexFree(sqlite3_mutex *p){
|
|
assert( SQLITE_MUTEX_RECURSIVE<2 );
|
|
assert( SQLITE_MUTEX_FAST<2 );
|
|
assert( SQLITE_MUTEX_WARNONCONTENTION<2 );
|
|
|
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
|
if( ((CheckMutex*)p)->iType<2 )
|
|
#endif
|
|
{
|
|
CheckMutex *pCheck = (CheckMutex*)p;
|
|
pGlobalMutexMethods->xMutexFree(pCheck->mutex);
|
|
sqlite3_free(pCheck);
|
|
}
|
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
|
else{
|
|
(void)SQLITE_MISUSE_BKPT;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
** Enter the mutex.
|
|
*/
|
|
static void checkMutexEnter(sqlite3_mutex *p){
|
|
CheckMutex *pCheck = (CheckMutex*)p;
|
|
if( pCheck->iType==SQLITE_MUTEX_WARNONCONTENTION ){
|
|
if( SQLITE_OK==pGlobalMutexMethods->xMutexTry(pCheck->mutex) ){
|
|
return;
|
|
}
|
|
sqlite3_log(SQLITE_MISUSE,
|
|
"illegal multi-threaded access to database connection"
|
|
);
|
|
}
|
|
pGlobalMutexMethods->xMutexEnter(pCheck->mutex);
|
|
}
|
|
|
|
/*
|
|
** Enter the mutex (do not block).
|
|
*/
|
|
static int checkMutexTry(sqlite3_mutex *p){
|
|
CheckMutex *pCheck = (CheckMutex*)p;
|
|
return pGlobalMutexMethods->xMutexTry(pCheck->mutex);
|
|
}
|
|
|
|
/*
|
|
** Leave the mutex.
|
|
*/
|
|
static void checkMutexLeave(sqlite3_mutex *p){
|
|
CheckMutex *pCheck = (CheckMutex*)p;
|
|
pGlobalMutexMethods->xMutexLeave(pCheck->mutex);
|
|
}
|
|
|
|
sqlite3_mutex_methods const *multiThreadedCheckMutex(void){
|
|
static const sqlite3_mutex_methods sMutex = {
|
|
checkMutexInit,
|
|
checkMutexEnd,
|
|
checkMutexAlloc,
|
|
checkMutexFree,
|
|
checkMutexEnter,
|
|
checkMutexTry,
|
|
checkMutexLeave,
|
|
#ifdef SQLITE_DEBUG
|
|
checkMutexHeld,
|
|
checkMutexNotheld
|
|
#else
|
|
0,
|
|
0
|
|
#endif
|
|
};
|
|
return &sMutex;
|
|
}
|
|
|
|
/*
|
|
** Mark the SQLITE_MUTEX_RECURSIVE mutex passed as the only argument as
|
|
** one on which there should be no contention.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3MutexWarnOnContention(sqlite3_mutex *p){
|
|
if( sqlite3GlobalConfig.mutex.xMutexAlloc==checkMutexAlloc ){
|
|
CheckMutex *pCheck = (CheckMutex*)p;
|
|
assert( pCheck->iType==SQLITE_MUTEX_RECURSIVE );
|
|
pCheck->iType = SQLITE_MUTEX_WARNONCONTENTION;
|
|
}
|
|
}
|
|
#endif /* ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS */
|
|
|
|
/*
|
|
** Initialize the mutex system.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3MutexInit(void){
|
|
int rc = SQLITE_OK;
|
|
if( !sqlite3GlobalConfig.mutex.xMutexAlloc ){
|
|
/* If the xMutexAlloc method has not been set, then the user did not
|
|
** install a mutex implementation via sqlite3_config() prior to
|
|
** sqlite3_initialize() being called. This block copies pointers to
|
|
** the default implementation into the sqlite3GlobalConfig structure.
|
|
*/
|
|
sqlite3_mutex_methods const *pFrom;
|
|
sqlite3_mutex_methods *pTo = &sqlite3GlobalConfig.mutex;
|
|
|
|
if( sqlite3GlobalConfig.bCoreMutex ){
|
|
#ifdef SQLITE_ENABLE_MULTITHREADED_CHECKS
|
|
pFrom = multiThreadedCheckMutex();
|
|
#else
|
|
pFrom = sqlite3DefaultMutex();
|
|
#endif
|
|
}else{
|
|
pFrom = sqlite3NoopMutex();
|
|
}
|
|
pTo->xMutexInit = pFrom->xMutexInit;
|
|
pTo->xMutexEnd = pFrom->xMutexEnd;
|
|
pTo->xMutexFree = pFrom->xMutexFree;
|
|
pTo->xMutexEnter = pFrom->xMutexEnter;
|
|
pTo->xMutexTry = pFrom->xMutexTry;
|
|
pTo->xMutexLeave = pFrom->xMutexLeave;
|
|
pTo->xMutexHeld = pFrom->xMutexHeld;
|
|
pTo->xMutexNotheld = pFrom->xMutexNotheld;
|
|
sqlite3MemoryBarrier();
|
|
pTo->xMutexAlloc = pFrom->xMutexAlloc;
|
|
}
|
|
assert( sqlite3GlobalConfig.mutex.xMutexInit );
|
|
rc = sqlite3GlobalConfig.mutex.xMutexInit();
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
GLOBAL(int, mutexIsInit) = 1;
|
|
#endif
|
|
|
|
sqlite3MemoryBarrier();
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Shutdown the mutex system. This call frees resources allocated by
|
|
** sqlite3MutexInit().
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3MutexEnd(void){
|
|
int rc = SQLITE_OK;
|
|
if( sqlite3GlobalConfig.mutex.xMutexEnd ){
|
|
rc = sqlite3GlobalConfig.mutex.xMutexEnd();
|
|
}
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
GLOBAL(int, mutexIsInit) = 0;
|
|
#endif
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Retrieve a pointer to a static mutex or allocate a new dynamic one.
|
|
*/
|
|
SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int id){
|
|
#ifndef SQLITE_OMIT_AUTOINIT
|
|
if( id<=SQLITE_MUTEX_RECURSIVE && sqlite3_initialize() ) return 0;
|
|
if( id>SQLITE_MUTEX_RECURSIVE && sqlite3MutexInit() ) return 0;
|
|
#endif
|
|
assert( sqlite3GlobalConfig.mutex.xMutexAlloc );
|
|
return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
|
|
}
|
|
|
|
SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int id){
|
|
if( !sqlite3GlobalConfig.bCoreMutex ){
|
|
return 0;
|
|
}
|
|
assert( GLOBAL(int, mutexIsInit) );
|
|
assert( sqlite3GlobalConfig.mutex.xMutexAlloc );
|
|
return sqlite3GlobalConfig.mutex.xMutexAlloc(id);
|
|
}
|
|
|
|
/*
|
|
** Free a dynamic mutex.
|
|
*/
|
|
SQLITE_API void sqlite3_mutex_free(sqlite3_mutex *p){
|
|
if( p ){
|
|
assert( sqlite3GlobalConfig.mutex.xMutexFree );
|
|
sqlite3GlobalConfig.mutex.xMutexFree(p);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Obtain the mutex p. If some other thread already has the mutex, block
|
|
** until it can be obtained.
|
|
*/
|
|
SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex *p){
|
|
if( p ){
|
|
assert( sqlite3GlobalConfig.mutex.xMutexEnter );
|
|
sqlite3GlobalConfig.mutex.xMutexEnter(p);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another
|
|
** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY.
|
|
*/
|
|
SQLITE_API int sqlite3_mutex_try(sqlite3_mutex *p){
|
|
int rc = SQLITE_OK;
|
|
if( p ){
|
|
assert( sqlite3GlobalConfig.mutex.xMutexTry );
|
|
return sqlite3GlobalConfig.mutex.xMutexTry(p);
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** The sqlite3_mutex_leave() routine exits a mutex that was previously
|
|
** entered by the same thread. The behavior is undefined if the mutex
|
|
** is not currently entered. If a NULL pointer is passed as an argument
|
|
** this function is a no-op.
|
|
*/
|
|
SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex *p){
|
|
if( p ){
|
|
assert( sqlite3GlobalConfig.mutex.xMutexLeave );
|
|
sqlite3GlobalConfig.mutex.xMutexLeave(p);
|
|
}
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
/*
|
|
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
|
|
** intended for use inside assert() statements.
|
|
*/
|
|
SQLITE_API int sqlite3_mutex_held(sqlite3_mutex *p){
|
|
assert( p==0 || sqlite3GlobalConfig.mutex.xMutexHeld );
|
|
return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p);
|
|
}
|
|
SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){
|
|
assert( p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld );
|
|
return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p);
|
|
}
|
|
#endif
|
|
|
|
#endif /* !defined(SQLITE_MUTEX_OMIT) */
|
|
|
|
/************** End of mutex.c ***********************************************/
|
|
/************** Begin file mutex_noop.c **************************************/
|
|
/*
|
|
** 2008 October 07
|
|
**
|
|
** 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 mutexes.
|
|
**
|
|
** This implementation in this file does not provide any mutual
|
|
** exclusion and is thus suitable for use only in applications
|
|
** that use SQLite in a single thread. The routines defined
|
|
** here are place-holders. Applications can substitute working
|
|
** mutex routines at start-time using the
|
|
**
|
|
** sqlite3_config(SQLITE_CONFIG_MUTEX,...)
|
|
**
|
|
** interface.
|
|
**
|
|
** If compiled with SQLITE_DEBUG, then additional logic is inserted
|
|
** that does error checking on mutexes to make sure they are being
|
|
** called correctly.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
|
|
#ifndef SQLITE_MUTEX_OMIT
|
|
|
|
#ifndef SQLITE_DEBUG
|
|
/*
|
|
** Stub routines for all mutex methods.
|
|
**
|
|
** This routines provide no mutual exclusion or error checking.
|
|
*/
|
|
static int noopMutexInit(void){ return SQLITE_OK; }
|
|
static int noopMutexEnd(void){ return SQLITE_OK; }
|
|
static sqlite3_mutex *noopMutexAlloc(int id){
|
|
UNUSED_PARAMETER(id);
|
|
return (sqlite3_mutex*)8;
|
|
}
|
|
static void noopMutexFree(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
|
|
static void noopMutexEnter(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
|
|
static int noopMutexTry(sqlite3_mutex *p){
|
|
UNUSED_PARAMETER(p);
|
|
return SQLITE_OK;
|
|
}
|
|
static void noopMutexLeave(sqlite3_mutex *p){ UNUSED_PARAMETER(p); return; }
|
|
|
|
SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3NoopMutex(void){
|
|
static const sqlite3_mutex_methods sMutex = {
|
|
noopMutexInit,
|
|
noopMutexEnd,
|
|
noopMutexAlloc,
|
|
noopMutexFree,
|
|
noopMutexEnter,
|
|
noopMutexTry,
|
|
noopMutexLeave,
|
|
|
|
0,
|
|
0,
|
|
};
|
|
|
|
return &sMutex;
|
|
}
|
|
#endif /* !SQLITE_DEBUG */
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
/*
|
|
** In this implementation, error checking is provided for testing
|
|
** and debugging purposes. The mutexes still do not provide any
|
|
** mutual exclusion.
|
|
*/
|
|
|
|
/*
|
|
** The mutex object
|
|
*/
|
|
typedef struct sqlite3_debug_mutex {
|
|
int id; /* The mutex type */
|
|
int cnt; /* Number of entries without a matching leave */
|
|
} sqlite3_debug_mutex;
|
|
|
|
/*
|
|
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
|
|
** intended for use inside assert() statements.
|
|
*/
|
|
static int debugMutexHeld(sqlite3_mutex *pX){
|
|
sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
|
|
return p==0 || p->cnt>0;
|
|
}
|
|
static int debugMutexNotheld(sqlite3_mutex *pX){
|
|
sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
|
|
return p==0 || p->cnt==0;
|
|
}
|
|
|
|
/*
|
|
** Initialize and deinitialize the mutex subsystem.
|
|
*/
|
|
static int debugMutexInit(void){ return SQLITE_OK; }
|
|
static int debugMutexEnd(void){ return SQLITE_OK; }
|
|
|
|
/*
|
|
** The sqlite3_mutex_alloc() routine allocates a new
|
|
** mutex and returns a pointer to it. If it returns NULL
|
|
** that means that a mutex could not be allocated.
|
|
*/
|
|
static sqlite3_mutex *debugMutexAlloc(int id){
|
|
static sqlite3_debug_mutex aStatic[SQLITE_MUTEX_STATIC_VFS3 - 1];
|
|
sqlite3_debug_mutex *pNew = 0;
|
|
switch( id ){
|
|
case SQLITE_MUTEX_FAST:
|
|
case SQLITE_MUTEX_RECURSIVE: {
|
|
pNew = sqlite3Malloc(sizeof(*pNew));
|
|
if( pNew ){
|
|
pNew->id = id;
|
|
pNew->cnt = 0;
|
|
}
|
|
break;
|
|
}
|
|
default: {
|
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
|
if( id-2<0 || id-2>=ArraySize(aStatic) ){
|
|
(void)SQLITE_MISUSE_BKPT;
|
|
return 0;
|
|
}
|
|
#endif
|
|
pNew = &aStatic[id-2];
|
|
pNew->id = id;
|
|
break;
|
|
}
|
|
}
|
|
return (sqlite3_mutex*)pNew;
|
|
}
|
|
|
|
/*
|
|
** This routine deallocates a previously allocated mutex.
|
|
*/
|
|
static void debugMutexFree(sqlite3_mutex *pX){
|
|
sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
|
|
assert( p->cnt==0 );
|
|
if( p->id==SQLITE_MUTEX_RECURSIVE || p->id==SQLITE_MUTEX_FAST ){
|
|
sqlite3_free(p);
|
|
}else{
|
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
|
(void)SQLITE_MISUSE_BKPT;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/*
|
|
** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
|
|
** to enter a mutex. If another thread is already within the mutex,
|
|
** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
|
|
** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK
|
|
** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can
|
|
** be entered multiple times by the same thread. In such cases the,
|
|
** mutex must be exited an equal number of times before another thread
|
|
** can enter. If the same thread tries to enter any other kind of mutex
|
|
** more than once, the behavior is undefined.
|
|
*/
|
|
static void debugMutexEnter(sqlite3_mutex *pX){
|
|
sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
|
|
assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
|
|
p->cnt++;
|
|
}
|
|
static int debugMutexTry(sqlite3_mutex *pX){
|
|
sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
|
|
assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
|
|
p->cnt++;
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** The sqlite3_mutex_leave() routine exits a mutex that was
|
|
** previously entered by the same thread. The behavior
|
|
** is undefined if the mutex is not currently entered or
|
|
** is not currently allocated. SQLite will never do either.
|
|
*/
|
|
static void debugMutexLeave(sqlite3_mutex *pX){
|
|
sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
|
|
assert( debugMutexHeld(pX) );
|
|
p->cnt--;
|
|
assert( p->id==SQLITE_MUTEX_RECURSIVE || debugMutexNotheld(pX) );
|
|
}
|
|
|
|
SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3NoopMutex(void){
|
|
static const sqlite3_mutex_methods sMutex = {
|
|
debugMutexInit,
|
|
debugMutexEnd,
|
|
debugMutexAlloc,
|
|
debugMutexFree,
|
|
debugMutexEnter,
|
|
debugMutexTry,
|
|
debugMutexLeave,
|
|
|
|
debugMutexHeld,
|
|
debugMutexNotheld
|
|
};
|
|
|
|
return &sMutex;
|
|
}
|
|
#endif /* SQLITE_DEBUG */
|
|
|
|
/*
|
|
** If compiled with SQLITE_MUTEX_NOOP, then the no-op mutex implementation
|
|
** is used regardless of the run-time threadsafety setting.
|
|
*/
|
|
#ifdef SQLITE_MUTEX_NOOP
|
|
SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
|
|
return sqlite3NoopMutex();
|
|
}
|
|
#endif /* defined(SQLITE_MUTEX_NOOP) */
|
|
#endif /* !defined(SQLITE_MUTEX_OMIT) */
|
|
|
|
/************** End of mutex_noop.c ******************************************/
|
|
/************** Begin file mutex_unix.c **************************************/
|
|
/*
|
|
** 2007 August 28
|
|
**
|
|
** 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 mutexes for pthreads
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
|
|
/*
|
|
** The code in this file is only used if we are compiling threadsafe
|
|
** under unix with pthreads.
|
|
**
|
|
** Note that this implementation requires a version of pthreads that
|
|
** supports recursive mutexes.
|
|
*/
|
|
#ifdef SQLITE_MUTEX_PTHREADS
|
|
|
|
#include <pthread.h>
|
|
|
|
/*
|
|
** The sqlite3_mutex.id, sqlite3_mutex.nRef, and sqlite3_mutex.owner fields
|
|
** are necessary under two conditions: (1) Debug builds and (2) using
|
|
** home-grown mutexes. Encapsulate these conditions into a single #define.
|
|
*/
|
|
#if defined(SQLITE_DEBUG) || defined(SQLITE_HOMEGROWN_RECURSIVE_MUTEX)
|
|
# define SQLITE_MUTEX_NREF 1
|
|
#else
|
|
# define SQLITE_MUTEX_NREF 0
|
|
#endif
|
|
|
|
/*
|
|
** Each recursive mutex is an instance of the following structure.
|
|
*/
|
|
struct sqlite3_mutex {
|
|
pthread_mutex_t mutex; /* Mutex controlling the lock */
|
|
#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR)
|
|
int id; /* Mutex type */
|
|
#endif
|
|
#if SQLITE_MUTEX_NREF
|
|
volatile int nRef; /* Number of entrances */
|
|
volatile pthread_t owner; /* Thread that is within this mutex */
|
|
int trace; /* True to trace changes */
|
|
#endif
|
|
};
|
|
#if SQLITE_MUTEX_NREF
|
|
# define SQLITE3_MUTEX_INITIALIZER(id) \
|
|
{PTHREAD_MUTEX_INITIALIZER,id,0,(pthread_t)0,0}
|
|
#elif defined(SQLITE_ENABLE_API_ARMOR)
|
|
# define SQLITE3_MUTEX_INITIALIZER(id) { PTHREAD_MUTEX_INITIALIZER, id }
|
|
#else
|
|
#define SQLITE3_MUTEX_INITIALIZER(id) { PTHREAD_MUTEX_INITIALIZER }
|
|
#endif
|
|
|
|
/*
|
|
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
|
|
** intended for use only inside assert() statements. On some platforms,
|
|
** there might be race conditions that can cause these routines to
|
|
** deliver incorrect results. In particular, if pthread_equal() is
|
|
** not an atomic operation, then these routines might delivery
|
|
** incorrect results. On most platforms, pthread_equal() is a
|
|
** comparison of two integers and is therefore atomic. But we are
|
|
** told that HPUX is not such a platform. If so, then these routines
|
|
** will not always work correctly on HPUX.
|
|
**
|
|
** On those platforms where pthread_equal() is not atomic, SQLite
|
|
** should be compiled without -DSQLITE_DEBUG and with -DNDEBUG to
|
|
** make sure no assert() statements are evaluated and hence these
|
|
** routines are never called.
|
|
*/
|
|
#if !defined(NDEBUG) || defined(SQLITE_DEBUG)
|
|
static int pthreadMutexHeld(sqlite3_mutex *p){
|
|
return (p->nRef!=0 && pthread_equal(p->owner, pthread_self()));
|
|
}
|
|
static int pthreadMutexNotheld(sqlite3_mutex *p){
|
|
return p->nRef==0 || pthread_equal(p->owner, pthread_self())==0;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
** Try to provide a memory barrier operation, needed for initialization
|
|
** and also for the implementation of xShmBarrier in the VFS in cases
|
|
** where SQLite is compiled without mutexes.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3MemoryBarrier(void){
|
|
#if defined(SQLITE_MEMORY_BARRIER)
|
|
SQLITE_MEMORY_BARRIER;
|
|
#elif defined(__GNUC__) && GCC_VERSION>=4001000
|
|
__sync_synchronize();
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
** Initialize and deinitialize the mutex subsystem.
|
|
*/
|
|
static int pthreadMutexInit(void){ return SQLITE_OK; }
|
|
static int pthreadMutexEnd(void){ return SQLITE_OK; }
|
|
|
|
/*
|
|
** The sqlite3_mutex_alloc() routine allocates a new
|
|
** mutex and returns a pointer to it. If it returns NULL
|
|
** that means that a mutex could not be allocated. SQLite
|
|
** will unwind its stack and return an error. The argument
|
|
** to sqlite3_mutex_alloc() is one of these integer constants:
|
|
**
|
|
** <ul>
|
|
** <li> SQLITE_MUTEX_FAST
|
|
** <li> SQLITE_MUTEX_RECURSIVE
|
|
** <li> SQLITE_MUTEX_STATIC_MAIN
|
|
** <li> SQLITE_MUTEX_STATIC_MEM
|
|
** <li> SQLITE_MUTEX_STATIC_OPEN
|
|
** <li> SQLITE_MUTEX_STATIC_PRNG
|
|
** <li> SQLITE_MUTEX_STATIC_LRU
|
|
** <li> SQLITE_MUTEX_STATIC_PMEM
|
|
** <li> SQLITE_MUTEX_STATIC_APP1
|
|
** <li> SQLITE_MUTEX_STATIC_APP2
|
|
** <li> SQLITE_MUTEX_STATIC_APP3
|
|
** <li> SQLITE_MUTEX_STATIC_VFS1
|
|
** <li> SQLITE_MUTEX_STATIC_VFS2
|
|
** <li> SQLITE_MUTEX_STATIC_VFS3
|
|
** </ul>
|
|
**
|
|
** The first two constants cause sqlite3_mutex_alloc() to create
|
|
** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
|
|
** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
|
|
** The mutex implementation does not need to make a distinction
|
|
** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
|
|
** not want to. But SQLite will only request a recursive mutex in
|
|
** cases where it really needs one. If a faster non-recursive mutex
|
|
** implementation is available on the host platform, the mutex subsystem
|
|
** might return such a mutex in response to SQLITE_MUTEX_FAST.
|
|
**
|
|
** The other allowed parameters to sqlite3_mutex_alloc() each return
|
|
** a pointer to a static preexisting mutex. Six static mutexes are
|
|
** used by the current version of SQLite. Future versions of SQLite
|
|
** may add additional static mutexes. Static mutexes are for internal
|
|
** use by SQLite only. Applications that use SQLite mutexes should
|
|
** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
|
|
** SQLITE_MUTEX_RECURSIVE.
|
|
**
|
|
** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
|
|
** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
|
|
** returns a different mutex on every call. But for the static
|
|
** mutex types, the same mutex is returned on every call that has
|
|
** the same type number.
|
|
*/
|
|
static sqlite3_mutex *pthreadMutexAlloc(int iType){
|
|
static sqlite3_mutex staticMutexes[] = {
|
|
SQLITE3_MUTEX_INITIALIZER(2),
|
|
SQLITE3_MUTEX_INITIALIZER(3),
|
|
SQLITE3_MUTEX_INITIALIZER(4),
|
|
SQLITE3_MUTEX_INITIALIZER(5),
|
|
SQLITE3_MUTEX_INITIALIZER(6),
|
|
SQLITE3_MUTEX_INITIALIZER(7),
|
|
SQLITE3_MUTEX_INITIALIZER(8),
|
|
SQLITE3_MUTEX_INITIALIZER(9),
|
|
SQLITE3_MUTEX_INITIALIZER(10),
|
|
SQLITE3_MUTEX_INITIALIZER(11),
|
|
SQLITE3_MUTEX_INITIALIZER(12),
|
|
SQLITE3_MUTEX_INITIALIZER(13)
|
|
};
|
|
sqlite3_mutex *p;
|
|
switch( iType ){
|
|
case SQLITE_MUTEX_RECURSIVE: {
|
|
p = sqlite3MallocZero( sizeof(*p) );
|
|
if( p ){
|
|
#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
|
|
/* If recursive mutexes are not available, we will have to
|
|
** build our own. See below. */
|
|
pthread_mutex_init(&p->mutex, 0);
|
|
#else
|
|
/* Use a recursive mutex if it is available */
|
|
pthread_mutexattr_t recursiveAttr;
|
|
pthread_mutexattr_init(&recursiveAttr);
|
|
pthread_mutexattr_settype(&recursiveAttr, PTHREAD_MUTEX_RECURSIVE);
|
|
pthread_mutex_init(&p->mutex, &recursiveAttr);
|
|
pthread_mutexattr_destroy(&recursiveAttr);
|
|
#endif
|
|
#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR)
|
|
p->id = SQLITE_MUTEX_RECURSIVE;
|
|
#endif
|
|
}
|
|
break;
|
|
}
|
|
case SQLITE_MUTEX_FAST: {
|
|
p = sqlite3MallocZero( sizeof(*p) );
|
|
if( p ){
|
|
pthread_mutex_init(&p->mutex, 0);
|
|
#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR)
|
|
p->id = SQLITE_MUTEX_FAST;
|
|
#endif
|
|
}
|
|
break;
|
|
}
|
|
default: {
|
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
|
if( iType-2<0 || iType-2>=ArraySize(staticMutexes) ){
|
|
(void)SQLITE_MISUSE_BKPT;
|
|
return 0;
|
|
}
|
|
#endif
|
|
p = &staticMutexes[iType-2];
|
|
break;
|
|
}
|
|
}
|
|
#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR)
|
|
assert( p==0 || p->id==iType );
|
|
#endif
|
|
return p;
|
|
}
|
|
|
|
|
|
/*
|
|
** This routine deallocates a previously
|
|
** allocated mutex. SQLite is careful to deallocate every
|
|
** mutex that it allocates.
|
|
*/
|
|
static void pthreadMutexFree(sqlite3_mutex *p){
|
|
assert( p->nRef==0 );
|
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
|
if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE )
|
|
#endif
|
|
{
|
|
pthread_mutex_destroy(&p->mutex);
|
|
sqlite3_free(p);
|
|
}
|
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
|
else{
|
|
(void)SQLITE_MISUSE_BKPT;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
|
|
** to enter a mutex. If another thread is already within the mutex,
|
|
** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
|
|
** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK
|
|
** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can
|
|
** be entered multiple times by the same thread. In such cases the,
|
|
** mutex must be exited an equal number of times before another thread
|
|
** can enter. If the same thread tries to enter any other kind of mutex
|
|
** more than once, the behavior is undefined.
|
|
*/
|
|
static void pthreadMutexEnter(sqlite3_mutex *p){
|
|
assert( p->id==SQLITE_MUTEX_RECURSIVE || pthreadMutexNotheld(p) );
|
|
|
|
#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
|
|
/* If recursive mutexes are not available, then we have to grow
|
|
** our own. This implementation assumes that pthread_equal()
|
|
** is atomic - that it cannot be deceived into thinking self
|
|
** and p->owner are equal if p->owner changes between two values
|
|
** that are not equal to self while the comparison is taking place.
|
|
** This implementation also assumes a coherent cache - that
|
|
** separate processes cannot read different values from the same
|
|
** address at the same time. If either of these two conditions
|
|
** are not met, then the mutexes will fail and problems will result.
|
|
*/
|
|
{
|
|
pthread_t self = pthread_self();
|
|
if( p->nRef>0 && pthread_equal(p->owner, self) ){
|
|
p->nRef++;
|
|
}else{
|
|
pthread_mutex_lock(&p->mutex);
|
|
assert( p->nRef==0 );
|
|
p->owner = self;
|
|
p->nRef = 1;
|
|
}
|
|
}
|
|
#else
|
|
/* Use the built-in recursive mutexes if they are available.
|
|
*/
|
|
pthread_mutex_lock(&p->mutex);
|
|
#if SQLITE_MUTEX_NREF
|
|
assert( p->nRef>0 || p->owner==0 );
|
|
p->owner = pthread_self();
|
|
p->nRef++;
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
if( p->trace ){
|
|
printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
|
|
}
|
|
#endif
|
|
}
|
|
static int pthreadMutexTry(sqlite3_mutex *p){
|
|
int rc;
|
|
assert( p->id==SQLITE_MUTEX_RECURSIVE || pthreadMutexNotheld(p) );
|
|
|
|
#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
|
|
/* If recursive mutexes are not available, then we have to grow
|
|
** our own. This implementation assumes that pthread_equal()
|
|
** is atomic - that it cannot be deceived into thinking self
|
|
** and p->owner are equal if p->owner changes between two values
|
|
** that are not equal to self while the comparison is taking place.
|
|
** This implementation also assumes a coherent cache - that
|
|
** separate processes cannot read different values from the same
|
|
** address at the same time. If either of these two conditions
|
|
** are not met, then the mutexes will fail and problems will result.
|
|
*/
|
|
{
|
|
pthread_t self = pthread_self();
|
|
if( p->nRef>0 && pthread_equal(p->owner, self) ){
|
|
p->nRef++;
|
|
rc = SQLITE_OK;
|
|
}else if( pthread_mutex_trylock(&p->mutex)==0 ){
|
|
assert( p->nRef==0 );
|
|
p->owner = self;
|
|
p->nRef = 1;
|
|
rc = SQLITE_OK;
|
|
}else{
|
|
rc = SQLITE_BUSY;
|
|
}
|
|
}
|
|
#else
|
|
/* Use the built-in recursive mutexes if they are available.
|
|
*/
|
|
if( pthread_mutex_trylock(&p->mutex)==0 ){
|
|
#if SQLITE_MUTEX_NREF
|
|
p->owner = pthread_self();
|
|
p->nRef++;
|
|
#endif
|
|
rc = SQLITE_OK;
|
|
}else{
|
|
rc = SQLITE_BUSY;
|
|
}
|
|
#endif
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
if( rc==SQLITE_OK && p->trace ){
|
|
printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
|
|
}
|
|
#endif
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** The sqlite3_mutex_leave() routine exits a mutex that was
|
|
** previously entered by the same thread. The behavior
|
|
** is undefined if the mutex is not currently entered or
|
|
** is not currently allocated. SQLite will never do either.
|
|
*/
|
|
static void pthreadMutexLeave(sqlite3_mutex *p){
|
|
assert( pthreadMutexHeld(p) );
|
|
#if SQLITE_MUTEX_NREF
|
|
p->nRef--;
|
|
if( p->nRef==0 ) p->owner = 0;
|
|
#endif
|
|
assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
|
|
|
|
#ifdef SQLITE_HOMEGROWN_RECURSIVE_MUTEX
|
|
if( p->nRef==0 ){
|
|
pthread_mutex_unlock(&p->mutex);
|
|
}
|
|
#else
|
|
pthread_mutex_unlock(&p->mutex);
|
|
#endif
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
if( p->trace ){
|
|
printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
|
|
static const sqlite3_mutex_methods sMutex = {
|
|
pthreadMutexInit,
|
|
pthreadMutexEnd,
|
|
pthreadMutexAlloc,
|
|
pthreadMutexFree,
|
|
pthreadMutexEnter,
|
|
pthreadMutexTry,
|
|
pthreadMutexLeave,
|
|
#ifdef SQLITE_DEBUG
|
|
pthreadMutexHeld,
|
|
pthreadMutexNotheld
|
|
#else
|
|
0,
|
|
0
|
|
#endif
|
|
};
|
|
|
|
return &sMutex;
|
|
}
|
|
|
|
#endif /* SQLITE_MUTEX_PTHREADS */
|
|
|
|
/************** End of mutex_unix.c ******************************************/
|
|
/************** Begin file mutex_w32.c ***************************************/
|
|
/*
|
|
** 2007 August 14
|
|
**
|
|
** 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 mutexes for Win32.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
|
|
#if SQLITE_OS_WIN
|
|
/*
|
|
** Include code that is common to all os_*.c files
|
|
*/
|
|
/* #include "os_common.h" */
|
|
|
|
/*
|
|
** Include the header file for the Windows VFS.
|
|
*/
|
|
/************** Include os_win.h in the middle of mutex_w32.c ****************/
|
|
/************** Begin file os_win.h ******************************************/
|
|
/*
|
|
** 2013 November 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 code that is specific to Windows.
|
|
*/
|
|
#ifndef SQLITE_OS_WIN_H
|
|
#define SQLITE_OS_WIN_H
|
|
|
|
/*
|
|
** Include the primary Windows SDK header file.
|
|
*/
|
|
#include "windows.h"
|
|
|
|
#ifdef __CYGWIN__
|
|
# include <sys/cygwin.h>
|
|
# include <errno.h> /* amalgamator: dontcache */
|
|
#endif
|
|
|
|
/*
|
|
** Determine if we are dealing with Windows NT.
|
|
**
|
|
** We ought to be able to determine if we are compiling for Windows 9x or
|
|
** Windows NT using the _WIN32_WINNT macro as follows:
|
|
**
|
|
** #if defined(_WIN32_WINNT)
|
|
** # define SQLITE_OS_WINNT 1
|
|
** #else
|
|
** # define SQLITE_OS_WINNT 0
|
|
** #endif
|
|
**
|
|
** However, Visual Studio 2005 does not set _WIN32_WINNT by default, as
|
|
** it ought to, so the above test does not work. We'll just assume that
|
|
** everything is Windows NT unless the programmer explicitly says otherwise
|
|
** by setting SQLITE_OS_WINNT to 0.
|
|
*/
|
|
#if SQLITE_OS_WIN && !defined(SQLITE_OS_WINNT)
|
|
# define SQLITE_OS_WINNT 1
|
|
#endif
|
|
|
|
/*
|
|
** Determine if we are dealing with Windows CE - which has a much reduced
|
|
** API.
|
|
*/
|
|
#if defined(_WIN32_WCE)
|
|
# define SQLITE_OS_WINCE 1
|
|
#else
|
|
# define SQLITE_OS_WINCE 0
|
|
#endif
|
|
|
|
/*
|
|
** Determine if we are dealing with WinRT, which provides only a subset of
|
|
** the full Win32 API.
|
|
*/
|
|
#if !defined(SQLITE_OS_WINRT)
|
|
# define SQLITE_OS_WINRT 0
|
|
#endif
|
|
|
|
/*
|
|
** For WinCE, some API function parameters do not appear to be declared as
|
|
** volatile.
|
|
*/
|
|
#if SQLITE_OS_WINCE
|
|
# define SQLITE_WIN32_VOLATILE
|
|
#else
|
|
# define SQLITE_WIN32_VOLATILE volatile
|
|
#endif
|
|
|
|
/*
|
|
** For some Windows sub-platforms, the _beginthreadex() / _endthreadex()
|
|
** functions are not available (e.g. those not using MSVC, Cygwin, etc).
|
|
*/
|
|
#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \
|
|
SQLITE_THREADSAFE>0 && !defined(__CYGWIN__)
|
|
# define SQLITE_OS_WIN_THREADS 1
|
|
#else
|
|
# define SQLITE_OS_WIN_THREADS 0
|
|
#endif
|
|
|
|
#endif /* SQLITE_OS_WIN_H */
|
|
|
|
/************** End of os_win.h **********************************************/
|
|
/************** Continuing where we left off in mutex_w32.c ******************/
|
|
#endif
|
|
|
|
/*
|
|
** The code in this file is only used if we are compiling multithreaded
|
|
** on a Win32 system.
|
|
*/
|
|
#ifdef SQLITE_MUTEX_W32
|
|
|
|
/*
|
|
** Each recursive mutex is an instance of the following structure.
|
|
*/
|
|
struct sqlite3_mutex {
|
|
CRITICAL_SECTION mutex; /* Mutex controlling the lock */
|
|
int id; /* Mutex type */
|
|
#ifdef SQLITE_DEBUG
|
|
volatile int nRef; /* Number of entrances */
|
|
volatile DWORD owner; /* Thread holding this mutex */
|
|
volatile LONG trace; /* True to trace changes */
|
|
#endif
|
|
};
|
|
|
|
/*
|
|
** These are the initializer values used when declaring a "static" mutex
|
|
** on Win32. It should be noted that all mutexes require initialization
|
|
** on the Win32 platform.
|
|
*/
|
|
#define SQLITE_W32_MUTEX_INITIALIZER { 0 }
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
#define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id, \
|
|
0L, (DWORD)0, 0 }
|
|
#else
|
|
#define SQLITE3_MUTEX_INITIALIZER(id) { SQLITE_W32_MUTEX_INITIALIZER, id }
|
|
#endif
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
/*
|
|
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
|
|
** intended for use only inside assert() statements.
|
|
*/
|
|
static int winMutexHeld(sqlite3_mutex *p){
|
|
return p->nRef!=0 && p->owner==GetCurrentThreadId();
|
|
}
|
|
|
|
static int winMutexNotheld2(sqlite3_mutex *p, DWORD tid){
|
|
return p->nRef==0 || p->owner!=tid;
|
|
}
|
|
|
|
static int winMutexNotheld(sqlite3_mutex *p){
|
|
DWORD tid = GetCurrentThreadId();
|
|
return winMutexNotheld2(p, tid);
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
** Try to provide a memory barrier operation, needed for initialization
|
|
** and also for the xShmBarrier method of the VFS in cases when SQLite is
|
|
** compiled without mutexes (SQLITE_THREADSAFE=0).
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3MemoryBarrier(void){
|
|
#if defined(SQLITE_MEMORY_BARRIER)
|
|
SQLITE_MEMORY_BARRIER;
|
|
#elif defined(__GNUC__)
|
|
__sync_synchronize();
|
|
#elif MSVC_VERSION>=1400
|
|
_ReadWriteBarrier();
|
|
#elif defined(MemoryBarrier)
|
|
MemoryBarrier();
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
** Initialize and deinitialize the mutex subsystem.
|
|
*/
|
|
static sqlite3_mutex winMutex_staticMutexes[] = {
|
|
SQLITE3_MUTEX_INITIALIZER(2),
|
|
SQLITE3_MUTEX_INITIALIZER(3),
|
|
SQLITE3_MUTEX_INITIALIZER(4),
|
|
SQLITE3_MUTEX_INITIALIZER(5),
|
|
SQLITE3_MUTEX_INITIALIZER(6),
|
|
SQLITE3_MUTEX_INITIALIZER(7),
|
|
SQLITE3_MUTEX_INITIALIZER(8),
|
|
SQLITE3_MUTEX_INITIALIZER(9),
|
|
SQLITE3_MUTEX_INITIALIZER(10),
|
|
SQLITE3_MUTEX_INITIALIZER(11),
|
|
SQLITE3_MUTEX_INITIALIZER(12),
|
|
SQLITE3_MUTEX_INITIALIZER(13)
|
|
};
|
|
|
|
static int winMutex_isInit = 0;
|
|
static int winMutex_isNt = -1; /* <0 means "need to query" */
|
|
|
|
/* As the winMutexInit() and winMutexEnd() functions are called as part
|
|
** of the sqlite3_initialize() and sqlite3_shutdown() processing, the
|
|
** "interlocked" magic used here is probably not strictly necessary.
|
|
*/
|
|
static LONG SQLITE_WIN32_VOLATILE winMutex_lock = 0;
|
|
|
|
SQLITE_API int sqlite3_win32_is_nt(void); /* os_win.c */
|
|
SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */
|
|
|
|
static int winMutexInit(void){
|
|
/* The first to increment to 1 does actual initialization */
|
|
if( InterlockedCompareExchange(&winMutex_lock, 1, 0)==0 ){
|
|
int i;
|
|
for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
|
|
#if SQLITE_OS_WINRT
|
|
InitializeCriticalSectionEx(&winMutex_staticMutexes[i].mutex, 0, 0);
|
|
#else
|
|
InitializeCriticalSection(&winMutex_staticMutexes[i].mutex);
|
|
#endif
|
|
}
|
|
winMutex_isInit = 1;
|
|
}else{
|
|
/* Another thread is (in the process of) initializing the static
|
|
** mutexes */
|
|
while( !winMutex_isInit ){
|
|
sqlite3_win32_sleep(1);
|
|
}
|
|
}
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
static int winMutexEnd(void){
|
|
/* The first to decrement to 0 does actual shutdown
|
|
** (which should be the last to shutdown.) */
|
|
if( InterlockedCompareExchange(&winMutex_lock, 0, 1)==1 ){
|
|
if( winMutex_isInit==1 ){
|
|
int i;
|
|
for(i=0; i<ArraySize(winMutex_staticMutexes); i++){
|
|
DeleteCriticalSection(&winMutex_staticMutexes[i].mutex);
|
|
}
|
|
winMutex_isInit = 0;
|
|
}
|
|
}
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** The sqlite3_mutex_alloc() routine allocates a new
|
|
** mutex and returns a pointer to it. If it returns NULL
|
|
** that means that a mutex could not be allocated. SQLite
|
|
** will unwind its stack and return an error. The argument
|
|
** to sqlite3_mutex_alloc() is one of these integer constants:
|
|
**
|
|
** <ul>
|
|
** <li> SQLITE_MUTEX_FAST
|
|
** <li> SQLITE_MUTEX_RECURSIVE
|
|
** <li> SQLITE_MUTEX_STATIC_MAIN
|
|
** <li> SQLITE_MUTEX_STATIC_MEM
|
|
** <li> SQLITE_MUTEX_STATIC_OPEN
|
|
** <li> SQLITE_MUTEX_STATIC_PRNG
|
|
** <li> SQLITE_MUTEX_STATIC_LRU
|
|
** <li> SQLITE_MUTEX_STATIC_PMEM
|
|
** <li> SQLITE_MUTEX_STATIC_APP1
|
|
** <li> SQLITE_MUTEX_STATIC_APP2
|
|
** <li> SQLITE_MUTEX_STATIC_APP3
|
|
** <li> SQLITE_MUTEX_STATIC_VFS1
|
|
** <li> SQLITE_MUTEX_STATIC_VFS2
|
|
** <li> SQLITE_MUTEX_STATIC_VFS3
|
|
** </ul>
|
|
**
|
|
** The first two constants cause sqlite3_mutex_alloc() to create
|
|
** a new mutex. The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
|
|
** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
|
|
** The mutex implementation does not need to make a distinction
|
|
** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
|
|
** not want to. But SQLite will only request a recursive mutex in
|
|
** cases where it really needs one. If a faster non-recursive mutex
|
|
** implementation is available on the host platform, the mutex subsystem
|
|
** might return such a mutex in response to SQLITE_MUTEX_FAST.
|
|
**
|
|
** The other allowed parameters to sqlite3_mutex_alloc() each return
|
|
** a pointer to a static preexisting mutex. Six static mutexes are
|
|
** used by the current version of SQLite. Future versions of SQLite
|
|
** may add additional static mutexes. Static mutexes are for internal
|
|
** use by SQLite only. Applications that use SQLite mutexes should
|
|
** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
|
|
** SQLITE_MUTEX_RECURSIVE.
|
|
**
|
|
** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
|
|
** or SQLITE_MUTEX_RECURSIVE) is used then sqlite3_mutex_alloc()
|
|
** returns a different mutex on every call. But for the static
|
|
** mutex types, the same mutex is returned on every call that has
|
|
** the same type number.
|
|
*/
|
|
static sqlite3_mutex *winMutexAlloc(int iType){
|
|
sqlite3_mutex *p;
|
|
|
|
switch( iType ){
|
|
case SQLITE_MUTEX_FAST:
|
|
case SQLITE_MUTEX_RECURSIVE: {
|
|
p = sqlite3MallocZero( sizeof(*p) );
|
|
if( p ){
|
|
p->id = iType;
|
|
#ifdef SQLITE_DEBUG
|
|
#ifdef SQLITE_WIN32_MUTEX_TRACE_DYNAMIC
|
|
p->trace = 1;
|
|
#endif
|
|
#endif
|
|
#if SQLITE_OS_WINRT
|
|
InitializeCriticalSectionEx(&p->mutex, 0, 0);
|
|
#else
|
|
InitializeCriticalSection(&p->mutex);
|
|
#endif
|
|
}
|
|
break;
|
|
}
|
|
default: {
|
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
|
if( iType-2<0 || iType-2>=ArraySize(winMutex_staticMutexes) ){
|
|
(void)SQLITE_MISUSE_BKPT;
|
|
return 0;
|
|
}
|
|
#endif
|
|
p = &winMutex_staticMutexes[iType-2];
|
|
#ifdef SQLITE_DEBUG
|
|
#ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC
|
|
InterlockedCompareExchange(&p->trace, 1, 0);
|
|
#endif
|
|
#endif
|
|
break;
|
|
}
|
|
}
|
|
assert( p==0 || p->id==iType );
|
|
return p;
|
|
}
|
|
|
|
|
|
/*
|
|
** This routine deallocates a previously
|
|
** allocated mutex. SQLite is careful to deallocate every
|
|
** mutex that it allocates.
|
|
*/
|
|
static void winMutexFree(sqlite3_mutex *p){
|
|
assert( p );
|
|
assert( p->nRef==0 && p->owner==0 );
|
|
if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ){
|
|
DeleteCriticalSection(&p->mutex);
|
|
sqlite3_free(p);
|
|
}else{
|
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
|
(void)SQLITE_MISUSE_BKPT;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/*
|
|
** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
|
|
** to enter a mutex. If another thread is already within the mutex,
|
|
** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
|
|
** SQLITE_BUSY. The sqlite3_mutex_try() interface returns SQLITE_OK
|
|
** upon successful entry. Mutexes created using SQLITE_MUTEX_RECURSIVE can
|
|
** be entered multiple times by the same thread. In such cases the,
|
|
** mutex must be exited an equal number of times before another thread
|
|
** can enter. If the same thread tries to enter any other kind of mutex
|
|
** more than once, the behavior is undefined.
|
|
*/
|
|
static void winMutexEnter(sqlite3_mutex *p){
|
|
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
|
DWORD tid = GetCurrentThreadId();
|
|
#endif
|
|
#ifdef SQLITE_DEBUG
|
|
assert( p );
|
|
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
|
|
#else
|
|
assert( p );
|
|
#endif
|
|
assert( winMutex_isInit==1 );
|
|
EnterCriticalSection(&p->mutex);
|
|
#ifdef SQLITE_DEBUG
|
|
assert( p->nRef>0 || p->owner==0 );
|
|
p->owner = tid;
|
|
p->nRef++;
|
|
if( p->trace ){
|
|
OSTRACE(("ENTER-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n",
|
|
tid, p->id, p, p->trace, p->nRef));
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static int winMutexTry(sqlite3_mutex *p){
|
|
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
|
DWORD tid = GetCurrentThreadId();
|
|
#endif
|
|
int rc = SQLITE_BUSY;
|
|
assert( p );
|
|
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld2(p, tid) );
|
|
/*
|
|
** The sqlite3_mutex_try() routine is very rarely used, and when it
|
|
** is used it is merely an optimization. So it is OK for it to always
|
|
** fail.
|
|
**
|
|
** The TryEnterCriticalSection() interface is only available on WinNT.
|
|
** And some windows compilers complain if you try to use it without
|
|
** first doing some #defines that prevent SQLite from building on Win98.
|
|
** For that reason, we will omit this optimization for now. See
|
|
** ticket #2685.
|
|
*/
|
|
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0400
|
|
assert( winMutex_isInit==1 );
|
|
assert( winMutex_isNt>=-1 && winMutex_isNt<=1 );
|
|
if( winMutex_isNt<0 ){
|
|
winMutex_isNt = sqlite3_win32_is_nt();
|
|
}
|
|
assert( winMutex_isNt==0 || winMutex_isNt==1 );
|
|
if( winMutex_isNt && TryEnterCriticalSection(&p->mutex) ){
|
|
#ifdef SQLITE_DEBUG
|
|
p->owner = tid;
|
|
p->nRef++;
|
|
#endif
|
|
rc = SQLITE_OK;
|
|
}
|
|
#else
|
|
UNUSED_PARAMETER(p);
|
|
#endif
|
|
#ifdef SQLITE_DEBUG
|
|
if( p->trace ){
|
|
OSTRACE(("TRY-MUTEX tid=%lu, mutex(%d)=%p (%d), owner=%lu, nRef=%d, rc=%s\n",
|
|
tid, p->id, p, p->trace, p->owner, p->nRef, sqlite3ErrName(rc)));
|
|
}
|
|
#endif
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** The sqlite3_mutex_leave() routine exits a mutex that was
|
|
** previously entered by the same thread. The behavior
|
|
** is undefined if the mutex is not currently entered or
|
|
** is not currently allocated. SQLite will never do either.
|
|
*/
|
|
static void winMutexLeave(sqlite3_mutex *p){
|
|
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
|
DWORD tid = GetCurrentThreadId();
|
|
#endif
|
|
assert( p );
|
|
#ifdef SQLITE_DEBUG
|
|
assert( p->nRef>0 );
|
|
assert( p->owner==tid );
|
|
p->nRef--;
|
|
if( p->nRef==0 ) p->owner = 0;
|
|
assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
|
|
#endif
|
|
assert( winMutex_isInit==1 );
|
|
LeaveCriticalSection(&p->mutex);
|
|
#ifdef SQLITE_DEBUG
|
|
if( p->trace ){
|
|
OSTRACE(("LEAVE-MUTEX tid=%lu, mutex(%d)=%p (%d), nRef=%d\n",
|
|
tid, p->id, p, p->trace, p->nRef));
|
|
}
|
|
#endif
|
|
}
|
|
|
|
SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
|
|
static const sqlite3_mutex_methods sMutex = {
|
|
winMutexInit,
|
|
winMutexEnd,
|
|
winMutexAlloc,
|
|
winMutexFree,
|
|
winMutexEnter,
|
|
winMutexTry,
|
|
winMutexLeave,
|
|
#ifdef SQLITE_DEBUG
|
|
winMutexHeld,
|
|
winMutexNotheld
|
|
#else
|
|
0,
|
|
0
|
|
#endif
|
|
};
|
|
return &sMutex;
|
|
}
|
|
|
|
#endif /* SQLITE_MUTEX_W32 */
|
|
|
|
/************** End of mutex_w32.c *******************************************/
|
|
/************** Begin file malloc.c ******************************************/
|
|
/*
|
|
** 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.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
/* #include <stdarg.h> */
|
|
|
|
/*
|
|
** Attempt to release up to n bytes of non-essential memory currently
|
|
** held by SQLite. An example of non-essential memory is memory used to
|
|
** cache database pages that are not currently in use.
|
|
*/
|
|
SQLITE_API int sqlite3_release_memory(int n){
|
|
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
|
return sqlite3PcacheReleaseMemory(n);
|
|
#else
|
|
/* IMPLEMENTATION-OF: R-34391-24921 The sqlite3_release_memory() routine
|
|
** is a no-op returning zero if SQLite is not compiled with
|
|
** SQLITE_ENABLE_MEMORY_MANAGEMENT. */
|
|
UNUSED_PARAMETER(n);
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
** Default value of the hard heap limit. 0 means "no limit".
|
|
*/
|
|
#ifndef SQLITE_MAX_MEMORY
|
|
# define SQLITE_MAX_MEMORY 0
|
|
#endif
|
|
|
|
/*
|
|
** State information local to the memory allocation subsystem.
|
|
*/
|
|
static SQLITE_WSD struct Mem0Global {
|
|
sqlite3_mutex *mutex; /* Mutex to serialize access */
|
|
sqlite3_int64 alarmThreshold; /* The soft heap limit */
|
|
sqlite3_int64 hardLimit; /* The hard upper bound on memory */
|
|
|
|
/*
|
|
** True if heap is nearly "full" where "full" is defined by the
|
|
** sqlite3_soft_heap_limit() setting.
|
|
*/
|
|
int nearlyFull;
|
|
} mem0 = { 0, SQLITE_MAX_MEMORY, SQLITE_MAX_MEMORY, 0 };
|
|
|
|
#define mem0 GLOBAL(struct Mem0Global, mem0)
|
|
|
|
/*
|
|
** Return the memory allocator mutex. sqlite3_status() needs it.
|
|
*/
|
|
SQLITE_PRIVATE sqlite3_mutex *sqlite3MallocMutex(void){
|
|
return mem0.mutex;
|
|
}
|
|
|
|
#ifndef SQLITE_OMIT_DEPRECATED
|
|
/*
|
|
** Deprecated external interface. It used to set an alarm callback
|
|
** that was invoked when memory usage grew too large. Now it is a
|
|
** no-op.
|
|
*/
|
|
SQLITE_API int sqlite3_memory_alarm(
|
|
void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
|
|
void *pArg,
|
|
sqlite3_int64 iThreshold
|
|
){
|
|
(void)xCallback;
|
|
(void)pArg;
|
|
(void)iThreshold;
|
|
return SQLITE_OK;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
** Set the soft heap-size limit for the library. An argument of
|
|
** zero disables the limit. A negative argument is a no-op used to
|
|
** obtain the return value.
|
|
**
|
|
** The return value is the value of the heap limit just before this
|
|
** interface was called.
|
|
**
|
|
** If the hard heap limit is enabled, then the soft heap limit cannot
|
|
** be disabled nor raised above the hard heap limit.
|
|
*/
|
|
SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){
|
|
sqlite3_int64 priorLimit;
|
|
sqlite3_int64 excess;
|
|
sqlite3_int64 nUsed;
|
|
#ifndef SQLITE_OMIT_AUTOINIT
|
|
int rc = sqlite3_initialize();
|
|
if( rc ) return -1;
|
|
#endif
|
|
sqlite3_mutex_enter(mem0.mutex);
|
|
priorLimit = mem0.alarmThreshold;
|
|
if( n<0 ){
|
|
sqlite3_mutex_leave(mem0.mutex);
|
|
return priorLimit;
|
|
}
|
|
if( mem0.hardLimit>0 && (n>mem0.hardLimit || n==0) ){
|
|
n = mem0.hardLimit;
|
|
}
|
|
mem0.alarmThreshold = n;
|
|
nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
|
|
AtomicStore(&mem0.nearlyFull, n>0 && n<=nUsed);
|
|
sqlite3_mutex_leave(mem0.mutex);
|
|
excess = sqlite3_memory_used() - n;
|
|
if( excess>0 ) sqlite3_release_memory((int)(excess & 0x7fffffff));
|
|
return priorLimit;
|
|
}
|
|
SQLITE_API void sqlite3_soft_heap_limit(int n){
|
|
if( n<0 ) n = 0;
|
|
sqlite3_soft_heap_limit64(n);
|
|
}
|
|
|
|
/*
|
|
** Set the hard heap-size limit for the library. An argument of zero
|
|
** disables the hard heap limit. A negative argument is a no-op used
|
|
** to obtain the return value without affecting the hard heap limit.
|
|
**
|
|
** The return value is the value of the hard heap limit just prior to
|
|
** calling this interface.
|
|
**
|
|
** Setting the hard heap limit will also activate the soft heap limit
|
|
** and constrain the soft heap limit to be no more than the hard heap
|
|
** limit.
|
|
*/
|
|
SQLITE_API sqlite3_int64 sqlite3_hard_heap_limit64(sqlite3_int64 n){
|
|
sqlite3_int64 priorLimit;
|
|
#ifndef SQLITE_OMIT_AUTOINIT
|
|
int rc = sqlite3_initialize();
|
|
if( rc ) return -1;
|
|
#endif
|
|
sqlite3_mutex_enter(mem0.mutex);
|
|
priorLimit = mem0.hardLimit;
|
|
if( n>=0 ){
|
|
mem0.hardLimit = n;
|
|
if( n<mem0.alarmThreshold || mem0.alarmThreshold==0 ){
|
|
mem0.alarmThreshold = n;
|
|
}
|
|
}
|
|
sqlite3_mutex_leave(mem0.mutex);
|
|
return priorLimit;
|
|
}
|
|
|
|
|
|
/*
|
|
** Initialize the memory allocation subsystem.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3MallocInit(void){
|
|
int rc;
|
|
if( sqlite3GlobalConfig.m.xMalloc==0 ){
|
|
sqlite3MemSetDefault();
|
|
}
|
|
mem0.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM);
|
|
if( sqlite3GlobalConfig.pPage==0 || sqlite3GlobalConfig.szPage<512
|
|
|| sqlite3GlobalConfig.nPage<=0 ){
|
|
sqlite3GlobalConfig.pPage = 0;
|
|
sqlite3GlobalConfig.szPage = 0;
|
|
}
|
|
rc = sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData);
|
|
if( rc!=SQLITE_OK ) memset(&mem0, 0, sizeof(mem0));
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Return true if the heap is currently under memory pressure - in other
|
|
** words if the amount of heap used is close to the limit set by
|
|
** sqlite3_soft_heap_limit().
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3HeapNearlyFull(void){
|
|
return AtomicLoad(&mem0.nearlyFull);
|
|
}
|
|
|
|
/*
|
|
** Deinitialize the memory allocation subsystem.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3MallocEnd(void){
|
|
if( sqlite3GlobalConfig.m.xShutdown ){
|
|
sqlite3GlobalConfig.m.xShutdown(sqlite3GlobalConfig.m.pAppData);
|
|
}
|
|
memset(&mem0, 0, sizeof(mem0));
|
|
}
|
|
|
|
/*
|
|
** Return the amount of memory currently checked out.
|
|
*/
|
|
SQLITE_API sqlite3_int64 sqlite3_memory_used(void){
|
|
sqlite3_int64 res, mx;
|
|
sqlite3_status64(SQLITE_STATUS_MEMORY_USED, &res, &mx, 0);
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
** Return the maximum amount of memory that has ever been
|
|
** checked out since either the beginning of this process
|
|
** or since the most recent reset.
|
|
*/
|
|
SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag){
|
|
sqlite3_int64 res, mx;
|
|
sqlite3_status64(SQLITE_STATUS_MEMORY_USED, &res, &mx, resetFlag);
|
|
return mx;
|
|
}
|
|
|
|
/*
|
|
** Trigger the alarm
|
|
*/
|
|
static void sqlite3MallocAlarm(int nByte){
|
|
if( mem0.alarmThreshold<=0 ) return;
|
|
sqlite3_mutex_leave(mem0.mutex);
|
|
sqlite3_release_memory(nByte);
|
|
sqlite3_mutex_enter(mem0.mutex);
|
|
}
|
|
|
|
/*
|
|
** Do a memory allocation with statistics and alarms. Assume the
|
|
** lock is already held.
|
|
*/
|
|
static void mallocWithAlarm(int n, void **pp){
|
|
void *p;
|
|
int nFull;
|
|
assert( sqlite3_mutex_held(mem0.mutex) );
|
|
assert( n>0 );
|
|
|
|
/* In Firefox (circa 2017-02-08), xRoundup() is remapped to an internal
|
|
** implementation of malloc_good_size(), which must be called in debug
|
|
** mode and specifically when the DMD "Dark Matter Detector" is enabled
|
|
** or else a crash results. Hence, do not attempt to optimize out the
|
|
** following xRoundup() call. */
|
|
nFull = sqlite3GlobalConfig.m.xRoundup(n);
|
|
|
|
sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, n);
|
|
if( mem0.alarmThreshold>0 ){
|
|
sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
|
|
if( nUsed >= mem0.alarmThreshold - nFull ){
|
|
AtomicStore(&mem0.nearlyFull, 1);
|
|
sqlite3MallocAlarm(nFull);
|
|
if( mem0.hardLimit ){
|
|
nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
|
|
if( nUsed >= mem0.hardLimit - nFull ){
|
|
*pp = 0;
|
|
return;
|
|
}
|
|
}
|
|
}else{
|
|
AtomicStore(&mem0.nearlyFull, 0);
|
|
}
|
|
}
|
|
p = sqlite3GlobalConfig.m.xMalloc(nFull);
|
|
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
|
if( p==0 && mem0.alarmThreshold>0 ){
|
|
sqlite3MallocAlarm(nFull);
|
|
p = sqlite3GlobalConfig.m.xMalloc(nFull);
|
|
}
|
|
#endif
|
|
if( p ){
|
|
nFull = sqlite3MallocSize(p);
|
|
sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nFull);
|
|
sqlite3StatusUp(SQLITE_STATUS_MALLOC_COUNT, 1);
|
|
}
|
|
*pp = p;
|
|
}
|
|
|
|
/*
|
|
** Maximum size of any single memory allocation.
|
|
**
|
|
** This is not a limit on the total amount of memory used. This is
|
|
** a limit on the size parameter to sqlite3_malloc() and sqlite3_realloc().
|
|
**
|
|
** The upper bound is slightly less than 2GiB: 0x7ffffeff == 2,147,483,391
|
|
** This provides a 256-byte safety margin for defense against 32-bit
|
|
** signed integer overflow bugs when computing memory allocation sizes.
|
|
** Paranoid applications might want to reduce the maximum allocation size
|
|
** further for an even larger safety margin. 0x3fffffff or 0x0fffffff
|
|
** or even smaller would be reasonable upper bounds on the size of a memory
|
|
** allocations for most applications.
|
|
*/
|
|
#ifndef SQLITE_MAX_ALLOCATION_SIZE
|
|
# define SQLITE_MAX_ALLOCATION_SIZE 2147483391
|
|
#endif
|
|
#if SQLITE_MAX_ALLOCATION_SIZE>2147483391
|
|
# error Maximum size for SQLITE_MAX_ALLOCATION_SIZE is 2147483391
|
|
#endif
|
|
|
|
/*
|
|
** Allocate memory. This routine is like sqlite3_malloc() except that it
|
|
** assumes the memory subsystem has already been initialized.
|
|
*/
|
|
SQLITE_PRIVATE void *sqlite3Malloc(u64 n){
|
|
void *p;
|
|
if( n==0 || n>SQLITE_MAX_ALLOCATION_SIZE ){
|
|
p = 0;
|
|
}else if( sqlite3GlobalConfig.bMemstat ){
|
|
sqlite3_mutex_enter(mem0.mutex);
|
|
mallocWithAlarm((int)n, &p);
|
|
sqlite3_mutex_leave(mem0.mutex);
|
|
}else{
|
|
p = sqlite3GlobalConfig.m.xMalloc((int)n);
|
|
}
|
|
assert( EIGHT_BYTE_ALIGNMENT(p) ); /* IMP: R-11148-40995 */
|
|
return p;
|
|
}
|
|
|
|
/*
|
|
** This version of the memory allocation is for use by the application.
|
|
** First make sure the memory subsystem is initialized, then do the
|
|
** allocation.
|
|
*/
|
|
SQLITE_API void *sqlite3_malloc(int n){
|
|
#ifndef SQLITE_OMIT_AUTOINIT
|
|
if( sqlite3_initialize() ) return 0;
|
|
#endif
|
|
return n<=0 ? 0 : sqlite3Malloc(n);
|
|
}
|
|
SQLITE_API void *sqlite3_malloc64(sqlite3_uint64 n){
|
|
#ifndef SQLITE_OMIT_AUTOINIT
|
|
if( sqlite3_initialize() ) return 0;
|
|
#endif
|
|
return sqlite3Malloc(n);
|
|
}
|
|
|
|
/*
|
|
** TRUE if p is a lookaside memory allocation from db
|
|
*/
|
|
#ifndef SQLITE_OMIT_LOOKASIDE
|
|
static int isLookaside(sqlite3 *db, const void *p){
|
|
return SQLITE_WITHIN(p, db->lookaside.pStart, db->lookaside.pTrueEnd);
|
|
}
|
|
#else
|
|
#define isLookaside(A,B) 0
|
|
#endif
|
|
|
|
/*
|
|
** Return the size of a memory allocation previously obtained from
|
|
** sqlite3Malloc() or sqlite3_malloc().
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3MallocSize(const void *p){
|
|
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
|
|
return sqlite3GlobalConfig.m.xSize((void*)p);
|
|
}
|
|
static int lookasideMallocSize(sqlite3 *db, const void *p){
|
|
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
|
return p<db->lookaside.pMiddle ? db->lookaside.szTrue : LOOKASIDE_SMALL;
|
|
#else
|
|
return db->lookaside.szTrue;
|
|
#endif
|
|
}
|
|
SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, const void *p){
|
|
assert( p!=0 );
|
|
#ifdef SQLITE_DEBUG
|
|
if( db==0 ){
|
|
assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
|
|
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
|
|
}else if( !isLookaside(db,p) ){
|
|
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
|
assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
|
}
|
|
#endif
|
|
if( db ){
|
|
if( ((uptr)p)<(uptr)(db->lookaside.pTrueEnd) ){
|
|
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
|
if( ((uptr)p)>=(uptr)(db->lookaside.pMiddle) ){
|
|
assert( sqlite3_mutex_held(db->mutex) );
|
|
return LOOKASIDE_SMALL;
|
|
}
|
|
#endif
|
|
if( ((uptr)p)>=(uptr)(db->lookaside.pStart) ){
|
|
assert( sqlite3_mutex_held(db->mutex) );
|
|
return db->lookaside.szTrue;
|
|
}
|
|
}
|
|
}
|
|
return sqlite3GlobalConfig.m.xSize((void*)p);
|
|
}
|
|
SQLITE_API sqlite3_uint64 sqlite3_msize(void *p){
|
|
assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
|
|
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
|
|
return p ? sqlite3GlobalConfig.m.xSize(p) : 0;
|
|
}
|
|
|
|
/*
|
|
** Free memory previously obtained from sqlite3Malloc().
|
|
*/
|
|
SQLITE_API void sqlite3_free(void *p){
|
|
if( p==0 ) return; /* IMP: R-49053-54554 */
|
|
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
|
|
assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
|
|
if( sqlite3GlobalConfig.bMemstat ){
|
|
sqlite3_mutex_enter(mem0.mutex);
|
|
sqlite3StatusDown(SQLITE_STATUS_MEMORY_USED, sqlite3MallocSize(p));
|
|
sqlite3StatusDown(SQLITE_STATUS_MALLOC_COUNT, 1);
|
|
sqlite3GlobalConfig.m.xFree(p);
|
|
sqlite3_mutex_leave(mem0.mutex);
|
|
}else{
|
|
sqlite3GlobalConfig.m.xFree(p);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Add the size of memory allocation "p" to the count in
|
|
** *db->pnBytesFreed.
|
|
*/
|
|
static SQLITE_NOINLINE void measureAllocationSize(sqlite3 *db, void *p){
|
|
*db->pnBytesFreed += sqlite3DbMallocSize(db,p);
|
|
}
|
|
|
|
/*
|
|
** Free memory that might be associated with a particular database
|
|
** connection. Calling sqlite3DbFree(D,X) for X==0 is a harmless no-op.
|
|
** The sqlite3DbFreeNN(D,X) version requires that X be non-NULL.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3DbFreeNN(sqlite3 *db, void *p){
|
|
assert( db==0 || sqlite3_mutex_held(db->mutex) );
|
|
assert( p!=0 );
|
|
if( db ){
|
|
if( ((uptr)p)<(uptr)(db->lookaside.pEnd) ){
|
|
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
|
if( ((uptr)p)>=(uptr)(db->lookaside.pMiddle) ){
|
|
LookasideSlot *pBuf = (LookasideSlot*)p;
|
|
assert( db->pnBytesFreed==0 );
|
|
#ifdef SQLITE_DEBUG
|
|
memset(p, 0xaa, LOOKASIDE_SMALL); /* Trash freed content */
|
|
#endif
|
|
pBuf->pNext = db->lookaside.pSmallFree;
|
|
db->lookaside.pSmallFree = pBuf;
|
|
return;
|
|
}
|
|
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
|
|
if( ((uptr)p)>=(uptr)(db->lookaside.pStart) ){
|
|
LookasideSlot *pBuf = (LookasideSlot*)p;
|
|
assert( db->pnBytesFreed==0 );
|
|
#ifdef SQLITE_DEBUG
|
|
memset(p, 0xaa, db->lookaside.szTrue); /* Trash freed content */
|
|
#endif
|
|
pBuf->pNext = db->lookaside.pFree;
|
|
db->lookaside.pFree = pBuf;
|
|
return;
|
|
}
|
|
}
|
|
if( db->pnBytesFreed ){
|
|
measureAllocationSize(db, p);
|
|
return;
|
|
}
|
|
}
|
|
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
|
assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
|
assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
|
|
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
|
|
sqlite3_free(p);
|
|
}
|
|
SQLITE_PRIVATE void sqlite3DbNNFreeNN(sqlite3 *db, void *p){
|
|
assert( db!=0 );
|
|
assert( sqlite3_mutex_held(db->mutex) );
|
|
assert( p!=0 );
|
|
if( ((uptr)p)<(uptr)(db->lookaside.pEnd) ){
|
|
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
|
if( ((uptr)p)>=(uptr)(db->lookaside.pMiddle) ){
|
|
LookasideSlot *pBuf = (LookasideSlot*)p;
|
|
assert( db->pnBytesFreed==0 );
|
|
#ifdef SQLITE_DEBUG
|
|
memset(p, 0xaa, LOOKASIDE_SMALL); /* Trash freed content */
|
|
#endif
|
|
pBuf->pNext = db->lookaside.pSmallFree;
|
|
db->lookaside.pSmallFree = pBuf;
|
|
return;
|
|
}
|
|
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
|
|
if( ((uptr)p)>=(uptr)(db->lookaside.pStart) ){
|
|
LookasideSlot *pBuf = (LookasideSlot*)p;
|
|
assert( db->pnBytesFreed==0 );
|
|
#ifdef SQLITE_DEBUG
|
|
memset(p, 0xaa, db->lookaside.szTrue); /* Trash freed content */
|
|
#endif
|
|
pBuf->pNext = db->lookaside.pFree;
|
|
db->lookaside.pFree = pBuf;
|
|
return;
|
|
}
|
|
}
|
|
if( db->pnBytesFreed ){
|
|
measureAllocationSize(db, p);
|
|
return;
|
|
}
|
|
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
|
assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
|
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
|
|
sqlite3_free(p);
|
|
}
|
|
SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){
|
|
assert( db==0 || sqlite3_mutex_held(db->mutex) );
|
|
if( p ) sqlite3DbFreeNN(db, p);
|
|
}
|
|
|
|
/*
|
|
** Change the size of an existing memory allocation
|
|
*/
|
|
SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, u64 nBytes){
|
|
int nOld, nNew, nDiff;
|
|
void *pNew;
|
|
assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) );
|
|
assert( sqlite3MemdebugNoType(pOld, (u8)~MEMTYPE_HEAP) );
|
|
if( pOld==0 ){
|
|
return sqlite3Malloc(nBytes); /* IMP: R-04300-56712 */
|
|
}
|
|
if( nBytes==0 ){
|
|
sqlite3_free(pOld); /* IMP: R-26507-47431 */
|
|
return 0;
|
|
}
|
|
if( nBytes>=0x7fffff00 ){
|
|
/* The 0x7ffff00 limit term is explained in comments on sqlite3Malloc() */
|
|
return 0;
|
|
}
|
|
nOld = sqlite3MallocSize(pOld);
|
|
/* IMPLEMENTATION-OF: R-46199-30249 SQLite guarantees that the second
|
|
** argument to xRealloc is always a value returned by a prior call to
|
|
** xRoundup. */
|
|
nNew = sqlite3GlobalConfig.m.xRoundup((int)nBytes);
|
|
if( nOld==nNew ){
|
|
pNew = pOld;
|
|
}else if( sqlite3GlobalConfig.bMemstat ){
|
|
sqlite3_int64 nUsed;
|
|
sqlite3_mutex_enter(mem0.mutex);
|
|
sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, (int)nBytes);
|
|
nDiff = nNew - nOld;
|
|
if( nDiff>0 && (nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)) >=
|
|
mem0.alarmThreshold-nDiff ){
|
|
sqlite3MallocAlarm(nDiff);
|
|
if( mem0.hardLimit>0 && nUsed >= mem0.hardLimit - nDiff ){
|
|
sqlite3_mutex_leave(mem0.mutex);
|
|
return 0;
|
|
}
|
|
}
|
|
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
|
|
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
|
if( pNew==0 && mem0.alarmThreshold>0 ){
|
|
sqlite3MallocAlarm((int)nBytes);
|
|
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
|
|
}
|
|
#endif
|
|
if( pNew ){
|
|
nNew = sqlite3MallocSize(pNew);
|
|
sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
|
|
}
|
|
sqlite3_mutex_leave(mem0.mutex);
|
|
}else{
|
|
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
|
|
}
|
|
assert( EIGHT_BYTE_ALIGNMENT(pNew) ); /* IMP: R-11148-40995 */
|
|
return pNew;
|
|
}
|
|
|
|
/*
|
|
** The public interface to sqlite3Realloc. Make sure that the memory
|
|
** subsystem is initialized prior to invoking sqliteRealloc.
|
|
*/
|
|
SQLITE_API void *sqlite3_realloc(void *pOld, int n){
|
|
#ifndef SQLITE_OMIT_AUTOINIT
|
|
if( sqlite3_initialize() ) return 0;
|
|
#endif
|
|
if( n<0 ) n = 0; /* IMP: R-26507-47431 */
|
|
return sqlite3Realloc(pOld, n);
|
|
}
|
|
SQLITE_API void *sqlite3_realloc64(void *pOld, sqlite3_uint64 n){
|
|
#ifndef SQLITE_OMIT_AUTOINIT
|
|
if( sqlite3_initialize() ) return 0;
|
|
#endif
|
|
return sqlite3Realloc(pOld, n);
|
|
}
|
|
|
|
|
|
/*
|
|
** Allocate and zero memory.
|
|
*/
|
|
SQLITE_PRIVATE void *sqlite3MallocZero(u64 n){
|
|
void *p = sqlite3Malloc(n);
|
|
if( p ){
|
|
memset(p, 0, (size_t)n);
|
|
}
|
|
return p;
|
|
}
|
|
|
|
/*
|
|
** Allocate and zero memory. If the allocation fails, make
|
|
** the mallocFailed flag in the connection pointer.
|
|
*/
|
|
SQLITE_PRIVATE void *sqlite3DbMallocZero(sqlite3 *db, u64 n){
|
|
void *p;
|
|
testcase( db==0 );
|
|
p = sqlite3DbMallocRaw(db, n);
|
|
if( p ) memset(p, 0, (size_t)n);
|
|
return p;
|
|
}
|
|
|
|
|
|
/* Finish the work of sqlite3DbMallocRawNN for the unusual and
|
|
** slower case when the allocation cannot be fulfilled using lookaside.
|
|
*/
|
|
static SQLITE_NOINLINE void *dbMallocRawFinish(sqlite3 *db, u64 n){
|
|
void *p;
|
|
assert( db!=0 );
|
|
p = sqlite3Malloc(n);
|
|
if( !p ) sqlite3OomFault(db);
|
|
sqlite3MemdebugSetType(p,
|
|
(db->lookaside.bDisable==0) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP);
|
|
return p;
|
|
}
|
|
|
|
/*
|
|
** Allocate memory, either lookaside (if possible) or heap.
|
|
** If the allocation fails, set the mallocFailed flag in
|
|
** the connection pointer.
|
|
**
|
|
** If db!=0 and db->mallocFailed is true (indicating a prior malloc
|
|
** failure on the same database connection) then always return 0.
|
|
** Hence for a particular database connection, once malloc starts
|
|
** failing, it fails consistently until mallocFailed is reset.
|
|
** This is an important assumption. There are many places in the
|
|
** code that do things like this:
|
|
**
|
|
** int *a = (int*)sqlite3DbMallocRaw(db, 100);
|
|
** int *b = (int*)sqlite3DbMallocRaw(db, 200);
|
|
** if( b ) a[10] = 9;
|
|
**
|
|
** In other words, if a subsequent malloc (ex: "b") worked, it is assumed
|
|
** that all prior mallocs (ex: "a") worked too.
|
|
**
|
|
** The sqlite3MallocRawNN() variant guarantees that the "db" parameter is
|
|
** not a NULL pointer.
|
|
*/
|
|
SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3 *db, u64 n){
|
|
void *p;
|
|
if( db ) return sqlite3DbMallocRawNN(db, n);
|
|
p = sqlite3Malloc(n);
|
|
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
|
|
return p;
|
|
}
|
|
SQLITE_PRIVATE void *sqlite3DbMallocRawNN(sqlite3 *db, u64 n){
|
|
#ifndef SQLITE_OMIT_LOOKASIDE
|
|
LookasideSlot *pBuf;
|
|
assert( db!=0 );
|
|
assert( sqlite3_mutex_held(db->mutex) );
|
|
assert( db->pnBytesFreed==0 );
|
|
if( n>db->lookaside.sz ){
|
|
if( !db->lookaside.bDisable ){
|
|
db->lookaside.anStat[1]++;
|
|
}else if( db->mallocFailed ){
|
|
return 0;
|
|
}
|
|
return dbMallocRawFinish(db, n);
|
|
}
|
|
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
|
if( n<=LOOKASIDE_SMALL ){
|
|
if( (pBuf = db->lookaside.pSmallFree)!=0 ){
|
|
db->lookaside.pSmallFree = pBuf->pNext;
|
|
db->lookaside.anStat[0]++;
|
|
return (void*)pBuf;
|
|
}else if( (pBuf = db->lookaside.pSmallInit)!=0 ){
|
|
db->lookaside.pSmallInit = pBuf->pNext;
|
|
db->lookaside.anStat[0]++;
|
|
return (void*)pBuf;
|
|
}
|
|
}
|
|
#endif
|
|
if( (pBuf = db->lookaside.pFree)!=0 ){
|
|
db->lookaside.pFree = pBuf->pNext;
|
|
db->lookaside.anStat[0]++;
|
|
return (void*)pBuf;
|
|
}else if( (pBuf = db->lookaside.pInit)!=0 ){
|
|
db->lookaside.pInit = pBuf->pNext;
|
|
db->lookaside.anStat[0]++;
|
|
return (void*)pBuf;
|
|
}else{
|
|
db->lookaside.anStat[2]++;
|
|
}
|
|
#else
|
|
assert( db!=0 );
|
|
assert( sqlite3_mutex_held(db->mutex) );
|
|
assert( db->pnBytesFreed==0 );
|
|
if( db->mallocFailed ){
|
|
return 0;
|
|
}
|
|
#endif
|
|
return dbMallocRawFinish(db, n);
|
|
}
|
|
|
|
/* Forward declaration */
|
|
static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n);
|
|
|
|
/*
|
|
** Resize the block of memory pointed to by p to n bytes. If the
|
|
** resize fails, set the mallocFailed flag in the connection object.
|
|
*/
|
|
SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){
|
|
assert( db!=0 );
|
|
if( p==0 ) return sqlite3DbMallocRawNN(db, n);
|
|
assert( sqlite3_mutex_held(db->mutex) );
|
|
if( ((uptr)p)<(uptr)db->lookaside.pEnd ){
|
|
#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
|
if( ((uptr)p)>=(uptr)db->lookaside.pMiddle ){
|
|
if( n<=LOOKASIDE_SMALL ) return p;
|
|
}else
|
|
#endif
|
|
if( ((uptr)p)>=(uptr)db->lookaside.pStart ){
|
|
if( n<=db->lookaside.szTrue ) return p;
|
|
}
|
|
}
|
|
return dbReallocFinish(db, p, n);
|
|
}
|
|
static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n){
|
|
void *pNew = 0;
|
|
assert( db!=0 );
|
|
assert( p!=0 );
|
|
if( db->mallocFailed==0 ){
|
|
if( isLookaside(db, p) ){
|
|
pNew = sqlite3DbMallocRawNN(db, n);
|
|
if( pNew ){
|
|
memcpy(pNew, p, lookasideMallocSize(db, p));
|
|
sqlite3DbFree(db, p);
|
|
}
|
|
}else{
|
|
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
|
assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
|
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
|
|
pNew = sqlite3Realloc(p, n);
|
|
if( !pNew ){
|
|
sqlite3OomFault(db);
|
|
}
|
|
sqlite3MemdebugSetType(pNew,
|
|
(db->lookaside.bDisable==0 ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
|
|
}
|
|
}
|
|
return pNew;
|
|
}
|
|
|
|
/*
|
|
** Attempt to reallocate p. If the reallocation fails, then free p
|
|
** and set the mallocFailed flag in the database connection.
|
|
*/
|
|
SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *db, void *p, u64 n){
|
|
void *pNew;
|
|
pNew = sqlite3DbRealloc(db, p, n);
|
|
if( !pNew ){
|
|
sqlite3DbFree(db, p);
|
|
}
|
|
return pNew;
|
|
}
|
|
|
|
/*
|
|
** 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.
|
|
*/
|
|
SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3 *db, const char *z){
|
|
char *zNew;
|
|
size_t n;
|
|
if( z==0 ){
|
|
return 0;
|
|
}
|
|
n = strlen(z) + 1;
|
|
zNew = sqlite3DbMallocRaw(db, n);
|
|
if( zNew ){
|
|
memcpy(zNew, z, n);
|
|
}
|
|
return zNew;
|
|
}
|
|
SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3 *db, const char *z, u64 n){
|
|
char *zNew;
|
|
assert( db!=0 );
|
|
assert( z!=0 || n==0 );
|
|
assert( (n&0x7fffffff)==n );
|
|
zNew = z ? sqlite3DbMallocRawNN(db, n+1) : 0;
|
|
if( zNew ){
|
|
memcpy(zNew, z, (size_t)n);
|
|
zNew[n] = 0;
|
|
}
|
|
return zNew;
|
|
}
|
|
|
|
/*
|
|
** The text between zStart and zEnd represents a phrase within a larger
|
|
** SQL statement. Make a copy of this phrase in space obtained form
|
|
** sqlite3DbMalloc(). Omit leading and trailing whitespace.
|
|
*/
|
|
SQLITE_PRIVATE char *sqlite3DbSpanDup(sqlite3 *db, const char *zStart, const char *zEnd){
|
|
int n;
|
|
#ifdef SQLITE_DEBUG
|
|
/* Because of the way the parser works, the span is guaranteed to contain
|
|
** at least one non-space character */
|
|
for(n=0; sqlite3Isspace(zStart[n]); n++){ assert( &zStart[n]<zEnd ); }
|
|
#endif
|
|
while( sqlite3Isspace(zStart[0]) ) zStart++;
|
|
n = (int)(zEnd - zStart);
|
|
while( sqlite3Isspace(zStart[n-1]) ) n--;
|
|
return sqlite3DbStrNDup(db, zStart, n);
|
|
}
|
|
|
|
/*
|
|
** Free any prior content in *pz and replace it with a copy of zNew.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){
|
|
char *z = sqlite3DbStrDup(db, zNew);
|
|
sqlite3DbFree(db, *pz);
|
|
*pz = z;
|
|
}
|
|
|
|
/*
|
|
** Call this routine to record the fact that an OOM (out-of-memory) error
|
|
** has happened. This routine will set db->mallocFailed, and also
|
|
** temporarily disable the lookaside memory allocator and interrupt
|
|
** any running VDBEs.
|
|
**
|
|
** Always return a NULL pointer so that this routine can be invoked using
|
|
**
|
|
** return sqlite3OomFault(db);
|
|
**
|
|
** and thereby avoid unnecessary stack frame allocations for the overwhelmingly
|
|
** common case where no OOM occurs.
|
|
*/
|
|
SQLITE_PRIVATE void *sqlite3OomFault(sqlite3 *db){
|
|
if( db->mallocFailed==0 && db->bBenignMalloc==0 ){
|
|
db->mallocFailed = 1;
|
|
if( db->nVdbeExec>0 ){
|
|
AtomicStore(&db->u1.isInterrupted, 1);
|
|
}
|
|
DisableLookaside;
|
|
if( db->pParse ){
|
|
Parse *pParse;
|
|
sqlite3ErrorMsg(db->pParse, "out of memory");
|
|
db->pParse->rc = SQLITE_NOMEM_BKPT;
|
|
for(pParse=db->pParse->pOuterParse; pParse; pParse = pParse->pOuterParse){
|
|
pParse->nErr++;
|
|
pParse->rc = SQLITE_NOMEM;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
** This routine reactivates the memory allocator and clears the
|
|
** db->mallocFailed flag as necessary.
|
|
**
|
|
** The memory allocator is not restarted if there are running
|
|
** VDBEs.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3OomClear(sqlite3 *db){
|
|
if( db->mallocFailed && db->nVdbeExec==0 ){
|
|
db->mallocFailed = 0;
|
|
AtomicStore(&db->u1.isInterrupted, 0);
|
|
assert( db->lookaside.bDisable>0 );
|
|
EnableLookaside;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Take actions at the end of an API call to deal with error codes.
|
|
*/
|
|
static SQLITE_NOINLINE int apiHandleError(sqlite3 *db, int rc){
|
|
if( db->mallocFailed || rc==SQLITE_IOERR_NOMEM ){
|
|
sqlite3OomClear(db);
|
|
sqlite3Error(db, SQLITE_NOMEM);
|
|
return SQLITE_NOMEM_BKPT;
|
|
}
|
|
return rc & db->errMask;
|
|
}
|
|
|
|
/*
|
|
** This function must be called before exiting any API function (i.e.
|
|
** returning control to the user) that has called sqlite3_malloc or
|
|
** sqlite3_realloc.
|
|
**
|
|
** The returned value is normally a copy of the second argument to this
|
|
** function. However, if a malloc() failure has occurred since the previous
|
|
** invocation SQLITE_NOMEM is returned instead.
|
|
**
|
|
** If an OOM as occurred, then the connection error-code (the value
|
|
** returned by sqlite3_errcode()) is set to SQLITE_NOMEM.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3ApiExit(sqlite3* db, int rc){
|
|
/* If the db handle must hold the connection handle mutex here.
|
|
** Otherwise the read (and possible write) of db->mallocFailed
|
|
** is unsafe, as is the call to sqlite3Error().
|
|
*/
|
|
assert( db!=0 );
|
|
assert( sqlite3_mutex_held(db->mutex) );
|
|
if( db->mallocFailed || rc ){
|
|
return apiHandleError(db, rc);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/************** End of malloc.c **********************************************/
|
|
/************** Begin file printf.c ******************************************/
|
|
/*
|
|
** The "printf" code that follows dates from the 1980's. It is in
|
|
** the public domain.
|
|
**
|
|
**************************************************************************
|
|
**
|
|
** This file contains code for a set of "printf"-like routines. These
|
|
** routines format strings much like the printf() from the standard C
|
|
** library, though the implementation here has enhancements to support
|
|
** SQLite.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
|
|
/*
|
|
** Conversion types fall into various categories as defined by the
|
|
** following enumeration.
|
|
*/
|
|
#define etRADIX 0 /* non-decimal integer types. %x %o */
|
|
#define etFLOAT 1 /* Floating point. %f */
|
|
#define etEXP 2 /* Exponentional notation. %e and %E */
|
|
#define etGENERIC 3 /* Floating or exponential, depending on exponent. %g */
|
|
#define etSIZE 4 /* Return number of characters processed so far. %n */
|
|
#define etSTRING 5 /* Strings. %s */
|
|
#define etDYNSTRING 6 /* Dynamically allocated strings. %z */
|
|
#define etPERCENT 7 /* Percent symbol. %% */
|
|
#define etCHARX 8 /* Characters. %c */
|
|
/* The rest are extensions, not normally found in printf() */
|
|
#define etSQLESCAPE 9 /* Strings with '\'' doubled. %q */
|
|
#define etSQLESCAPE2 10 /* Strings with '\'' doubled and enclosed in '',
|
|
NULL pointers replaced by SQL NULL. %Q */
|
|
#define etTOKEN 11 /* a pointer to a Token structure */
|
|
#define etSRCITEM 12 /* a pointer to a SrcItem */
|
|
#define etPOINTER 13 /* The %p conversion */
|
|
#define etSQLESCAPE3 14 /* %w -> Strings with '\"' doubled */
|
|
#define etORDINAL 15 /* %r -> 1st, 2nd, 3rd, 4th, etc. English only */
|
|
#define etDECIMAL 16 /* %d or %u, but not %x, %o */
|
|
|
|
#define etINVALID 17 /* Any unrecognized conversion type */
|
|
|
|
|
|
/*
|
|
** 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_STRING 4 /* Allow infinite 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, etDECIMAL, 0, 0 },
|
|
{ 's', 0, 4, etSTRING, 0, 0 },
|
|
{ 'g', 0, 1, etGENERIC, 30, 0 },
|
|
{ 'z', 0, 4, 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, etDECIMAL, 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, etDECIMAL, 0, 0 },
|
|
{ 'n', 0, 0, etSIZE, 0, 0 },
|
|
{ '%', 0, 0, etPERCENT, 0, 0 },
|
|
{ 'p', 16, 0, etPOINTER, 0, 1 },
|
|
|
|
/* All the rest are undocumented and are for internal use only */
|
|
{ 'T', 0, 0, etTOKEN, 0, 0 },
|
|
{ 'S', 0, 0, etSRCITEM, 0, 0 },
|
|
{ 'r', 10, 1, etORDINAL, 0, 0 },
|
|
};
|
|
|
|
/* Notes:
|
|
**
|
|
** %S Takes a pointer to SrcItem. Shows name or database.name
|
|
** %!S Like %S but prefer the zName over the zAlias
|
|
*/
|
|
|
|
/*
|
|
** Set the StrAccum object to an error mode.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3StrAccumSetError(StrAccum *p, u8 eError){
|
|
assert( eError==SQLITE_NOMEM || eError==SQLITE_TOOBIG );
|
|
p->accError = eError;
|
|
if( p->mxAlloc ) sqlite3_str_reset(p);
|
|
if( eError==SQLITE_TOOBIG ) sqlite3ErrorToParser(p->db, eError);
|
|
}
|
|
|
|
/*
|
|
** Extra argument values from a PrintfArguments object
|
|
*/
|
|
static sqlite3_int64 getIntArg(PrintfArguments *p){
|
|
if( p->nArg<=p->nUsed ) return 0;
|
|
return sqlite3_value_int64(p->apArg[p->nUsed++]);
|
|
}
|
|
static double getDoubleArg(PrintfArguments *p){
|
|
if( p->nArg<=p->nUsed ) return 0.0;
|
|
return sqlite3_value_double(p->apArg[p->nUsed++]);
|
|
}
|
|
static char *getTextArg(PrintfArguments *p){
|
|
if( p->nArg<=p->nUsed ) return 0;
|
|
return (char*)sqlite3_value_text(p->apArg[p->nUsed++]);
|
|
}
|
|
|
|
/*
|
|
** Allocate memory for a temporary buffer needed for printf rendering.
|
|
**
|
|
** If the requested size of the temp buffer is larger than the size
|
|
** of the output buffer in pAccum, then cause an SQLITE_TOOBIG error.
|
|
** Do the size check before the memory allocation to prevent rogue
|
|
** SQL from requesting large allocations using the precision or width
|
|
** field of the printf() function.
|
|
*/
|
|
static char *printfTempBuf(sqlite3_str *pAccum, sqlite3_int64 n){
|
|
char *z;
|
|
if( pAccum->accError ) return 0;
|
|
if( n>pAccum->nAlloc && n>pAccum->mxAlloc ){
|
|
sqlite3StrAccumSetError(pAccum, SQLITE_TOOBIG);
|
|
return 0;
|
|
}
|
|
z = sqlite3DbMallocRaw(pAccum->db, n);
|
|
if( z==0 ){
|
|
sqlite3StrAccumSetError(pAccum, SQLITE_NOMEM);
|
|
}
|
|
return z;
|
|
}
|
|
|
|
/*
|
|
** On machines with a small stack size, you can redefine the
|
|
** SQLITE_PRINT_BUF_SIZE to be something smaller, if desired.
|
|
*/
|
|
#ifndef SQLITE_PRINT_BUF_SIZE
|
|
# define SQLITE_PRINT_BUF_SIZE 70
|
|
#endif
|
|
#define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */
|
|
|
|
/*
|
|
** Hard limit on the precision of floating-point conversions.
|
|
*/
|
|
#ifndef SQLITE_PRINTF_PRECISION_LIMIT
|
|
# define SQLITE_FP_PRECISION_LIMIT 100000000
|
|
#endif
|
|
|
|
/*
|
|
** Render a string given by "fmt" into the StrAccum object.
|
|
*/
|
|
SQLITE_API void sqlite3_str_vappendf(
|
|
sqlite3_str *pAccum, /* Accumulate results here */
|
|
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 width; /* Width of the current field */
|
|
etByte flag_leftjustify; /* True if "-" flag is present */
|
|
etByte flag_prefix; /* '+' or ' ' or 0 for prefix */
|
|
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; /* 1 for the "l" flag, 2 for "ll", 0 by default */
|
|
etByte done; /* Loop termination flag */
|
|
etByte cThousand; /* Thousands separator for %d and %u */
|
|
etByte xtype = etINVALID; /* Conversion paradigm */
|
|
u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */
|
|
char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
|
|
sqlite_uint64 longvalue; /* Value for integer types */
|
|
double realvalue; /* Value for real types */
|
|
const et_info *infop; /* Pointer to the appropriate info structure */
|
|
char *zOut; /* Rendering buffer */
|
|
int nOut; /* Size of the rendering buffer */
|
|
char *zExtra = 0; /* Malloced memory used by some conversion */
|
|
int exp, e2; /* exponent of real numbers */
|
|
etByte flag_dp; /* True if decimal point should be shown */
|
|
etByte flag_rtz; /* True if trailing zeros should be removed */
|
|
|
|
PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */
|
|
char buf[etBUFSIZE]; /* Conversion buffer */
|
|
|
|
/* pAccum never starts out with an empty buffer that was obtained from
|
|
** malloc(). This precondition is required by the mprintf("%z...")
|
|
** optimization. */
|
|
assert( pAccum->nChar>0 || (pAccum->printfFlags&SQLITE_PRINTF_MALLOCED)==0 );
|
|
|
|
bufpt = 0;
|
|
if( (pAccum->printfFlags & SQLITE_PRINTF_SQLFUNC)!=0 ){
|
|
pArgList = va_arg(ap, PrintfArguments*);
|
|
bArgList = 1;
|
|
}else{
|
|
bArgList = 0;
|
|
}
|
|
for(; (c=(*fmt))!=0; ++fmt){
|
|
if( c!='%' ){
|
|
bufpt = (char *)fmt;
|
|
#if HAVE_STRCHRNUL
|
|
fmt = strchrnul(fmt, '%');
|
|
#else
|
|
do{ fmt++; }while( *fmt && *fmt != '%' );
|
|
#endif
|
|
sqlite3_str_append(pAccum, bufpt, (int)(fmt - bufpt));
|
|
if( *fmt==0 ) break;
|
|
}
|
|
if( (c=(*++fmt))==0 ){
|
|
sqlite3_str_append(pAccum, "%", 1);
|
|
break;
|
|
}
|
|
/* Find out what flags are present */
|
|
flag_leftjustify = flag_prefix = cThousand =
|
|
flag_alternateform = flag_altform2 = flag_zeropad = 0;
|
|
done = 0;
|
|
width = 0;
|
|
flag_long = 0;
|
|
precision = -1;
|
|
do{
|
|
switch( c ){
|
|
case '-': flag_leftjustify = 1; break;
|
|
case '+': flag_prefix = '+'; break;
|
|
case ' ': flag_prefix = ' '; break;
|
|
case '#': flag_alternateform = 1; break;
|
|
case '!': flag_altform2 = 1; break;
|
|
case '0': flag_zeropad = 1; break;
|
|
case ',': cThousand = ','; break;
|
|
default: done = 1; break;
|
|
case 'l': {
|
|
flag_long = 1;
|
|
c = *++fmt;
|
|
if( c=='l' ){
|
|
c = *++fmt;
|
|
flag_long = 2;
|
|
}
|
|
done = 1;
|
|
break;
|
|
}
|
|
case '1': case '2': case '3': case '4': case '5':
|
|
case '6': case '7': case '8': case '9': {
|
|
unsigned wx = c - '0';
|
|
while( (c = *++fmt)>='0' && c<='9' ){
|
|
wx = wx*10 + c - '0';
|
|
}
|
|
testcase( wx>0x7fffffff );
|
|
width = wx & 0x7fffffff;
|
|
#ifdef SQLITE_PRINTF_PRECISION_LIMIT
|
|
if( width>SQLITE_PRINTF_PRECISION_LIMIT ){
|
|
width = SQLITE_PRINTF_PRECISION_LIMIT;
|
|
}
|
|
#endif
|
|
if( c!='.' && c!='l' ){
|
|
done = 1;
|
|
}else{
|
|
fmt--;
|
|
}
|
|
break;
|
|
}
|
|
case '*': {
|
|
if( bArgList ){
|
|
width = (int)getIntArg(pArgList);
|
|
}else{
|
|
width = va_arg(ap,int);
|
|
}
|
|
if( width<0 ){
|
|
flag_leftjustify = 1;
|
|
width = width >= -2147483647 ? -width : 0;
|
|
}
|
|
#ifdef SQLITE_PRINTF_PRECISION_LIMIT
|
|
if( width>SQLITE_PRINTF_PRECISION_LIMIT ){
|
|
width = SQLITE_PRINTF_PRECISION_LIMIT;
|
|
}
|
|
#endif
|
|
if( (c = fmt[1])!='.' && c!='l' ){
|
|
c = *++fmt;
|
|
done = 1;
|
|
}
|
|
break;
|
|
}
|
|
case '.': {
|
|
c = *++fmt;
|
|
if( c=='*' ){
|
|
if( bArgList ){
|
|
precision = (int)getIntArg(pArgList);
|
|
}else{
|
|
precision = va_arg(ap,int);
|
|
}
|
|
if( precision<0 ){
|
|
precision = precision >= -2147483647 ? -precision : -1;
|
|
}
|
|
c = *++fmt;
|
|
}else{
|
|
unsigned px = 0;
|
|
while( c>='0' && c<='9' ){
|
|
px = px*10 + c - '0';
|
|
c = *++fmt;
|
|
}
|
|
testcase( px>0x7fffffff );
|
|
precision = px & 0x7fffffff;
|
|
}
|
|
#ifdef SQLITE_PRINTF_PRECISION_LIMIT
|
|
if( precision>SQLITE_PRINTF_PRECISION_LIMIT ){
|
|
precision = SQLITE_PRINTF_PRECISION_LIMIT;
|
|
}
|
|
#endif
|
|
if( c=='l' ){
|
|
--fmt;
|
|
}else{
|
|
done = 1;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}while( !done && (c=(*++fmt))!=0 );
|
|
|
|
/* Fetch the info entry for the field */
|
|
infop = &fmtinfo[0];
|
|
xtype = etINVALID;
|
|
for(idx=0; idx<ArraySize(fmtinfo); idx++){
|
|
if( c==fmtinfo[idx].fmttype ){
|
|
infop = &fmtinfo[idx];
|
|
xtype = infop->type;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** At this point, variables are initialized as follows:
|
|
**
|
|
** flag_alternateform TRUE if a '#' is present.
|
|
** flag_altform2 TRUE if a '!' is present.
|
|
** flag_prefix '+' or ' ' or zero
|
|
** 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 1 for "l", 2 for "ll"
|
|
** 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.
|
|
*/
|
|
assert( width>=0 );
|
|
assert( precision>=(-1) );
|
|
switch( xtype ){
|
|
case etPOINTER:
|
|
flag_long = sizeof(char*)==sizeof(i64) ? 2 :
|
|
sizeof(char*)==sizeof(long int) ? 1 : 0;
|
|
/* no break */ deliberate_fall_through
|
|
case etORDINAL:
|
|
case etRADIX:
|
|
cThousand = 0;
|
|
/* no break */ deliberate_fall_through
|
|
case etDECIMAL:
|
|
if( infop->flags & FLAG_SIGNED ){
|
|
i64 v;
|
|
if( bArgList ){
|
|
v = getIntArg(pArgList);
|
|
}else if( flag_long ){
|
|
if( flag_long==2 ){
|
|
v = va_arg(ap,i64) ;
|
|
}else{
|
|
v = va_arg(ap,long int);
|
|
}
|
|
}else{
|
|
v = va_arg(ap,int);
|
|
}
|
|
if( v<0 ){
|
|
testcase( v==SMALLEST_INT64 );
|
|
testcase( v==(-1) );
|
|
longvalue = ~v;
|
|
longvalue++;
|
|
prefix = '-';
|
|
}else{
|
|
longvalue = v;
|
|
prefix = flag_prefix;
|
|
}
|
|
}else{
|
|
if( bArgList ){
|
|
longvalue = (u64)getIntArg(pArgList);
|
|
}else if( flag_long ){
|
|
if( flag_long==2 ){
|
|
longvalue = va_arg(ap,u64);
|
|
}else{
|
|
longvalue = va_arg(ap,unsigned long int);
|
|
}
|
|
}else{
|
|
longvalue = va_arg(ap,unsigned int);
|
|
}
|
|
prefix = 0;
|
|
}
|
|
if( longvalue==0 ) flag_alternateform = 0;
|
|
if( flag_zeropad && precision<width-(prefix!=0) ){
|
|
precision = width-(prefix!=0);
|
|
}
|
|
if( precision<etBUFSIZE-10-etBUFSIZE/3 ){
|
|
nOut = etBUFSIZE;
|
|
zOut = buf;
|
|
}else{
|
|
u64 n;
|
|
n = (u64)precision + 10;
|
|
if( cThousand ) n += precision/3;
|
|
zOut = zExtra = printfTempBuf(pAccum, n);
|
|
if( zOut==0 ) return;
|
|
nOut = (int)n;
|
|
}
|
|
bufpt = &zOut[nOut-1];
|
|
if( xtype==etORDINAL ){
|
|
static const char zOrd[] = "thstndrd";
|
|
int x = (int)(longvalue % 10);
|
|
if( x>=4 || (longvalue/10)%10==1 ){
|
|
x = 0;
|
|
}
|
|
*(--bufpt) = zOrd[x*2+1];
|
|
*(--bufpt) = zOrd[x*2];
|
|
}
|
|
{
|
|
const char *cset = &aDigits[infop->charset];
|
|
u8 base = infop->base;
|
|
do{ /* Convert to ascii */
|
|
*(--bufpt) = cset[longvalue%base];
|
|
longvalue = longvalue/base;
|
|
}while( longvalue>0 );
|
|
}
|
|
length = (int)(&zOut[nOut-1]-bufpt);
|
|
while( precision>length ){
|
|
*(--bufpt) = '0'; /* Zero pad */
|
|
length++;
|
|
}
|
|
if( cThousand ){
|
|
int nn = (length - 1)/3; /* Number of "," to insert */
|
|
int ix = (length - 1)%3 + 1;
|
|
bufpt -= nn;
|
|
for(idx=0; nn>0; idx++){
|
|
bufpt[idx] = bufpt[idx+nn];
|
|
ix--;
|
|
if( ix==0 ){
|
|
bufpt[++idx] = cThousand;
|
|
nn--;
|
|
ix = 3;
|
|
}
|
|
}
|
|
}
|
|
if( prefix ) *(--bufpt) = prefix; /* Add sign */
|
|
if( flag_alternateform && infop->prefix ){ /* Add "0" or "0x" */
|
|
const char *pre;
|
|
char x;
|
|
pre = &aPrefix[infop->prefix];
|
|
for(; (x=(*pre))!=0; pre++) *(--bufpt) = x;
|
|
}
|
|
length = (int)(&zOut[nOut-1]-bufpt);
|
|
break;
|
|
case etFLOAT:
|
|
case etEXP:
|
|
case etGENERIC: {
|
|
FpDecode s;
|
|
int iRound;
|
|
int j;
|
|
|
|
if( bArgList ){
|
|
realvalue = getDoubleArg(pArgList);
|
|
}else{
|
|
realvalue = va_arg(ap,double);
|
|
}
|
|
if( precision<0 ) precision = 6; /* Set default precision */
|
|
#ifdef SQLITE_FP_PRECISION_LIMIT
|
|
if( precision>SQLITE_FP_PRECISION_LIMIT ){
|
|
precision = SQLITE_FP_PRECISION_LIMIT;
|
|
}
|
|
#endif
|
|
if( xtype==etFLOAT ){
|
|
iRound = -precision;
|
|
}else if( xtype==etGENERIC ){
|
|
if( precision==0 ) precision = 1;
|
|
iRound = precision;
|
|
}else{
|
|
iRound = precision+1;
|
|
}
|
|
sqlite3FpDecode(&s, realvalue, iRound, flag_altform2 ? 26 : 16);
|
|
if( s.isSpecial ){
|
|
if( s.isSpecial==2 ){
|
|
bufpt = flag_zeropad ? "null" : "NaN";
|
|
length = sqlite3Strlen30(bufpt);
|
|
break;
|
|
}else if( flag_zeropad ){
|
|
s.z[0] = '9';
|
|
s.iDP = 1000;
|
|
s.n = 1;
|
|
}else{
|
|
memcpy(buf, "-Inf", 5);
|
|
bufpt = buf;
|
|
if( s.sign=='-' ){
|
|
/* no-op */
|
|
}else if( flag_prefix ){
|
|
buf[0] = flag_prefix;
|
|
}else{
|
|
bufpt++;
|
|
}
|
|
length = sqlite3Strlen30(bufpt);
|
|
break;
|
|
}
|
|
}
|
|
if( s.sign=='-' ){
|
|
prefix = '-';
|
|
}else{
|
|
prefix = flag_prefix;
|
|
}
|
|
|
|
exp = s.iDP-1;
|
|
if( xtype==etGENERIC && precision>0 ) precision--;
|
|
|
|
/*
|
|
** If the field type is etGENERIC, then convert to either etEXP
|
|
** or etFLOAT, as appropriate.
|
|
*/
|
|
if( xtype==etGENERIC ){
|
|
flag_rtz = !flag_alternateform;
|
|
if( exp<-4 || exp>precision ){
|
|
xtype = etEXP;
|
|
}else{
|
|
precision = precision - exp;
|
|
xtype = etFLOAT;
|
|
}
|
|
}else{
|
|
flag_rtz = flag_altform2;
|
|
}
|
|
if( xtype==etEXP ){
|
|
e2 = 0;
|
|
}else{
|
|
e2 = s.iDP - 1;
|
|
}
|
|
bufpt = buf;
|
|
{
|
|
i64 szBufNeeded; /* Size of a temporary buffer needed */
|
|
szBufNeeded = MAX(e2,0)+(i64)precision+(i64)width+15;
|
|
if( cThousand && e2>0 ) szBufNeeded += (e2+2)/3;
|
|
if( szBufNeeded > etBUFSIZE ){
|
|
bufpt = zExtra = printfTempBuf(pAccum, szBufNeeded);
|
|
if( bufpt==0 ) return;
|
|
}
|
|
}
|
|
zOut = bufpt;
|
|
flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2;
|
|
/* The sign in front of the number */
|
|
if( prefix ){
|
|
*(bufpt++) = prefix;
|
|
}
|
|
/* Digits prior to the decimal point */
|
|
j = 0;
|
|
if( e2<0 ){
|
|
*(bufpt++) = '0';
|
|
}else{
|
|
for(; e2>=0; e2--){
|
|
*(bufpt++) = j<s.n ? s.z[j++] : '0';
|
|
if( cThousand && (e2%3)==0 && e2>1 ) *(bufpt++) = ',';
|
|
}
|
|
}
|
|
/* 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++) = j<s.n ? s.z[j++] : '0';
|
|
}
|
|
/* Remove trailing zeros and the "." if no digits follow the "." */
|
|
if( flag_rtz && flag_dp ){
|
|
while( bufpt[-1]=='0' ) *(--bufpt) = 0;
|
|
assert( bufpt>zOut );
|
|
if( bufpt[-1]=='.' ){
|
|
if( flag_altform2 ){
|
|
*(bufpt++) = '0';
|
|
}else{
|
|
*(--bufpt) = 0;
|
|
}
|
|
}
|
|
}
|
|
/* Add the "eNNN" suffix */
|
|
if( xtype==etEXP ){
|
|
exp = s.iDP - 1;
|
|
*(bufpt++) = aDigits[infop->charset];
|
|
if( exp<0 ){
|
|
*(bufpt++) = '-'; exp = -exp;
|
|
}else{
|
|
*(bufpt++) = '+';
|
|
}
|
|
if( exp>=100 ){
|
|
*(bufpt++) = (char)((exp/100)+'0'); /* 100's digit */
|
|
exp %= 100;
|
|
}
|
|
*(bufpt++) = (char)(exp/10+'0'); /* 10's digit */
|
|
*(bufpt++) = (char)(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 = (int)(bufpt-zOut);
|
|
bufpt = zOut;
|
|
|
|
/* 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;
|
|
}
|
|
break;
|
|
}
|
|
case etSIZE:
|
|
if( !bArgList ){
|
|
*(va_arg(ap,int*)) = pAccum->nChar;
|
|
}
|
|
length = width = 0;
|
|
break;
|
|
case etPERCENT:
|
|
buf[0] = '%';
|
|
bufpt = buf;
|
|
length = 1;
|
|
break;
|
|
case etCHARX:
|
|
if( bArgList ){
|
|
bufpt = getTextArg(pArgList);
|
|
length = 1;
|
|
if( bufpt ){
|
|
buf[0] = c = *(bufpt++);
|
|
if( (c&0xc0)==0xc0 ){
|
|
while( length<4 && (bufpt[0]&0xc0)==0x80 ){
|
|
buf[length++] = *(bufpt++);
|
|
}
|
|
}
|
|
}else{
|
|
buf[0] = 0;
|
|
}
|
|
}else{
|
|
unsigned int ch = va_arg(ap,unsigned int);
|
|
if( ch<0x00080 ){
|
|
buf[0] = ch & 0xff;
|
|
length = 1;
|
|
}else if( ch<0x00800 ){
|
|
buf[0] = 0xc0 + (u8)((ch>>6)&0x1f);
|
|
buf[1] = 0x80 + (u8)(ch & 0x3f);
|
|
length = 2;
|
|
}else if( ch<0x10000 ){
|
|
buf[0] = 0xe0 + (u8)((ch>>12)&0x0f);
|
|
buf[1] = 0x80 + (u8)((ch>>6) & 0x3f);
|
|
buf[2] = 0x80 + (u8)(ch & 0x3f);
|
|
length = 3;
|
|
}else{
|
|
buf[0] = 0xf0 + (u8)((ch>>18) & 0x07);
|
|
buf[1] = 0x80 + (u8)((ch>>12) & 0x3f);
|
|
buf[2] = 0x80 + (u8)((ch>>6) & 0x3f);
|
|
buf[3] = 0x80 + (u8)(ch & 0x3f);
|
|
length = 4;
|
|
}
|
|
}
|
|
if( precision>1 ){
|
|
i64 nPrior = 1;
|
|
width -= precision-1;
|
|
if( width>1 && !flag_leftjustify ){
|
|
sqlite3_str_appendchar(pAccum, width-1, ' ');
|
|
width = 0;
|
|
}
|
|
sqlite3_str_append(pAccum, buf, length);
|
|
precision--;
|
|
while( precision > 1 ){
|
|
i64 nCopyBytes;
|
|
if( nPrior > precision-1 ) nPrior = precision - 1;
|
|
nCopyBytes = length*nPrior;
|
|
if( nCopyBytes + pAccum->nChar >= pAccum->nAlloc ){
|
|
sqlite3StrAccumEnlarge(pAccum, nCopyBytes);
|
|
}
|
|
if( pAccum->accError ) break;
|
|
sqlite3_str_append(pAccum,
|
|
&pAccum->zText[pAccum->nChar-nCopyBytes], nCopyBytes);
|
|
precision -= nPrior;
|
|
nPrior *= 2;
|
|
}
|
|
}
|
|
bufpt = buf;
|
|
flag_altform2 = 1;
|
|
goto adjust_width_for_utf8;
|
|
case etSTRING:
|
|
case etDYNSTRING:
|
|
if( bArgList ){
|
|
bufpt = getTextArg(pArgList);
|
|
xtype = etSTRING;
|
|
}else{
|
|
bufpt = va_arg(ap,char*);
|
|
}
|
|
if( bufpt==0 ){
|
|
bufpt = "";
|
|
}else if( xtype==etDYNSTRING ){
|
|
if( pAccum->nChar==0
|
|
&& pAccum->mxAlloc
|
|
&& width==0
|
|
&& precision<0
|
|
&& pAccum->accError==0
|
|
){
|
|
/* Special optimization for sqlite3_mprintf("%z..."):
|
|
** Extend an existing memory allocation rather than creating
|
|
** a new one. */
|
|
assert( (pAccum->printfFlags&SQLITE_PRINTF_MALLOCED)==0 );
|
|
pAccum->zText = bufpt;
|
|
pAccum->nAlloc = sqlite3DbMallocSize(pAccum->db, bufpt);
|
|
pAccum->nChar = 0x7fffffff & (int)strlen(bufpt);
|
|
pAccum->printfFlags |= SQLITE_PRINTF_MALLOCED;
|
|
length = 0;
|
|
break;
|
|
}
|
|
zExtra = bufpt;
|
|
}
|
|
if( precision>=0 ){
|
|
if( flag_altform2 ){
|
|
/* Set length to the number of bytes needed in order to display
|
|
** precision characters */
|
|
unsigned char *z = (unsigned char*)bufpt;
|
|
while( precision-- > 0 && z[0] ){
|
|
SQLITE_SKIP_UTF8(z);
|
|
}
|
|
length = (int)(z - (unsigned char*)bufpt);
|
|
}else{
|
|
for(length=0; length<precision && bufpt[length]; length++){}
|
|
}
|
|
}else{
|
|
length = 0x7fffffff & (int)strlen(bufpt);
|
|
}
|
|
adjust_width_for_utf8:
|
|
if( flag_altform2 && width>0 ){
|
|
/* Adjust width to account for extra bytes in UTF-8 characters */
|
|
int ii = length - 1;
|
|
while( ii>=0 ) if( (bufpt[ii--] & 0xc0)==0x80 ) width++;
|
|
}
|
|
break;
|
|
case etSQLESCAPE: /* %q: Escape ' characters */
|
|
case etSQLESCAPE2: /* %Q: Escape ' and enclose in '...' */
|
|
case etSQLESCAPE3: { /* %w: Escape " characters */
|
|
i64 i, j, k, n;
|
|
int needQuote, isnull;
|
|
char ch;
|
|
char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */
|
|
char *escarg;
|
|
|
|
if( bArgList ){
|
|
escarg = getTextArg(pArgList);
|
|
}else{
|
|
escarg = va_arg(ap,char*);
|
|
}
|
|
isnull = escarg==0;
|
|
if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
|
|
/* For %q, %Q, and %w, the precision is the number of bytes (or
|
|
** characters if the ! flags is present) to use from the input.
|
|
** Because of the extra quoting characters inserted, the number
|
|
** of output characters may be larger than the precision.
|
|
*/
|
|
k = precision;
|
|
for(i=n=0; k!=0 && (ch=escarg[i])!=0; i++, k--){
|
|
if( ch==q ) n++;
|
|
if( flag_altform2 && (ch&0xc0)==0xc0 ){
|
|
while( (escarg[i+1]&0xc0)==0x80 ){ i++; }
|
|
}
|
|
}
|
|
needQuote = !isnull && xtype==etSQLESCAPE2;
|
|
n += i + 3;
|
|
if( n>etBUFSIZE ){
|
|
bufpt = zExtra = printfTempBuf(pAccum, n);
|
|
if( bufpt==0 ) return;
|
|
}else{
|
|
bufpt = buf;
|
|
}
|
|
j = 0;
|
|
if( needQuote ) bufpt[j++] = q;
|
|
k = i;
|
|
for(i=0; i<k; i++){
|
|
bufpt[j++] = ch = escarg[i];
|
|
if( ch==q ) bufpt[j++] = ch;
|
|
}
|
|
if( needQuote ) bufpt[j++] = q;
|
|
bufpt[j] = 0;
|
|
length = j;
|
|
goto adjust_width_for_utf8;
|
|
}
|
|
case etTOKEN: {
|
|
if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return;
|
|
if( flag_alternateform ){
|
|
/* %#T means an Expr pointer that uses Expr.u.zToken */
|
|
Expr *pExpr = va_arg(ap,Expr*);
|
|
if( ALWAYS(pExpr) && ALWAYS(!ExprHasProperty(pExpr,EP_IntValue)) ){
|
|
sqlite3_str_appendall(pAccum, (const char*)pExpr->u.zToken);
|
|
sqlite3RecordErrorOffsetOfExpr(pAccum->db, pExpr);
|
|
}
|
|
}else{
|
|
/* %T means a Token pointer */
|
|
Token *pToken = va_arg(ap, Token*);
|
|
assert( bArgList==0 );
|
|
if( pToken && pToken->n ){
|
|
sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n);
|
|
sqlite3RecordErrorByteOffset(pAccum->db, pToken->z);
|
|
}
|
|
}
|
|
length = width = 0;
|
|
break;
|
|
}
|
|
case etSRCITEM: {
|
|
SrcItem *pItem;
|
|
if( (pAccum->printfFlags & SQLITE_PRINTF_INTERNAL)==0 ) return;
|
|
pItem = va_arg(ap, SrcItem*);
|
|
assert( bArgList==0 );
|
|
if( pItem->zAlias && !flag_altform2 ){
|
|
sqlite3_str_appendall(pAccum, pItem->zAlias);
|
|
}else if( pItem->zName ){
|
|
if( pItem->zDatabase ){
|
|
sqlite3_str_appendall(pAccum, pItem->zDatabase);
|
|
sqlite3_str_append(pAccum, ".", 1);
|
|
}
|
|
sqlite3_str_appendall(pAccum, pItem->zName);
|
|
}else if( pItem->zAlias ){
|
|
sqlite3_str_appendall(pAccum, pItem->zAlias);
|
|
}else{
|
|
Select *pSel = pItem->pSelect;
|
|
assert( pSel!=0 );
|
|
if( pSel->selFlags & SF_NestedFrom ){
|
|
sqlite3_str_appendf(pAccum, "(join-%u)", pSel->selId);
|
|
}else{
|
|
sqlite3_str_appendf(pAccum, "(subquery-%u)", pSel->selId);
|
|
}
|
|
}
|
|
length = width = 0;
|
|
break;
|
|
}
|
|
default: {
|
|
assert( xtype==etINVALID );
|
|
return;
|
|
}
|
|
}/* 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. Both length and width are in bytes, not characters,
|
|
** at this point. If the "!" flag was present on string conversions
|
|
** indicating that width and precision should be expressed in characters,
|
|
** then the values have been translated prior to reaching this point.
|
|
*/
|
|
width -= length;
|
|
if( width>0 ){
|
|
if( !flag_leftjustify ) sqlite3_str_appendchar(pAccum, width, ' ');
|
|
sqlite3_str_append(pAccum, bufpt, length);
|
|
if( flag_leftjustify ) sqlite3_str_appendchar(pAccum, width, ' ');
|
|
}else{
|
|
sqlite3_str_append(pAccum, bufpt, length);
|
|
}
|
|
|
|
if( zExtra ){
|
|
sqlite3DbFree(pAccum->db, zExtra);
|
|
zExtra = 0;
|
|
}
|
|
}/* End for loop over the format string */
|
|
} /* End of function */
|
|
|
|
|
|
/*
|
|
** The z string points to the first character of a token that is
|
|
** associated with an error. If db does not already have an error
|
|
** byte offset recorded, try to compute the error byte offset for
|
|
** z and set the error byte offset in db.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3RecordErrorByteOffset(sqlite3 *db, const char *z){
|
|
const Parse *pParse;
|
|
const char *zText;
|
|
const char *zEnd;
|
|
assert( z!=0 );
|
|
if( NEVER(db==0) ) return;
|
|
if( db->errByteOffset!=(-2) ) return;
|
|
pParse = db->pParse;
|
|
if( NEVER(pParse==0) ) return;
|
|
zText =pParse->zTail;
|
|
if( NEVER(zText==0) ) return;
|
|
zEnd = &zText[strlen(zText)];
|
|
if( SQLITE_WITHIN(z,zText,zEnd) ){
|
|
db->errByteOffset = (int)(z-zText);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** If pExpr has a byte offset for the start of a token, record that as
|
|
** as the error offset.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3RecordErrorOffsetOfExpr(sqlite3 *db, const Expr *pExpr){
|
|
while( pExpr
|
|
&& (ExprHasProperty(pExpr,EP_OuterON|EP_InnerON) || pExpr->w.iOfst<=0)
|
|
){
|
|
pExpr = pExpr->pLeft;
|
|
}
|
|
if( pExpr==0 ) return;
|
|
db->errByteOffset = pExpr->w.iOfst;
|
|
}
|
|
|
|
/*
|
|
** Enlarge the memory allocation on a StrAccum object so that it is
|
|
** able to accept at least N more bytes of text.
|
|
**
|
|
** Return the number of bytes of text that StrAccum is able to accept
|
|
** after the attempted enlargement. The value returned might be zero.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3StrAccumEnlarge(StrAccum *p, i64 N){
|
|
char *zNew;
|
|
assert( p->nChar+N >= p->nAlloc ); /* Only called if really needed */
|
|
if( p->accError ){
|
|
testcase(p->accError==SQLITE_TOOBIG);
|
|
testcase(p->accError==SQLITE_NOMEM);
|
|
return 0;
|
|
}
|
|
if( p->mxAlloc==0 ){
|
|
sqlite3StrAccumSetError(p, SQLITE_TOOBIG);
|
|
return p->nAlloc - p->nChar - 1;
|
|
}else{
|
|
char *zOld = isMalloced(p) ? p->zText : 0;
|
|
i64 szNew = p->nChar + N + 1;
|
|
if( szNew+p->nChar<=p->mxAlloc ){
|
|
/* Force exponential buffer size growth as long as it does not overflow,
|
|
** to avoid having to call this routine too often */
|
|
szNew += p->nChar;
|
|
}
|
|
if( szNew > p->mxAlloc ){
|
|
sqlite3_str_reset(p);
|
|
sqlite3StrAccumSetError(p, SQLITE_TOOBIG);
|
|
return 0;
|
|
}else{
|
|
p->nAlloc = (int)szNew;
|
|
}
|
|
if( p->db ){
|
|
zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
|
|
}else{
|
|
zNew = sqlite3Realloc(zOld, p->nAlloc);
|
|
}
|
|
if( zNew ){
|
|
assert( p->zText!=0 || p->nChar==0 );
|
|
if( !isMalloced(p) && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
|
|
p->zText = zNew;
|
|
p->nAlloc = sqlite3DbMallocSize(p->db, zNew);
|
|
p->printfFlags |= SQLITE_PRINTF_MALLOCED;
|
|
}else{
|
|
sqlite3_str_reset(p);
|
|
sqlite3StrAccumSetError(p, SQLITE_NOMEM);
|
|
return 0;
|
|
}
|
|
}
|
|
assert( N>=0 && N<=0x7fffffff );
|
|
return (int)N;
|
|
}
|
|
|
|
/*
|
|
** Append N copies of character c to the given string buffer.
|
|
*/
|
|
SQLITE_API void sqlite3_str_appendchar(sqlite3_str *p, int N, char c){
|
|
testcase( p->nChar + (i64)N > 0x7fffffff );
|
|
if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){
|
|
return;
|
|
}
|
|
while( (N--)>0 ) p->zText[p->nChar++] = c;
|
|
}
|
|
|
|
/*
|
|
** The StrAccum "p" is not large enough to accept N new bytes of z[].
|
|
** So enlarge if first, then do the append.
|
|
**
|
|
** This is a helper routine to sqlite3_str_append() that does special-case
|
|
** work (enlarging the buffer) using tail recursion, so that the
|
|
** sqlite3_str_append() routine can use fast calling semantics.
|
|
*/
|
|
static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){
|
|
N = sqlite3StrAccumEnlarge(p, N);
|
|
if( N>0 ){
|
|
memcpy(&p->zText[p->nChar], z, N);
|
|
p->nChar += N;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Append N bytes of text from z to the StrAccum object. Increase the
|
|
** size of the memory allocation for StrAccum if necessary.
|
|
*/
|
|
SQLITE_API void sqlite3_str_append(sqlite3_str *p, const char *z, int N){
|
|
assert( z!=0 || N==0 );
|
|
assert( p->zText!=0 || p->nChar==0 || p->accError );
|
|
assert( N>=0 );
|
|
assert( p->accError==0 || p->nAlloc==0 || p->mxAlloc==0 );
|
|
if( p->nChar+N >= p->nAlloc ){
|
|
enlargeAndAppend(p,z,N);
|
|
}else if( N ){
|
|
assert( p->zText );
|
|
p->nChar += N;
|
|
memcpy(&p->zText[p->nChar-N], z, N);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Append the complete text of zero-terminated string z[] to the p string.
|
|
*/
|
|
SQLITE_API void sqlite3_str_appendall(sqlite3_str *p, const char *z){
|
|
sqlite3_str_append(p, z, sqlite3Strlen30(z));
|
|
}
|
|
|
|
|
|
/*
|
|
** Finish off a string by making sure it is zero-terminated.
|
|
** Return a pointer to the resulting string. Return a NULL
|
|
** pointer if any kind of error was encountered.
|
|
*/
|
|
static SQLITE_NOINLINE char *strAccumFinishRealloc(StrAccum *p){
|
|
char *zText;
|
|
assert( p->mxAlloc>0 && !isMalloced(p) );
|
|
zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
|
|
if( zText ){
|
|
memcpy(zText, p->zText, p->nChar+1);
|
|
p->printfFlags |= SQLITE_PRINTF_MALLOCED;
|
|
}else{
|
|
sqlite3StrAccumSetError(p, SQLITE_NOMEM);
|
|
}
|
|
p->zText = zText;
|
|
return zText;
|
|
}
|
|
SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){
|
|
if( p->zText ){
|
|
p->zText[p->nChar] = 0;
|
|
if( p->mxAlloc>0 && !isMalloced(p) ){
|
|
return strAccumFinishRealloc(p);
|
|
}
|
|
}
|
|
return p->zText;
|
|
}
|
|
|
|
/*
|
|
** Use the content of the StrAccum passed as the second argument
|
|
** as the result of an SQL function.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3ResultStrAccum(sqlite3_context *pCtx, StrAccum *p){
|
|
if( p->accError ){
|
|
sqlite3_result_error_code(pCtx, p->accError);
|
|
sqlite3_str_reset(p);
|
|
}else if( isMalloced(p) ){
|
|
sqlite3_result_text(pCtx, p->zText, p->nChar, SQLITE_DYNAMIC);
|
|
}else{
|
|
sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC);
|
|
sqlite3_str_reset(p);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** This singleton is an sqlite3_str object that is returned if
|
|
** sqlite3_malloc() fails to provide space for a real one. This
|
|
** sqlite3_str object accepts no new text and always returns
|
|
** an SQLITE_NOMEM error.
|
|
*/
|
|
static sqlite3_str sqlite3OomStr = {
|
|
0, 0, 0, 0, 0, SQLITE_NOMEM, 0
|
|
};
|
|
|
|
/* Finalize a string created using sqlite3_str_new().
|
|
*/
|
|
SQLITE_API char *sqlite3_str_finish(sqlite3_str *p){
|
|
char *z;
|
|
if( p!=0 && p!=&sqlite3OomStr ){
|
|
z = sqlite3StrAccumFinish(p);
|
|
sqlite3_free(p);
|
|
}else{
|
|
z = 0;
|
|
}
|
|
return z;
|
|
}
|
|
|
|
/* Return any error code associated with p */
|
|
SQLITE_API int sqlite3_str_errcode(sqlite3_str *p){
|
|
return p ? p->accError : SQLITE_NOMEM;
|
|
}
|
|
|
|
/* Return the current length of p in bytes */
|
|
SQLITE_API int sqlite3_str_length(sqlite3_str *p){
|
|
return p ? p->nChar : 0;
|
|
}
|
|
|
|
/* Return the current value for p */
|
|
SQLITE_API char *sqlite3_str_value(sqlite3_str *p){
|
|
if( p==0 || p->nChar==0 ) return 0;
|
|
p->zText[p->nChar] = 0;
|
|
return p->zText;
|
|
}
|
|
|
|
/*
|
|
** Reset an StrAccum string. Reclaim all malloced memory.
|
|
*/
|
|
SQLITE_API void sqlite3_str_reset(StrAccum *p){
|
|
if( isMalloced(p) ){
|
|
sqlite3DbFree(p->db, p->zText);
|
|
p->printfFlags &= ~SQLITE_PRINTF_MALLOCED;
|
|
}
|
|
p->nAlloc = 0;
|
|
p->nChar = 0;
|
|
p->zText = 0;
|
|
}
|
|
|
|
/*
|
|
** Initialize a string accumulator.
|
|
**
|
|
** p: The accumulator to be initialized.
|
|
** db: Pointer to a database connection. May be NULL. Lookaside
|
|
** memory is used if not NULL. db->mallocFailed is set appropriately
|
|
** when not NULL.
|
|
** zBase: An initial buffer. May be NULL in which case the initial buffer
|
|
** is malloced.
|
|
** n: Size of zBase in bytes. If total space requirements never exceed
|
|
** n then no memory allocations ever occur.
|
|
** mx: Maximum number of bytes to accumulate. If mx==0 then no memory
|
|
** allocations will ever occur.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum *p, sqlite3 *db, char *zBase, int n, int mx){
|
|
p->zText = zBase;
|
|
p->db = db;
|
|
p->nAlloc = n;
|
|
p->mxAlloc = mx;
|
|
p->nChar = 0;
|
|
p->accError = 0;
|
|
p->printfFlags = 0;
|
|
}
|
|
|
|
/* Allocate and initialize a new dynamic string object */
|
|
SQLITE_API sqlite3_str *sqlite3_str_new(sqlite3 *db){
|
|
sqlite3_str *p = sqlite3_malloc64(sizeof(*p));
|
|
if( p ){
|
|
sqlite3StrAccumInit(p, 0, 0, 0,
|
|
db ? db->aLimit[SQLITE_LIMIT_LENGTH] : SQLITE_MAX_LENGTH);
|
|
}else{
|
|
p = &sqlite3OomStr;
|
|
}
|
|
return p;
|
|
}
|
|
|
|
/*
|
|
** Print into memory obtained from sqliteMalloc(). Use the internal
|
|
** %-conversion extensions.
|
|
*/
|
|
SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){
|
|
char *z;
|
|
char zBase[SQLITE_PRINT_BUF_SIZE];
|
|
StrAccum acc;
|
|
assert( db!=0 );
|
|
sqlite3StrAccumInit(&acc, db, zBase, sizeof(zBase),
|
|
db->aLimit[SQLITE_LIMIT_LENGTH]);
|
|
acc.printfFlags = SQLITE_PRINTF_INTERNAL;
|
|
sqlite3_str_vappendf(&acc, zFormat, ap);
|
|
z = sqlite3StrAccumFinish(&acc);
|
|
if( acc.accError==SQLITE_NOMEM ){
|
|
sqlite3OomFault(db);
|
|
}
|
|
return z;
|
|
}
|
|
|
|
/*
|
|
** Print into memory obtained from sqliteMalloc(). Use the internal
|
|
** %-conversion extensions.
|
|
*/
|
|
SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3 *db, const char *zFormat, ...){
|
|
va_list ap;
|
|
char *z;
|
|
va_start(ap, zFormat);
|
|
z = sqlite3VMPrintf(db, zFormat, ap);
|
|
va_end(ap);
|
|
return z;
|
|
}
|
|
|
|
/*
|
|
** Print into memory obtained from sqlite3_malloc(). Omit the internal
|
|
** %-conversion extensions.
|
|
*/
|
|
SQLITE_API char *sqlite3_vmprintf(const char *zFormat, va_list ap){
|
|
char *z;
|
|
char zBase[SQLITE_PRINT_BUF_SIZE];
|
|
StrAccum acc;
|
|
|
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
|
if( zFormat==0 ){
|
|
(void)SQLITE_MISUSE_BKPT;
|
|
return 0;
|
|
}
|
|
#endif
|
|
#ifndef SQLITE_OMIT_AUTOINIT
|
|
if( sqlite3_initialize() ) return 0;
|
|
#endif
|
|
sqlite3StrAccumInit(&acc, 0, zBase, sizeof(zBase), SQLITE_MAX_LENGTH);
|
|
sqlite3_str_vappendf(&acc, zFormat, ap);
|
|
z = sqlite3StrAccumFinish(&acc);
|
|
return z;
|
|
}
|
|
|
|
/*
|
|
** Print into memory obtained from sqlite3_malloc()(). Omit the internal
|
|
** %-conversion extensions.
|
|
*/
|
|
SQLITE_API char *sqlite3_mprintf(const char *zFormat, ...){
|
|
va_list ap;
|
|
char *z;
|
|
#ifndef SQLITE_OMIT_AUTOINIT
|
|
if( sqlite3_initialize() ) return 0;
|
|
#endif
|
|
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.
|
|
**
|
|
** Oops: The first two arguments of sqlite3_snprintf() are backwards
|
|
** from the snprintf() standard. Unfortunately, it is too late to change
|
|
** this without breaking compatibility, so we just have to live with the
|
|
** mistake.
|
|
**
|
|
** sqlite3_vsnprintf() is the varargs version.
|
|
*/
|
|
SQLITE_API char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){
|
|
StrAccum acc;
|
|
if( n<=0 ) return zBuf;
|
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
|
if( zBuf==0 || zFormat==0 ) {
|
|
(void)SQLITE_MISUSE_BKPT;
|
|
if( zBuf ) zBuf[0] = 0;
|
|
return zBuf;
|
|
}
|
|
#endif
|
|
sqlite3StrAccumInit(&acc, 0, zBuf, n, 0);
|
|
sqlite3_str_vappendf(&acc, zFormat, ap);
|
|
zBuf[acc.nChar] = 0;
|
|
return zBuf;
|
|
}
|
|
SQLITE_API char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
|
|
StrAccum acc;
|
|
va_list ap;
|
|
if( n<=0 ) return zBuf;
|
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
|
if( zBuf==0 || zFormat==0 ) {
|
|
(void)SQLITE_MISUSE_BKPT;
|
|
if( zBuf ) zBuf[0] = 0;
|
|
return zBuf;
|
|
}
|
|
#endif
|
|
sqlite3StrAccumInit(&acc, 0, zBuf, n, 0);
|
|
va_start(ap,zFormat);
|
|
sqlite3_str_vappendf(&acc, zFormat, ap);
|
|
va_end(ap);
|
|
zBuf[acc.nChar] = 0;
|
|
return zBuf;
|
|
}
|
|
|
|
/*
|
|
** This is the routine that actually formats the sqlite3_log() message.
|
|
** We house it in a separate routine from sqlite3_log() to avoid using
|
|
** stack space on small-stack systems when logging is disabled.
|
|
**
|
|
** sqlite3_log() must render into a static buffer. It cannot dynamically
|
|
** allocate memory because it might be called while the memory allocator
|
|
** mutex is held.
|
|
**
|
|
** sqlite3_str_vappendf() might ask for *temporary* memory allocations for
|
|
** certain format characters (%q) or for very large precisions or widths.
|
|
** Care must be taken that any sqlite3_log() calls that occur while the
|
|
** memory mutex is held do not use these mechanisms.
|
|
*/
|
|
static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){
|
|
StrAccum acc; /* String accumulator */
|
|
char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */
|
|
|
|
sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0);
|
|
sqlite3_str_vappendf(&acc, zFormat, ap);
|
|
sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode,
|
|
sqlite3StrAccumFinish(&acc));
|
|
}
|
|
|
|
/*
|
|
** Format and write a message to the log if logging is enabled.
|
|
*/
|
|
SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...){
|
|
va_list ap; /* Vararg list */
|
|
if( sqlite3GlobalConfig.xLog ){
|
|
va_start(ap, zFormat);
|
|
renderLogMsg(iErrCode, zFormat, ap);
|
|
va_end(ap);
|
|
}
|
|
}
|
|
|
|
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
|
|
/*
|
|
** 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.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){
|
|
va_list ap;
|
|
StrAccum acc;
|
|
char zBuf[SQLITE_PRINT_BUF_SIZE*10];
|
|
sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
|
|
va_start(ap,zFormat);
|
|
sqlite3_str_vappendf(&acc, zFormat, ap);
|
|
va_end(ap);
|
|
sqlite3StrAccumFinish(&acc);
|
|
#ifdef SQLITE_OS_TRACE_PROC
|
|
{
|
|
extern void SQLITE_OS_TRACE_PROC(const char *zBuf, int nBuf);
|
|
SQLITE_OS_TRACE_PROC(zBuf, sizeof(zBuf));
|
|
}
|
|
#else
|
|
fprintf(stdout,"%s", zBuf);
|
|
fflush(stdout);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
** variable-argument wrapper around sqlite3_str_vappendf(). The bFlags argument
|
|
** can contain the bit SQLITE_PRINTF_INTERNAL enable internal formats.
|
|
*/
|
|
SQLITE_API void sqlite3_str_appendf(StrAccum *p, const char *zFormat, ...){
|
|
va_list ap;
|
|
va_start(ap,zFormat);
|
|
sqlite3_str_vappendf(p, zFormat, ap);
|
|
va_end(ap);
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
** Reference counted string/blob storage
|
|
*****************************************************************************/
|
|
|
|
/*
|
|
** Increase the reference count of the string by one.
|
|
**
|
|
** The input parameter is returned.
|
|
*/
|
|
SQLITE_PRIVATE char *sqlite3RCStrRef(char *z){
|
|
RCStr *p = (RCStr*)z;
|
|
assert( p!=0 );
|
|
p--;
|
|
p->nRCRef++;
|
|
return z;
|
|
}
|
|
|
|
/*
|
|
** Decrease the reference count by one. Free the string when the
|
|
** reference count reaches zero.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3RCStrUnref(void *z){
|
|
RCStr *p = (RCStr*)z;
|
|
assert( p!=0 );
|
|
p--;
|
|
assert( p->nRCRef>0 );
|
|
if( p->nRCRef>=2 ){
|
|
p->nRCRef--;
|
|
}else{
|
|
sqlite3_free(p);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Create a new string that is capable of holding N bytes of text, not counting
|
|
** the zero byte at the end. The string is uninitialized.
|
|
**
|
|
** The reference count is initially 1. Call sqlite3RCStrUnref() to free the
|
|
** newly allocated string.
|
|
**
|
|
** This routine returns 0 on an OOM.
|
|
*/
|
|
SQLITE_PRIVATE char *sqlite3RCStrNew(u64 N){
|
|
RCStr *p = sqlite3_malloc64( N + sizeof(*p) + 1 );
|
|
if( p==0 ) return 0;
|
|
p->nRCRef = 1;
|
|
return (char*)&p[1];
|
|
}
|
|
|
|
/*
|
|
** Change the size of the string so that it is able to hold N bytes.
|
|
** The string might be reallocated, so return the new allocation.
|
|
*/
|
|
SQLITE_PRIVATE char *sqlite3RCStrResize(char *z, u64 N){
|
|
RCStr *p = (RCStr*)z;
|
|
RCStr *pNew;
|
|
assert( p!=0 );
|
|
p--;
|
|
assert( p->nRCRef==1 );
|
|
pNew = sqlite3_realloc64(p, N+sizeof(RCStr)+1);
|
|
if( pNew==0 ){
|
|
sqlite3_free(p);
|
|
return 0;
|
|
}else{
|
|
return (char*)&pNew[1];
|
|
}
|
|
}
|
|
|
|
/************** End of printf.c **********************************************/
|
|
/************** Begin file treeview.c ****************************************/
|
|
/*
|
|
** 2015-06-08
|
|
**
|
|
** 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 to implement the TreeView debugging routines.
|
|
** These routines print a parse tree to standard output for debugging and
|
|
** analysis.
|
|
**
|
|
** The interfaces in this file is only available when compiling
|
|
** with SQLITE_DEBUG.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
#ifdef SQLITE_DEBUG
|
|
|
|
/*
|
|
** Add a new subitem to the tree. The moreToFollow flag indicates that this
|
|
** is not the last item in the tree.
|
|
*/
|
|
static void sqlite3TreeViewPush(TreeView **pp, u8 moreToFollow){
|
|
TreeView *p = *pp;
|
|
if( p==0 ){
|
|
*pp = p = sqlite3_malloc64( sizeof(*p) );
|
|
if( p==0 ) return;
|
|
memset(p, 0, sizeof(*p));
|
|
}else{
|
|
p->iLevel++;
|
|
}
|
|
assert( moreToFollow==0 || moreToFollow==1 );
|
|
if( p->iLevel<(int)sizeof(p->bLine) ) p->bLine[p->iLevel] = moreToFollow;
|
|
}
|
|
|
|
/*
|
|
** Finished with one layer of the tree
|
|
*/
|
|
static void sqlite3TreeViewPop(TreeView **pp){
|
|
TreeView *p = *pp;
|
|
if( p==0 ) return;
|
|
p->iLevel--;
|
|
if( p->iLevel<0 ){
|
|
sqlite3_free(p);
|
|
*pp = 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Generate a single line of output for the tree, with a prefix that contains
|
|
** all the appropriate tree lines
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
|
|
va_list ap;
|
|
int i;
|
|
StrAccum acc;
|
|
char zBuf[1000];
|
|
sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
|
|
if( p ){
|
|
for(i=0; i<p->iLevel && i<(int)sizeof(p->bLine)-1; i++){
|
|
sqlite3_str_append(&acc, p->bLine[i] ? "| " : " ", 4);
|
|
}
|
|
sqlite3_str_append(&acc, p->bLine[i] ? "|-- " : "'-- ", 4);
|
|
}
|
|
if( zFormat!=0 ){
|
|
va_start(ap, zFormat);
|
|
sqlite3_str_vappendf(&acc, zFormat, ap);
|
|
va_end(ap);
|
|
assert( acc.nChar>0 || acc.accError );
|
|
sqlite3_str_append(&acc, "\n", 1);
|
|
}
|
|
sqlite3StrAccumFinish(&acc);
|
|
fprintf(stdout,"%s", zBuf);
|
|
fflush(stdout);
|
|
}
|
|
|
|
/*
|
|
** Shorthand for starting a new tree item that consists of a single label
|
|
*/
|
|
static void sqlite3TreeViewItem(TreeView *p, const char *zLabel,u8 moreFollows){
|
|
sqlite3TreeViewPush(&p, moreFollows);
|
|
sqlite3TreeViewLine(p, "%s", zLabel);
|
|
}
|
|
|
|
/*
|
|
** Show a list of Column objects in tree format.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3TreeViewColumnList(
|
|
TreeView *pView,
|
|
const Column *aCol,
|
|
int nCol,
|
|
u8 moreToFollow
|
|
){
|
|
int i;
|
|
sqlite3TreeViewPush(&pView, moreToFollow);
|
|
sqlite3TreeViewLine(pView, "COLUMNS");
|
|
for(i=0; i<nCol; i++){
|
|
u16 flg = aCol[i].colFlags;
|
|
int colMoreToFollow = i<(nCol - 1);
|
|
sqlite3TreeViewPush(&pView, colMoreToFollow);
|
|
sqlite3TreeViewLine(pView, 0);
|
|
printf(" %s", aCol[i].zCnName);
|
|
switch( aCol[i].eCType ){
|
|
case COLTYPE_ANY: printf(" ANY"); break;
|
|
case COLTYPE_BLOB: printf(" BLOB"); break;
|
|
case COLTYPE_INT: printf(" INT"); break;
|
|
case COLTYPE_INTEGER: printf(" INTEGER"); break;
|
|
case COLTYPE_REAL: printf(" REAL"); break;
|
|
case COLTYPE_TEXT: printf(" TEXT"); break;
|
|
case COLTYPE_CUSTOM: {
|
|
if( flg & COLFLAG_HASTYPE ){
|
|
const char *z = aCol[i].zCnName;
|
|
z += strlen(z)+1;
|
|
printf(" X-%s", z);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if( flg & COLFLAG_PRIMKEY ) printf(" PRIMARY KEY");
|
|
if( flg & COLFLAG_HIDDEN ) printf(" HIDDEN");
|
|
#ifdef COLFLAG_NOEXPAND
|
|
if( flg & COLFLAG_NOEXPAND ) printf(" NO-EXPAND");
|
|
#endif
|
|
if( flg ) printf(" flags=%04x", flg);
|
|
printf("\n");
|
|
fflush(stdout);
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
|
|
/*
|
|
** Generate a human-readable description of a WITH clause.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 moreToFollow){
|
|
int i;
|
|
if( pWith==0 ) return;
|
|
if( pWith->nCte==0 ) return;
|
|
if( pWith->pOuter ){
|
|
sqlite3TreeViewLine(pView, "WITH (0x%p, pOuter=0x%p)",pWith,pWith->pOuter);
|
|
}else{
|
|
sqlite3TreeViewLine(pView, "WITH (0x%p)", pWith);
|
|
}
|
|
if( pWith->nCte>0 ){
|
|
sqlite3TreeViewPush(&pView, moreToFollow);
|
|
for(i=0; i<pWith->nCte; i++){
|
|
StrAccum x;
|
|
char zLine[1000];
|
|
const struct Cte *pCte = &pWith->a[i];
|
|
sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
|
|
sqlite3_str_appendf(&x, "%s", pCte->zName);
|
|
if( pCte->pCols && pCte->pCols->nExpr>0 ){
|
|
char cSep = '(';
|
|
int j;
|
|
for(j=0; j<pCte->pCols->nExpr; j++){
|
|
sqlite3_str_appendf(&x, "%c%s", cSep, pCte->pCols->a[j].zEName);
|
|
cSep = ',';
|
|
}
|
|
sqlite3_str_appendf(&x, ")");
|
|
}
|
|
if( pCte->eM10d!=M10d_Any ){
|
|
sqlite3_str_appendf(&x, " %sMATERIALIZED",
|
|
pCte->eM10d==M10d_No ? "NOT " : "");
|
|
}
|
|
if( pCte->pUse ){
|
|
sqlite3_str_appendf(&x, " (pUse=0x%p, nUse=%d)", pCte->pUse,
|
|
pCte->pUse->nUse);
|
|
}
|
|
sqlite3StrAccumFinish(&x);
|
|
sqlite3TreeViewItem(pView, zLine, i<pWith->nCte-1);
|
|
sqlite3TreeViewSelect(pView, pCte->pSelect, 0);
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Generate a human-readable description of a SrcList object.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){
|
|
int i;
|
|
if( pSrc==0 ) return;
|
|
for(i=0; i<pSrc->nSrc; i++){
|
|
const SrcItem *pItem = &pSrc->a[i];
|
|
StrAccum x;
|
|
int n = 0;
|
|
char zLine[1000];
|
|
sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
|
|
x.printfFlags |= SQLITE_PRINTF_INTERNAL;
|
|
sqlite3_str_appendf(&x, "{%d:*} %!S", pItem->iCursor, pItem);
|
|
if( pItem->pTab ){
|
|
sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx",
|
|
pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab, pItem->colUsed);
|
|
}
|
|
if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))==(JT_LEFT|JT_RIGHT) ){
|
|
sqlite3_str_appendf(&x, " FULL-OUTER-JOIN");
|
|
}else if( pItem->fg.jointype & JT_LEFT ){
|
|
sqlite3_str_appendf(&x, " LEFT-JOIN");
|
|
}else if( pItem->fg.jointype & JT_RIGHT ){
|
|
sqlite3_str_appendf(&x, " RIGHT-JOIN");
|
|
}else if( pItem->fg.jointype & JT_CROSS ){
|
|
sqlite3_str_appendf(&x, " CROSS-JOIN");
|
|
}
|
|
if( pItem->fg.jointype & JT_LTORJ ){
|
|
sqlite3_str_appendf(&x, " LTORJ");
|
|
}
|
|
if( pItem->fg.fromDDL ){
|
|
sqlite3_str_appendf(&x, " DDL");
|
|
}
|
|
if( pItem->fg.isCte ){
|
|
sqlite3_str_appendf(&x, " CteUse=0x%p", pItem->u2.pCteUse);
|
|
}
|
|
if( pItem->fg.isOn || (pItem->fg.isUsing==0 && pItem->u3.pOn!=0) ){
|
|
sqlite3_str_appendf(&x, " ON");
|
|
}
|
|
if( pItem->fg.isTabFunc ) sqlite3_str_appendf(&x, " isTabFunc");
|
|
if( pItem->fg.isCorrelated ) sqlite3_str_appendf(&x, " isCorrelated");
|
|
if( pItem->fg.isMaterialized ) sqlite3_str_appendf(&x, " isMaterialized");
|
|
if( pItem->fg.viaCoroutine ) sqlite3_str_appendf(&x, " viaCoroutine");
|
|
if( pItem->fg.notCte ) sqlite3_str_appendf(&x, " notCte");
|
|
if( pItem->fg.isNestedFrom ) sqlite3_str_appendf(&x, " isNestedFrom");
|
|
|
|
sqlite3StrAccumFinish(&x);
|
|
sqlite3TreeViewItem(pView, zLine, i<pSrc->nSrc-1);
|
|
n = 0;
|
|
if( pItem->pSelect ) n++;
|
|
if( pItem->fg.isTabFunc ) n++;
|
|
if( pItem->fg.isUsing ) n++;
|
|
if( pItem->fg.isUsing ){
|
|
sqlite3TreeViewIdList(pView, pItem->u3.pUsing, (--n)>0, "USING");
|
|
}
|
|
if( pItem->pSelect ){
|
|
if( pItem->pTab ){
|
|
Table *pTab = pItem->pTab;
|
|
sqlite3TreeViewColumnList(pView, pTab->aCol, pTab->nCol, 1);
|
|
}
|
|
assert( (int)pItem->fg.isNestedFrom == IsNestedFrom(pItem->pSelect) );
|
|
sqlite3TreeViewSelect(pView, pItem->pSelect, (--n)>0);
|
|
}
|
|
if( pItem->fg.isTabFunc ){
|
|
sqlite3TreeViewExprList(pView, pItem->u1.pFuncArg, 0, "func-args:");
|
|
}
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Generate a human-readable description of a Select object.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
|
|
int n = 0;
|
|
int cnt = 0;
|
|
if( p==0 ){
|
|
sqlite3TreeViewLine(pView, "nil-SELECT");
|
|
return;
|
|
}
|
|
sqlite3TreeViewPush(&pView, moreToFollow);
|
|
if( p->pWith ){
|
|
sqlite3TreeViewWith(pView, p->pWith, 1);
|
|
cnt = 1;
|
|
sqlite3TreeViewPush(&pView, 1);
|
|
}
|
|
do{
|
|
if( p->selFlags & SF_WhereBegin ){
|
|
sqlite3TreeViewLine(pView, "sqlite3WhereBegin()");
|
|
}else{
|
|
sqlite3TreeViewLine(pView,
|
|
"SELECT%s%s (%u/%p) selFlags=0x%x nSelectRow=%d",
|
|
((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
|
|
((p->selFlags & SF_Aggregate) ? " agg_flag" : ""),
|
|
p->selId, p, p->selFlags,
|
|
(int)p->nSelectRow
|
|
);
|
|
}
|
|
if( cnt++ ) sqlite3TreeViewPop(&pView);
|
|
if( p->pPrior ){
|
|
n = 1000;
|
|
}else{
|
|
n = 0;
|
|
if( p->pSrc && p->pSrc->nSrc ) n++;
|
|
if( p->pWhere ) n++;
|
|
if( p->pGroupBy ) n++;
|
|
if( p->pHaving ) n++;
|
|
if( p->pOrderBy ) n++;
|
|
if( p->pLimit ) n++;
|
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
if( p->pWin ) n++;
|
|
if( p->pWinDefn ) n++;
|
|
#endif
|
|
}
|
|
if( p->pEList ){
|
|
sqlite3TreeViewExprList(pView, p->pEList, n>0, "result-set");
|
|
}
|
|
n--;
|
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
if( p->pWin ){
|
|
Window *pX;
|
|
sqlite3TreeViewPush(&pView, (n--)>0);
|
|
sqlite3TreeViewLine(pView, "window-functions");
|
|
for(pX=p->pWin; pX; pX=pX->pNextWin){
|
|
sqlite3TreeViewWinFunc(pView, pX, pX->pNextWin!=0);
|
|
}
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
#endif
|
|
if( p->pSrc && p->pSrc->nSrc ){
|
|
sqlite3TreeViewPush(&pView, (n--)>0);
|
|
sqlite3TreeViewLine(pView, "FROM");
|
|
sqlite3TreeViewSrcList(pView, p->pSrc);
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
if( p->pWhere ){
|
|
sqlite3TreeViewItem(pView, "WHERE", (n--)>0);
|
|
sqlite3TreeViewExpr(pView, p->pWhere, 0);
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
if( p->pGroupBy ){
|
|
sqlite3TreeViewExprList(pView, p->pGroupBy, (n--)>0, "GROUPBY");
|
|
}
|
|
if( p->pHaving ){
|
|
sqlite3TreeViewItem(pView, "HAVING", (n--)>0);
|
|
sqlite3TreeViewExpr(pView, p->pHaving, 0);
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
if( p->pWinDefn ){
|
|
Window *pX;
|
|
sqlite3TreeViewItem(pView, "WINDOW", (n--)>0);
|
|
for(pX=p->pWinDefn; pX; pX=pX->pNextWin){
|
|
sqlite3TreeViewWindow(pView, pX, pX->pNextWin!=0);
|
|
}
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
#endif
|
|
if( p->pOrderBy ){
|
|
sqlite3TreeViewExprList(pView, p->pOrderBy, (n--)>0, "ORDERBY");
|
|
}
|
|
if( p->pLimit ){
|
|
sqlite3TreeViewItem(pView, "LIMIT", (n--)>0);
|
|
sqlite3TreeViewExpr(pView, p->pLimit->pLeft, p->pLimit->pRight!=0);
|
|
if( p->pLimit->pRight ){
|
|
sqlite3TreeViewItem(pView, "OFFSET", (n--)>0);
|
|
sqlite3TreeViewExpr(pView, p->pLimit->pRight, 0);
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
if( p->pPrior ){
|
|
const char *zOp = "UNION";
|
|
switch( p->op ){
|
|
case TK_ALL: zOp = "UNION ALL"; break;
|
|
case TK_INTERSECT: zOp = "INTERSECT"; break;
|
|
case TK_EXCEPT: zOp = "EXCEPT"; break;
|
|
}
|
|
sqlite3TreeViewItem(pView, zOp, 1);
|
|
}
|
|
p = p->pPrior;
|
|
}while( p!=0 );
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
|
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
/*
|
|
** Generate a description of starting or stopping bounds
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3TreeViewBound(
|
|
TreeView *pView, /* View context */
|
|
u8 eBound, /* UNBOUNDED, CURRENT, PRECEDING, FOLLOWING */
|
|
Expr *pExpr, /* Value for PRECEDING or FOLLOWING */
|
|
u8 moreToFollow /* True if more to follow */
|
|
){
|
|
switch( eBound ){
|
|
case TK_UNBOUNDED: {
|
|
sqlite3TreeViewItem(pView, "UNBOUNDED", moreToFollow);
|
|
sqlite3TreeViewPop(&pView);
|
|
break;
|
|
}
|
|
case TK_CURRENT: {
|
|
sqlite3TreeViewItem(pView, "CURRENT", moreToFollow);
|
|
sqlite3TreeViewPop(&pView);
|
|
break;
|
|
}
|
|
case TK_PRECEDING: {
|
|
sqlite3TreeViewItem(pView, "PRECEDING", moreToFollow);
|
|
sqlite3TreeViewExpr(pView, pExpr, 0);
|
|
sqlite3TreeViewPop(&pView);
|
|
break;
|
|
}
|
|
case TK_FOLLOWING: {
|
|
sqlite3TreeViewItem(pView, "FOLLOWING", moreToFollow);
|
|
sqlite3TreeViewExpr(pView, pExpr, 0);
|
|
sqlite3TreeViewPop(&pView);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif /* SQLITE_OMIT_WINDOWFUNC */
|
|
|
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
/*
|
|
** Generate a human-readable explanation for a Window object
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3TreeViewWindow(TreeView *pView, const Window *pWin, u8 more){
|
|
int nElement = 0;
|
|
if( pWin==0 ) return;
|
|
if( pWin->pFilter ){
|
|
sqlite3TreeViewItem(pView, "FILTER", 1);
|
|
sqlite3TreeViewExpr(pView, pWin->pFilter, 0);
|
|
sqlite3TreeViewPop(&pView);
|
|
if( pWin->eFrmType==TK_FILTER ) return;
|
|
}
|
|
sqlite3TreeViewPush(&pView, more);
|
|
if( pWin->zName ){
|
|
sqlite3TreeViewLine(pView, "OVER %s (%p)", pWin->zName, pWin);
|
|
}else{
|
|
sqlite3TreeViewLine(pView, "OVER (%p)", pWin);
|
|
}
|
|
if( pWin->zBase ) nElement++;
|
|
if( pWin->pOrderBy ) nElement++;
|
|
if( pWin->eFrmType!=0 && pWin->eFrmType!=TK_FILTER ) nElement++;
|
|
if( pWin->eExclude ) nElement++;
|
|
if( pWin->zBase ){
|
|
sqlite3TreeViewPush(&pView, (--nElement)>0);
|
|
sqlite3TreeViewLine(pView, "window: %s", pWin->zBase);
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
if( pWin->pPartition ){
|
|
sqlite3TreeViewExprList(pView, pWin->pPartition, nElement>0,"PARTITION-BY");
|
|
}
|
|
if( pWin->pOrderBy ){
|
|
sqlite3TreeViewExprList(pView, pWin->pOrderBy, (--nElement)>0, "ORDER-BY");
|
|
}
|
|
if( pWin->eFrmType!=0 && pWin->eFrmType!=TK_FILTER ){
|
|
char zBuf[30];
|
|
const char *zFrmType = "ROWS";
|
|
if( pWin->eFrmType==TK_RANGE ) zFrmType = "RANGE";
|
|
if( pWin->eFrmType==TK_GROUPS ) zFrmType = "GROUPS";
|
|
sqlite3_snprintf(sizeof(zBuf),zBuf,"%s%s",zFrmType,
|
|
pWin->bImplicitFrame ? " (implied)" : "");
|
|
sqlite3TreeViewItem(pView, zBuf, (--nElement)>0);
|
|
sqlite3TreeViewBound(pView, pWin->eStart, pWin->pStart, 1);
|
|
sqlite3TreeViewBound(pView, pWin->eEnd, pWin->pEnd, 0);
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
if( pWin->eExclude ){
|
|
char zBuf[30];
|
|
const char *zExclude;
|
|
switch( pWin->eExclude ){
|
|
case TK_NO: zExclude = "NO OTHERS"; break;
|
|
case TK_CURRENT: zExclude = "CURRENT ROW"; break;
|
|
case TK_GROUP: zExclude = "GROUP"; break;
|
|
case TK_TIES: zExclude = "TIES"; break;
|
|
default:
|
|
sqlite3_snprintf(sizeof(zBuf),zBuf,"invalid(%d)", pWin->eExclude);
|
|
zExclude = zBuf;
|
|
break;
|
|
}
|
|
sqlite3TreeViewPush(&pView, 0);
|
|
sqlite3TreeViewLine(pView, "EXCLUDE %s", zExclude);
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
#endif /* SQLITE_OMIT_WINDOWFUNC */
|
|
|
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
/*
|
|
** Generate a human-readable explanation for a Window Function object
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3TreeViewWinFunc(TreeView *pView, const Window *pWin, u8 more){
|
|
if( pWin==0 ) return;
|
|
sqlite3TreeViewPush(&pView, more);
|
|
sqlite3TreeViewLine(pView, "WINFUNC %s(%d)",
|
|
pWin->pWFunc->zName, pWin->pWFunc->nArg);
|
|
sqlite3TreeViewWindow(pView, pWin, 0);
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
#endif /* SQLITE_OMIT_WINDOWFUNC */
|
|
|
|
/*
|
|
** Generate a human-readable explanation of an expression tree.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
|
|
const char *zBinOp = 0; /* Binary operator */
|
|
const char *zUniOp = 0; /* Unary operator */
|
|
char zFlgs[200];
|
|
sqlite3TreeViewPush(&pView, moreToFollow);
|
|
if( pExpr==0 ){
|
|
sqlite3TreeViewLine(pView, "nil");
|
|
sqlite3TreeViewPop(&pView);
|
|
return;
|
|
}
|
|
if( pExpr->flags || pExpr->affExpr || pExpr->vvaFlags || pExpr->pAggInfo ){
|
|
StrAccum x;
|
|
sqlite3StrAccumInit(&x, 0, zFlgs, sizeof(zFlgs), 0);
|
|
sqlite3_str_appendf(&x, " fg.af=%x.%c",
|
|
pExpr->flags, pExpr->affExpr ? pExpr->affExpr : 'n');
|
|
if( ExprHasProperty(pExpr, EP_OuterON) ){
|
|
sqlite3_str_appendf(&x, " outer.iJoin=%d", pExpr->w.iJoin);
|
|
}
|
|
if( ExprHasProperty(pExpr, EP_InnerON) ){
|
|
sqlite3_str_appendf(&x, " inner.iJoin=%d", pExpr->w.iJoin);
|
|
}
|
|
if( ExprHasProperty(pExpr, EP_FromDDL) ){
|
|
sqlite3_str_appendf(&x, " DDL");
|
|
}
|
|
if( ExprHasVVAProperty(pExpr, EP_Immutable) ){
|
|
sqlite3_str_appendf(&x, " IMMUTABLE");
|
|
}
|
|
if( pExpr->pAggInfo!=0 ){
|
|
sqlite3_str_appendf(&x, " agg-column[%d]", pExpr->iAgg);
|
|
}
|
|
sqlite3StrAccumFinish(&x);
|
|
}else{
|
|
zFlgs[0] = 0;
|
|
}
|
|
switch( pExpr->op ){
|
|
case TK_AGG_COLUMN: {
|
|
sqlite3TreeViewLine(pView, "AGG{%d:%d}%s",
|
|
pExpr->iTable, pExpr->iColumn, zFlgs);
|
|
break;
|
|
}
|
|
case TK_COLUMN: {
|
|
if( pExpr->iTable<0 ){
|
|
/* This only happens when coding check constraints */
|
|
char zOp2[16];
|
|
if( pExpr->op2 ){
|
|
sqlite3_snprintf(sizeof(zOp2),zOp2," op2=0x%02x",pExpr->op2);
|
|
}else{
|
|
zOp2[0] = 0;
|
|
}
|
|
sqlite3TreeViewLine(pView, "COLUMN(%d)%s%s",
|
|
pExpr->iColumn, zFlgs, zOp2);
|
|
}else{
|
|
assert( ExprUseYTab(pExpr) );
|
|
sqlite3TreeViewLine(pView, "{%d:%d} pTab=%p%s",
|
|
pExpr->iTable, pExpr->iColumn,
|
|
pExpr->y.pTab, zFlgs);
|
|
}
|
|
if( ExprHasProperty(pExpr, EP_FixedCol) ){
|
|
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
|
|
}
|
|
break;
|
|
}
|
|
case TK_INTEGER: {
|
|
if( pExpr->flags & EP_IntValue ){
|
|
sqlite3TreeViewLine(pView, "%d", pExpr->u.iValue);
|
|
}else{
|
|
sqlite3TreeViewLine(pView, "%s", pExpr->u.zToken);
|
|
}
|
|
break;
|
|
}
|
|
#ifndef SQLITE_OMIT_FLOATING_POINT
|
|
case TK_FLOAT: {
|
|
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
|
sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
|
|
break;
|
|
}
|
|
#endif
|
|
case TK_STRING: {
|
|
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
|
sqlite3TreeViewLine(pView,"%Q", pExpr->u.zToken);
|
|
break;
|
|
}
|
|
case TK_NULL: {
|
|
sqlite3TreeViewLine(pView,"NULL");
|
|
break;
|
|
}
|
|
case TK_TRUEFALSE: {
|
|
sqlite3TreeViewLine(pView,"%s%s",
|
|
sqlite3ExprTruthValue(pExpr) ? "TRUE" : "FALSE", zFlgs);
|
|
break;
|
|
}
|
|
#ifndef SQLITE_OMIT_BLOB_LITERAL
|
|
case TK_BLOB: {
|
|
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
|
sqlite3TreeViewLine(pView,"%s", pExpr->u.zToken);
|
|
break;
|
|
}
|
|
#endif
|
|
case TK_VARIABLE: {
|
|
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
|
sqlite3TreeViewLine(pView,"VARIABLE(%s,%d)",
|
|
pExpr->u.zToken, pExpr->iColumn);
|
|
break;
|
|
}
|
|
case TK_REGISTER: {
|
|
sqlite3TreeViewLine(pView,"REGISTER(%d)", pExpr->iTable);
|
|
break;
|
|
}
|
|
case TK_ID: {
|
|
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
|
sqlite3TreeViewLine(pView,"ID \"%w\"", pExpr->u.zToken);
|
|
break;
|
|
}
|
|
#ifndef SQLITE_OMIT_CAST
|
|
case TK_CAST: {
|
|
/* Expressions of the form: CAST(pLeft AS token) */
|
|
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
|
sqlite3TreeViewLine(pView,"CAST %Q", pExpr->u.zToken);
|
|
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
|
|
break;
|
|
}
|
|
#endif /* SQLITE_OMIT_CAST */
|
|
case TK_LT: zBinOp = "LT"; break;
|
|
case TK_LE: zBinOp = "LE"; break;
|
|
case TK_GT: zBinOp = "GT"; break;
|
|
case TK_GE: zBinOp = "GE"; break;
|
|
case TK_NE: zBinOp = "NE"; break;
|
|
case TK_EQ: zBinOp = "EQ"; break;
|
|
case TK_IS: zBinOp = "IS"; break;
|
|
case TK_ISNOT: zBinOp = "ISNOT"; break;
|
|
case TK_AND: zBinOp = "AND"; break;
|
|
case TK_OR: zBinOp = "OR"; break;
|
|
case TK_PLUS: zBinOp = "ADD"; break;
|
|
case TK_STAR: zBinOp = "MUL"; break;
|
|
case TK_MINUS: zBinOp = "SUB"; break;
|
|
case TK_REM: zBinOp = "REM"; break;
|
|
case TK_BITAND: zBinOp = "BITAND"; break;
|
|
case TK_BITOR: zBinOp = "BITOR"; break;
|
|
case TK_SLASH: zBinOp = "DIV"; break;
|
|
case TK_LSHIFT: zBinOp = "LSHIFT"; break;
|
|
case TK_RSHIFT: zBinOp = "RSHIFT"; break;
|
|
case TK_CONCAT: zBinOp = "CONCAT"; break;
|
|
case TK_DOT: zBinOp = "DOT"; break;
|
|
case TK_LIMIT: zBinOp = "LIMIT"; break;
|
|
|
|
case TK_UMINUS: zUniOp = "UMINUS"; break;
|
|
case TK_UPLUS: zUniOp = "UPLUS"; break;
|
|
case TK_BITNOT: zUniOp = "BITNOT"; break;
|
|
case TK_NOT: zUniOp = "NOT"; break;
|
|
case TK_ISNULL: zUniOp = "ISNULL"; break;
|
|
case TK_NOTNULL: zUniOp = "NOTNULL"; break;
|
|
|
|
case TK_TRUTH: {
|
|
int x;
|
|
const char *azOp[] = {
|
|
"IS-FALSE", "IS-TRUE", "IS-NOT-FALSE", "IS-NOT-TRUE"
|
|
};
|
|
assert( pExpr->op2==TK_IS || pExpr->op2==TK_ISNOT );
|
|
assert( pExpr->pRight );
|
|
assert( sqlite3ExprSkipCollateAndLikely(pExpr->pRight)->op
|
|
== TK_TRUEFALSE );
|
|
x = (pExpr->op2==TK_ISNOT)*2 + sqlite3ExprTruthValue(pExpr->pRight);
|
|
zUniOp = azOp[x];
|
|
break;
|
|
}
|
|
|
|
case TK_SPAN: {
|
|
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
|
sqlite3TreeViewLine(pView, "SPAN %Q", pExpr->u.zToken);
|
|
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
|
|
break;
|
|
}
|
|
|
|
case TK_COLLATE: {
|
|
/* COLLATE operators without the EP_Collate flag are intended to
|
|
** emulate collation associated with a table column. These show
|
|
** up in the treeview output as "SOFT-COLLATE". Explicit COLLATE
|
|
** operators that appear in the original SQL always have the
|
|
** EP_Collate bit set and appear in treeview output as just "COLLATE" */
|
|
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
|
sqlite3TreeViewLine(pView, "%sCOLLATE %Q%s",
|
|
!ExprHasProperty(pExpr, EP_Collate) ? "SOFT-" : "",
|
|
pExpr->u.zToken, zFlgs);
|
|
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
|
|
break;
|
|
}
|
|
|
|
case TK_AGG_FUNCTION:
|
|
case TK_FUNCTION: {
|
|
ExprList *pFarg; /* List of function arguments */
|
|
Window *pWin;
|
|
if( ExprHasProperty(pExpr, EP_TokenOnly) ){
|
|
pFarg = 0;
|
|
pWin = 0;
|
|
}else{
|
|
assert( ExprUseXList(pExpr) );
|
|
pFarg = pExpr->x.pList;
|
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
pWin = IsWindowFunc(pExpr) ? pExpr->y.pWin : 0;
|
|
#else
|
|
pWin = 0;
|
|
#endif
|
|
}
|
|
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
|
if( pExpr->op==TK_AGG_FUNCTION ){
|
|
sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q%s agg=%d[%d]/%p",
|
|
pExpr->op2, pExpr->u.zToken, zFlgs,
|
|
pExpr->pAggInfo ? pExpr->pAggInfo->selId : 0,
|
|
pExpr->iAgg, pExpr->pAggInfo);
|
|
}else if( pExpr->op2!=0 ){
|
|
const char *zOp2;
|
|
char zBuf[8];
|
|
sqlite3_snprintf(sizeof(zBuf),zBuf,"0x%02x",pExpr->op2);
|
|
zOp2 = zBuf;
|
|
if( pExpr->op2==NC_IsCheck ) zOp2 = "NC_IsCheck";
|
|
if( pExpr->op2==NC_IdxExpr ) zOp2 = "NC_IdxExpr";
|
|
if( pExpr->op2==NC_PartIdx ) zOp2 = "NC_PartIdx";
|
|
if( pExpr->op2==NC_GenCol ) zOp2 = "NC_GenCol";
|
|
sqlite3TreeViewLine(pView, "FUNCTION %Q%s op2=%s",
|
|
pExpr->u.zToken, zFlgs, zOp2);
|
|
}else{
|
|
sqlite3TreeViewLine(pView, "FUNCTION %Q%s", pExpr->u.zToken, zFlgs);
|
|
}
|
|
if( pFarg ){
|
|
sqlite3TreeViewExprList(pView, pFarg, pWin!=0 || pExpr->pLeft, 0);
|
|
if( pExpr->pLeft ){
|
|
Expr *pOB = pExpr->pLeft;
|
|
assert( pOB->op==TK_ORDER );
|
|
assert( ExprUseXList(pOB) );
|
|
sqlite3TreeViewExprList(pView, pOB->x.pList, pWin!=0, "ORDERBY");
|
|
}
|
|
}
|
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
if( pWin ){
|
|
sqlite3TreeViewWindow(pView, pWin, 0);
|
|
}
|
|
#endif
|
|
break;
|
|
}
|
|
case TK_ORDER: {
|
|
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, "ORDERBY");
|
|
break;
|
|
}
|
|
#ifndef SQLITE_OMIT_SUBQUERY
|
|
case TK_EXISTS: {
|
|
assert( ExprUseXSelect(pExpr) );
|
|
sqlite3TreeViewLine(pView, "EXISTS-expr flags=0x%x", pExpr->flags);
|
|
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
|
|
break;
|
|
}
|
|
case TK_SELECT: {
|
|
assert( ExprUseXSelect(pExpr) );
|
|
sqlite3TreeViewLine(pView, "subquery-expr flags=0x%x", pExpr->flags);
|
|
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
|
|
break;
|
|
}
|
|
case TK_IN: {
|
|
sqlite3_str *pStr = sqlite3_str_new(0);
|
|
char *z;
|
|
sqlite3_str_appendf(pStr, "IN flags=0x%x", pExpr->flags);
|
|
if( pExpr->iTable ) sqlite3_str_appendf(pStr, " iTable=%d",pExpr->iTable);
|
|
if( ExprHasProperty(pExpr, EP_Subrtn) ){
|
|
sqlite3_str_appendf(pStr, " subrtn(%d,%d)",
|
|
pExpr->y.sub.regReturn, pExpr->y.sub.iAddr);
|
|
}
|
|
z = sqlite3_str_finish(pStr);
|
|
sqlite3TreeViewLine(pView, z);
|
|
sqlite3_free(z);
|
|
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
|
|
if( ExprUseXSelect(pExpr) ){
|
|
sqlite3TreeViewSelect(pView, pExpr->x.pSelect, 0);
|
|
}else{
|
|
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
|
|
}
|
|
break;
|
|
}
|
|
#endif /* SQLITE_OMIT_SUBQUERY */
|
|
|
|
/*
|
|
** x BETWEEN y AND z
|
|
**
|
|
** This is equivalent to
|
|
**
|
|
** x>=y AND x<=z
|
|
**
|
|
** X is stored in pExpr->pLeft.
|
|
** Y is stored in pExpr->pList->a[0].pExpr.
|
|
** Z is stored in pExpr->pList->a[1].pExpr.
|
|
*/
|
|
case TK_BETWEEN: {
|
|
const Expr *pX, *pY, *pZ;
|
|
pX = pExpr->pLeft;
|
|
assert( ExprUseXList(pExpr) );
|
|
assert( pExpr->x.pList->nExpr==2 );
|
|
pY = pExpr->x.pList->a[0].pExpr;
|
|
pZ = pExpr->x.pList->a[1].pExpr;
|
|
sqlite3TreeViewLine(pView, "BETWEEN%s", zFlgs);
|
|
sqlite3TreeViewExpr(pView, pX, 1);
|
|
sqlite3TreeViewExpr(pView, pY, 1);
|
|
sqlite3TreeViewExpr(pView, pZ, 0);
|
|
break;
|
|
}
|
|
case TK_TRIGGER: {
|
|
/* If the opcode is TK_TRIGGER, then the expression is a reference
|
|
** to a column in the new.* or old.* pseudo-tables available to
|
|
** trigger programs. In this case Expr.iTable is set to 1 for the
|
|
** new.* pseudo-table, or 0 for the old.* pseudo-table. Expr.iColumn
|
|
** is set to the column of the pseudo-table to read, or to -1 to
|
|
** read the rowid field.
|
|
*/
|
|
sqlite3TreeViewLine(pView, "%s(%d)",
|
|
pExpr->iTable ? "NEW" : "OLD", pExpr->iColumn);
|
|
break;
|
|
}
|
|
case TK_CASE: {
|
|
sqlite3TreeViewLine(pView, "CASE");
|
|
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
|
|
assert( ExprUseXList(pExpr) );
|
|
sqlite3TreeViewExprList(pView, pExpr->x.pList, 0, 0);
|
|
break;
|
|
}
|
|
#ifndef SQLITE_OMIT_TRIGGER
|
|
case TK_RAISE: {
|
|
const char *zType = "unk";
|
|
switch( pExpr->affExpr ){
|
|
case OE_Rollback: zType = "rollback"; break;
|
|
case OE_Abort: zType = "abort"; break;
|
|
case OE_Fail: zType = "fail"; break;
|
|
case OE_Ignore: zType = "ignore"; break;
|
|
}
|
|
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
|
sqlite3TreeViewLine(pView, "RAISE %s(%Q)", zType, pExpr->u.zToken);
|
|
break;
|
|
}
|
|
#endif
|
|
case TK_MATCH: {
|
|
sqlite3TreeViewLine(pView, "MATCH {%d:%d}%s",
|
|
pExpr->iTable, pExpr->iColumn, zFlgs);
|
|
sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
|
|
break;
|
|
}
|
|
case TK_VECTOR: {
|
|
char *z = sqlite3_mprintf("VECTOR%s",zFlgs);
|
|
assert( ExprUseXList(pExpr) );
|
|
sqlite3TreeViewBareExprList(pView, pExpr->x.pList, z);
|
|
sqlite3_free(z);
|
|
break;
|
|
}
|
|
case TK_SELECT_COLUMN: {
|
|
sqlite3TreeViewLine(pView, "SELECT-COLUMN %d of [0..%d]%s",
|
|
pExpr->iColumn, pExpr->iTable-1,
|
|
pExpr->pRight==pExpr->pLeft ? " (SELECT-owner)" : "");
|
|
assert( ExprUseXSelect(pExpr->pLeft) );
|
|
sqlite3TreeViewSelect(pView, pExpr->pLeft->x.pSelect, 0);
|
|
break;
|
|
}
|
|
case TK_IF_NULL_ROW: {
|
|
sqlite3TreeViewLine(pView, "IF-NULL-ROW %d", pExpr->iTable);
|
|
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
|
|
break;
|
|
}
|
|
case TK_ERROR: {
|
|
Expr tmp;
|
|
sqlite3TreeViewLine(pView, "ERROR");
|
|
tmp = *pExpr;
|
|
tmp.op = pExpr->op2;
|
|
sqlite3TreeViewExpr(pView, &tmp, 0);
|
|
break;
|
|
}
|
|
case TK_ROW: {
|
|
if( pExpr->iColumn<=0 ){
|
|
sqlite3TreeViewLine(pView, "First FROM table rowid");
|
|
}else{
|
|
sqlite3TreeViewLine(pView, "First FROM table column %d",
|
|
pExpr->iColumn-1);
|
|
}
|
|
break;
|
|
}
|
|
default: {
|
|
sqlite3TreeViewLine(pView, "op=%d", pExpr->op);
|
|
break;
|
|
}
|
|
}
|
|
if( zBinOp ){
|
|
sqlite3TreeViewLine(pView, "%s%s", zBinOp, zFlgs);
|
|
sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
|
|
sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
|
|
}else if( zUniOp ){
|
|
sqlite3TreeViewLine(pView, "%s%s", zUniOp, zFlgs);
|
|
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
|
|
}
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
|
|
|
|
/*
|
|
** Generate a human-readable explanation of an expression list.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3TreeViewBareExprList(
|
|
TreeView *pView,
|
|
const ExprList *pList,
|
|
const char *zLabel
|
|
){
|
|
if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST";
|
|
if( pList==0 ){
|
|
sqlite3TreeViewLine(pView, "%s (empty)", zLabel);
|
|
}else{
|
|
int i;
|
|
sqlite3TreeViewLine(pView, "%s", zLabel);
|
|
for(i=0; i<pList->nExpr; i++){
|
|
int j = pList->a[i].u.x.iOrderByCol;
|
|
char *zName = pList->a[i].zEName;
|
|
int moreToFollow = i<pList->nExpr - 1;
|
|
if( j || zName ){
|
|
sqlite3TreeViewPush(&pView, moreToFollow);
|
|
moreToFollow = 0;
|
|
sqlite3TreeViewLine(pView, 0);
|
|
if( zName ){
|
|
switch( pList->a[i].fg.eEName ){
|
|
default:
|
|
fprintf(stdout, "AS %s ", zName);
|
|
break;
|
|
case ENAME_TAB:
|
|
fprintf(stdout, "TABLE-ALIAS-NAME(\"%s\") ", zName);
|
|
if( pList->a[i].fg.bUsed ) fprintf(stdout, "(used) ");
|
|
if( pList->a[i].fg.bUsingTerm ) fprintf(stdout, "(USING-term) ");
|
|
if( pList->a[i].fg.bNoExpand ) fprintf(stdout, "(NoExpand) ");
|
|
break;
|
|
case ENAME_SPAN:
|
|
fprintf(stdout, "SPAN(\"%s\") ", zName);
|
|
break;
|
|
}
|
|
}
|
|
if( j ){
|
|
fprintf(stdout, "iOrderByCol=%d", j);
|
|
}
|
|
fprintf(stdout, "\n");
|
|
fflush(stdout);
|
|
}
|
|
sqlite3TreeViewExpr(pView, pList->a[i].pExpr, moreToFollow);
|
|
if( j || zName ){
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
SQLITE_PRIVATE void sqlite3TreeViewExprList(
|
|
TreeView *pView,
|
|
const ExprList *pList,
|
|
u8 moreToFollow,
|
|
const char *zLabel
|
|
){
|
|
sqlite3TreeViewPush(&pView, moreToFollow);
|
|
sqlite3TreeViewBareExprList(pView, pList, zLabel);
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
|
|
/*
|
|
** Generate a human-readable explanation of an id-list.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3TreeViewBareIdList(
|
|
TreeView *pView,
|
|
const IdList *pList,
|
|
const char *zLabel
|
|
){
|
|
if( zLabel==0 || zLabel[0]==0 ) zLabel = "LIST";
|
|
if( pList==0 ){
|
|
sqlite3TreeViewLine(pView, "%s (empty)", zLabel);
|
|
}else{
|
|
int i;
|
|
sqlite3TreeViewLine(pView, "%s", zLabel);
|
|
for(i=0; i<pList->nId; i++){
|
|
char *zName = pList->a[i].zName;
|
|
int moreToFollow = i<pList->nId - 1;
|
|
if( zName==0 ) zName = "(null)";
|
|
sqlite3TreeViewPush(&pView, moreToFollow);
|
|
sqlite3TreeViewLine(pView, 0);
|
|
if( pList->eU4==EU4_NONE ){
|
|
fprintf(stdout, "%s\n", zName);
|
|
}else if( pList->eU4==EU4_IDX ){
|
|
fprintf(stdout, "%s (%d)\n", zName, pList->a[i].u4.idx);
|
|
}else{
|
|
assert( pList->eU4==EU4_EXPR );
|
|
if( pList->a[i].u4.pExpr==0 ){
|
|
fprintf(stdout, "%s (pExpr=NULL)\n", zName);
|
|
}else{
|
|
fprintf(stdout, "%s\n", zName);
|
|
sqlite3TreeViewPush(&pView, i<pList->nId-1);
|
|
sqlite3TreeViewExpr(pView, pList->a[i].u4.pExpr, 0);
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
}
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
}
|
|
}
|
|
SQLITE_PRIVATE void sqlite3TreeViewIdList(
|
|
TreeView *pView,
|
|
const IdList *pList,
|
|
u8 moreToFollow,
|
|
const char *zLabel
|
|
){
|
|
sqlite3TreeViewPush(&pView, moreToFollow);
|
|
sqlite3TreeViewBareIdList(pView, pList, zLabel);
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
|
|
/*
|
|
** Generate a human-readable explanation of a list of Upsert objects
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3TreeViewUpsert(
|
|
TreeView *pView,
|
|
const Upsert *pUpsert,
|
|
u8 moreToFollow
|
|
){
|
|
if( pUpsert==0 ) return;
|
|
sqlite3TreeViewPush(&pView, moreToFollow);
|
|
while( pUpsert ){
|
|
int n;
|
|
sqlite3TreeViewPush(&pView, pUpsert->pNextUpsert!=0 || moreToFollow);
|
|
sqlite3TreeViewLine(pView, "ON CONFLICT DO %s",
|
|
pUpsert->isDoUpdate ? "UPDATE" : "NOTHING");
|
|
n = (pUpsert->pUpsertSet!=0) + (pUpsert->pUpsertWhere!=0);
|
|
sqlite3TreeViewExprList(pView, pUpsert->pUpsertTarget, (n--)>0, "TARGET");
|
|
sqlite3TreeViewExprList(pView, pUpsert->pUpsertSet, (n--)>0, "SET");
|
|
if( pUpsert->pUpsertWhere ){
|
|
sqlite3TreeViewItem(pView, "WHERE", (n--)>0);
|
|
sqlite3TreeViewExpr(pView, pUpsert->pUpsertWhere, 0);
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
sqlite3TreeViewPop(&pView);
|
|
pUpsert = pUpsert->pNextUpsert;
|
|
}
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
|
|
#if TREETRACE_ENABLED
|
|
/*
|
|
** Generate a human-readable diagram of the data structure that go
|
|
** into generating an DELETE statement.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3TreeViewDelete(
|
|
const With *pWith,
|
|
const SrcList *pTabList,
|
|
const Expr *pWhere,
|
|
const ExprList *pOrderBy,
|
|
const Expr *pLimit,
|
|
const Trigger *pTrigger
|
|
){
|
|
int n = 0;
|
|
TreeView *pView = 0;
|
|
sqlite3TreeViewPush(&pView, 0);
|
|
sqlite3TreeViewLine(pView, "DELETE");
|
|
if( pWith ) n++;
|
|
if( pTabList ) n++;
|
|
if( pWhere ) n++;
|
|
if( pOrderBy ) n++;
|
|
if( pLimit ) n++;
|
|
if( pTrigger ) n++;
|
|
if( pWith ){
|
|
sqlite3TreeViewPush(&pView, (--n)>0);
|
|
sqlite3TreeViewWith(pView, pWith, 0);
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
if( pTabList ){
|
|
sqlite3TreeViewPush(&pView, (--n)>0);
|
|
sqlite3TreeViewLine(pView, "FROM");
|
|
sqlite3TreeViewSrcList(pView, pTabList);
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
if( pWhere ){
|
|
sqlite3TreeViewPush(&pView, (--n)>0);
|
|
sqlite3TreeViewLine(pView, "WHERE");
|
|
sqlite3TreeViewExpr(pView, pWhere, 0);
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
if( pOrderBy ){
|
|
sqlite3TreeViewExprList(pView, pOrderBy, (--n)>0, "ORDER-BY");
|
|
}
|
|
if( pLimit ){
|
|
sqlite3TreeViewPush(&pView, (--n)>0);
|
|
sqlite3TreeViewLine(pView, "LIMIT");
|
|
sqlite3TreeViewExpr(pView, pLimit, 0);
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
if( pTrigger ){
|
|
sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1);
|
|
}
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
#endif /* TREETRACE_ENABLED */
|
|
|
|
#if TREETRACE_ENABLED
|
|
/*
|
|
** Generate a human-readable diagram of the data structure that go
|
|
** into generating an INSERT statement.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3TreeViewInsert(
|
|
const With *pWith,
|
|
const SrcList *pTabList,
|
|
const IdList *pColumnList,
|
|
const Select *pSelect,
|
|
const ExprList *pExprList,
|
|
int onError,
|
|
const Upsert *pUpsert,
|
|
const Trigger *pTrigger
|
|
){
|
|
TreeView *pView = 0;
|
|
int n = 0;
|
|
const char *zLabel = "INSERT";
|
|
switch( onError ){
|
|
case OE_Replace: zLabel = "REPLACE"; break;
|
|
case OE_Ignore: zLabel = "INSERT OR IGNORE"; break;
|
|
case OE_Rollback: zLabel = "INSERT OR ROLLBACK"; break;
|
|
case OE_Abort: zLabel = "INSERT OR ABORT"; break;
|
|
case OE_Fail: zLabel = "INSERT OR FAIL"; break;
|
|
}
|
|
sqlite3TreeViewPush(&pView, 0);
|
|
sqlite3TreeViewLine(pView, zLabel);
|
|
if( pWith ) n++;
|
|
if( pTabList ) n++;
|
|
if( pColumnList ) n++;
|
|
if( pSelect ) n++;
|
|
if( pExprList ) n++;
|
|
if( pUpsert ) n++;
|
|
if( pTrigger ) n++;
|
|
if( pWith ){
|
|
sqlite3TreeViewPush(&pView, (--n)>0);
|
|
sqlite3TreeViewWith(pView, pWith, 0);
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
if( pTabList ){
|
|
sqlite3TreeViewPush(&pView, (--n)>0);
|
|
sqlite3TreeViewLine(pView, "INTO");
|
|
sqlite3TreeViewSrcList(pView, pTabList);
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
if( pColumnList ){
|
|
sqlite3TreeViewIdList(pView, pColumnList, (--n)>0, "COLUMNS");
|
|
}
|
|
if( pSelect ){
|
|
sqlite3TreeViewPush(&pView, (--n)>0);
|
|
sqlite3TreeViewLine(pView, "DATA-SOURCE");
|
|
sqlite3TreeViewSelect(pView, pSelect, 0);
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
if( pExprList ){
|
|
sqlite3TreeViewExprList(pView, pExprList, (--n)>0, "VALUES");
|
|
}
|
|
if( pUpsert ){
|
|
sqlite3TreeViewPush(&pView, (--n)>0);
|
|
sqlite3TreeViewLine(pView, "UPSERT");
|
|
sqlite3TreeViewUpsert(pView, pUpsert, 0);
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
if( pTrigger ){
|
|
sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1);
|
|
}
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
#endif /* TREETRACE_ENABLED */
|
|
|
|
#if TREETRACE_ENABLED
|
|
/*
|
|
** Generate a human-readable diagram of the data structure that go
|
|
** into generating an UPDATE statement.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3TreeViewUpdate(
|
|
const With *pWith,
|
|
const SrcList *pTabList,
|
|
const ExprList *pChanges,
|
|
const Expr *pWhere,
|
|
int onError,
|
|
const ExprList *pOrderBy,
|
|
const Expr *pLimit,
|
|
const Upsert *pUpsert,
|
|
const Trigger *pTrigger
|
|
){
|
|
int n = 0;
|
|
TreeView *pView = 0;
|
|
const char *zLabel = "UPDATE";
|
|
switch( onError ){
|
|
case OE_Replace: zLabel = "UPDATE OR REPLACE"; break;
|
|
case OE_Ignore: zLabel = "UPDATE OR IGNORE"; break;
|
|
case OE_Rollback: zLabel = "UPDATE OR ROLLBACK"; break;
|
|
case OE_Abort: zLabel = "UPDATE OR ABORT"; break;
|
|
case OE_Fail: zLabel = "UPDATE OR FAIL"; break;
|
|
}
|
|
sqlite3TreeViewPush(&pView, 0);
|
|
sqlite3TreeViewLine(pView, zLabel);
|
|
if( pWith ) n++;
|
|
if( pTabList ) n++;
|
|
if( pChanges ) n++;
|
|
if( pWhere ) n++;
|
|
if( pOrderBy ) n++;
|
|
if( pLimit ) n++;
|
|
if( pUpsert ) n++;
|
|
if( pTrigger ) n++;
|
|
if( pWith ){
|
|
sqlite3TreeViewPush(&pView, (--n)>0);
|
|
sqlite3TreeViewWith(pView, pWith, 0);
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
if( pTabList ){
|
|
sqlite3TreeViewPush(&pView, (--n)>0);
|
|
sqlite3TreeViewLine(pView, "FROM");
|
|
sqlite3TreeViewSrcList(pView, pTabList);
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
if( pChanges ){
|
|
sqlite3TreeViewExprList(pView, pChanges, (--n)>0, "SET");
|
|
}
|
|
if( pWhere ){
|
|
sqlite3TreeViewPush(&pView, (--n)>0);
|
|
sqlite3TreeViewLine(pView, "WHERE");
|
|
sqlite3TreeViewExpr(pView, pWhere, 0);
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
if( pOrderBy ){
|
|
sqlite3TreeViewExprList(pView, pOrderBy, (--n)>0, "ORDER-BY");
|
|
}
|
|
if( pLimit ){
|
|
sqlite3TreeViewPush(&pView, (--n)>0);
|
|
sqlite3TreeViewLine(pView, "LIMIT");
|
|
sqlite3TreeViewExpr(pView, pLimit, 0);
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
if( pUpsert ){
|
|
sqlite3TreeViewPush(&pView, (--n)>0);
|
|
sqlite3TreeViewLine(pView, "UPSERT");
|
|
sqlite3TreeViewUpsert(pView, pUpsert, 0);
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
if( pTrigger ){
|
|
sqlite3TreeViewTrigger(pView, pTrigger, (--n)>0, 1);
|
|
}
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
#endif /* TREETRACE_ENABLED */
|
|
|
|
#ifndef SQLITE_OMIT_TRIGGER
|
|
/*
|
|
** Show a human-readable graph of a TriggerStep
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3TreeViewTriggerStep(
|
|
TreeView *pView,
|
|
const TriggerStep *pStep,
|
|
u8 moreToFollow,
|
|
u8 showFullList
|
|
){
|
|
int cnt = 0;
|
|
if( pStep==0 ) return;
|
|
sqlite3TreeViewPush(&pView,
|
|
moreToFollow || (showFullList && pStep->pNext!=0));
|
|
do{
|
|
if( cnt++ && pStep->pNext==0 ){
|
|
sqlite3TreeViewPop(&pView);
|
|
sqlite3TreeViewPush(&pView, 0);
|
|
}
|
|
sqlite3TreeViewLine(pView, "%s", pStep->zSpan ? pStep->zSpan : "RETURNING");
|
|
}while( showFullList && (pStep = pStep->pNext)!=0 );
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
|
|
/*
|
|
** Show a human-readable graph of a Trigger
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3TreeViewTrigger(
|
|
TreeView *pView,
|
|
const Trigger *pTrigger,
|
|
u8 moreToFollow,
|
|
u8 showFullList
|
|
){
|
|
int cnt = 0;
|
|
if( pTrigger==0 ) return;
|
|
sqlite3TreeViewPush(&pView,
|
|
moreToFollow || (showFullList && pTrigger->pNext!=0));
|
|
do{
|
|
if( cnt++ && pTrigger->pNext==0 ){
|
|
sqlite3TreeViewPop(&pView);
|
|
sqlite3TreeViewPush(&pView, 0);
|
|
}
|
|
sqlite3TreeViewLine(pView, "TRIGGER %s", pTrigger->zName);
|
|
sqlite3TreeViewPush(&pView, 0);
|
|
sqlite3TreeViewTriggerStep(pView, pTrigger->step_list, 0, 1);
|
|
sqlite3TreeViewPop(&pView);
|
|
}while( showFullList && (pTrigger = pTrigger->pNext)!=0 );
|
|
sqlite3TreeViewPop(&pView);
|
|
}
|
|
#endif /* SQLITE_OMIT_TRIGGER */
|
|
|
|
|
|
/*
|
|
** These simplified versions of the tree-view routines omit unnecessary
|
|
** parameters. These variants are intended to be used from a symbolic
|
|
** debugger, such as "gdb", during interactive debugging sessions.
|
|
**
|
|
** This routines are given external linkage so that they will always be
|
|
** accessible to the debugging, and to avoid warnings about unused
|
|
** functions. But these routines only exist in debugging builds, so they
|
|
** do not contaminate the interface.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3ShowExpr(const Expr *p){ sqlite3TreeViewExpr(0,p,0); }
|
|
SQLITE_PRIVATE void sqlite3ShowExprList(const ExprList *p){ sqlite3TreeViewExprList(0,p,0,0);}
|
|
SQLITE_PRIVATE void sqlite3ShowIdList(const IdList *p){ sqlite3TreeViewIdList(0,p,0,0); }
|
|
SQLITE_PRIVATE void sqlite3ShowSrcList(const SrcList *p){ sqlite3TreeViewSrcList(0,p); }
|
|
SQLITE_PRIVATE void sqlite3ShowSelect(const Select *p){ sqlite3TreeViewSelect(0,p,0); }
|
|
SQLITE_PRIVATE void sqlite3ShowWith(const With *p){ sqlite3TreeViewWith(0,p,0); }
|
|
SQLITE_PRIVATE void sqlite3ShowUpsert(const Upsert *p){ sqlite3TreeViewUpsert(0,p,0); }
|
|
#ifndef SQLITE_OMIT_TRIGGER
|
|
SQLITE_PRIVATE void sqlite3ShowTriggerStep(const TriggerStep *p){
|
|
sqlite3TreeViewTriggerStep(0,p,0,0);
|
|
}
|
|
SQLITE_PRIVATE void sqlite3ShowTriggerStepList(const TriggerStep *p){
|
|
sqlite3TreeViewTriggerStep(0,p,0,1);
|
|
}
|
|
SQLITE_PRIVATE void sqlite3ShowTrigger(const Trigger *p){ sqlite3TreeViewTrigger(0,p,0,0); }
|
|
SQLITE_PRIVATE void sqlite3ShowTriggerList(const Trigger *p){ sqlite3TreeViewTrigger(0,p,0,1);}
|
|
#endif
|
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
SQLITE_PRIVATE void sqlite3ShowWindow(const Window *p){ sqlite3TreeViewWindow(0,p,0); }
|
|
SQLITE_PRIVATE void sqlite3ShowWinFunc(const Window *p){ sqlite3TreeViewWinFunc(0,p,0); }
|
|
#endif
|
|
|
|
#endif /* SQLITE_DEBUG */
|
|
|
|
/************** End of treeview.c ********************************************/
|
|
/************** Begin file random.c ******************************************/
|
|
/*
|
|
** 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.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
|
|
|
|
/* All threads share a single random number generator.
|
|
** This structure is the current state of the generator.
|
|
*/
|
|
static SQLITE_WSD struct sqlite3PrngType {
|
|
u32 s[16]; /* 64 bytes of chacha20 state */
|
|
u8 out[64]; /* Output bytes */
|
|
u8 n; /* Output bytes remaining */
|
|
} sqlite3Prng;
|
|
|
|
|
|
/* The RFC-7539 ChaCha20 block function
|
|
*/
|
|
#define ROTL(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
|
|
#define QR(a, b, c, d) ( \
|
|
a += b, d ^= a, d = ROTL(d,16), \
|
|
c += d, b ^= c, b = ROTL(b,12), \
|
|
a += b, d ^= a, d = ROTL(d, 8), \
|
|
c += d, b ^= c, b = ROTL(b, 7))
|
|
static void chacha_block(u32 *out, const u32 *in){
|
|
int i;
|
|
u32 x[16];
|
|
memcpy(x, in, 64);
|
|
for(i=0; i<10; i++){
|
|
QR(x[0], x[4], x[ 8], x[12]);
|
|
QR(x[1], x[5], x[ 9], x[13]);
|
|
QR(x[2], x[6], x[10], x[14]);
|
|
QR(x[3], x[7], x[11], x[15]);
|
|
QR(x[0], x[5], x[10], x[15]);
|
|
QR(x[1], x[6], x[11], x[12]);
|
|
QR(x[2], x[7], x[ 8], x[13]);
|
|
QR(x[3], x[4], x[ 9], x[14]);
|
|
}
|
|
for(i=0; i<16; i++) out[i] = x[i]+in[i];
|
|
}
|
|
|
|
/*
|
|
** Return N random bytes.
|
|
*/
|
|
SQLITE_API void sqlite3_randomness(int N, void *pBuf){
|
|
unsigned char *zBuf = pBuf;
|
|
|
|
/* The "wsdPrng" macro will resolve to the pseudo-random number generator
|
|
** state vector. If writable static data is unsupported on the target,
|
|
** we have to locate the state vector at run-time. In the more common
|
|
** case where writable static data is supported, wsdPrng can refer directly
|
|
** to the "sqlite3Prng" state vector declared above.
|
|
*/
|
|
#ifdef SQLITE_OMIT_WSD
|
|
struct sqlite3PrngType *p = &GLOBAL(struct sqlite3PrngType, sqlite3Prng);
|
|
# define wsdPrng p[0]
|
|
#else
|
|
# define wsdPrng sqlite3Prng
|
|
#endif
|
|
|
|
#if SQLITE_THREADSAFE
|
|
sqlite3_mutex *mutex;
|
|
#endif
|
|
|
|
#ifndef SQLITE_OMIT_AUTOINIT
|
|
if( sqlite3_initialize() ) return;
|
|
#endif
|
|
|
|
#if SQLITE_THREADSAFE
|
|
mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG);
|
|
#endif
|
|
|
|
sqlite3_mutex_enter(mutex);
|
|
if( N<=0 || pBuf==0 ){
|
|
wsdPrng.s[0] = 0;
|
|
sqlite3_mutex_leave(mutex);
|
|
return;
|
|
}
|
|
|
|
/* Initialize the state of the random number generator once,
|
|
** the first time this routine is called.
|
|
*/
|
|
if( wsdPrng.s[0]==0 ){
|
|
sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
|
|
static const u32 chacha20_init[] = {
|
|
0x61707865, 0x3320646e, 0x79622d32, 0x6b206574
|
|
};
|
|
memcpy(&wsdPrng.s[0], chacha20_init, 16);
|
|
if( NEVER(pVfs==0) ){
|
|
memset(&wsdPrng.s[4], 0, 44);
|
|
}else{
|
|
sqlite3OsRandomness(pVfs, 44, (char*)&wsdPrng.s[4]);
|
|
}
|
|
wsdPrng.s[15] = wsdPrng.s[12];
|
|
wsdPrng.s[12] = 0;
|
|
wsdPrng.n = 0;
|
|
}
|
|
|
|
assert( N>0 );
|
|
while( 1 /* exit by break */ ){
|
|
if( N<=wsdPrng.n ){
|
|
memcpy(zBuf, &wsdPrng.out[wsdPrng.n-N], N);
|
|
wsdPrng.n -= N;
|
|
break;
|
|
}
|
|
if( wsdPrng.n>0 ){
|
|
memcpy(zBuf, wsdPrng.out, wsdPrng.n);
|
|
N -= wsdPrng.n;
|
|
zBuf += wsdPrng.n;
|
|
}
|
|
wsdPrng.s[12]++;
|
|
chacha_block((u32*)wsdPrng.out, wsdPrng.s);
|
|
wsdPrng.n = 64;
|
|
}
|
|
sqlite3_mutex_leave(mutex);
|
|
}
|
|
|
|
#ifndef SQLITE_UNTESTABLE
|
|
/*
|
|
** For testing purposes, we sometimes want to preserve the state of
|
|
** PRNG and restore the PRNG to its saved state at a later time, or
|
|
** to reset the PRNG to its initial state. These routines accomplish
|
|
** those tasks.
|
|
**
|
|
** The sqlite3_test_control() interface calls these routines to
|
|
** control the PRNG.
|
|
*/
|
|
static SQLITE_WSD struct sqlite3PrngType sqlite3SavedPrng;
|
|
SQLITE_PRIVATE void sqlite3PrngSaveState(void){
|
|
memcpy(
|
|
&GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng),
|
|
&GLOBAL(struct sqlite3PrngType, sqlite3Prng),
|
|
sizeof(sqlite3Prng)
|
|
);
|
|
}
|
|
SQLITE_PRIVATE void sqlite3PrngRestoreState(void){
|
|
memcpy(
|
|
&GLOBAL(struct sqlite3PrngType, sqlite3Prng),
|
|
&GLOBAL(struct sqlite3PrngType, sqlite3SavedPrng),
|
|
sizeof(sqlite3Prng)
|
|
);
|
|
}
|
|
#endif /* SQLITE_UNTESTABLE */
|
|
|
|
/************** End of random.c **********************************************/
|
|
/************** Begin file threads.c *****************************************/
|
|
/*
|
|
** 2012 July 21
|
|
**
|
|
** 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 presents a simple cross-platform threading interface for
|
|
** use internally by SQLite.
|
|
**
|
|
** A "thread" can be created using sqlite3ThreadCreate(). This thread
|
|
** runs independently of its creator until it is joined using
|
|
** sqlite3ThreadJoin(), at which point it terminates.
|
|
**
|
|
** Threads do not have to be real. It could be that the work of the
|
|
** "thread" is done by the main thread at either the sqlite3ThreadCreate()
|
|
** or sqlite3ThreadJoin() call. This is, in fact, what happens in
|
|
** single threaded systems. Nothing in SQLite requires multiple threads.
|
|
** This interface exists so that applications that want to take advantage
|
|
** of multiple cores can do so, while also allowing applications to stay
|
|
** single-threaded if desired.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
#if SQLITE_OS_WIN
|
|
/* # include "os_win.h" */
|
|
#endif
|
|
|
|
#if SQLITE_MAX_WORKER_THREADS>0
|
|
|
|
/********************************* Unix Pthreads ****************************/
|
|
#if SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) && SQLITE_THREADSAFE>0
|
|
|
|
#define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */
|
|
/* #include <pthread.h> */
|
|
|
|
/* A running thread */
|
|
struct SQLiteThread {
|
|
pthread_t tid; /* Thread ID */
|
|
int done; /* Set to true when thread finishes */
|
|
void *pOut; /* Result returned by the thread */
|
|
void *(*xTask)(void*); /* The thread routine */
|
|
void *pIn; /* Argument to the thread */
|
|
};
|
|
|
|
/* Create a new thread */
|
|
SQLITE_PRIVATE int sqlite3ThreadCreate(
|
|
SQLiteThread **ppThread, /* OUT: Write the thread object here */
|
|
void *(*xTask)(void*), /* Routine to run in a separate thread */
|
|
void *pIn /* Argument passed into xTask() */
|
|
){
|
|
SQLiteThread *p;
|
|
int rc;
|
|
|
|
assert( ppThread!=0 );
|
|
assert( xTask!=0 );
|
|
/* This routine is never used in single-threaded mode */
|
|
assert( sqlite3GlobalConfig.bCoreMutex!=0 );
|
|
|
|
*ppThread = 0;
|
|
p = sqlite3Malloc(sizeof(*p));
|
|
if( p==0 ) return SQLITE_NOMEM_BKPT;
|
|
memset(p, 0, sizeof(*p));
|
|
p->xTask = xTask;
|
|
p->pIn = pIn;
|
|
/* If the SQLITE_TESTCTRL_FAULT_INSTALL callback is registered to a
|
|
** function that returns SQLITE_ERROR when passed the argument 200, that
|
|
** forces worker threads to run sequentially and deterministically
|
|
** for testing purposes. */
|
|
if( sqlite3FaultSim(200) ){
|
|
rc = 1;
|
|
}else{
|
|
rc = pthread_create(&p->tid, 0, xTask, pIn);
|
|
}
|
|
if( rc ){
|
|
p->done = 1;
|
|
p->pOut = xTask(pIn);
|
|
}
|
|
*ppThread = p;
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/* Get the results of the thread */
|
|
SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
|
|
int rc;
|
|
|
|
assert( ppOut!=0 );
|
|
if( NEVER(p==0) ) return SQLITE_NOMEM_BKPT;
|
|
if( p->done ){
|
|
*ppOut = p->pOut;
|
|
rc = SQLITE_OK;
|
|
}else{
|
|
rc = pthread_join(p->tid, ppOut) ? SQLITE_ERROR : SQLITE_OK;
|
|
}
|
|
sqlite3_free(p);
|
|
return rc;
|
|
}
|
|
|
|
#endif /* SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) */
|
|
/******************************** End Unix Pthreads *************************/
|
|
|
|
|
|
/********************************* Win32 Threads ****************************/
|
|
#if SQLITE_OS_WIN_THREADS
|
|
|
|
#define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */
|
|
#include <process.h>
|
|
|
|
/* A running thread */
|
|
struct SQLiteThread {
|
|
void *tid; /* The thread handle */
|
|
unsigned id; /* The thread identifier */
|
|
void *(*xTask)(void*); /* The routine to run as a thread */
|
|
void *pIn; /* Argument to xTask */
|
|
void *pResult; /* Result of xTask */
|
|
};
|
|
|
|
/* Thread procedure Win32 compatibility shim */
|
|
static unsigned __stdcall sqlite3ThreadProc(
|
|
void *pArg /* IN: Pointer to the SQLiteThread structure */
|
|
){
|
|
SQLiteThread *p = (SQLiteThread *)pArg;
|
|
|
|
assert( p!=0 );
|
|
#if 0
|
|
/*
|
|
** This assert appears to trigger spuriously on certain
|
|
** versions of Windows, possibly due to _beginthreadex()
|
|
** and/or CreateThread() not fully setting their thread
|
|
** ID parameter before starting the thread.
|
|
*/
|
|
assert( p->id==GetCurrentThreadId() );
|
|
#endif
|
|
assert( p->xTask!=0 );
|
|
p->pResult = p->xTask(p->pIn);
|
|
|
|
_endthreadex(0);
|
|
return 0; /* NOT REACHED */
|
|
}
|
|
|
|
/* Create a new thread */
|
|
SQLITE_PRIVATE int sqlite3ThreadCreate(
|
|
SQLiteThread **ppThread, /* OUT: Write the thread object here */
|
|
void *(*xTask)(void*), /* Routine to run in a separate thread */
|
|
void *pIn /* Argument passed into xTask() */
|
|
){
|
|
SQLiteThread *p;
|
|
|
|
assert( ppThread!=0 );
|
|
assert( xTask!=0 );
|
|
*ppThread = 0;
|
|
p = sqlite3Malloc(sizeof(*p));
|
|
if( p==0 ) return SQLITE_NOMEM_BKPT;
|
|
/* If the SQLITE_TESTCTRL_FAULT_INSTALL callback is registered to a
|
|
** function that returns SQLITE_ERROR when passed the argument 200, that
|
|
** forces worker threads to run sequentially and deterministically
|
|
** (via the sqlite3FaultSim() term of the conditional) for testing
|
|
** purposes. */
|
|
if( sqlite3GlobalConfig.bCoreMutex==0 || sqlite3FaultSim(200) ){
|
|
memset(p, 0, sizeof(*p));
|
|
}else{
|
|
p->xTask = xTask;
|
|
p->pIn = pIn;
|
|
p->tid = (void*)_beginthreadex(0, 0, sqlite3ThreadProc, p, 0, &p->id);
|
|
if( p->tid==0 ){
|
|
memset(p, 0, sizeof(*p));
|
|
}
|
|
}
|
|
if( p->xTask==0 ){
|
|
p->id = GetCurrentThreadId();
|
|
p->pResult = xTask(pIn);
|
|
}
|
|
*ppThread = p;
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
SQLITE_PRIVATE DWORD sqlite3Win32Wait(HANDLE hObject); /* os_win.c */
|
|
|
|
/* Get the results of the thread */
|
|
SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
|
|
DWORD rc;
|
|
BOOL bRc;
|
|
|
|
assert( ppOut!=0 );
|
|
if( NEVER(p==0) ) return SQLITE_NOMEM_BKPT;
|
|
if( p->xTask==0 ){
|
|
/* assert( p->id==GetCurrentThreadId() ); */
|
|
rc = WAIT_OBJECT_0;
|
|
assert( p->tid==0 );
|
|
}else{
|
|
assert( p->id!=0 && p->id!=GetCurrentThreadId() );
|
|
rc = sqlite3Win32Wait((HANDLE)p->tid);
|
|
assert( rc!=WAIT_IO_COMPLETION );
|
|
bRc = CloseHandle((HANDLE)p->tid);
|
|
assert( bRc );
|
|
}
|
|
if( rc==WAIT_OBJECT_0 ) *ppOut = p->pResult;
|
|
sqlite3_free(p);
|
|
return (rc==WAIT_OBJECT_0) ? SQLITE_OK : SQLITE_ERROR;
|
|
}
|
|
|
|
#endif /* SQLITE_OS_WIN_THREADS */
|
|
/******************************** End Win32 Threads *************************/
|
|
|
|
|
|
/********************************* Single-Threaded **************************/
|
|
#ifndef SQLITE_THREADS_IMPLEMENTED
|
|
/*
|
|
** This implementation does not actually create a new thread. It does the
|
|
** work of the thread in the main thread, when either the thread is created
|
|
** or when it is joined
|
|
*/
|
|
|
|
/* A running thread */
|
|
struct SQLiteThread {
|
|
void *(*xTask)(void*); /* The routine to run as a thread */
|
|
void *pIn; /* Argument to xTask */
|
|
void *pResult; /* Result of xTask */
|
|
};
|
|
|
|
/* Create a new thread */
|
|
SQLITE_PRIVATE int sqlite3ThreadCreate(
|
|
SQLiteThread **ppThread, /* OUT: Write the thread object here */
|
|
void *(*xTask)(void*), /* Routine to run in a separate thread */
|
|
void *pIn /* Argument passed into xTask() */
|
|
){
|
|
SQLiteThread *p;
|
|
|
|
assert( ppThread!=0 );
|
|
assert( xTask!=0 );
|
|
*ppThread = 0;
|
|
p = sqlite3Malloc(sizeof(*p));
|
|
if( p==0 ) return SQLITE_NOMEM_BKPT;
|
|
if( (SQLITE_PTR_TO_INT(p)/17)&1 ){
|
|
p->xTask = xTask;
|
|
p->pIn = pIn;
|
|
}else{
|
|
p->xTask = 0;
|
|
p->pResult = xTask(pIn);
|
|
}
|
|
*ppThread = p;
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/* Get the results of the thread */
|
|
SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
|
|
|
|
assert( ppOut!=0 );
|
|
if( NEVER(p==0) ) return SQLITE_NOMEM_BKPT;
|
|
if( p->xTask ){
|
|
*ppOut = p->xTask(p->pIn);
|
|
}else{
|
|
*ppOut = p->pResult;
|
|
}
|
|
sqlite3_free(p);
|
|
|
|
#if defined(SQLITE_TEST)
|
|
{
|
|
void *pTstAlloc = sqlite3Malloc(10);
|
|
if (!pTstAlloc) return SQLITE_NOMEM_BKPT;
|
|
sqlite3_free(pTstAlloc);
|
|
}
|
|
#endif
|
|
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
#endif /* !defined(SQLITE_THREADS_IMPLEMENTED) */
|
|
/****************************** End Single-Threaded *************************/
|
|
#endif /* SQLITE_MAX_WORKER_THREADS>0 */
|
|
|
|
/************** End of threads.c *********************************************/
|
|
/************** Begin file utf.c *********************************************/
|
|
/*
|
|
** 2004 April 13
|
|
**
|
|
** The author disclaims copyright to this source code. In place of
|
|
** a legal notice, here is a blessing:
|
|
**
|
|
** May you do good and not evil.
|
|
** May you find forgiveness for yourself and forgive others.
|
|
** May you share freely, never taking more than you give.
|
|
**
|
|
*************************************************************************
|
|
** This file contains routines used to translate between UTF-8,
|
|
** UTF-16, UTF-16BE, and UTF-16LE.
|
|
**
|
|
** Notes on UTF-8:
|
|
**
|
|
** Byte-0 Byte-1 Byte-2 Byte-3 Value
|
|
** 0xxxxxxx 00000000 00000000 0xxxxxxx
|
|
** 110yyyyy 10xxxxxx 00000000 00000yyy yyxxxxxx
|
|
** 1110zzzz 10yyyyyy 10xxxxxx 00000000 zzzzyyyy yyxxxxxx
|
|
** 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx 000uuuuu zzzzyyyy yyxxxxxx
|
|
**
|
|
**
|
|
** Notes on UTF-16: (with wwww+1==uuuuu)
|
|
**
|
|
** Word-0 Word-1 Value
|
|
** 110110ww wwzzzzyy 110111yy yyxxxxxx 000uuuuu zzzzyyyy yyxxxxxx
|
|
** zzzzyyyy yyxxxxxx 00000000 zzzzyyyy yyxxxxxx
|
|
**
|
|
**
|
|
** BOM or Byte Order Mark:
|
|
** 0xff 0xfe little-endian utf-16 follows
|
|
** 0xfe 0xff big-endian utf-16 follows
|
|
**
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
/* #include <assert.h> */
|
|
/* #include "vdbeInt.h" */
|
|
|
|
#if !defined(SQLITE_AMALGAMATION) && SQLITE_BYTEORDER==0
|
|
/*
|
|
** The following constant value is used by the SQLITE_BIGENDIAN and
|
|
** SQLITE_LITTLEENDIAN macros.
|
|
*/
|
|
SQLITE_PRIVATE const int sqlite3one = 1;
|
|
#endif /* SQLITE_AMALGAMATION && SQLITE_BYTEORDER==0 */
|
|
|
|
/*
|
|
** This lookup table is used to help decode the first byte of
|
|
** a multi-byte UTF8 character.
|
|
*/
|
|
static const unsigned char sqlite3Utf8Trans1[] = {
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
|
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
|
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00,
|
|
};
|
|
|
|
|
|
#define WRITE_UTF8(zOut, c) { \
|
|
if( c<0x00080 ){ \
|
|
*zOut++ = (u8)(c&0xFF); \
|
|
} \
|
|
else if( c<0x00800 ){ \
|
|
*zOut++ = 0xC0 + (u8)((c>>6)&0x1F); \
|
|
*zOut++ = 0x80 + (u8)(c & 0x3F); \
|
|
} \
|
|
else if( c<0x10000 ){ \
|
|
*zOut++ = 0xE0 + (u8)((c>>12)&0x0F); \
|
|
*zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \
|
|
*zOut++ = 0x80 + (u8)(c & 0x3F); \
|
|
}else{ \
|
|
*zOut++ = 0xF0 + (u8)((c>>18) & 0x07); \
|
|
*zOut++ = 0x80 + (u8)((c>>12) & 0x3F); \
|
|
*zOut++ = 0x80 + (u8)((c>>6) & 0x3F); \
|
|
*zOut++ = 0x80 + (u8)(c & 0x3F); \
|
|
} \
|
|
}
|
|
|
|
#define WRITE_UTF16LE(zOut, c) { \
|
|
if( c<=0xFFFF ){ \
|
|
*zOut++ = (u8)(c&0x00FF); \
|
|
*zOut++ = (u8)((c>>8)&0x00FF); \
|
|
}else{ \
|
|
*zOut++ = (u8)(((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0)); \
|
|
*zOut++ = (u8)(0x00D8 + (((c-0x10000)>>18)&0x03)); \
|
|
*zOut++ = (u8)(c&0x00FF); \
|
|
*zOut++ = (u8)(0x00DC + ((c>>8)&0x03)); \
|
|
} \
|
|
}
|
|
|
|
#define WRITE_UTF16BE(zOut, c) { \
|
|
if( c<=0xFFFF ){ \
|
|
*zOut++ = (u8)((c>>8)&0x00FF); \
|
|
*zOut++ = (u8)(c&0x00FF); \
|
|
}else{ \
|
|
*zOut++ = (u8)(0x00D8 + (((c-0x10000)>>18)&0x03)); \
|
|
*zOut++ = (u8)(((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0)); \
|
|
*zOut++ = (u8)(0x00DC + ((c>>8)&0x03)); \
|
|
*zOut++ = (u8)(c&0x00FF); \
|
|
} \
|
|
}
|
|
|
|
/*
|
|
** Translate a single UTF-8 character. Return the unicode value.
|
|
**
|
|
** During translation, assume that the byte that zTerm points
|
|
** is a 0x00.
|
|
**
|
|
** Write a pointer to the next unread byte back into *pzNext.
|
|
**
|
|
** Notes On Invalid UTF-8:
|
|
**
|
|
** * This routine never allows a 7-bit character (0x00 through 0x7f) to
|
|
** be encoded as a multi-byte character. Any multi-byte character that
|
|
** attempts to encode a value between 0x00 and 0x7f is rendered as 0xfffd.
|
|
**
|
|
** * This routine never allows a UTF16 surrogate value to be encoded.
|
|
** If a multi-byte character attempts to encode a value between
|
|
** 0xd800 and 0xe000 then it is rendered as 0xfffd.
|
|
**
|
|
** * Bytes in the range of 0x80 through 0xbf which occur as the first
|
|
** byte of a character are interpreted as single-byte characters
|
|
** and rendered as themselves even though they are technically
|
|
** invalid characters.
|
|
**
|
|
** * This routine accepts over-length UTF8 encodings
|
|
** for unicode values 0x80 and greater. It does not change over-length
|
|
** encodings to 0xfffd as some systems recommend.
|
|
*/
|
|
#define READ_UTF8(zIn, zTerm, c) \
|
|
c = *(zIn++); \
|
|
if( c>=0xc0 ){ \
|
|
c = sqlite3Utf8Trans1[c-0xc0]; \
|
|
while( zIn!=zTerm && (*zIn & 0xc0)==0x80 ){ \
|
|
c = (c<<6) + (0x3f & *(zIn++)); \
|
|
} \
|
|
if( c<0x80 \
|
|
|| (c&0xFFFFF800)==0xD800 \
|
|
|| (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \
|
|
}
|
|
SQLITE_PRIVATE u32 sqlite3Utf8Read(
|
|
const unsigned char **pz /* Pointer to string from which to read char */
|
|
){
|
|
unsigned int c;
|
|
|
|
/* Same as READ_UTF8() above but without the zTerm parameter.
|
|
** For this routine, we assume the UTF8 string is always zero-terminated.
|
|
*/
|
|
c = *((*pz)++);
|
|
if( c>=0xc0 ){
|
|
c = sqlite3Utf8Trans1[c-0xc0];
|
|
while( (*(*pz) & 0xc0)==0x80 ){
|
|
c = (c<<6) + (0x3f & *((*pz)++));
|
|
}
|
|
if( c<0x80
|
|
|| (c&0xFFFFF800)==0xD800
|
|
|| (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; }
|
|
}
|
|
return c;
|
|
}
|
|
|
|
/*
|
|
** Read a single UTF8 character out of buffer z[], but reading no
|
|
** more than n characters from the buffer. z[] is not zero-terminated.
|
|
**
|
|
** Return the number of bytes used to construct the character.
|
|
**
|
|
** Invalid UTF8 might generate a strange result. No effort is made
|
|
** to detect invalid UTF8.
|
|
**
|
|
** At most 4 bytes will be read out of z[]. The return value will always
|
|
** be between 1 and 4.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3Utf8ReadLimited(
|
|
const u8 *z,
|
|
int n,
|
|
u32 *piOut
|
|
){
|
|
u32 c;
|
|
int i = 1;
|
|
assert( n>0 );
|
|
c = z[0];
|
|
if( c>=0xc0 ){
|
|
c = sqlite3Utf8Trans1[c-0xc0];
|
|
if( n>4 ) n = 4;
|
|
while( i<n && (z[i] & 0xc0)==0x80 ){
|
|
c = (c<<6) + (0x3f & z[i]);
|
|
i++;
|
|
}
|
|
}
|
|
*piOut = c;
|
|
return i;
|
|
}
|
|
|
|
|
|
/*
|
|
** If the TRANSLATE_TRACE macro is defined, the value of each Mem is
|
|
** printed on stderr on the way into and out of sqlite3VdbeMemTranslate().
|
|
*/
|
|
/* #define TRANSLATE_TRACE 1 */
|
|
|
|
#ifndef SQLITE_OMIT_UTF16
|
|
/*
|
|
** This routine transforms the internal text encoding used by pMem to
|
|
** desiredEnc. It is an error if the string is already of the desired
|
|
** encoding, or if *pMem does not contain a string value.
|
|
*/
|
|
SQLITE_PRIVATE SQLITE_NOINLINE int sqlite3VdbeMemTranslate(Mem *pMem, u8 desiredEnc){
|
|
sqlite3_int64 len; /* Maximum length of output string in bytes */
|
|
unsigned char *zOut; /* Output buffer */
|
|
unsigned char *zIn; /* Input iterator */
|
|
unsigned char *zTerm; /* End of input */
|
|
unsigned char *z; /* Output iterator */
|
|
unsigned int c;
|
|
|
|
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
|
|
assert( pMem->flags&MEM_Str );
|
|
assert( pMem->enc!=desiredEnc );
|
|
assert( pMem->enc!=0 );
|
|
assert( pMem->n>=0 );
|
|
|
|
#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
|
|
{
|
|
StrAccum acc;
|
|
char zBuf[1000];
|
|
sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
|
|
sqlite3VdbeMemPrettyPrint(pMem, &acc);
|
|
fprintf(stderr, "INPUT: %s\n", sqlite3StrAccumFinish(&acc));
|
|
}
|
|
#endif
|
|
|
|
/* If the translation is between UTF-16 little and big endian, then
|
|
** all that is required is to swap the byte order. This case is handled
|
|
** differently from the others.
|
|
*/
|
|
if( pMem->enc!=SQLITE_UTF8 && desiredEnc!=SQLITE_UTF8 ){
|
|
u8 temp;
|
|
int rc;
|
|
rc = sqlite3VdbeMemMakeWriteable(pMem);
|
|
if( rc!=SQLITE_OK ){
|
|
assert( rc==SQLITE_NOMEM );
|
|
return SQLITE_NOMEM_BKPT;
|
|
}
|
|
zIn = (u8*)pMem->z;
|
|
zTerm = &zIn[pMem->n&~1];
|
|
while( zIn<zTerm ){
|
|
temp = *zIn;
|
|
*zIn = *(zIn+1);
|
|
zIn++;
|
|
*zIn++ = temp;
|
|
}
|
|
pMem->enc = desiredEnc;
|
|
goto translate_out;
|
|
}
|
|
|
|
/* Set len to the maximum number of bytes required in the output buffer. */
|
|
if( desiredEnc==SQLITE_UTF8 ){
|
|
/* When converting from UTF-16, the maximum growth results from
|
|
** translating a 2-byte character to a 4-byte UTF-8 character.
|
|
** A single byte is required for the output string
|
|
** nul-terminator.
|
|
*/
|
|
pMem->n &= ~1;
|
|
len = 2 * (sqlite3_int64)pMem->n + 1;
|
|
}else{
|
|
/* When converting from UTF-8 to UTF-16 the maximum growth is caused
|
|
** when a 1-byte UTF-8 character is translated into a 2-byte UTF-16
|
|
** character. Two bytes are required in the output buffer for the
|
|
** nul-terminator.
|
|
*/
|
|
len = 2 * (sqlite3_int64)pMem->n + 2;
|
|
}
|
|
|
|
/* Set zIn to point at the start of the input buffer and zTerm to point 1
|
|
** byte past the end.
|
|
**
|
|
** Variable zOut is set to point at the output buffer, space obtained
|
|
** from sqlite3_malloc().
|
|
*/
|
|
zIn = (u8*)pMem->z;
|
|
zTerm = &zIn[pMem->n];
|
|
zOut = sqlite3DbMallocRaw(pMem->db, len);
|
|
if( !zOut ){
|
|
return SQLITE_NOMEM_BKPT;
|
|
}
|
|
z = zOut;
|
|
|
|
if( pMem->enc==SQLITE_UTF8 ){
|
|
if( desiredEnc==SQLITE_UTF16LE ){
|
|
/* UTF-8 -> UTF-16 Little-endian */
|
|
while( zIn<zTerm ){
|
|
READ_UTF8(zIn, zTerm, c);
|
|
WRITE_UTF16LE(z, c);
|
|
}
|
|
}else{
|
|
assert( desiredEnc==SQLITE_UTF16BE );
|
|
/* UTF-8 -> UTF-16 Big-endian */
|
|
while( zIn<zTerm ){
|
|
READ_UTF8(zIn, zTerm, c);
|
|
WRITE_UTF16BE(z, c);
|
|
}
|
|
}
|
|
pMem->n = (int)(z - zOut);
|
|
*z++ = 0;
|
|
}else{
|
|
assert( desiredEnc==SQLITE_UTF8 );
|
|
if( pMem->enc==SQLITE_UTF16LE ){
|
|
/* UTF-16 Little-endian -> UTF-8 */
|
|
while( zIn<zTerm ){
|
|
c = *(zIn++);
|
|
c += (*(zIn++))<<8;
|
|
if( c>=0xd800 && c<0xe000 ){
|
|
#ifdef SQLITE_REPLACE_INVALID_UTF
|
|
if( c>=0xdc00 || zIn>=zTerm ){
|
|
c = 0xfffd;
|
|
}else{
|
|
int c2 = *(zIn++);
|
|
c2 += (*(zIn++))<<8;
|
|
if( c2<0xdc00 || c2>=0xe000 ){
|
|
zIn -= 2;
|
|
c = 0xfffd;
|
|
}else{
|
|
c = ((c&0x3ff)<<10) + (c2&0x3ff) + 0x10000;
|
|
}
|
|
}
|
|
#else
|
|
if( zIn<zTerm ){
|
|
int c2 = (*zIn++);
|
|
c2 += ((*zIn++)<<8);
|
|
c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10);
|
|
}
|
|
#endif
|
|
}
|
|
WRITE_UTF8(z, c);
|
|
}
|
|
}else{
|
|
/* UTF-16 Big-endian -> UTF-8 */
|
|
while( zIn<zTerm ){
|
|
c = (*(zIn++))<<8;
|
|
c += *(zIn++);
|
|
if( c>=0xd800 && c<0xe000 ){
|
|
#ifdef SQLITE_REPLACE_INVALID_UTF
|
|
if( c>=0xdc00 || zIn>=zTerm ){
|
|
c = 0xfffd;
|
|
}else{
|
|
int c2 = (*(zIn++))<<8;
|
|
c2 += *(zIn++);
|
|
if( c2<0xdc00 || c2>=0xe000 ){
|
|
zIn -= 2;
|
|
c = 0xfffd;
|
|
}else{
|
|
c = ((c&0x3ff)<<10) + (c2&0x3ff) + 0x10000;
|
|
}
|
|
}
|
|
#else
|
|
if( zIn<zTerm ){
|
|
int c2 = ((*zIn++)<<8);
|
|
c2 += (*zIn++);
|
|
c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10);
|
|
}
|
|
#endif
|
|
}
|
|
WRITE_UTF8(z, c);
|
|
}
|
|
}
|
|
pMem->n = (int)(z - zOut);
|
|
}
|
|
*z = 0;
|
|
assert( (pMem->n+(desiredEnc==SQLITE_UTF8?1:2))<=len );
|
|
|
|
c = MEM_Str|MEM_Term|(pMem->flags&(MEM_AffMask|MEM_Subtype));
|
|
sqlite3VdbeMemRelease(pMem);
|
|
pMem->flags = c;
|
|
pMem->enc = desiredEnc;
|
|
pMem->z = (char*)zOut;
|
|
pMem->zMalloc = pMem->z;
|
|
pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->z);
|
|
|
|
translate_out:
|
|
#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
|
|
{
|
|
StrAccum acc;
|
|
char zBuf[1000];
|
|
sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
|
|
sqlite3VdbeMemPrettyPrint(pMem, &acc);
|
|
fprintf(stderr, "OUTPUT: %s\n", sqlite3StrAccumFinish(&acc));
|
|
}
|
|
#endif
|
|
return SQLITE_OK;
|
|
}
|
|
#endif /* SQLITE_OMIT_UTF16 */
|
|
|
|
#ifndef SQLITE_OMIT_UTF16
|
|
/*
|
|
** This routine checks for a byte-order mark at the beginning of the
|
|
** UTF-16 string stored in *pMem. If one is present, it is removed and
|
|
** the encoding of the Mem adjusted. This routine does not do any
|
|
** byte-swapping, it just sets Mem.enc appropriately.
|
|
**
|
|
** The allocation (static, dynamic etc.) and encoding of the Mem may be
|
|
** changed by this function.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3VdbeMemHandleBom(Mem *pMem){
|
|
int rc = SQLITE_OK;
|
|
u8 bom = 0;
|
|
|
|
assert( pMem->n>=0 );
|
|
if( pMem->n>1 ){
|
|
u8 b1 = *(u8 *)pMem->z;
|
|
u8 b2 = *(((u8 *)pMem->z) + 1);
|
|
if( b1==0xFE && b2==0xFF ){
|
|
bom = SQLITE_UTF16BE;
|
|
}
|
|
if( b1==0xFF && b2==0xFE ){
|
|
bom = SQLITE_UTF16LE;
|
|
}
|
|
}
|
|
|
|
if( bom ){
|
|
rc = sqlite3VdbeMemMakeWriteable(pMem);
|
|
if( rc==SQLITE_OK ){
|
|
pMem->n -= 2;
|
|
memmove(pMem->z, &pMem->z[2], pMem->n);
|
|
pMem->z[pMem->n] = '\0';
|
|
pMem->z[pMem->n+1] = '\0';
|
|
pMem->flags |= MEM_Term;
|
|
pMem->enc = bom;
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
#endif /* SQLITE_OMIT_UTF16 */
|
|
|
|
/*
|
|
** pZ is a UTF-8 encoded unicode string. If nByte is less than zero,
|
|
** return the number of unicode characters in pZ up to (but not including)
|
|
** the first 0x00 byte. If nByte is not less than zero, return the
|
|
** number of unicode characters in the first nByte of pZ (or up to
|
|
** the first 0x00, whichever comes first).
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3Utf8CharLen(const char *zIn, int nByte){
|
|
int r = 0;
|
|
const u8 *z = (const u8*)zIn;
|
|
const u8 *zTerm;
|
|
if( nByte>=0 ){
|
|
zTerm = &z[nByte];
|
|
}else{
|
|
zTerm = (const u8*)(-1);
|
|
}
|
|
assert( z<=zTerm );
|
|
while( *z!=0 && z<zTerm ){
|
|
SQLITE_SKIP_UTF8(z);
|
|
r++;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
/* This test function is not currently used by the automated test-suite.
|
|
** Hence it is only available in debug builds.
|
|
*/
|
|
#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
|
|
/*
|
|
** Translate UTF-8 to UTF-8.
|
|
**
|
|
** This has the effect of making sure that the string is well-formed
|
|
** UTF-8. Miscoded characters are removed.
|
|
**
|
|
** The translation is done in-place and aborted if the output
|
|
** overruns the input.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3Utf8To8(unsigned char *zIn){
|
|
unsigned char *zOut = zIn;
|
|
unsigned char *zStart = zIn;
|
|
u32 c;
|
|
|
|
while( zIn[0] && zOut<=zIn ){
|
|
c = sqlite3Utf8Read((const u8**)&zIn);
|
|
if( c!=0xfffd ){
|
|
WRITE_UTF8(zOut, c);
|
|
}
|
|
}
|
|
*zOut = 0;
|
|
return (int)(zOut - zStart);
|
|
}
|
|
#endif
|
|
|
|
#ifndef SQLITE_OMIT_UTF16
|
|
/*
|
|
** Convert a UTF-16 string in the native encoding into a UTF-8 string.
|
|
** Memory to hold the UTF-8 string is obtained from sqlite3_malloc and must
|
|
** be freed by the calling function.
|
|
**
|
|
** NULL is returned if there is an allocation error.
|
|
*/
|
|
SQLITE_PRIVATE char *sqlite3Utf16to8(sqlite3 *db, const void *z, int nByte, u8 enc){
|
|
Mem m;
|
|
memset(&m, 0, sizeof(m));
|
|
m.db = db;
|
|
sqlite3VdbeMemSetStr(&m, z, nByte, enc, SQLITE_STATIC);
|
|
sqlite3VdbeChangeEncoding(&m, SQLITE_UTF8);
|
|
if( db->mallocFailed ){
|
|
sqlite3VdbeMemRelease(&m);
|
|
m.z = 0;
|
|
}
|
|
assert( (m.flags & MEM_Term)!=0 || db->mallocFailed );
|
|
assert( (m.flags & MEM_Str)!=0 || db->mallocFailed );
|
|
assert( m.z || db->mallocFailed );
|
|
return m.z;
|
|
}
|
|
|
|
/*
|
|
** zIn is a UTF-16 encoded unicode string at least nChar characters long.
|
|
** Return the number of bytes in the first nChar unicode characters
|
|
** in pZ. nChar must be non-negative.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3Utf16ByteLen(const void *zIn, int nChar){
|
|
int c;
|
|
unsigned char const *z = zIn;
|
|
int n = 0;
|
|
|
|
if( SQLITE_UTF16NATIVE==SQLITE_UTF16LE ) z++;
|
|
while( n<nChar ){
|
|
c = z[0];
|
|
z += 2;
|
|
if( c>=0xd8 && c<0xdc && z[0]>=0xdc && z[0]<0xe0 ) z += 2;
|
|
n++;
|
|
}
|
|
return (int)(z-(unsigned char const *)zIn)
|
|
- (SQLITE_UTF16NATIVE==SQLITE_UTF16LE);
|
|
}
|
|
|
|
#if defined(SQLITE_TEST)
|
|
/*
|
|
** This routine is called from the TCL test function "translate_selftest".
|
|
** It checks that the primitives for serializing and deserializing
|
|
** characters in each encoding are inverses of each other.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3UtfSelfTest(void){
|
|
unsigned int i, t;
|
|
unsigned char zBuf[20];
|
|
unsigned char *z;
|
|
int n;
|
|
unsigned int c;
|
|
|
|
for(i=0; i<0x00110000; i++){
|
|
z = zBuf;
|
|
WRITE_UTF8(z, i);
|
|
n = (int)(z-zBuf);
|
|
assert( n>0 && n<=4 );
|
|
z[0] = 0;
|
|
z = zBuf;
|
|
c = sqlite3Utf8Read((const u8**)&z);
|
|
t = i;
|
|
if( i>=0xD800 && i<=0xDFFF ) t = 0xFFFD;
|
|
if( (i&0xFFFFFFFE)==0xFFFE ) t = 0xFFFD;
|
|
assert( c==t );
|
|
assert( (z-zBuf)==n );
|
|
}
|
|
}
|
|
#endif /* SQLITE_TEST */
|
|
#endif /* SQLITE_OMIT_UTF16 */
|
|
|
|
/************** End of utf.c *************************************************/
|
|
/************** Begin file util.c ********************************************/
|
|
/*
|
|
** 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.
|
|
**
|
|
*************************************************************************
|
|
** Utility functions used throughout sqlite.
|
|
**
|
|
** This file contains functions for allocating memory, comparing
|
|
** strings, and stuff like that.
|
|
**
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
/* #include <stdarg.h> */
|
|
#ifndef SQLITE_OMIT_FLOATING_POINT
|
|
#include <math.h>
|
|
#endif
|
|
|
|
/*
|
|
** Calls to sqlite3FaultSim() are used to simulate a failure during testing,
|
|
** or to bypass normal error detection during testing in order to let
|
|
** execute proceed further downstream.
|
|
**
|
|
** In deployment, sqlite3FaultSim() *always* return SQLITE_OK (0). The
|
|
** sqlite3FaultSim() function only returns non-zero during testing.
|
|
**
|
|
** During testing, if the test harness has set a fault-sim callback using
|
|
** a call to sqlite3_test_control(SQLITE_TESTCTRL_FAULT_INSTALL), then
|
|
** each call to sqlite3FaultSim() is relayed to that application-supplied
|
|
** callback and the integer return value form the application-supplied
|
|
** callback is returned by sqlite3FaultSim().
|
|
**
|
|
** The integer argument to sqlite3FaultSim() is a code to identify which
|
|
** sqlite3FaultSim() instance is being invoked. Each call to sqlite3FaultSim()
|
|
** should have a unique code. To prevent legacy testing applications from
|
|
** breaking, the codes should not be changed or reused.
|
|
*/
|
|
#ifndef SQLITE_UNTESTABLE
|
|
SQLITE_PRIVATE int sqlite3FaultSim(int iTest){
|
|
int (*xCallback)(int) = sqlite3GlobalConfig.xTestCallback;
|
|
return xCallback ? xCallback(iTest) : SQLITE_OK;
|
|
}
|
|
#endif
|
|
|
|
#ifndef SQLITE_OMIT_FLOATING_POINT
|
|
/*
|
|
** Return true if the floating point value is Not a Number (NaN).
|
|
**
|
|
** Use the math library isnan() function if compiled with SQLITE_HAVE_ISNAN.
|
|
** Otherwise, we have our own implementation that works on most systems.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3IsNaN(double x){
|
|
int rc; /* The value return */
|
|
#if !SQLITE_HAVE_ISNAN && !HAVE_ISNAN
|
|
u64 y;
|
|
memcpy(&y,&x,sizeof(y));
|
|
rc = IsNaN(y);
|
|
#else
|
|
rc = isnan(x);
|
|
#endif /* HAVE_ISNAN */
|
|
testcase( rc );
|
|
return rc;
|
|
}
|
|
#endif /* SQLITE_OMIT_FLOATING_POINT */
|
|
|
|
#ifndef SQLITE_OMIT_FLOATING_POINT
|
|
/*
|
|
** Return true if the floating point value is NaN or +Inf or -Inf.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3IsOverflow(double x){
|
|
int rc; /* The value return */
|
|
u64 y;
|
|
memcpy(&y,&x,sizeof(y));
|
|
rc = IsOvfl(y);
|
|
return rc;
|
|
}
|
|
#endif /* SQLITE_OMIT_FLOATING_POINT */
|
|
|
|
/*
|
|
** Compute a string length that is limited to what can be stored in
|
|
** lower 30 bits of a 32-bit signed integer.
|
|
**
|
|
** The value returned will never be negative. Nor will it ever be greater
|
|
** than the actual length of the string. For very long strings (greater
|
|
** than 1GiB) the value returned might be less than the true string length.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3Strlen30(const char *z){
|
|
if( z==0 ) return 0;
|
|
return 0x3fffffff & (int)strlen(z);
|
|
}
|
|
|
|
/*
|
|
** Return the declared type of a column. Or return zDflt if the column
|
|
** has no declared type.
|
|
**
|
|
** The column type is an extra string stored after the zero-terminator on
|
|
** the column name if and only if the COLFLAG_HASTYPE flag is set.
|
|
*/
|
|
SQLITE_PRIVATE char *sqlite3ColumnType(Column *pCol, char *zDflt){
|
|
if( pCol->colFlags & COLFLAG_HASTYPE ){
|
|
return pCol->zCnName + strlen(pCol->zCnName) + 1;
|
|
}else if( pCol->eCType ){
|
|
assert( pCol->eCType<=SQLITE_N_STDTYPE );
|
|
return (char*)sqlite3StdType[pCol->eCType-1];
|
|
}else{
|
|
return zDflt;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Helper function for sqlite3Error() - called rarely. Broken out into
|
|
** a separate routine to avoid unnecessary register saves on entry to
|
|
** sqlite3Error().
|
|
*/
|
|
static SQLITE_NOINLINE void sqlite3ErrorFinish(sqlite3 *db, int err_code){
|
|
if( db->pErr ) sqlite3ValueSetNull(db->pErr);
|
|
sqlite3SystemError(db, err_code);
|
|
}
|
|
|
|
/*
|
|
** Set the current error code to err_code and clear any prior error message.
|
|
** Also set iSysErrno (by calling sqlite3System) if the err_code indicates
|
|
** that would be appropriate.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3Error(sqlite3 *db, int err_code){
|
|
assert( db!=0 );
|
|
db->errCode = err_code;
|
|
if( err_code || db->pErr ){
|
|
sqlite3ErrorFinish(db, err_code);
|
|
}else{
|
|
db->errByteOffset = -1;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** The equivalent of sqlite3Error(db, SQLITE_OK). Clear the error state
|
|
** and error message.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3ErrorClear(sqlite3 *db){
|
|
assert( db!=0 );
|
|
db->errCode = SQLITE_OK;
|
|
db->errByteOffset = -1;
|
|
if( db->pErr ) sqlite3ValueSetNull(db->pErr);
|
|
}
|
|
|
|
/*
|
|
** Load the sqlite3.iSysErrno field if that is an appropriate thing
|
|
** to do based on the SQLite error code in rc.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3SystemError(sqlite3 *db, int rc){
|
|
if( rc==SQLITE_IOERR_NOMEM ) return;
|
|
#if defined(SQLITE_USE_SEH) && !defined(SQLITE_OMIT_WAL)
|
|
if( rc==SQLITE_IOERR_IN_PAGE ){
|
|
int ii;
|
|
int iErr;
|
|
sqlite3BtreeEnterAll(db);
|
|
for(ii=0; ii<db->nDb; ii++){
|
|
if( db->aDb[ii].pBt ){
|
|
iErr = sqlite3PagerWalSystemErrno(sqlite3BtreePager(db->aDb[ii].pBt));
|
|
if( iErr ){
|
|
db->iSysErrno = iErr;
|
|
}
|
|
}
|
|
}
|
|
sqlite3BtreeLeaveAll(db);
|
|
return;
|
|
}
|
|
#endif
|
|
rc &= 0xff;
|
|
if( rc==SQLITE_CANTOPEN || rc==SQLITE_IOERR ){
|
|
db->iSysErrno = sqlite3OsGetLastError(db->pVfs);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Set the most recent error code and error string for the sqlite
|
|
** handle "db". The error code is set to "err_code".
|
|
**
|
|
** If it is not NULL, string zFormat specifies the format of the
|
|
** error string. zFormat and any string tokens that follow it are
|
|
** assumed to be encoded in UTF-8.
|
|
**
|
|
** To clear the most recent error for sqlite handle "db", sqlite3Error
|
|
** should be called with err_code set to SQLITE_OK and zFormat set
|
|
** to NULL.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3ErrorWithMsg(sqlite3 *db, int err_code, const char *zFormat, ...){
|
|
assert( db!=0 );
|
|
db->errCode = err_code;
|
|
sqlite3SystemError(db, err_code);
|
|
if( zFormat==0 ){
|
|
sqlite3Error(db, err_code);
|
|
}else if( db->pErr || (db->pErr = sqlite3ValueNew(db))!=0 ){
|
|
char *z;
|
|
va_list ap;
|
|
va_start(ap, zFormat);
|
|
z = sqlite3VMPrintf(db, zFormat, ap);
|
|
va_end(ap);
|
|
sqlite3ValueSetStr(db->pErr, -1, z, SQLITE_UTF8, SQLITE_DYNAMIC);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Check for interrupts and invoke progress callback.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3ProgressCheck(Parse *p){
|
|
sqlite3 *db = p->db;
|
|
if( AtomicLoad(&db->u1.isInterrupted) ){
|
|
p->nErr++;
|
|
p->rc = SQLITE_INTERRUPT;
|
|
}
|
|
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
|
|
if( db->xProgress ){
|
|
if( p->rc==SQLITE_INTERRUPT ){
|
|
p->nProgressSteps = 0;
|
|
}else if( (++p->nProgressSteps)>=db->nProgressOps ){
|
|
if( db->xProgress(db->pProgressArg) ){
|
|
p->nErr++;
|
|
p->rc = SQLITE_INTERRUPT;
|
|
}
|
|
p->nProgressSteps = 0;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
** Add an error message to pParse->zErrMsg and increment pParse->nErr.
|
|
**
|
|
** This function should be used to report any error that occurs while
|
|
** compiling an SQL statement (i.e. within sqlite3_prepare()). The
|
|
** last thing the sqlite3_prepare() function does is copy the error
|
|
** stored by this function into the database handle using sqlite3Error().
|
|
** Functions sqlite3Error() or sqlite3ErrorWithMsg() should be used
|
|
** during statement execution (sqlite3_step() etc.).
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){
|
|
char *zMsg;
|
|
va_list ap;
|
|
sqlite3 *db = pParse->db;
|
|
assert( db!=0 );
|
|
assert( db->pParse==pParse || db->pParse->pToplevel==pParse );
|
|
db->errByteOffset = -2;
|
|
va_start(ap, zFormat);
|
|
zMsg = sqlite3VMPrintf(db, zFormat, ap);
|
|
va_end(ap);
|
|
if( db->errByteOffset<-1 ) db->errByteOffset = -1;
|
|
if( db->suppressErr ){
|
|
sqlite3DbFree(db, zMsg);
|
|
if( db->mallocFailed ){
|
|
pParse->nErr++;
|
|
pParse->rc = SQLITE_NOMEM;
|
|
}
|
|
}else{
|
|
pParse->nErr++;
|
|
sqlite3DbFree(db, pParse->zErrMsg);
|
|
pParse->zErrMsg = zMsg;
|
|
pParse->rc = SQLITE_ERROR;
|
|
pParse->pWith = 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** If database connection db is currently parsing SQL, then transfer
|
|
** error code errCode to that parser if the parser has not already
|
|
** encountered some other kind of error.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3ErrorToParser(sqlite3 *db, int errCode){
|
|
Parse *pParse;
|
|
if( db==0 || (pParse = db->pParse)==0 ) return errCode;
|
|
pParse->rc = errCode;
|
|
pParse->nErr++;
|
|
return errCode;
|
|
}
|
|
|
|
/*
|
|
** Convert an SQL-style quoted string into a normal string by removing
|
|
** the quote characters. The conversion is done in-place. If the
|
|
** input does not begin with a quote character, then this routine
|
|
** is a no-op.
|
|
**
|
|
** The input string must be zero-terminated. A new zero-terminator
|
|
** is added to the dequoted string.
|
|
**
|
|
** The return value is -1 if no dequoting occurs or the length of the
|
|
** dequoted string, exclusive of the zero terminator, if dequoting does
|
|
** occur.
|
|
**
|
|
** 2002-02-14: This routine is extended to remove MS-Access style
|
|
** brackets from around identifiers. For example: "[a-b-c]" becomes
|
|
** "a-b-c".
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3Dequote(char *z){
|
|
char quote;
|
|
int i, j;
|
|
if( z==0 ) return;
|
|
quote = z[0];
|
|
if( !sqlite3Isquote(quote) ) return;
|
|
if( quote=='[' ) quote = ']';
|
|
for(i=1, j=0;; i++){
|
|
assert( z[i] );
|
|
if( z[i]==quote ){
|
|
if( z[i+1]==quote ){
|
|
z[j++] = quote;
|
|
i++;
|
|
}else{
|
|
break;
|
|
}
|
|
}else{
|
|
z[j++] = z[i];
|
|
}
|
|
}
|
|
z[j] = 0;
|
|
}
|
|
SQLITE_PRIVATE void sqlite3DequoteExpr(Expr *p){
|
|
assert( !ExprHasProperty(p, EP_IntValue) );
|
|
assert( sqlite3Isquote(p->u.zToken[0]) );
|
|
p->flags |= p->u.zToken[0]=='"' ? EP_Quoted|EP_DblQuoted : EP_Quoted;
|
|
sqlite3Dequote(p->u.zToken);
|
|
}
|
|
|
|
/*
|
|
** If the input token p is quoted, try to adjust the token to remove
|
|
** the quotes. This is not always possible:
|
|
**
|
|
** "abc" -> abc
|
|
** "ab""cd" -> (not possible because of the interior "")
|
|
**
|
|
** Remove the quotes if possible. This is a optimization. The overall
|
|
** system should still return the correct answer even if this routine
|
|
** is always a no-op.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3DequoteToken(Token *p){
|
|
unsigned int i;
|
|
if( p->n<2 ) return;
|
|
if( !sqlite3Isquote(p->z[0]) ) return;
|
|
for(i=1; i<p->n-1; i++){
|
|
if( sqlite3Isquote(p->z[i]) ) return;
|
|
}
|
|
p->n -= 2;
|
|
p->z++;
|
|
}
|
|
|
|
/*
|
|
** Generate a Token object from a string
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3TokenInit(Token *p, char *z){
|
|
p->z = z;
|
|
p->n = sqlite3Strlen30(z);
|
|
}
|
|
|
|
/* Convenient short-hand */
|
|
#define UpperToLower sqlite3UpperToLower
|
|
|
|
/*
|
|
** Some systems have stricmp(). Others have strcasecmp(). Because
|
|
** there is no consistency, we will define our own.
|
|
**
|
|
** IMPLEMENTATION-OF: R-30243-02494 The sqlite3_stricmp() and
|
|
** sqlite3_strnicmp() APIs allow applications and extensions to compare
|
|
** the contents of two buffers containing UTF-8 strings in a
|
|
** case-independent fashion, using the same definition of "case
|
|
** independence" that SQLite uses internally when comparing identifiers.
|
|
*/
|
|
SQLITE_API int sqlite3_stricmp(const char *zLeft, const char *zRight){
|
|
if( zLeft==0 ){
|
|
return zRight ? -1 : 0;
|
|
}else if( zRight==0 ){
|
|
return 1;
|
|
}
|
|
return sqlite3StrICmp(zLeft, zRight);
|
|
}
|
|
SQLITE_PRIVATE int sqlite3StrICmp(const char *zLeft, const char *zRight){
|
|
unsigned char *a, *b;
|
|
int c, x;
|
|
a = (unsigned char *)zLeft;
|
|
b = (unsigned char *)zRight;
|
|
for(;;){
|
|
c = *a;
|
|
x = *b;
|
|
if( c==x ){
|
|
if( c==0 ) break;
|
|
}else{
|
|
c = (int)UpperToLower[c] - (int)UpperToLower[x];
|
|
if( c ) break;
|
|
}
|
|
a++;
|
|
b++;
|
|
}
|
|
return c;
|
|
}
|
|
SQLITE_API int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){
|
|
register unsigned char *a, *b;
|
|
if( zLeft==0 ){
|
|
return zRight ? -1 : 0;
|
|
}else if( zRight==0 ){
|
|
return 1;
|
|
}
|
|
a = (unsigned char *)zLeft;
|
|
b = (unsigned char *)zRight;
|
|
while( N-- > 0 && *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
|
|
return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b];
|
|
}
|
|
|
|
/*
|
|
** Compute an 8-bit hash on a string that is insensitive to case differences
|
|
*/
|
|
SQLITE_PRIVATE u8 sqlite3StrIHash(const char *z){
|
|
u8 h = 0;
|
|
if( z==0 ) return 0;
|
|
while( z[0] ){
|
|
h += UpperToLower[(unsigned char)z[0]];
|
|
z++;
|
|
}
|
|
return h;
|
|
}
|
|
|
|
/* Double-Double multiplication. (x[0],x[1]) *= (y,yy)
|
|
**
|
|
** Reference:
|
|
** T. J. Dekker, "A Floating-Point Technique for Extending the
|
|
** Available Precision". 1971-07-26.
|
|
*/
|
|
static void dekkerMul2(volatile double *x, double y, double yy){
|
|
/*
|
|
** The "volatile" keywords on parameter x[] and on local variables
|
|
** below are needed force intermediate results to be truncated to
|
|
** binary64 rather than be carried around in an extended-precision
|
|
** format. The truncation is necessary for the Dekker algorithm to
|
|
** work. Intel x86 floating point might omit the truncation without
|
|
** the use of volatile.
|
|
*/
|
|
volatile double tx, ty, p, q, c, cc;
|
|
double hx, hy;
|
|
u64 m;
|
|
memcpy(&m, (void*)&x[0], 8);
|
|
m &= 0xfffffffffc000000LL;
|
|
memcpy(&hx, &m, 8);
|
|
tx = x[0] - hx;
|
|
memcpy(&m, &y, 8);
|
|
m &= 0xfffffffffc000000LL;
|
|
memcpy(&hy, &m, 8);
|
|
ty = y - hy;
|
|
p = hx*hy;
|
|
q = hx*ty + tx*hy;
|
|
c = p+q;
|
|
cc = p - c + q + tx*ty;
|
|
cc = x[0]*yy + x[1]*y + cc;
|
|
x[0] = c + cc;
|
|
x[1] = c - x[0];
|
|
x[1] += cc;
|
|
}
|
|
|
|
/*
|
|
** The string z[] is an text representation of a real number.
|
|
** Convert this string to a double and write it into *pResult.
|
|
**
|
|
** The string z[] is length bytes in length (bytes, not characters) and
|
|
** uses the encoding enc. The string is not necessarily zero-terminated.
|
|
**
|
|
** Return TRUE if the result is a valid real number (or integer) and FALSE
|
|
** if the string is empty or contains extraneous text. More specifically
|
|
** return
|
|
** 1 => The input string is a pure integer
|
|
** 2 or more => The input has a decimal point or eNNN clause
|
|
** 0 or less => The input string is not a valid number
|
|
** -1 => Not a valid number, but has a valid prefix which
|
|
** includes a decimal point and/or an eNNN clause
|
|
**
|
|
** Valid numbers are in one of these formats:
|
|
**
|
|
** [+-]digits[E[+-]digits]
|
|
** [+-]digits.[digits][E[+-]digits]
|
|
** [+-].digits[E[+-]digits]
|
|
**
|
|
** Leading and trailing whitespace is ignored for the purpose of determining
|
|
** validity.
|
|
**
|
|
** If some prefix of the input string is a valid number, this routine
|
|
** returns FALSE but it still converts the prefix and writes the result
|
|
** into *pResult.
|
|
*/
|
|
#if defined(_MSC_VER)
|
|
#pragma warning(disable : 4756)
|
|
#endif
|
|
SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
|
|
#ifndef SQLITE_OMIT_FLOATING_POINT
|
|
int incr;
|
|
const char *zEnd;
|
|
/* sign * significand * (10 ^ (esign * exponent)) */
|
|
int sign = 1; /* sign of significand */
|
|
u64 s = 0; /* significand */
|
|
int d = 0; /* adjust exponent for shifting decimal point */
|
|
int esign = 1; /* sign of exponent */
|
|
int e = 0; /* exponent */
|
|
int eValid = 1; /* True exponent is either not used or is well-formed */
|
|
int nDigit = 0; /* Number of digits processed */
|
|
int eType = 1; /* 1: pure integer, 2+: fractional -1 or less: bad UTF16 */
|
|
|
|
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
|
|
*pResult = 0.0; /* Default return value, in case of an error */
|
|
if( length==0 ) return 0;
|
|
|
|
if( enc==SQLITE_UTF8 ){
|
|
incr = 1;
|
|
zEnd = z + length;
|
|
}else{
|
|
int i;
|
|
incr = 2;
|
|
length &= ~1;
|
|
assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
|
|
testcase( enc==SQLITE_UTF16LE );
|
|
testcase( enc==SQLITE_UTF16BE );
|
|
for(i=3-enc; i<length && z[i]==0; i+=2){}
|
|
if( i<length ) eType = -100;
|
|
zEnd = &z[i^1];
|
|
z += (enc&1);
|
|
}
|
|
|
|
/* skip leading spaces */
|
|
while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
|
|
if( z>=zEnd ) return 0;
|
|
|
|
/* get sign of significand */
|
|
if( *z=='-' ){
|
|
sign = -1;
|
|
z+=incr;
|
|
}else if( *z=='+' ){
|
|
z+=incr;
|
|
}
|
|
|
|
/* copy max significant digits to significand */
|
|
while( z<zEnd && sqlite3Isdigit(*z) ){
|
|
s = s*10 + (*z - '0');
|
|
z+=incr; nDigit++;
|
|
if( s>=((LARGEST_UINT64-9)/10) ){
|
|
/* skip non-significant significand digits
|
|
** (increase exponent by d to shift decimal left) */
|
|
while( z<zEnd && sqlite3Isdigit(*z) ){ z+=incr; d++; }
|
|
}
|
|
}
|
|
if( z>=zEnd ) goto do_atof_calc;
|
|
|
|
/* if decimal point is present */
|
|
if( *z=='.' ){
|
|
z+=incr;
|
|
eType++;
|
|
/* copy digits from after decimal to significand
|
|
** (decrease exponent by d to shift decimal right) */
|
|
while( z<zEnd && sqlite3Isdigit(*z) ){
|
|
if( s<((LARGEST_UINT64-9)/10) ){
|
|
s = s*10 + (*z - '0');
|
|
d--;
|
|
nDigit++;
|
|
}
|
|
z+=incr;
|
|
}
|
|
}
|
|
if( z>=zEnd ) goto do_atof_calc;
|
|
|
|
/* if exponent is present */
|
|
if( *z=='e' || *z=='E' ){
|
|
z+=incr;
|
|
eValid = 0;
|
|
eType++;
|
|
|
|
/* This branch is needed to avoid a (harmless) buffer overread. The
|
|
** special comment alerts the mutation tester that the correct answer
|
|
** is obtained even if the branch is omitted */
|
|
if( z>=zEnd ) goto do_atof_calc; /*PREVENTS-HARMLESS-OVERREAD*/
|
|
|
|
/* get sign of exponent */
|
|
if( *z=='-' ){
|
|
esign = -1;
|
|
z+=incr;
|
|
}else if( *z=='+' ){
|
|
z+=incr;
|
|
}
|
|
/* copy digits to exponent */
|
|
while( z<zEnd && sqlite3Isdigit(*z) ){
|
|
e = e<10000 ? (e*10 + (*z - '0')) : 10000;
|
|
z+=incr;
|
|
eValid = 1;
|
|
}
|
|
}
|
|
|
|
/* skip trailing spaces */
|
|
while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
|
|
|
|
do_atof_calc:
|
|
/* Zero is a special case */
|
|
if( s==0 ){
|
|
*pResult = sign<0 ? -0.0 : +0.0;
|
|
goto atof_return;
|
|
}
|
|
|
|
/* adjust exponent by d, and update sign */
|
|
e = (e*esign) + d;
|
|
|
|
/* Try to adjust the exponent to make it smaller */
|
|
while( e>0 && s<(LARGEST_UINT64/10) ){
|
|
s *= 10;
|
|
e--;
|
|
}
|
|
while( e<0 && (s%10)==0 ){
|
|
s /= 10;
|
|
e++;
|
|
}
|
|
|
|
if( e==0 ){
|
|
*pResult = s;
|
|
}else if( sqlite3Config.bUseLongDouble ){
|
|
LONGDOUBLE_TYPE r = (LONGDOUBLE_TYPE)s;
|
|
if( e>0 ){
|
|
while( e>=100 ){ e-=100; r *= 1.0e+100L; }
|
|
while( e>=10 ){ e-=10; r *= 1.0e+10L; }
|
|
while( e>=1 ){ e-=1; r *= 1.0e+01L; }
|
|
}else{
|
|
while( e<=-100 ){ e+=100; r *= 1.0e-100L; }
|
|
while( e<=-10 ){ e+=10; r *= 1.0e-10L; }
|
|
while( e<=-1 ){ e+=1; r *= 1.0e-01L; }
|
|
}
|
|
assert( r>=0.0 );
|
|
if( r>+1.7976931348623157081452742373e+308L ){
|
|
#ifdef INFINITY
|
|
*pResult = +INFINITY;
|
|
#else
|
|
*pResult = 1.0e308*10.0;
|
|
#endif
|
|
}else{
|
|
*pResult = (double)r;
|
|
}
|
|
}else{
|
|
double rr[2];
|
|
u64 s2;
|
|
rr[0] = (double)s;
|
|
s2 = (u64)rr[0];
|
|
#if defined(_MSC_VER) && _MSC_VER<1700
|
|
if( s2==0x8000000000000000LL ){ s2 = 2*(u64)(0.5*rr[0]); }
|
|
#endif
|
|
rr[1] = s>=s2 ? (double)(s - s2) : -(double)(s2 - s);
|
|
if( e>0 ){
|
|
while( e>=100 ){
|
|
e -= 100;
|
|
dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
|
|
}
|
|
while( e>=10 ){
|
|
e -= 10;
|
|
dekkerMul2(rr, 1.0e+10, 0.0);
|
|
}
|
|
while( e>=1 ){
|
|
e -= 1;
|
|
dekkerMul2(rr, 1.0e+01, 0.0);
|
|
}
|
|
}else{
|
|
while( e<=-100 ){
|
|
e += 100;
|
|
dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117);
|
|
}
|
|
while( e<=-10 ){
|
|
e += 10;
|
|
dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27);
|
|
}
|
|
while( e<=-1 ){
|
|
e += 1;
|
|
dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18);
|
|
}
|
|
}
|
|
*pResult = rr[0]+rr[1];
|
|
if( sqlite3IsNaN(*pResult) ) *pResult = 1e300*1e300;
|
|
}
|
|
if( sign<0 ) *pResult = -*pResult;
|
|
assert( !sqlite3IsNaN(*pResult) );
|
|
|
|
atof_return:
|
|
/* return true if number and no extra non-whitespace characters after */
|
|
if( z==zEnd && nDigit>0 && eValid && eType>0 ){
|
|
return eType;
|
|
}else if( eType>=2 && (eType==3 || eValid) && nDigit>0 ){
|
|
return -1;
|
|
}else{
|
|
return 0;
|
|
}
|
|
#else
|
|
return !sqlite3Atoi64(z, pResult, length, enc);
|
|
#endif /* SQLITE_OMIT_FLOATING_POINT */
|
|
}
|
|
#if defined(_MSC_VER)
|
|
#pragma warning(default : 4756)
|
|
#endif
|
|
|
|
/*
|
|
** Render an signed 64-bit integer as text. Store the result in zOut[] and
|
|
** return the length of the string that was stored, in bytes. The value
|
|
** returned does not include the zero terminator at the end of the output
|
|
** string.
|
|
**
|
|
** The caller must ensure that zOut[] is at least 21 bytes in size.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3Int64ToText(i64 v, char *zOut){
|
|
int i;
|
|
u64 x;
|
|
char zTemp[22];
|
|
if( v<0 ){
|
|
x = (v==SMALLEST_INT64) ? ((u64)1)<<63 : (u64)-v;
|
|
}else{
|
|
x = v;
|
|
}
|
|
i = sizeof(zTemp)-2;
|
|
zTemp[sizeof(zTemp)-1] = 0;
|
|
while( 1 /*exit-by-break*/ ){
|
|
zTemp[i] = (x%10) + '0';
|
|
x = x/10;
|
|
if( x==0 ) break;
|
|
i--;
|
|
};
|
|
if( v<0 ) zTemp[--i] = '-';
|
|
memcpy(zOut, &zTemp[i], sizeof(zTemp)-i);
|
|
return sizeof(zTemp)-1-i;
|
|
}
|
|
|
|
/*
|
|
** Compare the 19-character string zNum against the text representation
|
|
** value 2^63: 9223372036854775808. Return negative, zero, or positive
|
|
** if zNum is less than, equal to, or greater than the string.
|
|
** Note that zNum must contain exactly 19 characters.
|
|
**
|
|
** Unlike memcmp() this routine is guaranteed to return the difference
|
|
** in the values of the last digit if the only difference is in the
|
|
** last digit. So, for example,
|
|
**
|
|
** compare2pow63("9223372036854775800", 1)
|
|
**
|
|
** will return -8.
|
|
*/
|
|
static int compare2pow63(const char *zNum, int incr){
|
|
int c = 0;
|
|
int i;
|
|
/* 012345678901234567 */
|
|
const char *pow63 = "922337203685477580";
|
|
for(i=0; c==0 && i<18; i++){
|
|
c = (zNum[i*incr]-pow63[i])*10;
|
|
}
|
|
if( c==0 ){
|
|
c = zNum[18*incr] - '8';
|
|
testcase( c==(-1) );
|
|
testcase( c==0 );
|
|
testcase( c==(+1) );
|
|
}
|
|
return c;
|
|
}
|
|
|
|
/*
|
|
** Convert zNum to a 64-bit signed integer. zNum must be decimal. This
|
|
** routine does *not* accept hexadecimal notation.
|
|
**
|
|
** Returns:
|
|
**
|
|
** -1 Not even a prefix of the input text looks like an integer
|
|
** 0 Successful transformation. Fits in a 64-bit signed integer.
|
|
** 1 Excess non-space text after the integer value
|
|
** 2 Integer too large for a 64-bit signed integer or is malformed
|
|
** 3 Special case of 9223372036854775808
|
|
**
|
|
** length is the number of bytes in the string (bytes, not characters).
|
|
** The string is not necessarily zero-terminated. The encoding is
|
|
** given by enc.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
|
|
int incr;
|
|
u64 u = 0;
|
|
int neg = 0; /* assume positive */
|
|
int i;
|
|
int c = 0;
|
|
int nonNum = 0; /* True if input contains UTF16 with high byte non-zero */
|
|
int rc; /* Baseline return code */
|
|
const char *zStart;
|
|
const char *zEnd = zNum + length;
|
|
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
|
|
if( enc==SQLITE_UTF8 ){
|
|
incr = 1;
|
|
}else{
|
|
incr = 2;
|
|
length &= ~1;
|
|
assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
|
|
for(i=3-enc; i<length && zNum[i]==0; i+=2){}
|
|
nonNum = i<length;
|
|
zEnd = &zNum[i^1];
|
|
zNum += (enc&1);
|
|
}
|
|
while( zNum<zEnd && sqlite3Isspace(*zNum) ) zNum+=incr;
|
|
if( zNum<zEnd ){
|
|
if( *zNum=='-' ){
|
|
neg = 1;
|
|
zNum+=incr;
|
|
}else if( *zNum=='+' ){
|
|
zNum+=incr;
|
|
}
|
|
}
|
|
zStart = zNum;
|
|
while( zNum<zEnd && zNum[0]=='0' ){ zNum+=incr; } /* Skip leading zeros. */
|
|
for(i=0; &zNum[i]<zEnd && (c=zNum[i])>='0' && c<='9'; i+=incr){
|
|
u = u*10 + c - '0';
|
|
}
|
|
testcase( i==18*incr );
|
|
testcase( i==19*incr );
|
|
testcase( i==20*incr );
|
|
if( u>LARGEST_INT64 ){
|
|
/* This test and assignment is needed only to suppress UB warnings
|
|
** from clang and -fsanitize=undefined. This test and assignment make
|
|
** the code a little larger and slower, and no harm comes from omitting
|
|
** them, but we must appease the undefined-behavior pharisees. */
|
|
*pNum = neg ? SMALLEST_INT64 : LARGEST_INT64;
|
|
}else if( neg ){
|
|
*pNum = -(i64)u;
|
|
}else{
|
|
*pNum = (i64)u;
|
|
}
|
|
rc = 0;
|
|
if( i==0 && zStart==zNum ){ /* No digits */
|
|
rc = -1;
|
|
}else if( nonNum ){ /* UTF16 with high-order bytes non-zero */
|
|
rc = 1;
|
|
}else if( &zNum[i]<zEnd ){ /* Extra bytes at the end */
|
|
int jj = i;
|
|
do{
|
|
if( !sqlite3Isspace(zNum[jj]) ){
|
|
rc = 1; /* Extra non-space text after the integer */
|
|
break;
|
|
}
|
|
jj += incr;
|
|
}while( &zNum[jj]<zEnd );
|
|
}
|
|
if( i<19*incr ){
|
|
/* Less than 19 digits, so we know that it fits in 64 bits */
|
|
assert( u<=LARGEST_INT64 );
|
|
return rc;
|
|
}else{
|
|
/* zNum is a 19-digit numbers. Compare it against 9223372036854775808. */
|
|
c = i>19*incr ? 1 : compare2pow63(zNum, incr);
|
|
if( c<0 ){
|
|
/* zNum is less than 9223372036854775808 so it fits */
|
|
assert( u<=LARGEST_INT64 );
|
|
return rc;
|
|
}else{
|
|
*pNum = neg ? SMALLEST_INT64 : LARGEST_INT64;
|
|
if( c>0 ){
|
|
/* zNum is greater than 9223372036854775808 so it overflows */
|
|
return 2;
|
|
}else{
|
|
/* zNum is exactly 9223372036854775808. Fits if negative. The
|
|
** special case 2 overflow if positive */
|
|
assert( u-1==LARGEST_INT64 );
|
|
return neg ? rc : 3;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Transform a UTF-8 integer literal, in either decimal or hexadecimal,
|
|
** into a 64-bit signed integer. This routine accepts hexadecimal literals,
|
|
** whereas sqlite3Atoi64() does not.
|
|
**
|
|
** Returns:
|
|
**
|
|
** 0 Successful transformation. Fits in a 64-bit signed integer.
|
|
** 1 Excess text after the integer value
|
|
** 2 Integer too large for a 64-bit signed integer or is malformed
|
|
** 3 Special case of 9223372036854775808
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char *z, i64 *pOut){
|
|
#ifndef SQLITE_OMIT_HEX_INTEGER
|
|
if( z[0]=='0'
|
|
&& (z[1]=='x' || z[1]=='X')
|
|
){
|
|
u64 u = 0;
|
|
int i, k;
|
|
for(i=2; z[i]=='0'; i++){}
|
|
for(k=i; sqlite3Isxdigit(z[k]); k++){
|
|
u = u*16 + sqlite3HexToInt(z[k]);
|
|
}
|
|
memcpy(pOut, &u, 8);
|
|
if( k-i>16 ) return 2;
|
|
if( z[k]!=0 ) return 1;
|
|
return 0;
|
|
}else
|
|
#endif /* SQLITE_OMIT_HEX_INTEGER */
|
|
{
|
|
int n = (int)(0x3fffffff&strspn(z,"+- \n\t0123456789"));
|
|
if( z[n] ) n++;
|
|
return sqlite3Atoi64(z, pOut, n, SQLITE_UTF8);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** If zNum represents an integer that will fit in 32-bits, then set
|
|
** *pValue to that integer and return true. Otherwise return false.
|
|
**
|
|
** This routine accepts both decimal and hexadecimal notation for integers.
|
|
**
|
|
** Any non-numeric characters that following zNum are ignored.
|
|
** This is different from sqlite3Atoi64() which requires the
|
|
** input number to be zero-terminated.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3GetInt32(const char *zNum, int *pValue){
|
|
sqlite_int64 v = 0;
|
|
int i, c;
|
|
int neg = 0;
|
|
if( zNum[0]=='-' ){
|
|
neg = 1;
|
|
zNum++;
|
|
}else if( zNum[0]=='+' ){
|
|
zNum++;
|
|
}
|
|
#ifndef SQLITE_OMIT_HEX_INTEGER
|
|
else if( zNum[0]=='0'
|
|
&& (zNum[1]=='x' || zNum[1]=='X')
|
|
&& sqlite3Isxdigit(zNum[2])
|
|
){
|
|
u32 u = 0;
|
|
zNum += 2;
|
|
while( zNum[0]=='0' ) zNum++;
|
|
for(i=0; i<8 && sqlite3Isxdigit(zNum[i]); i++){
|
|
u = u*16 + sqlite3HexToInt(zNum[i]);
|
|
}
|
|
if( (u&0x80000000)==0 && sqlite3Isxdigit(zNum[i])==0 ){
|
|
memcpy(pValue, &u, 4);
|
|
return 1;
|
|
}else{
|
|
return 0;
|
|
}
|
|
}
|
|
#endif
|
|
if( !sqlite3Isdigit(zNum[0]) ) return 0;
|
|
while( zNum[0]=='0' ) zNum++;
|
|
for(i=0; i<11 && (c = zNum[i] - '0')>=0 && c<=9; i++){
|
|
v = v*10 + c;
|
|
}
|
|
|
|
/* The longest decimal representation of a 32 bit integer is 10 digits:
|
|
**
|
|
** 1234567890
|
|
** 2^31 -> 2147483648
|
|
*/
|
|
testcase( i==10 );
|
|
if( i>10 ){
|
|
return 0;
|
|
}
|
|
testcase( v-neg==2147483647 );
|
|
if( v-neg>2147483647 ){
|
|
return 0;
|
|
}
|
|
if( neg ){
|
|
v = -v;
|
|
}
|
|
*pValue = (int)v;
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
** Return a 32-bit integer value extracted from a string. If the
|
|
** string is not an integer, just return 0.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3Atoi(const char *z){
|
|
int x = 0;
|
|
sqlite3GetInt32(z, &x);
|
|
return x;
|
|
}
|
|
|
|
/*
|
|
** Decode a floating-point value into an approximate decimal
|
|
** representation.
|
|
**
|
|
** Round the decimal representation to n significant digits if
|
|
** n is positive. Or round to -n signficant digits after the
|
|
** decimal point if n is negative. No rounding is performed if
|
|
** n is zero.
|
|
**
|
|
** The significant digits of the decimal representation are
|
|
** stored in p->z[] which is a often (but not always) a pointer
|
|
** into the middle of p->zBuf[]. There are p->n significant digits.
|
|
** The p->z[] array is *not* zero-terminated.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3FpDecode(FpDecode *p, double r, int iRound, int mxRound){
|
|
int i;
|
|
u64 v;
|
|
int e, exp = 0;
|
|
p->isSpecial = 0;
|
|
p->z = p->zBuf;
|
|
|
|
/* Convert negative numbers to positive. Deal with Infinity, 0.0, and
|
|
** NaN. */
|
|
if( r<0.0 ){
|
|
p->sign = '-';
|
|
r = -r;
|
|
}else if( r==0.0 ){
|
|
p->sign = '+';
|
|
p->n = 1;
|
|
p->iDP = 1;
|
|
p->z = "0";
|
|
return;
|
|
}else{
|
|
p->sign = '+';
|
|
}
|
|
memcpy(&v,&r,8);
|
|
e = v>>52;
|
|
if( (e&0x7ff)==0x7ff ){
|
|
p->isSpecial = 1 + (v!=0x7ff0000000000000LL);
|
|
p->n = 0;
|
|
p->iDP = 0;
|
|
return;
|
|
}
|
|
|
|
/* Multiply r by powers of ten until it lands somewhere in between
|
|
** 1.0e+19 and 1.0e+17.
|
|
*/
|
|
if( sqlite3Config.bUseLongDouble ){
|
|
LONGDOUBLE_TYPE rr = r;
|
|
if( rr>=1.0e+19 ){
|
|
while( rr>=1.0e+119L ){ exp+=100; rr *= 1.0e-100L; }
|
|
while( rr>=1.0e+29L ){ exp+=10; rr *= 1.0e-10L; }
|
|
while( rr>=1.0e+19L ){ exp++; rr *= 1.0e-1L; }
|
|
}else{
|
|
while( rr<1.0e-97L ){ exp-=100; rr *= 1.0e+100L; }
|
|
while( rr<1.0e+07L ){ exp-=10; rr *= 1.0e+10L; }
|
|
while( rr<1.0e+17L ){ exp--; rr *= 1.0e+1L; }
|
|
}
|
|
v = (u64)rr;
|
|
}else{
|
|
/* If high-precision floating point is not available using "long double",
|
|
** then use Dekker-style double-double computation to increase the
|
|
** precision.
|
|
**
|
|
** The error terms on constants like 1.0e+100 computed using the
|
|
** decimal extension, for example as follows:
|
|
**
|
|
** SELECT decimal_exp(decimal_sub('1.0e+100',decimal(1.0e+100)));
|
|
*/
|
|
double rr[2];
|
|
rr[0] = r;
|
|
rr[1] = 0.0;
|
|
if( rr[0]>9.223372036854774784e+18 ){
|
|
while( rr[0]>9.223372036854774784e+118 ){
|
|
exp += 100;
|
|
dekkerMul2(rr, 1.0e-100, -1.99918998026028836196e-117);
|
|
}
|
|
while( rr[0]>9.223372036854774784e+28 ){
|
|
exp += 10;
|
|
dekkerMul2(rr, 1.0e-10, -3.6432197315497741579e-27);
|
|
}
|
|
while( rr[0]>9.223372036854774784e+18 ){
|
|
exp += 1;
|
|
dekkerMul2(rr, 1.0e-01, -5.5511151231257827021e-18);
|
|
}
|
|
}else{
|
|
while( rr[0]<9.223372036854774784e-83 ){
|
|
exp -= 100;
|
|
dekkerMul2(rr, 1.0e+100, -1.5902891109759918046e+83);
|
|
}
|
|
while( rr[0]<9.223372036854774784e+07 ){
|
|
exp -= 10;
|
|
dekkerMul2(rr, 1.0e+10, 0.0);
|
|
}
|
|
while( rr[0]<9.22337203685477478e+17 ){
|
|
exp -= 1;
|
|
dekkerMul2(rr, 1.0e+01, 0.0);
|
|
}
|
|
}
|
|
v = rr[1]<0.0 ? (u64)rr[0]-(u64)(-rr[1]) : (u64)rr[0]+(u64)rr[1];
|
|
}
|
|
|
|
|
|
/* Extract significant digits. */
|
|
i = sizeof(p->zBuf)-1;
|
|
assert( v>0 );
|
|
while( v ){ p->zBuf[i--] = (v%10) + '0'; v /= 10; }
|
|
assert( i>=0 && i<sizeof(p->zBuf)-1 );
|
|
p->n = sizeof(p->zBuf) - 1 - i;
|
|
assert( p->n>0 );
|
|
assert( p->n<sizeof(p->zBuf) );
|
|
p->iDP = p->n + exp;
|
|
if( iRound<=0 ){
|
|
iRound = p->iDP - iRound;
|
|
if( iRound==0 && p->zBuf[i+1]>='5' ){
|
|
iRound = 1;
|
|
p->zBuf[i--] = '0';
|
|
p->n++;
|
|
p->iDP++;
|
|
}
|
|
}
|
|
if( iRound>0 && (iRound<p->n || p->n>mxRound) ){
|
|
char *z = &p->zBuf[i+1];
|
|
if( iRound>mxRound ) iRound = mxRound;
|
|
p->n = iRound;
|
|
if( z[iRound]>='5' ){
|
|
int j = iRound-1;
|
|
while( 1 /*exit-by-break*/ ){
|
|
z[j]++;
|
|
if( z[j]<='9' ) break;
|
|
z[j] = '0';
|
|
if( j==0 ){
|
|
p->z[i--] = '1';
|
|
p->n++;
|
|
p->iDP++;
|
|
break;
|
|
}else{
|
|
j--;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
p->z = &p->zBuf[i+1];
|
|
assert( i+p->n < sizeof(p->zBuf) );
|
|
while( ALWAYS(p->n>0) && p->z[p->n-1]=='0' ){ p->n--; }
|
|
}
|
|
|
|
/*
|
|
** Try to convert z into an unsigned 32-bit integer. Return true on
|
|
** success and false if there is an error.
|
|
**
|
|
** Only decimal notation is accepted.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3GetUInt32(const char *z, u32 *pI){
|
|
u64 v = 0;
|
|
int i;
|
|
for(i=0; sqlite3Isdigit(z[i]); i++){
|
|
v = v*10 + z[i] - '0';
|
|
if( v>4294967296LL ){ *pI = 0; return 0; }
|
|
}
|
|
if( i==0 || z[i]!=0 ){ *pI = 0; return 0; }
|
|
*pI = (u32)v;
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
** The variable-length integer encoding is as follows:
|
|
**
|
|
** KEY:
|
|
** A = 0xxxxxxx 7 bits of data and one flag bit
|
|
** B = 1xxxxxxx 7 bits of data and one flag bit
|
|
** C = xxxxxxxx 8 bits of data
|
|
**
|
|
** 7 bits - A
|
|
** 14 bits - BA
|
|
** 21 bits - BBA
|
|
** 28 bits - BBBA
|
|
** 35 bits - BBBBA
|
|
** 42 bits - BBBBBA
|
|
** 49 bits - BBBBBBA
|
|
** 56 bits - BBBBBBBA
|
|
** 64 bits - BBBBBBBBC
|
|
*/
|
|
|
|
/*
|
|
** Write a 64-bit variable-length integer to memory starting at p[0].
|
|
** The length of data write will be between 1 and 9 bytes. The number
|
|
** of bytes written is returned.
|
|
**
|
|
** A variable-length integer consists of the lower 7 bits of each byte
|
|
** for all bytes that have the 8th bit set and one byte with the 8th
|
|
** bit clear. Except, if we get to the 9th byte, it stores the full
|
|
** 8 bits and is the last byte.
|
|
*/
|
|
static int SQLITE_NOINLINE putVarint64(unsigned char *p, u64 v){
|
|
int i, j, n;
|
|
u8 buf[10];
|
|
if( v & (((u64)0xff000000)<<32) ){
|
|
p[8] = (u8)v;
|
|
v >>= 8;
|
|
for(i=7; i>=0; i--){
|
|
p[i] = (u8)((v & 0x7f) | 0x80);
|
|
v >>= 7;
|
|
}
|
|
return 9;
|
|
}
|
|
n = 0;
|
|
do{
|
|
buf[n++] = (u8)((v & 0x7f) | 0x80);
|
|
v >>= 7;
|
|
}while( v!=0 );
|
|
buf[0] &= 0x7f;
|
|
assert( n<=9 );
|
|
for(i=0, j=n-1; j>=0; j--, i++){
|
|
p[i] = buf[j];
|
|
}
|
|
return n;
|
|
}
|
|
SQLITE_PRIVATE int sqlite3PutVarint(unsigned char *p, u64 v){
|
|
if( v<=0x7f ){
|
|
p[0] = v&0x7f;
|
|
return 1;
|
|
}
|
|
if( v<=0x3fff ){
|
|
p[0] = ((v>>7)&0x7f)|0x80;
|
|
p[1] = v&0x7f;
|
|
return 2;
|
|
}
|
|
return putVarint64(p,v);
|
|
}
|
|
|
|
/*
|
|
** Bitmasks used by sqlite3GetVarint(). These precomputed constants
|
|
** are defined here rather than simply putting the constant expressions
|
|
** inline in order to work around bugs in the RVT compiler.
|
|
**
|
|
** SLOT_2_0 A mask for (0x7f<<14) | 0x7f
|
|
**
|
|
** SLOT_4_2_0 A mask for (0x7f<<28) | SLOT_2_0
|
|
*/
|
|
#define SLOT_2_0 0x001fc07f
|
|
#define SLOT_4_2_0 0xf01fc07f
|
|
|
|
|
|
/*
|
|
** Read a 64-bit variable-length integer from memory starting at p[0].
|
|
** Return the number of bytes read. The value is stored in *v.
|
|
*/
|
|
SQLITE_PRIVATE u8 sqlite3GetVarint(const unsigned char *p, u64 *v){
|
|
u32 a,b,s;
|
|
|
|
if( ((signed char*)p)[0]>=0 ){
|
|
*v = *p;
|
|
return 1;
|
|
}
|
|
if( ((signed char*)p)[1]>=0 ){
|
|
*v = ((u32)(p[0]&0x7f)<<7) | p[1];
|
|
return 2;
|
|
}
|
|
|
|
/* Verify that constants are precomputed correctly */
|
|
assert( SLOT_2_0 == ((0x7f<<14) | (0x7f)) );
|
|
assert( SLOT_4_2_0 == ((0xfU<<28) | (0x7f<<14) | (0x7f)) );
|
|
|
|
a = ((u32)p[0])<<14;
|
|
b = p[1];
|
|
p += 2;
|
|
a |= *p;
|
|
/* a: p0<<14 | p2 (unmasked) */
|
|
if (!(a&0x80))
|
|
{
|
|
a &= SLOT_2_0;
|
|
b &= 0x7f;
|
|
b = b<<7;
|
|
a |= b;
|
|
*v = a;
|
|
return 3;
|
|
}
|
|
|
|
/* CSE1 from below */
|
|
a &= SLOT_2_0;
|
|
p++;
|
|
b = b<<14;
|
|
b |= *p;
|
|
/* b: p1<<14 | p3 (unmasked) */
|
|
if (!(b&0x80))
|
|
{
|
|
b &= SLOT_2_0;
|
|
/* moved CSE1 up */
|
|
/* a &= (0x7f<<14)|(0x7f); */
|
|
a = a<<7;
|
|
a |= b;
|
|
*v = a;
|
|
return 4;
|
|
}
|
|
|
|
/* a: p0<<14 | p2 (masked) */
|
|
/* b: p1<<14 | p3 (unmasked) */
|
|
/* 1:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
|
|
/* moved CSE1 up */
|
|
/* a &= (0x7f<<14)|(0x7f); */
|
|
b &= SLOT_2_0;
|
|
s = a;
|
|
/* s: p0<<14 | p2 (masked) */
|
|
|
|
p++;
|
|
a = a<<14;
|
|
a |= *p;
|
|
/* a: p0<<28 | p2<<14 | p4 (unmasked) */
|
|
if (!(a&0x80))
|
|
{
|
|
/* we can skip these cause they were (effectively) done above
|
|
** while calculating s */
|
|
/* a &= (0x7f<<28)|(0x7f<<14)|(0x7f); */
|
|
/* b &= (0x7f<<14)|(0x7f); */
|
|
b = b<<7;
|
|
a |= b;
|
|
s = s>>18;
|
|
*v = ((u64)s)<<32 | a;
|
|
return 5;
|
|
}
|
|
|
|
/* 2:save off p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
|
|
s = s<<7;
|
|
s |= b;
|
|
/* s: p0<<21 | p1<<14 | p2<<7 | p3 (masked) */
|
|
|
|
p++;
|
|
b = b<<14;
|
|
b |= *p;
|
|
/* b: p1<<28 | p3<<14 | p5 (unmasked) */
|
|
if (!(b&0x80))
|
|
{
|
|
/* we can skip this cause it was (effectively) done above in calc'ing s */
|
|
/* b &= (0x7f<<28)|(0x7f<<14)|(0x7f); */
|
|
a &= SLOT_2_0;
|
|
a = a<<7;
|
|
a |= b;
|
|
s = s>>18;
|
|
*v = ((u64)s)<<32 | a;
|
|
return 6;
|
|
}
|
|
|
|
p++;
|
|
a = a<<14;
|
|
a |= *p;
|
|
/* a: p2<<28 | p4<<14 | p6 (unmasked) */
|
|
if (!(a&0x80))
|
|
{
|
|
a &= SLOT_4_2_0;
|
|
b &= SLOT_2_0;
|
|
b = b<<7;
|
|
a |= b;
|
|
s = s>>11;
|
|
*v = ((u64)s)<<32 | a;
|
|
return 7;
|
|
}
|
|
|
|
/* CSE2 from below */
|
|
a &= SLOT_2_0;
|
|
p++;
|
|
b = b<<14;
|
|
b |= *p;
|
|
/* b: p3<<28 | p5<<14 | p7 (unmasked) */
|
|
if (!(b&0x80))
|
|
{
|
|
b &= SLOT_4_2_0;
|
|
/* moved CSE2 up */
|
|
/* a &= (0x7f<<14)|(0x7f); */
|
|
a = a<<7;
|
|
a |= b;
|
|
s = s>>4;
|
|
*v = ((u64)s)<<32 | a;
|
|
return 8;
|
|
}
|
|
|
|
p++;
|
|
a = a<<15;
|
|
a |= *p;
|
|
/* a: p4<<29 | p6<<15 | p8 (unmasked) */
|
|
|
|
/* moved CSE2 up */
|
|
/* a &= (0x7f<<29)|(0x7f<<15)|(0xff); */
|
|
b &= SLOT_2_0;
|
|
b = b<<8;
|
|
a |= b;
|
|
|
|
s = s<<4;
|
|
b = p[-4];
|
|
b &= 0x7f;
|
|
b = b>>3;
|
|
s |= b;
|
|
|
|
*v = ((u64)s)<<32 | a;
|
|
|
|
return 9;
|
|
}
|
|
|
|
/*
|
|
** Read a 32-bit variable-length integer from memory starting at p[0].
|
|
** Return the number of bytes read. The value is stored in *v.
|
|
**
|
|
** If the varint stored in p[0] is larger than can fit in a 32-bit unsigned
|
|
** integer, then set *v to 0xffffffff.
|
|
**
|
|
** A MACRO version, getVarint32, is provided which inlines the
|
|
** single-byte case. All code should use the MACRO version as
|
|
** this function assumes the single-byte case has already been handled.
|
|
*/
|
|
SQLITE_PRIVATE u8 sqlite3GetVarint32(const unsigned char *p, u32 *v){
|
|
u64 v64;
|
|
u8 n;
|
|
|
|
/* Assume that the single-byte case has already been handled by
|
|
** the getVarint32() macro */
|
|
assert( (p[0] & 0x80)!=0 );
|
|
|
|
if( (p[1] & 0x80)==0 ){
|
|
/* This is the two-byte case */
|
|
*v = ((p[0]&0x7f)<<7) | p[1];
|
|
return 2;
|
|
}
|
|
if( (p[2] & 0x80)==0 ){
|
|
/* This is the three-byte case */
|
|
*v = ((p[0]&0x7f)<<14) | ((p[1]&0x7f)<<7) | p[2];
|
|
return 3;
|
|
}
|
|
/* four or more bytes */
|
|
n = sqlite3GetVarint(p, &v64);
|
|
assert( n>3 && n<=9 );
|
|
if( (v64 & SQLITE_MAX_U32)!=v64 ){
|
|
*v = 0xffffffff;
|
|
}else{
|
|
*v = (u32)v64;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
/*
|
|
** Return the number of bytes that will be needed to store the given
|
|
** 64-bit integer.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3VarintLen(u64 v){
|
|
int i;
|
|
for(i=1; (v >>= 7)!=0; i++){ assert( i<10 ); }
|
|
return i;
|
|
}
|
|
|
|
|
|
/*
|
|
** Read or write a four-byte big-endian integer value.
|
|
*/
|
|
SQLITE_PRIVATE u32 sqlite3Get4byte(const u8 *p){
|
|
#if SQLITE_BYTEORDER==4321
|
|
u32 x;
|
|
memcpy(&x,p,4);
|
|
return x;
|
|
#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
|
|
u32 x;
|
|
memcpy(&x,p,4);
|
|
return __builtin_bswap32(x);
|
|
#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
|
|
u32 x;
|
|
memcpy(&x,p,4);
|
|
return _byteswap_ulong(x);
|
|
#else
|
|
testcase( p[0]&0x80 );
|
|
return ((unsigned)p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
|
|
#endif
|
|
}
|
|
SQLITE_PRIVATE void sqlite3Put4byte(unsigned char *p, u32 v){
|
|
#if SQLITE_BYTEORDER==4321
|
|
memcpy(p,&v,4);
|
|
#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000
|
|
u32 x = __builtin_bswap32(v);
|
|
memcpy(p,&x,4);
|
|
#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300
|
|
u32 x = _byteswap_ulong(v);
|
|
memcpy(p,&x,4);
|
|
#else
|
|
p[0] = (u8)(v>>24);
|
|
p[1] = (u8)(v>>16);
|
|
p[2] = (u8)(v>>8);
|
|
p[3] = (u8)v;
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
** Translate a single byte of Hex into an integer.
|
|
** This routine only works if h really is a valid hexadecimal
|
|
** character: 0..9a..fA..F
|
|
*/
|
|
SQLITE_PRIVATE u8 sqlite3HexToInt(int h){
|
|
assert( (h>='0' && h<='9') || (h>='a' && h<='f') || (h>='A' && h<='F') );
|
|
#ifdef SQLITE_ASCII
|
|
h += 9*(1&(h>>6));
|
|
#endif
|
|
#ifdef SQLITE_EBCDIC
|
|
h += 9*(1&~(h>>4));
|
|
#endif
|
|
return (u8)(h & 0xf);
|
|
}
|
|
|
|
#if !defined(SQLITE_OMIT_BLOB_LITERAL)
|
|
/*
|
|
** Convert a BLOB literal of the form "x'hhhhhh'" into its binary
|
|
** value. Return a pointer to its binary value. Space to hold the
|
|
** binary value has been obtained from malloc and must be freed by
|
|
** the calling routine.
|
|
*/
|
|
SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3 *db, const char *z, int n){
|
|
char *zBlob;
|
|
int i;
|
|
|
|
zBlob = (char *)sqlite3DbMallocRawNN(db, n/2 + 1);
|
|
n--;
|
|
if( zBlob ){
|
|
for(i=0; i<n; i+=2){
|
|
zBlob[i/2] = (sqlite3HexToInt(z[i])<<4) | sqlite3HexToInt(z[i+1]);
|
|
}
|
|
zBlob[i/2] = 0;
|
|
}
|
|
return zBlob;
|
|
}
|
|
#endif /* !SQLITE_OMIT_BLOB_LITERAL */
|
|
|
|
/*
|
|
** Log an error that is an API call on a connection pointer that should
|
|
** not have been used. The "type" of connection pointer is given as the
|
|
** argument. The zType is a word like "NULL" or "closed" or "invalid".
|
|
*/
|
|
static void logBadConnection(const char *zType){
|
|
sqlite3_log(SQLITE_MISUSE,
|
|
"API call with %s database connection pointer",
|
|
zType
|
|
);
|
|
}
|
|
|
|
/*
|
|
** Check to make sure we have a valid db pointer. This test is not
|
|
** foolproof but it does provide some measure of protection against
|
|
** misuse of the interface such as passing in db pointers that are
|
|
** NULL or which have been previously closed. If this routine returns
|
|
** 1 it means that the db pointer is valid and 0 if it should not be
|
|
** dereferenced for any reason. The calling function should invoke
|
|
** SQLITE_MISUSE immediately.
|
|
**
|
|
** sqlite3SafetyCheckOk() requires that the db pointer be valid for
|
|
** use. sqlite3SafetyCheckSickOrOk() allows a db pointer that failed to
|
|
** open properly and is not fit for general use but which can be
|
|
** used as an argument to sqlite3_errmsg() or sqlite3_close().
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3SafetyCheckOk(sqlite3 *db){
|
|
u8 eOpenState;
|
|
if( db==0 ){
|
|
logBadConnection("NULL");
|
|
return 0;
|
|
}
|
|
eOpenState = db->eOpenState;
|
|
if( eOpenState!=SQLITE_STATE_OPEN ){
|
|
if( sqlite3SafetyCheckSickOrOk(db) ){
|
|
testcase( sqlite3GlobalConfig.xLog!=0 );
|
|
logBadConnection("unopened");
|
|
}
|
|
return 0;
|
|
}else{
|
|
return 1;
|
|
}
|
|
}
|
|
SQLITE_PRIVATE int sqlite3SafetyCheckSickOrOk(sqlite3 *db){
|
|
u8 eOpenState;
|
|
eOpenState = db->eOpenState;
|
|
if( eOpenState!=SQLITE_STATE_SICK &&
|
|
eOpenState!=SQLITE_STATE_OPEN &&
|
|
eOpenState!=SQLITE_STATE_BUSY ){
|
|
testcase( sqlite3GlobalConfig.xLog!=0 );
|
|
logBadConnection("invalid");
|
|
return 0;
|
|
}else{
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Attempt to add, subtract, or multiply the 64-bit signed value iB against
|
|
** the other 64-bit signed integer at *pA and store the result in *pA.
|
|
** Return 0 on success. Or if the operation would have resulted in an
|
|
** overflow, leave *pA unchanged and return 1.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3AddInt64(i64 *pA, i64 iB){
|
|
#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER)
|
|
return __builtin_add_overflow(*pA, iB, pA);
|
|
#else
|
|
i64 iA = *pA;
|
|
testcase( iA==0 ); testcase( iA==1 );
|
|
testcase( iB==-1 ); testcase( iB==0 );
|
|
if( iB>=0 ){
|
|
testcase( iA>0 && LARGEST_INT64 - iA == iB );
|
|
testcase( iA>0 && LARGEST_INT64 - iA == iB - 1 );
|
|
if( iA>0 && LARGEST_INT64 - iA < iB ) return 1;
|
|
}else{
|
|
testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 1 );
|
|
testcase( iA<0 && -(iA + LARGEST_INT64) == iB + 2 );
|
|
if( iA<0 && -(iA + LARGEST_INT64) > iB + 1 ) return 1;
|
|
}
|
|
*pA += iB;
|
|
return 0;
|
|
#endif
|
|
}
|
|
SQLITE_PRIVATE int sqlite3SubInt64(i64 *pA, i64 iB){
|
|
#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER)
|
|
return __builtin_sub_overflow(*pA, iB, pA);
|
|
#else
|
|
testcase( iB==SMALLEST_INT64+1 );
|
|
if( iB==SMALLEST_INT64 ){
|
|
testcase( (*pA)==(-1) ); testcase( (*pA)==0 );
|
|
if( (*pA)>=0 ) return 1;
|
|
*pA -= iB;
|
|
return 0;
|
|
}else{
|
|
return sqlite3AddInt64(pA, -iB);
|
|
}
|
|
#endif
|
|
}
|
|
SQLITE_PRIVATE int sqlite3MulInt64(i64 *pA, i64 iB){
|
|
#if GCC_VERSION>=5004000 && !defined(__INTEL_COMPILER)
|
|
return __builtin_mul_overflow(*pA, iB, pA);
|
|
#else
|
|
i64 iA = *pA;
|
|
if( iB>0 ){
|
|
if( iA>LARGEST_INT64/iB ) return 1;
|
|
if( iA<SMALLEST_INT64/iB ) return 1;
|
|
}else if( iB<0 ){
|
|
if( iA>0 ){
|
|
if( iB<SMALLEST_INT64/iA ) return 1;
|
|
}else if( iA<0 ){
|
|
if( iB==SMALLEST_INT64 ) return 1;
|
|
if( iA==SMALLEST_INT64 ) return 1;
|
|
if( -iA>LARGEST_INT64/-iB ) return 1;
|
|
}
|
|
}
|
|
*pA = iA*iB;
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
** Compute the absolute value of a 32-bit signed integer, of possible. Or
|
|
** if the integer has a value of -2147483648, return +2147483647
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3AbsInt32(int x){
|
|
if( x>=0 ) return x;
|
|
if( x==(int)0x80000000 ) return 0x7fffffff;
|
|
return -x;
|
|
}
|
|
|
|
#ifdef SQLITE_ENABLE_8_3_NAMES
|
|
/*
|
|
** If SQLITE_ENABLE_8_3_NAMES is set at compile-time and if the database
|
|
** filename in zBaseFilename is a URI with the "8_3_names=1" parameter and
|
|
** if filename in z[] has a suffix (a.k.a. "extension") that is longer than
|
|
** three characters, then shorten the suffix on z[] to be the last three
|
|
** characters of the original suffix.
|
|
**
|
|
** If SQLITE_ENABLE_8_3_NAMES is set to 2 at compile-time, then always
|
|
** do the suffix shortening regardless of URI parameter.
|
|
**
|
|
** Examples:
|
|
**
|
|
** test.db-journal => test.nal
|
|
** test.db-wal => test.wal
|
|
** test.db-shm => test.shm
|
|
** test.db-mj7f3319fa => test.9fa
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
|
|
#if SQLITE_ENABLE_8_3_NAMES<2
|
|
if( sqlite3_uri_boolean(zBaseFilename, "8_3_names", 0) )
|
|
#endif
|
|
{
|
|
int i, sz;
|
|
sz = sqlite3Strlen30(z);
|
|
for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
|
|
if( z[i]=='.' && ALWAYS(sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
** Find (an approximate) sum of two LogEst values. This computation is
|
|
** not a simple "+" operator because LogEst is stored as a logarithmic
|
|
** value.
|
|
**
|
|
*/
|
|
SQLITE_PRIVATE LogEst sqlite3LogEstAdd(LogEst a, LogEst b){
|
|
static const unsigned char x[] = {
|
|
10, 10, /* 0,1 */
|
|
9, 9, /* 2,3 */
|
|
8, 8, /* 4,5 */
|
|
7, 7, 7, /* 6,7,8 */
|
|
6, 6, 6, /* 9,10,11 */
|
|
5, 5, 5, /* 12-14 */
|
|
4, 4, 4, 4, /* 15-18 */
|
|
3, 3, 3, 3, 3, 3, /* 19-24 */
|
|
2, 2, 2, 2, 2, 2, 2, /* 25-31 */
|
|
};
|
|
if( a>=b ){
|
|
if( a>b+49 ) return a;
|
|
if( a>b+31 ) return a+1;
|
|
return a+x[a-b];
|
|
}else{
|
|
if( b>a+49 ) return b;
|
|
if( b>a+31 ) return b+1;
|
|
return b+x[b-a];
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Convert an integer into a LogEst. In other words, compute an
|
|
** approximation for 10*log2(x).
|
|
*/
|
|
SQLITE_PRIVATE LogEst sqlite3LogEst(u64 x){
|
|
static LogEst a[] = { 0, 2, 3, 5, 6, 7, 8, 9 };
|
|
LogEst y = 40;
|
|
if( x<8 ){
|
|
if( x<2 ) return 0;
|
|
while( x<8 ){ y -= 10; x <<= 1; }
|
|
}else{
|
|
#if GCC_VERSION>=5004000
|
|
int i = 60 - __builtin_clzll(x);
|
|
y += i*10;
|
|
x >>= i;
|
|
#else
|
|
while( x>255 ){ y += 40; x >>= 4; } /*OPTIMIZATION-IF-TRUE*/
|
|
while( x>15 ){ y += 10; x >>= 1; }
|
|
#endif
|
|
}
|
|
return a[x&7] + y - 10;
|
|
}
|
|
|
|
/*
|
|
** Convert a double into a LogEst
|
|
** In other words, compute an approximation for 10*log2(x).
|
|
*/
|
|
SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double x){
|
|
u64 a;
|
|
LogEst e;
|
|
assert( sizeof(x)==8 && sizeof(a)==8 );
|
|
if( x<=1 ) return 0;
|
|
if( x<=2000000000 ) return sqlite3LogEst((u64)x);
|
|
memcpy(&a, &x, 8);
|
|
e = (a>>52) - 1022;
|
|
return e*10;
|
|
}
|
|
|
|
/*
|
|
** Convert a LogEst into an integer.
|
|
*/
|
|
SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst x){
|
|
u64 n;
|
|
n = x%10;
|
|
x /= 10;
|
|
if( n>=5 ) n -= 2;
|
|
else if( n>=1 ) n -= 1;
|
|
if( x>60 ) return (u64)LARGEST_INT64;
|
|
return x>=3 ? (n+8)<<(x-3) : (n+8)>>(3-x);
|
|
}
|
|
|
|
/*
|
|
** Add a new name/number pair to a VList. This might require that the
|
|
** VList object be reallocated, so return the new VList. If an OOM
|
|
** error occurs, the original VList returned and the
|
|
** db->mallocFailed flag is set.
|
|
**
|
|
** A VList is really just an array of integers. To destroy a VList,
|
|
** simply pass it to sqlite3DbFree().
|
|
**
|
|
** The first integer is the number of integers allocated for the whole
|
|
** VList. The second integer is the number of integers actually used.
|
|
** Each name/number pair is encoded by subsequent groups of 3 or more
|
|
** integers.
|
|
**
|
|
** Each name/number pair starts with two integers which are the numeric
|
|
** value for the pair and the size of the name/number pair, respectively.
|
|
** The text name overlays one or more following integers. The text name
|
|
** is always zero-terminated.
|
|
**
|
|
** Conceptually:
|
|
**
|
|
** struct VList {
|
|
** int nAlloc; // Number of allocated slots
|
|
** int nUsed; // Number of used slots
|
|
** struct VListEntry {
|
|
** int iValue; // Value for this entry
|
|
** int nSlot; // Slots used by this entry
|
|
** // ... variable name goes here
|
|
** } a[0];
|
|
** }
|
|
**
|
|
** During code generation, pointers to the variable names within the
|
|
** VList are taken. When that happens, nAlloc is set to zero as an
|
|
** indication that the VList may never again be enlarged, since the
|
|
** accompanying realloc() would invalidate the pointers.
|
|
*/
|
|
SQLITE_PRIVATE VList *sqlite3VListAdd(
|
|
sqlite3 *db, /* The database connection used for malloc() */
|
|
VList *pIn, /* The input VList. Might be NULL */
|
|
const char *zName, /* Name of symbol to add */
|
|
int nName, /* Bytes of text in zName */
|
|
int iVal /* Value to associate with zName */
|
|
){
|
|
int nInt; /* number of sizeof(int) objects needed for zName */
|
|
char *z; /* Pointer to where zName will be stored */
|
|
int i; /* Index in pIn[] where zName is stored */
|
|
|
|
nInt = nName/4 + 3;
|
|
assert( pIn==0 || pIn[0]>=3 ); /* Verify ok to add new elements */
|
|
if( pIn==0 || pIn[1]+nInt > pIn[0] ){
|
|
/* Enlarge the allocation */
|
|
sqlite3_int64 nAlloc = (pIn ? 2*(sqlite3_int64)pIn[0] : 10) + nInt;
|
|
VList *pOut = sqlite3DbRealloc(db, pIn, nAlloc*sizeof(int));
|
|
if( pOut==0 ) return pIn;
|
|
if( pIn==0 ) pOut[1] = 2;
|
|
pIn = pOut;
|
|
pIn[0] = nAlloc;
|
|
}
|
|
i = pIn[1];
|
|
pIn[i] = iVal;
|
|
pIn[i+1] = nInt;
|
|
z = (char*)&pIn[i+2];
|
|
pIn[1] = i+nInt;
|
|
assert( pIn[1]<=pIn[0] );
|
|
memcpy(z, zName, nName);
|
|
z[nName] = 0;
|
|
return pIn;
|
|
}
|
|
|
|
/*
|
|
** Return a pointer to the name of a variable in the given VList that
|
|
** has the value iVal. Or return a NULL if there is no such variable in
|
|
** the list
|
|
*/
|
|
SQLITE_PRIVATE const char *sqlite3VListNumToName(VList *pIn, int iVal){
|
|
int i, mx;
|
|
if( pIn==0 ) return 0;
|
|
mx = pIn[1];
|
|
i = 2;
|
|
do{
|
|
if( pIn[i]==iVal ) return (char*)&pIn[i+2];
|
|
i += pIn[i+1];
|
|
}while( i<mx );
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
** Return the number of the variable named zName, if it is in VList.
|
|
** or return 0 if there is no such variable.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3VListNameToNum(VList *pIn, const char *zName, int nName){
|
|
int i, mx;
|
|
if( pIn==0 ) return 0;
|
|
mx = pIn[1];
|
|
i = 2;
|
|
do{
|
|
const char *z = (const char*)&pIn[i+2];
|
|
if( strncmp(z,zName,nName)==0 && z[nName]==0 ) return pIn[i];
|
|
i += pIn[i+1];
|
|
}while( i<mx );
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
** High-resolution hardware timer used for debugging and testing only.
|
|
*/
|
|
#if defined(VDBE_PROFILE) \
|
|
|| defined(SQLITE_PERFORMANCE_TRACE) \
|
|
|| defined(SQLITE_ENABLE_STMT_SCANSTATUS)
|
|
/************** Include hwtime.h in the middle of util.c *********************/
|
|
/************** Begin file hwtime.h ******************************************/
|
|
/*
|
|
** 2008 May 27
|
|
**
|
|
** 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 inline asm code for retrieving "high-performance"
|
|
** counters for x86 and x86_64 class CPUs.
|
|
*/
|
|
#ifndef SQLITE_HWTIME_H
|
|
#define SQLITE_HWTIME_H
|
|
|
|
/*
|
|
** The following routine only works on Pentium-class (or newer) processors.
|
|
** It uses the RDTSC opcode to read the cycle count value out of the
|
|
** processor and returns that value. This can be used for high-res
|
|
** profiling.
|
|
*/
|
|
#if !defined(__STRICT_ANSI__) && \
|
|
(defined(__GNUC__) || defined(_MSC_VER)) && \
|
|
(defined(i386) || defined(__i386__) || defined(_M_IX86))
|
|
|
|
#if defined(__GNUC__)
|
|
|
|
__inline__ sqlite_uint64 sqlite3Hwtime(void){
|
|
unsigned int lo, hi;
|
|
__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
|
|
return (sqlite_uint64)hi << 32 | lo;
|
|
}
|
|
|
|
#elif defined(_MSC_VER)
|
|
|
|
__declspec(naked) __inline sqlite_uint64 __cdecl sqlite3Hwtime(void){
|
|
__asm {
|
|
rdtsc
|
|
ret ; return value at EDX:EAX
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
|
|
|
|
__inline__ sqlite_uint64 sqlite3Hwtime(void){
|
|
unsigned int lo, hi;
|
|
__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
|
|
return (sqlite_uint64)hi << 32 | lo;
|
|
}
|
|
|
|
#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
|
|
|
|
__inline__ sqlite_uint64 sqlite3Hwtime(void){
|
|
unsigned long long retval;
|
|
unsigned long junk;
|
|
__asm__ __volatile__ ("\n\
|
|
1: mftbu %1\n\
|
|
mftb %L0\n\
|
|
mftbu %0\n\
|
|
cmpw %0,%1\n\
|
|
bne 1b"
|
|
: "=r" (retval), "=r" (junk));
|
|
return retval;
|
|
}
|
|
|
|
#else
|
|
|
|
/*
|
|
** asm() is needed for hardware timing support. Without asm(),
|
|
** disable the sqlite3Hwtime() routine.
|
|
**
|
|
** sqlite3Hwtime() is only used for some obscure debugging
|
|
** and analysis configurations, not in any deliverable, so this
|
|
** should not be a great loss.
|
|
*/
|
|
SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
|
|
|
|
#endif
|
|
|
|
#endif /* !defined(SQLITE_HWTIME_H) */
|
|
|
|
/************** End of hwtime.h **********************************************/
|
|
/************** Continuing where we left off in util.c ***********************/
|
|
#endif
|
|
|
|
/************** End of util.c ************************************************/
|
|
/************** Begin file hash.c ********************************************/
|
|
/*
|
|
** 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.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
/* #include <assert.h> */
|
|
|
|
/* Turn bulk memory into a hash table object by initializing the
|
|
** fields of the Hash structure.
|
|
**
|
|
** "pNew" is a pointer to the hash table that is to be initialized.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3HashInit(Hash *pNew){
|
|
assert( pNew!=0 );
|
|
pNew->first = 0;
|
|
pNew->count = 0;
|
|
pNew->htsize = 0;
|
|
pNew->ht = 0;
|
|
}
|
|
|
|
/* 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.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3HashClear(Hash *pH){
|
|
HashElem *elem; /* For looping over all elements of the table */
|
|
|
|
assert( pH!=0 );
|
|
elem = pH->first;
|
|
pH->first = 0;
|
|
sqlite3_free(pH->ht);
|
|
pH->ht = 0;
|
|
pH->htsize = 0;
|
|
while( elem ){
|
|
HashElem *next_elem = elem->next;
|
|
sqlite3_free(elem);
|
|
elem = next_elem;
|
|
}
|
|
pH->count = 0;
|
|
}
|
|
|
|
/*
|
|
** The hashing function.
|
|
*/
|
|
static unsigned int strHash(const char *z){
|
|
unsigned int h = 0;
|
|
unsigned char c;
|
|
while( (c = (unsigned char)*z++)!=0 ){ /*OPTIMIZATION-IF-TRUE*/
|
|
/* Knuth multiplicative hashing. (Sorting & Searching, p. 510).
|
|
** 0x9e3779b1 is 2654435761 which is the closest prime number to
|
|
** (2**32)*golden_ratio, where golden_ratio = (sqrt(5) - 1)/2. */
|
|
h += sqlite3UpperToLower[c];
|
|
h *= 0x9e3779b1;
|
|
}
|
|
return h;
|
|
}
|
|
|
|
|
|
/* Link pNew element into the hash table pH. If pEntry!=0 then also
|
|
** insert pNew into the pEntry hash bucket.
|
|
*/
|
|
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 */
|
|
if( pEntry ){
|
|
pHead = pEntry->count ? pEntry->chain : 0;
|
|
pEntry->count++;
|
|
pEntry->chain = pNew;
|
|
}else{
|
|
pHead = 0;
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
|
|
|
|
/* Resize the hash table so that it contains "new_size" buckets.
|
|
**
|
|
** The hash table might fail to resize if sqlite3_malloc() fails or
|
|
** if the new size is the same as the prior size.
|
|
** Return TRUE if the resize occurs and false if not.
|
|
*/
|
|
static int rehash(Hash *pH, unsigned int new_size){
|
|
struct _ht *new_ht; /* The new hash table */
|
|
HashElem *elem, *next_elem; /* For looping over existing elements */
|
|
|
|
#if SQLITE_MALLOC_SOFT_LIMIT>0
|
|
if( new_size*sizeof(struct _ht)>SQLITE_MALLOC_SOFT_LIMIT ){
|
|
new_size = SQLITE_MALLOC_SOFT_LIMIT/sizeof(struct _ht);
|
|
}
|
|
if( new_size==pH->htsize ) return 0;
|
|
#endif
|
|
|
|
/* The inability to allocates space for a larger hash table is
|
|
** a performance hit but it is not a fatal error. So mark the
|
|
** allocation as a benign. Use sqlite3Malloc()/memset(0) instead of
|
|
** sqlite3MallocZero() to make the allocation, as sqlite3MallocZero()
|
|
** only zeroes the requested number of bytes whereas this module will
|
|
** use the actual amount of space allocated for the hash table (which
|
|
** may be larger than the requested amount).
|
|
*/
|
|
sqlite3BeginBenignMalloc();
|
|
new_ht = (struct _ht *)sqlite3Malloc( new_size*sizeof(struct _ht) );
|
|
sqlite3EndBenignMalloc();
|
|
|
|
if( new_ht==0 ) return 0;
|
|
sqlite3_free(pH->ht);
|
|
pH->ht = new_ht;
|
|
pH->htsize = new_size = sqlite3MallocSize(new_ht)/sizeof(struct _ht);
|
|
memset(new_ht, 0, new_size*sizeof(struct _ht));
|
|
for(elem=pH->first, pH->first=0; elem; elem = next_elem){
|
|
unsigned int h = strHash(elem->pKey) % new_size;
|
|
next_elem = elem->next;
|
|
insertElement(pH, &new_ht[h], elem);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/* This function (for internal use only) locates an element in an
|
|
** hash table that matches the given key. If no element is found,
|
|
** a pointer to a static null element with HashElem.data==0 is returned.
|
|
** If pH is not NULL, then the hash for this key is written to *pH.
|
|
*/
|
|
static HashElem *findElementWithHash(
|
|
const Hash *pH, /* The pH to be searched */
|
|
const char *pKey, /* The key we are searching for */
|
|
unsigned int *pHash /* Write the hash value here */
|
|
){
|
|
HashElem *elem; /* Used to loop thru the element list */
|
|
unsigned int count; /* Number of elements left to test */
|
|
unsigned int h; /* The computed hash */
|
|
static HashElem nullElement = { 0, 0, 0, 0 };
|
|
|
|
if( pH->ht ){ /*OPTIMIZATION-IF-TRUE*/
|
|
struct _ht *pEntry;
|
|
h = strHash(pKey) % pH->htsize;
|
|
pEntry = &pH->ht[h];
|
|
elem = pEntry->chain;
|
|
count = pEntry->count;
|
|
}else{
|
|
h = 0;
|
|
elem = pH->first;
|
|
count = pH->count;
|
|
}
|
|
if( pHash ) *pHash = h;
|
|
while( count ){
|
|
assert( elem!=0 );
|
|
if( sqlite3StrICmp(elem->pKey,pKey)==0 ){
|
|
return elem;
|
|
}
|
|
elem = elem->next;
|
|
count--;
|
|
}
|
|
return &nullElement;
|
|
}
|
|
|
|
/* 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 */
|
|
unsigned 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;
|
|
}
|
|
if( pH->ht ){
|
|
pEntry = &pH->ht[h];
|
|
if( pEntry->chain==elem ){
|
|
pEntry->chain = elem->next;
|
|
}
|
|
assert( pEntry->count>0 );
|
|
pEntry->count--;
|
|
}
|
|
sqlite3_free( 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. Return the data for this element if it is
|
|
** found, or NULL if there is no match.
|
|
*/
|
|
SQLITE_PRIVATE void *sqlite3HashFind(const Hash *pH, const char *pKey){
|
|
assert( pH!=0 );
|
|
assert( pKey!=0 );
|
|
return findElementWithHash(pH, pKey, 0)->data;
|
|
}
|
|
|
|
/* Insert an element into the hash table pH. The key is pKey
|
|
** and the data is "data".
|
|
**
|
|
** If no element exists with a matching key, then a new
|
|
** element is created and 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.
|
|
*/
|
|
SQLITE_PRIVATE void *sqlite3HashInsert(Hash *pH, const char *pKey, void *data){
|
|
unsigned 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 */
|
|
|
|
assert( pH!=0 );
|
|
assert( pKey!=0 );
|
|
elem = findElementWithHash(pH,pKey,&h);
|
|
if( elem->data ){
|
|
void *old_data = elem->data;
|
|
if( data==0 ){
|
|
removeElementGivenHash(pH,elem,h);
|
|
}else{
|
|
elem->data = data;
|
|
elem->pKey = pKey;
|
|
}
|
|
return old_data;
|
|
}
|
|
if( data==0 ) return 0;
|
|
new_elem = (HashElem*)sqlite3Malloc( sizeof(HashElem) );
|
|
if( new_elem==0 ) return data;
|
|
new_elem->pKey = pKey;
|
|
new_elem->data = data;
|
|
pH->count++;
|
|
if( pH->count>=10 && pH->count > 2*pH->htsize ){
|
|
if( rehash(pH, pH->count*2) ){
|
|
assert( pH->htsize>0 );
|
|
h = strHash(pKey) % pH->htsize;
|
|
}
|
|
}
|
|
insertElement(pH, pH->ht ? &pH->ht[h] : 0, new_elem);
|
|
return 0;
|
|
}
|
|
|
|
/************** End of hash.c ************************************************/
|
|
/************** Begin file opcodes.c *****************************************/
|
|
/* Automatically generated. Do not edit */
|
|
/* See the tool/mkopcodec.tcl script for details. */
|
|
#if !defined(SQLITE_OMIT_EXPLAIN) \
|
|
|| defined(VDBE_PROFILE) \
|
|
|| defined(SQLITE_DEBUG)
|
|
#if defined(SQLITE_ENABLE_EXPLAIN_COMMENTS) || defined(SQLITE_DEBUG)
|
|
# define OpHelp(X) "\0" X
|
|
#else
|
|
# define OpHelp(X)
|
|
#endif
|
|
SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
|
|
static const char *const azName[] = {
|
|
/* 0 */ "Savepoint" OpHelp(""),
|
|
/* 1 */ "AutoCommit" OpHelp(""),
|
|
/* 2 */ "Transaction" OpHelp(""),
|
|
/* 3 */ "Checkpoint" OpHelp(""),
|
|
/* 4 */ "JournalMode" OpHelp(""),
|
|
/* 5 */ "Vacuum" OpHelp(""),
|
|
/* 6 */ "VFilter" OpHelp("iplan=r[P3] zplan='P4'"),
|
|
/* 7 */ "VUpdate" OpHelp("data=r[P3@P2]"),
|
|
/* 8 */ "Init" OpHelp("Start at P2"),
|
|
/* 9 */ "Goto" OpHelp(""),
|
|
/* 10 */ "Gosub" OpHelp(""),
|
|
/* 11 */ "InitCoroutine" OpHelp(""),
|
|
/* 12 */ "Yield" OpHelp(""),
|
|
/* 13 */ "MustBeInt" OpHelp(""),
|
|
/* 14 */ "Jump" OpHelp(""),
|
|
/* 15 */ "Once" OpHelp(""),
|
|
/* 16 */ "If" OpHelp(""),
|
|
/* 17 */ "IfNot" OpHelp(""),
|
|
/* 18 */ "IsType" OpHelp("if typeof(P1.P3) in P5 goto P2"),
|
|
/* 19 */ "Not" OpHelp("r[P2]= !r[P1]"),
|
|
/* 20 */ "IfNullRow" OpHelp("if P1.nullRow then r[P3]=NULL, goto P2"),
|
|
/* 21 */ "SeekLT" OpHelp("key=r[P3@P4]"),
|
|
/* 22 */ "SeekLE" OpHelp("key=r[P3@P4]"),
|
|
/* 23 */ "SeekGE" OpHelp("key=r[P3@P4]"),
|
|
/* 24 */ "SeekGT" OpHelp("key=r[P3@P4]"),
|
|
/* 25 */ "IfNotOpen" OpHelp("if( !csr[P1] ) goto P2"),
|
|
/* 26 */ "IfNoHope" OpHelp("key=r[P3@P4]"),
|
|
/* 27 */ "NoConflict" OpHelp("key=r[P3@P4]"),
|
|
/* 28 */ "NotFound" OpHelp("key=r[P3@P4]"),
|
|
/* 29 */ "Found" OpHelp("key=r[P3@P4]"),
|
|
/* 30 */ "SeekRowid" OpHelp("intkey=r[P3]"),
|
|
/* 31 */ "NotExists" OpHelp("intkey=r[P3]"),
|
|
/* 32 */ "Last" OpHelp(""),
|
|
/* 33 */ "IfSmaller" OpHelp(""),
|
|
/* 34 */ "SorterSort" OpHelp(""),
|
|
/* 35 */ "Sort" OpHelp(""),
|
|
/* 36 */ "Rewind" OpHelp(""),
|
|
/* 37 */ "SorterNext" OpHelp(""),
|
|
/* 38 */ "Prev" OpHelp(""),
|
|
/* 39 */ "Next" OpHelp(""),
|
|
/* 40 */ "IdxLE" OpHelp("key=r[P3@P4]"),
|
|
/* 41 */ "IdxGT" OpHelp("key=r[P3@P4]"),
|
|
/* 42 */ "IdxLT" OpHelp("key=r[P3@P4]"),
|
|
/* 43 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"),
|
|
/* 44 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"),
|
|
/* 45 */ "IdxGE" OpHelp("key=r[P3@P4]"),
|
|
/* 46 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
|
|
/* 47 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
|
|
/* 48 */ "Program" OpHelp(""),
|
|
/* 49 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
|
|
/* 50 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"),
|
|
/* 51 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
|
|
/* 52 */ "Ne" OpHelp("IF r[P3]!=r[P1]"),
|
|
/* 53 */ "Eq" OpHelp("IF r[P3]==r[P1]"),
|
|
/* 54 */ "Gt" OpHelp("IF r[P3]>r[P1]"),
|
|
/* 55 */ "Le" OpHelp("IF r[P3]<=r[P1]"),
|
|
/* 56 */ "Lt" OpHelp("IF r[P3]<r[P1]"),
|
|
/* 57 */ "Ge" OpHelp("IF r[P3]>=r[P1]"),
|
|
/* 58 */ "ElseEq" OpHelp(""),
|
|
/* 59 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
|
|
/* 60 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
|
|
/* 61 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
|
|
/* 62 */ "IncrVacuum" OpHelp(""),
|
|
/* 63 */ "VNext" OpHelp(""),
|
|
/* 64 */ "Filter" OpHelp("if key(P3@P4) not in filter(P1) goto P2"),
|
|
/* 65 */ "PureFunc" OpHelp("r[P3]=func(r[P2@NP])"),
|
|
/* 66 */ "Function" OpHelp("r[P3]=func(r[P2@NP])"),
|
|
/* 67 */ "Return" OpHelp(""),
|
|
/* 68 */ "EndCoroutine" OpHelp(""),
|
|
/* 69 */ "HaltIfNull" OpHelp("if r[P3]=null halt"),
|
|
/* 70 */ "Halt" OpHelp(""),
|
|
/* 71 */ "Integer" OpHelp("r[P2]=P1"),
|
|
/* 72 */ "Int64" OpHelp("r[P2]=P4"),
|
|
/* 73 */ "String" OpHelp("r[P2]='P4' (len=P1)"),
|
|
/* 74 */ "BeginSubrtn" OpHelp("r[P2]=NULL"),
|
|
/* 75 */ "Null" OpHelp("r[P2..P3]=NULL"),
|
|
/* 76 */ "SoftNull" OpHelp("r[P1]=NULL"),
|
|
/* 77 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"),
|
|
/* 78 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"),
|
|
/* 79 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"),
|
|
/* 80 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
|
|
/* 81 */ "SCopy" OpHelp("r[P2]=r[P1]"),
|
|
/* 82 */ "IntCopy" OpHelp("r[P2]=r[P1]"),
|
|
/* 83 */ "FkCheck" OpHelp(""),
|
|
/* 84 */ "ResultRow" OpHelp("output=r[P1@P2]"),
|
|
/* 85 */ "CollSeq" OpHelp(""),
|
|
/* 86 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
|
|
/* 87 */ "RealAffinity" OpHelp(""),
|
|
/* 88 */ "Cast" OpHelp("affinity(r[P1])"),
|
|
/* 89 */ "Permutation" OpHelp(""),
|
|
/* 90 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"),
|
|
/* 91 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"),
|
|
/* 92 */ "ZeroOrNull" OpHelp("r[P2] = 0 OR NULL"),
|
|
/* 93 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"),
|
|
/* 94 */ "Column" OpHelp("r[P3]=PX cursor P1 column P2"),
|
|
/* 95 */ "TypeCheck" OpHelp("typecheck(r[P1@P2])"),
|
|
/* 96 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
|
|
/* 97 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
|
|
/* 98 */ "Count" OpHelp("r[P2]=count()"),
|
|
/* 99 */ "ReadCookie" OpHelp(""),
|
|
/* 100 */ "SetCookie" OpHelp(""),
|
|
/* 101 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
|
|
/* 102 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
|
|
/* 103 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
|
|
/* 104 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"),
|
|
/* 105 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"),
|
|
/* 106 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
|
|
/* 107 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
|
|
/* 108 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
|
|
/* 109 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
|
|
/* 110 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
|
|
/* 111 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
|
|
/* 112 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
|
|
/* 113 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
|
|
/* 114 */ "BitNot" OpHelp("r[P2]= ~r[P1]"),
|
|
/* 115 */ "OpenDup" OpHelp(""),
|
|
/* 116 */ "OpenAutoindex" OpHelp("nColumn=P2"),
|
|
/* 117 */ "String8" OpHelp("r[P2]='P4'"),
|
|
/* 118 */ "OpenEphemeral" OpHelp("nColumn=P2"),
|
|
/* 119 */ "SorterOpen" OpHelp(""),
|
|
/* 120 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
|
|
/* 121 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
|
|
/* 122 */ "Close" OpHelp(""),
|
|
/* 123 */ "ColumnsUsed" OpHelp(""),
|
|
/* 124 */ "SeekScan" OpHelp("Scan-ahead up to P1 rows"),
|
|
/* 125 */ "SeekHit" OpHelp("set P2<=seekHit<=P3"),
|
|
/* 126 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
|
|
/* 127 */ "NewRowid" OpHelp("r[P2]=rowid"),
|
|
/* 128 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
|
|
/* 129 */ "RowCell" OpHelp(""),
|
|
/* 130 */ "Delete" OpHelp(""),
|
|
/* 131 */ "ResetCount" OpHelp(""),
|
|
/* 132 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
|
|
/* 133 */ "SorterData" OpHelp("r[P2]=data"),
|
|
/* 134 */ "RowData" OpHelp("r[P2]=data"),
|
|
/* 135 */ "Rowid" OpHelp("r[P2]=PX rowid of P1"),
|
|
/* 136 */ "NullRow" OpHelp(""),
|
|
/* 137 */ "SeekEnd" OpHelp(""),
|
|
/* 138 */ "IdxInsert" OpHelp("key=r[P2]"),
|
|
/* 139 */ "SorterInsert" OpHelp("key=r[P2]"),
|
|
/* 140 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
|
|
/* 141 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
|
|
/* 142 */ "IdxRowid" OpHelp("r[P2]=rowid"),
|
|
/* 143 */ "FinishSeek" OpHelp(""),
|
|
/* 144 */ "Destroy" OpHelp(""),
|
|
/* 145 */ "Clear" OpHelp(""),
|
|
/* 146 */ "ResetSorter" OpHelp(""),
|
|
/* 147 */ "CreateBtree" OpHelp("r[P2]=root iDb=P1 flags=P3"),
|
|
/* 148 */ "SqlExec" OpHelp(""),
|
|
/* 149 */ "ParseSchema" OpHelp(""),
|
|
/* 150 */ "LoadAnalysis" OpHelp(""),
|
|
/* 151 */ "DropTable" OpHelp(""),
|
|
/* 152 */ "DropIndex" OpHelp(""),
|
|
/* 153 */ "Real" OpHelp("r[P2]=P4"),
|
|
/* 154 */ "DropTrigger" OpHelp(""),
|
|
/* 155 */ "IntegrityCk" OpHelp(""),
|
|
/* 156 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
|
|
/* 157 */ "Param" OpHelp(""),
|
|
/* 158 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
|
|
/* 159 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
|
|
/* 160 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
|
|
/* 161 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"),
|
|
/* 162 */ "AggStep" OpHelp("accum=r[P3] step(r[P2@P5])"),
|
|
/* 163 */ "AggStep1" OpHelp("accum=r[P3] step(r[P2@P5])"),
|
|
/* 164 */ "AggValue" OpHelp("r[P3]=value N=P2"),
|
|
/* 165 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
|
|
/* 166 */ "Expire" OpHelp(""),
|
|
/* 167 */ "CursorLock" OpHelp(""),
|
|
/* 168 */ "CursorUnlock" OpHelp(""),
|
|
/* 169 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
|
|
/* 170 */ "VBegin" OpHelp(""),
|
|
/* 171 */ "VCreate" OpHelp(""),
|
|
/* 172 */ "VDestroy" OpHelp(""),
|
|
/* 173 */ "VOpen" OpHelp(""),
|
|
/* 174 */ "VCheck" OpHelp(""),
|
|
/* 175 */ "VInitIn" OpHelp("r[P2]=ValueList(P1,P3)"),
|
|
/* 176 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
|
|
/* 177 */ "VRename" OpHelp(""),
|
|
/* 178 */ "Pagecount" OpHelp(""),
|
|
/* 179 */ "MaxPgcnt" OpHelp(""),
|
|
/* 180 */ "ClrSubtype" OpHelp("r[P1].subtype = 0"),
|
|
/* 181 */ "GetSubtype" OpHelp("r[P2] = r[P1].subtype"),
|
|
/* 182 */ "SetSubtype" OpHelp("r[P2].subtype = r[P1]"),
|
|
/* 183 */ "FilterAdd" OpHelp("filter(P1) += key(P3@P4)"),
|
|
/* 184 */ "Trace" OpHelp(""),
|
|
/* 185 */ "CursorHint" OpHelp(""),
|
|
/* 186 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"),
|
|
/* 187 */ "Noop" OpHelp(""),
|
|
/* 188 */ "Explain" OpHelp(""),
|
|
/* 189 */ "Abortable" OpHelp(""),
|
|
};
|
|
return azName[i];
|
|
}
|
|
#endif
|
|
|
|
/************** End of opcodes.c *********************************************/
|
|
/************** Begin file os_kv.c *******************************************/
|
|
/*
|
|
** 2022-09-06
|
|
**
|
|
** 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 an experimental VFS layer that operates on a
|
|
** Key/Value storage engine where both keys and values must be pure
|
|
** text.
|
|
*/
|
|
/* #include <sqliteInt.h> */
|
|
#if SQLITE_OS_KV || (SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL))
|
|
|
|
/*****************************************************************************
|
|
** Debugging logic
|
|
*/
|
|
|
|
/* SQLITE_KV_TRACE() is used for tracing calls to kvstorage routines. */
|
|
#if 0
|
|
#define SQLITE_KV_TRACE(X) printf X
|
|
#else
|
|
#define SQLITE_KV_TRACE(X)
|
|
#endif
|
|
|
|
/* SQLITE_KV_LOG() is used for tracing calls to the VFS interface */
|
|
#if 0
|
|
#define SQLITE_KV_LOG(X) printf X
|
|
#else
|
|
#define SQLITE_KV_LOG(X)
|
|
#endif
|
|
|
|
|
|
/*
|
|
** Forward declaration of objects used by this VFS implementation
|
|
*/
|
|
typedef struct KVVfsFile KVVfsFile;
|
|
|
|
/* A single open file. There are only two files represented by this
|
|
** VFS - the database and the rollback journal.
|
|
*/
|
|
struct KVVfsFile {
|
|
sqlite3_file base; /* IO methods */
|
|
const char *zClass; /* Storage class */
|
|
int isJournal; /* True if this is a journal file */
|
|
unsigned int nJrnl; /* Space allocated for aJrnl[] */
|
|
char *aJrnl; /* Journal content */
|
|
int szPage; /* Last known page size */
|
|
sqlite3_int64 szDb; /* Database file size. -1 means unknown */
|
|
char *aData; /* Buffer to hold page data */
|
|
};
|
|
#define SQLITE_KVOS_SZ 133073
|
|
|
|
/*
|
|
** Methods for KVVfsFile
|
|
*/
|
|
static int kvvfsClose(sqlite3_file*);
|
|
static int kvvfsReadDb(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
|
|
static int kvvfsReadJrnl(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
|
|
static int kvvfsWriteDb(sqlite3_file*,const void*,int iAmt, sqlite3_int64);
|
|
static int kvvfsWriteJrnl(sqlite3_file*,const void*,int iAmt, sqlite3_int64);
|
|
static int kvvfsTruncateDb(sqlite3_file*, sqlite3_int64 size);
|
|
static int kvvfsTruncateJrnl(sqlite3_file*, sqlite3_int64 size);
|
|
static int kvvfsSyncDb(sqlite3_file*, int flags);
|
|
static int kvvfsSyncJrnl(sqlite3_file*, int flags);
|
|
static int kvvfsFileSizeDb(sqlite3_file*, sqlite3_int64 *pSize);
|
|
static int kvvfsFileSizeJrnl(sqlite3_file*, sqlite3_int64 *pSize);
|
|
static int kvvfsLock(sqlite3_file*, int);
|
|
static int kvvfsUnlock(sqlite3_file*, int);
|
|
static int kvvfsCheckReservedLock(sqlite3_file*, int *pResOut);
|
|
static int kvvfsFileControlDb(sqlite3_file*, int op, void *pArg);
|
|
static int kvvfsFileControlJrnl(sqlite3_file*, int op, void *pArg);
|
|
static int kvvfsSectorSize(sqlite3_file*);
|
|
static int kvvfsDeviceCharacteristics(sqlite3_file*);
|
|
|
|
/*
|
|
** Methods for sqlite3_vfs
|
|
*/
|
|
static int kvvfsOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
|
|
static int kvvfsDelete(sqlite3_vfs*, const char *zName, int syncDir);
|
|
static int kvvfsAccess(sqlite3_vfs*, const char *zName, int flags, int *);
|
|
static int kvvfsFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
|
|
static void *kvvfsDlOpen(sqlite3_vfs*, const char *zFilename);
|
|
static int kvvfsRandomness(sqlite3_vfs*, int nByte, char *zOut);
|
|
static int kvvfsSleep(sqlite3_vfs*, int microseconds);
|
|
static int kvvfsCurrentTime(sqlite3_vfs*, double*);
|
|
static int kvvfsCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
|
|
|
|
static sqlite3_vfs sqlite3OsKvvfsObject = {
|
|
1, /* iVersion */
|
|
sizeof(KVVfsFile), /* szOsFile */
|
|
1024, /* mxPathname */
|
|
0, /* pNext */
|
|
"kvvfs", /* zName */
|
|
0, /* pAppData */
|
|
kvvfsOpen, /* xOpen */
|
|
kvvfsDelete, /* xDelete */
|
|
kvvfsAccess, /* xAccess */
|
|
kvvfsFullPathname, /* xFullPathname */
|
|
kvvfsDlOpen, /* xDlOpen */
|
|
0, /* xDlError */
|
|
0, /* xDlSym */
|
|
0, /* xDlClose */
|
|
kvvfsRandomness, /* xRandomness */
|
|
kvvfsSleep, /* xSleep */
|
|
kvvfsCurrentTime, /* xCurrentTime */
|
|
0, /* xGetLastError */
|
|
kvvfsCurrentTimeInt64 /* xCurrentTimeInt64 */
|
|
};
|
|
|
|
/* Methods for sqlite3_file objects referencing a database file
|
|
*/
|
|
static sqlite3_io_methods kvvfs_db_io_methods = {
|
|
1, /* iVersion */
|
|
kvvfsClose, /* xClose */
|
|
kvvfsReadDb, /* xRead */
|
|
kvvfsWriteDb, /* xWrite */
|
|
kvvfsTruncateDb, /* xTruncate */
|
|
kvvfsSyncDb, /* xSync */
|
|
kvvfsFileSizeDb, /* xFileSize */
|
|
kvvfsLock, /* xLock */
|
|
kvvfsUnlock, /* xUnlock */
|
|
kvvfsCheckReservedLock, /* xCheckReservedLock */
|
|
kvvfsFileControlDb, /* xFileControl */
|
|
kvvfsSectorSize, /* xSectorSize */
|
|
kvvfsDeviceCharacteristics, /* xDeviceCharacteristics */
|
|
0, /* xShmMap */
|
|
0, /* xShmLock */
|
|
0, /* xShmBarrier */
|
|
0, /* xShmUnmap */
|
|
0, /* xFetch */
|
|
0 /* xUnfetch */
|
|
};
|
|
|
|
/* Methods for sqlite3_file objects referencing a rollback journal
|
|
*/
|
|
static sqlite3_io_methods kvvfs_jrnl_io_methods = {
|
|
1, /* iVersion */
|
|
kvvfsClose, /* xClose */
|
|
kvvfsReadJrnl, /* xRead */
|
|
kvvfsWriteJrnl, /* xWrite */
|
|
kvvfsTruncateJrnl, /* xTruncate */
|
|
kvvfsSyncJrnl, /* xSync */
|
|
kvvfsFileSizeJrnl, /* xFileSize */
|
|
kvvfsLock, /* xLock */
|
|
kvvfsUnlock, /* xUnlock */
|
|
kvvfsCheckReservedLock, /* xCheckReservedLock */
|
|
kvvfsFileControlJrnl, /* xFileControl */
|
|
kvvfsSectorSize, /* xSectorSize */
|
|
kvvfsDeviceCharacteristics, /* xDeviceCharacteristics */
|
|
0, /* xShmMap */
|
|
0, /* xShmLock */
|
|
0, /* xShmBarrier */
|
|
0, /* xShmUnmap */
|
|
0, /* xFetch */
|
|
0 /* xUnfetch */
|
|
};
|
|
|
|
/****** Storage subsystem **************************************************/
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
|
|
/* Forward declarations for the low-level storage engine
|
|
*/
|
|
static int kvstorageWrite(const char*, const char *zKey, const char *zData);
|
|
static int kvstorageDelete(const char*, const char *zKey);
|
|
static int kvstorageRead(const char*, const char *zKey, char *zBuf, int nBuf);
|
|
#define KVSTORAGE_KEY_SZ 32
|
|
|
|
/* Expand the key name with an appropriate prefix and put the result
|
|
** zKeyOut[]. The zKeyOut[] buffer is assumed to hold at least
|
|
** KVSTORAGE_KEY_SZ bytes.
|
|
*/
|
|
static void kvstorageMakeKey(
|
|
const char *zClass,
|
|
const char *zKeyIn,
|
|
char *zKeyOut
|
|
){
|
|
sqlite3_snprintf(KVSTORAGE_KEY_SZ, zKeyOut, "kvvfs-%s-%s", zClass, zKeyIn);
|
|
}
|
|
|
|
/* Write content into a key. zClass is the particular namespace of the
|
|
** underlying key/value store to use - either "local" or "session".
|
|
**
|
|
** Both zKey and zData are zero-terminated pure text strings.
|
|
**
|
|
** Return the number of errors.
|
|
*/
|
|
static int kvstorageWrite(
|
|
const char *zClass,
|
|
const char *zKey,
|
|
const char *zData
|
|
){
|
|
FILE *fd;
|
|
char zXKey[KVSTORAGE_KEY_SZ];
|
|
kvstorageMakeKey(zClass, zKey, zXKey);
|
|
fd = fopen(zXKey, "wb");
|
|
if( fd ){
|
|
SQLITE_KV_TRACE(("KVVFS-WRITE %-15s (%d) %.50s%s\n", zXKey,
|
|
(int)strlen(zData), zData,
|
|
strlen(zData)>50 ? "..." : ""));
|
|
fputs(zData, fd);
|
|
fclose(fd);
|
|
return 0;
|
|
}else{
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
/* Delete a key (with its corresponding data) from the key/value
|
|
** namespace given by zClass. If the key does not previously exist,
|
|
** this routine is a no-op.
|
|
*/
|
|
static int kvstorageDelete(const char *zClass, const char *zKey){
|
|
char zXKey[KVSTORAGE_KEY_SZ];
|
|
kvstorageMakeKey(zClass, zKey, zXKey);
|
|
unlink(zXKey);
|
|
SQLITE_KV_TRACE(("KVVFS-DELETE %-15s\n", zXKey));
|
|
return 0;
|
|
}
|
|
|
|
/* Read the value associated with a zKey from the key/value namespace given
|
|
** by zClass and put the text data associated with that key in the first
|
|
** nBuf bytes of zBuf[]. The value might be truncated if zBuf is not large
|
|
** enough to hold it all. The value put into zBuf must always be zero
|
|
** terminated, even if it gets truncated because nBuf is not large enough.
|
|
**
|
|
** Return the total number of bytes in the data, without truncation, and
|
|
** not counting the final zero terminator. Return -1 if the key does
|
|
** not exist.
|
|
**
|
|
** If nBuf<=0 then this routine simply returns the size of the data without
|
|
** actually reading it.
|
|
*/
|
|
static int kvstorageRead(
|
|
const char *zClass,
|
|
const char *zKey,
|
|
char *zBuf,
|
|
int nBuf
|
|
){
|
|
FILE *fd;
|
|
struct stat buf;
|
|
char zXKey[KVSTORAGE_KEY_SZ];
|
|
kvstorageMakeKey(zClass, zKey, zXKey);
|
|
if( access(zXKey, R_OK)!=0
|
|
|| stat(zXKey, &buf)!=0
|
|
|| !S_ISREG(buf.st_mode)
|
|
){
|
|
SQLITE_KV_TRACE(("KVVFS-READ %-15s (-1)\n", zXKey));
|
|
return -1;
|
|
}
|
|
if( nBuf<=0 ){
|
|
return (int)buf.st_size;
|
|
}else if( nBuf==1 ){
|
|
zBuf[0] = 0;
|
|
SQLITE_KV_TRACE(("KVVFS-READ %-15s (%d)\n", zXKey,
|
|
(int)buf.st_size));
|
|
return (int)buf.st_size;
|
|
}
|
|
if( nBuf > buf.st_size + 1 ){
|
|
nBuf = buf.st_size + 1;
|
|
}
|
|
fd = fopen(zXKey, "rb");
|
|
if( fd==0 ){
|
|
SQLITE_KV_TRACE(("KVVFS-READ %-15s (-1)\n", zXKey));
|
|
return -1;
|
|
}else{
|
|
sqlite3_int64 n = fread(zBuf, 1, nBuf-1, fd);
|
|
fclose(fd);
|
|
zBuf[n] = 0;
|
|
SQLITE_KV_TRACE(("KVVFS-READ %-15s (%lld) %.50s%s\n", zXKey,
|
|
n, zBuf, n>50 ? "..." : ""));
|
|
return (int)n;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** An internal level of indirection which enables us to replace the
|
|
** kvvfs i/o methods with JavaScript implementations in WASM builds.
|
|
** Maintenance reminder: if this struct changes in any way, the JSON
|
|
** rendering of its structure must be updated in
|
|
** sqlite3_wasm_enum_json(). There are no binary compatibility
|
|
** concerns, so it does not need an iVersion member. This file is
|
|
** necessarily always compiled together with sqlite3_wasm_enum_json(),
|
|
** and JS code dynamically creates the mapping of members based on
|
|
** that JSON description.
|
|
*/
|
|
typedef struct sqlite3_kvvfs_methods sqlite3_kvvfs_methods;
|
|
struct sqlite3_kvvfs_methods {
|
|
int (*xRead)(const char *zClass, const char *zKey, char *zBuf, int nBuf);
|
|
int (*xWrite)(const char *zClass, const char *zKey, const char *zData);
|
|
int (*xDelete)(const char *zClass, const char *zKey);
|
|
const int nKeySize;
|
|
};
|
|
|
|
/*
|
|
** This object holds the kvvfs I/O methods which may be swapped out
|
|
** for JavaScript-side implementations in WASM builds. In such builds
|
|
** it cannot be const, but in native builds it should be so that
|
|
** the compiler can hopefully optimize this level of indirection out.
|
|
** That said, kvvfs is intended primarily for use in WASM builds.
|
|
**
|
|
** Note that this is not explicitly flagged as static because the
|
|
** amalgamation build will tag it with SQLITE_PRIVATE.
|
|
*/
|
|
#ifndef SQLITE_WASM
|
|
const
|
|
#endif
|
|
SQLITE_PRIVATE sqlite3_kvvfs_methods sqlite3KvvfsMethods = {
|
|
kvstorageRead,
|
|
kvstorageWrite,
|
|
kvstorageDelete,
|
|
KVSTORAGE_KEY_SZ
|
|
};
|
|
|
|
/****** Utility subroutines ************************************************/
|
|
|
|
/*
|
|
** Encode binary into the text encoded used to persist on disk.
|
|
** The output text is stored in aOut[], which must be at least
|
|
** nData+1 bytes in length.
|
|
**
|
|
** Return the actual length of the encoded text, not counting the
|
|
** zero terminator at the end.
|
|
**
|
|
** Encoding format
|
|
** ---------------
|
|
**
|
|
** * Non-zero bytes are encoded as upper-case hexadecimal
|
|
**
|
|
** * A sequence of one or more zero-bytes that are not at the
|
|
** beginning of the buffer are encoded as a little-endian
|
|
** base-26 number using a..z. "a" means 0. "b" means 1,
|
|
** "z" means 25. "ab" means 26. "ac" means 52. And so forth.
|
|
**
|
|
** * Because there is no overlap between the encoding characters
|
|
** of hexadecimal and base-26 numbers, it is always clear where
|
|
** one stops and the next begins.
|
|
*/
|
|
static int kvvfsEncode(const char *aData, int nData, char *aOut){
|
|
int i, j;
|
|
const unsigned char *a = (const unsigned char*)aData;
|
|
for(i=j=0; i<nData; i++){
|
|
unsigned char c = a[i];
|
|
if( c!=0 ){
|
|
aOut[j++] = "0123456789ABCDEF"[c>>4];
|
|
aOut[j++] = "0123456789ABCDEF"[c&0xf];
|
|
}else{
|
|
/* A sequence of 1 or more zeros is stored as a little-endian
|
|
** base-26 number using a..z as the digits. So one zero is "b".
|
|
** Two zeros is "c". 25 zeros is "z", 26 zeros is "ab", 27 is "bb",
|
|
** and so forth.
|
|
*/
|
|
int k;
|
|
for(k=1; i+k<nData && a[i+k]==0; k++){}
|
|
i += k-1;
|
|
while( k>0 ){
|
|
aOut[j++] = 'a'+(k%26);
|
|
k /= 26;
|
|
}
|
|
}
|
|
}
|
|
aOut[j] = 0;
|
|
return j;
|
|
}
|
|
|
|
static const signed char kvvfsHexValue[256] = {
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
|
|
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
|
|
};
|
|
|
|
/*
|
|
** Decode the text encoding back to binary. The binary content is
|
|
** written into pOut, which must be at least nOut bytes in length.
|
|
**
|
|
** The return value is the number of bytes actually written into aOut[].
|
|
*/
|
|
static int kvvfsDecode(const char *a, char *aOut, int nOut){
|
|
int i, j;
|
|
int c;
|
|
const unsigned char *aIn = (const unsigned char*)a;
|
|
i = 0;
|
|
j = 0;
|
|
while( 1 ){
|
|
c = kvvfsHexValue[aIn[i]];
|
|
if( c<0 ){
|
|
int n = 0;
|
|
int mult = 1;
|
|
c = aIn[i];
|
|
if( c==0 ) break;
|
|
while( c>='a' && c<='z' ){
|
|
n += (c - 'a')*mult;
|
|
mult *= 26;
|
|
c = aIn[++i];
|
|
}
|
|
if( j+n>nOut ) return -1;
|
|
memset(&aOut[j], 0, n);
|
|
j += n;
|
|
if( c==0 || mult==1 ) break; /* progress stalled if mult==1 */
|
|
}else{
|
|
aOut[j] = c<<4;
|
|
c = kvvfsHexValue[aIn[++i]];
|
|
if( c<0 ) break;
|
|
aOut[j++] += c;
|
|
i++;
|
|
}
|
|
}
|
|
return j;
|
|
}
|
|
|
|
/*
|
|
** Decode a complete journal file. Allocate space in pFile->aJrnl
|
|
** and store the decoding there. Or leave pFile->aJrnl set to NULL
|
|
** if an error is encountered.
|
|
**
|
|
** The first few characters of the text encoding will be a little-endian
|
|
** base-26 number (digits a..z) that is the total number of bytes
|
|
** in the decoded journal file image. This base-26 number is followed
|
|
** by a single space, then the encoding of the journal. The space
|
|
** separator is required to act as a terminator for the base-26 number.
|
|
*/
|
|
static void kvvfsDecodeJournal(
|
|
KVVfsFile *pFile, /* Store decoding in pFile->aJrnl */
|
|
const char *zTxt, /* Text encoding. Zero-terminated */
|
|
int nTxt /* Bytes in zTxt, excluding zero terminator */
|
|
){
|
|
unsigned int n = 0;
|
|
int c, i, mult;
|
|
i = 0;
|
|
mult = 1;
|
|
while( (c = zTxt[i++])>='a' && c<='z' ){
|
|
n += (zTxt[i] - 'a')*mult;
|
|
mult *= 26;
|
|
}
|
|
sqlite3_free(pFile->aJrnl);
|
|
pFile->aJrnl = sqlite3_malloc64( n );
|
|
if( pFile->aJrnl==0 ){
|
|
pFile->nJrnl = 0;
|
|
return;
|
|
}
|
|
pFile->nJrnl = n;
|
|
n = kvvfsDecode(zTxt+i, pFile->aJrnl, pFile->nJrnl);
|
|
if( n<pFile->nJrnl ){
|
|
sqlite3_free(pFile->aJrnl);
|
|
pFile->aJrnl = 0;
|
|
pFile->nJrnl = 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Read or write the "sz" element, containing the database file size.
|
|
*/
|
|
static sqlite3_int64 kvvfsReadFileSize(KVVfsFile *pFile){
|
|
char zData[50];
|
|
zData[0] = 0;
|
|
sqlite3KvvfsMethods.xRead(pFile->zClass, "sz", zData, sizeof(zData)-1);
|
|
return strtoll(zData, 0, 0);
|
|
}
|
|
static int kvvfsWriteFileSize(KVVfsFile *pFile, sqlite3_int64 sz){
|
|
char zData[50];
|
|
sqlite3_snprintf(sizeof(zData), zData, "%lld", sz);
|
|
return sqlite3KvvfsMethods.xWrite(pFile->zClass, "sz", zData);
|
|
}
|
|
|
|
/****** sqlite3_io_methods methods ******************************************/
|
|
|
|
/*
|
|
** Close an kvvfs-file.
|
|
*/
|
|
static int kvvfsClose(sqlite3_file *pProtoFile){
|
|
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
|
|
|
SQLITE_KV_LOG(("xClose %s %s\n", pFile->zClass,
|
|
pFile->isJournal ? "journal" : "db"));
|
|
sqlite3_free(pFile->aJrnl);
|
|
sqlite3_free(pFile->aData);
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Read from the -journal file.
|
|
*/
|
|
static int kvvfsReadJrnl(
|
|
sqlite3_file *pProtoFile,
|
|
void *zBuf,
|
|
int iAmt,
|
|
sqlite_int64 iOfst
|
|
){
|
|
KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
|
|
assert( pFile->isJournal );
|
|
SQLITE_KV_LOG(("xRead('%s-journal',%d,%lld)\n", pFile->zClass, iAmt, iOfst));
|
|
if( pFile->aJrnl==0 ){
|
|
int szTxt = kvstorageRead(pFile->zClass, "jrnl", 0, 0);
|
|
char *aTxt;
|
|
if( szTxt<=4 ){
|
|
return SQLITE_IOERR;
|
|
}
|
|
aTxt = sqlite3_malloc64( szTxt+1 );
|
|
if( aTxt==0 ) return SQLITE_NOMEM;
|
|
kvstorageRead(pFile->zClass, "jrnl", aTxt, szTxt+1);
|
|
kvvfsDecodeJournal(pFile, aTxt, szTxt);
|
|
sqlite3_free(aTxt);
|
|
if( pFile->aJrnl==0 ) return SQLITE_IOERR;
|
|
}
|
|
if( iOfst+iAmt>pFile->nJrnl ){
|
|
return SQLITE_IOERR_SHORT_READ;
|
|
}
|
|
memcpy(zBuf, pFile->aJrnl+iOfst, iAmt);
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Read from the database file.
|
|
*/
|
|
static int kvvfsReadDb(
|
|
sqlite3_file *pProtoFile,
|
|
void *zBuf,
|
|
int iAmt,
|
|
sqlite_int64 iOfst
|
|
){
|
|
KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
|
|
unsigned int pgno;
|
|
int got, n;
|
|
char zKey[30];
|
|
char *aData = pFile->aData;
|
|
assert( iOfst>=0 );
|
|
assert( iAmt>=0 );
|
|
SQLITE_KV_LOG(("xRead('%s-db',%d,%lld)\n", pFile->zClass, iAmt, iOfst));
|
|
if( iOfst+iAmt>=512 ){
|
|
if( (iOfst % iAmt)!=0 ){
|
|
return SQLITE_IOERR_READ;
|
|
}
|
|
if( (iAmt & (iAmt-1))!=0 || iAmt<512 || iAmt>65536 ){
|
|
return SQLITE_IOERR_READ;
|
|
}
|
|
pFile->szPage = iAmt;
|
|
pgno = 1 + iOfst/iAmt;
|
|
}else{
|
|
pgno = 1;
|
|
}
|
|
sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno);
|
|
got = sqlite3KvvfsMethods.xRead(pFile->zClass, zKey,
|
|
aData, SQLITE_KVOS_SZ-1);
|
|
if( got<0 ){
|
|
n = 0;
|
|
}else{
|
|
aData[got] = 0;
|
|
if( iOfst+iAmt<512 ){
|
|
int k = iOfst+iAmt;
|
|
aData[k*2] = 0;
|
|
n = kvvfsDecode(aData, &aData[2000], SQLITE_KVOS_SZ-2000);
|
|
if( n>=iOfst+iAmt ){
|
|
memcpy(zBuf, &aData[2000+iOfst], iAmt);
|
|
n = iAmt;
|
|
}else{
|
|
n = 0;
|
|
}
|
|
}else{
|
|
n = kvvfsDecode(aData, zBuf, iAmt);
|
|
}
|
|
}
|
|
if( n<iAmt ){
|
|
memset(zBuf+n, 0, iAmt-n);
|
|
return SQLITE_IOERR_SHORT_READ;
|
|
}
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
** Write into the -journal file.
|
|
*/
|
|
static int kvvfsWriteJrnl(
|
|
sqlite3_file *pProtoFile,
|
|
const void *zBuf,
|
|
int iAmt,
|
|
sqlite_int64 iOfst
|
|
){
|
|
KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
|
|
sqlite3_int64 iEnd = iOfst+iAmt;
|
|
SQLITE_KV_LOG(("xWrite('%s-journal',%d,%lld)\n", pFile->zClass, iAmt, iOfst));
|
|
if( iEnd>=0x10000000 ) return SQLITE_FULL;
|
|
if( pFile->aJrnl==0 || pFile->nJrnl<iEnd ){
|
|
char *aNew = sqlite3_realloc(pFile->aJrnl, iEnd);
|
|
if( aNew==0 ){
|
|
return SQLITE_IOERR_NOMEM;
|
|
}
|
|
pFile->aJrnl = aNew;
|
|
if( pFile->nJrnl<iOfst ){
|
|
memset(pFile->aJrnl+pFile->nJrnl, 0, iOfst-pFile->nJrnl);
|
|
}
|
|
pFile->nJrnl = iEnd;
|
|
}
|
|
memcpy(pFile->aJrnl+iOfst, zBuf, iAmt);
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Write into the database file.
|
|
*/
|
|
static int kvvfsWriteDb(
|
|
sqlite3_file *pProtoFile,
|
|
const void *zBuf,
|
|
int iAmt,
|
|
sqlite_int64 iOfst
|
|
){
|
|
KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
|
|
unsigned int pgno;
|
|
char zKey[30];
|
|
char *aData = pFile->aData;
|
|
SQLITE_KV_LOG(("xWrite('%s-db',%d,%lld)\n", pFile->zClass, iAmt, iOfst));
|
|
assert( iAmt>=512 && iAmt<=65536 );
|
|
assert( (iAmt & (iAmt-1))==0 );
|
|
assert( pFile->szPage<0 || pFile->szPage==iAmt );
|
|
pFile->szPage = iAmt;
|
|
pgno = 1 + iOfst/iAmt;
|
|
sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno);
|
|
kvvfsEncode(zBuf, iAmt, aData);
|
|
if( sqlite3KvvfsMethods.xWrite(pFile->zClass, zKey, aData) ){
|
|
return SQLITE_IOERR;
|
|
}
|
|
if( iOfst+iAmt > pFile->szDb ){
|
|
pFile->szDb = iOfst + iAmt;
|
|
}
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Truncate an kvvfs-file.
|
|
*/
|
|
static int kvvfsTruncateJrnl(sqlite3_file *pProtoFile, sqlite_int64 size){
|
|
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
|
SQLITE_KV_LOG(("xTruncate('%s-journal',%lld)\n", pFile->zClass, size));
|
|
assert( size==0 );
|
|
sqlite3KvvfsMethods.xDelete(pFile->zClass, "jrnl");
|
|
sqlite3_free(pFile->aJrnl);
|
|
pFile->aJrnl = 0;
|
|
pFile->nJrnl = 0;
|
|
return SQLITE_OK;
|
|
}
|
|
static int kvvfsTruncateDb(sqlite3_file *pProtoFile, sqlite_int64 size){
|
|
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
|
if( pFile->szDb>size
|
|
&& pFile->szPage>0
|
|
&& (size % pFile->szPage)==0
|
|
){
|
|
char zKey[50];
|
|
unsigned int pgno, pgnoMax;
|
|
SQLITE_KV_LOG(("xTruncate('%s-db',%lld)\n", pFile->zClass, size));
|
|
pgno = 1 + size/pFile->szPage;
|
|
pgnoMax = 2 + pFile->szDb/pFile->szPage;
|
|
while( pgno<=pgnoMax ){
|
|
sqlite3_snprintf(sizeof(zKey), zKey, "%u", pgno);
|
|
sqlite3KvvfsMethods.xDelete(pFile->zClass, zKey);
|
|
pgno++;
|
|
}
|
|
pFile->szDb = size;
|
|
return kvvfsWriteFileSize(pFile, size) ? SQLITE_IOERR : SQLITE_OK;
|
|
}
|
|
return SQLITE_IOERR;
|
|
}
|
|
|
|
/*
|
|
** Sync an kvvfs-file.
|
|
*/
|
|
static int kvvfsSyncJrnl(sqlite3_file *pProtoFile, int flags){
|
|
int i, n;
|
|
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
|
char *zOut;
|
|
SQLITE_KV_LOG(("xSync('%s-journal')\n", pFile->zClass));
|
|
if( pFile->nJrnl<=0 ){
|
|
return kvvfsTruncateJrnl(pProtoFile, 0);
|
|
}
|
|
zOut = sqlite3_malloc64( pFile->nJrnl*2 + 50 );
|
|
if( zOut==0 ){
|
|
return SQLITE_IOERR_NOMEM;
|
|
}
|
|
n = pFile->nJrnl;
|
|
i = 0;
|
|
do{
|
|
zOut[i++] = 'a' + (n%26);
|
|
n /= 26;
|
|
}while( n>0 );
|
|
zOut[i++] = ' ';
|
|
kvvfsEncode(pFile->aJrnl, pFile->nJrnl, &zOut[i]);
|
|
i = sqlite3KvvfsMethods.xWrite(pFile->zClass, "jrnl", zOut);
|
|
sqlite3_free(zOut);
|
|
return i ? SQLITE_IOERR : SQLITE_OK;
|
|
}
|
|
static int kvvfsSyncDb(sqlite3_file *pProtoFile, int flags){
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Return the current file-size of an kvvfs-file.
|
|
*/
|
|
static int kvvfsFileSizeJrnl(sqlite3_file *pProtoFile, sqlite_int64 *pSize){
|
|
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
|
SQLITE_KV_LOG(("xFileSize('%s-journal')\n", pFile->zClass));
|
|
*pSize = pFile->nJrnl;
|
|
return SQLITE_OK;
|
|
}
|
|
static int kvvfsFileSizeDb(sqlite3_file *pProtoFile, sqlite_int64 *pSize){
|
|
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
|
SQLITE_KV_LOG(("xFileSize('%s-db')\n", pFile->zClass));
|
|
if( pFile->szDb>=0 ){
|
|
*pSize = pFile->szDb;
|
|
}else{
|
|
*pSize = kvvfsReadFileSize(pFile);
|
|
}
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Lock an kvvfs-file.
|
|
*/
|
|
static int kvvfsLock(sqlite3_file *pProtoFile, int eLock){
|
|
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
|
assert( !pFile->isJournal );
|
|
SQLITE_KV_LOG(("xLock(%s,%d)\n", pFile->zClass, eLock));
|
|
|
|
if( eLock!=SQLITE_LOCK_NONE ){
|
|
pFile->szDb = kvvfsReadFileSize(pFile);
|
|
}
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Unlock an kvvfs-file.
|
|
*/
|
|
static int kvvfsUnlock(sqlite3_file *pProtoFile, int eLock){
|
|
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
|
assert( !pFile->isJournal );
|
|
SQLITE_KV_LOG(("xUnlock(%s,%d)\n", pFile->zClass, eLock));
|
|
if( eLock==SQLITE_LOCK_NONE ){
|
|
pFile->szDb = -1;
|
|
}
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Check if another file-handle holds a RESERVED lock on an kvvfs-file.
|
|
*/
|
|
static int kvvfsCheckReservedLock(sqlite3_file *pProtoFile, int *pResOut){
|
|
SQLITE_KV_LOG(("xCheckReservedLock\n"));
|
|
*pResOut = 0;
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** File control method. For custom operations on an kvvfs-file.
|
|
*/
|
|
static int kvvfsFileControlJrnl(sqlite3_file *pProtoFile, int op, void *pArg){
|
|
SQLITE_KV_LOG(("xFileControl(%d) on journal\n", op));
|
|
return SQLITE_NOTFOUND;
|
|
}
|
|
static int kvvfsFileControlDb(sqlite3_file *pProtoFile, int op, void *pArg){
|
|
SQLITE_KV_LOG(("xFileControl(%d) on database\n", op));
|
|
if( op==SQLITE_FCNTL_SYNC ){
|
|
KVVfsFile *pFile = (KVVfsFile *)pProtoFile;
|
|
int rc = SQLITE_OK;
|
|
SQLITE_KV_LOG(("xSync('%s-db')\n", pFile->zClass));
|
|
if( pFile->szDb>0 && 0!=kvvfsWriteFileSize(pFile, pFile->szDb) ){
|
|
rc = SQLITE_IOERR;
|
|
}
|
|
return rc;
|
|
}
|
|
return SQLITE_NOTFOUND;
|
|
}
|
|
|
|
/*
|
|
** Return the sector-size in bytes for an kvvfs-file.
|
|
*/
|
|
static int kvvfsSectorSize(sqlite3_file *pFile){
|
|
return 512;
|
|
}
|
|
|
|
/*
|
|
** Return the device characteristic flags supported by an kvvfs-file.
|
|
*/
|
|
static int kvvfsDeviceCharacteristics(sqlite3_file *pProtoFile){
|
|
return 0;
|
|
}
|
|
|
|
/****** sqlite3_vfs methods *************************************************/
|
|
|
|
/*
|
|
** Open an kvvfs file handle.
|
|
*/
|
|
static int kvvfsOpen(
|
|
sqlite3_vfs *pProtoVfs,
|
|
const char *zName,
|
|
sqlite3_file *pProtoFile,
|
|
int flags,
|
|
int *pOutFlags
|
|
){
|
|
KVVfsFile *pFile = (KVVfsFile*)pProtoFile;
|
|
if( zName==0 ) zName = "";
|
|
SQLITE_KV_LOG(("xOpen(\"%s\")\n", zName));
|
|
if( strcmp(zName, "local")==0
|
|
|| strcmp(zName, "session")==0
|
|
){
|
|
pFile->isJournal = 0;
|
|
pFile->base.pMethods = &kvvfs_db_io_methods;
|
|
}else
|
|
if( strcmp(zName, "local-journal")==0
|
|
|| strcmp(zName, "session-journal")==0
|
|
){
|
|
pFile->isJournal = 1;
|
|
pFile->base.pMethods = &kvvfs_jrnl_io_methods;
|
|
}else{
|
|
return SQLITE_CANTOPEN;
|
|
}
|
|
if( zName[0]=='s' ){
|
|
pFile->zClass = "session";
|
|
}else{
|
|
pFile->zClass = "local";
|
|
}
|
|
pFile->aData = sqlite3_malloc64(SQLITE_KVOS_SZ);
|
|
if( pFile->aData==0 ){
|
|
return SQLITE_NOMEM;
|
|
}
|
|
pFile->aJrnl = 0;
|
|
pFile->nJrnl = 0;
|
|
pFile->szPage = -1;
|
|
pFile->szDb = -1;
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Delete the file located at zPath. If the dirSync argument is true,
|
|
** ensure the file-system modifications are synced to disk before
|
|
** returning.
|
|
*/
|
|
static int kvvfsDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
|
|
if( strcmp(zPath, "local-journal")==0 ){
|
|
sqlite3KvvfsMethods.xDelete("local", "jrnl");
|
|
}else
|
|
if( strcmp(zPath, "session-journal")==0 ){
|
|
sqlite3KvvfsMethods.xDelete("session", "jrnl");
|
|
}
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Test for access permissions. Return true if the requested permission
|
|
** is available, or false otherwise.
|
|
*/
|
|
static int kvvfsAccess(
|
|
sqlite3_vfs *pProtoVfs,
|
|
const char *zPath,
|
|
int flags,
|
|
int *pResOut
|
|
){
|
|
SQLITE_KV_LOG(("xAccess(\"%s\")\n", zPath));
|
|
if( strcmp(zPath, "local-journal")==0 ){
|
|
*pResOut = sqlite3KvvfsMethods.xRead("local", "jrnl", 0, 0)>0;
|
|
}else
|
|
if( strcmp(zPath, "session-journal")==0 ){
|
|
*pResOut = sqlite3KvvfsMethods.xRead("session", "jrnl", 0, 0)>0;
|
|
}else
|
|
if( strcmp(zPath, "local")==0 ){
|
|
*pResOut = sqlite3KvvfsMethods.xRead("local", "sz", 0, 0)>0;
|
|
}else
|
|
if( strcmp(zPath, "session")==0 ){
|
|
*pResOut = sqlite3KvvfsMethods.xRead("session", "sz", 0, 0)>0;
|
|
}else
|
|
{
|
|
*pResOut = 0;
|
|
}
|
|
SQLITE_KV_LOG(("xAccess returns %d\n",*pResOut));
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Populate buffer zOut with the full canonical pathname corresponding
|
|
** to the pathname in zPath. zOut is guaranteed to point to a buffer
|
|
** of at least (INST_MAX_PATHNAME+1) bytes.
|
|
*/
|
|
static int kvvfsFullPathname(
|
|
sqlite3_vfs *pVfs,
|
|
const char *zPath,
|
|
int nOut,
|
|
char *zOut
|
|
){
|
|
size_t nPath;
|
|
#ifdef SQLITE_OS_KV_ALWAYS_LOCAL
|
|
zPath = "local";
|
|
#endif
|
|
nPath = strlen(zPath);
|
|
SQLITE_KV_LOG(("xFullPathname(\"%s\")\n", zPath));
|
|
if( nOut<nPath+1 ) nPath = nOut - 1;
|
|
memcpy(zOut, zPath, nPath);
|
|
zOut[nPath] = 0;
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Open the dynamic library located at zPath and return a handle.
|
|
*/
|
|
static void *kvvfsDlOpen(sqlite3_vfs *pVfs, const char *zPath){
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
** Populate the buffer pointed to by zBufOut with nByte bytes of
|
|
** random data.
|
|
*/
|
|
static int kvvfsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
|
|
memset(zBufOut, 0, nByte);
|
|
return nByte;
|
|
}
|
|
|
|
/*
|
|
** Sleep for nMicro microseconds. Return the number of microseconds
|
|
** actually slept.
|
|
*/
|
|
static int kvvfsSleep(sqlite3_vfs *pVfs, int nMicro){
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Return the current time as a Julian Day number in *pTimeOut.
|
|
*/
|
|
static int kvvfsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
|
|
sqlite3_int64 i = 0;
|
|
int rc;
|
|
rc = kvvfsCurrentTimeInt64(0, &i);
|
|
*pTimeOut = i/86400000.0;
|
|
return rc;
|
|
}
|
|
#include <sys/time.h>
|
|
static int kvvfsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
|
|
static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
|
|
struct timeval sNow;
|
|
(void)gettimeofday(&sNow, 0); /* Cannot fail given valid arguments */
|
|
*pTimeOut = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_usec/1000;
|
|
return SQLITE_OK;
|
|
}
|
|
#endif /* SQLITE_OS_KV || SQLITE_OS_UNIX */
|
|
|
|
#if SQLITE_OS_KV
|
|
/*
|
|
** This routine is called initialize the KV-vfs as the default VFS.
|
|
*/
|
|
SQLITE_API int sqlite3_os_init(void){
|
|
return sqlite3_vfs_register(&sqlite3OsKvvfsObject, 1);
|
|
}
|
|
SQLITE_API int sqlite3_os_end(void){
|
|
return SQLITE_OK;
|
|
}
|
|
#endif /* SQLITE_OS_KV */
|
|
|
|
#if SQLITE_OS_UNIX && defined(SQLITE_OS_KV_OPTIONAL)
|
|
SQLITE_PRIVATE int sqlite3KvvfsInit(void){
|
|
return sqlite3_vfs_register(&sqlite3OsKvvfsObject, 0);
|
|
}
|
|
#endif
|
|
|
|
/************** End of os_kv.c ***********************************************/
|
|
/************** Begin file os_unix.c *****************************************/
|
|
/*
|
|
** 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 the VFS implementation for unix-like operating systems
|
|
** include Linux, MacOSX, *BSD, QNX, VxWorks, AIX, HPUX, and others.
|
|
**
|
|
** There are actually several different VFS implementations in this file.
|
|
** The differences are in the way that file locking is done. The default
|
|
** implementation uses Posix Advisory Locks. Alternative implementations
|
|
** use flock(), dot-files, various proprietary locking schemas, or simply
|
|
** skip locking all together.
|
|
**
|
|
** This source file is organized into divisions where the logic for various
|
|
** subfunctions is contained within the appropriate division. PLEASE
|
|
** KEEP THE STRUCTURE OF THIS FILE INTACT. New code should be placed
|
|
** in the correct division and should be clearly labelled.
|
|
**
|
|
** The layout of divisions is as follows:
|
|
**
|
|
** * General-purpose declarations and utility functions.
|
|
** * Unique file ID logic used by VxWorks.
|
|
** * Various locking primitive implementations (all except proxy locking):
|
|
** + for Posix Advisory Locks
|
|
** + for no-op locks
|
|
** + for dot-file locks
|
|
** + for flock() locking
|
|
** + for named semaphore locks (VxWorks only)
|
|
** + for AFP filesystem locks (MacOSX only)
|
|
** * sqlite3_file methods not associated with locking.
|
|
** * Definitions of sqlite3_io_methods objects for all locking
|
|
** methods plus "finder" functions for each locking method.
|
|
** * sqlite3_vfs method implementations.
|
|
** * Locking primitives for the proxy uber-locking-method. (MacOSX only)
|
|
** * Definitions of sqlite3_vfs objects for all locking methods
|
|
** plus implementations of sqlite3_os_init() and sqlite3_os_end().
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
#if SQLITE_OS_UNIX /* This file is used on unix only */
|
|
|
|
/*
|
|
** There are various methods for file locking used for concurrency
|
|
** control:
|
|
**
|
|
** 1. POSIX locking (the default),
|
|
** 2. No locking,
|
|
** 3. Dot-file locking,
|
|
** 4. flock() locking,
|
|
** 5. AFP locking (OSX only),
|
|
** 6. Named POSIX semaphores (VXWorks only),
|
|
** 7. proxy locking. (OSX only)
|
|
**
|
|
** Styles 4, 5, and 7 are only available of SQLITE_ENABLE_LOCKING_STYLE
|
|
** is defined to 1. The SQLITE_ENABLE_LOCKING_STYLE also enables automatic
|
|
** selection of the appropriate locking style based on the filesystem
|
|
** where the database is located.
|
|
*/
|
|
#if !defined(SQLITE_ENABLE_LOCKING_STYLE)
|
|
# if defined(__APPLE__)
|
|
# define SQLITE_ENABLE_LOCKING_STYLE 1
|
|
# else
|
|
# define SQLITE_ENABLE_LOCKING_STYLE 0
|
|
# endif
|
|
#endif
|
|
|
|
/* Use pread() and pwrite() if they are available */
|
|
#if defined(__APPLE__) || defined(__linux__)
|
|
# define HAVE_PREAD 1
|
|
# define HAVE_PWRITE 1
|
|
#endif
|
|
#if defined(HAVE_PREAD64) && defined(HAVE_PWRITE64)
|
|
# undef USE_PREAD
|
|
# define USE_PREAD64 1
|
|
#elif defined(HAVE_PREAD) && defined(HAVE_PWRITE)
|
|
# undef USE_PREAD64
|
|
# define USE_PREAD 1
|
|
#endif
|
|
|
|
/*
|
|
** standard include files.
|
|
*/
|
|
#include <sys/types.h> /* amalgamator: keep */
|
|
#include <sys/stat.h> /* amalgamator: keep */
|
|
#include <fcntl.h>
|
|
#include <sys/ioctl.h>
|
|
#include <unistd.h> /* amalgamator: keep */
|
|
/* #include <time.h> */
|
|
#include <sys/time.h> /* amalgamator: keep */
|
|
#include <errno.h>
|
|
#if (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) \
|
|
&& !defined(SQLITE_WASI)
|
|
# include <sys/mman.h>
|
|
#endif
|
|
|
|
#if SQLITE_ENABLE_LOCKING_STYLE
|
|
/* # include <sys/ioctl.h> */
|
|
# include <sys/file.h>
|
|
# include <sys/param.h>
|
|
#endif /* SQLITE_ENABLE_LOCKING_STYLE */
|
|
|
|
/*
|
|
** Try to determine if gethostuuid() is available based on standard
|
|
** macros. This might sometimes compute the wrong value for some
|
|
** obscure platforms. For those cases, simply compile with one of
|
|
** the following:
|
|
**
|
|
** -DHAVE_GETHOSTUUID=0
|
|
** -DHAVE_GETHOSTUUID=1
|
|
**
|
|
** None if this matters except when building on Apple products with
|
|
** -DSQLITE_ENABLE_LOCKING_STYLE.
|
|
*/
|
|
#ifndef HAVE_GETHOSTUUID
|
|
# define HAVE_GETHOSTUUID 0
|
|
# if defined(__APPLE__) && ((__MAC_OS_X_VERSION_MIN_REQUIRED > 1050) || \
|
|
(__IPHONE_OS_VERSION_MIN_REQUIRED > 2000))
|
|
# if (!defined(TARGET_OS_EMBEDDED) || (TARGET_OS_EMBEDDED==0)) \
|
|
&& (!defined(TARGET_IPHONE_SIMULATOR) || (TARGET_IPHONE_SIMULATOR==0))\
|
|
&& (!defined(TARGET_OS_MACCATALYST) || (TARGET_OS_MACCATALYST==0))
|
|
# undef HAVE_GETHOSTUUID
|
|
# define HAVE_GETHOSTUUID 1
|
|
# else
|
|
# warning "gethostuuid() is disabled."
|
|
# endif
|
|
# endif
|
|
#endif
|
|
|
|
|
|
#if OS_VXWORKS
|
|
/* # include <sys/ioctl.h> */
|
|
# include <semaphore.h>
|
|
# include <limits.h>
|
|
#endif /* OS_VXWORKS */
|
|
|
|
#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
|
|
# include <sys/mount.h>
|
|
#endif
|
|
|
|
#ifdef HAVE_UTIME
|
|
# include <utime.h>
|
|
#endif
|
|
|
|
/*
|
|
** Allowed values of unixFile.fsFlags
|
|
*/
|
|
#define SQLITE_FSFLAGS_IS_MSDOS 0x1
|
|
|
|
/*
|
|
** If we are to be thread-safe, include the pthreads header.
|
|
*/
|
|
#if SQLITE_THREADSAFE
|
|
/* # include <pthread.h> */
|
|
#endif
|
|
|
|
/*
|
|
** Default permissions when creating a new file
|
|
*/
|
|
#ifndef SQLITE_DEFAULT_FILE_PERMISSIONS
|
|
# define SQLITE_DEFAULT_FILE_PERMISSIONS 0644
|
|
#endif
|
|
|
|
/*
|
|
** Default permissions when creating auto proxy dir
|
|
*/
|
|
#ifndef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
|
|
# define SQLITE_DEFAULT_PROXYDIR_PERMISSIONS 0755
|
|
#endif
|
|
|
|
/*
|
|
** Maximum supported path-length.
|
|
*/
|
|
#define MAX_PATHNAME 512
|
|
|
|
/*
|
|
** Maximum supported symbolic links
|
|
*/
|
|
#define SQLITE_MAX_SYMLINKS 100
|
|
|
|
/*
|
|
** Remove and stub certain info for WASI (WebAssembly System
|
|
** Interface) builds.
|
|
*/
|
|
#ifdef SQLITE_WASI
|
|
# undef HAVE_FCHMOD
|
|
# undef HAVE_FCHOWN
|
|
# undef HAVE_MREMAP
|
|
# define HAVE_MREMAP 0
|
|
# ifndef SQLITE_DEFAULT_UNIX_VFS
|
|
# define SQLITE_DEFAULT_UNIX_VFS "unix-dotfile"
|
|
/* ^^^ should SQLITE_DEFAULT_UNIX_VFS be "unix-none"? */
|
|
# endif
|
|
# ifndef F_RDLCK
|
|
# define F_RDLCK 0
|
|
# define F_WRLCK 1
|
|
# define F_UNLCK 2
|
|
# if __LONG_MAX == 0x7fffffffL
|
|
# define F_GETLK 12
|
|
# define F_SETLK 13
|
|
# define F_SETLKW 14
|
|
# else
|
|
# define F_GETLK 5
|
|
# define F_SETLK 6
|
|
# define F_SETLKW 7
|
|
# endif
|
|
# endif
|
|
#else /* !SQLITE_WASI */
|
|
# ifndef HAVE_FCHMOD
|
|
# define HAVE_FCHMOD
|
|
# endif
|
|
#endif /* SQLITE_WASI */
|
|
|
|
#ifdef SQLITE_WASI
|
|
# define osGetpid(X) (pid_t)1
|
|
#else
|
|
/* Always cast the getpid() return type for compatibility with
|
|
** kernel modules in VxWorks. */
|
|
# define osGetpid(X) (pid_t)getpid()
|
|
#endif
|
|
|
|
/*
|
|
** Only set the lastErrno if the error code is a real error and not
|
|
** a normal expected return code of SQLITE_BUSY or SQLITE_OK
|
|
*/
|
|
#define IS_LOCK_ERROR(x) ((x != SQLITE_OK) && (x != SQLITE_BUSY))
|
|
|
|
/* Forward references */
|
|
typedef struct unixShm unixShm; /* Connection shared memory */
|
|
typedef struct unixShmNode unixShmNode; /* Shared memory instance */
|
|
typedef struct unixInodeInfo unixInodeInfo; /* An i-node */
|
|
typedef struct UnixUnusedFd UnixUnusedFd; /* An unused file descriptor */
|
|
|
|
/*
|
|
** Sometimes, after a file handle is closed by SQLite, the file descriptor
|
|
** cannot be closed immediately. In these cases, instances of the following
|
|
** structure are used to store the file descriptor while waiting for an
|
|
** opportunity to either close or reuse it.
|
|
*/
|
|
struct UnixUnusedFd {
|
|
int fd; /* File descriptor to close */
|
|
int flags; /* Flags this file descriptor was opened with */
|
|
UnixUnusedFd *pNext; /* Next unused file descriptor on same file */
|
|
};
|
|
|
|
/*
|
|
** The unixFile structure is subclass of sqlite3_file specific to the unix
|
|
** VFS implementations.
|
|
*/
|
|
typedef struct unixFile unixFile;
|
|
struct unixFile {
|
|
sqlite3_io_methods const *pMethod; /* Always the first entry */
|
|
sqlite3_vfs *pVfs; /* The VFS that created this unixFile */
|
|
unixInodeInfo *pInode; /* Info about locks on this inode */
|
|
int h; /* The file descriptor */
|
|
unsigned char eFileLock; /* The type of lock held on this fd */
|
|
unsigned short int ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */
|
|
int lastErrno; /* The unix errno from last I/O error */
|
|
void *lockingContext; /* Locking style specific state */
|
|
UnixUnusedFd *pPreallocatedUnused; /* Pre-allocated UnixUnusedFd */
|
|
const char *zPath; /* Name of the file */
|
|
unixShm *pShm; /* Shared memory segment information */
|
|
int szChunk; /* Configured by FCNTL_CHUNK_SIZE */
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
int nFetchOut; /* Number of outstanding xFetch refs */
|
|
sqlite3_int64 mmapSize; /* Usable size of mapping at pMapRegion */
|
|
sqlite3_int64 mmapSizeActual; /* Actual size of mapping at pMapRegion */
|
|
sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */
|
|
void *pMapRegion; /* Memory mapped region */
|
|
#endif
|
|
int sectorSize; /* Device sector size */
|
|
int deviceCharacteristics; /* Precomputed device characteristics */
|
|
#if SQLITE_ENABLE_LOCKING_STYLE
|
|
int openFlags; /* The flags specified at open() */
|
|
#endif
|
|
#if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__)
|
|
unsigned fsFlags; /* cached details from statfs() */
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
unsigned iBusyTimeout; /* Wait this many millisec on locks */
|
|
#endif
|
|
#if OS_VXWORKS
|
|
struct vxworksFileId *pId; /* Unique file ID */
|
|
#endif
|
|
#ifdef SQLITE_DEBUG
|
|
/* The next group of variables are used to track whether or not the
|
|
** transaction counter in bytes 24-27 of database files are updated
|
|
** whenever any part of the database changes. An assertion fault will
|
|
** occur if a file is updated without also updating the transaction
|
|
** counter. This test is made to avoid new problems similar to the
|
|
** one described by ticket #3584.
|
|
*/
|
|
unsigned char transCntrChng; /* True if the transaction counter changed */
|
|
unsigned char dbUpdate; /* True if any part of database file changed */
|
|
unsigned char inNormalWrite; /* True if in a normal write operation */
|
|
|
|
#endif
|
|
|
|
#ifdef SQLITE_TEST
|
|
/* In test mode, increase the size of this structure a bit so that
|
|
** it is larger than the struct CrashFile defined in test6.c.
|
|
*/
|
|
char aPadding[32];
|
|
#endif
|
|
};
|
|
|
|
/* This variable holds the process id (pid) from when the xRandomness()
|
|
** method was called. If xOpen() is called from a different process id,
|
|
** indicating that a fork() has occurred, the PRNG will be reset.
|
|
*/
|
|
static pid_t randomnessPid = 0;
|
|
|
|
/*
|
|
** Allowed values for the unixFile.ctrlFlags bitmask:
|
|
*/
|
|
#define UNIXFILE_EXCL 0x01 /* Connections from one process only */
|
|
#define UNIXFILE_RDONLY 0x02 /* Connection is read only */
|
|
#define UNIXFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */
|
|
#ifndef SQLITE_DISABLE_DIRSYNC
|
|
# define UNIXFILE_DIRSYNC 0x08 /* Directory sync needed */
|
|
#else
|
|
# define UNIXFILE_DIRSYNC 0x00
|
|
#endif
|
|
#define UNIXFILE_PSOW 0x10 /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
|
|
#define UNIXFILE_DELETE 0x20 /* Delete on close */
|
|
#define UNIXFILE_URI 0x40 /* Filename might have query parameters */
|
|
#define UNIXFILE_NOLOCK 0x80 /* Do no file locking */
|
|
|
|
/*
|
|
** Include code that is common to all os_*.c files
|
|
*/
|
|
/* #include "os_common.h" */
|
|
|
|
/*
|
|
** 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 threadid macro resolves to the thread-id or to 0. Used for
|
|
** testing and debugging only.
|
|
*/
|
|
#if SQLITE_THREADSAFE
|
|
#define threadid pthread_self()
|
|
#else
|
|
#define threadid 0
|
|
#endif
|
|
|
|
/*
|
|
** HAVE_MREMAP defaults to true on Linux and false everywhere else.
|
|
*/
|
|
#if !defined(HAVE_MREMAP)
|
|
# if defined(__linux__) && defined(_GNU_SOURCE)
|
|
# define HAVE_MREMAP 1
|
|
# else
|
|
# define HAVE_MREMAP 0
|
|
# endif
|
|
#endif
|
|
|
|
/*
|
|
** Explicitly call the 64-bit version of lseek() on Android. Otherwise, lseek()
|
|
** is the 32-bit version, even if _FILE_OFFSET_BITS=64 is defined.
|
|
*/
|
|
#ifdef __ANDROID__
|
|
# define lseek lseek64
|
|
#endif
|
|
|
|
#ifdef __linux__
|
|
/*
|
|
** Linux-specific IOCTL magic numbers used for controlling F2FS
|
|
*/
|
|
#define F2FS_IOCTL_MAGIC 0xf5
|
|
#define F2FS_IOC_START_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 1)
|
|
#define F2FS_IOC_COMMIT_ATOMIC_WRITE _IO(F2FS_IOCTL_MAGIC, 2)
|
|
#define F2FS_IOC_START_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 3)
|
|
#define F2FS_IOC_ABORT_VOLATILE_WRITE _IO(F2FS_IOCTL_MAGIC, 5)
|
|
#define F2FS_IOC_GET_FEATURES _IOR(F2FS_IOCTL_MAGIC, 12, u32)
|
|
#define F2FS_FEATURE_ATOMIC_WRITE 0x0004
|
|
#endif /* __linux__ */
|
|
|
|
|
|
/*
|
|
** Different Unix systems declare open() in different ways. Same use
|
|
** open(const char*,int,mode_t). Others use open(const char*,int,...).
|
|
** The difference is important when using a pointer to the function.
|
|
**
|
|
** The safest way to deal with the problem is to always use this wrapper
|
|
** which always has the same well-defined interface.
|
|
*/
|
|
static int posixOpen(const char *zFile, int flags, int mode){
|
|
return open(zFile, flags, mode);
|
|
}
|
|
|
|
/* Forward reference */
|
|
static int openDirectory(const char*, int*);
|
|
static int unixGetpagesize(void);
|
|
|
|
/*
|
|
** Many system calls are accessed through pointer-to-functions so that
|
|
** they may be overridden at runtime to facilitate fault injection during
|
|
** testing and sandboxing. The following array holds the names and pointers
|
|
** to all overrideable system calls.
|
|
*/
|
|
static struct unix_syscall {
|
|
const char *zName; /* Name of the system call */
|
|
sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
|
|
sqlite3_syscall_ptr pDefault; /* Default value */
|
|
} aSyscall[] = {
|
|
{ "open", (sqlite3_syscall_ptr)posixOpen, 0 },
|
|
#define osOpen ((int(*)(const char*,int,int))aSyscall[0].pCurrent)
|
|
|
|
{ "close", (sqlite3_syscall_ptr)close, 0 },
|
|
#define osClose ((int(*)(int))aSyscall[1].pCurrent)
|
|
|
|
{ "access", (sqlite3_syscall_ptr)access, 0 },
|
|
#define osAccess ((int(*)(const char*,int))aSyscall[2].pCurrent)
|
|
|
|
{ "getcwd", (sqlite3_syscall_ptr)getcwd, 0 },
|
|
#define osGetcwd ((char*(*)(char*,size_t))aSyscall[3].pCurrent)
|
|
|
|
{ "stat", (sqlite3_syscall_ptr)stat, 0 },
|
|
#define osStat ((int(*)(const char*,struct stat*))aSyscall[4].pCurrent)
|
|
|
|
/*
|
|
** 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 is DOS - what did you expect?
|
|
*/
|
|
#ifdef __DJGPP__
|
|
{ "fstat", 0, 0 },
|
|
#define osFstat(a,b,c) 0
|
|
#else
|
|
{ "fstat", (sqlite3_syscall_ptr)fstat, 0 },
|
|
#define osFstat ((int(*)(int,struct stat*))aSyscall[5].pCurrent)
|
|
#endif
|
|
|
|
{ "ftruncate", (sqlite3_syscall_ptr)ftruncate, 0 },
|
|
#define osFtruncate ((int(*)(int,off_t))aSyscall[6].pCurrent)
|
|
|
|
{ "fcntl", (sqlite3_syscall_ptr)fcntl, 0 },
|
|
#define osFcntl ((int(*)(int,int,...))aSyscall[7].pCurrent)
|
|
|
|
{ "read", (sqlite3_syscall_ptr)read, 0 },
|
|
#define osRead ((ssize_t(*)(int,void*,size_t))aSyscall[8].pCurrent)
|
|
|
|
#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
|
|
{ "pread", (sqlite3_syscall_ptr)pread, 0 },
|
|
#else
|
|
{ "pread", (sqlite3_syscall_ptr)0, 0 },
|
|
#endif
|
|
#define osPread ((ssize_t(*)(int,void*,size_t,off_t))aSyscall[9].pCurrent)
|
|
|
|
#if defined(USE_PREAD64)
|
|
{ "pread64", (sqlite3_syscall_ptr)pread64, 0 },
|
|
#else
|
|
{ "pread64", (sqlite3_syscall_ptr)0, 0 },
|
|
#endif
|
|
#define osPread64 ((ssize_t(*)(int,void*,size_t,off64_t))aSyscall[10].pCurrent)
|
|
|
|
{ "write", (sqlite3_syscall_ptr)write, 0 },
|
|
#define osWrite ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent)
|
|
|
|
#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
|
|
{ "pwrite", (sqlite3_syscall_ptr)pwrite, 0 },
|
|
#else
|
|
{ "pwrite", (sqlite3_syscall_ptr)0, 0 },
|
|
#endif
|
|
#define osPwrite ((ssize_t(*)(int,const void*,size_t,off_t))\
|
|
aSyscall[12].pCurrent)
|
|
|
|
#if defined(USE_PREAD64)
|
|
{ "pwrite64", (sqlite3_syscall_ptr)pwrite64, 0 },
|
|
#else
|
|
{ "pwrite64", (sqlite3_syscall_ptr)0, 0 },
|
|
#endif
|
|
#define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off64_t))\
|
|
aSyscall[13].pCurrent)
|
|
|
|
#if defined(HAVE_FCHMOD)
|
|
{ "fchmod", (sqlite3_syscall_ptr)fchmod, 0 },
|
|
#else
|
|
{ "fchmod", (sqlite3_syscall_ptr)0, 0 },
|
|
#endif
|
|
#define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent)
|
|
|
|
#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
|
|
{ "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 },
|
|
#else
|
|
{ "fallocate", (sqlite3_syscall_ptr)0, 0 },
|
|
#endif
|
|
#define osFallocate ((int(*)(int,off_t,off_t))aSyscall[15].pCurrent)
|
|
|
|
{ "unlink", (sqlite3_syscall_ptr)unlink, 0 },
|
|
#define osUnlink ((int(*)(const char*))aSyscall[16].pCurrent)
|
|
|
|
{ "openDirectory", (sqlite3_syscall_ptr)openDirectory, 0 },
|
|
#define osOpenDirectory ((int(*)(const char*,int*))aSyscall[17].pCurrent)
|
|
|
|
{ "mkdir", (sqlite3_syscall_ptr)mkdir, 0 },
|
|
#define osMkdir ((int(*)(const char*,mode_t))aSyscall[18].pCurrent)
|
|
|
|
{ "rmdir", (sqlite3_syscall_ptr)rmdir, 0 },
|
|
#define osRmdir ((int(*)(const char*))aSyscall[19].pCurrent)
|
|
|
|
#if defined(HAVE_FCHOWN)
|
|
{ "fchown", (sqlite3_syscall_ptr)fchown, 0 },
|
|
#else
|
|
{ "fchown", (sqlite3_syscall_ptr)0, 0 },
|
|
#endif
|
|
#define osFchown ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)
|
|
|
|
#if defined(HAVE_FCHOWN)
|
|
{ "geteuid", (sqlite3_syscall_ptr)geteuid, 0 },
|
|
#else
|
|
{ "geteuid", (sqlite3_syscall_ptr)0, 0 },
|
|
#endif
|
|
#define osGeteuid ((uid_t(*)(void))aSyscall[21].pCurrent)
|
|
|
|
#if (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) \
|
|
&& !defined(SQLITE_WASI)
|
|
{ "mmap", (sqlite3_syscall_ptr)mmap, 0 },
|
|
#else
|
|
{ "mmap", (sqlite3_syscall_ptr)0, 0 },
|
|
#endif
|
|
#define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[22].pCurrent)
|
|
|
|
#if (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) \
|
|
&& !defined(SQLITE_WASI)
|
|
{ "munmap", (sqlite3_syscall_ptr)munmap, 0 },
|
|
#else
|
|
{ "munmap", (sqlite3_syscall_ptr)0, 0 },
|
|
#endif
|
|
#define osMunmap ((int(*)(void*,size_t))aSyscall[23].pCurrent)
|
|
|
|
#if HAVE_MREMAP && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)
|
|
{ "mremap", (sqlite3_syscall_ptr)mremap, 0 },
|
|
#else
|
|
{ "mremap", (sqlite3_syscall_ptr)0, 0 },
|
|
#endif
|
|
#define osMremap ((void*(*)(void*,size_t,size_t,int,...))aSyscall[24].pCurrent)
|
|
|
|
#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
|
|
{ "getpagesize", (sqlite3_syscall_ptr)unixGetpagesize, 0 },
|
|
#else
|
|
{ "getpagesize", (sqlite3_syscall_ptr)0, 0 },
|
|
#endif
|
|
#define osGetpagesize ((int(*)(void))aSyscall[25].pCurrent)
|
|
|
|
#if defined(HAVE_READLINK)
|
|
{ "readlink", (sqlite3_syscall_ptr)readlink, 0 },
|
|
#else
|
|
{ "readlink", (sqlite3_syscall_ptr)0, 0 },
|
|
#endif
|
|
#define osReadlink ((ssize_t(*)(const char*,char*,size_t))aSyscall[26].pCurrent)
|
|
|
|
#if defined(HAVE_LSTAT)
|
|
{ "lstat", (sqlite3_syscall_ptr)lstat, 0 },
|
|
#else
|
|
{ "lstat", (sqlite3_syscall_ptr)0, 0 },
|
|
#endif
|
|
#define osLstat ((int(*)(const char*,struct stat*))aSyscall[27].pCurrent)
|
|
|
|
#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
|
|
# ifdef __ANDROID__
|
|
{ "ioctl", (sqlite3_syscall_ptr)(int(*)(int, int, ...))ioctl, 0 },
|
|
#define osIoctl ((int(*)(int,int,...))aSyscall[28].pCurrent)
|
|
# else
|
|
{ "ioctl", (sqlite3_syscall_ptr)ioctl, 0 },
|
|
#define osIoctl ((int(*)(int,unsigned long,...))aSyscall[28].pCurrent)
|
|
# endif
|
|
#else
|
|
{ "ioctl", (sqlite3_syscall_ptr)0, 0 },
|
|
#endif
|
|
|
|
}; /* End of the overrideable system calls */
|
|
|
|
|
|
/*
|
|
** On some systems, calls to fchown() will trigger a message in a security
|
|
** log if they come from non-root processes. So avoid calling fchown() if
|
|
** we are not running as root.
|
|
*/
|
|
static int robustFchown(int fd, uid_t uid, gid_t gid){
|
|
#if defined(HAVE_FCHOWN)
|
|
return osGeteuid() ? 0 : osFchown(fd,uid,gid);
|
|
#else
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
** This is the xSetSystemCall() method of sqlite3_vfs for all of the
|
|
** "unix" VFSes. Return SQLITE_OK upon successfully updating the
|
|
** system call pointer, or SQLITE_NOTFOUND if there is no configurable
|
|
** system call named zName.
|
|
*/
|
|
static int unixSetSystemCall(
|
|
sqlite3_vfs *pNotUsed, /* The VFS pointer. Not used */
|
|
const char *zName, /* Name of system call to override */
|
|
sqlite3_syscall_ptr pNewFunc /* Pointer to new system call value */
|
|
){
|
|
unsigned int i;
|
|
int rc = SQLITE_NOTFOUND;
|
|
|
|
UNUSED_PARAMETER(pNotUsed);
|
|
if( zName==0 ){
|
|
/* If no zName is given, restore all system calls to their default
|
|
** settings and return NULL
|
|
*/
|
|
rc = SQLITE_OK;
|
|
for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
|
|
if( aSyscall[i].pDefault ){
|
|
aSyscall[i].pCurrent = aSyscall[i].pDefault;
|
|
}
|
|
}
|
|
}else{
|
|
/* If zName is specified, operate on only the one system call
|
|
** specified.
|
|
*/
|
|
for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
|
|
if( strcmp(zName, aSyscall[i].zName)==0 ){
|
|
if( aSyscall[i].pDefault==0 ){
|
|
aSyscall[i].pDefault = aSyscall[i].pCurrent;
|
|
}
|
|
rc = SQLITE_OK;
|
|
if( pNewFunc==0 ) pNewFunc = aSyscall[i].pDefault;
|
|
aSyscall[i].pCurrent = pNewFunc;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Return the value of a system call. Return NULL if zName is not a
|
|
** recognized system call name. NULL is also returned if the system call
|
|
** is currently undefined.
|
|
*/
|
|
static sqlite3_syscall_ptr unixGetSystemCall(
|
|
sqlite3_vfs *pNotUsed,
|
|
const char *zName
|
|
){
|
|
unsigned int i;
|
|
|
|
UNUSED_PARAMETER(pNotUsed);
|
|
for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
|
|
if( strcmp(zName, aSyscall[i].zName)==0 ) return aSyscall[i].pCurrent;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
** Return the name of the first system call after zName. If zName==NULL
|
|
** then return the name of the first system call. Return NULL if zName
|
|
** is the last system call or if zName is not the name of a valid
|
|
** system call.
|
|
*/
|
|
static const char *unixNextSystemCall(sqlite3_vfs *p, const char *zName){
|
|
int i = -1;
|
|
|
|
UNUSED_PARAMETER(p);
|
|
if( zName ){
|
|
for(i=0; i<ArraySize(aSyscall)-1; i++){
|
|
if( strcmp(zName, aSyscall[i].zName)==0 ) break;
|
|
}
|
|
}
|
|
for(i++; i<ArraySize(aSyscall); i++){
|
|
if( aSyscall[i].pCurrent!=0 ) return aSyscall[i].zName;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
** Do not accept any file descriptor less than this value, in order to avoid
|
|
** opening database file using file descriptors that are commonly used for
|
|
** standard input, output, and error.
|
|
*/
|
|
#ifndef SQLITE_MINIMUM_FILE_DESCRIPTOR
|
|
# define SQLITE_MINIMUM_FILE_DESCRIPTOR 3
|
|
#endif
|
|
|
|
/*
|
|
** Invoke open(). Do so multiple times, until it either succeeds or
|
|
** fails for some reason other than EINTR.
|
|
**
|
|
** If the file creation mode "m" is 0 then set it to the default for
|
|
** SQLite. The default is SQLITE_DEFAULT_FILE_PERMISSIONS (normally
|
|
** 0644) as modified by the system umask. If m is not 0, then
|
|
** make the file creation mode be exactly m ignoring the umask.
|
|
**
|
|
** The m parameter will be non-zero only when creating -wal, -journal,
|
|
** and -shm files. We want those files to have *exactly* the same
|
|
** permissions as their original database, unadulterated by the umask.
|
|
** In that way, if a database file is -rw-rw-rw or -rw-rw-r-, and a
|
|
** transaction crashes and leaves behind hot journals, then any
|
|
** process that is able to write to the database will also be able to
|
|
** recover the hot journals.
|
|
*/
|
|
static int robust_open(const char *z, int f, mode_t m){
|
|
int fd;
|
|
mode_t m2 = m ? m : SQLITE_DEFAULT_FILE_PERMISSIONS;
|
|
while(1){
|
|
#if defined(O_CLOEXEC)
|
|
fd = osOpen(z,f|O_CLOEXEC,m2);
|
|
#else
|
|
fd = osOpen(z,f,m2);
|
|
#endif
|
|
if( fd<0 ){
|
|
if( errno==EINTR ) continue;
|
|
break;
|
|
}
|
|
if( fd>=SQLITE_MINIMUM_FILE_DESCRIPTOR ) break;
|
|
if( (f & (O_EXCL|O_CREAT))==(O_EXCL|O_CREAT) ){
|
|
(void)osUnlink(z);
|
|
}
|
|
osClose(fd);
|
|
sqlite3_log(SQLITE_WARNING,
|
|
"attempt to open \"%s\" as file descriptor %d", z, fd);
|
|
fd = -1;
|
|
if( osOpen("/dev/null", O_RDONLY, m)<0 ) break;
|
|
}
|
|
if( fd>=0 ){
|
|
if( m!=0 ){
|
|
struct stat statbuf;
|
|
if( osFstat(fd, &statbuf)==0
|
|
&& statbuf.st_size==0
|
|
&& (statbuf.st_mode&0777)!=m
|
|
){
|
|
osFchmod(fd, m);
|
|
}
|
|
}
|
|
#if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0)
|
|
osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
|
|
#endif
|
|
}
|
|
return fd;
|
|
}
|
|
|
|
/*
|
|
** Helper functions to obtain and relinquish the global mutex. The
|
|
** global mutex is used to protect the unixInodeInfo and
|
|
** vxworksFileId objects used by this file, all of which may be
|
|
** shared by multiple threads.
|
|
**
|
|
** Function unixMutexHeld() is used to assert() that the global mutex
|
|
** is held when required. This function is only used as part of assert()
|
|
** statements. e.g.
|
|
**
|
|
** unixEnterMutex()
|
|
** assert( unixMutexHeld() );
|
|
** unixEnterLeave()
|
|
**
|
|
** To prevent deadlock, the global unixBigLock must must be acquired
|
|
** before the unixInodeInfo.pLockMutex mutex, if both are held. It is
|
|
** OK to get the pLockMutex without holding unixBigLock first, but if
|
|
** that happens, the unixBigLock mutex must not be acquired until after
|
|
** pLockMutex is released.
|
|
**
|
|
** OK: enter(unixBigLock), enter(pLockInfo)
|
|
** OK: enter(unixBigLock)
|
|
** OK: enter(pLockInfo)
|
|
** ERROR: enter(pLockInfo), enter(unixBigLock)
|
|
*/
|
|
static sqlite3_mutex *unixBigLock = 0;
|
|
static void unixEnterMutex(void){
|
|
assert( sqlite3_mutex_notheld(unixBigLock) ); /* Not a recursive mutex */
|
|
sqlite3_mutex_enter(unixBigLock);
|
|
}
|
|
static void unixLeaveMutex(void){
|
|
assert( sqlite3_mutex_held(unixBigLock) );
|
|
sqlite3_mutex_leave(unixBigLock);
|
|
}
|
|
#ifdef SQLITE_DEBUG
|
|
static int unixMutexHeld(void) {
|
|
return sqlite3_mutex_held(unixBigLock);
|
|
}
|
|
#endif
|
|
|
|
|
|
#ifdef SQLITE_HAVE_OS_TRACE
|
|
/*
|
|
** Helper function for printing out trace information from debugging
|
|
** binaries. This returns the string representation of the supplied
|
|
** integer lock-type.
|
|
*/
|
|
static const char *azFileLock(int eFileLock){
|
|
switch( eFileLock ){
|
|
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
|
|
|
|
#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 = osFcntl(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 = osFcntl(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;
|
|
osFcntl(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;
|
|
}
|
|
#undef osFcntl
|
|
#define osFcntl lockTrace
|
|
#endif /* SQLITE_LOCK_TRACE */
|
|
|
|
/*
|
|
** Retry ftruncate() calls that fail due to EINTR
|
|
**
|
|
** All calls to ftruncate() within this file should be made through
|
|
** this wrapper. On the Android platform, bypassing the logic below
|
|
** could lead to a corrupt database.
|
|
*/
|
|
static int robust_ftruncate(int h, sqlite3_int64 sz){
|
|
int rc;
|
|
#ifdef __ANDROID__
|
|
/* On Android, ftruncate() always uses 32-bit offsets, even if
|
|
** _FILE_OFFSET_BITS=64 is defined. This means it is unsafe to attempt to
|
|
** truncate a file to any size larger than 2GiB. Silently ignore any
|
|
** such attempts. */
|
|
if( sz>(sqlite3_int64)0x7FFFFFFF ){
|
|
rc = SQLITE_OK;
|
|
}else
|
|
#endif
|
|
do{ rc = osFtruncate(h,sz); }while( rc<0 && errno==EINTR );
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** This routine translates a standard POSIX errno code into something
|
|
** useful to the clients of the sqlite3 functions. Specifically, it is
|
|
** intended to translate a variety of "try again" errors into SQLITE_BUSY
|
|
** and a variety of "please close the file descriptor NOW" errors into
|
|
** SQLITE_IOERR
|
|
**
|
|
** Errors during initialization of locks, or file system support for locks,
|
|
** should handle ENOLCK, ENOTSUP, EOPNOTSUPP separately.
|
|
*/
|
|
static int sqliteErrorFromPosixError(int posixError, int sqliteIOErr) {
|
|
assert( (sqliteIOErr == SQLITE_IOERR_LOCK) ||
|
|
(sqliteIOErr == SQLITE_IOERR_UNLOCK) ||
|
|
(sqliteIOErr == SQLITE_IOERR_RDLOCK) ||
|
|
(sqliteIOErr == SQLITE_IOERR_CHECKRESERVEDLOCK) );
|
|
switch (posixError) {
|
|
case EACCES:
|
|
case EAGAIN:
|
|
case ETIMEDOUT:
|
|
case EBUSY:
|
|
case EINTR:
|
|
case ENOLCK:
|
|
/* random NFS retry error, unless during file system support
|
|
* introspection, in which it actually means what it says */
|
|
return SQLITE_BUSY;
|
|
|
|
case EPERM:
|
|
return SQLITE_PERM;
|
|
|
|
default:
|
|
return sqliteIOErr;
|
|
}
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
****************** Begin Unique File ID Utility Used By VxWorks ***************
|
|
**
|
|
** On most versions of unix, we can get a unique ID for a file by concatenating
|
|
** the device number and the inode number. But this does not work on VxWorks.
|
|
** On VxWorks, a unique file id must be based on the canonical filename.
|
|
**
|
|
** A pointer to an instance of the following structure can be used as a
|
|
** unique file ID in VxWorks. Each instance of this structure contains
|
|
** a copy of the canonical filename. There is also a reference count.
|
|
** The structure is reclaimed when the number of pointers to it drops to
|
|
** zero.
|
|
**
|
|
** There are never very many files open at one time and lookups are not
|
|
** a performance-critical path, so it is sufficient to put these
|
|
** structures on a linked list.
|
|
*/
|
|
struct vxworksFileId {
|
|
struct vxworksFileId *pNext; /* Next in a list of them all */
|
|
int nRef; /* Number of references to this one */
|
|
int nName; /* Length of the zCanonicalName[] string */
|
|
char *zCanonicalName; /* Canonical filename */
|
|
};
|
|
|
|
#if OS_VXWORKS
|
|
/*
|
|
** All unique filenames are held on a linked list headed by this
|
|
** variable:
|
|
*/
|
|
static struct vxworksFileId *vxworksFileList = 0;
|
|
|
|
/*
|
|
** Simplify a filename into its canonical form
|
|
** by making the following changes:
|
|
**
|
|
** * removing any trailing and duplicate /
|
|
** * convert /./ into just /
|
|
** * convert /A/../ where A is any simple name into just /
|
|
**
|
|
** Changes are made in-place. Return the new name length.
|
|
**
|
|
** The original filename is in z[0..n-1]. Return the number of
|
|
** characters in the simplified name.
|
|
*/
|
|
static int vxworksSimplifyName(char *z, int n){
|
|
int i, j;
|
|
while( n>1 && z[n-1]=='/' ){ n--; }
|
|
for(i=j=0; i<n; i++){
|
|
if( z[i]=='/' ){
|
|
if( z[i+1]=='/' ) continue;
|
|
if( z[i+1]=='.' && i+2<n && z[i+2]=='/' ){
|
|
i += 1;
|
|
continue;
|
|
}
|
|
if( z[i+1]=='.' && i+3<n && z[i+2]=='.' && z[i+3]=='/' ){
|
|
while( j>0 && z[j-1]!='/' ){ j--; }
|
|
if( j>0 ){ j--; }
|
|
i += 2;
|
|
continue;
|
|
}
|
|
}
|
|
z[j++] = z[i];
|
|
}
|
|
z[j] = 0;
|
|
return j;
|
|
}
|
|
|
|
/*
|
|
** Find a unique file ID for the given absolute pathname. Return
|
|
** a pointer to the vxworksFileId object. This pointer is the unique
|
|
** file ID.
|
|
**
|
|
** The nRef field of the vxworksFileId object is incremented before
|
|
** the object is returned. A new vxworksFileId object is created
|
|
** and added to the global list if necessary.
|
|
**
|
|
** If a memory allocation error occurs, return NULL.
|
|
*/
|
|
static struct vxworksFileId *vxworksFindFileId(const char *zAbsoluteName){
|
|
struct vxworksFileId *pNew; /* search key and new file ID */
|
|
struct vxworksFileId *pCandidate; /* For looping over existing file IDs */
|
|
int n; /* Length of zAbsoluteName string */
|
|
|
|
assert( zAbsoluteName[0]=='/' );
|
|
n = (int)strlen(zAbsoluteName);
|
|
pNew = sqlite3_malloc64( sizeof(*pNew) + (n+1) );
|
|
if( pNew==0 ) return 0;
|
|
pNew->zCanonicalName = (char*)&pNew[1];
|
|
memcpy(pNew->zCanonicalName, zAbsoluteName, n+1);
|
|
n = vxworksSimplifyName(pNew->zCanonicalName, n);
|
|
|
|
/* Search for an existing entry that matching the canonical name.
|
|
** If found, increment the reference count and return a pointer to
|
|
** the existing file ID.
|
|
*/
|
|
unixEnterMutex();
|
|
for(pCandidate=vxworksFileList; pCandidate; pCandidate=pCandidate->pNext){
|
|
if( pCandidate->nName==n
|
|
&& memcmp(pCandidate->zCanonicalName, pNew->zCanonicalName, n)==0
|
|
){
|
|
sqlite3_free(pNew);
|
|
pCandidate->nRef++;
|
|
unixLeaveMutex();
|
|
return pCandidate;
|
|
}
|
|
}
|
|
|
|
/* No match was found. We will make a new file ID */
|
|
pNew->nRef = 1;
|
|
pNew->nName = n;
|
|
pNew->pNext = vxworksFileList;
|
|
vxworksFileList = pNew;
|
|
unixLeaveMutex();
|
|
return pNew;
|
|
}
|
|
|
|
/*
|
|
** Decrement the reference count on a vxworksFileId object. Free
|
|
** the object when the reference count reaches zero.
|
|
*/
|
|
static void vxworksReleaseFileId(struct vxworksFileId *pId){
|
|
unixEnterMutex();
|
|
assert( pId->nRef>0 );
|
|
pId->nRef--;
|
|
if( pId->nRef==0 ){
|
|
struct vxworksFileId **pp;
|
|
for(pp=&vxworksFileList; *pp && *pp!=pId; pp = &((*pp)->pNext)){}
|
|
assert( *pp==pId );
|
|
*pp = pId->pNext;
|
|
sqlite3_free(pId);
|
|
}
|
|
unixLeaveMutex();
|
|
}
|
|
#endif /* OS_VXWORKS */
|
|
/*************** End of Unique File ID Utility Used By VxWorks ****************
|
|
******************************************************************************/
|
|
|
|
|
|
/******************************************************************************
|
|
*************************** Posix Advisory Locking ****************************
|
|
**
|
|
** POSIX advisory locks are broken by design. 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.
|
|
**
|
|
** This 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.
|
|
**
|
|
** (Aside: The use of inode numbers as unique IDs does not work on VxWorks.
|
|
** For VxWorks, we have to use the alternative unique ID system based on
|
|
** canonical filename and implemented in the previous division.)
|
|
**
|
|
** The sqlite3_file 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 unixFile 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.
|
|
**
|
|
** But wait: there are yet more problems with POSIX advisory locks.
|
|
**
|
|
** 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 unixInodeInfo object
|
|
** maintains a count of the number of pending locks on the inode.
|
|
** When an attempt is made to close an unixFile, if there are
|
|
** other unixFile 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 unixInodeInfo structure keeps a list of file descriptors that need to
|
|
** be closed and that list is walked (and cleared) when the last lock
|
|
** clears.
|
|
**
|
|
** Yet another problem: LinuxThreads do not play well with posix locks.
|
|
**
|
|
** Many older versions of linux use the LinuxThreads library which is
|
|
** not posix compliant. Under LinuxThreads, a lock created by thread
|
|
** A cannot be modified or overridden by a different thread B.
|
|
** Only thread A can modify the lock. Locking behavior is correct
|
|
** if the application uses the newer Native Posix Thread Library (NPTL)
|
|
** on linux - with NPTL a lock created by thread A can override locks
|
|
** in thread B. But there is no way to know at compile-time which
|
|
** threading library is being used. So there is no way to know at
|
|
** compile-time whether or not thread A can override locks on thread B.
|
|
** One has to do a run-time check to discover the behavior of the
|
|
** current process.
|
|
**
|
|
** SQLite used to support LinuxThreads. But support for LinuxThreads
|
|
** was dropped beginning with version 3.7.0. SQLite will still work with
|
|
** LinuxThreads provided that (1) there is no more than one connection
|
|
** per database file in the same process and (2) database connections
|
|
** do not move across threads.
|
|
*/
|
|
|
|
/*
|
|
** An instance of the following structure serves as the key used
|
|
** to locate a particular unixInodeInfo object.
|
|
*/
|
|
struct unixFileId {
|
|
dev_t dev; /* Device number */
|
|
#if OS_VXWORKS
|
|
struct vxworksFileId *pId; /* Unique file ID for vxworks. */
|
|
#else
|
|
/* We are told that some versions of Android contain a bug that
|
|
** sizes ino_t at only 32-bits instead of 64-bits. (See
|
|
** https://android-review.googlesource.com/#/c/115351/3/dist/sqlite3.c)
|
|
** To work around this, always allocate 64-bits for the inode number.
|
|
** On small machines that only have 32-bit inodes, this wastes 4 bytes,
|
|
** but that should not be a big deal. */
|
|
/* WAS: ino_t ino; */
|
|
u64 ino; /* Inode number */
|
|
#endif
|
|
};
|
|
|
|
/*
|
|
** An instance of the following structure is allocated for each open
|
|
** inode.
|
|
**
|
|
** A single inode can have multiple file descriptors, so each unixFile
|
|
** structure contains a pointer to an instance of this object and this
|
|
** object keeps a count of the number of unixFile pointing to it.
|
|
**
|
|
** Mutex rules:
|
|
**
|
|
** (1) Only the pLockMutex mutex must be held in order to read or write
|
|
** any of the locking fields:
|
|
** nShared, nLock, eFileLock, bProcessLock, pUnused
|
|
**
|
|
** (2) When nRef>0, then the following fields are unchanging and can
|
|
** be read (but not written) without holding any mutex:
|
|
** fileId, pLockMutex
|
|
**
|
|
** (3) With the exceptions above, all the fields may only be read
|
|
** or written while holding the global unixBigLock mutex.
|
|
**
|
|
** Deadlock prevention: The global unixBigLock mutex may not
|
|
** be acquired while holding the pLockMutex mutex. If both unixBigLock
|
|
** and pLockMutex are needed, then unixBigLock must be acquired first.
|
|
*/
|
|
struct unixInodeInfo {
|
|
struct unixFileId fileId; /* The lookup key */
|
|
sqlite3_mutex *pLockMutex; /* Hold this mutex for... */
|
|
int nShared; /* Number of SHARED locks held */
|
|
int nLock; /* Number of outstanding file locks */
|
|
unsigned char eFileLock; /* One of SHARED_LOCK, RESERVED_LOCK etc. */
|
|
unsigned char bProcessLock; /* An exclusive process lock is held */
|
|
UnixUnusedFd *pUnused; /* Unused file descriptors to close */
|
|
int nRef; /* Number of pointers to this structure */
|
|
unixShmNode *pShmNode; /* Shared memory associated with this inode */
|
|
unixInodeInfo *pNext; /* List of all unixInodeInfo objects */
|
|
unixInodeInfo *pPrev; /* .... doubly linked */
|
|
#if SQLITE_ENABLE_LOCKING_STYLE
|
|
unsigned long long sharedByte; /* for AFP simulated shared lock */
|
|
#endif
|
|
#if OS_VXWORKS
|
|
sem_t *pSem; /* Named POSIX semaphore */
|
|
char aSemName[MAX_PATHNAME+2]; /* Name of that semaphore */
|
|
#endif
|
|
};
|
|
|
|
/*
|
|
** A lists of all unixInodeInfo objects.
|
|
**
|
|
** Must hold unixBigLock in order to read or write this variable.
|
|
*/
|
|
static unixInodeInfo *inodeList = 0; /* All unixInodeInfo objects */
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
/*
|
|
** True if the inode mutex (on the unixFile.pFileMutex field) is held, or not.
|
|
** This routine is used only within assert() to help verify correct mutex
|
|
** usage.
|
|
*/
|
|
int unixFileMutexHeld(unixFile *pFile){
|
|
assert( pFile->pInode );
|
|
return sqlite3_mutex_held(pFile->pInode->pLockMutex);
|
|
}
|
|
int unixFileMutexNotheld(unixFile *pFile){
|
|
assert( pFile->pInode );
|
|
return sqlite3_mutex_notheld(pFile->pInode->pLockMutex);
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
**
|
|
** This function - unixLogErrorAtLine(), is only ever called via the macro
|
|
** unixLogError().
|
|
**
|
|
** It is invoked after an error occurs in an OS function and errno has been
|
|
** set. It logs a message using sqlite3_log() containing the current value of
|
|
** errno and, if possible, the human-readable equivalent from strerror() or
|
|
** strerror_r().
|
|
**
|
|
** The first argument passed to the macro should be the error code that
|
|
** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
|
|
** The two subsequent arguments should be the name of the OS function that
|
|
** failed (e.g. "unlink", "open") and the associated file-system path,
|
|
** if any.
|
|
*/
|
|
#define unixLogError(a,b,c) unixLogErrorAtLine(a,b,c,__LINE__)
|
|
static int unixLogErrorAtLine(
|
|
int errcode, /* SQLite error code */
|
|
const char *zFunc, /* Name of OS function that failed */
|
|
const char *zPath, /* File path associated with error */
|
|
int iLine /* Source line number where error occurred */
|
|
){
|
|
char *zErr; /* Message from strerror() or equivalent */
|
|
int iErrno = errno; /* Saved syscall error number */
|
|
|
|
/* If this is not a threadsafe build (SQLITE_THREADSAFE==0), then use
|
|
** the strerror() function to obtain the human-readable error message
|
|
** equivalent to errno. Otherwise, use strerror_r().
|
|
*/
|
|
#if SQLITE_THREADSAFE && defined(HAVE_STRERROR_R)
|
|
char aErr[80];
|
|
memset(aErr, 0, sizeof(aErr));
|
|
zErr = aErr;
|
|
|
|
/* If STRERROR_R_CHAR_P (set by autoconf scripts) or __USE_GNU is defined,
|
|
** assume that the system provides the GNU version of strerror_r() that
|
|
** returns a pointer to a buffer containing the error message. That pointer
|
|
** may point to aErr[], or it may point to some static storage somewhere.
|
|
** Otherwise, assume that the system provides the POSIX version of
|
|
** strerror_r(), which always writes an error message into aErr[].
|
|
**
|
|
** If the code incorrectly assumes that it is the POSIX version that is
|
|
** available, the error message will often be an empty string. Not a
|
|
** huge problem. Incorrectly concluding that the GNU version is available
|
|
** could lead to a segfault though.
|
|
*/
|
|
#if defined(STRERROR_R_CHAR_P) || defined(__USE_GNU)
|
|
zErr =
|
|
# endif
|
|
strerror_r(iErrno, aErr, sizeof(aErr)-1);
|
|
|
|
#elif SQLITE_THREADSAFE
|
|
/* This is a threadsafe build, but strerror_r() is not available. */
|
|
zErr = "";
|
|
#else
|
|
/* Non-threadsafe build, use strerror(). */
|
|
zErr = strerror(iErrno);
|
|
#endif
|
|
|
|
if( zPath==0 ) zPath = "";
|
|
sqlite3_log(errcode,
|
|
"os_unix.c:%d: (%d) %s(%s) - %s",
|
|
iLine, iErrno, zFunc, zPath, zErr
|
|
);
|
|
|
|
return errcode;
|
|
}
|
|
|
|
/*
|
|
** Close a file descriptor.
|
|
**
|
|
** We assume that close() almost always works, since it is only in a
|
|
** very sick application or on a very sick platform that it might fail.
|
|
** If it does fail, simply leak the file descriptor, but do log the
|
|
** error.
|
|
**
|
|
** Note that it is not safe to retry close() after EINTR since the
|
|
** file descriptor might have already been reused by another thread.
|
|
** So we don't even try to recover from an EINTR. Just log the error
|
|
** and move on.
|
|
*/
|
|
static void robust_close(unixFile *pFile, int h, int lineno){
|
|
if( osClose(h) ){
|
|
unixLogErrorAtLine(SQLITE_IOERR_CLOSE, "close",
|
|
pFile ? pFile->zPath : 0, lineno);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Set the pFile->lastErrno. Do this in a subroutine as that provides
|
|
** a convenient place to set a breakpoint.
|
|
*/
|
|
static void storeLastErrno(unixFile *pFile, int error){
|
|
pFile->lastErrno = error;
|
|
}
|
|
|
|
/*
|
|
** Close all file descriptors accumulated in the unixInodeInfo->pUnused list.
|
|
*/
|
|
static void closePendingFds(unixFile *pFile){
|
|
unixInodeInfo *pInode = pFile->pInode;
|
|
UnixUnusedFd *p;
|
|
UnixUnusedFd *pNext;
|
|
assert( unixFileMutexHeld(pFile) );
|
|
for(p=pInode->pUnused; p; p=pNext){
|
|
pNext = p->pNext;
|
|
robust_close(pFile, p->fd, __LINE__);
|
|
sqlite3_free(p);
|
|
}
|
|
pInode->pUnused = 0;
|
|
}
|
|
|
|
/*
|
|
** Release a unixInodeInfo structure previously allocated by findInodeInfo().
|
|
**
|
|
** The global mutex must be held when this routine is called, but the mutex
|
|
** on the inode being deleted must NOT be held.
|
|
*/
|
|
static void releaseInodeInfo(unixFile *pFile){
|
|
unixInodeInfo *pInode = pFile->pInode;
|
|
assert( unixMutexHeld() );
|
|
assert( unixFileMutexNotheld(pFile) );
|
|
if( ALWAYS(pInode) ){
|
|
pInode->nRef--;
|
|
if( pInode->nRef==0 ){
|
|
assert( pInode->pShmNode==0 );
|
|
sqlite3_mutex_enter(pInode->pLockMutex);
|
|
closePendingFds(pFile);
|
|
sqlite3_mutex_leave(pInode->pLockMutex);
|
|
if( pInode->pPrev ){
|
|
assert( pInode->pPrev->pNext==pInode );
|
|
pInode->pPrev->pNext = pInode->pNext;
|
|
}else{
|
|
assert( inodeList==pInode );
|
|
inodeList = pInode->pNext;
|
|
}
|
|
if( pInode->pNext ){
|
|
assert( pInode->pNext->pPrev==pInode );
|
|
pInode->pNext->pPrev = pInode->pPrev;
|
|
}
|
|
sqlite3_mutex_free(pInode->pLockMutex);
|
|
sqlite3_free(pInode);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Given a file descriptor, locate the unixInodeInfo object that
|
|
** describes that file descriptor. Create a new one if necessary. The
|
|
** return value might be uninitialized if an error occurs.
|
|
**
|
|
** The global mutex must held when calling this routine.
|
|
**
|
|
** Return an appropriate error code.
|
|
*/
|
|
static int findInodeInfo(
|
|
unixFile *pFile, /* Unix file with file desc used in the key */
|
|
unixInodeInfo **ppInode /* Return the unixInodeInfo object here */
|
|
){
|
|
int rc; /* System call return code */
|
|
int fd; /* The file descriptor for pFile */
|
|
struct unixFileId fileId; /* Lookup key for the unixInodeInfo */
|
|
struct stat statbuf; /* Low-level file information */
|
|
unixInodeInfo *pInode = 0; /* Candidate unixInodeInfo object */
|
|
|
|
assert( unixMutexHeld() );
|
|
|
|
/* Get low-level information about the file that we can used to
|
|
** create a unique name for the file.
|
|
*/
|
|
fd = pFile->h;
|
|
rc = osFstat(fd, &statbuf);
|
|
if( rc!=0 ){
|
|
storeLastErrno(pFile, errno);
|
|
#if defined(EOVERFLOW) && defined(SQLITE_DISABLE_LFS)
|
|
if( pFile->lastErrno==EOVERFLOW ) return SQLITE_NOLFS;
|
|
#endif
|
|
return SQLITE_IOERR;
|
|
}
|
|
|
|
#ifdef __APPLE__
|
|
/* On OS X on an msdos filesystem, the inode number is reported
|
|
** incorrectly for zero-size files. See ticket #3260. To work
|
|
** around this problem (we consider it a bug in OS X, not SQLite)
|
|
** we always increase the file size to 1 by writing a single byte
|
|
** prior to accessing the inode number. The one byte written is
|
|
** an ASCII 'S' character which also happens to be the first byte
|
|
** in the header of every SQLite database. In this way, if there
|
|
** is a race condition such that another thread has already populated
|
|
** the first page of the database, no damage is done.
|
|
*/
|
|
if( statbuf.st_size==0 && (pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS)!=0 ){
|
|
do{ rc = osWrite(fd, "S", 1); }while( rc<0 && errno==EINTR );
|
|
if( rc!=1 ){
|
|
storeLastErrno(pFile, errno);
|
|
return SQLITE_IOERR;
|
|
}
|
|
rc = osFstat(fd, &statbuf);
|
|
if( rc!=0 ){
|
|
storeLastErrno(pFile, errno);
|
|
return SQLITE_IOERR;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
memset(&fileId, 0, sizeof(fileId));
|
|
fileId.dev = statbuf.st_dev;
|
|
#if OS_VXWORKS
|
|
fileId.pId = pFile->pId;
|
|
#else
|
|
fileId.ino = (u64)statbuf.st_ino;
|
|
#endif
|
|
assert( unixMutexHeld() );
|
|
pInode = inodeList;
|
|
while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){
|
|
pInode = pInode->pNext;
|
|
}
|
|
if( pInode==0 ){
|
|
pInode = sqlite3_malloc64( sizeof(*pInode) );
|
|
if( pInode==0 ){
|
|
return SQLITE_NOMEM_BKPT;
|
|
}
|
|
memset(pInode, 0, sizeof(*pInode));
|
|
memcpy(&pInode->fileId, &fileId, sizeof(fileId));
|
|
if( sqlite3GlobalConfig.bCoreMutex ){
|
|
pInode->pLockMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
|
|
if( pInode->pLockMutex==0 ){
|
|
sqlite3_free(pInode);
|
|
return SQLITE_NOMEM_BKPT;
|
|
}
|
|
}
|
|
pInode->nRef = 1;
|
|
assert( unixMutexHeld() );
|
|
pInode->pNext = inodeList;
|
|
pInode->pPrev = 0;
|
|
if( inodeList ) inodeList->pPrev = pInode;
|
|
inodeList = pInode;
|
|
}else{
|
|
pInode->nRef++;
|
|
}
|
|
*ppInode = pInode;
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Return TRUE if pFile has been renamed or unlinked since it was first opened.
|
|
*/
|
|
static int fileHasMoved(unixFile *pFile){
|
|
#if OS_VXWORKS
|
|
return pFile->pInode!=0 && pFile->pId!=pFile->pInode->fileId.pId;
|
|
#else
|
|
struct stat buf;
|
|
return pFile->pInode!=0 &&
|
|
(osStat(pFile->zPath, &buf)!=0
|
|
|| (u64)buf.st_ino!=pFile->pInode->fileId.ino);
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
** Check a unixFile that is a database. Verify the following:
|
|
**
|
|
** (1) There is exactly one hard link on the file
|
|
** (2) The file is not a symbolic link
|
|
** (3) The file has not been renamed or unlinked
|
|
**
|
|
** Issue sqlite3_log(SQLITE_WARNING,...) messages if anything is not right.
|
|
*/
|
|
static void verifyDbFile(unixFile *pFile){
|
|
struct stat buf;
|
|
int rc;
|
|
|
|
/* These verifications occurs for the main database only */
|
|
if( pFile->ctrlFlags & UNIXFILE_NOLOCK ) return;
|
|
|
|
rc = osFstat(pFile->h, &buf);
|
|
if( rc!=0 ){
|
|
sqlite3_log(SQLITE_WARNING, "cannot fstat db file %s", pFile->zPath);
|
|
return;
|
|
}
|
|
if( buf.st_nlink==0 ){
|
|
sqlite3_log(SQLITE_WARNING, "file unlinked while open: %s", pFile->zPath);
|
|
return;
|
|
}
|
|
if( buf.st_nlink>1 ){
|
|
sqlite3_log(SQLITE_WARNING, "multiple links to file: %s", pFile->zPath);
|
|
return;
|
|
}
|
|
if( fileHasMoved(pFile) ){
|
|
sqlite3_log(SQLITE_WARNING, "file renamed while open: %s", pFile->zPath);
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
** 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, set *pResOut
|
|
** to a non-zero value otherwise *pResOut is set to zero. The return value
|
|
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
|
|
*/
|
|
static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
|
|
int rc = SQLITE_OK;
|
|
int reserved = 0;
|
|
unixFile *pFile = (unixFile*)id;
|
|
|
|
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
|
|
|
|
assert( pFile );
|
|
assert( pFile->eFileLock<=SHARED_LOCK );
|
|
sqlite3_mutex_enter(pFile->pInode->pLockMutex);
|
|
|
|
/* Check if a thread in this process holds such a lock */
|
|
if( pFile->pInode->eFileLock>SHARED_LOCK ){
|
|
reserved = 1;
|
|
}
|
|
|
|
/* Otherwise see if some other process holds it.
|
|
*/
|
|
#ifndef __DJGPP__
|
|
if( !reserved && !pFile->pInode->bProcessLock ){
|
|
struct flock lock;
|
|
lock.l_whence = SEEK_SET;
|
|
lock.l_start = RESERVED_BYTE;
|
|
lock.l_len = 1;
|
|
lock.l_type = F_WRLCK;
|
|
if( osFcntl(pFile->h, F_GETLK, &lock) ){
|
|
rc = SQLITE_IOERR_CHECKRESERVEDLOCK;
|
|
storeLastErrno(pFile, errno);
|
|
} else if( lock.l_type!=F_UNLCK ){
|
|
reserved = 1;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
sqlite3_mutex_leave(pFile->pInode->pLockMutex);
|
|
OSTRACE(("TEST WR-LOCK %d %d %d (unix)\n", pFile->h, rc, reserved));
|
|
|
|
*pResOut = reserved;
|
|
return rc;
|
|
}
|
|
|
|
/* Forward declaration*/
|
|
static int unixSleep(sqlite3_vfs*,int);
|
|
|
|
/*
|
|
** Set a posix-advisory-lock.
|
|
**
|
|
** There are two versions of this routine. If compiled with
|
|
** SQLITE_ENABLE_SETLK_TIMEOUT then the routine has an extra parameter
|
|
** which is a pointer to a unixFile. If the unixFile->iBusyTimeout
|
|
** value is set, then it is the number of milliseconds to wait before
|
|
** failing the lock. The iBusyTimeout value is always reset back to
|
|
** zero on each call.
|
|
**
|
|
** If SQLITE_ENABLE_SETLK_TIMEOUT is not defined, then do a non-blocking
|
|
** attempt to set the lock.
|
|
*/
|
|
#ifndef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
# define osSetPosixAdvisoryLock(h,x,t) osFcntl(h,F_SETLK,x)
|
|
#else
|
|
static int osSetPosixAdvisoryLock(
|
|
int h, /* The file descriptor on which to take the lock */
|
|
struct flock *pLock, /* The description of the lock */
|
|
unixFile *pFile /* Structure holding timeout value */
|
|
){
|
|
int tm = pFile->iBusyTimeout;
|
|
int rc = osFcntl(h,F_SETLK,pLock);
|
|
while( rc<0 && tm>0 ){
|
|
/* On systems that support some kind of blocking file lock with a timeout,
|
|
** make appropriate changes here to invoke that blocking file lock. On
|
|
** generic posix, however, there is no such API. So we simply try the
|
|
** lock once every millisecond until either the timeout expires, or until
|
|
** the lock is obtained. */
|
|
unixSleep(0,1000);
|
|
rc = osFcntl(h,F_SETLK,pLock);
|
|
tm--;
|
|
}
|
|
return rc;
|
|
}
|
|
#endif /* SQLITE_ENABLE_SETLK_TIMEOUT */
|
|
|
|
|
|
/*
|
|
** Attempt to set a system-lock on the file pFile. The lock is
|
|
** described by pLock.
|
|
**
|
|
** If the pFile was opened read/write from unix-excl, then the only lock
|
|
** ever obtained is an exclusive lock, and it is obtained exactly once
|
|
** the first time any lock is attempted. All subsequent system locking
|
|
** operations become no-ops. Locking operations still happen internally,
|
|
** in order to coordinate access between separate database connections
|
|
** within this process, but all of that is handled in memory and the
|
|
** operating system does not participate.
|
|
**
|
|
** This function is a pass-through to fcntl(F_SETLK) if pFile is using
|
|
** any VFS other than "unix-excl" or if pFile is opened on "unix-excl"
|
|
** and is read-only.
|
|
**
|
|
** Zero is returned if the call completes successfully, or -1 if a call
|
|
** to fcntl() fails. In this case, errno is set appropriately (by fcntl()).
|
|
*/
|
|
static int unixFileLock(unixFile *pFile, struct flock *pLock){
|
|
int rc;
|
|
unixInodeInfo *pInode = pFile->pInode;
|
|
assert( pInode!=0 );
|
|
assert( sqlite3_mutex_held(pInode->pLockMutex) );
|
|
if( (pFile->ctrlFlags & (UNIXFILE_EXCL|UNIXFILE_RDONLY))==UNIXFILE_EXCL ){
|
|
if( pInode->bProcessLock==0 ){
|
|
struct flock lock;
|
|
assert( pInode->nLock==0 );
|
|
lock.l_whence = SEEK_SET;
|
|
lock.l_start = SHARED_FIRST;
|
|
lock.l_len = SHARED_SIZE;
|
|
lock.l_type = F_WRLCK;
|
|
rc = osSetPosixAdvisoryLock(pFile->h, &lock, pFile);
|
|
if( rc<0 ) return rc;
|
|
pInode->bProcessLock = 1;
|
|
pInode->nLock++;
|
|
}else{
|
|
rc = 0;
|
|
}
|
|
}else{
|
|
rc = osSetPosixAdvisoryLock(pFile->h, pLock, pFile);
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Lock the file with the lock specified by parameter eFileLock - 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 -> 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(sqlite3_file *id, int eFileLock){
|
|
/* 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 Windows95 systems simultaneously
|
|
** accessing the same database file, in case that is ever required.
|
|
**
|
|
** Symbols defined in os.h identify 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, 'shared byte range' is read-locked
|
|
** and the lock on the 'pending byte' released. (Legacy note: When
|
|
** SQLite was first developed, Windows95 systems were still very common,
|
|
** and Windows95 lacks a shared-lock capability. So on Windows95, a
|
|
** single randomly selected by from the 'shared byte range' is locked.
|
|
** Windows95 is now pretty much extinct, but this work-around for the
|
|
** lack of shared-locks on Windows95 lives on, for backwards
|
|
** compatibility.)
|
|
**
|
|
** 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'.
|
|
**
|
|
** An EXCLUSIVE lock may only be requested after either a SHARED or
|
|
** RESERVED lock is held. An EXCLUSIVE lock 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.
|
|
**
|
|
** If a process that holds a RESERVED lock requests an EXCLUSIVE, then
|
|
** a PENDING lock is obtained first. 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. If the call to this function fails to obtain the EXCLUSIVE
|
|
** lock in this case, it holds the PENDING lock instead. The client may
|
|
** then re-attempt the EXCLUSIVE lock later on, after existing SHARED
|
|
** locks have cleared.
|
|
*/
|
|
int rc = SQLITE_OK;
|
|
unixFile *pFile = (unixFile*)id;
|
|
unixInodeInfo *pInode;
|
|
struct flock lock;
|
|
int tErrno = 0;
|
|
|
|
assert( pFile );
|
|
OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h,
|
|
azFileLock(eFileLock), azFileLock(pFile->eFileLock),
|
|
azFileLock(pFile->pInode->eFileLock), pFile->pInode->nShared,
|
|
osGetpid(0)));
|
|
|
|
/* If there is already a lock of this type or more restrictive on the
|
|
** unixFile, do nothing. Don't use the end_lock: exit path, as
|
|
** unixEnterMutex() hasn't been called yet.
|
|
*/
|
|
if( pFile->eFileLock>=eFileLock ){
|
|
OSTRACE(("LOCK %d %s ok (already held) (unix)\n", pFile->h,
|
|
azFileLock(eFileLock)));
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/* Make sure the locking sequence is correct.
|
|
** (1) We never move from unlocked to anything higher than shared lock.
|
|
** (2) SQLite never explicitly requests a pending lock.
|
|
** (3) A shared lock is always held when a reserve lock is requested.
|
|
*/
|
|
assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK );
|
|
assert( eFileLock!=PENDING_LOCK );
|
|
assert( eFileLock!=RESERVED_LOCK || pFile->eFileLock==SHARED_LOCK );
|
|
|
|
/* This mutex is needed because pFile->pInode is shared across threads
|
|
*/
|
|
pInode = pFile->pInode;
|
|
sqlite3_mutex_enter(pInode->pLockMutex);
|
|
|
|
/* If some thread using this PID has a lock via a different unixFile*
|
|
** handle that precludes the requested lock, return BUSY.
|
|
*/
|
|
if( (pFile->eFileLock!=pInode->eFileLock &&
|
|
(pInode->eFileLock>=PENDING_LOCK || eFileLock>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( eFileLock==SHARED_LOCK &&
|
|
(pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){
|
|
assert( eFileLock==SHARED_LOCK );
|
|
assert( pFile->eFileLock==0 );
|
|
assert( pInode->nShared>0 );
|
|
pFile->eFileLock = SHARED_LOCK;
|
|
pInode->nShared++;
|
|
pInode->nLock++;
|
|
goto end_lock;
|
|
}
|
|
|
|
|
|
/* 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.
|
|
*/
|
|
lock.l_len = 1L;
|
|
lock.l_whence = SEEK_SET;
|
|
if( eFileLock==SHARED_LOCK
|
|
|| (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock==RESERVED_LOCK)
|
|
){
|
|
lock.l_type = (eFileLock==SHARED_LOCK?F_RDLCK:F_WRLCK);
|
|
lock.l_start = PENDING_BYTE;
|
|
if( unixFileLock(pFile, &lock) ){
|
|
tErrno = errno;
|
|
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
|
|
if( rc!=SQLITE_BUSY ){
|
|
storeLastErrno(pFile, tErrno);
|
|
}
|
|
goto end_lock;
|
|
}else if( eFileLock==EXCLUSIVE_LOCK ){
|
|
pFile->eFileLock = PENDING_LOCK;
|
|
pInode->eFileLock = PENDING_LOCK;
|
|
}
|
|
}
|
|
|
|
|
|
/* If control gets to this point, then actually go ahead and make
|
|
** operating system calls for the specified lock.
|
|
*/
|
|
if( eFileLock==SHARED_LOCK ){
|
|
assert( pInode->nShared==0 );
|
|
assert( pInode->eFileLock==0 );
|
|
assert( rc==SQLITE_OK );
|
|
|
|
/* Now get the read-lock */
|
|
lock.l_start = SHARED_FIRST;
|
|
lock.l_len = SHARED_SIZE;
|
|
if( unixFileLock(pFile, &lock) ){
|
|
tErrno = errno;
|
|
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
|
|
}
|
|
|
|
/* Drop the temporary PENDING lock */
|
|
lock.l_start = PENDING_BYTE;
|
|
lock.l_len = 1L;
|
|
lock.l_type = F_UNLCK;
|
|
if( unixFileLock(pFile, &lock) && rc==SQLITE_OK ){
|
|
/* This could happen with a network mount */
|
|
tErrno = errno;
|
|
rc = SQLITE_IOERR_UNLOCK;
|
|
}
|
|
|
|
if( rc ){
|
|
if( rc!=SQLITE_BUSY ){
|
|
storeLastErrno(pFile, tErrno);
|
|
}
|
|
goto end_lock;
|
|
}else{
|
|
pFile->eFileLock = SHARED_LOCK;
|
|
pInode->nLock++;
|
|
pInode->nShared = 1;
|
|
}
|
|
}else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>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->eFileLock );
|
|
lock.l_type = F_WRLCK;
|
|
|
|
assert( eFileLock==RESERVED_LOCK || eFileLock==EXCLUSIVE_LOCK );
|
|
if( eFileLock==RESERVED_LOCK ){
|
|
lock.l_start = RESERVED_BYTE;
|
|
lock.l_len = 1L;
|
|
}else{
|
|
lock.l_start = SHARED_FIRST;
|
|
lock.l_len = SHARED_SIZE;
|
|
}
|
|
|
|
if( unixFileLock(pFile, &lock) ){
|
|
tErrno = errno;
|
|
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
|
|
if( rc!=SQLITE_BUSY ){
|
|
storeLastErrno(pFile, tErrno);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
/* Set up the transaction-counter change checking flags when
|
|
** transitioning from a SHARED to a RESERVED lock. The change
|
|
** from SHARED to RESERVED marks the beginning of a normal
|
|
** write operation (not a hot journal rollback).
|
|
*/
|
|
if( rc==SQLITE_OK
|
|
&& pFile->eFileLock<=SHARED_LOCK
|
|
&& eFileLock==RESERVED_LOCK
|
|
){
|
|
pFile->transCntrChng = 0;
|
|
pFile->dbUpdate = 0;
|
|
pFile->inNormalWrite = 1;
|
|
}
|
|
#endif
|
|
|
|
if( rc==SQLITE_OK ){
|
|
pFile->eFileLock = eFileLock;
|
|
pInode->eFileLock = eFileLock;
|
|
}
|
|
|
|
end_lock:
|
|
sqlite3_mutex_leave(pInode->pLockMutex);
|
|
OSTRACE(("LOCK %d %s %s (unix)\n", pFile->h, azFileLock(eFileLock),
|
|
rc==SQLITE_OK ? "ok" : "failed"));
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Add the file descriptor used by file handle pFile to the corresponding
|
|
** pUnused list.
|
|
*/
|
|
static void setPendingFd(unixFile *pFile){
|
|
unixInodeInfo *pInode = pFile->pInode;
|
|
UnixUnusedFd *p = pFile->pPreallocatedUnused;
|
|
assert( unixFileMutexHeld(pFile) );
|
|
p->pNext = pInode->pUnused;
|
|
pInode->pUnused = p;
|
|
pFile->h = -1;
|
|
pFile->pPreallocatedUnused = 0;
|
|
}
|
|
|
|
/*
|
|
** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
|
|
** 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.
|
|
**
|
|
** If handleNFSUnlock is true, then on downgrading an EXCLUSIVE_LOCK to SHARED
|
|
** the byte range is divided into 2 parts and the first part is unlocked then
|
|
** set to a read lock, then the other part is simply unlocked. This works
|
|
** around a bug in BSD NFS lockd (also seen on MacOSX 10.3+) that fails to
|
|
** remove the write lock on a region when a read lock is set.
|
|
*/
|
|
static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
|
|
unixFile *pFile = (unixFile*)id;
|
|
unixInodeInfo *pInode;
|
|
struct flock lock;
|
|
int rc = SQLITE_OK;
|
|
|
|
assert( pFile );
|
|
OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, eFileLock,
|
|
pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared,
|
|
osGetpid(0)));
|
|
|
|
assert( eFileLock<=SHARED_LOCK );
|
|
if( pFile->eFileLock<=eFileLock ){
|
|
return SQLITE_OK;
|
|
}
|
|
pInode = pFile->pInode;
|
|
sqlite3_mutex_enter(pInode->pLockMutex);
|
|
assert( pInode->nShared!=0 );
|
|
if( pFile->eFileLock>SHARED_LOCK ){
|
|
assert( pInode->eFileLock==pFile->eFileLock );
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
/* When reducing a lock such that other processes can start
|
|
** reading the database file again, make sure that the
|
|
** transaction counter was updated if any part of the database
|
|
** file changed. If the transaction counter is not updated,
|
|
** other connections to the same file might not realize that
|
|
** the file has changed and hence might not know to flush their
|
|
** cache. The use of a stale cache can lead to database corruption.
|
|
*/
|
|
pFile->inNormalWrite = 0;
|
|
#endif
|
|
|
|
/* downgrading to a shared lock on NFS involves clearing the write lock
|
|
** before establishing the readlock - to avoid a race condition we downgrade
|
|
** the lock in 2 blocks, so that part of the range will be covered by a
|
|
** write lock until the rest is covered by a read lock:
|
|
** 1: [WWWWW]
|
|
** 2: [....W]
|
|
** 3: [RRRRW]
|
|
** 4: [RRRR.]
|
|
*/
|
|
if( eFileLock==SHARED_LOCK ){
|
|
#if !defined(__APPLE__) || !SQLITE_ENABLE_LOCKING_STYLE
|
|
(void)handleNFSUnlock;
|
|
assert( handleNFSUnlock==0 );
|
|
#endif
|
|
#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
|
|
if( handleNFSUnlock ){
|
|
int tErrno; /* Error code from system call errors */
|
|
off_t divSize = SHARED_SIZE - 1;
|
|
|
|
lock.l_type = F_UNLCK;
|
|
lock.l_whence = SEEK_SET;
|
|
lock.l_start = SHARED_FIRST;
|
|
lock.l_len = divSize;
|
|
if( unixFileLock(pFile, &lock)==(-1) ){
|
|
tErrno = errno;
|
|
rc = SQLITE_IOERR_UNLOCK;
|
|
storeLastErrno(pFile, tErrno);
|
|
goto end_unlock;
|
|
}
|
|
lock.l_type = F_RDLCK;
|
|
lock.l_whence = SEEK_SET;
|
|
lock.l_start = SHARED_FIRST;
|
|
lock.l_len = divSize;
|
|
if( unixFileLock(pFile, &lock)==(-1) ){
|
|
tErrno = errno;
|
|
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
|
|
if( IS_LOCK_ERROR(rc) ){
|
|
storeLastErrno(pFile, tErrno);
|
|
}
|
|
goto end_unlock;
|
|
}
|
|
lock.l_type = F_UNLCK;
|
|
lock.l_whence = SEEK_SET;
|
|
lock.l_start = SHARED_FIRST+divSize;
|
|
lock.l_len = SHARED_SIZE-divSize;
|
|
if( unixFileLock(pFile, &lock)==(-1) ){
|
|
tErrno = errno;
|
|
rc = SQLITE_IOERR_UNLOCK;
|
|
storeLastErrno(pFile, tErrno);
|
|
goto end_unlock;
|
|
}
|
|
}else
|
|
#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
|
|
{
|
|
lock.l_type = F_RDLCK;
|
|
lock.l_whence = SEEK_SET;
|
|
lock.l_start = SHARED_FIRST;
|
|
lock.l_len = SHARED_SIZE;
|
|
if( unixFileLock(pFile, &lock) ){
|
|
/* In theory, the call to unixFileLock() cannot fail because another
|
|
** process is holding an incompatible lock. If it does, this
|
|
** indicates that the other process is not following the locking
|
|
** protocol. If this happens, return SQLITE_IOERR_RDLOCK. Returning
|
|
** SQLITE_BUSY would confuse the upper layer (in practice it causes
|
|
** an assert to fail). */
|
|
rc = SQLITE_IOERR_RDLOCK;
|
|
storeLastErrno(pFile, errno);
|
|
goto end_unlock;
|
|
}
|
|
}
|
|
}
|
|
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( unixFileLock(pFile, &lock)==0 ){
|
|
pInode->eFileLock = SHARED_LOCK;
|
|
}else{
|
|
rc = SQLITE_IOERR_UNLOCK;
|
|
storeLastErrno(pFile, errno);
|
|
goto end_unlock;
|
|
}
|
|
}
|
|
if( eFileLock==NO_LOCK ){
|
|
/* Decrement the shared lock counter. Release the lock using an
|
|
** OS call only when all threads in this same process have released
|
|
** the lock.
|
|
*/
|
|
pInode->nShared--;
|
|
if( pInode->nShared==0 ){
|
|
lock.l_type = F_UNLCK;
|
|
lock.l_whence = SEEK_SET;
|
|
lock.l_start = lock.l_len = 0L;
|
|
if( unixFileLock(pFile, &lock)==0 ){
|
|
pInode->eFileLock = NO_LOCK;
|
|
}else{
|
|
rc = SQLITE_IOERR_UNLOCK;
|
|
storeLastErrno(pFile, errno);
|
|
pInode->eFileLock = NO_LOCK;
|
|
pFile->eFileLock = NO_LOCK;
|
|
}
|
|
}
|
|
|
|
/* 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.
|
|
*/
|
|
pInode->nLock--;
|
|
assert( pInode->nLock>=0 );
|
|
if( pInode->nLock==0 ) closePendingFds(pFile);
|
|
}
|
|
|
|
end_unlock:
|
|
sqlite3_mutex_leave(pInode->pLockMutex);
|
|
if( rc==SQLITE_OK ){
|
|
pFile->eFileLock = eFileLock;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
|
|
** 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(sqlite3_file *id, int eFileLock){
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
assert( eFileLock==SHARED_LOCK || ((unixFile *)id)->nFetchOut==0 );
|
|
#endif
|
|
return posixUnlock(id, eFileLock, 0);
|
|
}
|
|
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
static int unixMapfile(unixFile *pFd, i64 nByte);
|
|
static void unixUnmapfile(unixFile *pFd);
|
|
#endif
|
|
|
|
/*
|
|
** This function performs the parts of the "close file" operation
|
|
** common to all locking schemes. It closes the directory and file
|
|
** handles, if they are valid, and sets all fields of the unixFile
|
|
** structure to 0.
|
|
**
|
|
** It is *not* necessary to hold the mutex when this routine is called,
|
|
** even on VxWorks. A mutex will be acquired on VxWorks by the
|
|
** vxworksReleaseFileId() routine.
|
|
*/
|
|
static int closeUnixFile(sqlite3_file *id){
|
|
unixFile *pFile = (unixFile*)id;
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
unixUnmapfile(pFile);
|
|
#endif
|
|
if( pFile->h>=0 ){
|
|
robust_close(pFile, pFile->h, __LINE__);
|
|
pFile->h = -1;
|
|
}
|
|
#if OS_VXWORKS
|
|
if( pFile->pId ){
|
|
if( pFile->ctrlFlags & UNIXFILE_DELETE ){
|
|
osUnlink(pFile->pId->zCanonicalName);
|
|
}
|
|
vxworksReleaseFileId(pFile->pId);
|
|
pFile->pId = 0;
|
|
}
|
|
#endif
|
|
#ifdef SQLITE_UNLINK_AFTER_CLOSE
|
|
if( pFile->ctrlFlags & UNIXFILE_DELETE ){
|
|
osUnlink(pFile->zPath);
|
|
sqlite3_free(*(char**)&pFile->zPath);
|
|
pFile->zPath = 0;
|
|
}
|
|
#endif
|
|
OSTRACE(("CLOSE %-3d\n", pFile->h));
|
|
OpenCounter(-1);
|
|
sqlite3_free(pFile->pPreallocatedUnused);
|
|
memset(pFile, 0, sizeof(unixFile));
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Close a file.
|
|
*/
|
|
static int unixClose(sqlite3_file *id){
|
|
int rc = SQLITE_OK;
|
|
unixFile *pFile = (unixFile *)id;
|
|
unixInodeInfo *pInode = pFile->pInode;
|
|
|
|
assert( pInode!=0 );
|
|
verifyDbFile(pFile);
|
|
unixUnlock(id, NO_LOCK);
|
|
assert( unixFileMutexNotheld(pFile) );
|
|
unixEnterMutex();
|
|
|
|
/* unixFile.pInode is always valid here. Otherwise, a different close
|
|
** routine (e.g. nolockClose()) would be called instead.
|
|
*/
|
|
assert( pFile->pInode->nLock>0 || pFile->pInode->bProcessLock==0 );
|
|
sqlite3_mutex_enter(pInode->pLockMutex);
|
|
if( pInode->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 pInode->pUnused list. It will be automatically closed
|
|
** when the last lock is cleared.
|
|
*/
|
|
setPendingFd(pFile);
|
|
}
|
|
sqlite3_mutex_leave(pInode->pLockMutex);
|
|
releaseInodeInfo(pFile);
|
|
assert( pFile->pShm==0 );
|
|
rc = closeUnixFile(id);
|
|
unixLeaveMutex();
|
|
return rc;
|
|
}
|
|
|
|
/************** End of the posix advisory lock implementation *****************
|
|
******************************************************************************/
|
|
|
|
/******************************************************************************
|
|
****************************** No-op Locking **********************************
|
|
**
|
|
** Of the various locking implementations available, this is by far the
|
|
** simplest: locking is ignored. No attempt is made to lock the database
|
|
** file for reading or writing.
|
|
**
|
|
** This locking mode is appropriate for use on read-only databases
|
|
** (ex: databases that are burned into CD-ROM, for example.) It can
|
|
** also be used if the application employs some external mechanism to
|
|
** prevent simultaneous access of the same database by two or more
|
|
** database connections. But there is a serious risk of database
|
|
** corruption if this locking mode is used in situations where multiple
|
|
** database connections are accessing the same database file at the same
|
|
** time and one or more of those connections are writing.
|
|
*/
|
|
|
|
static int nolockCheckReservedLock(sqlite3_file *NotUsed, int *pResOut){
|
|
UNUSED_PARAMETER(NotUsed);
|
|
*pResOut = 0;
|
|
return SQLITE_OK;
|
|
}
|
|
static int nolockLock(sqlite3_file *NotUsed, int NotUsed2){
|
|
UNUSED_PARAMETER2(NotUsed, NotUsed2);
|
|
return SQLITE_OK;
|
|
}
|
|
static int nolockUnlock(sqlite3_file *NotUsed, int NotUsed2){
|
|
UNUSED_PARAMETER2(NotUsed, NotUsed2);
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Close the file.
|
|
*/
|
|
static int nolockClose(sqlite3_file *id) {
|
|
return closeUnixFile(id);
|
|
}
|
|
|
|
/******************* End of the no-op lock implementation *********************
|
|
******************************************************************************/
|
|
|
|
/******************************************************************************
|
|
************************* Begin dot-file Locking ******************************
|
|
**
|
|
** The dotfile locking implementation uses the existence of separate lock
|
|
** files (really a directory) to control access to the database. This works
|
|
** on just about every filesystem imaginable. But there are serious downsides:
|
|
**
|
|
** (1) There is zero concurrency. A single reader blocks all other
|
|
** connections from reading or writing the database.
|
|
**
|
|
** (2) An application crash or power loss can leave stale lock files
|
|
** sitting around that need to be cleared manually.
|
|
**
|
|
** Nevertheless, a dotlock is an appropriate locking mode for use if no
|
|
** other locking strategy is available.
|
|
**
|
|
** Dotfile locking works by creating a subdirectory in the same directory as
|
|
** the database and with the same name but with a ".lock" extension added.
|
|
** The existence of a lock directory implies an EXCLUSIVE lock. All other
|
|
** lock types (SHARED, RESERVED, PENDING) are mapped into EXCLUSIVE.
|
|
*/
|
|
|
|
/*
|
|
** The file suffix added to the data base filename in order to create the
|
|
** lock directory.
|
|
*/
|
|
#define DOTLOCK_SUFFIX ".lock"
|
|
|
|
/*
|
|
** 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, set *pResOut
|
|
** to a non-zero value otherwise *pResOut is set to zero. The return value
|
|
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
|
|
**
|
|
** In dotfile locking, either a lock exists or it does not. So in this
|
|
** variation of CheckReservedLock(), *pResOut is set to true if any lock
|
|
** is held on the file and false if the file is unlocked.
|
|
*/
|
|
static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
|
|
int rc = SQLITE_OK;
|
|
int reserved = 0;
|
|
unixFile *pFile = (unixFile*)id;
|
|
|
|
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
|
|
|
|
assert( pFile );
|
|
reserved = osAccess((const char*)pFile->lockingContext, 0)==0;
|
|
OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved));
|
|
*pResOut = reserved;
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Lock the file with the lock specified by parameter eFileLock - 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.
|
|
**
|
|
** With dotfile locking, we really only support state (4): EXCLUSIVE.
|
|
** But we track the other locking levels internally.
|
|
*/
|
|
static int dotlockLock(sqlite3_file *id, int eFileLock) {
|
|
unixFile *pFile = (unixFile*)id;
|
|
char *zLockFile = (char *)pFile->lockingContext;
|
|
int rc = SQLITE_OK;
|
|
|
|
|
|
/* If we have any lock, then the lock file already exists. All we have
|
|
** to do is adjust our internal record of the lock level.
|
|
*/
|
|
if( pFile->eFileLock > NO_LOCK ){
|
|
pFile->eFileLock = eFileLock;
|
|
/* Always update the timestamp on the old file */
|
|
#ifdef HAVE_UTIME
|
|
utime(zLockFile, NULL);
|
|
#else
|
|
utimes(zLockFile, NULL);
|
|
#endif
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/* grab an exclusive lock */
|
|
rc = osMkdir(zLockFile, 0777);
|
|
if( rc<0 ){
|
|
/* failed to open/create the lock directory */
|
|
int tErrno = errno;
|
|
if( EEXIST == tErrno ){
|
|
rc = SQLITE_BUSY;
|
|
} else {
|
|
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
|
|
if( rc!=SQLITE_BUSY ){
|
|
storeLastErrno(pFile, tErrno);
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/* got it, set the type and return ok */
|
|
pFile->eFileLock = eFileLock;
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
|
|
** 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.
|
|
**
|
|
** When the locking level reaches NO_LOCK, delete the lock file.
|
|
*/
|
|
static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
|
|
unixFile *pFile = (unixFile*)id;
|
|
char *zLockFile = (char *)pFile->lockingContext;
|
|
int rc;
|
|
|
|
assert( pFile );
|
|
OSTRACE(("UNLOCK %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock,
|
|
pFile->eFileLock, osGetpid(0)));
|
|
assert( eFileLock<=SHARED_LOCK );
|
|
|
|
/* no-op if possible */
|
|
if( pFile->eFileLock==eFileLock ){
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/* To downgrade to shared, simply update our internal notion of the
|
|
** lock state. No need to mess with the file on disk.
|
|
*/
|
|
if( eFileLock==SHARED_LOCK ){
|
|
pFile->eFileLock = SHARED_LOCK;
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/* To fully unlock the database, delete the lock file */
|
|
assert( eFileLock==NO_LOCK );
|
|
rc = osRmdir(zLockFile);
|
|
if( rc<0 ){
|
|
int tErrno = errno;
|
|
if( tErrno==ENOENT ){
|
|
rc = SQLITE_OK;
|
|
}else{
|
|
rc = SQLITE_IOERR_UNLOCK;
|
|
storeLastErrno(pFile, tErrno);
|
|
}
|
|
return rc;
|
|
}
|
|
pFile->eFileLock = NO_LOCK;
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Close a file. Make sure the lock has been released before closing.
|
|
*/
|
|
static int dotlockClose(sqlite3_file *id) {
|
|
unixFile *pFile = (unixFile*)id;
|
|
assert( id!=0 );
|
|
dotlockUnlock(id, NO_LOCK);
|
|
sqlite3_free(pFile->lockingContext);
|
|
return closeUnixFile(id);
|
|
}
|
|
/****************** End of the dot-file lock implementation *******************
|
|
******************************************************************************/
|
|
|
|
/******************************************************************************
|
|
************************** Begin flock Locking ********************************
|
|
**
|
|
** Use the flock() system call to do file locking.
|
|
**
|
|
** flock() locking is like dot-file locking in that the various
|
|
** fine-grain locking levels supported by SQLite are collapsed into
|
|
** a single exclusive lock. In other words, SHARED, RESERVED, and
|
|
** PENDING locks are the same thing as an EXCLUSIVE lock. SQLite
|
|
** still works when you do this, but concurrency is reduced since
|
|
** only a single process can be reading the database at a time.
|
|
**
|
|
** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off
|
|
*/
|
|
#if SQLITE_ENABLE_LOCKING_STYLE
|
|
|
|
/*
|
|
** Retry flock() calls that fail with EINTR
|
|
*/
|
|
#ifdef EINTR
|
|
static int robust_flock(int fd, int op){
|
|
int rc;
|
|
do{ rc = flock(fd,op); }while( rc<0 && errno==EINTR );
|
|
return rc;
|
|
}
|
|
#else
|
|
# define robust_flock(a,b) flock(a,b)
|
|
#endif
|
|
|
|
|
|
/*
|
|
** 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, set *pResOut
|
|
** to a non-zero value otherwise *pResOut is set to zero. The return value
|
|
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
|
|
*/
|
|
static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
|
|
int rc = SQLITE_OK;
|
|
int reserved = 0;
|
|
unixFile *pFile = (unixFile*)id;
|
|
|
|
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
|
|
|
|
assert( pFile );
|
|
|
|
/* Check if a thread in this process holds such a lock */
|
|
if( pFile->eFileLock>SHARED_LOCK ){
|
|
reserved = 1;
|
|
}
|
|
|
|
/* Otherwise see if some other process holds it. */
|
|
if( !reserved ){
|
|
/* attempt to get the lock */
|
|
int lrc = robust_flock(pFile->h, LOCK_EX | LOCK_NB);
|
|
if( !lrc ){
|
|
/* got the lock, unlock it */
|
|
lrc = robust_flock(pFile->h, LOCK_UN);
|
|
if ( lrc ) {
|
|
int tErrno = errno;
|
|
/* unlock failed with an error */
|
|
lrc = SQLITE_IOERR_UNLOCK;
|
|
storeLastErrno(pFile, tErrno);
|
|
rc = lrc;
|
|
}
|
|
} else {
|
|
int tErrno = errno;
|
|
reserved = 1;
|
|
/* someone else might have it reserved */
|
|
lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
|
|
if( IS_LOCK_ERROR(lrc) ){
|
|
storeLastErrno(pFile, tErrno);
|
|
rc = lrc;
|
|
}
|
|
}
|
|
}
|
|
OSTRACE(("TEST WR-LOCK %d %d %d (flock)\n", pFile->h, rc, reserved));
|
|
|
|
#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
|
|
if( (rc & 0xff) == SQLITE_IOERR ){
|
|
rc = SQLITE_OK;
|
|
reserved=1;
|
|
}
|
|
#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
|
|
*pResOut = reserved;
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Lock the file with the lock specified by parameter eFileLock - 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
|
|
**
|
|
** flock() only really support EXCLUSIVE locks. We track intermediate
|
|
** lock states in the sqlite3_file structure, but all locks SHARED or
|
|
** above are really EXCLUSIVE locks and exclude all other processes from
|
|
** access the file.
|
|
**
|
|
** This routine will only increase a lock. Use the sqlite3OsUnlock()
|
|
** routine to lower a locking level.
|
|
*/
|
|
static int flockLock(sqlite3_file *id, int eFileLock) {
|
|
int rc = SQLITE_OK;
|
|
unixFile *pFile = (unixFile*)id;
|
|
|
|
assert( pFile );
|
|
|
|
/* if we already have a lock, it is exclusive.
|
|
** Just adjust level and punt on outta here. */
|
|
if (pFile->eFileLock > NO_LOCK) {
|
|
pFile->eFileLock = eFileLock;
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/* grab an exclusive lock */
|
|
|
|
if (robust_flock(pFile->h, LOCK_EX | LOCK_NB)) {
|
|
int tErrno = errno;
|
|
/* didn't get, must be busy */
|
|
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
|
|
if( IS_LOCK_ERROR(rc) ){
|
|
storeLastErrno(pFile, tErrno);
|
|
}
|
|
} else {
|
|
/* got it, set the type and return ok */
|
|
pFile->eFileLock = eFileLock;
|
|
}
|
|
OSTRACE(("LOCK %d %s %s (flock)\n", pFile->h, azFileLock(eFileLock),
|
|
rc==SQLITE_OK ? "ok" : "failed"));
|
|
#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
|
|
if( (rc & 0xff) == SQLITE_IOERR ){
|
|
rc = SQLITE_BUSY;
|
|
}
|
|
#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
|
|
return rc;
|
|
}
|
|
|
|
|
|
/*
|
|
** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
|
|
** 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 flockUnlock(sqlite3_file *id, int eFileLock) {
|
|
unixFile *pFile = (unixFile*)id;
|
|
|
|
assert( pFile );
|
|
OSTRACE(("UNLOCK %d %d was %d pid=%d (flock)\n", pFile->h, eFileLock,
|
|
pFile->eFileLock, osGetpid(0)));
|
|
assert( eFileLock<=SHARED_LOCK );
|
|
|
|
/* no-op if possible */
|
|
if( pFile->eFileLock==eFileLock ){
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/* shared can just be set because we always have an exclusive */
|
|
if (eFileLock==SHARED_LOCK) {
|
|
pFile->eFileLock = eFileLock;
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/* no, really, unlock. */
|
|
if( robust_flock(pFile->h, LOCK_UN) ){
|
|
#ifdef SQLITE_IGNORE_FLOCK_LOCK_ERRORS
|
|
return SQLITE_OK;
|
|
#endif /* SQLITE_IGNORE_FLOCK_LOCK_ERRORS */
|
|
return SQLITE_IOERR_UNLOCK;
|
|
}else{
|
|
pFile->eFileLock = NO_LOCK;
|
|
return SQLITE_OK;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Close a file.
|
|
*/
|
|
static int flockClose(sqlite3_file *id) {
|
|
assert( id!=0 );
|
|
flockUnlock(id, NO_LOCK);
|
|
return closeUnixFile(id);
|
|
}
|
|
|
|
#endif /* SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORK */
|
|
|
|
/******************* End of the flock lock implementation *********************
|
|
******************************************************************************/
|
|
|
|
/******************************************************************************
|
|
************************ Begin Named Semaphore Locking ************************
|
|
**
|
|
** Named semaphore locking is only supported on VxWorks.
|
|
**
|
|
** Semaphore locking is like dot-lock and flock in that it really only
|
|
** supports EXCLUSIVE locking. Only a single process can read or write
|
|
** the database file at a time. This reduces potential concurrency, but
|
|
** makes the lock implementation much easier.
|
|
*/
|
|
#if OS_VXWORKS
|
|
|
|
/*
|
|
** 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, set *pResOut
|
|
** to a non-zero value otherwise *pResOut is set to zero. The return value
|
|
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
|
|
*/
|
|
static int semXCheckReservedLock(sqlite3_file *id, int *pResOut) {
|
|
int rc = SQLITE_OK;
|
|
int reserved = 0;
|
|
unixFile *pFile = (unixFile*)id;
|
|
|
|
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
|
|
|
|
assert( pFile );
|
|
|
|
/* Check if a thread in this process holds such a lock */
|
|
if( pFile->eFileLock>SHARED_LOCK ){
|
|
reserved = 1;
|
|
}
|
|
|
|
/* Otherwise see if some other process holds it. */
|
|
if( !reserved ){
|
|
sem_t *pSem = pFile->pInode->pSem;
|
|
|
|
if( sem_trywait(pSem)==-1 ){
|
|
int tErrno = errno;
|
|
if( EAGAIN != tErrno ){
|
|
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
|
|
storeLastErrno(pFile, tErrno);
|
|
} else {
|
|
/* someone else has the lock when we are in NO_LOCK */
|
|
reserved = (pFile->eFileLock < SHARED_LOCK);
|
|
}
|
|
}else{
|
|
/* we could have it if we want it */
|
|
sem_post(pSem);
|
|
}
|
|
}
|
|
OSTRACE(("TEST WR-LOCK %d %d %d (sem)\n", pFile->h, rc, reserved));
|
|
|
|
*pResOut = reserved;
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Lock the file with the lock specified by parameter eFileLock - 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
|
|
**
|
|
** Semaphore locks only really support EXCLUSIVE locks. We track intermediate
|
|
** lock states in the sqlite3_file structure, but all locks SHARED or
|
|
** above are really EXCLUSIVE locks and exclude all other processes from
|
|
** access the file.
|
|
**
|
|
** This routine will only increase a lock. Use the sqlite3OsUnlock()
|
|
** routine to lower a locking level.
|
|
*/
|
|
static int semXLock(sqlite3_file *id, int eFileLock) {
|
|
unixFile *pFile = (unixFile*)id;
|
|
sem_t *pSem = pFile->pInode->pSem;
|
|
int rc = SQLITE_OK;
|
|
|
|
/* if we already have a lock, it is exclusive.
|
|
** Just adjust level and punt on outta here. */
|
|
if (pFile->eFileLock > NO_LOCK) {
|
|
pFile->eFileLock = eFileLock;
|
|
rc = SQLITE_OK;
|
|
goto sem_end_lock;
|
|
}
|
|
|
|
/* lock semaphore now but bail out when already locked. */
|
|
if( sem_trywait(pSem)==-1 ){
|
|
rc = SQLITE_BUSY;
|
|
goto sem_end_lock;
|
|
}
|
|
|
|
/* got it, set the type and return ok */
|
|
pFile->eFileLock = eFileLock;
|
|
|
|
sem_end_lock:
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
|
|
** 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 semXUnlock(sqlite3_file *id, int eFileLock) {
|
|
unixFile *pFile = (unixFile*)id;
|
|
sem_t *pSem = pFile->pInode->pSem;
|
|
|
|
assert( pFile );
|
|
assert( pSem );
|
|
OSTRACE(("UNLOCK %d %d was %d pid=%d (sem)\n", pFile->h, eFileLock,
|
|
pFile->eFileLock, osGetpid(0)));
|
|
assert( eFileLock<=SHARED_LOCK );
|
|
|
|
/* no-op if possible */
|
|
if( pFile->eFileLock==eFileLock ){
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/* shared can just be set because we always have an exclusive */
|
|
if (eFileLock==SHARED_LOCK) {
|
|
pFile->eFileLock = eFileLock;
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/* no, really unlock. */
|
|
if ( sem_post(pSem)==-1 ) {
|
|
int rc, tErrno = errno;
|
|
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
|
|
if( IS_LOCK_ERROR(rc) ){
|
|
storeLastErrno(pFile, tErrno);
|
|
}
|
|
return rc;
|
|
}
|
|
pFile->eFileLock = NO_LOCK;
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Close a file.
|
|
*/
|
|
static int semXClose(sqlite3_file *id) {
|
|
if( id ){
|
|
unixFile *pFile = (unixFile*)id;
|
|
semXUnlock(id, NO_LOCK);
|
|
assert( pFile );
|
|
assert( unixFileMutexNotheld(pFile) );
|
|
unixEnterMutex();
|
|
releaseInodeInfo(pFile);
|
|
unixLeaveMutex();
|
|
closeUnixFile(id);
|
|
}
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
#endif /* OS_VXWORKS */
|
|
/*
|
|
** Named semaphore locking is only available on VxWorks.
|
|
**
|
|
*************** End of the named semaphore lock implementation ****************
|
|
******************************************************************************/
|
|
|
|
|
|
/******************************************************************************
|
|
*************************** Begin AFP Locking *********************************
|
|
**
|
|
** AFP is the Apple Filing Protocol. AFP is a network filesystem found
|
|
** on Apple Macintosh computers - both OS9 and OSX.
|
|
**
|
|
** Third-party implementations of AFP are available. But this code here
|
|
** only works on OSX.
|
|
*/
|
|
|
|
#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
|
|
/*
|
|
** The afpLockingContext structure contains all afp lock specific state
|
|
*/
|
|
typedef struct afpLockingContext afpLockingContext;
|
|
struct afpLockingContext {
|
|
int reserved;
|
|
const char *dbPath; /* Name of the open file */
|
|
};
|
|
|
|
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)
|
|
|
|
/*
|
|
** This is a utility for setting or clearing a bit-range lock on an
|
|
** AFP filesystem.
|
|
**
|
|
** Return SQLITE_OK on success, SQLITE_BUSY on failure.
|
|
*/
|
|
static int afpSetLock(
|
|
const char *path, /* Name of the file to be locked or unlocked */
|
|
unixFile *pFile, /* Open file descriptor on path */
|
|
unsigned long long offset, /* First byte to be locked */
|
|
unsigned long long length, /* Number of bytes to lock */
|
|
int setLockFlag /* True to set lock. False to clear lock */
|
|
){
|
|
struct ByteRangeLockPB2 pb;
|
|
int err;
|
|
|
|
pb.unLockFlag = setLockFlag ? 0 : 1;
|
|
pb.startEndFlag = 0;
|
|
pb.offset = offset;
|
|
pb.length = length;
|
|
pb.fd = pFile->h;
|
|
|
|
OSTRACE(("AFPSETLOCK [%s] for %d%s in range %llx:%llx\n",
|
|
(setLockFlag?"ON":"OFF"), pFile->h, (pb.fd==-1?"[testval-1]":""),
|
|
offset, length));
|
|
err = fsctl(path, afpfsByteRangeLock2FSCTL, &pb, 0);
|
|
if ( err==-1 ) {
|
|
int rc;
|
|
int tErrno = errno;
|
|
OSTRACE(("AFPSETLOCK failed to fsctl() '%s' %d %s\n",
|
|
path, tErrno, strerror(tErrno)));
|
|
#ifdef SQLITE_IGNORE_AFP_LOCK_ERRORS
|
|
rc = SQLITE_BUSY;
|
|
#else
|
|
rc = sqliteErrorFromPosixError(tErrno,
|
|
setLockFlag ? SQLITE_IOERR_LOCK : SQLITE_IOERR_UNLOCK);
|
|
#endif /* SQLITE_IGNORE_AFP_LOCK_ERRORS */
|
|
if( IS_LOCK_ERROR(rc) ){
|
|
storeLastErrno(pFile, tErrno);
|
|
}
|
|
return rc;
|
|
} else {
|
|
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, set *pResOut
|
|
** to a non-zero value otherwise *pResOut is set to zero. The return value
|
|
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
|
|
*/
|
|
static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
|
|
int rc = SQLITE_OK;
|
|
int reserved = 0;
|
|
unixFile *pFile = (unixFile*)id;
|
|
afpLockingContext *context;
|
|
|
|
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
|
|
|
|
assert( pFile );
|
|
context = (afpLockingContext *) pFile->lockingContext;
|
|
if( context->reserved ){
|
|
*pResOut = 1;
|
|
return SQLITE_OK;
|
|
}
|
|
sqlite3_mutex_enter(pFile->pInode->pLockMutex);
|
|
/* Check if a thread in this process holds such a lock */
|
|
if( pFile->pInode->eFileLock>SHARED_LOCK ){
|
|
reserved = 1;
|
|
}
|
|
|
|
/* Otherwise see if some other process holds it.
|
|
*/
|
|
if( !reserved ){
|
|
/* lock the RESERVED byte */
|
|
int lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1);
|
|
if( SQLITE_OK==lrc ){
|
|
/* if we succeeded in taking the reserved lock, unlock it to restore
|
|
** the original state */
|
|
lrc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0);
|
|
} else {
|
|
/* if we failed to get the lock then someone else must have it */
|
|
reserved = 1;
|
|
}
|
|
if( IS_LOCK_ERROR(lrc) ){
|
|
rc=lrc;
|
|
}
|
|
}
|
|
|
|
sqlite3_mutex_leave(pFile->pInode->pLockMutex);
|
|
OSTRACE(("TEST WR-LOCK %d %d %d (afp)\n", pFile->h, rc, reserved));
|
|
|
|
*pResOut = reserved;
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Lock the file with the lock specified by parameter eFileLock - 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 afpLock(sqlite3_file *id, int eFileLock){
|
|
int rc = SQLITE_OK;
|
|
unixFile *pFile = (unixFile*)id;
|
|
unixInodeInfo *pInode = pFile->pInode;
|
|
afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
|
|
|
|
assert( pFile );
|
|
OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (afp)\n", pFile->h,
|
|
azFileLock(eFileLock), azFileLock(pFile->eFileLock),
|
|
azFileLock(pInode->eFileLock), pInode->nShared , osGetpid(0)));
|
|
|
|
/* If there is already a lock of this type or more restrictive on the
|
|
** unixFile, do nothing. Don't use the afp_end_lock: exit path, as
|
|
** unixEnterMutex() hasn't been called yet.
|
|
*/
|
|
if( pFile->eFileLock>=eFileLock ){
|
|
OSTRACE(("LOCK %d %s ok (already held) (afp)\n", pFile->h,
|
|
azFileLock(eFileLock)));
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/* Make sure the locking sequence is correct
|
|
** (1) We never move from unlocked to anything higher than shared lock.
|
|
** (2) SQLite never explicitly requests a pending lock.
|
|
** (3) A shared lock is always held when a reserve lock is requested.
|
|
*/
|
|
assert( pFile->eFileLock!=NO_LOCK || eFileLock==SHARED_LOCK );
|
|
assert( eFileLock!=PENDING_LOCK );
|
|
assert( eFileLock!=RESERVED_LOCK || pFile->eFileLock==SHARED_LOCK );
|
|
|
|
/* This mutex is needed because pFile->pInode is shared across threads
|
|
*/
|
|
pInode = pFile->pInode;
|
|
sqlite3_mutex_enter(pInode->pLockMutex);
|
|
|
|
/* If some thread using this PID has a lock via a different unixFile*
|
|
** handle that precludes the requested lock, return BUSY.
|
|
*/
|
|
if( (pFile->eFileLock!=pInode->eFileLock &&
|
|
(pInode->eFileLock>=PENDING_LOCK || eFileLock>SHARED_LOCK))
|
|
){
|
|
rc = SQLITE_BUSY;
|
|
goto afp_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( eFileLock==SHARED_LOCK &&
|
|
(pInode->eFileLock==SHARED_LOCK || pInode->eFileLock==RESERVED_LOCK) ){
|
|
assert( eFileLock==SHARED_LOCK );
|
|
assert( pFile->eFileLock==0 );
|
|
assert( pInode->nShared>0 );
|
|
pFile->eFileLock = SHARED_LOCK;
|
|
pInode->nShared++;
|
|
pInode->nLock++;
|
|
goto afp_end_lock;
|
|
}
|
|
|
|
/* 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( eFileLock==SHARED_LOCK
|
|
|| (eFileLock==EXCLUSIVE_LOCK && pFile->eFileLock<PENDING_LOCK)
|
|
){
|
|
int failed;
|
|
failed = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 1);
|
|
if (failed) {
|
|
rc = failed;
|
|
goto afp_end_lock;
|
|
}
|
|
}
|
|
|
|
/* If control gets to this point, then actually go ahead and make
|
|
** operating system calls for the specified lock.
|
|
*/
|
|
if( eFileLock==SHARED_LOCK ){
|
|
int lrc1, lrc2, lrc1Errno = 0;
|
|
long lk, mask;
|
|
|
|
assert( pInode->nShared==0 );
|
|
assert( pInode->eFileLock==0 );
|
|
|
|
mask = (sizeof(long)==8) ? LARGEST_INT64 : 0x7fffffff;
|
|
/* Now get the read-lock SHARED_LOCK */
|
|
/* note that the quality of the randomness doesn't matter that much */
|
|
lk = random();
|
|
pInode->sharedByte = (lk & mask)%(SHARED_SIZE - 1);
|
|
lrc1 = afpSetLock(context->dbPath, pFile,
|
|
SHARED_FIRST+pInode->sharedByte, 1, 1);
|
|
if( IS_LOCK_ERROR(lrc1) ){
|
|
lrc1Errno = pFile->lastErrno;
|
|
}
|
|
/* Drop the temporary PENDING lock */
|
|
lrc2 = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0);
|
|
|
|
if( IS_LOCK_ERROR(lrc1) ) {
|
|
storeLastErrno(pFile, lrc1Errno);
|
|
rc = lrc1;
|
|
goto afp_end_lock;
|
|
} else if( IS_LOCK_ERROR(lrc2) ){
|
|
rc = lrc2;
|
|
goto afp_end_lock;
|
|
} else if( lrc1 != SQLITE_OK ) {
|
|
rc = lrc1;
|
|
} else {
|
|
pFile->eFileLock = SHARED_LOCK;
|
|
pInode->nLock++;
|
|
pInode->nShared = 1;
|
|
}
|
|
}else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>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.
|
|
*/
|
|
int failed = 0;
|
|
assert( 0!=pFile->eFileLock );
|
|
if (eFileLock >= RESERVED_LOCK && pFile->eFileLock < RESERVED_LOCK) {
|
|
/* Acquire a RESERVED lock */
|
|
failed = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1,1);
|
|
if( !failed ){
|
|
context->reserved = 1;
|
|
}
|
|
}
|
|
if (!failed && eFileLock == 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 afpUnlock
|
|
*/
|
|
if( !(failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST +
|
|
pInode->sharedByte, 1, 0)) ){
|
|
int failed2 = SQLITE_OK;
|
|
/* now attempt to get the exclusive lock range */
|
|
failed = afpSetLock(context->dbPath, pFile, SHARED_FIRST,
|
|
SHARED_SIZE, 1);
|
|
if( failed && (failed2 = afpSetLock(context->dbPath, pFile,
|
|
SHARED_FIRST + pInode->sharedByte, 1, 1)) ){
|
|
/* Can't reestablish the shared lock. Sqlite can't deal, this is
|
|
** a critical I/O error
|
|
*/
|
|
rc = ((failed & 0xff) == SQLITE_IOERR) ? failed2 :
|
|
SQLITE_IOERR_LOCK;
|
|
goto afp_end_lock;
|
|
}
|
|
}else{
|
|
rc = failed;
|
|
}
|
|
}
|
|
if( failed ){
|
|
rc = failed;
|
|
}
|
|
}
|
|
|
|
if( rc==SQLITE_OK ){
|
|
pFile->eFileLock = eFileLock;
|
|
pInode->eFileLock = eFileLock;
|
|
}else if( eFileLock==EXCLUSIVE_LOCK ){
|
|
pFile->eFileLock = PENDING_LOCK;
|
|
pInode->eFileLock = PENDING_LOCK;
|
|
}
|
|
|
|
afp_end_lock:
|
|
sqlite3_mutex_leave(pInode->pLockMutex);
|
|
OSTRACE(("LOCK %d %s %s (afp)\n", pFile->h, azFileLock(eFileLock),
|
|
rc==SQLITE_OK ? "ok" : "failed"));
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
|
|
** 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 afpUnlock(sqlite3_file *id, int eFileLock) {
|
|
int rc = SQLITE_OK;
|
|
unixFile *pFile = (unixFile*)id;
|
|
unixInodeInfo *pInode;
|
|
afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
|
|
int skipShared = 0;
|
|
|
|
assert( pFile );
|
|
OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, eFileLock,
|
|
pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared,
|
|
osGetpid(0)));
|
|
|
|
assert( eFileLock<=SHARED_LOCK );
|
|
if( pFile->eFileLock<=eFileLock ){
|
|
return SQLITE_OK;
|
|
}
|
|
pInode = pFile->pInode;
|
|
sqlite3_mutex_enter(pInode->pLockMutex);
|
|
assert( pInode->nShared!=0 );
|
|
if( pFile->eFileLock>SHARED_LOCK ){
|
|
assert( pInode->eFileLock==pFile->eFileLock );
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
/* When reducing a lock such that other processes can start
|
|
** reading the database file again, make sure that the
|
|
** transaction counter was updated if any part of the database
|
|
** file changed. If the transaction counter is not updated,
|
|
** other connections to the same file might not realize that
|
|
** the file has changed and hence might not know to flush their
|
|
** cache. The use of a stale cache can lead to database corruption.
|
|
*/
|
|
assert( pFile->inNormalWrite==0
|
|
|| pFile->dbUpdate==0
|
|
|| pFile->transCntrChng==1 );
|
|
pFile->inNormalWrite = 0;
|
|
#endif
|
|
|
|
if( pFile->eFileLock==EXCLUSIVE_LOCK ){
|
|
rc = afpSetLock(context->dbPath, pFile, SHARED_FIRST, SHARED_SIZE, 0);
|
|
if( rc==SQLITE_OK && (eFileLock==SHARED_LOCK || pInode->nShared>1) ){
|
|
/* only re-establish the shared lock if necessary */
|
|
int sharedLockByte = SHARED_FIRST+pInode->sharedByte;
|
|
rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 1);
|
|
} else {
|
|
skipShared = 1;
|
|
}
|
|
}
|
|
if( rc==SQLITE_OK && pFile->eFileLock>=PENDING_LOCK ){
|
|
rc = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0);
|
|
}
|
|
if( rc==SQLITE_OK && pFile->eFileLock>=RESERVED_LOCK && context->reserved ){
|
|
rc = afpSetLock(context->dbPath, pFile, RESERVED_BYTE, 1, 0);
|
|
if( !rc ){
|
|
context->reserved = 0;
|
|
}
|
|
}
|
|
if( rc==SQLITE_OK && (eFileLock==SHARED_LOCK || pInode->nShared>1)){
|
|
pInode->eFileLock = SHARED_LOCK;
|
|
}
|
|
}
|
|
if( rc==SQLITE_OK && eFileLock==NO_LOCK ){
|
|
|
|
/* Decrement the shared lock counter. Release the lock using an
|
|
** OS call only when all threads in this same process have released
|
|
** the lock.
|
|
*/
|
|
unsigned long long sharedLockByte = SHARED_FIRST+pInode->sharedByte;
|
|
pInode->nShared--;
|
|
if( pInode->nShared==0 ){
|
|
if( !skipShared ){
|
|
rc = afpSetLock(context->dbPath, pFile, sharedLockByte, 1, 0);
|
|
}
|
|
if( !rc ){
|
|
pInode->eFileLock = NO_LOCK;
|
|
pFile->eFileLock = NO_LOCK;
|
|
}
|
|
}
|
|
if( rc==SQLITE_OK ){
|
|
pInode->nLock--;
|
|
assert( pInode->nLock>=0 );
|
|
if( pInode->nLock==0 ) closePendingFds(pFile);
|
|
}
|
|
}
|
|
|
|
sqlite3_mutex_leave(pInode->pLockMutex);
|
|
if( rc==SQLITE_OK ){
|
|
pFile->eFileLock = eFileLock;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Close a file & cleanup AFP specific locking context
|
|
*/
|
|
static int afpClose(sqlite3_file *id) {
|
|
int rc = SQLITE_OK;
|
|
unixFile *pFile = (unixFile*)id;
|
|
assert( id!=0 );
|
|
afpUnlock(id, NO_LOCK);
|
|
assert( unixFileMutexNotheld(pFile) );
|
|
unixEnterMutex();
|
|
if( pFile->pInode ){
|
|
unixInodeInfo *pInode = pFile->pInode;
|
|
sqlite3_mutex_enter(pInode->pLockMutex);
|
|
if( pInode->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 pInode->aPending. It will be automatically closed when
|
|
** the last lock is cleared.
|
|
*/
|
|
setPendingFd(pFile);
|
|
}
|
|
sqlite3_mutex_leave(pInode->pLockMutex);
|
|
}
|
|
releaseInodeInfo(pFile);
|
|
sqlite3_free(pFile->lockingContext);
|
|
rc = closeUnixFile(id);
|
|
unixLeaveMutex();
|
|
return rc;
|
|
}
|
|
|
|
#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
|
|
/*
|
|
** The code above is the AFP lock implementation. The code is specific
|
|
** to MacOSX and does not work on other unix platforms. No alternative
|
|
** is available. If you don't compile for a mac, then the "unix-afp"
|
|
** VFS is not available.
|
|
**
|
|
********************* End of the AFP lock implementation **********************
|
|
******************************************************************************/
|
|
|
|
/******************************************************************************
|
|
*************************** Begin NFS Locking ********************************/
|
|
|
|
#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
|
|
/*
|
|
** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
|
|
** 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 nfsUnlock(sqlite3_file *id, int eFileLock){
|
|
return posixUnlock(id, eFileLock, 1);
|
|
}
|
|
|
|
#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
|
|
/*
|
|
** The code above is the NFS lock implementation. The code is specific
|
|
** to MacOSX and does not work on other unix platforms. No alternative
|
|
** is available.
|
|
**
|
|
********************* End of the NFS lock implementation **********************
|
|
******************************************************************************/
|
|
|
|
/******************************************************************************
|
|
**************** Non-locking sqlite3_file methods *****************************
|
|
**
|
|
** The next division contains implementations for all methods of the
|
|
** sqlite3_file object other than the locking methods. The locking
|
|
** methods were defined in divisions above (one locking method per
|
|
** division). Those methods that are common to all locking modes
|
|
** are gather together into this division.
|
|
*/
|
|
|
|
/*
|
|
** Seek to the offset passed as the second argument, then read cnt
|
|
** bytes into pBuf. Return the number of bytes actually read.
|
|
**
|
|
** To avoid stomping the errno value on a failed read the lastErrno value
|
|
** is set before returning.
|
|
*/
|
|
static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
|
|
int got;
|
|
int prior = 0;
|
|
#if (!defined(USE_PREAD) && !defined(USE_PREAD64))
|
|
i64 newOffset;
|
|
#endif
|
|
TIMER_START;
|
|
assert( cnt==(cnt&0x1ffff) );
|
|
assert( id->h>2 );
|
|
do{
|
|
#if defined(USE_PREAD)
|
|
got = osPread(id->h, pBuf, cnt, offset);
|
|
SimulateIOError( got = -1 );
|
|
#elif defined(USE_PREAD64)
|
|
got = osPread64(id->h, pBuf, cnt, offset);
|
|
SimulateIOError( got = -1 );
|
|
#else
|
|
newOffset = lseek(id->h, offset, SEEK_SET);
|
|
SimulateIOError( newOffset = -1 );
|
|
if( newOffset<0 ){
|
|
storeLastErrno((unixFile*)id, errno);
|
|
return -1;
|
|
}
|
|
got = osRead(id->h, pBuf, cnt);
|
|
#endif
|
|
if( got==cnt ) break;
|
|
if( got<0 ){
|
|
if( errno==EINTR ){ got = 1; continue; }
|
|
prior = 0;
|
|
storeLastErrno((unixFile*)id, errno);
|
|
break;
|
|
}else if( got>0 ){
|
|
cnt -= got;
|
|
offset += got;
|
|
prior += got;
|
|
pBuf = (void*)(got + (char*)pBuf);
|
|
}
|
|
}while( got>0 );
|
|
TIMER_END;
|
|
OSTRACE(("READ %-3d %5d %7lld %llu\n",
|
|
id->h, got+prior, offset-prior, TIMER_ELAPSED));
|
|
return got+prior;
|
|
}
|
|
|
|
/*
|
|
** 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(
|
|
sqlite3_file *id,
|
|
void *pBuf,
|
|
int amt,
|
|
sqlite3_int64 offset
|
|
){
|
|
unixFile *pFile = (unixFile *)id;
|
|
int got;
|
|
assert( id );
|
|
assert( offset>=0 );
|
|
assert( amt>0 );
|
|
|
|
/* If this is a database file (not a journal, super-journal or temp
|
|
** file), the bytes in the locking range should never be read or written. */
|
|
#if 0
|
|
assert( pFile->pPreallocatedUnused==0
|
|
|| offset>=PENDING_BYTE+512
|
|
|| offset+amt<=PENDING_BYTE
|
|
);
|
|
#endif
|
|
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
/* Deal with as much of this read request as possible by transferring
|
|
** data from the memory mapping using memcpy(). */
|
|
if( offset<pFile->mmapSize ){
|
|
if( offset+amt <= pFile->mmapSize ){
|
|
memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt);
|
|
return SQLITE_OK;
|
|
}else{
|
|
int nCopy = pFile->mmapSize - offset;
|
|
memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], nCopy);
|
|
pBuf = &((u8 *)pBuf)[nCopy];
|
|
amt -= nCopy;
|
|
offset += nCopy;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
got = seekAndRead(pFile, offset, pBuf, amt);
|
|
if( got==amt ){
|
|
return SQLITE_OK;
|
|
}else if( got<0 ){
|
|
/* pFile->lastErrno has been set by seekAndRead().
|
|
** Usually we return SQLITE_IOERR_READ here, though for some
|
|
** kinds of errors we return SQLITE_IOERR_CORRUPTFS. The
|
|
** SQLITE_IOERR_CORRUPTFS will be converted into SQLITE_CORRUPT
|
|
** prior to returning to the application by the sqlite3ApiExit()
|
|
** routine.
|
|
*/
|
|
switch( pFile->lastErrno ){
|
|
case ERANGE:
|
|
case EIO:
|
|
#ifdef ENXIO
|
|
case ENXIO:
|
|
#endif
|
|
#ifdef EDEVERR
|
|
case EDEVERR:
|
|
#endif
|
|
return SQLITE_IOERR_CORRUPTFS;
|
|
}
|
|
return SQLITE_IOERR_READ;
|
|
}else{
|
|
storeLastErrno(pFile, 0); /* not a system error */
|
|
/* Unread parts of the buffer must be zero-filled */
|
|
memset(&((char*)pBuf)[got], 0, amt-got);
|
|
return SQLITE_IOERR_SHORT_READ;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Attempt to seek the file-descriptor passed as the first argument to
|
|
** absolute offset iOff, then attempt to write nBuf bytes of data from
|
|
** pBuf to it. If an error occurs, return -1 and set *piErrno. Otherwise,
|
|
** return the actual number of bytes written (which may be less than
|
|
** nBuf).
|
|
*/
|
|
static int seekAndWriteFd(
|
|
int fd, /* File descriptor to write to */
|
|
i64 iOff, /* File offset to begin writing at */
|
|
const void *pBuf, /* Copy data from this buffer to the file */
|
|
int nBuf, /* Size of buffer pBuf in bytes */
|
|
int *piErrno /* OUT: Error number if error occurs */
|
|
){
|
|
int rc = 0; /* Value returned by system call */
|
|
|
|
assert( nBuf==(nBuf&0x1ffff) );
|
|
assert( fd>2 );
|
|
assert( piErrno!=0 );
|
|
nBuf &= 0x1ffff;
|
|
TIMER_START;
|
|
|
|
#if defined(USE_PREAD)
|
|
do{ rc = (int)osPwrite(fd, pBuf, nBuf, iOff); }while( rc<0 && errno==EINTR );
|
|
#elif defined(USE_PREAD64)
|
|
do{ rc = (int)osPwrite64(fd, pBuf, nBuf, iOff);}while( rc<0 && errno==EINTR);
|
|
#else
|
|
do{
|
|
i64 iSeek = lseek(fd, iOff, SEEK_SET);
|
|
SimulateIOError( iSeek = -1 );
|
|
if( iSeek<0 ){
|
|
rc = -1;
|
|
break;
|
|
}
|
|
rc = osWrite(fd, pBuf, nBuf);
|
|
}while( rc<0 && errno==EINTR );
|
|
#endif
|
|
|
|
TIMER_END;
|
|
OSTRACE(("WRITE %-3d %5d %7lld %llu\n", fd, rc, iOff, TIMER_ELAPSED));
|
|
|
|
if( rc<0 ) *piErrno = errno;
|
|
return rc;
|
|
}
|
|
|
|
|
|
/*
|
|
** Seek to the offset in id->offset then read cnt bytes into pBuf.
|
|
** Return the number of bytes actually read. Update the offset.
|
|
**
|
|
** To avoid stomping the errno value on a failed write the lastErrno value
|
|
** is set before returning.
|
|
*/
|
|
static int seekAndWrite(unixFile *id, i64 offset, const void *pBuf, int cnt){
|
|
return seekAndWriteFd(id->h, offset, pBuf, cnt, &id->lastErrno);
|
|
}
|
|
|
|
|
|
/*
|
|
** Write data from a buffer into a file. Return SQLITE_OK on success
|
|
** or some other error code on failure.
|
|
*/
|
|
static int unixWrite(
|
|
sqlite3_file *id,
|
|
const void *pBuf,
|
|
int amt,
|
|
sqlite3_int64 offset
|
|
){
|
|
unixFile *pFile = (unixFile*)id;
|
|
int wrote = 0;
|
|
assert( id );
|
|
assert( amt>0 );
|
|
|
|
/* If this is a database file (not a journal, super-journal or temp
|
|
** file), the bytes in the locking range should never be read or written. */
|
|
#if 0
|
|
assert( pFile->pPreallocatedUnused==0
|
|
|| offset>=PENDING_BYTE+512
|
|
|| offset+amt<=PENDING_BYTE
|
|
);
|
|
#endif
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
/* If we are doing a normal write to a database file (as opposed to
|
|
** doing a hot-journal rollback or a write to some file other than a
|
|
** normal database file) then record the fact that the database
|
|
** has changed. If the transaction counter is modified, record that
|
|
** fact too.
|
|
*/
|
|
if( pFile->inNormalWrite ){
|
|
pFile->dbUpdate = 1; /* The database has been modified */
|
|
if( offset<=24 && offset+amt>=27 ){
|
|
int rc;
|
|
char oldCntr[4];
|
|
SimulateIOErrorBenign(1);
|
|
rc = seekAndRead(pFile, 24, oldCntr, 4);
|
|
SimulateIOErrorBenign(0);
|
|
if( rc!=4 || memcmp(oldCntr, &((char*)pBuf)[24-offset], 4)!=0 ){
|
|
pFile->transCntrChng = 1; /* The transaction counter has changed */
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if defined(SQLITE_MMAP_READWRITE) && SQLITE_MAX_MMAP_SIZE>0
|
|
/* Deal with as much of this write request as possible by transferring
|
|
** data from the memory mapping using memcpy(). */
|
|
if( offset<pFile->mmapSize ){
|
|
if( offset+amt <= pFile->mmapSize ){
|
|
memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt);
|
|
return SQLITE_OK;
|
|
}else{
|
|
int nCopy = pFile->mmapSize - offset;
|
|
memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, nCopy);
|
|
pBuf = &((u8 *)pBuf)[nCopy];
|
|
amt -= nCopy;
|
|
offset += nCopy;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
while( (wrote = seekAndWrite(pFile, offset, pBuf, amt))<amt && wrote>0 ){
|
|
amt -= wrote;
|
|
offset += wrote;
|
|
pBuf = &((char*)pBuf)[wrote];
|
|
}
|
|
SimulateIOError(( wrote=(-1), amt=1 ));
|
|
SimulateDiskfullError(( wrote=0, amt=1 ));
|
|
|
|
if( amt>wrote ){
|
|
if( wrote<0 && pFile->lastErrno!=ENOSPC ){
|
|
/* lastErrno set by seekAndWrite */
|
|
return SQLITE_IOERR_WRITE;
|
|
}else{
|
|
storeLastErrno(pFile, 0); /* not a system error */
|
|
return SQLITE_FULL;
|
|
}
|
|
}
|
|
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
#ifdef SQLITE_TEST
|
|
/*
|
|
** Count the number of fullsyncs and normal syncs. This is used to test
|
|
** that syncs and fullsyncs are occurring at the right times.
|
|
*/
|
|
SQLITE_API int sqlite3_sync_count = 0;
|
|
SQLITE_API int sqlite3_fullsync_count = 0;
|
|
#endif
|
|
|
|
/*
|
|
** We do not trust systems to provide a working fdatasync(). Some do.
|
|
** Others do no. To be safe, we will stick with the (slightly slower)
|
|
** fsync(). If you know that your system does support fdatasync() correctly,
|
|
** then simply compile with -Dfdatasync=fdatasync or -DHAVE_FDATASYNC
|
|
*/
|
|
#if !defined(fdatasync) && !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.
|
|
**
|
|
** SQLite sets the dataOnly flag if the size of the file is unchanged.
|
|
** The idea behind dataOnly is that it should only write the file content
|
|
** to disk, not the inode. We only set dataOnly if the file size is
|
|
** unchanged since the file size is part of the inode. However,
|
|
** Ted Ts'o tells us that fdatasync() will also write the inode if the
|
|
** file size has changed. The only real difference between fdatasync()
|
|
** and fsync(), Ted tells us, is that fdatasync() will not flush the
|
|
** inode if the mtime or owner or other inode attributes have changed.
|
|
** We only care about the file size, not the other file attributes, so
|
|
** as far as SQLite is concerned, an fdatasync() is always adequate.
|
|
** So, we always use fdatasync() if it is available, regardless of
|
|
** the value of the dataOnly flag.
|
|
*/
|
|
static int full_fsync(int fd, int fullSync, int dataOnly){
|
|
int rc;
|
|
|
|
/* The following "ifdef/elif/else/" block has the same structure as
|
|
** the one below. It is replicated here solely to avoid cluttering
|
|
** up the real code with the UNUSED_PARAMETER() macros.
|
|
*/
|
|
#ifdef SQLITE_NO_SYNC
|
|
UNUSED_PARAMETER(fd);
|
|
UNUSED_PARAMETER(fullSync);
|
|
UNUSED_PARAMETER(dataOnly);
|
|
#elif HAVE_FULLFSYNC
|
|
UNUSED_PARAMETER(dataOnly);
|
|
#else
|
|
UNUSED_PARAMETER(fullSync);
|
|
UNUSED_PARAMETER(dataOnly);
|
|
#endif
|
|
|
|
/* 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. But go ahead and call fstat() to validate the file
|
|
** descriptor as we need a method to provoke a failure during
|
|
** coverage testing.
|
|
*/
|
|
#ifdef SQLITE_NO_SYNC
|
|
{
|
|
struct stat buf;
|
|
rc = osFstat(fd, &buf);
|
|
}
|
|
#elif HAVE_FULLFSYNC
|
|
if( fullSync ){
|
|
rc = osFcntl(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);
|
|
|
|
#elif defined(__APPLE__)
|
|
/* fdatasync() on HFS+ doesn't yet flush the file size if it changed correctly
|
|
** so currently we default to the macro that redefines fdatasync to fsync
|
|
*/
|
|
rc = fsync(fd);
|
|
#else
|
|
rc = fdatasync(fd);
|
|
#if OS_VXWORKS
|
|
if( rc==-1 && errno==ENOTSUP ){
|
|
rc = fsync(fd);
|
|
}
|
|
#endif /* OS_VXWORKS */
|
|
#endif /* ifdef SQLITE_NO_SYNC elif HAVE_FULLFSYNC */
|
|
|
|
if( OS_VXWORKS && rc!= -1 ){
|
|
rc = 0;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Open a file descriptor to the directory containing file zFilename.
|
|
** If successful, *pFd is set to the opened file descriptor and
|
|
** SQLITE_OK is returned. If an error occurs, either SQLITE_NOMEM
|
|
** or SQLITE_CANTOPEN is returned and *pFd is set to an undefined
|
|
** value.
|
|
**
|
|
** The directory file descriptor is used for only one thing - to
|
|
** fsync() a directory to make sure file creation and deletion events
|
|
** are flushed to disk. Such fsyncs are not needed on newer
|
|
** journaling filesystems, but are required on older filesystems.
|
|
**
|
|
** This routine can be overridden using the xSetSysCall interface.
|
|
** The ability to override this routine was added in support of the
|
|
** chromium sandbox. Opening a directory is a security risk (we are
|
|
** told) so making it overrideable allows the chromium sandbox to
|
|
** replace this routine with a harmless no-op. To make this routine
|
|
** a no-op, replace it with a stub that returns SQLITE_OK but leaves
|
|
** *pFd set to a negative number.
|
|
**
|
|
** If SQLITE_OK is returned, the caller is responsible for closing
|
|
** the file descriptor *pFd using close().
|
|
*/
|
|
static int openDirectory(const char *zFilename, int *pFd){
|
|
int ii;
|
|
int fd = -1;
|
|
char zDirname[MAX_PATHNAME+1];
|
|
|
|
sqlite3_snprintf(MAX_PATHNAME, zDirname, "%s", zFilename);
|
|
for(ii=(int)strlen(zDirname); ii>0 && zDirname[ii]!='/'; ii--);
|
|
if( ii>0 ){
|
|
zDirname[ii] = '\0';
|
|
}else{
|
|
if( zDirname[0]!='/' ) zDirname[0] = '.';
|
|
zDirname[1] = 0;
|
|
}
|
|
fd = robust_open(zDirname, O_RDONLY|O_BINARY, 0);
|
|
if( fd>=0 ){
|
|
OSTRACE(("OPENDIR %-3d %s\n", fd, zDirname));
|
|
}
|
|
*pFd = fd;
|
|
if( fd>=0 ) return SQLITE_OK;
|
|
return unixLogError(SQLITE_CANTOPEN_BKPT, "openDirectory", zDirname);
|
|
}
|
|
|
|
/*
|
|
** 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(sqlite3_file *id, int flags){
|
|
int rc;
|
|
unixFile *pFile = (unixFile*)id;
|
|
|
|
int isDataOnly = (flags&SQLITE_SYNC_DATAONLY);
|
|
int isFullsync = (flags&0x0F)==SQLITE_SYNC_FULL;
|
|
|
|
/* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */
|
|
assert((flags&0x0F)==SQLITE_SYNC_NORMAL
|
|
|| (flags&0x0F)==SQLITE_SYNC_FULL
|
|
);
|
|
|
|
/* Unix cannot, but some systems may return SQLITE_FULL from here. This
|
|
** line is to test that doing so does not cause any problems.
|
|
*/
|
|
SimulateDiskfullError( return SQLITE_FULL );
|
|
|
|
assert( pFile );
|
|
OSTRACE(("SYNC %-3d\n", pFile->h));
|
|
rc = full_fsync(pFile->h, isFullsync, isDataOnly);
|
|
SimulateIOError( rc=1 );
|
|
if( rc ){
|
|
storeLastErrno(pFile, errno);
|
|
return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath);
|
|
}
|
|
|
|
/* Also fsync the directory containing the file if the DIRSYNC flag
|
|
** is set. This is a one-time occurrence. Many systems (examples: AIX)
|
|
** are unable to fsync a directory, so ignore errors on the fsync.
|
|
*/
|
|
if( pFile->ctrlFlags & UNIXFILE_DIRSYNC ){
|
|
int dirfd;
|
|
OSTRACE(("DIRSYNC %s (have_fullfsync=%d fullsync=%d)\n", pFile->zPath,
|
|
HAVE_FULLFSYNC, isFullsync));
|
|
rc = osOpenDirectory(pFile->zPath, &dirfd);
|
|
if( rc==SQLITE_OK ){
|
|
full_fsync(dirfd, 0, 0);
|
|
robust_close(pFile, dirfd, __LINE__);
|
|
}else{
|
|
assert( rc==SQLITE_CANTOPEN );
|
|
rc = SQLITE_OK;
|
|
}
|
|
pFile->ctrlFlags &= ~UNIXFILE_DIRSYNC;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Truncate an open file to a specified size
|
|
*/
|
|
static int unixTruncate(sqlite3_file *id, i64 nByte){
|
|
unixFile *pFile = (unixFile *)id;
|
|
int rc;
|
|
assert( pFile );
|
|
SimulateIOError( return SQLITE_IOERR_TRUNCATE );
|
|
|
|
/* If the user has configured a chunk-size for this file, truncate the
|
|
** file so that it consists of an integer number of chunks (i.e. the
|
|
** actual file size after the operation may be larger than the requested
|
|
** size).
|
|
*/
|
|
if( pFile->szChunk>0 ){
|
|
nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
|
|
}
|
|
|
|
rc = robust_ftruncate(pFile->h, nByte);
|
|
if( rc ){
|
|
storeLastErrno(pFile, errno);
|
|
return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
|
|
}else{
|
|
#ifdef SQLITE_DEBUG
|
|
/* If we are doing a normal write to a database file (as opposed to
|
|
** doing a hot-journal rollback or a write to some file other than a
|
|
** normal database file) and we truncate the file to zero length,
|
|
** that effectively updates the change counter. This might happen
|
|
** when restoring a database using the backup API from a zero-length
|
|
** source.
|
|
*/
|
|
if( pFile->inNormalWrite && nByte==0 ){
|
|
pFile->transCntrChng = 1;
|
|
}
|
|
#endif
|
|
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
/* If the file was just truncated to a size smaller than the currently
|
|
** mapped region, reduce the effective mapping size as well. SQLite will
|
|
** use read() and write() to access data beyond this point from now on.
|
|
*/
|
|
if( nByte<pFile->mmapSize ){
|
|
pFile->mmapSize = nByte;
|
|
}
|
|
#endif
|
|
|
|
return SQLITE_OK;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Determine the current size of a file in bytes
|
|
*/
|
|
static int unixFileSize(sqlite3_file *id, i64 *pSize){
|
|
int rc;
|
|
struct stat buf;
|
|
assert( id );
|
|
rc = osFstat(((unixFile*)id)->h, &buf);
|
|
SimulateIOError( rc=1 );
|
|
if( rc!=0 ){
|
|
storeLastErrno((unixFile*)id, errno);
|
|
return SQLITE_IOERR_FSTAT;
|
|
}
|
|
*pSize = buf.st_size;
|
|
|
|
/* When opening a zero-size database, the findInodeInfo() procedure
|
|
** writes a single byte into that file in order to work around a bug
|
|
** in the OS-X msdos filesystem. In order to avoid problems with upper
|
|
** layers, we need to report this file size as zero even though it is
|
|
** really 1. Ticket #3260.
|
|
*/
|
|
if( *pSize==1 ) *pSize = 0;
|
|
|
|
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
|
|
/*
|
|
** Handler for proxy-locking file-control verbs. Defined below in the
|
|
** proxying locking division.
|
|
*/
|
|
static int proxyFileControl(sqlite3_file*,int,void*);
|
|
#endif
|
|
|
|
/*
|
|
** This function is called to handle the SQLITE_FCNTL_SIZE_HINT
|
|
** file-control operation. Enlarge the database to nBytes in size
|
|
** (rounded up to the next chunk-size). If the database is already
|
|
** nBytes or larger, this routine is a no-op.
|
|
*/
|
|
static int fcntlSizeHint(unixFile *pFile, i64 nByte){
|
|
if( pFile->szChunk>0 ){
|
|
i64 nSize; /* Required file size */
|
|
struct stat buf; /* Used to hold return values of fstat() */
|
|
|
|
if( osFstat(pFile->h, &buf) ){
|
|
return SQLITE_IOERR_FSTAT;
|
|
}
|
|
|
|
nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk;
|
|
if( nSize>(i64)buf.st_size ){
|
|
|
|
#if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
|
|
/* The code below is handling the return value of osFallocate()
|
|
** correctly. posix_fallocate() is defined to "returns zero on success,
|
|
** or an error number on failure". See the manpage for details. */
|
|
int err;
|
|
do{
|
|
err = osFallocate(pFile->h, buf.st_size, nSize-buf.st_size);
|
|
}while( err==EINTR );
|
|
if( err && err!=EINVAL ) return SQLITE_IOERR_WRITE;
|
|
#else
|
|
/* If the OS does not have posix_fallocate(), fake it. Write a
|
|
** single byte to the last byte in each block that falls entirely
|
|
** within the extended region. Then, if required, a single byte
|
|
** at offset (nSize-1), to set the size of the file correctly.
|
|
** This is a similar technique to that used by glibc on systems
|
|
** that do not have a real fallocate() call.
|
|
*/
|
|
int nBlk = buf.st_blksize; /* File-system block size */
|
|
int nWrite = 0; /* Number of bytes written by seekAndWrite */
|
|
i64 iWrite; /* Next offset to write to */
|
|
|
|
iWrite = (buf.st_size/nBlk)*nBlk + nBlk - 1;
|
|
assert( iWrite>=buf.st_size );
|
|
assert( ((iWrite+1)%nBlk)==0 );
|
|
for(/*no-op*/; iWrite<nSize+nBlk-1; iWrite+=nBlk ){
|
|
if( iWrite>=nSize ) iWrite = nSize - 1;
|
|
nWrite = seekAndWrite(pFile, iWrite, "", 1);
|
|
if( nWrite!=1 ) return SQLITE_IOERR_WRITE;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
if( pFile->mmapSizeMax>0 && nByte>pFile->mmapSize ){
|
|
int rc;
|
|
if( pFile->szChunk<=0 ){
|
|
if( robust_ftruncate(pFile->h, nByte) ){
|
|
storeLastErrno(pFile, errno);
|
|
return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
|
|
}
|
|
}
|
|
|
|
rc = unixMapfile(pFile, nByte);
|
|
return rc;
|
|
}
|
|
#endif
|
|
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** If *pArg is initially negative then this is a query. Set *pArg to
|
|
** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set.
|
|
**
|
|
** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags.
|
|
*/
|
|
static void unixModeBit(unixFile *pFile, unsigned char mask, int *pArg){
|
|
if( *pArg<0 ){
|
|
*pArg = (pFile->ctrlFlags & mask)!=0;
|
|
}else if( (*pArg)==0 ){
|
|
pFile->ctrlFlags &= ~mask;
|
|
}else{
|
|
pFile->ctrlFlags |= mask;
|
|
}
|
|
}
|
|
|
|
/* Forward declaration */
|
|
static int unixGetTempname(int nBuf, char *zBuf);
|
|
#ifndef SQLITE_OMIT_WAL
|
|
static int unixFcntlExternalReader(unixFile*, int*);
|
|
#endif
|
|
|
|
/*
|
|
** Information and control of an open file handle.
|
|
*/
|
|
static int unixFileControl(sqlite3_file *id, int op, void *pArg){
|
|
unixFile *pFile = (unixFile*)id;
|
|
switch( op ){
|
|
#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
|
|
case SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: {
|
|
int rc = osIoctl(pFile->h, F2FS_IOC_START_ATOMIC_WRITE);
|
|
return rc ? SQLITE_IOERR_BEGIN_ATOMIC : SQLITE_OK;
|
|
}
|
|
case SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: {
|
|
int rc = osIoctl(pFile->h, F2FS_IOC_COMMIT_ATOMIC_WRITE);
|
|
return rc ? SQLITE_IOERR_COMMIT_ATOMIC : SQLITE_OK;
|
|
}
|
|
case SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: {
|
|
int rc = osIoctl(pFile->h, F2FS_IOC_ABORT_VOLATILE_WRITE);
|
|
return rc ? SQLITE_IOERR_ROLLBACK_ATOMIC : SQLITE_OK;
|
|
}
|
|
#endif /* __linux__ && SQLITE_ENABLE_BATCH_ATOMIC_WRITE */
|
|
|
|
case SQLITE_FCNTL_LOCKSTATE: {
|
|
*(int*)pArg = pFile->eFileLock;
|
|
return SQLITE_OK;
|
|
}
|
|
case SQLITE_FCNTL_LAST_ERRNO: {
|
|
*(int*)pArg = pFile->lastErrno;
|
|
return SQLITE_OK;
|
|
}
|
|
case SQLITE_FCNTL_CHUNK_SIZE: {
|
|
pFile->szChunk = *(int *)pArg;
|
|
return SQLITE_OK;
|
|
}
|
|
case SQLITE_FCNTL_SIZE_HINT: {
|
|
int rc;
|
|
SimulateIOErrorBenign(1);
|
|
rc = fcntlSizeHint(pFile, *(i64 *)pArg);
|
|
SimulateIOErrorBenign(0);
|
|
return rc;
|
|
}
|
|
case SQLITE_FCNTL_PERSIST_WAL: {
|
|
unixModeBit(pFile, UNIXFILE_PERSIST_WAL, (int*)pArg);
|
|
return SQLITE_OK;
|
|
}
|
|
case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
|
|
unixModeBit(pFile, UNIXFILE_PSOW, (int*)pArg);
|
|
return SQLITE_OK;
|
|
}
|
|
case SQLITE_FCNTL_VFSNAME: {
|
|
*(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName);
|
|
return SQLITE_OK;
|
|
}
|
|
case SQLITE_FCNTL_TEMPFILENAME: {
|
|
char *zTFile = sqlite3_malloc64( pFile->pVfs->mxPathname );
|
|
if( zTFile ){
|
|
unixGetTempname(pFile->pVfs->mxPathname, zTFile);
|
|
*(char**)pArg = zTFile;
|
|
}
|
|
return SQLITE_OK;
|
|
}
|
|
case SQLITE_FCNTL_HAS_MOVED: {
|
|
*(int*)pArg = fileHasMoved(pFile);
|
|
return SQLITE_OK;
|
|
}
|
|
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
case SQLITE_FCNTL_LOCK_TIMEOUT: {
|
|
int iOld = pFile->iBusyTimeout;
|
|
#if SQLITE_ENABLE_SETLK_TIMEOUT==1
|
|
pFile->iBusyTimeout = *(int*)pArg;
|
|
#elif SQLITE_ENABLE_SETLK_TIMEOUT==2
|
|
pFile->iBusyTimeout = !!(*(int*)pArg);
|
|
#else
|
|
# error "SQLITE_ENABLE_SETLK_TIMEOUT must be set to 1 or 2"
|
|
#endif
|
|
*(int*)pArg = iOld;
|
|
return SQLITE_OK;
|
|
}
|
|
#endif
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
case SQLITE_FCNTL_MMAP_SIZE: {
|
|
i64 newLimit = *(i64*)pArg;
|
|
int rc = SQLITE_OK;
|
|
if( newLimit>sqlite3GlobalConfig.mxMmap ){
|
|
newLimit = sqlite3GlobalConfig.mxMmap;
|
|
}
|
|
|
|
/* The value of newLimit may be eventually cast to (size_t) and passed
|
|
** to mmap(). Restrict its value to 2GB if (size_t) is not at least a
|
|
** 64-bit type. */
|
|
if( newLimit>0 && sizeof(size_t)<8 ){
|
|
newLimit = (newLimit & 0x7FFFFFFF);
|
|
}
|
|
|
|
*(i64*)pArg = pFile->mmapSizeMax;
|
|
if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){
|
|
pFile->mmapSizeMax = newLimit;
|
|
if( pFile->mmapSize>0 ){
|
|
unixUnmapfile(pFile);
|
|
rc = unixMapfile(pFile, -1);
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
#endif
|
|
#ifdef SQLITE_DEBUG
|
|
/* The pager calls this method to signal that it has done
|
|
** a rollback and that the database is therefore unchanged and
|
|
** it hence it is OK for the transaction change counter to be
|
|
** unchanged.
|
|
*/
|
|
case SQLITE_FCNTL_DB_UNCHANGED: {
|
|
((unixFile*)id)->dbUpdate = 0;
|
|
return SQLITE_OK;
|
|
}
|
|
#endif
|
|
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
|
|
case SQLITE_FCNTL_SET_LOCKPROXYFILE:
|
|
case SQLITE_FCNTL_GET_LOCKPROXYFILE: {
|
|
return proxyFileControl(id,op,pArg);
|
|
}
|
|
#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
|
|
|
|
case SQLITE_FCNTL_EXTERNAL_READER: {
|
|
#ifndef SQLITE_OMIT_WAL
|
|
return unixFcntlExternalReader((unixFile*)id, (int*)pArg);
|
|
#else
|
|
*(int*)pArg = 0;
|
|
return SQLITE_OK;
|
|
#endif
|
|
}
|
|
}
|
|
return SQLITE_NOTFOUND;
|
|
}
|
|
|
|
/*
|
|
** If pFd->sectorSize is non-zero when this function is called, it is a
|
|
** no-op. Otherwise, the values of pFd->sectorSize and
|
|
** pFd->deviceCharacteristics are set according to the file-system
|
|
** characteristics.
|
|
**
|
|
** There are two versions of this function. One for QNX and one for all
|
|
** other systems.
|
|
*/
|
|
#ifndef __QNXNTO__
|
|
static void setDeviceCharacteristics(unixFile *pFd){
|
|
assert( pFd->deviceCharacteristics==0 || pFd->sectorSize!=0 );
|
|
if( pFd->sectorSize==0 ){
|
|
#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
|
|
int res;
|
|
u32 f = 0;
|
|
|
|
/* Check for support for F2FS atomic batch writes. */
|
|
res = osIoctl(pFd->h, F2FS_IOC_GET_FEATURES, &f);
|
|
if( res==0 && (f & F2FS_FEATURE_ATOMIC_WRITE) ){
|
|
pFd->deviceCharacteristics = SQLITE_IOCAP_BATCH_ATOMIC;
|
|
}
|
|
#endif /* __linux__ && SQLITE_ENABLE_BATCH_ATOMIC_WRITE */
|
|
|
|
/* Set the POWERSAFE_OVERWRITE flag if requested. */
|
|
if( pFd->ctrlFlags & UNIXFILE_PSOW ){
|
|
pFd->deviceCharacteristics |= SQLITE_IOCAP_POWERSAFE_OVERWRITE;
|
|
}
|
|
|
|
pFd->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
|
|
}
|
|
}
|
|
#else
|
|
#include <sys/dcmd_blk.h>
|
|
#include <sys/statvfs.h>
|
|
static void setDeviceCharacteristics(unixFile *pFile){
|
|
if( pFile->sectorSize == 0 ){
|
|
struct statvfs fsInfo;
|
|
|
|
/* Set defaults for non-supported filesystems */
|
|
pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
|
|
pFile->deviceCharacteristics = 0;
|
|
if( fstatvfs(pFile->h, &fsInfo) == -1 ) {
|
|
return;
|
|
}
|
|
|
|
if( !strcmp(fsInfo.f_basetype, "tmp") ) {
|
|
pFile->sectorSize = fsInfo.f_bsize;
|
|
pFile->deviceCharacteristics =
|
|
SQLITE_IOCAP_ATOMIC4K | /* All ram filesystem writes are atomic */
|
|
SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until
|
|
** the write succeeds */
|
|
SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
|
|
** so it is ordered */
|
|
0;
|
|
}else if( strstr(fsInfo.f_basetype, "etfs") ){
|
|
pFile->sectorSize = fsInfo.f_bsize;
|
|
pFile->deviceCharacteristics =
|
|
/* etfs cluster size writes are atomic */
|
|
(pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) |
|
|
SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until
|
|
** the write succeeds */
|
|
SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
|
|
** so it is ordered */
|
|
0;
|
|
}else if( !strcmp(fsInfo.f_basetype, "qnx6") ){
|
|
pFile->sectorSize = fsInfo.f_bsize;
|
|
pFile->deviceCharacteristics =
|
|
SQLITE_IOCAP_ATOMIC | /* All filesystem writes are atomic */
|
|
SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until
|
|
** the write succeeds */
|
|
SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
|
|
** so it is ordered */
|
|
0;
|
|
}else if( !strcmp(fsInfo.f_basetype, "qnx4") ){
|
|
pFile->sectorSize = fsInfo.f_bsize;
|
|
pFile->deviceCharacteristics =
|
|
/* full bitset of atomics from max sector size and smaller */
|
|
((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
|
|
SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
|
|
** so it is ordered */
|
|
0;
|
|
}else if( strstr(fsInfo.f_basetype, "dos") ){
|
|
pFile->sectorSize = fsInfo.f_bsize;
|
|
pFile->deviceCharacteristics =
|
|
/* full bitset of atomics from max sector size and smaller */
|
|
((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 |
|
|
SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind
|
|
** so it is ordered */
|
|
0;
|
|
}else{
|
|
pFile->deviceCharacteristics =
|
|
SQLITE_IOCAP_ATOMIC512 | /* blocks are atomic */
|
|
SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until
|
|
** the write succeeds */
|
|
0;
|
|
}
|
|
}
|
|
/* Last chance verification. If the sector size isn't a multiple of 512
|
|
** then it isn't valid.*/
|
|
if( pFile->sectorSize % 512 != 0 ){
|
|
pFile->deviceCharacteristics = 0;
|
|
pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
** 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 its journal file) that the sector size will be the
|
|
** same for both.
|
|
*/
|
|
static int unixSectorSize(sqlite3_file *id){
|
|
unixFile *pFd = (unixFile*)id;
|
|
setDeviceCharacteristics(pFd);
|
|
return pFd->sectorSize;
|
|
}
|
|
|
|
/*
|
|
** Return the device characteristics for the file.
|
|
**
|
|
** This VFS is set up to return SQLITE_IOCAP_POWERSAFE_OVERWRITE by default.
|
|
** However, that choice is controversial since technically the underlying
|
|
** file system does not always provide powersafe overwrites. (In other
|
|
** words, after a power-loss event, parts of the file that were never
|
|
** written might end up being altered.) However, non-PSOW behavior is very,
|
|
** very rare. And asserting PSOW makes a large reduction in the amount
|
|
** of required I/O for journaling, since a lot of padding is eliminated.
|
|
** Hence, while POWERSAFE_OVERWRITE is on by default, there is a file-control
|
|
** available to turn it off and URI query parameter available to turn it off.
|
|
*/
|
|
static int unixDeviceCharacteristics(sqlite3_file *id){
|
|
unixFile *pFd = (unixFile*)id;
|
|
setDeviceCharacteristics(pFd);
|
|
return pFd->deviceCharacteristics;
|
|
}
|
|
|
|
#if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
|
|
|
|
/*
|
|
** Return the system page size.
|
|
**
|
|
** This function should not be called directly by other code in this file.
|
|
** Instead, it should be called via macro osGetpagesize().
|
|
*/
|
|
static int unixGetpagesize(void){
|
|
#if OS_VXWORKS
|
|
return 1024;
|
|
#elif defined(_BSD_SOURCE)
|
|
return getpagesize();
|
|
#else
|
|
return (int)sysconf(_SC_PAGESIZE);
|
|
#endif
|
|
}
|
|
|
|
#endif /* !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 */
|
|
|
|
#ifndef SQLITE_OMIT_WAL
|
|
|
|
/*
|
|
** Object used to represent an shared memory buffer.
|
|
**
|
|
** When multiple threads all reference the same wal-index, each thread
|
|
** has its own unixShm object, but they all point to a single instance
|
|
** of this unixShmNode object. In other words, each wal-index is opened
|
|
** only once per process.
|
|
**
|
|
** Each unixShmNode object is connected to a single unixInodeInfo object.
|
|
** We could coalesce this object into unixInodeInfo, but that would mean
|
|
** every open file that does not use shared memory (in other words, most
|
|
** open files) would have to carry around this extra information. So
|
|
** the unixInodeInfo object contains a pointer to this unixShmNode object
|
|
** and the unixShmNode object is created only when needed.
|
|
**
|
|
** unixMutexHeld() must be true when creating or destroying
|
|
** this object or while reading or writing the following fields:
|
|
**
|
|
** nRef
|
|
**
|
|
** The following fields are read-only after the object is created:
|
|
**
|
|
** hShm
|
|
** zFilename
|
|
**
|
|
** Either unixShmNode.pShmMutex must be held or unixShmNode.nRef==0 and
|
|
** unixMutexHeld() is true when reading or writing any other field
|
|
** in this structure.
|
|
**
|
|
** aLock[SQLITE_SHM_NLOCK]:
|
|
** This array records the various locks held by clients on each of the
|
|
** SQLITE_SHM_NLOCK slots. If the aLock[] entry is set to 0, then no
|
|
** locks are held by the process on this slot. If it is set to -1, then
|
|
** some client holds an EXCLUSIVE lock on the locking slot. If the aLock[]
|
|
** value is set to a positive value, then it is the number of shared
|
|
** locks currently held on the slot.
|
|
**
|
|
** aMutex[SQLITE_SHM_NLOCK]:
|
|
** Normally, when SQLITE_ENABLE_SETLK_TIMEOUT is not defined, mutex
|
|
** pShmMutex is used to protect the aLock[] array and the right to
|
|
** call fcntl() on unixShmNode.hShm to obtain or release locks.
|
|
**
|
|
** If SQLITE_ENABLE_SETLK_TIMEOUT is defined though, we use an array
|
|
** of mutexes - one for each locking slot. To read or write locking
|
|
** slot aLock[iSlot], the caller must hold the corresponding mutex
|
|
** aMutex[iSlot]. Similarly, to call fcntl() to obtain or release a
|
|
** lock corresponding to slot iSlot, mutex aMutex[iSlot] must be held.
|
|
*/
|
|
struct unixShmNode {
|
|
unixInodeInfo *pInode; /* unixInodeInfo that owns this SHM node */
|
|
sqlite3_mutex *pShmMutex; /* Mutex to access this object */
|
|
char *zFilename; /* Name of the mmapped file */
|
|
int hShm; /* Open file descriptor */
|
|
int szRegion; /* Size of shared-memory regions */
|
|
u16 nRegion; /* Size of array apRegion */
|
|
u8 isReadonly; /* True if read-only */
|
|
u8 isUnlocked; /* True if no DMS lock held */
|
|
char **apRegion; /* Array of mapped shared-memory regions */
|
|
int nRef; /* Number of unixShm objects pointing to this */
|
|
unixShm *pFirst; /* All unixShm objects pointing to this */
|
|
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
sqlite3_mutex *aMutex[SQLITE_SHM_NLOCK];
|
|
#endif
|
|
int aLock[SQLITE_SHM_NLOCK]; /* # shared locks on slot, -1==excl lock */
|
|
#ifdef SQLITE_DEBUG
|
|
u8 nextShmId; /* Next available unixShm.id value */
|
|
#endif
|
|
};
|
|
|
|
/*
|
|
** Structure used internally by this VFS to record the state of an
|
|
** open shared memory connection.
|
|
**
|
|
** The following fields are initialized when this object is created and
|
|
** are read-only thereafter:
|
|
**
|
|
** unixShm.pShmNode
|
|
** unixShm.id
|
|
**
|
|
** All other fields are read/write. The unixShm.pShmNode->pShmMutex must
|
|
** be held while accessing any read/write fields.
|
|
*/
|
|
struct unixShm {
|
|
unixShmNode *pShmNode; /* The underlying unixShmNode object */
|
|
unixShm *pNext; /* Next unixShm with the same unixShmNode */
|
|
u8 hasMutex; /* True if holding the unixShmNode->pShmMutex */
|
|
u8 id; /* Id of this connection within its unixShmNode */
|
|
u16 sharedMask; /* Mask of shared locks held */
|
|
u16 exclMask; /* Mask of exclusive locks held */
|
|
};
|
|
|
|
/*
|
|
** Constants used for locking
|
|
*/
|
|
#define UNIX_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */
|
|
#define UNIX_SHM_DMS (UNIX_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */
|
|
|
|
/*
|
|
** Use F_GETLK to check whether or not there are any readers with open
|
|
** wal-mode transactions in other processes on database file pFile. If
|
|
** no error occurs, return SQLITE_OK and set (*piOut) to 1 if there are
|
|
** such transactions, or 0 otherwise. If an error occurs, return an
|
|
** SQLite error code. The final value of *piOut is undefined in this
|
|
** case.
|
|
*/
|
|
static int unixFcntlExternalReader(unixFile *pFile, int *piOut){
|
|
int rc = SQLITE_OK;
|
|
*piOut = 0;
|
|
if( pFile->pShm){
|
|
unixShmNode *pShmNode = pFile->pShm->pShmNode;
|
|
struct flock f;
|
|
|
|
memset(&f, 0, sizeof(f));
|
|
f.l_type = F_WRLCK;
|
|
f.l_whence = SEEK_SET;
|
|
f.l_start = UNIX_SHM_BASE + 3;
|
|
f.l_len = SQLITE_SHM_NLOCK - 3;
|
|
|
|
sqlite3_mutex_enter(pShmNode->pShmMutex);
|
|
if( osFcntl(pShmNode->hShm, F_GETLK, &f)<0 ){
|
|
rc = SQLITE_IOERR_LOCK;
|
|
}else{
|
|
*piOut = (f.l_type!=F_UNLCK);
|
|
}
|
|
sqlite3_mutex_leave(pShmNode->pShmMutex);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
/*
|
|
** Apply posix advisory locks for all bytes from ofst through ofst+n-1.
|
|
**
|
|
** Locks block if the mask is exactly UNIX_SHM_C and are non-blocking
|
|
** otherwise.
|
|
*/
|
|
static int unixShmSystemLock(
|
|
unixFile *pFile, /* Open connection to the WAL file */
|
|
int lockType, /* F_UNLCK, F_RDLCK, or F_WRLCK */
|
|
int ofst, /* First byte of the locking range */
|
|
int n /* Number of bytes to lock */
|
|
){
|
|
unixShmNode *pShmNode; /* Apply locks to this open shared-memory segment */
|
|
struct flock f; /* The posix advisory locking structure */
|
|
int rc = SQLITE_OK; /* Result code form fcntl() */
|
|
|
|
pShmNode = pFile->pInode->pShmNode;
|
|
|
|
/* Assert that the parameters are within expected range and that the
|
|
** correct mutex or mutexes are held. */
|
|
assert( pShmNode->nRef>=0 );
|
|
assert( (ofst==UNIX_SHM_DMS && n==1)
|
|
|| (ofst>=UNIX_SHM_BASE && ofst+n<=(UNIX_SHM_BASE+SQLITE_SHM_NLOCK))
|
|
);
|
|
if( ofst==UNIX_SHM_DMS ){
|
|
assert( pShmNode->nRef>0 || unixMutexHeld() );
|
|
assert( pShmNode->nRef==0 || sqlite3_mutex_held(pShmNode->pShmMutex) );
|
|
}else{
|
|
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
int ii;
|
|
for(ii=ofst-UNIX_SHM_BASE; ii<ofst-UNIX_SHM_BASE+n; ii++){
|
|
assert( sqlite3_mutex_held(pShmNode->aMutex[ii]) );
|
|
}
|
|
#else
|
|
assert( sqlite3_mutex_held(pShmNode->pShmMutex) );
|
|
assert( pShmNode->nRef>0 );
|
|
#endif
|
|
}
|
|
|
|
/* Shared locks never span more than one byte */
|
|
assert( n==1 || lockType!=F_RDLCK );
|
|
|
|
/* Locks are within range */
|
|
assert( n>=1 && n<=SQLITE_SHM_NLOCK );
|
|
assert( ofst>=UNIX_SHM_BASE && ofst<=(UNIX_SHM_DMS+SQLITE_SHM_NLOCK) );
|
|
|
|
if( pShmNode->hShm>=0 ){
|
|
int res;
|
|
/* Initialize the locking parameters */
|
|
f.l_type = lockType;
|
|
f.l_whence = SEEK_SET;
|
|
f.l_start = ofst;
|
|
f.l_len = n;
|
|
res = osSetPosixAdvisoryLock(pShmNode->hShm, &f, pFile);
|
|
if( res==-1 ){
|
|
#if defined(SQLITE_ENABLE_SETLK_TIMEOUT) && SQLITE_ENABLE_SETLK_TIMEOUT==1
|
|
rc = (pFile->iBusyTimeout ? SQLITE_BUSY_TIMEOUT : SQLITE_BUSY);
|
|
#else
|
|
rc = SQLITE_BUSY;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/* Do debug tracing */
|
|
#ifdef SQLITE_DEBUG
|
|
OSTRACE(("SHM-LOCK "));
|
|
if( rc==SQLITE_OK ){
|
|
if( lockType==F_UNLCK ){
|
|
OSTRACE(("unlock %d..%d ok\n", ofst, ofst+n-1));
|
|
}else if( lockType==F_RDLCK ){
|
|
OSTRACE(("read-lock %d..%d ok\n", ofst, ofst+n-1));
|
|
}else{
|
|
assert( lockType==F_WRLCK );
|
|
OSTRACE(("write-lock %d..%d ok\n", ofst, ofst+n-1));
|
|
}
|
|
}else{
|
|
if( lockType==F_UNLCK ){
|
|
OSTRACE(("unlock %d..%d failed\n", ofst, ofst+n-1));
|
|
}else if( lockType==F_RDLCK ){
|
|
OSTRACE(("read-lock %d..%d failed\n", ofst, ofst+n-1));
|
|
}else{
|
|
assert( lockType==F_WRLCK );
|
|
OSTRACE(("write-lock %d..%d failed\n", ofst, ofst+n-1));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Return the minimum number of 32KB shm regions that should be mapped at
|
|
** a time, assuming that each mapping must be an integer multiple of the
|
|
** current system page-size.
|
|
**
|
|
** Usually, this is 1. The exception seems to be systems that are configured
|
|
** to use 64KB pages - in this case each mapping must cover at least two
|
|
** shm regions.
|
|
*/
|
|
static int unixShmRegionPerMap(void){
|
|
int shmsz = 32*1024; /* SHM region size */
|
|
int pgsz = osGetpagesize(); /* System page size */
|
|
assert( ((pgsz-1)&pgsz)==0 ); /* Page size must be a power of 2 */
|
|
if( pgsz<shmsz ) return 1;
|
|
return pgsz/shmsz;
|
|
}
|
|
|
|
/*
|
|
** Purge the unixShmNodeList list of all entries with unixShmNode.nRef==0.
|
|
**
|
|
** This is not a VFS shared-memory method; it is a utility function called
|
|
** by VFS shared-memory methods.
|
|
*/
|
|
static void unixShmPurge(unixFile *pFd){
|
|
unixShmNode *p = pFd->pInode->pShmNode;
|
|
assert( unixMutexHeld() );
|
|
if( p && ALWAYS(p->nRef==0) ){
|
|
int nShmPerMap = unixShmRegionPerMap();
|
|
int i;
|
|
assert( p->pInode==pFd->pInode );
|
|
sqlite3_mutex_free(p->pShmMutex);
|
|
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
for(i=0; i<SQLITE_SHM_NLOCK; i++){
|
|
sqlite3_mutex_free(p->aMutex[i]);
|
|
}
|
|
#endif
|
|
for(i=0; i<p->nRegion; i+=nShmPerMap){
|
|
if( p->hShm>=0 ){
|
|
osMunmap(p->apRegion[i], p->szRegion);
|
|
}else{
|
|
sqlite3_free(p->apRegion[i]);
|
|
}
|
|
}
|
|
sqlite3_free(p->apRegion);
|
|
if( p->hShm>=0 ){
|
|
robust_close(pFd, p->hShm, __LINE__);
|
|
p->hShm = -1;
|
|
}
|
|
p->pInode->pShmNode = 0;
|
|
sqlite3_free(p);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** The DMS lock has not yet been taken on shm file pShmNode. Attempt to
|
|
** take it now. Return SQLITE_OK if successful, or an SQLite error
|
|
** code otherwise.
|
|
**
|
|
** If the DMS cannot be locked because this is a readonly_shm=1
|
|
** connection and no other process already holds a lock, return
|
|
** SQLITE_READONLY_CANTINIT and set pShmNode->isUnlocked=1.
|
|
*/
|
|
static int unixLockSharedMemory(unixFile *pDbFd, unixShmNode *pShmNode){
|
|
struct flock lock;
|
|
int rc = SQLITE_OK;
|
|
|
|
/* Use F_GETLK to determine the locks other processes are holding
|
|
** on the DMS byte. If it indicates that another process is holding
|
|
** a SHARED lock, then this process may also take a SHARED lock
|
|
** and proceed with opening the *-shm file.
|
|
**
|
|
** Or, if no other process is holding any lock, then this process
|
|
** is the first to open it. In this case take an EXCLUSIVE lock on the
|
|
** DMS byte and truncate the *-shm file to zero bytes in size. Then
|
|
** downgrade to a SHARED lock on the DMS byte.
|
|
**
|
|
** If another process is holding an EXCLUSIVE lock on the DMS byte,
|
|
** return SQLITE_BUSY to the caller (it will try again). An earlier
|
|
** version of this code attempted the SHARED lock at this point. But
|
|
** this introduced a subtle race condition: if the process holding
|
|
** EXCLUSIVE failed just before truncating the *-shm file, then this
|
|
** process might open and use the *-shm file without truncating it.
|
|
** And if the *-shm file has been corrupted by a power failure or
|
|
** system crash, the database itself may also become corrupt. */
|
|
lock.l_whence = SEEK_SET;
|
|
lock.l_start = UNIX_SHM_DMS;
|
|
lock.l_len = 1;
|
|
lock.l_type = F_WRLCK;
|
|
if( osFcntl(pShmNode->hShm, F_GETLK, &lock)!=0 ) {
|
|
rc = SQLITE_IOERR_LOCK;
|
|
}else if( lock.l_type==F_UNLCK ){
|
|
if( pShmNode->isReadonly ){
|
|
pShmNode->isUnlocked = 1;
|
|
rc = SQLITE_READONLY_CANTINIT;
|
|
}else{
|
|
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
/* Do not use a blocking lock here. If the lock cannot be obtained
|
|
** immediately, it means some other connection is truncating the
|
|
** *-shm file. And after it has done so, it will not release its
|
|
** lock, but only downgrade it to a shared lock. So no point in
|
|
** blocking here. The call below to obtain the shared DMS lock may
|
|
** use a blocking lock. */
|
|
int iSaveTimeout = pDbFd->iBusyTimeout;
|
|
pDbFd->iBusyTimeout = 0;
|
|
#endif
|
|
rc = unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1);
|
|
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
pDbFd->iBusyTimeout = iSaveTimeout;
|
|
#endif
|
|
/* The first connection to attach must truncate the -shm file. We
|
|
** truncate to 3 bytes (an arbitrary small number, less than the
|
|
** -shm header size) rather than 0 as a system debugging aid, to
|
|
** help detect if a -shm file truncation is legitimate or is the work
|
|
** or a rogue process. */
|
|
if( rc==SQLITE_OK && robust_ftruncate(pShmNode->hShm, 3) ){
|
|
rc = unixLogError(SQLITE_IOERR_SHMOPEN,"ftruncate",pShmNode->zFilename);
|
|
}
|
|
}
|
|
}else if( lock.l_type==F_WRLCK ){
|
|
rc = SQLITE_BUSY;
|
|
}
|
|
|
|
if( rc==SQLITE_OK ){
|
|
assert( lock.l_type==F_UNLCK || lock.l_type==F_RDLCK );
|
|
rc = unixShmSystemLock(pDbFd, F_RDLCK, UNIX_SHM_DMS, 1);
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Open a shared-memory area associated with open database file pDbFd.
|
|
** This particular implementation uses mmapped files.
|
|
**
|
|
** The file used to implement shared-memory is in the same directory
|
|
** as the open database file and has the same name as the open database
|
|
** file with the "-shm" suffix added. For example, if the database file
|
|
** is "/home/user1/config.db" then the file that is created and mmapped
|
|
** for shared memory will be called "/home/user1/config.db-shm".
|
|
**
|
|
** Another approach to is to use files in /dev/shm or /dev/tmp or an
|
|
** some other tmpfs mount. But if a file in a different directory
|
|
** from the database file is used, then differing access permissions
|
|
** or a chroot() might cause two different processes on the same
|
|
** database to end up using different files for shared memory -
|
|
** meaning that their memory would not really be shared - resulting
|
|
** in database corruption. Nevertheless, this tmpfs file usage
|
|
** can be enabled at compile-time using -DSQLITE_SHM_DIRECTORY="/dev/shm"
|
|
** or the equivalent. The use of the SQLITE_SHM_DIRECTORY compile-time
|
|
** option results in an incompatible build of SQLite; builds of SQLite
|
|
** that with differing SQLITE_SHM_DIRECTORY settings attempt to use the
|
|
** same database file at the same time, database corruption will likely
|
|
** result. The SQLITE_SHM_DIRECTORY compile-time option is considered
|
|
** "unsupported" and may go away in a future SQLite release.
|
|
**
|
|
** When opening a new shared-memory file, if no other instances of that
|
|
** file are currently open, in this process or in other processes, then
|
|
** the file must be truncated to zero length or have its header cleared.
|
|
**
|
|
** If the original database file (pDbFd) is using the "unix-excl" VFS
|
|
** that means that an exclusive lock is held on the database file and
|
|
** that no other processes are able to read or write the database. In
|
|
** that case, we do not really need shared memory. No shared memory
|
|
** file is created. The shared memory will be simulated with heap memory.
|
|
*/
|
|
static int unixOpenSharedMemory(unixFile *pDbFd){
|
|
struct unixShm *p = 0; /* The connection to be opened */
|
|
struct unixShmNode *pShmNode; /* The underlying mmapped file */
|
|
int rc = SQLITE_OK; /* Result code */
|
|
unixInodeInfo *pInode; /* The inode of fd */
|
|
char *zShm; /* Name of the file used for SHM */
|
|
int nShmFilename; /* Size of the SHM filename in bytes */
|
|
|
|
/* Allocate space for the new unixShm object. */
|
|
p = sqlite3_malloc64( sizeof(*p) );
|
|
if( p==0 ) return SQLITE_NOMEM_BKPT;
|
|
memset(p, 0, sizeof(*p));
|
|
assert( pDbFd->pShm==0 );
|
|
|
|
/* Check to see if a unixShmNode object already exists. Reuse an existing
|
|
** one if present. Create a new one if necessary.
|
|
*/
|
|
assert( unixFileMutexNotheld(pDbFd) );
|
|
unixEnterMutex();
|
|
pInode = pDbFd->pInode;
|
|
pShmNode = pInode->pShmNode;
|
|
if( pShmNode==0 ){
|
|
struct stat sStat; /* fstat() info for database file */
|
|
#ifndef SQLITE_SHM_DIRECTORY
|
|
const char *zBasePath = pDbFd->zPath;
|
|
#endif
|
|
|
|
/* Call fstat() to figure out the permissions on the database file. If
|
|
** a new *-shm file is created, an attempt will be made to create it
|
|
** with the same permissions.
|
|
*/
|
|
if( osFstat(pDbFd->h, &sStat) ){
|
|
rc = SQLITE_IOERR_FSTAT;
|
|
goto shm_open_err;
|
|
}
|
|
|
|
#ifdef SQLITE_SHM_DIRECTORY
|
|
nShmFilename = sizeof(SQLITE_SHM_DIRECTORY) + 31;
|
|
#else
|
|
nShmFilename = 6 + (int)strlen(zBasePath);
|
|
#endif
|
|
pShmNode = sqlite3_malloc64( sizeof(*pShmNode) + nShmFilename );
|
|
if( pShmNode==0 ){
|
|
rc = SQLITE_NOMEM_BKPT;
|
|
goto shm_open_err;
|
|
}
|
|
memset(pShmNode, 0, sizeof(*pShmNode)+nShmFilename);
|
|
zShm = pShmNode->zFilename = (char*)&pShmNode[1];
|
|
#ifdef SQLITE_SHM_DIRECTORY
|
|
sqlite3_snprintf(nShmFilename, zShm,
|
|
SQLITE_SHM_DIRECTORY "/sqlite-shm-%x-%x",
|
|
(u32)sStat.st_ino, (u32)sStat.st_dev);
|
|
#else
|
|
sqlite3_snprintf(nShmFilename, zShm, "%s-shm", zBasePath);
|
|
sqlite3FileSuffix3(pDbFd->zPath, zShm);
|
|
#endif
|
|
pShmNode->hShm = -1;
|
|
pDbFd->pInode->pShmNode = pShmNode;
|
|
pShmNode->pInode = pDbFd->pInode;
|
|
if( sqlite3GlobalConfig.bCoreMutex ){
|
|
pShmNode->pShmMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
|
|
if( pShmNode->pShmMutex==0 ){
|
|
rc = SQLITE_NOMEM_BKPT;
|
|
goto shm_open_err;
|
|
}
|
|
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
{
|
|
int ii;
|
|
for(ii=0; ii<SQLITE_SHM_NLOCK; ii++){
|
|
pShmNode->aMutex[ii] = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
|
|
if( pShmNode->aMutex[ii]==0 ){
|
|
rc = SQLITE_NOMEM_BKPT;
|
|
goto shm_open_err;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if( pInode->bProcessLock==0 ){
|
|
if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
|
|
pShmNode->hShm = robust_open(zShm, O_RDWR|O_CREAT|O_NOFOLLOW,
|
|
(sStat.st_mode&0777));
|
|
}
|
|
if( pShmNode->hShm<0 ){
|
|
pShmNode->hShm = robust_open(zShm, O_RDONLY|O_NOFOLLOW,
|
|
(sStat.st_mode&0777));
|
|
if( pShmNode->hShm<0 ){
|
|
rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShm);
|
|
goto shm_open_err;
|
|
}
|
|
pShmNode->isReadonly = 1;
|
|
}
|
|
|
|
/* If this process is running as root, make sure that the SHM file
|
|
** is owned by the same user that owns the original database. Otherwise,
|
|
** the original owner will not be able to connect.
|
|
*/
|
|
robustFchown(pShmNode->hShm, sStat.st_uid, sStat.st_gid);
|
|
|
|
rc = unixLockSharedMemory(pDbFd, pShmNode);
|
|
if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err;
|
|
}
|
|
}
|
|
|
|
/* Make the new connection a child of the unixShmNode */
|
|
p->pShmNode = pShmNode;
|
|
#ifdef SQLITE_DEBUG
|
|
p->id = pShmNode->nextShmId++;
|
|
#endif
|
|
pShmNode->nRef++;
|
|
pDbFd->pShm = p;
|
|
unixLeaveMutex();
|
|
|
|
/* The reference count on pShmNode has already been incremented under
|
|
** the cover of the unixEnterMutex() mutex and the pointer from the
|
|
** new (struct unixShm) object to the pShmNode has been set. All that is
|
|
** left to do is to link the new object into the linked list starting
|
|
** at pShmNode->pFirst. This must be done while holding the
|
|
** pShmNode->pShmMutex.
|
|
*/
|
|
sqlite3_mutex_enter(pShmNode->pShmMutex);
|
|
p->pNext = pShmNode->pFirst;
|
|
pShmNode->pFirst = p;
|
|
sqlite3_mutex_leave(pShmNode->pShmMutex);
|
|
return rc;
|
|
|
|
/* Jump here on any error */
|
|
shm_open_err:
|
|
unixShmPurge(pDbFd); /* This call frees pShmNode if required */
|
|
sqlite3_free(p);
|
|
unixLeaveMutex();
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** This function is called to obtain a pointer to region iRegion of the
|
|
** shared-memory associated with the database file fd. Shared-memory regions
|
|
** are numbered starting from zero. Each shared-memory region is szRegion
|
|
** bytes in size.
|
|
**
|
|
** If an error occurs, an error code is returned and *pp is set to NULL.
|
|
**
|
|
** Otherwise, if the bExtend parameter is 0 and the requested shared-memory
|
|
** region has not been allocated (by any client, including one running in a
|
|
** separate process), then *pp is set to NULL and SQLITE_OK returned. If
|
|
** bExtend is non-zero and the requested shared-memory region has not yet
|
|
** been allocated, it is allocated by this function.
|
|
**
|
|
** If the shared-memory region has already been allocated or is allocated by
|
|
** this call as described above, then it is mapped into this processes
|
|
** address space (if it is not already), *pp is set to point to the mapped
|
|
** memory and SQLITE_OK returned.
|
|
*/
|
|
static int unixShmMap(
|
|
sqlite3_file *fd, /* Handle open on database file */
|
|
int iRegion, /* Region to retrieve */
|
|
int szRegion, /* Size of regions */
|
|
int bExtend, /* True to extend file if necessary */
|
|
void volatile **pp /* OUT: Mapped memory */
|
|
){
|
|
unixFile *pDbFd = (unixFile*)fd;
|
|
unixShm *p;
|
|
unixShmNode *pShmNode;
|
|
int rc = SQLITE_OK;
|
|
int nShmPerMap = unixShmRegionPerMap();
|
|
int nReqRegion;
|
|
|
|
/* If the shared-memory file has not yet been opened, open it now. */
|
|
if( pDbFd->pShm==0 ){
|
|
rc = unixOpenSharedMemory(pDbFd);
|
|
if( rc!=SQLITE_OK ) return rc;
|
|
}
|
|
|
|
p = pDbFd->pShm;
|
|
pShmNode = p->pShmNode;
|
|
sqlite3_mutex_enter(pShmNode->pShmMutex);
|
|
if( pShmNode->isUnlocked ){
|
|
rc = unixLockSharedMemory(pDbFd, pShmNode);
|
|
if( rc!=SQLITE_OK ) goto shmpage_out;
|
|
pShmNode->isUnlocked = 0;
|
|
}
|
|
assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
|
|
assert( pShmNode->pInode==pDbFd->pInode );
|
|
assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 );
|
|
assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 );
|
|
|
|
/* Minimum number of regions required to be mapped. */
|
|
nReqRegion = ((iRegion+nShmPerMap) / nShmPerMap) * nShmPerMap;
|
|
|
|
if( pShmNode->nRegion<nReqRegion ){
|
|
char **apNew; /* New apRegion[] array */
|
|
int nByte = nReqRegion*szRegion; /* Minimum required file size */
|
|
struct stat sStat; /* Used by fstat() */
|
|
|
|
pShmNode->szRegion = szRegion;
|
|
|
|
if( pShmNode->hShm>=0 ){
|
|
/* The requested region is not mapped into this processes address space.
|
|
** Check to see if it has been allocated (i.e. if the wal-index file is
|
|
** large enough to contain the requested region).
|
|
*/
|
|
if( osFstat(pShmNode->hShm, &sStat) ){
|
|
rc = SQLITE_IOERR_SHMSIZE;
|
|
goto shmpage_out;
|
|
}
|
|
|
|
if( sStat.st_size<nByte ){
|
|
/* The requested memory region does not exist. If bExtend is set to
|
|
** false, exit early. *pp will be set to NULL and SQLITE_OK returned.
|
|
*/
|
|
if( !bExtend ){
|
|
goto shmpage_out;
|
|
}
|
|
|
|
/* Alternatively, if bExtend is true, extend the file. Do this by
|
|
** writing a single byte to the end of each (OS) page being
|
|
** allocated or extended. Technically, we need only write to the
|
|
** last page in order to extend the file. But writing to all new
|
|
** pages forces the OS to allocate them immediately, which reduces
|
|
** the chances of SIGBUS while accessing the mapped region later on.
|
|
*/
|
|
else{
|
|
static const int pgsz = 4096;
|
|
int iPg;
|
|
|
|
/* Write to the last byte of each newly allocated or extended page */
|
|
assert( (nByte % pgsz)==0 );
|
|
for(iPg=(sStat.st_size/pgsz); iPg<(nByte/pgsz); iPg++){
|
|
int x = 0;
|
|
if( seekAndWriteFd(pShmNode->hShm, iPg*pgsz + pgsz-1,"",1,&x)!=1 ){
|
|
const char *zFile = pShmNode->zFilename;
|
|
rc = unixLogError(SQLITE_IOERR_SHMSIZE, "write", zFile);
|
|
goto shmpage_out;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Map the requested memory region into this processes address space. */
|
|
apNew = (char **)sqlite3_realloc(
|
|
pShmNode->apRegion, nReqRegion*sizeof(char *)
|
|
);
|
|
if( !apNew ){
|
|
rc = SQLITE_IOERR_NOMEM_BKPT;
|
|
goto shmpage_out;
|
|
}
|
|
pShmNode->apRegion = apNew;
|
|
while( pShmNode->nRegion<nReqRegion ){
|
|
int nMap = szRegion*nShmPerMap;
|
|
int i;
|
|
void *pMem;
|
|
if( pShmNode->hShm>=0 ){
|
|
pMem = osMmap(0, nMap,
|
|
pShmNode->isReadonly ? PROT_READ : PROT_READ|PROT_WRITE,
|
|
MAP_SHARED, pShmNode->hShm, szRegion*(i64)pShmNode->nRegion
|
|
);
|
|
if( pMem==MAP_FAILED ){
|
|
rc = unixLogError(SQLITE_IOERR_SHMMAP, "mmap", pShmNode->zFilename);
|
|
goto shmpage_out;
|
|
}
|
|
}else{
|
|
pMem = sqlite3_malloc64(nMap);
|
|
if( pMem==0 ){
|
|
rc = SQLITE_NOMEM_BKPT;
|
|
goto shmpage_out;
|
|
}
|
|
memset(pMem, 0, nMap);
|
|
}
|
|
|
|
for(i=0; i<nShmPerMap; i++){
|
|
pShmNode->apRegion[pShmNode->nRegion+i] = &((char*)pMem)[szRegion*i];
|
|
}
|
|
pShmNode->nRegion += nShmPerMap;
|
|
}
|
|
}
|
|
|
|
shmpage_out:
|
|
if( pShmNode->nRegion>iRegion ){
|
|
*pp = pShmNode->apRegion[iRegion];
|
|
}else{
|
|
*pp = 0;
|
|
}
|
|
if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY;
|
|
sqlite3_mutex_leave(pShmNode->pShmMutex);
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Check that the pShmNode->aLock[] array comports with the locking bitmasks
|
|
** held by each client. Return true if it does, or false otherwise. This
|
|
** is to be used in an assert(). e.g.
|
|
**
|
|
** assert( assertLockingArrayOk(pShmNode) );
|
|
*/
|
|
#ifdef SQLITE_DEBUG
|
|
static int assertLockingArrayOk(unixShmNode *pShmNode){
|
|
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
return 1;
|
|
#else
|
|
unixShm *pX;
|
|
int aLock[SQLITE_SHM_NLOCK];
|
|
|
|
memset(aLock, 0, sizeof(aLock));
|
|
for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
|
|
int i;
|
|
for(i=0; i<SQLITE_SHM_NLOCK; i++){
|
|
if( pX->exclMask & (1<<i) ){
|
|
assert( aLock[i]==0 );
|
|
aLock[i] = -1;
|
|
}else if( pX->sharedMask & (1<<i) ){
|
|
assert( aLock[i]>=0 );
|
|
aLock[i]++;
|
|
}
|
|
}
|
|
}
|
|
|
|
assert( 0==memcmp(pShmNode->aLock, aLock, sizeof(aLock)) );
|
|
return (memcmp(pShmNode->aLock, aLock, sizeof(aLock))==0);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
** Change the lock state for a shared-memory segment.
|
|
**
|
|
** Note that the relationship between SHARED and EXCLUSIVE locks is a little
|
|
** different here than in posix. In xShmLock(), one can go from unlocked
|
|
** to shared and back or from unlocked to exclusive and back. But one may
|
|
** not go from shared to exclusive or from exclusive to shared.
|
|
*/
|
|
static int unixShmLock(
|
|
sqlite3_file *fd, /* Database file holding the shared memory */
|
|
int ofst, /* First lock to acquire or release */
|
|
int n, /* Number of locks to acquire or release */
|
|
int flags /* What to do with the lock */
|
|
){
|
|
unixFile *pDbFd = (unixFile*)fd; /* Connection holding shared memory */
|
|
unixShm *p; /* The shared memory being locked */
|
|
unixShmNode *pShmNode; /* The underlying file iNode */
|
|
int rc = SQLITE_OK; /* Result code */
|
|
u16 mask = (1<<(ofst+n)) - (1<<ofst); /* Mask of locks to take or release */
|
|
int *aLock;
|
|
|
|
p = pDbFd->pShm;
|
|
if( p==0 ) return SQLITE_IOERR_SHMLOCK;
|
|
pShmNode = p->pShmNode;
|
|
if( NEVER(pShmNode==0) ) return SQLITE_IOERR_SHMLOCK;
|
|
aLock = pShmNode->aLock;
|
|
|
|
assert( pShmNode==pDbFd->pInode->pShmNode );
|
|
assert( pShmNode->pInode==pDbFd->pInode );
|
|
assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
|
|
assert( n>=1 );
|
|
assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
|
|
|| flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE)
|
|
|| flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
|
|
|| flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
|
|
assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
|
|
assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 );
|
|
assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 );
|
|
|
|
/* Check that, if this to be a blocking lock, no locks that occur later
|
|
** in the following list than the lock being obtained are already held:
|
|
**
|
|
** 1. Checkpointer lock (ofst==1).
|
|
** 2. Write lock (ofst==0).
|
|
** 3. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK).
|
|
**
|
|
** In other words, if this is a blocking lock, none of the locks that
|
|
** occur later in the above list than the lock being obtained may be
|
|
** held.
|
|
**
|
|
** It is not permitted to block on the RECOVER lock.
|
|
*/
|
|
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
{
|
|
u16 lockMask = (p->exclMask|p->sharedMask);
|
|
assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || (
|
|
(ofst!=2) /* not RECOVER */
|
|
&& (ofst!=1 || lockMask==0 || lockMask==2)
|
|
&& (ofst!=0 || lockMask<3)
|
|
&& (ofst<3 || lockMask<(1<<ofst))
|
|
));
|
|
}
|
|
#endif
|
|
|
|
/* Check if there is any work to do. There are three cases:
|
|
**
|
|
** a) An unlock operation where there are locks to unlock,
|
|
** b) An shared lock where the requested lock is not already held
|
|
** c) An exclusive lock where the requested lock is not already held
|
|
**
|
|
** The SQLite core never requests an exclusive lock that it already holds.
|
|
** This is assert()ed below.
|
|
*/
|
|
assert( flags!=(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK)
|
|
|| 0==(p->exclMask & mask)
|
|
);
|
|
if( ((flags & SQLITE_SHM_UNLOCK) && ((p->exclMask|p->sharedMask) & mask))
|
|
|| (flags==(SQLITE_SHM_SHARED|SQLITE_SHM_LOCK) && 0==(p->sharedMask & mask))
|
|
|| (flags==(SQLITE_SHM_EXCLUSIVE|SQLITE_SHM_LOCK))
|
|
){
|
|
|
|
/* Take the required mutexes. In SETLK_TIMEOUT mode (blocking locks), if
|
|
** this is an attempt on an exclusive lock use sqlite3_mutex_try(). If any
|
|
** other thread is holding this mutex, then it is either holding or about
|
|
** to hold a lock exclusive to the one being requested, and we may
|
|
** therefore return SQLITE_BUSY to the caller.
|
|
**
|
|
** Doing this prevents some deadlock scenarios. For example, thread 1 may
|
|
** be a checkpointer blocked waiting on the WRITER lock. And thread 2
|
|
** may be a normal SQL client upgrading to a write transaction. In this
|
|
** case thread 2 does a non-blocking request for the WRITER lock. But -
|
|
** if it were to use sqlite3_mutex_enter() then it would effectively
|
|
** become a (doomed) blocking request, as thread 2 would block until thread
|
|
** 1 obtained WRITER and released the mutex. Since thread 2 already holds
|
|
** a lock on a read-locking slot at this point, this breaks the
|
|
** anti-deadlock rules (see above). */
|
|
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
int iMutex;
|
|
for(iMutex=ofst; iMutex<ofst+n; iMutex++){
|
|
if( flags==(SQLITE_SHM_LOCK|SQLITE_SHM_EXCLUSIVE) ){
|
|
rc = sqlite3_mutex_try(pShmNode->aMutex[iMutex]);
|
|
if( rc!=SQLITE_OK ) goto leave_shmnode_mutexes;
|
|
}else{
|
|
sqlite3_mutex_enter(pShmNode->aMutex[iMutex]);
|
|
}
|
|
}
|
|
#else
|
|
sqlite3_mutex_enter(pShmNode->pShmMutex);
|
|
#endif
|
|
|
|
if( ALWAYS(rc==SQLITE_OK) ){
|
|
if( flags & SQLITE_SHM_UNLOCK ){
|
|
/* Case (a) - unlock. */
|
|
int bUnlock = 1;
|
|
assert( (p->exclMask & p->sharedMask)==0 );
|
|
assert( !(flags & SQLITE_SHM_EXCLUSIVE) || (p->exclMask & mask)==mask );
|
|
assert( !(flags & SQLITE_SHM_SHARED) || (p->sharedMask & mask)==mask );
|
|
|
|
/* If this is a SHARED lock being unlocked, it is possible that other
|
|
** clients within this process are holding the same SHARED lock. In
|
|
** this case, set bUnlock to 0 so that the posix lock is not removed
|
|
** from the file-descriptor below. */
|
|
if( flags & SQLITE_SHM_SHARED ){
|
|
assert( n==1 );
|
|
assert( aLock[ofst]>=1 );
|
|
if( aLock[ofst]>1 ){
|
|
bUnlock = 0;
|
|
aLock[ofst]--;
|
|
p->sharedMask &= ~mask;
|
|
}
|
|
}
|
|
|
|
if( bUnlock ){
|
|
rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n);
|
|
if( rc==SQLITE_OK ){
|
|
memset(&aLock[ofst], 0, sizeof(int)*n);
|
|
p->sharedMask &= ~mask;
|
|
p->exclMask &= ~mask;
|
|
}
|
|
}
|
|
}else if( flags & SQLITE_SHM_SHARED ){
|
|
/* Case (b) - a shared lock. */
|
|
|
|
if( aLock[ofst]<0 ){
|
|
/* An exclusive lock is held by some other connection. BUSY. */
|
|
rc = SQLITE_BUSY;
|
|
}else if( aLock[ofst]==0 ){
|
|
rc = unixShmSystemLock(pDbFd, F_RDLCK, ofst+UNIX_SHM_BASE, n);
|
|
}
|
|
|
|
/* Get the local shared locks */
|
|
if( rc==SQLITE_OK ){
|
|
p->sharedMask |= mask;
|
|
aLock[ofst]++;
|
|
}
|
|
}else{
|
|
/* Case (c) - an exclusive lock. */
|
|
int ii;
|
|
|
|
assert( flags==(SQLITE_SHM_LOCK|SQLITE_SHM_EXCLUSIVE) );
|
|
assert( (p->sharedMask & mask)==0 );
|
|
assert( (p->exclMask & mask)==0 );
|
|
|
|
/* Make sure no sibling connections hold locks that will block this
|
|
** lock. If any do, return SQLITE_BUSY right away. */
|
|
for(ii=ofst; ii<ofst+n; ii++){
|
|
if( aLock[ii] ){
|
|
rc = SQLITE_BUSY;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Get the exclusive locks at the system level. Then if successful
|
|
** also update the in-memory values. */
|
|
if( rc==SQLITE_OK ){
|
|
rc = unixShmSystemLock(pDbFd, F_WRLCK, ofst+UNIX_SHM_BASE, n);
|
|
if( rc==SQLITE_OK ){
|
|
p->exclMask |= mask;
|
|
for(ii=ofst; ii<ofst+n; ii++){
|
|
aLock[ii] = -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
assert( assertLockingArrayOk(pShmNode) );
|
|
}
|
|
|
|
/* Drop the mutexes acquired above. */
|
|
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
leave_shmnode_mutexes:
|
|
for(iMutex--; iMutex>=ofst; iMutex--){
|
|
sqlite3_mutex_leave(pShmNode->aMutex[iMutex]);
|
|
}
|
|
#else
|
|
sqlite3_mutex_leave(pShmNode->pShmMutex);
|
|
#endif
|
|
}
|
|
|
|
OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n",
|
|
p->id, osGetpid(0), p->sharedMask, p->exclMask));
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Implement a memory barrier or memory fence on shared memory.
|
|
**
|
|
** All loads and stores begun before the barrier must complete before
|
|
** any load or store begun after the barrier.
|
|
*/
|
|
static void unixShmBarrier(
|
|
sqlite3_file *fd /* Database file holding the shared memory */
|
|
){
|
|
UNUSED_PARAMETER(fd);
|
|
sqlite3MemoryBarrier(); /* compiler-defined memory barrier */
|
|
assert( fd->pMethods->xLock==nolockLock
|
|
|| unixFileMutexNotheld((unixFile*)fd)
|
|
);
|
|
unixEnterMutex(); /* Also mutex, for redundancy */
|
|
unixLeaveMutex();
|
|
}
|
|
|
|
/*
|
|
** Close a connection to shared-memory. Delete the underlying
|
|
** storage if deleteFlag is true.
|
|
**
|
|
** If there is no shared memory associated with the connection then this
|
|
** routine is a harmless no-op.
|
|
*/
|
|
static int unixShmUnmap(
|
|
sqlite3_file *fd, /* The underlying database file */
|
|
int deleteFlag /* Delete shared-memory if true */
|
|
){
|
|
unixShm *p; /* The connection to be closed */
|
|
unixShmNode *pShmNode; /* The underlying shared-memory file */
|
|
unixShm **pp; /* For looping over sibling connections */
|
|
unixFile *pDbFd; /* The underlying database file */
|
|
|
|
pDbFd = (unixFile*)fd;
|
|
p = pDbFd->pShm;
|
|
if( p==0 ) return SQLITE_OK;
|
|
pShmNode = p->pShmNode;
|
|
|
|
assert( pShmNode==pDbFd->pInode->pShmNode );
|
|
assert( pShmNode->pInode==pDbFd->pInode );
|
|
|
|
/* Remove connection p from the set of connections associated
|
|
** with pShmNode */
|
|
sqlite3_mutex_enter(pShmNode->pShmMutex);
|
|
for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
|
|
*pp = p->pNext;
|
|
|
|
/* Free the connection p */
|
|
sqlite3_free(p);
|
|
pDbFd->pShm = 0;
|
|
sqlite3_mutex_leave(pShmNode->pShmMutex);
|
|
|
|
/* If pShmNode->nRef has reached 0, then close the underlying
|
|
** shared-memory file, too */
|
|
assert( unixFileMutexNotheld(pDbFd) );
|
|
unixEnterMutex();
|
|
assert( pShmNode->nRef>0 );
|
|
pShmNode->nRef--;
|
|
if( pShmNode->nRef==0 ){
|
|
if( deleteFlag && pShmNode->hShm>=0 ){
|
|
osUnlink(pShmNode->zFilename);
|
|
}
|
|
unixShmPurge(pDbFd);
|
|
}
|
|
unixLeaveMutex();
|
|
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
|
|
#else
|
|
# define unixShmMap 0
|
|
# define unixShmLock 0
|
|
# define unixShmBarrier 0
|
|
# define unixShmUnmap 0
|
|
#endif /* #ifndef SQLITE_OMIT_WAL */
|
|
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
/*
|
|
** If it is currently memory mapped, unmap file pFd.
|
|
*/
|
|
static void unixUnmapfile(unixFile *pFd){
|
|
assert( pFd->nFetchOut==0 );
|
|
if( pFd->pMapRegion ){
|
|
osMunmap(pFd->pMapRegion, pFd->mmapSizeActual);
|
|
pFd->pMapRegion = 0;
|
|
pFd->mmapSize = 0;
|
|
pFd->mmapSizeActual = 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Attempt to set the size of the memory mapping maintained by file
|
|
** descriptor pFd to nNew bytes. Any existing mapping is discarded.
|
|
**
|
|
** If successful, this function sets the following variables:
|
|
**
|
|
** unixFile.pMapRegion
|
|
** unixFile.mmapSize
|
|
** unixFile.mmapSizeActual
|
|
**
|
|
** If unsuccessful, an error message is logged via sqlite3_log() and
|
|
** the three variables above are zeroed. In this case SQLite should
|
|
** continue accessing the database using the xRead() and xWrite()
|
|
** methods.
|
|
*/
|
|
static void unixRemapfile(
|
|
unixFile *pFd, /* File descriptor object */
|
|
i64 nNew /* Required mapping size */
|
|
){
|
|
const char *zErr = "mmap";
|
|
int h = pFd->h; /* File descriptor open on db file */
|
|
u8 *pOrig = (u8 *)pFd->pMapRegion; /* Pointer to current file mapping */
|
|
i64 nOrig = pFd->mmapSizeActual; /* Size of pOrig region in bytes */
|
|
u8 *pNew = 0; /* Location of new mapping */
|
|
int flags = PROT_READ; /* Flags to pass to mmap() */
|
|
|
|
assert( pFd->nFetchOut==0 );
|
|
assert( nNew>pFd->mmapSize );
|
|
assert( nNew<=pFd->mmapSizeMax );
|
|
assert( nNew>0 );
|
|
assert( pFd->mmapSizeActual>=pFd->mmapSize );
|
|
assert( MAP_FAILED!=0 );
|
|
|
|
#ifdef SQLITE_MMAP_READWRITE
|
|
if( (pFd->ctrlFlags & UNIXFILE_RDONLY)==0 ) flags |= PROT_WRITE;
|
|
#endif
|
|
|
|
if( pOrig ){
|
|
#if HAVE_MREMAP
|
|
i64 nReuse = pFd->mmapSize;
|
|
#else
|
|
const int szSyspage = osGetpagesize();
|
|
i64 nReuse = (pFd->mmapSize & ~(szSyspage-1));
|
|
#endif
|
|
u8 *pReq = &pOrig[nReuse];
|
|
|
|
/* Unmap any pages of the existing mapping that cannot be reused. */
|
|
if( nReuse!=nOrig ){
|
|
osMunmap(pReq, nOrig-nReuse);
|
|
}
|
|
|
|
#if HAVE_MREMAP
|
|
pNew = osMremap(pOrig, nReuse, nNew, MREMAP_MAYMOVE);
|
|
zErr = "mremap";
|
|
#else
|
|
pNew = osMmap(pReq, nNew-nReuse, flags, MAP_SHARED, h, nReuse);
|
|
if( pNew!=MAP_FAILED ){
|
|
if( pNew!=pReq ){
|
|
osMunmap(pNew, nNew - nReuse);
|
|
pNew = 0;
|
|
}else{
|
|
pNew = pOrig;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* The attempt to extend the existing mapping failed. Free it. */
|
|
if( pNew==MAP_FAILED || pNew==0 ){
|
|
osMunmap(pOrig, nReuse);
|
|
}
|
|
}
|
|
|
|
/* If pNew is still NULL, try to create an entirely new mapping. */
|
|
if( pNew==0 ){
|
|
pNew = osMmap(0, nNew, flags, MAP_SHARED, h, 0);
|
|
}
|
|
|
|
if( pNew==MAP_FAILED ){
|
|
pNew = 0;
|
|
nNew = 0;
|
|
unixLogError(SQLITE_OK, zErr, pFd->zPath);
|
|
|
|
/* If the mmap() above failed, assume that all subsequent mmap() calls
|
|
** will probably fail too. Fall back to using xRead/xWrite exclusively
|
|
** in this case. */
|
|
pFd->mmapSizeMax = 0;
|
|
}
|
|
pFd->pMapRegion = (void *)pNew;
|
|
pFd->mmapSize = pFd->mmapSizeActual = nNew;
|
|
}
|
|
|
|
/*
|
|
** Memory map or remap the file opened by file-descriptor pFd (if the file
|
|
** is already mapped, the existing mapping is replaced by the new). Or, if
|
|
** there already exists a mapping for this file, and there are still
|
|
** outstanding xFetch() references to it, this function is a no-op.
|
|
**
|
|
** If parameter nByte is non-negative, then it is the requested size of
|
|
** the mapping to create. Otherwise, if nByte is less than zero, then the
|
|
** requested size is the size of the file on disk. The actual size of the
|
|
** created mapping is either the requested size or the value configured
|
|
** using SQLITE_FCNTL_MMAP_LIMIT, whichever is smaller.
|
|
**
|
|
** SQLITE_OK is returned if no error occurs (even if the mapping is not
|
|
** recreated as a result of outstanding references) or an SQLite error
|
|
** code otherwise.
|
|
*/
|
|
static int unixMapfile(unixFile *pFd, i64 nMap){
|
|
assert( nMap>=0 || pFd->nFetchOut==0 );
|
|
assert( nMap>0 || (pFd->mmapSize==0 && pFd->pMapRegion==0) );
|
|
if( pFd->nFetchOut>0 ) return SQLITE_OK;
|
|
|
|
if( nMap<0 ){
|
|
struct stat statbuf; /* Low-level file information */
|
|
if( osFstat(pFd->h, &statbuf) ){
|
|
return SQLITE_IOERR_FSTAT;
|
|
}
|
|
nMap = statbuf.st_size;
|
|
}
|
|
if( nMap>pFd->mmapSizeMax ){
|
|
nMap = pFd->mmapSizeMax;
|
|
}
|
|
|
|
assert( nMap>0 || (pFd->mmapSize==0 && pFd->pMapRegion==0) );
|
|
if( nMap!=pFd->mmapSize ){
|
|
unixRemapfile(pFd, nMap);
|
|
}
|
|
|
|
return SQLITE_OK;
|
|
}
|
|
#endif /* SQLITE_MAX_MMAP_SIZE>0 */
|
|
|
|
/*
|
|
** If possible, return a pointer to a mapping of file fd starting at offset
|
|
** iOff. The mapping must be valid for at least nAmt bytes.
|
|
**
|
|
** If such a pointer can be obtained, store it in *pp and return SQLITE_OK.
|
|
** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK.
|
|
** Finally, if an error does occur, return an SQLite error code. The final
|
|
** value of *pp is undefined in this case.
|
|
**
|
|
** If this function does return a pointer, the caller must eventually
|
|
** release the reference by calling unixUnfetch().
|
|
*/
|
|
static int unixFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
unixFile *pFd = (unixFile *)fd; /* The underlying database file */
|
|
#endif
|
|
*pp = 0;
|
|
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
if( pFd->mmapSizeMax>0 ){
|
|
/* Ensure that there is always at least a 256 byte buffer of addressable
|
|
** memory following the returned page. If the database is corrupt,
|
|
** SQLite may overread the page slightly (in practice only a few bytes,
|
|
** but 256 is safe, round, number). */
|
|
const int nEofBuffer = 256;
|
|
if( pFd->pMapRegion==0 ){
|
|
int rc = unixMapfile(pFd, -1);
|
|
if( rc!=SQLITE_OK ) return rc;
|
|
}
|
|
if( pFd->mmapSize >= (iOff+nAmt+nEofBuffer) ){
|
|
*pp = &((u8 *)pFd->pMapRegion)[iOff];
|
|
pFd->nFetchOut++;
|
|
}
|
|
}
|
|
#endif
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** If the third argument is non-NULL, then this function releases a
|
|
** reference obtained by an earlier call to unixFetch(). The second
|
|
** argument passed to this function must be the same as the corresponding
|
|
** argument that was passed to the unixFetch() invocation.
|
|
**
|
|
** Or, if the third argument is NULL, then this function is being called
|
|
** to inform the VFS layer that, according to POSIX, any existing mapping
|
|
** may now be invalid and should be unmapped.
|
|
*/
|
|
static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
unixFile *pFd = (unixFile *)fd; /* The underlying database file */
|
|
UNUSED_PARAMETER(iOff);
|
|
|
|
/* If p==0 (unmap the entire file) then there must be no outstanding
|
|
** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
|
|
** then there must be at least one outstanding. */
|
|
assert( (p==0)==(pFd->nFetchOut==0) );
|
|
|
|
/* If p!=0, it must match the iOff value. */
|
|
assert( p==0 || p==&((u8 *)pFd->pMapRegion)[iOff] );
|
|
|
|
if( p ){
|
|
pFd->nFetchOut--;
|
|
}else{
|
|
unixUnmapfile(pFd);
|
|
}
|
|
|
|
assert( pFd->nFetchOut>=0 );
|
|
#else
|
|
UNUSED_PARAMETER(fd);
|
|
UNUSED_PARAMETER(p);
|
|
UNUSED_PARAMETER(iOff);
|
|
#endif
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Here ends the implementation of all sqlite3_file methods.
|
|
**
|
|
********************** End sqlite3_file Methods *******************************
|
|
******************************************************************************/
|
|
|
|
/*
|
|
** This division contains definitions of sqlite3_io_methods objects that
|
|
** implement various file locking strategies. It also contains definitions
|
|
** of "finder" functions. A finder-function is used to locate the appropriate
|
|
** sqlite3_io_methods object for a particular database file. The pAppData
|
|
** field of the sqlite3_vfs VFS objects are initialized to be pointers to
|
|
** the correct finder-function for that VFS.
|
|
**
|
|
** Most finder functions return a pointer to a fixed sqlite3_io_methods
|
|
** object. The only interesting finder-function is autolockIoFinder, which
|
|
** looks at the filesystem type and tries to guess the best locking
|
|
** strategy from that.
|
|
**
|
|
** For finder-function F, two objects are created:
|
|
**
|
|
** (1) The real finder-function named "FImpt()".
|
|
**
|
|
** (2) A constant pointer to this function named just "F".
|
|
**
|
|
**
|
|
** A pointer to the F pointer is used as the pAppData value for VFS
|
|
** objects. We have to do this instead of letting pAppData point
|
|
** directly at the finder-function since C90 rules prevent a void*
|
|
** from be cast into a function pointer.
|
|
**
|
|
**
|
|
** Each instance of this macro generates two objects:
|
|
**
|
|
** * A constant sqlite3_io_methods object call METHOD that has locking
|
|
** methods CLOSE, LOCK, UNLOCK, CKRESLOCK.
|
|
**
|
|
** * An I/O method finder function called FINDER that returns a pointer
|
|
** to the METHOD object in the previous bullet.
|
|
*/
|
|
#define IOMETHODS(FINDER,METHOD,VERSION,CLOSE,LOCK,UNLOCK,CKLOCK,SHMMAP) \
|
|
static const sqlite3_io_methods METHOD = { \
|
|
VERSION, /* iVersion */ \
|
|
CLOSE, /* xClose */ \
|
|
unixRead, /* xRead */ \
|
|
unixWrite, /* xWrite */ \
|
|
unixTruncate, /* xTruncate */ \
|
|
unixSync, /* xSync */ \
|
|
unixFileSize, /* xFileSize */ \
|
|
LOCK, /* xLock */ \
|
|
UNLOCK, /* xUnlock */ \
|
|
CKLOCK, /* xCheckReservedLock */ \
|
|
unixFileControl, /* xFileControl */ \
|
|
unixSectorSize, /* xSectorSize */ \
|
|
unixDeviceCharacteristics, /* xDeviceCapabilities */ \
|
|
SHMMAP, /* xShmMap */ \
|
|
unixShmLock, /* xShmLock */ \
|
|
unixShmBarrier, /* xShmBarrier */ \
|
|
unixShmUnmap, /* xShmUnmap */ \
|
|
unixFetch, /* xFetch */ \
|
|
unixUnfetch, /* xUnfetch */ \
|
|
}; \
|
|
static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){ \
|
|
UNUSED_PARAMETER(z); UNUSED_PARAMETER(p); \
|
|
return &METHOD; \
|
|
} \
|
|
static const sqlite3_io_methods *(*const FINDER)(const char*,unixFile *p) \
|
|
= FINDER##Impl;
|
|
|
|
/*
|
|
** Here are all of the sqlite3_io_methods objects for each of the
|
|
** locking strategies. Functions that return pointers to these methods
|
|
** are also created.
|
|
*/
|
|
IOMETHODS(
|
|
posixIoFinder, /* Finder function name */
|
|
posixIoMethods, /* sqlite3_io_methods object name */
|
|
3, /* shared memory and mmap are enabled */
|
|
unixClose, /* xClose method */
|
|
unixLock, /* xLock method */
|
|
unixUnlock, /* xUnlock method */
|
|
unixCheckReservedLock, /* xCheckReservedLock method */
|
|
unixShmMap /* xShmMap method */
|
|
)
|
|
IOMETHODS(
|
|
nolockIoFinder, /* Finder function name */
|
|
nolockIoMethods, /* sqlite3_io_methods object name */
|
|
3, /* shared memory and mmap are enabled */
|
|
nolockClose, /* xClose method */
|
|
nolockLock, /* xLock method */
|
|
nolockUnlock, /* xUnlock method */
|
|
nolockCheckReservedLock, /* xCheckReservedLock method */
|
|
0 /* xShmMap method */
|
|
)
|
|
IOMETHODS(
|
|
dotlockIoFinder, /* Finder function name */
|
|
dotlockIoMethods, /* sqlite3_io_methods object name */
|
|
1, /* shared memory is disabled */
|
|
dotlockClose, /* xClose method */
|
|
dotlockLock, /* xLock method */
|
|
dotlockUnlock, /* xUnlock method */
|
|
dotlockCheckReservedLock, /* xCheckReservedLock method */
|
|
0 /* xShmMap method */
|
|
)
|
|
|
|
#if SQLITE_ENABLE_LOCKING_STYLE
|
|
IOMETHODS(
|
|
flockIoFinder, /* Finder function name */
|
|
flockIoMethods, /* sqlite3_io_methods object name */
|
|
1, /* shared memory is disabled */
|
|
flockClose, /* xClose method */
|
|
flockLock, /* xLock method */
|
|
flockUnlock, /* xUnlock method */
|
|
flockCheckReservedLock, /* xCheckReservedLock method */
|
|
0 /* xShmMap method */
|
|
)
|
|
#endif
|
|
|
|
#if OS_VXWORKS
|
|
IOMETHODS(
|
|
semIoFinder, /* Finder function name */
|
|
semIoMethods, /* sqlite3_io_methods object name */
|
|
1, /* shared memory is disabled */
|
|
semXClose, /* xClose method */
|
|
semXLock, /* xLock method */
|
|
semXUnlock, /* xUnlock method */
|
|
semXCheckReservedLock, /* xCheckReservedLock method */
|
|
0 /* xShmMap method */
|
|
)
|
|
#endif
|
|
|
|
#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
|
|
IOMETHODS(
|
|
afpIoFinder, /* Finder function name */
|
|
afpIoMethods, /* sqlite3_io_methods object name */
|
|
1, /* shared memory is disabled */
|
|
afpClose, /* xClose method */
|
|
afpLock, /* xLock method */
|
|
afpUnlock, /* xUnlock method */
|
|
afpCheckReservedLock, /* xCheckReservedLock method */
|
|
0 /* xShmMap method */
|
|
)
|
|
#endif
|
|
|
|
/*
|
|
** The proxy locking method is a "super-method" in the sense that it
|
|
** opens secondary file descriptors for the conch and lock files and
|
|
** it uses proxy, dot-file, AFP, and flock() locking methods on those
|
|
** secondary files. For this reason, the division that implements
|
|
** proxy locking is located much further down in the file. But we need
|
|
** to go ahead and define the sqlite3_io_methods and finder function
|
|
** for proxy locking here. So we forward declare the I/O methods.
|
|
*/
|
|
#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
|
|
static int proxyClose(sqlite3_file*);
|
|
static int proxyLock(sqlite3_file*, int);
|
|
static int proxyUnlock(sqlite3_file*, int);
|
|
static int proxyCheckReservedLock(sqlite3_file*, int*);
|
|
IOMETHODS(
|
|
proxyIoFinder, /* Finder function name */
|
|
proxyIoMethods, /* sqlite3_io_methods object name */
|
|
1, /* shared memory is disabled */
|
|
proxyClose, /* xClose method */
|
|
proxyLock, /* xLock method */
|
|
proxyUnlock, /* xUnlock method */
|
|
proxyCheckReservedLock, /* xCheckReservedLock method */
|
|
0 /* xShmMap method */
|
|
)
|
|
#endif
|
|
|
|
/* nfs lockd on OSX 10.3+ doesn't clear write locks when a read lock is set */
|
|
#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
|
|
IOMETHODS(
|
|
nfsIoFinder, /* Finder function name */
|
|
nfsIoMethods, /* sqlite3_io_methods object name */
|
|
1, /* shared memory is disabled */
|
|
unixClose, /* xClose method */
|
|
unixLock, /* xLock method */
|
|
nfsUnlock, /* xUnlock method */
|
|
unixCheckReservedLock, /* xCheckReservedLock method */
|
|
0 /* xShmMap method */
|
|
)
|
|
#endif
|
|
|
|
#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
|
|
/*
|
|
** This "finder" function attempts to determine the best locking strategy
|
|
** for the database file "filePath". It then returns the sqlite3_io_methods
|
|
** object that implements that strategy.
|
|
**
|
|
** This is for MacOSX only.
|
|
*/
|
|
static const sqlite3_io_methods *autolockIoFinderImpl(
|
|
const char *filePath, /* name of the database file */
|
|
unixFile *pNew /* open file object for the database file */
|
|
){
|
|
static const struct Mapping {
|
|
const char *zFilesystem; /* Filesystem type name */
|
|
const sqlite3_io_methods *pMethods; /* Appropriate locking method */
|
|
} aMap[] = {
|
|
{ "hfs", &posixIoMethods },
|
|
{ "ufs", &posixIoMethods },
|
|
{ "afpfs", &afpIoMethods },
|
|
{ "smbfs", &afpIoMethods },
|
|
{ "webdav", &nolockIoMethods },
|
|
{ 0, 0 }
|
|
};
|
|
int i;
|
|
struct statfs fsInfo;
|
|
struct flock lockInfo;
|
|
|
|
if( !filePath ){
|
|
/* If filePath==NULL that means we are dealing with a transient file
|
|
** that does not need to be locked. */
|
|
return &nolockIoMethods;
|
|
}
|
|
if( statfs(filePath, &fsInfo) != -1 ){
|
|
if( fsInfo.f_flags & MNT_RDONLY ){
|
|
return &nolockIoMethods;
|
|
}
|
|
for(i=0; aMap[i].zFilesystem; i++){
|
|
if( strcmp(fsInfo.f_fstypename, aMap[i].zFilesystem)==0 ){
|
|
return aMap[i].pMethods;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Default case. Handles, amongst others, "nfs".
|
|
** Test byte-range lock using fcntl(). If the call succeeds,
|
|
** assume that the file-system supports POSIX style locks.
|
|
*/
|
|
lockInfo.l_len = 1;
|
|
lockInfo.l_start = 0;
|
|
lockInfo.l_whence = SEEK_SET;
|
|
lockInfo.l_type = F_RDLCK;
|
|
if( osFcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) {
|
|
if( strcmp(fsInfo.f_fstypename, "nfs")==0 ){
|
|
return &nfsIoMethods;
|
|
} else {
|
|
return &posixIoMethods;
|
|
}
|
|
}else{
|
|
return &dotlockIoMethods;
|
|
}
|
|
}
|
|
static const sqlite3_io_methods
|
|
*(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl;
|
|
|
|
#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
|
|
|
|
#if OS_VXWORKS
|
|
/*
|
|
** This "finder" function for VxWorks checks to see if posix advisory
|
|
** locking works. If it does, then that is what is used. If it does not
|
|
** work, then fallback to named semaphore locking.
|
|
*/
|
|
static const sqlite3_io_methods *vxworksIoFinderImpl(
|
|
const char *filePath, /* name of the database file */
|
|
unixFile *pNew /* the open file object */
|
|
){
|
|
struct flock lockInfo;
|
|
|
|
if( !filePath ){
|
|
/* If filePath==NULL that means we are dealing with a transient file
|
|
** that does not need to be locked. */
|
|
return &nolockIoMethods;
|
|
}
|
|
|
|
/* Test if fcntl() is supported and use POSIX style locks.
|
|
** Otherwise fall back to the named semaphore method.
|
|
*/
|
|
lockInfo.l_len = 1;
|
|
lockInfo.l_start = 0;
|
|
lockInfo.l_whence = SEEK_SET;
|
|
lockInfo.l_type = F_RDLCK;
|
|
if( osFcntl(pNew->h, F_GETLK, &lockInfo)!=-1 ) {
|
|
return &posixIoMethods;
|
|
}else{
|
|
return &semIoMethods;
|
|
}
|
|
}
|
|
static const sqlite3_io_methods
|
|
*(*const vxworksIoFinder)(const char*,unixFile*) = vxworksIoFinderImpl;
|
|
|
|
#endif /* OS_VXWORKS */
|
|
|
|
/*
|
|
** An abstract type for a pointer to an IO method finder function:
|
|
*/
|
|
typedef const sqlite3_io_methods *(*finder_type)(const char*,unixFile*);
|
|
|
|
|
|
/****************************************************************************
|
|
**************************** sqlite3_vfs methods ****************************
|
|
**
|
|
** This division contains the implementation of methods on the
|
|
** sqlite3_vfs object.
|
|
*/
|
|
|
|
/*
|
|
** Initialize the contents of the unixFile structure pointed to by pId.
|
|
*/
|
|
static int fillInUnixFile(
|
|
sqlite3_vfs *pVfs, /* Pointer to vfs object */
|
|
int h, /* Open file descriptor of file being opened */
|
|
sqlite3_file *pId, /* Write to the unixFile structure here */
|
|
const char *zFilename, /* Name of the file being opened */
|
|
int ctrlFlags /* Zero or more UNIXFILE_* values */
|
|
){
|
|
const sqlite3_io_methods *pLockingStyle;
|
|
unixFile *pNew = (unixFile *)pId;
|
|
int rc = SQLITE_OK;
|
|
|
|
assert( pNew->pInode==NULL );
|
|
|
|
/* No locking occurs in temporary files */
|
|
assert( zFilename!=0 || (ctrlFlags & UNIXFILE_NOLOCK)!=0 );
|
|
|
|
OSTRACE(("OPEN %-3d %s\n", h, zFilename));
|
|
pNew->h = h;
|
|
pNew->pVfs = pVfs;
|
|
pNew->zPath = zFilename;
|
|
pNew->ctrlFlags = (u8)ctrlFlags;
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
pNew->mmapSizeMax = sqlite3GlobalConfig.szMmap;
|
|
#endif
|
|
if( sqlite3_uri_boolean(((ctrlFlags & UNIXFILE_URI) ? zFilename : 0),
|
|
"psow", SQLITE_POWERSAFE_OVERWRITE) ){
|
|
pNew->ctrlFlags |= UNIXFILE_PSOW;
|
|
}
|
|
if( strcmp(pVfs->zName,"unix-excl")==0 ){
|
|
pNew->ctrlFlags |= UNIXFILE_EXCL;
|
|
}
|
|
|
|
#if OS_VXWORKS
|
|
pNew->pId = vxworksFindFileId(zFilename);
|
|
if( pNew->pId==0 ){
|
|
ctrlFlags |= UNIXFILE_NOLOCK;
|
|
rc = SQLITE_NOMEM_BKPT;
|
|
}
|
|
#endif
|
|
|
|
if( ctrlFlags & UNIXFILE_NOLOCK ){
|
|
pLockingStyle = &nolockIoMethods;
|
|
}else{
|
|
pLockingStyle = (**(finder_type*)pVfs->pAppData)(zFilename, pNew);
|
|
#if SQLITE_ENABLE_LOCKING_STYLE
|
|
/* Cache zFilename in the locking context (AFP and dotlock override) for
|
|
** proxyLock activation is possible (remote proxy is based on db name)
|
|
** zFilename remains valid until file is closed, to support */
|
|
pNew->lockingContext = (void*)zFilename;
|
|
#endif
|
|
}
|
|
|
|
if( pLockingStyle == &posixIoMethods
|
|
#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
|
|
|| pLockingStyle == &nfsIoMethods
|
|
#endif
|
|
){
|
|
unixEnterMutex();
|
|
rc = findInodeInfo(pNew, &pNew->pInode);
|
|
if( rc!=SQLITE_OK ){
|
|
/* If an error occurred in findInodeInfo(), close the file descriptor
|
|
** immediately, before releasing the mutex. findInodeInfo() may fail
|
|
** in two scenarios:
|
|
**
|
|
** (a) A call to fstat() failed.
|
|
** (b) A malloc failed.
|
|
**
|
|
** Scenario (b) may only occur if the process is holding no other
|
|
** file descriptors open on the same file. If there were other file
|
|
** descriptors on this file, then no malloc would be required by
|
|
** findInodeInfo(). If this is the case, it is quite safe to close
|
|
** handle h - as it is guaranteed that no posix locks will be released
|
|
** by doing so.
|
|
**
|
|
** If scenario (a) caused the error then things are not so safe. The
|
|
** implicit assumption here is that if fstat() fails, things are in
|
|
** such bad shape that dropping a lock or two doesn't matter much.
|
|
*/
|
|
robust_close(pNew, h, __LINE__);
|
|
h = -1;
|
|
}
|
|
unixLeaveMutex();
|
|
}
|
|
|
|
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
|
|
else if( pLockingStyle == &afpIoMethods ){
|
|
/* AFP locking uses the file path so it needs to be included in
|
|
** the afpLockingContext.
|
|
*/
|
|
afpLockingContext *pCtx;
|
|
pNew->lockingContext = pCtx = sqlite3_malloc64( sizeof(*pCtx) );
|
|
if( pCtx==0 ){
|
|
rc = SQLITE_NOMEM_BKPT;
|
|
}else{
|
|
/* NB: zFilename exists and remains valid until the file is closed
|
|
** according to requirement F11141. So we do not need to make a
|
|
** copy of the filename. */
|
|
pCtx->dbPath = zFilename;
|
|
pCtx->reserved = 0;
|
|
srandomdev();
|
|
unixEnterMutex();
|
|
rc = findInodeInfo(pNew, &pNew->pInode);
|
|
if( rc!=SQLITE_OK ){
|
|
sqlite3_free(pNew->lockingContext);
|
|
robust_close(pNew, h, __LINE__);
|
|
h = -1;
|
|
}
|
|
unixLeaveMutex();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
else if( pLockingStyle == &dotlockIoMethods ){
|
|
/* Dotfile locking uses the file path so it needs to be included in
|
|
** the dotlockLockingContext
|
|
*/
|
|
char *zLockFile;
|
|
int nFilename;
|
|
assert( zFilename!=0 );
|
|
nFilename = (int)strlen(zFilename) + 6;
|
|
zLockFile = (char *)sqlite3_malloc64(nFilename);
|
|
if( zLockFile==0 ){
|
|
rc = SQLITE_NOMEM_BKPT;
|
|
}else{
|
|
sqlite3_snprintf(nFilename, zLockFile, "%s" DOTLOCK_SUFFIX, zFilename);
|
|
}
|
|
pNew->lockingContext = zLockFile;
|
|
}
|
|
|
|
#if OS_VXWORKS
|
|
else if( pLockingStyle == &semIoMethods ){
|
|
/* Named semaphore locking uses the file path so it needs to be
|
|
** included in the semLockingContext
|
|
*/
|
|
unixEnterMutex();
|
|
rc = findInodeInfo(pNew, &pNew->pInode);
|
|
if( (rc==SQLITE_OK) && (pNew->pInode->pSem==NULL) ){
|
|
char *zSemName = pNew->pInode->aSemName;
|
|
int n;
|
|
sqlite3_snprintf(MAX_PATHNAME, zSemName, "/%s.sem",
|
|
pNew->pId->zCanonicalName);
|
|
for( n=1; zSemName[n]; n++ )
|
|
if( zSemName[n]=='/' ) zSemName[n] = '_';
|
|
pNew->pInode->pSem = sem_open(zSemName, O_CREAT, 0666, 1);
|
|
if( pNew->pInode->pSem == SEM_FAILED ){
|
|
rc = SQLITE_NOMEM_BKPT;
|
|
pNew->pInode->aSemName[0] = '\0';
|
|
}
|
|
}
|
|
unixLeaveMutex();
|
|
}
|
|
#endif
|
|
|
|
storeLastErrno(pNew, 0);
|
|
#if OS_VXWORKS
|
|
if( rc!=SQLITE_OK ){
|
|
if( h>=0 ) robust_close(pNew, h, __LINE__);
|
|
h = -1;
|
|
osUnlink(zFilename);
|
|
pNew->ctrlFlags |= UNIXFILE_DELETE;
|
|
}
|
|
#endif
|
|
if( rc!=SQLITE_OK ){
|
|
if( h>=0 ) robust_close(pNew, h, __LINE__);
|
|
}else{
|
|
pId->pMethods = pLockingStyle;
|
|
OpenCounter(+1);
|
|
verifyDbFile(pNew);
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Directories to consider for temp files.
|
|
*/
|
|
static const char *azTempDirs[] = {
|
|
0,
|
|
0,
|
|
"/var/tmp",
|
|
"/usr/tmp",
|
|
"/tmp",
|
|
"."
|
|
};
|
|
|
|
/*
|
|
** Initialize first two members of azTempDirs[] array.
|
|
*/
|
|
static void unixTempFileInit(void){
|
|
azTempDirs[0] = getenv("SQLITE_TMPDIR");
|
|
azTempDirs[1] = getenv("TMPDIR");
|
|
}
|
|
|
|
/*
|
|
** Return the name of a directory in which to put temporary files.
|
|
** If no suitable temporary file directory can be found, return NULL.
|
|
*/
|
|
static const char *unixTempFileDir(void){
|
|
unsigned int i = 0;
|
|
struct stat buf;
|
|
const char *zDir = sqlite3_temp_directory;
|
|
|
|
while(1){
|
|
if( zDir!=0
|
|
&& osStat(zDir, &buf)==0
|
|
&& S_ISDIR(buf.st_mode)
|
|
&& osAccess(zDir, 03)==0
|
|
){
|
|
return zDir;
|
|
}
|
|
if( i>=sizeof(azTempDirs)/sizeof(azTempDirs[0]) ) break;
|
|
zDir = azTempDirs[i++];
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
** Create a temporary file name in zBuf. zBuf must be allocated
|
|
** by the calling process and must be big enough to hold at least
|
|
** pVfs->mxPathname bytes.
|
|
*/
|
|
static int unixGetTempname(int nBuf, char *zBuf){
|
|
const char *zDir;
|
|
int iLimit = 0;
|
|
int rc = SQLITE_OK;
|
|
|
|
/* It's odd to simulate an io-error here, but really this is just
|
|
** using the io-error infrastructure to test that SQLite handles this
|
|
** function failing.
|
|
*/
|
|
zBuf[0] = 0;
|
|
SimulateIOError( return SQLITE_IOERR );
|
|
|
|
sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
|
|
zDir = unixTempFileDir();
|
|
if( zDir==0 ){
|
|
rc = SQLITE_IOERR_GETTEMPPATH;
|
|
}else{
|
|
do{
|
|
u64 r;
|
|
sqlite3_randomness(sizeof(r), &r);
|
|
assert( nBuf>2 );
|
|
zBuf[nBuf-2] = 0;
|
|
sqlite3_snprintf(nBuf, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX"%llx%c",
|
|
zDir, r, 0);
|
|
if( zBuf[nBuf-2]!=0 || (iLimit++)>10 ){
|
|
rc = SQLITE_ERROR;
|
|
break;
|
|
}
|
|
}while( osAccess(zBuf,0)==0 );
|
|
}
|
|
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
|
|
return rc;
|
|
}
|
|
|
|
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
|
|
/*
|
|
** Routine to transform a unixFile into a proxy-locking unixFile.
|
|
** Implementation in the proxy-lock division, but used by unixOpen()
|
|
** if SQLITE_PREFER_PROXY_LOCKING is defined.
|
|
*/
|
|
static int proxyTransformUnixFile(unixFile*, const char*);
|
|
#endif
|
|
|
|
/*
|
|
** Search for an unused file descriptor that was opened on the database
|
|
** file (not a journal or super-journal file) identified by pathname
|
|
** zPath with SQLITE_OPEN_XXX flags matching those passed as the second
|
|
** argument to this function.
|
|
**
|
|
** Such a file descriptor may exist if a database connection was closed
|
|
** but the associated file descriptor could not be closed because some
|
|
** other file descriptor open on the same file is holding a file-lock.
|
|
** Refer to comments in the unixClose() function and the lengthy comment
|
|
** describing "Posix Advisory Locking" at the start of this file for
|
|
** further details. Also, ticket #4018.
|
|
**
|
|
** If a suitable file descriptor is found, then it is returned. If no
|
|
** such file descriptor is located, -1 is returned.
|
|
*/
|
|
static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
|
|
UnixUnusedFd *pUnused = 0;
|
|
|
|
/* Do not search for an unused file descriptor on vxworks. Not because
|
|
** vxworks would not benefit from the change (it might, we're not sure),
|
|
** but because no way to test it is currently available. It is better
|
|
** not to risk breaking vxworks support for the sake of such an obscure
|
|
** feature. */
|
|
#if !OS_VXWORKS
|
|
struct stat sStat; /* Results of stat() call */
|
|
|
|
unixEnterMutex();
|
|
|
|
/* A stat() call may fail for various reasons. If this happens, it is
|
|
** almost certain that an open() call on the same path will also fail.
|
|
** For this reason, if an error occurs in the stat() call here, it is
|
|
** ignored and -1 is returned. The caller will try to open a new file
|
|
** descriptor on the same path, fail, and return an error to SQLite.
|
|
**
|
|
** Even if a subsequent open() call does succeed, the consequences of
|
|
** not searching for a reusable file descriptor are not dire. */
|
|
if( inodeList!=0 && 0==osStat(zPath, &sStat) ){
|
|
unixInodeInfo *pInode;
|
|
|
|
pInode = inodeList;
|
|
while( pInode && (pInode->fileId.dev!=sStat.st_dev
|
|
|| pInode->fileId.ino!=(u64)sStat.st_ino) ){
|
|
pInode = pInode->pNext;
|
|
}
|
|
if( pInode ){
|
|
UnixUnusedFd **pp;
|
|
assert( sqlite3_mutex_notheld(pInode->pLockMutex) );
|
|
sqlite3_mutex_enter(pInode->pLockMutex);
|
|
flags &= (SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE);
|
|
for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext));
|
|
pUnused = *pp;
|
|
if( pUnused ){
|
|
*pp = pUnused->pNext;
|
|
}
|
|
sqlite3_mutex_leave(pInode->pLockMutex);
|
|
}
|
|
}
|
|
unixLeaveMutex();
|
|
#endif /* if !OS_VXWORKS */
|
|
return pUnused;
|
|
}
|
|
|
|
/*
|
|
** Find the mode, uid and gid of file zFile.
|
|
*/
|
|
static int getFileMode(
|
|
const char *zFile, /* File name */
|
|
mode_t *pMode, /* OUT: Permissions of zFile */
|
|
uid_t *pUid, /* OUT: uid of zFile. */
|
|
gid_t *pGid /* OUT: gid of zFile. */
|
|
){
|
|
struct stat sStat; /* Output of stat() on database file */
|
|
int rc = SQLITE_OK;
|
|
if( 0==osStat(zFile, &sStat) ){
|
|
*pMode = sStat.st_mode & 0777;
|
|
*pUid = sStat.st_uid;
|
|
*pGid = sStat.st_gid;
|
|
}else{
|
|
rc = SQLITE_IOERR_FSTAT;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** This function is called by unixOpen() to determine the unix permissions
|
|
** to create new files with. If no error occurs, then SQLITE_OK is returned
|
|
** and a value suitable for passing as the third argument to open(2) is
|
|
** written to *pMode. If an IO error occurs, an SQLite error code is
|
|
** returned and the value of *pMode is not modified.
|
|
**
|
|
** In most cases, this routine sets *pMode to 0, which will become
|
|
** an indication to robust_open() to create the file using
|
|
** SQLITE_DEFAULT_FILE_PERMISSIONS adjusted by the umask.
|
|
** But if the file being opened is a WAL or regular journal file, then
|
|
** this function queries the file-system for the permissions on the
|
|
** corresponding database file and sets *pMode to this value. Whenever
|
|
** possible, WAL and journal files are created using the same permissions
|
|
** as the associated database file.
|
|
**
|
|
** If the SQLITE_ENABLE_8_3_NAMES option is enabled, then the
|
|
** original filename is unavailable. But 8_3_NAMES is only used for
|
|
** FAT filesystems and permissions do not matter there, so just use
|
|
** the default permissions. In 8_3_NAMES mode, leave *pMode set to zero.
|
|
*/
|
|
static int findCreateFileMode(
|
|
const char *zPath, /* Path of file (possibly) being created */
|
|
int flags, /* Flags passed as 4th argument to xOpen() */
|
|
mode_t *pMode, /* OUT: Permissions to open file with */
|
|
uid_t *pUid, /* OUT: uid to set on the file */
|
|
gid_t *pGid /* OUT: gid to set on the file */
|
|
){
|
|
int rc = SQLITE_OK; /* Return Code */
|
|
*pMode = 0;
|
|
*pUid = 0;
|
|
*pGid = 0;
|
|
if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
|
|
char zDb[MAX_PATHNAME+1]; /* Database file path */
|
|
int nDb; /* Number of valid bytes in zDb */
|
|
|
|
/* zPath is a path to a WAL or journal file. The following block derives
|
|
** the path to the associated database file from zPath. This block handles
|
|
** the following naming conventions:
|
|
**
|
|
** "<path to db>-journal"
|
|
** "<path to db>-wal"
|
|
** "<path to db>-journalNN"
|
|
** "<path to db>-walNN"
|
|
**
|
|
** where NN is a decimal number. The NN naming schemes are
|
|
** used by the test_multiplex.c module.
|
|
**
|
|
** In normal operation, the journal file name will always contain
|
|
** a '-' character. However in 8+3 filename mode, or if a corrupt
|
|
** rollback journal specifies a super-journal with a goofy name, then
|
|
** the '-' might be missing or the '-' might be the first character in
|
|
** the filename. In that case, just return SQLITE_OK with *pMode==0.
|
|
*/
|
|
nDb = sqlite3Strlen30(zPath) - 1;
|
|
while( nDb>0 && zPath[nDb]!='.' ){
|
|
if( zPath[nDb]=='-' ){
|
|
memcpy(zDb, zPath, nDb);
|
|
zDb[nDb] = '\0';
|
|
rc = getFileMode(zDb, pMode, pUid, pGid);
|
|
break;
|
|
}
|
|
nDb--;
|
|
}
|
|
}else if( flags & SQLITE_OPEN_DELETEONCLOSE ){
|
|
*pMode = 0600;
|
|
}else if( flags & SQLITE_OPEN_URI ){
|
|
/* If this is a main database file and the file was opened using a URI
|
|
** filename, check for the "modeof" parameter. If present, interpret
|
|
** its value as a filename and try to copy the mode, uid and gid from
|
|
** that file. */
|
|
const char *z = sqlite3_uri_parameter(zPath, "modeof");
|
|
if( z ){
|
|
rc = getFileMode(z, pMode, pUid, pGid);
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Open the file zPath.
|
|
**
|
|
** Previously, the SQLite OS layer used three functions in place of this
|
|
** one:
|
|
**
|
|
** sqlite3OsOpenReadWrite();
|
|
** sqlite3OsOpenReadOnly();
|
|
** sqlite3OsOpenExclusive();
|
|
**
|
|
** These calls correspond to the following combinations of flags:
|
|
**
|
|
** ReadWrite() -> (READWRITE | CREATE)
|
|
** ReadOnly() -> (READONLY)
|
|
** OpenExclusive() -> (READWRITE | CREATE | EXCLUSIVE)
|
|
**
|
|
** The old OpenExclusive() accepted a boolean argument - "delFlag". If
|
|
** true, the file was configured to be automatically deleted when the
|
|
** file handle closed. To achieve the same effect using this new
|
|
** interface, add the DELETEONCLOSE flag to those specified above for
|
|
** OpenExclusive().
|
|
*/
|
|
static int unixOpen(
|
|
sqlite3_vfs *pVfs, /* The VFS for which this is the xOpen method */
|
|
const char *zPath, /* Pathname of file to be opened */
|
|
sqlite3_file *pFile, /* The file descriptor to be filled in */
|
|
int flags, /* Input flags to control the opening */
|
|
int *pOutFlags /* Output flags returned to SQLite core */
|
|
){
|
|
unixFile *p = (unixFile *)pFile;
|
|
int fd = -1; /* File descriptor returned by open() */
|
|
int openFlags = 0; /* Flags to pass to open() */
|
|
int eType = flags&0x0FFF00; /* Type of file to open */
|
|
int noLock; /* True to omit locking primitives */
|
|
int rc = SQLITE_OK; /* Function Return Code */
|
|
int ctrlFlags = 0; /* UNIXFILE_* flags */
|
|
|
|
int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
|
|
int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
|
|
int isCreate = (flags & SQLITE_OPEN_CREATE);
|
|
int isReadonly = (flags & SQLITE_OPEN_READONLY);
|
|
int isReadWrite = (flags & SQLITE_OPEN_READWRITE);
|
|
#if SQLITE_ENABLE_LOCKING_STYLE
|
|
int isAutoProxy = (flags & SQLITE_OPEN_AUTOPROXY);
|
|
#endif
|
|
#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
|
|
struct statfs fsInfo;
|
|
#endif
|
|
|
|
/* If creating a super- or main-file journal, this function will open
|
|
** a file-descriptor on the directory too. The first time unixSync()
|
|
** is called the directory file descriptor will be fsync()ed and close()d.
|
|
*/
|
|
int isNewJrnl = (isCreate && (
|
|
eType==SQLITE_OPEN_SUPER_JOURNAL
|
|
|| eType==SQLITE_OPEN_MAIN_JOURNAL
|
|
|| eType==SQLITE_OPEN_WAL
|
|
));
|
|
|
|
/* If argument zPath is a NULL pointer, this function is required to open
|
|
** a temporary file. Use this buffer to store the file name in.
|
|
*/
|
|
char zTmpname[MAX_PATHNAME+2];
|
|
const char *zName = zPath;
|
|
|
|
/* Check the following statements are true:
|
|
**
|
|
** (a) Exactly one of the READWRITE and READONLY flags must be set, and
|
|
** (b) if CREATE is set, then READWRITE must also be set, and
|
|
** (c) if EXCLUSIVE is set, then CREATE must also be set.
|
|
** (d) if DELETEONCLOSE is set, then CREATE must also be set.
|
|
*/
|
|
assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
|
|
assert(isCreate==0 || isReadWrite);
|
|
assert(isExclusive==0 || isCreate);
|
|
assert(isDelete==0 || isCreate);
|
|
|
|
/* The main DB, main journal, WAL file and super-journal are never
|
|
** automatically deleted. Nor are they ever temporary files. */
|
|
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
|
|
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
|
|
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_SUPER_JOURNAL );
|
|
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
|
|
|
|
/* Assert that the upper layer has set one of the "file-type" flags. */
|
|
assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
|
|
|| eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
|
|
|| eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_SUPER_JOURNAL
|
|
|| eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
|
|
);
|
|
|
|
/* Detect a pid change and reset the PRNG. There is a race condition
|
|
** here such that two or more threads all trying to open databases at
|
|
** the same instant might all reset the PRNG. But multiple resets
|
|
** are harmless.
|
|
*/
|
|
if( randomnessPid!=osGetpid(0) ){
|
|
randomnessPid = osGetpid(0);
|
|
sqlite3_randomness(0,0);
|
|
}
|
|
memset(p, 0, sizeof(unixFile));
|
|
|
|
#ifdef SQLITE_ASSERT_NO_FILES
|
|
/* Applications that never read or write a persistent disk files */
|
|
assert( zName==0 );
|
|
#endif
|
|
|
|
if( eType==SQLITE_OPEN_MAIN_DB ){
|
|
UnixUnusedFd *pUnused;
|
|
pUnused = findReusableFd(zName, flags);
|
|
if( pUnused ){
|
|
fd = pUnused->fd;
|
|
}else{
|
|
pUnused = sqlite3_malloc64(sizeof(*pUnused));
|
|
if( !pUnused ){
|
|
return SQLITE_NOMEM_BKPT;
|
|
}
|
|
}
|
|
p->pPreallocatedUnused = pUnused;
|
|
|
|
/* Database filenames are double-zero terminated if they are not
|
|
** URIs with parameters. Hence, they can always be passed into
|
|
** sqlite3_uri_parameter(). */
|
|
assert( (flags & SQLITE_OPEN_URI) || zName[strlen(zName)+1]==0 );
|
|
|
|
}else if( !zName ){
|
|
/* If zName is NULL, the upper layer is requesting a temp file. */
|
|
assert(isDelete && !isNewJrnl);
|
|
rc = unixGetTempname(pVfs->mxPathname, zTmpname);
|
|
if( rc!=SQLITE_OK ){
|
|
return rc;
|
|
}
|
|
zName = zTmpname;
|
|
|
|
/* Generated temporary filenames are always double-zero terminated
|
|
** for use by sqlite3_uri_parameter(). */
|
|
assert( zName[strlen(zName)+1]==0 );
|
|
}
|
|
|
|
/* Determine the value of the flags parameter passed to POSIX function
|
|
** open(). These must be calculated even if open() is not called, as
|
|
** they may be stored as part of the file handle and used by the
|
|
** 'conch file' locking functions later on. */
|
|
if( isReadonly ) openFlags |= O_RDONLY;
|
|
if( isReadWrite ) openFlags |= O_RDWR;
|
|
if( isCreate ) openFlags |= O_CREAT;
|
|
if( isExclusive ) openFlags |= (O_EXCL|O_NOFOLLOW);
|
|
openFlags |= (O_LARGEFILE|O_BINARY|O_NOFOLLOW);
|
|
|
|
if( fd<0 ){
|
|
mode_t openMode; /* Permissions to create file with */
|
|
uid_t uid; /* Userid for the file */
|
|
gid_t gid; /* Groupid for the file */
|
|
rc = findCreateFileMode(zName, flags, &openMode, &uid, &gid);
|
|
if( rc!=SQLITE_OK ){
|
|
assert( !p->pPreallocatedUnused );
|
|
assert( eType==SQLITE_OPEN_WAL || eType==SQLITE_OPEN_MAIN_JOURNAL );
|
|
return rc;
|
|
}
|
|
fd = robust_open(zName, openFlags, openMode);
|
|
OSTRACE(("OPENX %-3d %s 0%o\n", fd, zName, openFlags));
|
|
assert( !isExclusive || (openFlags & O_CREAT)!=0 );
|
|
if( fd<0 ){
|
|
if( isNewJrnl && errno==EACCES && osAccess(zName, F_OK) ){
|
|
/* If unable to create a journal because the directory is not
|
|
** writable, change the error code to indicate that. */
|
|
rc = SQLITE_READONLY_DIRECTORY;
|
|
}else if( errno!=EISDIR && isReadWrite ){
|
|
/* Failed to open the file for read/write access. Try read-only. */
|
|
flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
|
|
openFlags &= ~(O_RDWR|O_CREAT);
|
|
flags |= SQLITE_OPEN_READONLY;
|
|
openFlags |= O_RDONLY;
|
|
isReadonly = 1;
|
|
fd = robust_open(zName, openFlags, openMode);
|
|
}
|
|
}
|
|
if( fd<0 ){
|
|
int rc2 = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zName);
|
|
if( rc==SQLITE_OK ) rc = rc2;
|
|
goto open_finished;
|
|
}
|
|
|
|
/* The owner of the rollback journal or WAL file should always be the
|
|
** same as the owner of the database file. Try to ensure that this is
|
|
** the case. The chown() system call will be a no-op if the current
|
|
** process lacks root privileges, be we should at least try. Without
|
|
** this step, if a root process opens a database file, it can leave
|
|
** behinds a journal/WAL that is owned by root and hence make the
|
|
** database inaccessible to unprivileged processes.
|
|
**
|
|
** If openMode==0, then that means uid and gid are not set correctly
|
|
** (probably because SQLite is configured to use 8+3 filename mode) and
|
|
** in that case we do not want to attempt the chown().
|
|
*/
|
|
if( openMode && (flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL))!=0 ){
|
|
robustFchown(fd, uid, gid);
|
|
}
|
|
}
|
|
assert( fd>=0 );
|
|
if( pOutFlags ){
|
|
*pOutFlags = flags;
|
|
}
|
|
|
|
if( p->pPreallocatedUnused ){
|
|
p->pPreallocatedUnused->fd = fd;
|
|
p->pPreallocatedUnused->flags =
|
|
flags & (SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE);
|
|
}
|
|
|
|
if( isDelete ){
|
|
#if OS_VXWORKS
|
|
zPath = zName;
|
|
#elif defined(SQLITE_UNLINK_AFTER_CLOSE)
|
|
zPath = sqlite3_mprintf("%s", zName);
|
|
if( zPath==0 ){
|
|
robust_close(p, fd, __LINE__);
|
|
return SQLITE_NOMEM_BKPT;
|
|
}
|
|
#else
|
|
osUnlink(zName);
|
|
#endif
|
|
}
|
|
#if SQLITE_ENABLE_LOCKING_STYLE
|
|
else{
|
|
p->openFlags = openFlags;
|
|
}
|
|
#endif
|
|
|
|
#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
|
|
if( fstatfs(fd, &fsInfo) == -1 ){
|
|
storeLastErrno(p, errno);
|
|
robust_close(p, fd, __LINE__);
|
|
return SQLITE_IOERR_ACCESS;
|
|
}
|
|
if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) {
|
|
((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS;
|
|
}
|
|
if (0 == strncmp("exfat", fsInfo.f_fstypename, 5)) {
|
|
((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS;
|
|
}
|
|
#endif
|
|
|
|
/* Set up appropriate ctrlFlags */
|
|
if( isDelete ) ctrlFlags |= UNIXFILE_DELETE;
|
|
if( isReadonly ) ctrlFlags |= UNIXFILE_RDONLY;
|
|
noLock = eType!=SQLITE_OPEN_MAIN_DB;
|
|
if( noLock ) ctrlFlags |= UNIXFILE_NOLOCK;
|
|
if( isNewJrnl ) ctrlFlags |= UNIXFILE_DIRSYNC;
|
|
if( flags & SQLITE_OPEN_URI ) ctrlFlags |= UNIXFILE_URI;
|
|
|
|
#if SQLITE_ENABLE_LOCKING_STYLE
|
|
#if SQLITE_PREFER_PROXY_LOCKING
|
|
isAutoProxy = 1;
|
|
#endif
|
|
if( isAutoProxy && (zPath!=NULL) && (!noLock) && pVfs->xOpen ){
|
|
char *envforce = getenv("SQLITE_FORCE_PROXY_LOCKING");
|
|
int useProxy = 0;
|
|
|
|
/* SQLITE_FORCE_PROXY_LOCKING==1 means force always use proxy, 0 means
|
|
** never use proxy, NULL means use proxy for non-local files only. */
|
|
if( envforce!=NULL ){
|
|
useProxy = atoi(envforce)>0;
|
|
}else{
|
|
useProxy = !(fsInfo.f_flags&MNT_LOCAL);
|
|
}
|
|
if( useProxy ){
|
|
rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
|
|
if( rc==SQLITE_OK ){
|
|
rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:");
|
|
if( rc!=SQLITE_OK ){
|
|
/* Use unixClose to clean up the resources added in fillInUnixFile
|
|
** and clear all the structure's references. Specifically,
|
|
** pFile->pMethods will be NULL so sqlite3OsClose will be a no-op
|
|
*/
|
|
unixClose(pFile);
|
|
return rc;
|
|
}
|
|
}
|
|
goto open_finished;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
assert( zPath==0 || zPath[0]=='/'
|
|
|| eType==SQLITE_OPEN_SUPER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL
|
|
);
|
|
rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
|
|
|
|
open_finished:
|
|
if( rc!=SQLITE_OK ){
|
|
sqlite3_free(p->pPreallocatedUnused);
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
|
|
/*
|
|
** Delete the file at zPath. If the dirSync argument is true, fsync()
|
|
** the directory after deleting the file.
|
|
*/
|
|
static int unixDelete(
|
|
sqlite3_vfs *NotUsed, /* VFS containing this as the xDelete method */
|
|
const char *zPath, /* Name of file to be deleted */
|
|
int dirSync /* If true, fsync() directory after deleting file */
|
|
){
|
|
int rc = SQLITE_OK;
|
|
UNUSED_PARAMETER(NotUsed);
|
|
SimulateIOError(return SQLITE_IOERR_DELETE);
|
|
if( osUnlink(zPath)==(-1) ){
|
|
if( errno==ENOENT
|
|
#if OS_VXWORKS
|
|
|| osAccess(zPath,0)!=0
|
|
#endif
|
|
){
|
|
rc = SQLITE_IOERR_DELETE_NOENT;
|
|
}else{
|
|
rc = unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath);
|
|
}
|
|
return rc;
|
|
}
|
|
#ifndef SQLITE_DISABLE_DIRSYNC
|
|
if( (dirSync & 1)!=0 ){
|
|
int fd;
|
|
rc = osOpenDirectory(zPath, &fd);
|
|
if( rc==SQLITE_OK ){
|
|
if( full_fsync(fd,0,0) ){
|
|
rc = unixLogError(SQLITE_IOERR_DIR_FSYNC, "fsync", zPath);
|
|
}
|
|
robust_close(0, fd, __LINE__);
|
|
}else{
|
|
assert( rc==SQLITE_CANTOPEN );
|
|
rc = SQLITE_OK;
|
|
}
|
|
}
|
|
#endif
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Test the existence of or access permissions of file zPath. The
|
|
** test performed depends on the value of flags:
|
|
**
|
|
** SQLITE_ACCESS_EXISTS: Return 1 if the file exists
|
|
** SQLITE_ACCESS_READWRITE: Return 1 if the file is read and writable.
|
|
** SQLITE_ACCESS_READONLY: Return 1 if the file is readable.
|
|
**
|
|
** Otherwise return 0.
|
|
*/
|
|
static int unixAccess(
|
|
sqlite3_vfs *NotUsed, /* The VFS containing this xAccess method */
|
|
const char *zPath, /* Path of the file to examine */
|
|
int flags, /* What do we want to learn about the zPath file? */
|
|
int *pResOut /* Write result boolean here */
|
|
){
|
|
UNUSED_PARAMETER(NotUsed);
|
|
SimulateIOError( return SQLITE_IOERR_ACCESS; );
|
|
assert( pResOut!=0 );
|
|
|
|
/* The spec says there are three possible values for flags. But only
|
|
** two of them are actually used */
|
|
assert( flags==SQLITE_ACCESS_EXISTS || flags==SQLITE_ACCESS_READWRITE );
|
|
|
|
if( flags==SQLITE_ACCESS_EXISTS ){
|
|
struct stat buf;
|
|
*pResOut = 0==osStat(zPath, &buf) &&
|
|
(!S_ISREG(buf.st_mode) || buf.st_size>0);
|
|
}else{
|
|
*pResOut = osAccess(zPath, W_OK|R_OK)==0;
|
|
}
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** A pathname under construction
|
|
*/
|
|
typedef struct DbPath DbPath;
|
|
struct DbPath {
|
|
int rc; /* Non-zero following any error */
|
|
int nSymlink; /* Number of symlinks resolved */
|
|
char *zOut; /* Write the pathname here */
|
|
int nOut; /* Bytes of space available to zOut[] */
|
|
int nUsed; /* Bytes of zOut[] currently being used */
|
|
};
|
|
|
|
/* Forward reference */
|
|
static void appendAllPathElements(DbPath*,const char*);
|
|
|
|
/*
|
|
** Append a single path element to the DbPath under construction
|
|
*/
|
|
static void appendOnePathElement(
|
|
DbPath *pPath, /* Path under construction, to which to append zName */
|
|
const char *zName, /* Name to append to pPath. Not zero-terminated */
|
|
int nName /* Number of significant bytes in zName */
|
|
){
|
|
assert( nName>0 );
|
|
assert( zName!=0 );
|
|
if( zName[0]=='.' ){
|
|
if( nName==1 ) return;
|
|
if( zName[1]=='.' && nName==2 ){
|
|
if( pPath->nUsed>1 ){
|
|
assert( pPath->zOut[0]=='/' );
|
|
while( pPath->zOut[--pPath->nUsed]!='/' ){}
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
if( pPath->nUsed + nName + 2 >= pPath->nOut ){
|
|
pPath->rc = SQLITE_ERROR;
|
|
return;
|
|
}
|
|
pPath->zOut[pPath->nUsed++] = '/';
|
|
memcpy(&pPath->zOut[pPath->nUsed], zName, nName);
|
|
pPath->nUsed += nName;
|
|
#if defined(HAVE_READLINK) && defined(HAVE_LSTAT)
|
|
if( pPath->rc==SQLITE_OK ){
|
|
const char *zIn;
|
|
struct stat buf;
|
|
pPath->zOut[pPath->nUsed] = 0;
|
|
zIn = pPath->zOut;
|
|
if( osLstat(zIn, &buf)!=0 ){
|
|
if( errno!=ENOENT ){
|
|
pPath->rc = unixLogError(SQLITE_CANTOPEN_BKPT, "lstat", zIn);
|
|
}
|
|
}else if( S_ISLNK(buf.st_mode) ){
|
|
ssize_t got;
|
|
char zLnk[SQLITE_MAX_PATHLEN+2];
|
|
if( pPath->nSymlink++ > SQLITE_MAX_SYMLINK ){
|
|
pPath->rc = SQLITE_CANTOPEN_BKPT;
|
|
return;
|
|
}
|
|
got = osReadlink(zIn, zLnk, sizeof(zLnk)-2);
|
|
if( got<=0 || got>=(ssize_t)sizeof(zLnk)-2 ){
|
|
pPath->rc = unixLogError(SQLITE_CANTOPEN_BKPT, "readlink", zIn);
|
|
return;
|
|
}
|
|
zLnk[got] = 0;
|
|
if( zLnk[0]=='/' ){
|
|
pPath->nUsed = 0;
|
|
}else{
|
|
pPath->nUsed -= nName + 1;
|
|
}
|
|
appendAllPathElements(pPath, zLnk);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
** Append all path elements in zPath to the DbPath under construction.
|
|
*/
|
|
static void appendAllPathElements(
|
|
DbPath *pPath, /* Path under construction, to which to append zName */
|
|
const char *zPath /* Path to append to pPath. Is zero-terminated */
|
|
){
|
|
int i = 0;
|
|
int j = 0;
|
|
do{
|
|
while( zPath[i] && zPath[i]!='/' ){ i++; }
|
|
if( i>j ){
|
|
appendOnePathElement(pPath, &zPath[j], i-j);
|
|
}
|
|
j = i+1;
|
|
}while( zPath[i++] );
|
|
}
|
|
|
|
/*
|
|
** Turn a relative pathname into a full pathname. The relative path
|
|
** is stored as a nul-terminated string in the buffer pointed to by
|
|
** zPath.
|
|
**
|
|
** zOut points to a buffer of at least sqlite3_vfs.mxPathname bytes
|
|
** (in this case, MAX_PATHNAME bytes). The full-path is written to
|
|
** this buffer before returning.
|
|
*/
|
|
static int unixFullPathname(
|
|
sqlite3_vfs *pVfs, /* Pointer to vfs object */
|
|
const char *zPath, /* Possibly relative input path */
|
|
int nOut, /* Size of output buffer in bytes */
|
|
char *zOut /* Output buffer */
|
|
){
|
|
DbPath path;
|
|
UNUSED_PARAMETER(pVfs);
|
|
path.rc = 0;
|
|
path.nUsed = 0;
|
|
path.nSymlink = 0;
|
|
path.nOut = nOut;
|
|
path.zOut = zOut;
|
|
if( zPath[0]!='/' ){
|
|
char zPwd[SQLITE_MAX_PATHLEN+2];
|
|
if( osGetcwd(zPwd, sizeof(zPwd)-2)==0 ){
|
|
return unixLogError(SQLITE_CANTOPEN_BKPT, "getcwd", zPath);
|
|
}
|
|
appendAllPathElements(&path, zPwd);
|
|
}
|
|
appendAllPathElements(&path, zPath);
|
|
zOut[path.nUsed] = 0;
|
|
if( path.rc || path.nUsed<2 ) return SQLITE_CANTOPEN_BKPT;
|
|
if( path.nSymlink ) return SQLITE_OK_SYMLINK;
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
#ifndef SQLITE_OMIT_LOAD_EXTENSION
|
|
/*
|
|
** Interfaces for opening a shared library, finding entry points
|
|
** within the shared library, and closing the shared library.
|
|
*/
|
|
#include <dlfcn.h>
|
|
static void *unixDlOpen(sqlite3_vfs *NotUsed, const char *zFilename){
|
|
UNUSED_PARAMETER(NotUsed);
|
|
return dlopen(zFilename, RTLD_NOW | RTLD_GLOBAL);
|
|
}
|
|
|
|
/*
|
|
** SQLite calls this function immediately after a call to unixDlSym() or
|
|
** unixDlOpen() fails (returns a null pointer). If a more detailed error
|
|
** message is available, it is written to zBufOut. If no error message
|
|
** is available, zBufOut is left unmodified and SQLite uses a default
|
|
** error message.
|
|
*/
|
|
static void unixDlError(sqlite3_vfs *NotUsed, int nBuf, char *zBufOut){
|
|
const char *zErr;
|
|
UNUSED_PARAMETER(NotUsed);
|
|
unixEnterMutex();
|
|
zErr = dlerror();
|
|
if( zErr ){
|
|
sqlite3_snprintf(nBuf, zBufOut, "%s", zErr);
|
|
}
|
|
unixLeaveMutex();
|
|
}
|
|
static void (*unixDlSym(sqlite3_vfs *NotUsed, void *p, const char*zSym))(void){
|
|
/*
|
|
** GCC with -pedantic-errors says that C90 does not allow a void* to be
|
|
** cast into a pointer to a function. And yet the library dlsym() routine
|
|
** returns a void* which is really a pointer to a function. So how do we
|
|
** use dlsym() with -pedantic-errors?
|
|
**
|
|
** Variable x below is defined to be a pointer to a function taking
|
|
** parameters void* and const char* and returning a pointer to a function.
|
|
** We initialize x by assigning it a pointer to the dlsym() function.
|
|
** (That assignment requires a cast.) Then we call the function that
|
|
** x points to.
|
|
**
|
|
** This work-around is unlikely to work correctly on any system where
|
|
** you really cannot cast a function pointer into void*. But then, on the
|
|
** other hand, dlsym() will not work on such a system either, so we have
|
|
** not really lost anything.
|
|
*/
|
|
void (*(*x)(void*,const char*))(void);
|
|
UNUSED_PARAMETER(NotUsed);
|
|
x = (void(*(*)(void*,const char*))(void))dlsym;
|
|
return (*x)(p, zSym);
|
|
}
|
|
static void unixDlClose(sqlite3_vfs *NotUsed, void *pHandle){
|
|
UNUSED_PARAMETER(NotUsed);
|
|
dlclose(pHandle);
|
|
}
|
|
#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
|
|
#define unixDlOpen 0
|
|
#define unixDlError 0
|
|
#define unixDlSym 0
|
|
#define unixDlClose 0
|
|
#endif
|
|
|
|
/*
|
|
** Write nBuf bytes of random data to the supplied buffer zBuf.
|
|
*/
|
|
static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){
|
|
UNUSED_PARAMETER(NotUsed);
|
|
assert((size_t)nBuf>=(sizeof(time_t)+sizeof(int)));
|
|
|
|
/* 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, nBuf);
|
|
randomnessPid = osGetpid(0);
|
|
#if !defined(SQLITE_TEST) && !defined(SQLITE_OMIT_RANDOMNESS)
|
|
{
|
|
int fd, got;
|
|
fd = robust_open("/dev/urandom", O_RDONLY, 0);
|
|
if( fd<0 ){
|
|
time_t t;
|
|
time(&t);
|
|
memcpy(zBuf, &t, sizeof(t));
|
|
memcpy(&zBuf[sizeof(t)], &randomnessPid, sizeof(randomnessPid));
|
|
assert( sizeof(t)+sizeof(randomnessPid)<=(size_t)nBuf );
|
|
nBuf = sizeof(t) + sizeof(randomnessPid);
|
|
}else{
|
|
do{ got = osRead(fd, zBuf, nBuf); }while( got<0 && errno==EINTR );
|
|
robust_close(0, fd, __LINE__);
|
|
}
|
|
}
|
|
#endif
|
|
return nBuf;
|
|
}
|
|
|
|
|
|
/*
|
|
** Sleep for a little while. Return the amount of time slept.
|
|
** The argument is the number of microseconds we want to sleep.
|
|
** The return value is the number of microseconds of sleep actually
|
|
** requested from the underlying operating system, a number which
|
|
** might be greater than or equal to the argument, but not less
|
|
** than the argument.
|
|
*/
|
|
static int unixSleep(sqlite3_vfs *NotUsed, int microseconds){
|
|
#if !defined(HAVE_NANOSLEEP) || HAVE_NANOSLEEP+0
|
|
struct timespec sp;
|
|
sp.tv_sec = microseconds / 1000000;
|
|
sp.tv_nsec = (microseconds % 1000000) * 1000;
|
|
|
|
/* Almost all modern unix systems support nanosleep(). But if you are
|
|
** compiling for one of the rare exceptions, you can use
|
|
** -DHAVE_NANOSLEEP=0 (perhaps in conjuction with -DHAVE_USLEEP if
|
|
** usleep() is available) in order to bypass the use of nanosleep() */
|
|
nanosleep(&sp, NULL);
|
|
|
|
UNUSED_PARAMETER(NotUsed);
|
|
return microseconds;
|
|
#elif defined(HAVE_USLEEP) && HAVE_USLEEP
|
|
if( microseconds>=1000000 ) sleep(microseconds/1000000);
|
|
if( microseconds%1000000 ) usleep(microseconds%1000000);
|
|
UNUSED_PARAMETER(NotUsed);
|
|
return microseconds;
|
|
#else
|
|
int seconds = (microseconds+999999)/1000000;
|
|
sleep(seconds);
|
|
UNUSED_PARAMETER(NotUsed);
|
|
return seconds*1000000;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
** The following variable, if set to a non-zero value, is interpreted as
|
|
** the number of seconds since 1970 and is used to set the result of
|
|
** sqlite3OsCurrentTime() during testing.
|
|
*/
|
|
#ifdef SQLITE_TEST
|
|
SQLITE_API int sqlite3_current_time = 0; /* Fake system time in seconds since 1970. */
|
|
#endif
|
|
|
|
/*
|
|
** Find the current time (in Universal Coordinated Time). Write into *piNow
|
|
** the current time and date as a Julian Day number times 86_400_000. In
|
|
** other words, write into *piNow the number of milliseconds since the Julian
|
|
** epoch of noon in Greenwich on November 24, 4714 B.C according to the
|
|
** proleptic Gregorian calendar.
|
|
**
|
|
** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date
|
|
** cannot be found.
|
|
*/
|
|
static int unixCurrentTimeInt64(sqlite3_vfs *NotUsed, sqlite3_int64 *piNow){
|
|
static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
|
|
int rc = SQLITE_OK;
|
|
#if defined(NO_GETTOD)
|
|
time_t t;
|
|
time(&t);
|
|
*piNow = ((sqlite3_int64)t)*1000 + unixEpoch;
|
|
#elif OS_VXWORKS
|
|
struct timespec sNow;
|
|
clock_gettime(CLOCK_REALTIME, &sNow);
|
|
*piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_nsec/1000000;
|
|
#else
|
|
struct timeval sNow;
|
|
(void)gettimeofday(&sNow, 0); /* Cannot fail given valid arguments */
|
|
*piNow = unixEpoch + 1000*(sqlite3_int64)sNow.tv_sec + sNow.tv_usec/1000;
|
|
#endif
|
|
|
|
#ifdef SQLITE_TEST
|
|
if( sqlite3_current_time ){
|
|
*piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch;
|
|
}
|
|
#endif
|
|
UNUSED_PARAMETER(NotUsed);
|
|
return rc;
|
|
}
|
|
|
|
#ifndef SQLITE_OMIT_DEPRECATED
|
|
/*
|
|
** 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.
|
|
*/
|
|
static int unixCurrentTime(sqlite3_vfs *NotUsed, double *prNow){
|
|
sqlite3_int64 i = 0;
|
|
int rc;
|
|
UNUSED_PARAMETER(NotUsed);
|
|
rc = unixCurrentTimeInt64(0, &i);
|
|
*prNow = i/86400000.0;
|
|
return rc;
|
|
}
|
|
#else
|
|
# define unixCurrentTime 0
|
|
#endif
|
|
|
|
/*
|
|
** The xGetLastError() method is designed to return a better
|
|
** low-level error message when operating-system problems come up
|
|
** during SQLite operation. Only the integer return code is currently
|
|
** used.
|
|
*/
|
|
static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
|
|
UNUSED_PARAMETER(NotUsed);
|
|
UNUSED_PARAMETER(NotUsed2);
|
|
UNUSED_PARAMETER(NotUsed3);
|
|
return errno;
|
|
}
|
|
|
|
|
|
/*
|
|
************************ End of sqlite3_vfs methods ***************************
|
|
******************************************************************************/
|
|
|
|
/******************************************************************************
|
|
************************** Begin Proxy Locking ********************************
|
|
**
|
|
** Proxy locking is a "uber-locking-method" in this sense: It uses the
|
|
** other locking methods on secondary lock files. Proxy locking is a
|
|
** meta-layer over top of the primitive locking implemented above. For
|
|
** this reason, the division that implements of proxy locking is deferred
|
|
** until late in the file (here) after all of the other I/O methods have
|
|
** been defined - so that the primitive locking methods are available
|
|
** as services to help with the implementation of proxy locking.
|
|
**
|
|
****
|
|
**
|
|
** The default locking schemes in SQLite use byte-range locks on the
|
|
** database file to coordinate safe, concurrent access by multiple readers
|
|
** and writers [http://sqlite.org/lockingv3.html]. The five file locking
|
|
** states (UNLOCKED, PENDING, SHARED, RESERVED, EXCLUSIVE) are implemented
|
|
** as POSIX read & write locks over fixed set of locations (via fsctl),
|
|
** on AFP and SMB only exclusive byte-range locks are available via fsctl
|
|
** with _IOWR('z', 23, struct ByteRangeLockPB2) to track the same 5 states.
|
|
** To simulate a F_RDLCK on the shared range, on AFP a randomly selected
|
|
** address in the shared range is taken for a SHARED lock, the entire
|
|
** shared range is taken for an EXCLUSIVE lock):
|
|
**
|
|
** PENDING_BYTE 0x40000000
|
|
** RESERVED_BYTE 0x40000001
|
|
** SHARED_RANGE 0x40000002 -> 0x40000200
|
|
**
|
|
** This works well on the local file system, but shows a nearly 100x
|
|
** slowdown in read performance on AFP because the AFP client disables
|
|
** the read cache when byte-range locks are present. Enabling the read
|
|
** cache exposes a cache coherency problem that is present on all OS X
|
|
** supported network file systems. NFS and AFP both observe the
|
|
** close-to-open semantics for ensuring cache coherency
|
|
** [http://nfs.sourceforge.net/#faq_a8], which does not effectively
|
|
** address the requirements for concurrent database access by multiple
|
|
** readers and writers
|
|
** [http://www.nabble.com/SQLite-on-NFS-cache-coherency-td15655701.html].
|
|
**
|
|
** To address the performance and cache coherency issues, proxy file locking
|
|
** changes the way database access is controlled by limiting access to a
|
|
** single host at a time and moving file locks off of the database file
|
|
** and onto a proxy file on the local file system.
|
|
**
|
|
**
|
|
** Using proxy locks
|
|
** -----------------
|
|
**
|
|
** C APIs
|
|
**
|
|
** sqlite3_file_control(db, dbname, SQLITE_FCNTL_SET_LOCKPROXYFILE,
|
|
** <proxy_path> | ":auto:");
|
|
** sqlite3_file_control(db, dbname, SQLITE_FCNTL_GET_LOCKPROXYFILE,
|
|
** &<proxy_path>);
|
|
**
|
|
**
|
|
** SQL pragmas
|
|
**
|
|
** PRAGMA [database.]lock_proxy_file=<proxy_path> | :auto:
|
|
** PRAGMA [database.]lock_proxy_file
|
|
**
|
|
** Specifying ":auto:" means that if there is a conch file with a matching
|
|
** host ID in it, the proxy path in the conch file will be used, otherwise
|
|
** a proxy path based on the user's temp dir
|
|
** (via confstr(_CS_DARWIN_USER_TEMP_DIR,...)) will be used and the
|
|
** actual proxy file name is generated from the name and path of the
|
|
** database file. For example:
|
|
**
|
|
** For database path "/Users/me/foo.db"
|
|
** The lock path will be "<tmpdir>/sqliteplocks/_Users_me_foo.db:auto:")
|
|
**
|
|
** Once a lock proxy is configured for a database connection, it can not
|
|
** be removed, however it may be switched to a different proxy path via
|
|
** the above APIs (assuming the conch file is not being held by another
|
|
** connection or process).
|
|
**
|
|
**
|
|
** How proxy locking works
|
|
** -----------------------
|
|
**
|
|
** Proxy file locking relies primarily on two new supporting files:
|
|
**
|
|
** * conch file to limit access to the database file to a single host
|
|
** at a time
|
|
**
|
|
** * proxy file to act as a proxy for the advisory locks normally
|
|
** taken on the database
|
|
**
|
|
** The conch file - to use a proxy file, sqlite must first "hold the conch"
|
|
** by taking an sqlite-style shared lock on the conch file, reading the
|
|
** contents and comparing the host's unique host ID (see below) and lock
|
|
** proxy path against the values stored in the conch. The conch file is
|
|
** stored in the same directory as the database file and the file name
|
|
** is patterned after the database file name as ".<databasename>-conch".
|
|
** If the conch file does not exist, or its contents do not match the
|
|
** host ID and/or proxy path, then the lock is escalated to an exclusive
|
|
** lock and the conch file contents is updated with the host ID and proxy
|
|
** path and the lock is downgraded to a shared lock again. If the conch
|
|
** is held by another process (with a shared lock), the exclusive lock
|
|
** will fail and SQLITE_BUSY is returned.
|
|
**
|
|
** The proxy file - a single-byte file used for all advisory file locks
|
|
** normally taken on the database file. This allows for safe sharing
|
|
** of the database file for multiple readers and writers on the same
|
|
** host (the conch ensures that they all use the same local lock file).
|
|
**
|
|
** Requesting the lock proxy does not immediately take the conch, it is
|
|
** only taken when the first request to lock database file is made.
|
|
** This matches the semantics of the traditional locking behavior, where
|
|
** opening a connection to a database file does not take a lock on it.
|
|
** The shared lock and an open file descriptor are maintained until
|
|
** the connection to the database is closed.
|
|
**
|
|
** The proxy file and the lock file are never deleted so they only need
|
|
** to be created the first time they are used.
|
|
**
|
|
** Configuration options
|
|
** ---------------------
|
|
**
|
|
** SQLITE_PREFER_PROXY_LOCKING
|
|
**
|
|
** Database files accessed on non-local file systems are
|
|
** automatically configured for proxy locking, lock files are
|
|
** named automatically using the same logic as
|
|
** PRAGMA lock_proxy_file=":auto:"
|
|
**
|
|
** SQLITE_PROXY_DEBUG
|
|
**
|
|
** Enables the logging of error messages during host id file
|
|
** retrieval and creation
|
|
**
|
|
** LOCKPROXYDIR
|
|
**
|
|
** Overrides the default directory used for lock proxy files that
|
|
** are named automatically via the ":auto:" setting
|
|
**
|
|
** SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
|
|
**
|
|
** Permissions to use when creating a directory for storing the
|
|
** lock proxy files, only used when LOCKPROXYDIR is not set.
|
|
**
|
|
**
|
|
** As mentioned above, when compiled with SQLITE_PREFER_PROXY_LOCKING,
|
|
** setting the environment variable SQLITE_FORCE_PROXY_LOCKING to 1 will
|
|
** force proxy locking to be used for every database file opened, and 0
|
|
** will force automatic proxy locking to be disabled for all database
|
|
** files (explicitly calling the SQLITE_FCNTL_SET_LOCKPROXYFILE pragma or
|
|
** sqlite_file_control API is not affected by SQLITE_FORCE_PROXY_LOCKING).
|
|
*/
|
|
|
|
/*
|
|
** Proxy locking is only available on MacOSX
|
|
*/
|
|
#if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
|
|
|
|
/*
|
|
** The proxyLockingContext has the path and file structures for the remote
|
|
** and local proxy files in it
|
|
*/
|
|
typedef struct proxyLockingContext proxyLockingContext;
|
|
struct proxyLockingContext {
|
|
unixFile *conchFile; /* Open conch file */
|
|
char *conchFilePath; /* Name of the conch file */
|
|
unixFile *lockProxy; /* Open proxy lock file */
|
|
char *lockProxyPath; /* Name of the proxy lock file */
|
|
char *dbPath; /* Name of the open file */
|
|
int conchHeld; /* 1 if the conch is held, -1 if lockless */
|
|
int nFails; /* Number of conch taking failures */
|
|
void *oldLockingContext; /* Original lockingcontext to restore on close */
|
|
sqlite3_io_methods const *pOldMethod; /* Original I/O methods for close */
|
|
};
|
|
|
|
/*
|
|
** The proxy lock file path for the database at dbPath is written into lPath,
|
|
** which must point to valid, writable memory large enough for a maxLen length
|
|
** file path.
|
|
*/
|
|
static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){
|
|
int len;
|
|
int dbLen;
|
|
int i;
|
|
|
|
#ifdef LOCKPROXYDIR
|
|
len = strlcpy(lPath, LOCKPROXYDIR, maxLen);
|
|
#else
|
|
# ifdef _CS_DARWIN_USER_TEMP_DIR
|
|
{
|
|
if( !confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen) ){
|
|
OSTRACE(("GETLOCKPATH failed %s errno=%d pid=%d\n",
|
|
lPath, errno, osGetpid(0)));
|
|
return SQLITE_IOERR_LOCK;
|
|
}
|
|
len = strlcat(lPath, "sqliteplocks", maxLen);
|
|
}
|
|
# else
|
|
len = strlcpy(lPath, "/tmp/", maxLen);
|
|
# endif
|
|
#endif
|
|
|
|
if( lPath[len-1]!='/' ){
|
|
len = strlcat(lPath, "/", maxLen);
|
|
}
|
|
|
|
/* transform the db path to a unique cache name */
|
|
dbLen = (int)strlen(dbPath);
|
|
for( i=0; i<dbLen && (i+len+7)<(int)maxLen; i++){
|
|
char c = dbPath[i];
|
|
lPath[i+len] = (c=='/')?'_':c;
|
|
}
|
|
lPath[i+len]='\0';
|
|
strlcat(lPath, ":auto:", maxLen);
|
|
OSTRACE(("GETLOCKPATH proxy lock path=%s pid=%d\n", lPath, osGetpid(0)));
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Creates the lock file and any missing directories in lockPath
|
|
*/
|
|
static int proxyCreateLockPath(const char *lockPath){
|
|
int i, len;
|
|
char buf[MAXPATHLEN];
|
|
int start = 0;
|
|
|
|
assert(lockPath!=NULL);
|
|
/* try to create all the intermediate directories */
|
|
len = (int)strlen(lockPath);
|
|
buf[0] = lockPath[0];
|
|
for( i=1; i<len; i++ ){
|
|
if( lockPath[i] == '/' && (i - start > 0) ){
|
|
/* only mkdir if leaf dir != "." or "/" or ".." */
|
|
if( i-start>2 || (i-start==1 && buf[start] != '.' && buf[start] != '/')
|
|
|| (i-start==2 && buf[start] != '.' && buf[start+1] != '.') ){
|
|
buf[i]='\0';
|
|
if( osMkdir(buf, SQLITE_DEFAULT_PROXYDIR_PERMISSIONS) ){
|
|
int err=errno;
|
|
if( err!=EEXIST ) {
|
|
OSTRACE(("CREATELOCKPATH FAILED creating %s, "
|
|
"'%s' proxy lock path=%s pid=%d\n",
|
|
buf, strerror(err), lockPath, osGetpid(0)));
|
|
return err;
|
|
}
|
|
}
|
|
}
|
|
start=i+1;
|
|
}
|
|
buf[i] = lockPath[i];
|
|
}
|
|
OSTRACE(("CREATELOCKPATH proxy lock path=%s pid=%d\n",lockPath,osGetpid(0)));
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
** Create a new VFS file descriptor (stored in memory obtained from
|
|
** sqlite3_malloc) and open the file named "path" in the file descriptor.
|
|
**
|
|
** The caller is responsible not only for closing the file descriptor
|
|
** but also for freeing the memory associated with the file descriptor.
|
|
*/
|
|
static int proxyCreateUnixFile(
|
|
const char *path, /* path for the new unixFile */
|
|
unixFile **ppFile, /* unixFile created and returned by ref */
|
|
int islockfile /* if non zero missing dirs will be created */
|
|
) {
|
|
int fd = -1;
|
|
unixFile *pNew;
|
|
int rc = SQLITE_OK;
|
|
int openFlags = O_RDWR | O_CREAT | O_NOFOLLOW;
|
|
sqlite3_vfs dummyVfs;
|
|
int terrno = 0;
|
|
UnixUnusedFd *pUnused = NULL;
|
|
|
|
/* 1. first try to open/create the file
|
|
** 2. if that fails, and this is a lock file (not-conch), try creating
|
|
** the parent directories and then try again.
|
|
** 3. if that fails, try to open the file read-only
|
|
** otherwise return BUSY (if lock file) or CANTOPEN for the conch file
|
|
*/
|
|
pUnused = findReusableFd(path, openFlags);
|
|
if( pUnused ){
|
|
fd = pUnused->fd;
|
|
}else{
|
|
pUnused = sqlite3_malloc64(sizeof(*pUnused));
|
|
if( !pUnused ){
|
|
return SQLITE_NOMEM_BKPT;
|
|
}
|
|
}
|
|
if( fd<0 ){
|
|
fd = robust_open(path, openFlags, 0);
|
|
terrno = errno;
|
|
if( fd<0 && errno==ENOENT && islockfile ){
|
|
if( proxyCreateLockPath(path) == SQLITE_OK ){
|
|
fd = robust_open(path, openFlags, 0);
|
|
}
|
|
}
|
|
}
|
|
if( fd<0 ){
|
|
openFlags = O_RDONLY | O_NOFOLLOW;
|
|
fd = robust_open(path, openFlags, 0);
|
|
terrno = errno;
|
|
}
|
|
if( fd<0 ){
|
|
if( islockfile ){
|
|
return SQLITE_BUSY;
|
|
}
|
|
switch (terrno) {
|
|
case EACCES:
|
|
return SQLITE_PERM;
|
|
case EIO:
|
|
return SQLITE_IOERR_LOCK; /* even though it is the conch */
|
|
default:
|
|
return SQLITE_CANTOPEN_BKPT;
|
|
}
|
|
}
|
|
|
|
pNew = (unixFile *)sqlite3_malloc64(sizeof(*pNew));
|
|
if( pNew==NULL ){
|
|
rc = SQLITE_NOMEM_BKPT;
|
|
goto end_create_proxy;
|
|
}
|
|
memset(pNew, 0, sizeof(unixFile));
|
|
pNew->openFlags = openFlags;
|
|
memset(&dummyVfs, 0, sizeof(dummyVfs));
|
|
dummyVfs.pAppData = (void*)&autolockIoFinder;
|
|
dummyVfs.zName = "dummy";
|
|
pUnused->fd = fd;
|
|
pUnused->flags = openFlags;
|
|
pNew->pPreallocatedUnused = pUnused;
|
|
|
|
rc = fillInUnixFile(&dummyVfs, fd, (sqlite3_file*)pNew, path, 0);
|
|
if( rc==SQLITE_OK ){
|
|
*ppFile = pNew;
|
|
return SQLITE_OK;
|
|
}
|
|
end_create_proxy:
|
|
robust_close(pNew, fd, __LINE__);
|
|
sqlite3_free(pNew);
|
|
sqlite3_free(pUnused);
|
|
return rc;
|
|
}
|
|
|
|
#ifdef SQLITE_TEST
|
|
/* simulate multiple hosts by creating unique hostid file paths */
|
|
SQLITE_API int sqlite3_hostid_num = 0;
|
|
#endif
|
|
|
|
#define PROXY_HOSTIDLEN 16 /* conch file host id length */
|
|
|
|
#if HAVE_GETHOSTUUID
|
|
/* Not always defined in the headers as it ought to be */
|
|
extern int gethostuuid(uuid_t id, const struct timespec *wait);
|
|
#endif
|
|
|
|
/* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN
|
|
** bytes of writable memory.
|
|
*/
|
|
static int proxyGetHostID(unsigned char *pHostID, int *pError){
|
|
assert(PROXY_HOSTIDLEN == sizeof(uuid_t));
|
|
memset(pHostID, 0, PROXY_HOSTIDLEN);
|
|
#if HAVE_GETHOSTUUID
|
|
{
|
|
struct timespec timeout = {1, 0}; /* 1 sec timeout */
|
|
if( gethostuuid(pHostID, &timeout) ){
|
|
int err = errno;
|
|
if( pError ){
|
|
*pError = err;
|
|
}
|
|
return SQLITE_IOERR;
|
|
}
|
|
}
|
|
#else
|
|
UNUSED_PARAMETER(pError);
|
|
#endif
|
|
#ifdef SQLITE_TEST
|
|
/* simulate multiple hosts by creating unique hostid file paths */
|
|
if( sqlite3_hostid_num != 0){
|
|
pHostID[0] = (char)(pHostID[0] + (char)(sqlite3_hostid_num & 0xFF));
|
|
}
|
|
#endif
|
|
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/* The conch file contains the header, host id and lock file path
|
|
*/
|
|
#define PROXY_CONCHVERSION 2 /* 1-byte header, 16-byte host id, path */
|
|
#define PROXY_HEADERLEN 1 /* conch file header length */
|
|
#define PROXY_PATHINDEX (PROXY_HEADERLEN+PROXY_HOSTIDLEN)
|
|
#define PROXY_MAXCONCHLEN (PROXY_HEADERLEN+PROXY_HOSTIDLEN+MAXPATHLEN)
|
|
|
|
/*
|
|
** Takes an open conch file, copies the contents to a new path and then moves
|
|
** it back. The newly created file's file descriptor is assigned to the
|
|
** conch file structure and finally the original conch file descriptor is
|
|
** closed. Returns zero if successful.
|
|
*/
|
|
static int proxyBreakConchLock(unixFile *pFile, uuid_t myHostID){
|
|
proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
|
|
unixFile *conchFile = pCtx->conchFile;
|
|
char tPath[MAXPATHLEN];
|
|
char buf[PROXY_MAXCONCHLEN];
|
|
char *cPath = pCtx->conchFilePath;
|
|
size_t readLen = 0;
|
|
size_t pathLen = 0;
|
|
char errmsg[64] = "";
|
|
int fd = -1;
|
|
int rc = -1;
|
|
UNUSED_PARAMETER(myHostID);
|
|
|
|
/* create a new path by replace the trailing '-conch' with '-break' */
|
|
pathLen = strlcpy(tPath, cPath, MAXPATHLEN);
|
|
if( pathLen>MAXPATHLEN || pathLen<6 ||
|
|
(strlcpy(&tPath[pathLen-5], "break", 6) != 5) ){
|
|
sqlite3_snprintf(sizeof(errmsg),errmsg,"path error (len %d)",(int)pathLen);
|
|
goto end_breaklock;
|
|
}
|
|
/* read the conch content */
|
|
readLen = osPread(conchFile->h, buf, PROXY_MAXCONCHLEN, 0);
|
|
if( readLen<PROXY_PATHINDEX ){
|
|
sqlite3_snprintf(sizeof(errmsg),errmsg,"read error (len %d)",(int)readLen);
|
|
goto end_breaklock;
|
|
}
|
|
/* write it out to the temporary break file */
|
|
fd = robust_open(tPath, (O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW), 0);
|
|
if( fd<0 ){
|
|
sqlite3_snprintf(sizeof(errmsg), errmsg, "create failed (%d)", errno);
|
|
goto end_breaklock;
|
|
}
|
|
if( osPwrite(fd, buf, readLen, 0) != (ssize_t)readLen ){
|
|
sqlite3_snprintf(sizeof(errmsg), errmsg, "write failed (%d)", errno);
|
|
goto end_breaklock;
|
|
}
|
|
if( rename(tPath, cPath) ){
|
|
sqlite3_snprintf(sizeof(errmsg), errmsg, "rename failed (%d)", errno);
|
|
goto end_breaklock;
|
|
}
|
|
rc = 0;
|
|
fprintf(stderr, "broke stale lock on %s\n", cPath);
|
|
robust_close(pFile, conchFile->h, __LINE__);
|
|
conchFile->h = fd;
|
|
conchFile->openFlags = O_RDWR | O_CREAT;
|
|
|
|
end_breaklock:
|
|
if( rc ){
|
|
if( fd>=0 ){
|
|
osUnlink(tPath);
|
|
robust_close(pFile, fd, __LINE__);
|
|
}
|
|
fprintf(stderr, "failed to break stale lock on %s, %s\n", cPath, errmsg);
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/* Take the requested lock on the conch file and break a stale lock if the
|
|
** host id matches.
|
|
*/
|
|
static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){
|
|
proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
|
|
unixFile *conchFile = pCtx->conchFile;
|
|
int rc = SQLITE_OK;
|
|
int nTries = 0;
|
|
struct timespec conchModTime;
|
|
|
|
memset(&conchModTime, 0, sizeof(conchModTime));
|
|
do {
|
|
rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
|
|
nTries ++;
|
|
if( rc==SQLITE_BUSY ){
|
|
/* If the lock failed (busy):
|
|
* 1st try: get the mod time of the conch, wait 0.5s and try again.
|
|
* 2nd try: fail if the mod time changed or host id is different, wait
|
|
* 10 sec and try again
|
|
* 3rd try: break the lock unless the mod time has changed.
|
|
*/
|
|
struct stat buf;
|
|
if( osFstat(conchFile->h, &buf) ){
|
|
storeLastErrno(pFile, errno);
|
|
return SQLITE_IOERR_LOCK;
|
|
}
|
|
|
|
if( nTries==1 ){
|
|
conchModTime = buf.st_mtimespec;
|
|
unixSleep(0,500000); /* wait 0.5 sec and try the lock again*/
|
|
continue;
|
|
}
|
|
|
|
assert( nTries>1 );
|
|
if( conchModTime.tv_sec != buf.st_mtimespec.tv_sec ||
|
|
conchModTime.tv_nsec != buf.st_mtimespec.tv_nsec ){
|
|
return SQLITE_BUSY;
|
|
}
|
|
|
|
if( nTries==2 ){
|
|
char tBuf[PROXY_MAXCONCHLEN];
|
|
int len = osPread(conchFile->h, tBuf, PROXY_MAXCONCHLEN, 0);
|
|
if( len<0 ){
|
|
storeLastErrno(pFile, errno);
|
|
return SQLITE_IOERR_LOCK;
|
|
}
|
|
if( len>PROXY_PATHINDEX && tBuf[0]==(char)PROXY_CONCHVERSION){
|
|
/* don't break the lock if the host id doesn't match */
|
|
if( 0!=memcmp(&tBuf[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN) ){
|
|
return SQLITE_BUSY;
|
|
}
|
|
}else{
|
|
/* don't break the lock on short read or a version mismatch */
|
|
return SQLITE_BUSY;
|
|
}
|
|
unixSleep(0,10000000); /* wait 10 sec and try the lock again */
|
|
continue;
|
|
}
|
|
|
|
assert( nTries==3 );
|
|
if( 0==proxyBreakConchLock(pFile, myHostID) ){
|
|
rc = SQLITE_OK;
|
|
if( lockType==EXCLUSIVE_LOCK ){
|
|
rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK);
|
|
}
|
|
if( !rc ){
|
|
rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
|
|
}
|
|
}
|
|
}
|
|
} while( rc==SQLITE_BUSY && nTries<3 );
|
|
|
|
return rc;
|
|
}
|
|
|
|
/* Takes the conch by taking a shared lock and read the contents conch, if
|
|
** lockPath is non-NULL, the host ID and lock file path must match. A NULL
|
|
** lockPath means that the lockPath in the conch file will be used if the
|
|
** host IDs match, or a new lock path will be generated automatically
|
|
** and written to the conch file.
|
|
*/
|
|
static int proxyTakeConch(unixFile *pFile){
|
|
proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
|
|
|
|
if( pCtx->conchHeld!=0 ){
|
|
return SQLITE_OK;
|
|
}else{
|
|
unixFile *conchFile = pCtx->conchFile;
|
|
uuid_t myHostID;
|
|
int pError = 0;
|
|
char readBuf[PROXY_MAXCONCHLEN];
|
|
char lockPath[MAXPATHLEN];
|
|
char *tempLockPath = NULL;
|
|
int rc = SQLITE_OK;
|
|
int createConch = 0;
|
|
int hostIdMatch = 0;
|
|
int readLen = 0;
|
|
int tryOldLockPath = 0;
|
|
int forceNewLockPath = 0;
|
|
|
|
OSTRACE(("TAKECONCH %d for %s pid=%d\n", conchFile->h,
|
|
(pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"),
|
|
osGetpid(0)));
|
|
|
|
rc = proxyGetHostID(myHostID, &pError);
|
|
if( (rc&0xff)==SQLITE_IOERR ){
|
|
storeLastErrno(pFile, pError);
|
|
goto end_takeconch;
|
|
}
|
|
rc = proxyConchLock(pFile, myHostID, SHARED_LOCK);
|
|
if( rc!=SQLITE_OK ){
|
|
goto end_takeconch;
|
|
}
|
|
/* read the existing conch file */
|
|
readLen = seekAndRead((unixFile*)conchFile, 0, readBuf, PROXY_MAXCONCHLEN);
|
|
if( readLen<0 ){
|
|
/* I/O error: lastErrno set by seekAndRead */
|
|
storeLastErrno(pFile, conchFile->lastErrno);
|
|
rc = SQLITE_IOERR_READ;
|
|
goto end_takeconch;
|
|
}else if( readLen<=(PROXY_HEADERLEN+PROXY_HOSTIDLEN) ||
|
|
readBuf[0]!=(char)PROXY_CONCHVERSION ){
|
|
/* a short read or version format mismatch means we need to create a new
|
|
** conch file.
|
|
*/
|
|
createConch = 1;
|
|
}
|
|
/* if the host id matches and the lock path already exists in the conch
|
|
** we'll try to use the path there, if we can't open that path, we'll
|
|
** retry with a new auto-generated path
|
|
*/
|
|
do { /* in case we need to try again for an :auto: named lock file */
|
|
|
|
if( !createConch && !forceNewLockPath ){
|
|
hostIdMatch = !memcmp(&readBuf[PROXY_HEADERLEN], myHostID,
|
|
PROXY_HOSTIDLEN);
|
|
/* if the conch has data compare the contents */
|
|
if( !pCtx->lockProxyPath ){
|
|
/* for auto-named local lock file, just check the host ID and we'll
|
|
** use the local lock file path that's already in there
|
|
*/
|
|
if( hostIdMatch ){
|
|
size_t pathLen = (readLen - PROXY_PATHINDEX);
|
|
|
|
if( pathLen>=MAXPATHLEN ){
|
|
pathLen=MAXPATHLEN-1;
|
|
}
|
|
memcpy(lockPath, &readBuf[PROXY_PATHINDEX], pathLen);
|
|
lockPath[pathLen] = 0;
|
|
tempLockPath = lockPath;
|
|
tryOldLockPath = 1;
|
|
/* create a copy of the lock path if the conch is taken */
|
|
goto end_takeconch;
|
|
}
|
|
}else if( hostIdMatch
|
|
&& !strncmp(pCtx->lockProxyPath, &readBuf[PROXY_PATHINDEX],
|
|
readLen-PROXY_PATHINDEX)
|
|
){
|
|
/* conch host and lock path match */
|
|
goto end_takeconch;
|
|
}
|
|
}
|
|
|
|
/* if the conch isn't writable and doesn't match, we can't take it */
|
|
if( (conchFile->openFlags&O_RDWR) == 0 ){
|
|
rc = SQLITE_BUSY;
|
|
goto end_takeconch;
|
|
}
|
|
|
|
/* either the conch didn't match or we need to create a new one */
|
|
if( !pCtx->lockProxyPath ){
|
|
proxyGetLockPath(pCtx->dbPath, lockPath, MAXPATHLEN);
|
|
tempLockPath = lockPath;
|
|
/* create a copy of the lock path _only_ if the conch is taken */
|
|
}
|
|
|
|
/* update conch with host and path (this will fail if other process
|
|
** has a shared lock already), if the host id matches, use the big
|
|
** stick.
|
|
*/
|
|
futimes(conchFile->h, NULL);
|
|
if( hostIdMatch && !createConch ){
|
|
if( conchFile->pInode && conchFile->pInode->nShared>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 {
|
|
rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK);
|
|
}
|
|
}else{
|
|
rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK);
|
|
}
|
|
if( rc==SQLITE_OK ){
|
|
char writeBuffer[PROXY_MAXCONCHLEN];
|
|
int writeSize = 0;
|
|
|
|
writeBuffer[0] = (char)PROXY_CONCHVERSION;
|
|
memcpy(&writeBuffer[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN);
|
|
if( pCtx->lockProxyPath!=NULL ){
|
|
strlcpy(&writeBuffer[PROXY_PATHINDEX], pCtx->lockProxyPath,
|
|
MAXPATHLEN);
|
|
}else{
|
|
strlcpy(&writeBuffer[PROXY_PATHINDEX], tempLockPath, MAXPATHLEN);
|
|
}
|
|
writeSize = PROXY_PATHINDEX + strlen(&writeBuffer[PROXY_PATHINDEX]);
|
|
robust_ftruncate(conchFile->h, writeSize);
|
|
rc = unixWrite((sqlite3_file *)conchFile, writeBuffer, writeSize, 0);
|
|
full_fsync(conchFile->h,0,0);
|
|
/* If we created a new conch file (not just updated the contents of a
|
|
** valid conch file), try to match the permissions of the database
|
|
*/
|
|
if( rc==SQLITE_OK && createConch ){
|
|
struct stat buf;
|
|
int err = osFstat(pFile->h, &buf);
|
|
if( err==0 ){
|
|
mode_t cmode = buf.st_mode&(S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP |
|
|
S_IROTH|S_IWOTH);
|
|
/* try to match the database file R/W permissions, ignore failure */
|
|
#ifndef SQLITE_PROXY_DEBUG
|
|
osFchmod(conchFile->h, cmode);
|
|
#else
|
|
do{
|
|
rc = osFchmod(conchFile->h, cmode);
|
|
}while( rc==(-1) && errno==EINTR );
|
|
if( rc!=0 ){
|
|
int code = errno;
|
|
fprintf(stderr, "fchmod %o FAILED with %d %s\n",
|
|
cmode, code, strerror(code));
|
|
} else {
|
|
fprintf(stderr, "fchmod %o SUCCEDED\n",cmode);
|
|
}
|
|
}else{
|
|
int code = errno;
|
|
fprintf(stderr, "STAT FAILED[%d] with %d %s\n",
|
|
err, code, strerror(code));
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, SHARED_LOCK);
|
|
|
|
end_takeconch:
|
|
OSTRACE(("TRANSPROXY: CLOSE %d\n", pFile->h));
|
|
if( rc==SQLITE_OK && pFile->openFlags ){
|
|
int fd;
|
|
if( pFile->h>=0 ){
|
|
robust_close(pFile, pFile->h, __LINE__);
|
|
}
|
|
pFile->h = -1;
|
|
fd = robust_open(pCtx->dbPath, pFile->openFlags, 0);
|
|
OSTRACE(("TRANSPROXY: OPEN %d\n", fd));
|
|
if( fd>=0 ){
|
|
pFile->h = fd;
|
|
}else{
|
|
rc=SQLITE_CANTOPEN_BKPT; /* SQLITE_BUSY? proxyTakeConch called
|
|
during locking */
|
|
}
|
|
}
|
|
if( rc==SQLITE_OK && !pCtx->lockProxy ){
|
|
char *path = tempLockPath ? tempLockPath : pCtx->lockProxyPath;
|
|
rc = proxyCreateUnixFile(path, &pCtx->lockProxy, 1);
|
|
if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM && tryOldLockPath ){
|
|
/* we couldn't create the proxy lock file with the old lock file path
|
|
** so try again via auto-naming
|
|
*/
|
|
forceNewLockPath = 1;
|
|
tryOldLockPath = 0;
|
|
continue; /* go back to the do {} while start point, try again */
|
|
}
|
|
}
|
|
if( rc==SQLITE_OK ){
|
|
/* Need to make a copy of path if we extracted the value
|
|
** from the conch file or the path was allocated on the stack
|
|
*/
|
|
if( tempLockPath ){
|
|
pCtx->lockProxyPath = sqlite3DbStrDup(0, tempLockPath);
|
|
if( !pCtx->lockProxyPath ){
|
|
rc = SQLITE_NOMEM_BKPT;
|
|
}
|
|
}
|
|
}
|
|
if( rc==SQLITE_OK ){
|
|
pCtx->conchHeld = 1;
|
|
|
|
if( pCtx->lockProxy->pMethod == &afpIoMethods ){
|
|
afpLockingContext *afpCtx;
|
|
afpCtx = (afpLockingContext *)pCtx->lockProxy->lockingContext;
|
|
afpCtx->dbPath = pCtx->lockProxyPath;
|
|
}
|
|
} else {
|
|
conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
|
|
}
|
|
OSTRACE(("TAKECONCH %d %s\n", conchFile->h,
|
|
rc==SQLITE_OK?"ok":"failed"));
|
|
return rc;
|
|
} while (1); /* in case we need to retry the :auto: lock file -
|
|
** we should never get here except via the 'continue' call. */
|
|
}
|
|
}
|
|
|
|
/*
|
|
** If pFile holds a lock on a conch file, then release that lock.
|
|
*/
|
|
static int proxyReleaseConch(unixFile *pFile){
|
|
int rc = SQLITE_OK; /* Subroutine return code */
|
|
proxyLockingContext *pCtx; /* The locking context for the proxy lock */
|
|
unixFile *conchFile; /* Name of the conch file */
|
|
|
|
pCtx = (proxyLockingContext *)pFile->lockingContext;
|
|
conchFile = pCtx->conchFile;
|
|
OSTRACE(("RELEASECONCH %d for %s pid=%d\n", conchFile->h,
|
|
(pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"),
|
|
osGetpid(0)));
|
|
if( pCtx->conchHeld>0 ){
|
|
rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
|
|
}
|
|
pCtx->conchHeld = 0;
|
|
OSTRACE(("RELEASECONCH %d %s\n", conchFile->h,
|
|
(rc==SQLITE_OK ? "ok" : "failed")));
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Given the name of a database file, compute the name of its conch file.
|
|
** Store the conch filename in memory obtained from sqlite3_malloc64().
|
|
** Make *pConchPath point to the new name. Return SQLITE_OK on success
|
|
** or SQLITE_NOMEM if unable to obtain memory.
|
|
**
|
|
** The caller is responsible for ensuring that the allocated memory
|
|
** space is eventually freed.
|
|
**
|
|
** *pConchPath is set to NULL if a memory allocation error occurs.
|
|
*/
|
|
static int proxyCreateConchPathname(char *dbPath, char **pConchPath){
|
|
int i; /* Loop counter */
|
|
int len = (int)strlen(dbPath); /* Length of database filename - dbPath */
|
|
char *conchPath; /* buffer in which to construct conch name */
|
|
|
|
/* Allocate space for the conch filename and initialize the name to
|
|
** the name of the original database file. */
|
|
*pConchPath = conchPath = (char *)sqlite3_malloc64(len + 8);
|
|
if( conchPath==0 ){
|
|
return SQLITE_NOMEM_BKPT;
|
|
}
|
|
memcpy(conchPath, dbPath, len+1);
|
|
|
|
/* now insert a "." before the last / character */
|
|
for( i=(len-1); i>=0; i-- ){
|
|
if( conchPath[i]=='/' ){
|
|
i++;
|
|
break;
|
|
}
|
|
}
|
|
conchPath[i]='.';
|
|
while ( i<len ){
|
|
conchPath[i+1]=dbPath[i];
|
|
i++;
|
|
}
|
|
|
|
/* append the "-conch" suffix to the file */
|
|
memcpy(&conchPath[i+1], "-conch", 7);
|
|
assert( (int)strlen(conchPath) == len+7 );
|
|
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
|
|
/* Takes a fully configured proxy locking-style unix file and switches
|
|
** the local lock file path
|
|
*/
|
|
static int switchLockProxyPath(unixFile *pFile, const char *path) {
|
|
proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext;
|
|
char *oldPath = pCtx->lockProxyPath;
|
|
int rc = SQLITE_OK;
|
|
|
|
if( pFile->eFileLock!=NO_LOCK ){
|
|
return SQLITE_BUSY;
|
|
}
|
|
|
|
/* nothing to do if the path is NULL, :auto: or matches the existing path */
|
|
if( !path || path[0]=='\0' || !strcmp(path, ":auto:") ||
|
|
(oldPath && !strncmp(oldPath, path, MAXPATHLEN)) ){
|
|
return SQLITE_OK;
|
|
}else{
|
|
unixFile *lockProxy = pCtx->lockProxy;
|
|
pCtx->lockProxy=NULL;
|
|
pCtx->conchHeld = 0;
|
|
if( lockProxy!=NULL ){
|
|
rc=lockProxy->pMethod->xClose((sqlite3_file *)lockProxy);
|
|
if( rc ) return rc;
|
|
sqlite3_free(lockProxy);
|
|
}
|
|
sqlite3_free(oldPath);
|
|
pCtx->lockProxyPath = sqlite3DbStrDup(0, path);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** pFile is a file that has been opened by a prior xOpen call. dbPath
|
|
** is a string buffer at least MAXPATHLEN+1 characters in size.
|
|
**
|
|
** This routine find the filename associated with pFile and writes it
|
|
** int dbPath.
|
|
*/
|
|
static int proxyGetDbPathForUnixFile(unixFile *pFile, char *dbPath){
|
|
#if defined(__APPLE__)
|
|
if( pFile->pMethod == &afpIoMethods ){
|
|
/* afp style keeps a reference to the db path in the filePath field
|
|
** of the struct */
|
|
assert( (int)strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
|
|
strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath,
|
|
MAXPATHLEN);
|
|
} else
|
|
#endif
|
|
if( pFile->pMethod == &dotlockIoMethods ){
|
|
/* dot lock style uses the locking context to store the dot lock
|
|
** file path */
|
|
int len = strlen((char *)pFile->lockingContext) - strlen(DOTLOCK_SUFFIX);
|
|
memcpy(dbPath, (char *)pFile->lockingContext, len + 1);
|
|
}else{
|
|
/* all other styles use the locking context to store the db file path */
|
|
assert( strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
|
|
strlcpy(dbPath, (char *)pFile->lockingContext, MAXPATHLEN);
|
|
}
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Takes an already filled in unix file and alters it so all file locking
|
|
** will be performed on the local proxy lock file. The following fields
|
|
** are preserved in the locking context so that they can be restored and
|
|
** the unix structure properly cleaned up at close time:
|
|
** ->lockingContext
|
|
** ->pMethod
|
|
*/
|
|
static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
|
|
proxyLockingContext *pCtx;
|
|
char dbPath[MAXPATHLEN+1]; /* Name of the database file */
|
|
char *lockPath=NULL;
|
|
int rc = SQLITE_OK;
|
|
|
|
if( pFile->eFileLock!=NO_LOCK ){
|
|
return SQLITE_BUSY;
|
|
}
|
|
proxyGetDbPathForUnixFile(pFile, dbPath);
|
|
if( !path || path[0]=='\0' || !strcmp(path, ":auto:") ){
|
|
lockPath=NULL;
|
|
}else{
|
|
lockPath=(char *)path;
|
|
}
|
|
|
|
OSTRACE(("TRANSPROXY %d for %s pid=%d\n", pFile->h,
|
|
(lockPath ? lockPath : ":auto:"), osGetpid(0)));
|
|
|
|
pCtx = sqlite3_malloc64( sizeof(*pCtx) );
|
|
if( pCtx==0 ){
|
|
return SQLITE_NOMEM_BKPT;
|
|
}
|
|
memset(pCtx, 0, sizeof(*pCtx));
|
|
|
|
rc = proxyCreateConchPathname(dbPath, &pCtx->conchFilePath);
|
|
if( rc==SQLITE_OK ){
|
|
rc = proxyCreateUnixFile(pCtx->conchFilePath, &pCtx->conchFile, 0);
|
|
if( rc==SQLITE_CANTOPEN && ((pFile->openFlags&O_RDWR) == 0) ){
|
|
/* if (a) the open flags are not O_RDWR, (b) the conch isn't there, and
|
|
** (c) the file system is read-only, then enable no-locking access.
|
|
** Ugh, since O_RDONLY==0x0000 we test for !O_RDWR since unixOpen asserts
|
|
** that openFlags will have only one of O_RDONLY or O_RDWR.
|
|
*/
|
|
struct statfs fsInfo;
|
|
struct stat conchInfo;
|
|
int goLockless = 0;
|
|
|
|
if( osStat(pCtx->conchFilePath, &conchInfo) == -1 ) {
|
|
int err = errno;
|
|
if( (err==ENOENT) && (statfs(dbPath, &fsInfo) != -1) ){
|
|
goLockless = (fsInfo.f_flags&MNT_RDONLY) == MNT_RDONLY;
|
|
}
|
|
}
|
|
if( goLockless ){
|
|
pCtx->conchHeld = -1; /* read only FS/ lockless */
|
|
rc = SQLITE_OK;
|
|
}
|
|
}
|
|
}
|
|
if( rc==SQLITE_OK && lockPath ){
|
|
pCtx->lockProxyPath = sqlite3DbStrDup(0, lockPath);
|
|
}
|
|
|
|
if( rc==SQLITE_OK ){
|
|
pCtx->dbPath = sqlite3DbStrDup(0, dbPath);
|
|
if( pCtx->dbPath==NULL ){
|
|
rc = SQLITE_NOMEM_BKPT;
|
|
}
|
|
}
|
|
if( rc==SQLITE_OK ){
|
|
/* all memory is allocated, proxys are created and assigned,
|
|
** switch the locking context and pMethod then return.
|
|
*/
|
|
pCtx->oldLockingContext = pFile->lockingContext;
|
|
pFile->lockingContext = pCtx;
|
|
pCtx->pOldMethod = pFile->pMethod;
|
|
pFile->pMethod = &proxyIoMethods;
|
|
}else{
|
|
if( pCtx->conchFile ){
|
|
pCtx->conchFile->pMethod->xClose((sqlite3_file *)pCtx->conchFile);
|
|
sqlite3_free(pCtx->conchFile);
|
|
}
|
|
sqlite3DbFree(0, pCtx->lockProxyPath);
|
|
sqlite3_free(pCtx->conchFilePath);
|
|
sqlite3_free(pCtx);
|
|
}
|
|
OSTRACE(("TRANSPROXY %d %s\n", pFile->h,
|
|
(rc==SQLITE_OK ? "ok" : "failed")));
|
|
return rc;
|
|
}
|
|
|
|
|
|
/*
|
|
** This routine handles sqlite3_file_control() calls that are specific
|
|
** to proxy locking.
|
|
*/
|
|
static int proxyFileControl(sqlite3_file *id, int op, void *pArg){
|
|
switch( op ){
|
|
case SQLITE_FCNTL_GET_LOCKPROXYFILE: {
|
|
unixFile *pFile = (unixFile*)id;
|
|
if( pFile->pMethod == &proxyIoMethods ){
|
|
proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext;
|
|
proxyTakeConch(pFile);
|
|
if( pCtx->lockProxyPath ){
|
|
*(const char **)pArg = pCtx->lockProxyPath;
|
|
}else{
|
|
*(const char **)pArg = ":auto: (not held)";
|
|
}
|
|
} else {
|
|
*(const char **)pArg = NULL;
|
|
}
|
|
return SQLITE_OK;
|
|
}
|
|
case SQLITE_FCNTL_SET_LOCKPROXYFILE: {
|
|
unixFile *pFile = (unixFile*)id;
|
|
int rc = SQLITE_OK;
|
|
int isProxyStyle = (pFile->pMethod == &proxyIoMethods);
|
|
if( pArg==NULL || (const char *)pArg==0 ){
|
|
if( isProxyStyle ){
|
|
/* turn off proxy locking - not supported. If support is added for
|
|
** switching proxy locking mode off then it will need to fail if
|
|
** the journal mode is WAL mode.
|
|
*/
|
|
rc = SQLITE_ERROR /*SQLITE_PROTOCOL? SQLITE_MISUSE?*/;
|
|
}else{
|
|
/* turn off proxy locking - already off - NOOP */
|
|
rc = SQLITE_OK;
|
|
}
|
|
}else{
|
|
const char *proxyPath = (const char *)pArg;
|
|
if( isProxyStyle ){
|
|
proxyLockingContext *pCtx =
|
|
(proxyLockingContext*)pFile->lockingContext;
|
|
if( !strcmp(pArg, ":auto:")
|
|
|| (pCtx->lockProxyPath &&
|
|
!strncmp(pCtx->lockProxyPath, proxyPath, MAXPATHLEN))
|
|
){
|
|
rc = SQLITE_OK;
|
|
}else{
|
|
rc = switchLockProxyPath(pFile, proxyPath);
|
|
}
|
|
}else{
|
|
/* turn on proxy file locking */
|
|
rc = proxyTransformUnixFile(pFile, proxyPath);
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
default: {
|
|
assert( 0 ); /* The call assures that only valid opcodes are sent */
|
|
}
|
|
}
|
|
/*NOTREACHED*/ assert(0);
|
|
return SQLITE_ERROR;
|
|
}
|
|
|
|
/*
|
|
** Within this division (the proxying locking implementation) the procedures
|
|
** above this point are all utilities. The lock-related methods of the
|
|
** proxy-locking sqlite3_io_method object follow.
|
|
*/
|
|
|
|
|
|
/*
|
|
** 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, set *pResOut
|
|
** to a non-zero value otherwise *pResOut is set to zero. The return value
|
|
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
|
|
*/
|
|
static int proxyCheckReservedLock(sqlite3_file *id, int *pResOut) {
|
|
unixFile *pFile = (unixFile*)id;
|
|
int rc = proxyTakeConch(pFile);
|
|
if( rc==SQLITE_OK ){
|
|
proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
|
|
if( pCtx->conchHeld>0 ){
|
|
unixFile *proxy = pCtx->lockProxy;
|
|
return proxy->pMethod->xCheckReservedLock((sqlite3_file*)proxy, pResOut);
|
|
}else{ /* conchHeld < 0 is lockless */
|
|
pResOut=0;
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Lock the file with the lock specified by parameter eFileLock - 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 proxyLock(sqlite3_file *id, int eFileLock) {
|
|
unixFile *pFile = (unixFile*)id;
|
|
int rc = proxyTakeConch(pFile);
|
|
if( rc==SQLITE_OK ){
|
|
proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
|
|
if( pCtx->conchHeld>0 ){
|
|
unixFile *proxy = pCtx->lockProxy;
|
|
rc = proxy->pMethod->xLock((sqlite3_file*)proxy, eFileLock);
|
|
pFile->eFileLock = proxy->eFileLock;
|
|
}else{
|
|
/* conchHeld < 0 is lockless */
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
|
|
/*
|
|
** Lower the locking level on file descriptor pFile to eFileLock. eFileLock
|
|
** 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 proxyUnlock(sqlite3_file *id, int eFileLock) {
|
|
unixFile *pFile = (unixFile*)id;
|
|
int rc = proxyTakeConch(pFile);
|
|
if( rc==SQLITE_OK ){
|
|
proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
|
|
if( pCtx->conchHeld>0 ){
|
|
unixFile *proxy = pCtx->lockProxy;
|
|
rc = proxy->pMethod->xUnlock((sqlite3_file*)proxy, eFileLock);
|
|
pFile->eFileLock = proxy->eFileLock;
|
|
}else{
|
|
/* conchHeld < 0 is lockless */
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Close a file that uses proxy locks.
|
|
*/
|
|
static int proxyClose(sqlite3_file *id) {
|
|
if( ALWAYS(id) ){
|
|
unixFile *pFile = (unixFile*)id;
|
|
proxyLockingContext *pCtx = (proxyLockingContext *)pFile->lockingContext;
|
|
unixFile *lockProxy = pCtx->lockProxy;
|
|
unixFile *conchFile = pCtx->conchFile;
|
|
int rc = SQLITE_OK;
|
|
|
|
if( lockProxy ){
|
|
rc = lockProxy->pMethod->xUnlock((sqlite3_file*)lockProxy, NO_LOCK);
|
|
if( rc ) return rc;
|
|
rc = lockProxy->pMethod->xClose((sqlite3_file*)lockProxy);
|
|
if( rc ) return rc;
|
|
sqlite3_free(lockProxy);
|
|
pCtx->lockProxy = 0;
|
|
}
|
|
if( conchFile ){
|
|
if( pCtx->conchHeld ){
|
|
rc = proxyReleaseConch(pFile);
|
|
if( rc ) return rc;
|
|
}
|
|
rc = conchFile->pMethod->xClose((sqlite3_file*)conchFile);
|
|
if( rc ) return rc;
|
|
sqlite3_free(conchFile);
|
|
}
|
|
sqlite3DbFree(0, pCtx->lockProxyPath);
|
|
sqlite3_free(pCtx->conchFilePath);
|
|
sqlite3DbFree(0, pCtx->dbPath);
|
|
/* restore the original locking context and pMethod then close it */
|
|
pFile->lockingContext = pCtx->oldLockingContext;
|
|
pFile->pMethod = pCtx->pOldMethod;
|
|
sqlite3_free(pCtx);
|
|
return pFile->pMethod->xClose(id);
|
|
}
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
|
|
|
|
#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
|
|
/*
|
|
** The proxy locking style is intended for use with AFP filesystems.
|
|
** And since AFP is only supported on MacOSX, the proxy locking is also
|
|
** restricted to MacOSX.
|
|
**
|
|
**
|
|
******************* End of the proxy lock implementation **********************
|
|
******************************************************************************/
|
|
|
|
/*
|
|
** Initialize the operating system interface.
|
|
**
|
|
** This routine registers all VFS implementations for unix-like operating
|
|
** systems. This routine, and the sqlite3_os_end() routine that follows,
|
|
** should be the only routines in this file that are visible from other
|
|
** files.
|
|
**
|
|
** This routine is called once during SQLite initialization and by a
|
|
** single thread. The memory allocation and mutex subsystems have not
|
|
** necessarily been initialized when this routine is called, and so they
|
|
** should not be used.
|
|
*/
|
|
SQLITE_API int sqlite3_os_init(void){
|
|
/*
|
|
** The following macro defines an initializer for an sqlite3_vfs object.
|
|
** The name of the VFS is NAME. The pAppData is a pointer to a pointer
|
|
** to the "finder" function. (pAppData is a pointer to a pointer because
|
|
** silly C90 rules prohibit a void* from being cast to a function pointer
|
|
** and so we have to go through the intermediate pointer to avoid problems
|
|
** when compiling with -pedantic-errors on GCC.)
|
|
**
|
|
** The FINDER parameter to this macro is the name of the pointer to the
|
|
** finder-function. The finder-function returns a pointer to the
|
|
** sqlite_io_methods object that implements the desired locking
|
|
** behaviors. See the division above that contains the IOMETHODS
|
|
** macro for addition information on finder-functions.
|
|
**
|
|
** Most finders simply return a pointer to a fixed sqlite3_io_methods
|
|
** object. But the "autolockIoFinder" available on MacOSX does a little
|
|
** more than that; it looks at the filesystem type that hosts the
|
|
** database file and tries to choose an locking method appropriate for
|
|
** that filesystem time.
|
|
*/
|
|
#define UNIXVFS(VFSNAME, FINDER) { \
|
|
3, /* iVersion */ \
|
|
sizeof(unixFile), /* szOsFile */ \
|
|
MAX_PATHNAME, /* mxPathname */ \
|
|
0, /* pNext */ \
|
|
VFSNAME, /* zName */ \
|
|
(void*)&FINDER, /* pAppData */ \
|
|
unixOpen, /* xOpen */ \
|
|
unixDelete, /* xDelete */ \
|
|
unixAccess, /* xAccess */ \
|
|
unixFullPathname, /* xFullPathname */ \
|
|
unixDlOpen, /* xDlOpen */ \
|
|
unixDlError, /* xDlError */ \
|
|
unixDlSym, /* xDlSym */ \
|
|
unixDlClose, /* xDlClose */ \
|
|
unixRandomness, /* xRandomness */ \
|
|
unixSleep, /* xSleep */ \
|
|
unixCurrentTime, /* xCurrentTime */ \
|
|
unixGetLastError, /* xGetLastError */ \
|
|
unixCurrentTimeInt64, /* xCurrentTimeInt64 */ \
|
|
unixSetSystemCall, /* xSetSystemCall */ \
|
|
unixGetSystemCall, /* xGetSystemCall */ \
|
|
unixNextSystemCall, /* xNextSystemCall */ \
|
|
}
|
|
|
|
/*
|
|
** All default VFSes for unix are contained in the following array.
|
|
**
|
|
** Note that the sqlite3_vfs.pNext field of the VFS object is modified
|
|
** by the SQLite core when the VFS is registered. So the following
|
|
** array cannot be const.
|
|
*/
|
|
static sqlite3_vfs aVfs[] = {
|
|
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
|
|
UNIXVFS("unix", autolockIoFinder ),
|
|
#elif OS_VXWORKS
|
|
UNIXVFS("unix", vxworksIoFinder ),
|
|
#else
|
|
UNIXVFS("unix", posixIoFinder ),
|
|
#endif
|
|
UNIXVFS("unix-none", nolockIoFinder ),
|
|
UNIXVFS("unix-dotfile", dotlockIoFinder ),
|
|
UNIXVFS("unix-excl", posixIoFinder ),
|
|
#if OS_VXWORKS
|
|
UNIXVFS("unix-namedsem", semIoFinder ),
|
|
#endif
|
|
#if SQLITE_ENABLE_LOCKING_STYLE || OS_VXWORKS
|
|
UNIXVFS("unix-posix", posixIoFinder ),
|
|
#endif
|
|
#if SQLITE_ENABLE_LOCKING_STYLE
|
|
UNIXVFS("unix-flock", flockIoFinder ),
|
|
#endif
|
|
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
|
|
UNIXVFS("unix-afp", afpIoFinder ),
|
|
UNIXVFS("unix-nfs", nfsIoFinder ),
|
|
UNIXVFS("unix-proxy", proxyIoFinder ),
|
|
#endif
|
|
};
|
|
unsigned int i; /* Loop counter */
|
|
|
|
/* Double-check that the aSyscall[] array has been constructed
|
|
** correctly. See ticket [bb3a86e890c8e96ab] */
|
|
assert( ArraySize(aSyscall)==29 );
|
|
|
|
/* Register all VFSes defined in the aVfs[] array */
|
|
for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
|
|
#ifdef SQLITE_DEFAULT_UNIX_VFS
|
|
sqlite3_vfs_register(&aVfs[i],
|
|
0==strcmp(aVfs[i].zName,SQLITE_DEFAULT_UNIX_VFS));
|
|
#else
|
|
sqlite3_vfs_register(&aVfs[i], i==0);
|
|
#endif
|
|
}
|
|
#ifdef SQLITE_OS_KV_OPTIONAL
|
|
sqlite3KvvfsInit();
|
|
#endif
|
|
unixBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
|
|
|
|
#ifndef SQLITE_OMIT_WAL
|
|
/* Validate lock assumptions */
|
|
assert( SQLITE_SHM_NLOCK==8 ); /* Number of available locks */
|
|
assert( UNIX_SHM_BASE==120 ); /* Start of locking area */
|
|
/* Locks:
|
|
** WRITE UNIX_SHM_BASE 120
|
|
** CKPT UNIX_SHM_BASE+1 121
|
|
** RECOVER UNIX_SHM_BASE+2 122
|
|
** READ-0 UNIX_SHM_BASE+3 123
|
|
** READ-1 UNIX_SHM_BASE+4 124
|
|
** READ-2 UNIX_SHM_BASE+5 125
|
|
** READ-3 UNIX_SHM_BASE+6 126
|
|
** READ-4 UNIX_SHM_BASE+7 127
|
|
** DMS UNIX_SHM_BASE+8 128
|
|
*/
|
|
assert( UNIX_SHM_DMS==128 ); /* Byte offset of the deadman-switch */
|
|
#endif
|
|
|
|
/* Initialize temp file dir array. */
|
|
unixTempFileInit();
|
|
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Shutdown the operating system interface.
|
|
**
|
|
** Some operating systems might need to do some cleanup in this routine,
|
|
** to release dynamically allocated objects. But not on unix.
|
|
** This routine is a no-op for unix.
|
|
*/
|
|
SQLITE_API int sqlite3_os_end(void){
|
|
unixBigLock = 0;
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
#endif /* SQLITE_OS_UNIX */
|
|
|
|
/************** End of os_unix.c *********************************************/
|
|
/************** Begin file os_win.c ******************************************/
|
|
/*
|
|
** 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" */
|
|
#if SQLITE_OS_WIN /* This file is used for Windows only */
|
|
|
|
/*
|
|
** Include code that is common to all os_*.c files
|
|
*/
|
|
/* #include "os_common.h" */
|
|
|
|
/*
|
|
** Include the header file for the Windows VFS.
|
|
*/
|
|
/* #include "os_win.h" */
|
|
|
|
/*
|
|
** Compiling and using WAL mode requires several APIs that are only
|
|
** available in Windows platforms based on the NT kernel.
|
|
*/
|
|
#if !SQLITE_OS_WINNT && !defined(SQLITE_OMIT_WAL)
|
|
# error "WAL mode requires support from the Windows NT kernel, compile\
|
|
with SQLITE_OMIT_WAL."
|
|
#endif
|
|
|
|
#if !SQLITE_OS_WINNT && SQLITE_MAX_MMAP_SIZE>0
|
|
# error "Memory mapped files require support from the Windows NT kernel,\
|
|
compile with SQLITE_MAX_MMAP_SIZE=0."
|
|
#endif
|
|
|
|
/*
|
|
** Are most of the Win32 ANSI APIs available (i.e. with certain exceptions
|
|
** based on the sub-platform)?
|
|
*/
|
|
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(SQLITE_WIN32_NO_ANSI)
|
|
# define SQLITE_WIN32_HAS_ANSI
|
|
#endif
|
|
|
|
/*
|
|
** Are most of the Win32 Unicode APIs available (i.e. with certain exceptions
|
|
** based on the sub-platform)?
|
|
*/
|
|
#if (SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT) && \
|
|
!defined(SQLITE_WIN32_NO_WIDE)
|
|
# define SQLITE_WIN32_HAS_WIDE
|
|
#endif
|
|
|
|
/*
|
|
** Make sure at least one set of Win32 APIs is available.
|
|
*/
|
|
#if !defined(SQLITE_WIN32_HAS_ANSI) && !defined(SQLITE_WIN32_HAS_WIDE)
|
|
# error "At least one of SQLITE_WIN32_HAS_ANSI and SQLITE_WIN32_HAS_WIDE\
|
|
must be defined."
|
|
#endif
|
|
|
|
/*
|
|
** Define the required Windows SDK version constants if they are not
|
|
** already available.
|
|
*/
|
|
#ifndef NTDDI_WIN8
|
|
# define NTDDI_WIN8 0x06020000
|
|
#endif
|
|
|
|
#ifndef NTDDI_WINBLUE
|
|
# define NTDDI_WINBLUE 0x06030000
|
|
#endif
|
|
|
|
#ifndef NTDDI_WINTHRESHOLD
|
|
# define NTDDI_WINTHRESHOLD 0x06040000
|
|
#endif
|
|
|
|
/*
|
|
** Check to see if the GetVersionEx[AW] functions are deprecated on the
|
|
** target system. GetVersionEx was first deprecated in Win8.1.
|
|
*/
|
|
#ifndef SQLITE_WIN32_GETVERSIONEX
|
|
# if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WINBLUE
|
|
# define SQLITE_WIN32_GETVERSIONEX 0 /* GetVersionEx() is deprecated */
|
|
# else
|
|
# define SQLITE_WIN32_GETVERSIONEX 1 /* GetVersionEx() is current */
|
|
# endif
|
|
#endif
|
|
|
|
/*
|
|
** Check to see if the CreateFileMappingA function is supported on the
|
|
** target system. It is unavailable when using "mincore.lib" on Win10.
|
|
** When compiling for Windows 10, always assume "mincore.lib" is in use.
|
|
*/
|
|
#ifndef SQLITE_WIN32_CREATEFILEMAPPINGA
|
|
# if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WINTHRESHOLD
|
|
# define SQLITE_WIN32_CREATEFILEMAPPINGA 0
|
|
# else
|
|
# define SQLITE_WIN32_CREATEFILEMAPPINGA 1
|
|
# endif
|
|
#endif
|
|
|
|
/*
|
|
** This constant should already be defined (in the "WinDef.h" SDK file).
|
|
*/
|
|
#ifndef MAX_PATH
|
|
# define MAX_PATH (260)
|
|
#endif
|
|
|
|
/*
|
|
** Maximum pathname length (in chars) for Win32. This should normally be
|
|
** MAX_PATH.
|
|
*/
|
|
#ifndef SQLITE_WIN32_MAX_PATH_CHARS
|
|
# define SQLITE_WIN32_MAX_PATH_CHARS (MAX_PATH)
|
|
#endif
|
|
|
|
/*
|
|
** This constant should already be defined (in the "WinNT.h" SDK file).
|
|
*/
|
|
#ifndef UNICODE_STRING_MAX_CHARS
|
|
# define UNICODE_STRING_MAX_CHARS (32767)
|
|
#endif
|
|
|
|
/*
|
|
** Maximum pathname length (in chars) for WinNT. This should normally be
|
|
** UNICODE_STRING_MAX_CHARS.
|
|
*/
|
|
#ifndef SQLITE_WINNT_MAX_PATH_CHARS
|
|
# define SQLITE_WINNT_MAX_PATH_CHARS (UNICODE_STRING_MAX_CHARS)
|
|
#endif
|
|
|
|
/*
|
|
** Maximum pathname length (in bytes) for Win32. The MAX_PATH macro is in
|
|
** characters, so we allocate 4 bytes per character assuming worst-case of
|
|
** 4-bytes-per-character for UTF8.
|
|
*/
|
|
#ifndef SQLITE_WIN32_MAX_PATH_BYTES
|
|
# define SQLITE_WIN32_MAX_PATH_BYTES (SQLITE_WIN32_MAX_PATH_CHARS*4)
|
|
#endif
|
|
|
|
/*
|
|
** Maximum pathname length (in bytes) for WinNT. This should normally be
|
|
** UNICODE_STRING_MAX_CHARS * sizeof(WCHAR).
|
|
*/
|
|
#ifndef SQLITE_WINNT_MAX_PATH_BYTES
|
|
# define SQLITE_WINNT_MAX_PATH_BYTES \
|
|
(sizeof(WCHAR) * SQLITE_WINNT_MAX_PATH_CHARS)
|
|
#endif
|
|
|
|
/*
|
|
** Maximum error message length (in chars) for WinRT.
|
|
*/
|
|
#ifndef SQLITE_WIN32_MAX_ERRMSG_CHARS
|
|
# define SQLITE_WIN32_MAX_ERRMSG_CHARS (1024)
|
|
#endif
|
|
|
|
/*
|
|
** Returns non-zero if the character should be treated as a directory
|
|
** separator.
|
|
*/
|
|
#ifndef winIsDirSep
|
|
# define winIsDirSep(a) (((a) == '/') || ((a) == '\\'))
|
|
#endif
|
|
|
|
/*
|
|
** This macro is used when a local variable is set to a value that is
|
|
** [sometimes] not used by the code (e.g. via conditional compilation).
|
|
*/
|
|
#ifndef UNUSED_VARIABLE_VALUE
|
|
# define UNUSED_VARIABLE_VALUE(x) (void)(x)
|
|
#endif
|
|
|
|
/*
|
|
** Returns the character that should be used as the directory separator.
|
|
*/
|
|
#ifndef winGetDirSep
|
|
# define winGetDirSep() '\\'
|
|
#endif
|
|
|
|
/*
|
|
** Do we need to manually define the Win32 file mapping APIs for use with WAL
|
|
** mode or memory mapped files (e.g. these APIs are available in the Windows
|
|
** CE SDK; however, they are not present in the header file)?
|
|
*/
|
|
#if SQLITE_WIN32_FILEMAPPING_API && \
|
|
(!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)
|
|
/*
|
|
** Two of the file mapping APIs are different under WinRT. Figure out which
|
|
** set we need.
|
|
*/
|
|
#if SQLITE_OS_WINRT
|
|
WINBASEAPI HANDLE WINAPI CreateFileMappingFromApp(HANDLE, \
|
|
LPSECURITY_ATTRIBUTES, ULONG, ULONG64, LPCWSTR);
|
|
|
|
WINBASEAPI LPVOID WINAPI MapViewOfFileFromApp(HANDLE, ULONG, ULONG64, SIZE_T);
|
|
#else
|
|
#if defined(SQLITE_WIN32_HAS_ANSI)
|
|
WINBASEAPI HANDLE WINAPI CreateFileMappingA(HANDLE, LPSECURITY_ATTRIBUTES, \
|
|
DWORD, DWORD, DWORD, LPCSTR);
|
|
#endif /* defined(SQLITE_WIN32_HAS_ANSI) */
|
|
|
|
#if defined(SQLITE_WIN32_HAS_WIDE)
|
|
WINBASEAPI HANDLE WINAPI CreateFileMappingW(HANDLE, LPSECURITY_ATTRIBUTES, \
|
|
DWORD, DWORD, DWORD, LPCWSTR);
|
|
#endif /* defined(SQLITE_WIN32_HAS_WIDE) */
|
|
|
|
WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T);
|
|
#endif /* SQLITE_OS_WINRT */
|
|
|
|
/*
|
|
** These file mapping APIs are common to both Win32 and WinRT.
|
|
*/
|
|
|
|
WINBASEAPI BOOL WINAPI FlushViewOfFile(LPCVOID, SIZE_T);
|
|
WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID);
|
|
#endif /* SQLITE_WIN32_FILEMAPPING_API */
|
|
|
|
/*
|
|
** Some Microsoft compilers lack this definition.
|
|
*/
|
|
#ifndef INVALID_FILE_ATTRIBUTES
|
|
# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
|
|
#endif
|
|
|
|
#ifndef FILE_FLAG_MASK
|
|
# define FILE_FLAG_MASK (0xFF3C0000)
|
|
#endif
|
|
|
|
#ifndef FILE_ATTRIBUTE_MASK
|
|
# define FILE_ATTRIBUTE_MASK (0x0003FFF7)
|
|
#endif
|
|
|
|
#ifndef SQLITE_OMIT_WAL
|
|
/* Forward references to structures used for WAL */
|
|
typedef struct winShm winShm; /* A connection to shared-memory */
|
|
typedef struct winShmNode winShmNode; /* A region of shared-memory */
|
|
#endif
|
|
|
|
/*
|
|
** WinCE lacks native support for file locking so we have to fake it
|
|
** with some code of our own.
|
|
*/
|
|
#if SQLITE_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 sqlite3_file* specific to the win32
|
|
** portability layer.
|
|
*/
|
|
typedef struct winFile winFile;
|
|
struct winFile {
|
|
const sqlite3_io_methods *pMethod; /*** Must be first ***/
|
|
sqlite3_vfs *pVfs; /* The VFS used to open this file */
|
|
HANDLE h; /* Handle for accessing the file */
|
|
u8 locktype; /* Type of lock currently held on this file */
|
|
short sharedLockByte; /* Randomly chosen byte used as a shared lock */
|
|
u8 ctrlFlags; /* Flags. See WINFILE_* below */
|
|
DWORD lastErrno; /* The Windows errno from the last I/O error */
|
|
#ifndef SQLITE_OMIT_WAL
|
|
winShm *pShm; /* Instance of shared memory on this file */
|
|
#endif
|
|
const char *zPath; /* Full pathname of this file */
|
|
int szChunk; /* Chunk size configured by FCNTL_CHUNK_SIZE */
|
|
#if SQLITE_OS_WINCE
|
|
LPWSTR 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
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
int nFetchOut; /* Number of outstanding xFetch references */
|
|
HANDLE hMap; /* Handle for accessing memory mapping */
|
|
void *pMapRegion; /* Area memory mapped */
|
|
sqlite3_int64 mmapSize; /* Size of mapped region */
|
|
sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */
|
|
#endif
|
|
};
|
|
|
|
/*
|
|
** The winVfsAppData structure is used for the pAppData member for all of the
|
|
** Win32 VFS variants.
|
|
*/
|
|
typedef struct winVfsAppData winVfsAppData;
|
|
struct winVfsAppData {
|
|
const sqlite3_io_methods *pMethod; /* The file I/O methods to use. */
|
|
void *pAppData; /* The extra pAppData, if any. */
|
|
BOOL bNoLock; /* Non-zero if locking is disabled. */
|
|
};
|
|
|
|
/*
|
|
** Allowed values for winFile.ctrlFlags
|
|
*/
|
|
#define WINFILE_RDONLY 0x02 /* Connection is read only */
|
|
#define WINFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */
|
|
#define WINFILE_PSOW 0x10 /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
|
|
|
|
/*
|
|
* The size of the buffer used by sqlite3_win32_write_debug().
|
|
*/
|
|
#ifndef SQLITE_WIN32_DBG_BUF_SIZE
|
|
# define SQLITE_WIN32_DBG_BUF_SIZE ((int)(4096-sizeof(DWORD)))
|
|
#endif
|
|
|
|
/*
|
|
* If compiled with SQLITE_WIN32_MALLOC on Windows, we will use the
|
|
* various Win32 API heap functions instead of our own.
|
|
*/
|
|
#ifdef SQLITE_WIN32_MALLOC
|
|
|
|
/*
|
|
* If this is non-zero, an isolated heap will be created by the native Win32
|
|
* allocator subsystem; otherwise, the default process heap will be used. This
|
|
* setting has no effect when compiling for WinRT. By default, this is enabled
|
|
* and an isolated heap will be created to store all allocated data.
|
|
*
|
|
******************************************************************************
|
|
* WARNING: It is important to note that when this setting is non-zero and the
|
|
* winMemShutdown function is called (e.g. by the sqlite3_shutdown
|
|
* function), all data that was allocated using the isolated heap will
|
|
* be freed immediately and any attempt to access any of that freed
|
|
* data will almost certainly result in an immediate access violation.
|
|
******************************************************************************
|
|
*/
|
|
#ifndef SQLITE_WIN32_HEAP_CREATE
|
|
# define SQLITE_WIN32_HEAP_CREATE (TRUE)
|
|
#endif
|
|
|
|
/*
|
|
* This is the maximum possible initial size of the Win32-specific heap, in
|
|
* bytes.
|
|
*/
|
|
#ifndef SQLITE_WIN32_HEAP_MAX_INIT_SIZE
|
|
# define SQLITE_WIN32_HEAP_MAX_INIT_SIZE (4294967295U)
|
|
#endif
|
|
|
|
/*
|
|
* This is the extra space for the initial size of the Win32-specific heap,
|
|
* in bytes. This value may be zero.
|
|
*/
|
|
#ifndef SQLITE_WIN32_HEAP_INIT_EXTRA
|
|
# define SQLITE_WIN32_HEAP_INIT_EXTRA (4194304)
|
|
#endif
|
|
|
|
/*
|
|
* Calculate the maximum legal cache size, in pages, based on the maximum
|
|
* possible initial heap size and the default page size, setting aside the
|
|
* needed extra space.
|
|
*/
|
|
#ifndef SQLITE_WIN32_MAX_CACHE_SIZE
|
|
# define SQLITE_WIN32_MAX_CACHE_SIZE (((SQLITE_WIN32_HEAP_MAX_INIT_SIZE) - \
|
|
(SQLITE_WIN32_HEAP_INIT_EXTRA)) / \
|
|
(SQLITE_DEFAULT_PAGE_SIZE))
|
|
#endif
|
|
|
|
/*
|
|
* This is cache size used in the calculation of the initial size of the
|
|
* Win32-specific heap. It cannot be negative.
|
|
*/
|
|
#ifndef SQLITE_WIN32_CACHE_SIZE
|
|
# if SQLITE_DEFAULT_CACHE_SIZE>=0
|
|
# define SQLITE_WIN32_CACHE_SIZE (SQLITE_DEFAULT_CACHE_SIZE)
|
|
# else
|
|
# define SQLITE_WIN32_CACHE_SIZE (-(SQLITE_DEFAULT_CACHE_SIZE))
|
|
# endif
|
|
#endif
|
|
|
|
/*
|
|
* Make sure that the calculated cache size, in pages, cannot cause the
|
|
* initial size of the Win32-specific heap to exceed the maximum amount
|
|
* of memory that can be specified in the call to HeapCreate.
|
|
*/
|
|
#if SQLITE_WIN32_CACHE_SIZE>SQLITE_WIN32_MAX_CACHE_SIZE
|
|
# undef SQLITE_WIN32_CACHE_SIZE
|
|
# define SQLITE_WIN32_CACHE_SIZE (2000)
|
|
#endif
|
|
|
|
/*
|
|
* The initial size of the Win32-specific heap. This value may be zero.
|
|
*/
|
|
#ifndef SQLITE_WIN32_HEAP_INIT_SIZE
|
|
# define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_WIN32_CACHE_SIZE) * \
|
|
(SQLITE_DEFAULT_PAGE_SIZE) + \
|
|
(SQLITE_WIN32_HEAP_INIT_EXTRA))
|
|
#endif
|
|
|
|
/*
|
|
* The maximum size of the Win32-specific heap. This value may be zero.
|
|
*/
|
|
#ifndef SQLITE_WIN32_HEAP_MAX_SIZE
|
|
# define SQLITE_WIN32_HEAP_MAX_SIZE (0)
|
|
#endif
|
|
|
|
/*
|
|
* The extra flags to use in calls to the Win32 heap APIs. This value may be
|
|
* zero for the default behavior.
|
|
*/
|
|
#ifndef SQLITE_WIN32_HEAP_FLAGS
|
|
# define SQLITE_WIN32_HEAP_FLAGS (0)
|
|
#endif
|
|
|
|
|
|
/*
|
|
** The winMemData structure stores information required by the Win32-specific
|
|
** sqlite3_mem_methods implementation.
|
|
*/
|
|
typedef struct winMemData winMemData;
|
|
struct winMemData {
|
|
#ifndef NDEBUG
|
|
u32 magic1; /* Magic number to detect structure corruption. */
|
|
#endif
|
|
HANDLE hHeap; /* The handle to our heap. */
|
|
BOOL bOwned; /* Do we own the heap (i.e. destroy it on shutdown)? */
|
|
#ifndef NDEBUG
|
|
u32 magic2; /* Magic number to detect structure corruption. */
|
|
#endif
|
|
};
|
|
|
|
#ifndef NDEBUG
|
|
#define WINMEM_MAGIC1 0x42b2830b
|
|
#define WINMEM_MAGIC2 0xbd4d7cf4
|
|
#endif
|
|
|
|
static struct winMemData win_mem_data = {
|
|
#ifndef NDEBUG
|
|
WINMEM_MAGIC1,
|
|
#endif
|
|
NULL, FALSE
|
|
#ifndef NDEBUG
|
|
,WINMEM_MAGIC2
|
|
#endif
|
|
};
|
|
|
|
#ifndef NDEBUG
|
|
#define winMemAssertMagic1() assert( win_mem_data.magic1==WINMEM_MAGIC1 )
|
|
#define winMemAssertMagic2() assert( win_mem_data.magic2==WINMEM_MAGIC2 )
|
|
#define winMemAssertMagic() winMemAssertMagic1(); winMemAssertMagic2();
|
|
#else
|
|
#define winMemAssertMagic()
|
|
#endif
|
|
|
|
#define winMemGetDataPtr() &win_mem_data
|
|
#define winMemGetHeap() win_mem_data.hHeap
|
|
#define winMemGetOwned() win_mem_data.bOwned
|
|
|
|
static void *winMemMalloc(int nBytes);
|
|
static void winMemFree(void *pPrior);
|
|
static void *winMemRealloc(void *pPrior, int nBytes);
|
|
static int winMemSize(void *p);
|
|
static int winMemRoundup(int n);
|
|
static int winMemInit(void *pAppData);
|
|
static void winMemShutdown(void *pAppData);
|
|
|
|
SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetWin32(void);
|
|
#endif /* SQLITE_WIN32_MALLOC */
|
|
|
|
/*
|
|
** The following variable is (normally) set once and never changes
|
|
** thereafter. It records whether the operating system is Win9x
|
|
** or WinNT.
|
|
**
|
|
** 0: Operating system unknown.
|
|
** 1: Operating system is Win9x.
|
|
** 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.
|
|
*/
|
|
#ifdef SQLITE_TEST
|
|
SQLITE_API LONG SQLITE_WIN32_VOLATILE sqlite3_os_type = 0;
|
|
#else
|
|
static LONG SQLITE_WIN32_VOLATILE sqlite3_os_type = 0;
|
|
#endif
|
|
|
|
#ifndef SYSCALL
|
|
# define SYSCALL sqlite3_syscall_ptr
|
|
#endif
|
|
|
|
/*
|
|
** This function is not available on Windows CE or WinRT.
|
|
*/
|
|
|
|
#if SQLITE_OS_WINCE || SQLITE_OS_WINRT
|
|
# define osAreFileApisANSI() 1
|
|
#endif
|
|
|
|
/*
|
|
** Many system calls are accessed through pointer-to-functions so that
|
|
** they may be overridden at runtime to facilitate fault injection during
|
|
** testing and sandboxing. The following array holds the names and pointers
|
|
** to all overrideable system calls.
|
|
*/
|
|
static struct win_syscall {
|
|
const char *zName; /* Name of the system call */
|
|
sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
|
|
sqlite3_syscall_ptr pDefault; /* Default value */
|
|
} aSyscall[] = {
|
|
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
|
|
{ "AreFileApisANSI", (SYSCALL)AreFileApisANSI, 0 },
|
|
#else
|
|
{ "AreFileApisANSI", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#ifndef osAreFileApisANSI
|
|
#define osAreFileApisANSI ((BOOL(WINAPI*)(VOID))aSyscall[0].pCurrent)
|
|
#endif
|
|
|
|
#if SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE)
|
|
{ "CharLowerW", (SYSCALL)CharLowerW, 0 },
|
|
#else
|
|
{ "CharLowerW", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osCharLowerW ((LPWSTR(WINAPI*)(LPWSTR))aSyscall[1].pCurrent)
|
|
|
|
#if SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE)
|
|
{ "CharUpperW", (SYSCALL)CharUpperW, 0 },
|
|
#else
|
|
{ "CharUpperW", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osCharUpperW ((LPWSTR(WINAPI*)(LPWSTR))aSyscall[2].pCurrent)
|
|
|
|
{ "CloseHandle", (SYSCALL)CloseHandle, 0 },
|
|
|
|
#define osCloseHandle ((BOOL(WINAPI*)(HANDLE))aSyscall[3].pCurrent)
|
|
|
|
#if defined(SQLITE_WIN32_HAS_ANSI)
|
|
{ "CreateFileA", (SYSCALL)CreateFileA, 0 },
|
|
#else
|
|
{ "CreateFileA", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osCreateFileA ((HANDLE(WINAPI*)(LPCSTR,DWORD,DWORD, \
|
|
LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[4].pCurrent)
|
|
|
|
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
|
|
{ "CreateFileW", (SYSCALL)CreateFileW, 0 },
|
|
#else
|
|
{ "CreateFileW", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \
|
|
LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent)
|
|
|
|
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \
|
|
(!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) && \
|
|
SQLITE_WIN32_CREATEFILEMAPPINGA
|
|
{ "CreateFileMappingA", (SYSCALL)CreateFileMappingA, 0 },
|
|
#else
|
|
{ "CreateFileMappingA", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osCreateFileMappingA ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
|
|
DWORD,DWORD,DWORD,LPCSTR))aSyscall[6].pCurrent)
|
|
|
|
#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
|
|
(!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0))
|
|
{ "CreateFileMappingW", (SYSCALL)CreateFileMappingW, 0 },
|
|
#else
|
|
{ "CreateFileMappingW", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osCreateFileMappingW ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
|
|
DWORD,DWORD,DWORD,LPCWSTR))aSyscall[7].pCurrent)
|
|
|
|
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
|
|
{ "CreateMutexW", (SYSCALL)CreateMutexW, 0 },
|
|
#else
|
|
{ "CreateMutexW", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osCreateMutexW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,BOOL, \
|
|
LPCWSTR))aSyscall[8].pCurrent)
|
|
|
|
#if defined(SQLITE_WIN32_HAS_ANSI)
|
|
{ "DeleteFileA", (SYSCALL)DeleteFileA, 0 },
|
|
#else
|
|
{ "DeleteFileA", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osDeleteFileA ((BOOL(WINAPI*)(LPCSTR))aSyscall[9].pCurrent)
|
|
|
|
#if defined(SQLITE_WIN32_HAS_WIDE)
|
|
{ "DeleteFileW", (SYSCALL)DeleteFileW, 0 },
|
|
#else
|
|
{ "DeleteFileW", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osDeleteFileW ((BOOL(WINAPI*)(LPCWSTR))aSyscall[10].pCurrent)
|
|
|
|
#if SQLITE_OS_WINCE
|
|
{ "FileTimeToLocalFileTime", (SYSCALL)FileTimeToLocalFileTime, 0 },
|
|
#else
|
|
{ "FileTimeToLocalFileTime", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osFileTimeToLocalFileTime ((BOOL(WINAPI*)(CONST FILETIME*, \
|
|
LPFILETIME))aSyscall[11].pCurrent)
|
|
|
|
#if SQLITE_OS_WINCE
|
|
{ "FileTimeToSystemTime", (SYSCALL)FileTimeToSystemTime, 0 },
|
|
#else
|
|
{ "FileTimeToSystemTime", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osFileTimeToSystemTime ((BOOL(WINAPI*)(CONST FILETIME*, \
|
|
LPSYSTEMTIME))aSyscall[12].pCurrent)
|
|
|
|
{ "FlushFileBuffers", (SYSCALL)FlushFileBuffers, 0 },
|
|
|
|
#define osFlushFileBuffers ((BOOL(WINAPI*)(HANDLE))aSyscall[13].pCurrent)
|
|
|
|
#if defined(SQLITE_WIN32_HAS_ANSI)
|
|
{ "FormatMessageA", (SYSCALL)FormatMessageA, 0 },
|
|
#else
|
|
{ "FormatMessageA", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osFormatMessageA ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPSTR, \
|
|
DWORD,va_list*))aSyscall[14].pCurrent)
|
|
|
|
#if defined(SQLITE_WIN32_HAS_WIDE)
|
|
{ "FormatMessageW", (SYSCALL)FormatMessageW, 0 },
|
|
#else
|
|
{ "FormatMessageW", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osFormatMessageW ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPWSTR, \
|
|
DWORD,va_list*))aSyscall[15].pCurrent)
|
|
|
|
#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
|
{ "FreeLibrary", (SYSCALL)FreeLibrary, 0 },
|
|
#else
|
|
{ "FreeLibrary", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osFreeLibrary ((BOOL(WINAPI*)(HMODULE))aSyscall[16].pCurrent)
|
|
|
|
{ "GetCurrentProcessId", (SYSCALL)GetCurrentProcessId, 0 },
|
|
|
|
#define osGetCurrentProcessId ((DWORD(WINAPI*)(VOID))aSyscall[17].pCurrent)
|
|
|
|
#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI)
|
|
{ "GetDiskFreeSpaceA", (SYSCALL)GetDiskFreeSpaceA, 0 },
|
|
#else
|
|
{ "GetDiskFreeSpaceA", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osGetDiskFreeSpaceA ((BOOL(WINAPI*)(LPCSTR,LPDWORD,LPDWORD,LPDWORD, \
|
|
LPDWORD))aSyscall[18].pCurrent)
|
|
|
|
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
|
|
{ "GetDiskFreeSpaceW", (SYSCALL)GetDiskFreeSpaceW, 0 },
|
|
#else
|
|
{ "GetDiskFreeSpaceW", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osGetDiskFreeSpaceW ((BOOL(WINAPI*)(LPCWSTR,LPDWORD,LPDWORD,LPDWORD, \
|
|
LPDWORD))aSyscall[19].pCurrent)
|
|
|
|
#if defined(SQLITE_WIN32_HAS_ANSI)
|
|
{ "GetFileAttributesA", (SYSCALL)GetFileAttributesA, 0 },
|
|
#else
|
|
{ "GetFileAttributesA", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osGetFileAttributesA ((DWORD(WINAPI*)(LPCSTR))aSyscall[20].pCurrent)
|
|
|
|
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
|
|
{ "GetFileAttributesW", (SYSCALL)GetFileAttributesW, 0 },
|
|
#else
|
|
{ "GetFileAttributesW", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osGetFileAttributesW ((DWORD(WINAPI*)(LPCWSTR))aSyscall[21].pCurrent)
|
|
|
|
#if defined(SQLITE_WIN32_HAS_WIDE)
|
|
{ "GetFileAttributesExW", (SYSCALL)GetFileAttributesExW, 0 },
|
|
#else
|
|
{ "GetFileAttributesExW", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osGetFileAttributesExW ((BOOL(WINAPI*)(LPCWSTR,GET_FILEEX_INFO_LEVELS, \
|
|
LPVOID))aSyscall[22].pCurrent)
|
|
|
|
#if !SQLITE_OS_WINRT
|
|
{ "GetFileSize", (SYSCALL)GetFileSize, 0 },
|
|
#else
|
|
{ "GetFileSize", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osGetFileSize ((DWORD(WINAPI*)(HANDLE,LPDWORD))aSyscall[23].pCurrent)
|
|
|
|
#if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI)
|
|
{ "GetFullPathNameA", (SYSCALL)GetFullPathNameA, 0 },
|
|
#else
|
|
{ "GetFullPathNameA", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osGetFullPathNameA ((DWORD(WINAPI*)(LPCSTR,DWORD,LPSTR, \
|
|
LPSTR*))aSyscall[24].pCurrent)
|
|
|
|
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
|
|
{ "GetFullPathNameW", (SYSCALL)GetFullPathNameW, 0 },
|
|
#else
|
|
{ "GetFullPathNameW", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osGetFullPathNameW ((DWORD(WINAPI*)(LPCWSTR,DWORD,LPWSTR, \
|
|
LPWSTR*))aSyscall[25].pCurrent)
|
|
|
|
{ "GetLastError", (SYSCALL)GetLastError, 0 },
|
|
|
|
#define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[26].pCurrent)
|
|
|
|
#if !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
|
#if SQLITE_OS_WINCE
|
|
/* The GetProcAddressA() routine is only available on Windows CE. */
|
|
{ "GetProcAddressA", (SYSCALL)GetProcAddressA, 0 },
|
|
#else
|
|
/* All other Windows platforms expect GetProcAddress() to take
|
|
** an ANSI string regardless of the _UNICODE setting */
|
|
{ "GetProcAddressA", (SYSCALL)GetProcAddress, 0 },
|
|
#endif
|
|
#else
|
|
{ "GetProcAddressA", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osGetProcAddressA ((FARPROC(WINAPI*)(HMODULE, \
|
|
LPCSTR))aSyscall[27].pCurrent)
|
|
|
|
#if !SQLITE_OS_WINRT
|
|
{ "GetSystemInfo", (SYSCALL)GetSystemInfo, 0 },
|
|
#else
|
|
{ "GetSystemInfo", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[28].pCurrent)
|
|
|
|
{ "GetSystemTime", (SYSCALL)GetSystemTime, 0 },
|
|
|
|
#define osGetSystemTime ((VOID(WINAPI*)(LPSYSTEMTIME))aSyscall[29].pCurrent)
|
|
|
|
#if !SQLITE_OS_WINCE
|
|
{ "GetSystemTimeAsFileTime", (SYSCALL)GetSystemTimeAsFileTime, 0 },
|
|
#else
|
|
{ "GetSystemTimeAsFileTime", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osGetSystemTimeAsFileTime ((VOID(WINAPI*)( \
|
|
LPFILETIME))aSyscall[30].pCurrent)
|
|
|
|
#if defined(SQLITE_WIN32_HAS_ANSI)
|
|
{ "GetTempPathA", (SYSCALL)GetTempPathA, 0 },
|
|
#else
|
|
{ "GetTempPathA", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osGetTempPathA ((DWORD(WINAPI*)(DWORD,LPSTR))aSyscall[31].pCurrent)
|
|
|
|
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
|
|
{ "GetTempPathW", (SYSCALL)GetTempPathW, 0 },
|
|
#else
|
|
{ "GetTempPathW", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osGetTempPathW ((DWORD(WINAPI*)(DWORD,LPWSTR))aSyscall[32].pCurrent)
|
|
|
|
#if !SQLITE_OS_WINRT
|
|
{ "GetTickCount", (SYSCALL)GetTickCount, 0 },
|
|
#else
|
|
{ "GetTickCount", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent)
|
|
|
|
#if defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_GETVERSIONEX
|
|
{ "GetVersionExA", (SYSCALL)GetVersionExA, 0 },
|
|
#else
|
|
{ "GetVersionExA", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osGetVersionExA ((BOOL(WINAPI*)( \
|
|
LPOSVERSIONINFOA))aSyscall[34].pCurrent)
|
|
|
|
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
|
|
SQLITE_WIN32_GETVERSIONEX
|
|
{ "GetVersionExW", (SYSCALL)GetVersionExW, 0 },
|
|
#else
|
|
{ "GetVersionExW", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osGetVersionExW ((BOOL(WINAPI*)( \
|
|
LPOSVERSIONINFOW))aSyscall[35].pCurrent)
|
|
|
|
{ "HeapAlloc", (SYSCALL)HeapAlloc, 0 },
|
|
|
|
#define osHeapAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD, \
|
|
SIZE_T))aSyscall[36].pCurrent)
|
|
|
|
#if !SQLITE_OS_WINRT
|
|
{ "HeapCreate", (SYSCALL)HeapCreate, 0 },
|
|
#else
|
|
{ "HeapCreate", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osHeapCreate ((HANDLE(WINAPI*)(DWORD,SIZE_T, \
|
|
SIZE_T))aSyscall[37].pCurrent)
|
|
|
|
#if !SQLITE_OS_WINRT
|
|
{ "HeapDestroy", (SYSCALL)HeapDestroy, 0 },
|
|
#else
|
|
{ "HeapDestroy", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[38].pCurrent)
|
|
|
|
{ "HeapFree", (SYSCALL)HeapFree, 0 },
|
|
|
|
#define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[39].pCurrent)
|
|
|
|
{ "HeapReAlloc", (SYSCALL)HeapReAlloc, 0 },
|
|
|
|
#define osHeapReAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD,LPVOID, \
|
|
SIZE_T))aSyscall[40].pCurrent)
|
|
|
|
{ "HeapSize", (SYSCALL)HeapSize, 0 },
|
|
|
|
#define osHeapSize ((SIZE_T(WINAPI*)(HANDLE,DWORD, \
|
|
LPCVOID))aSyscall[41].pCurrent)
|
|
|
|
#if !SQLITE_OS_WINRT
|
|
{ "HeapValidate", (SYSCALL)HeapValidate, 0 },
|
|
#else
|
|
{ "HeapValidate", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osHeapValidate ((BOOL(WINAPI*)(HANDLE,DWORD, \
|
|
LPCVOID))aSyscall[42].pCurrent)
|
|
|
|
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
|
|
{ "HeapCompact", (SYSCALL)HeapCompact, 0 },
|
|
#else
|
|
{ "HeapCompact", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osHeapCompact ((UINT(WINAPI*)(HANDLE,DWORD))aSyscall[43].pCurrent)
|
|
|
|
#if defined(SQLITE_WIN32_HAS_ANSI) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
|
{ "LoadLibraryA", (SYSCALL)LoadLibraryA, 0 },
|
|
#else
|
|
{ "LoadLibraryA", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[44].pCurrent)
|
|
|
|
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \
|
|
!defined(SQLITE_OMIT_LOAD_EXTENSION)
|
|
{ "LoadLibraryW", (SYSCALL)LoadLibraryW, 0 },
|
|
#else
|
|
{ "LoadLibraryW", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[45].pCurrent)
|
|
|
|
#if !SQLITE_OS_WINRT
|
|
{ "LocalFree", (SYSCALL)LocalFree, 0 },
|
|
#else
|
|
{ "LocalFree", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[46].pCurrent)
|
|
|
|
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
|
|
{ "LockFile", (SYSCALL)LockFile, 0 },
|
|
#else
|
|
{ "LockFile", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#ifndef osLockFile
|
|
#define osLockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
|
|
DWORD))aSyscall[47].pCurrent)
|
|
#endif
|
|
|
|
#if !SQLITE_OS_WINCE
|
|
{ "LockFileEx", (SYSCALL)LockFileEx, 0 },
|
|
#else
|
|
{ "LockFileEx", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#ifndef osLockFileEx
|
|
#define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \
|
|
LPOVERLAPPED))aSyscall[48].pCurrent)
|
|
#endif
|
|
|
|
#if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && \
|
|
(!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0))
|
|
{ "MapViewOfFile", (SYSCALL)MapViewOfFile, 0 },
|
|
#else
|
|
{ "MapViewOfFile", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osMapViewOfFile ((LPVOID(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
|
|
SIZE_T))aSyscall[49].pCurrent)
|
|
|
|
{ "MultiByteToWideChar", (SYSCALL)MultiByteToWideChar, 0 },
|
|
|
|
#define osMultiByteToWideChar ((int(WINAPI*)(UINT,DWORD,LPCSTR,int,LPWSTR, \
|
|
int))aSyscall[50].pCurrent)
|
|
|
|
{ "QueryPerformanceCounter", (SYSCALL)QueryPerformanceCounter, 0 },
|
|
|
|
#define osQueryPerformanceCounter ((BOOL(WINAPI*)( \
|
|
LARGE_INTEGER*))aSyscall[51].pCurrent)
|
|
|
|
{ "ReadFile", (SYSCALL)ReadFile, 0 },
|
|
|
|
#define osReadFile ((BOOL(WINAPI*)(HANDLE,LPVOID,DWORD,LPDWORD, \
|
|
LPOVERLAPPED))aSyscall[52].pCurrent)
|
|
|
|
{ "SetEndOfFile", (SYSCALL)SetEndOfFile, 0 },
|
|
|
|
#define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[53].pCurrent)
|
|
|
|
#if !SQLITE_OS_WINRT
|
|
{ "SetFilePointer", (SYSCALL)SetFilePointer, 0 },
|
|
#else
|
|
{ "SetFilePointer", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osSetFilePointer ((DWORD(WINAPI*)(HANDLE,LONG,PLONG, \
|
|
DWORD))aSyscall[54].pCurrent)
|
|
|
|
#if !SQLITE_OS_WINRT
|
|
{ "Sleep", (SYSCALL)Sleep, 0 },
|
|
#else
|
|
{ "Sleep", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[55].pCurrent)
|
|
|
|
{ "SystemTimeToFileTime", (SYSCALL)SystemTimeToFileTime, 0 },
|
|
|
|
#define osSystemTimeToFileTime ((BOOL(WINAPI*)(CONST SYSTEMTIME*, \
|
|
LPFILETIME))aSyscall[56].pCurrent)
|
|
|
|
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
|
|
{ "UnlockFile", (SYSCALL)UnlockFile, 0 },
|
|
#else
|
|
{ "UnlockFile", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#ifndef osUnlockFile
|
|
#define osUnlockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
|
|
DWORD))aSyscall[57].pCurrent)
|
|
#endif
|
|
|
|
#if !SQLITE_OS_WINCE
|
|
{ "UnlockFileEx", (SYSCALL)UnlockFileEx, 0 },
|
|
#else
|
|
{ "UnlockFileEx", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
|
|
LPOVERLAPPED))aSyscall[58].pCurrent)
|
|
|
|
#if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0
|
|
{ "UnmapViewOfFile", (SYSCALL)UnmapViewOfFile, 0 },
|
|
#else
|
|
{ "UnmapViewOfFile", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[59].pCurrent)
|
|
|
|
{ "WideCharToMultiByte", (SYSCALL)WideCharToMultiByte, 0 },
|
|
|
|
#define osWideCharToMultiByte ((int(WINAPI*)(UINT,DWORD,LPCWSTR,int,LPSTR,int, \
|
|
LPCSTR,LPBOOL))aSyscall[60].pCurrent)
|
|
|
|
{ "WriteFile", (SYSCALL)WriteFile, 0 },
|
|
|
|
#define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \
|
|
LPOVERLAPPED))aSyscall[61].pCurrent)
|
|
|
|
#if SQLITE_OS_WINRT
|
|
{ "CreateEventExW", (SYSCALL)CreateEventExW, 0 },
|
|
#else
|
|
{ "CreateEventExW", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \
|
|
DWORD,DWORD))aSyscall[62].pCurrent)
|
|
|
|
#if !SQLITE_OS_WINRT
|
|
{ "WaitForSingleObject", (SYSCALL)WaitForSingleObject, 0 },
|
|
#else
|
|
{ "WaitForSingleObject", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \
|
|
DWORD))aSyscall[63].pCurrent)
|
|
|
|
#if !SQLITE_OS_WINCE
|
|
{ "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 },
|
|
#else
|
|
{ "WaitForSingleObjectEx", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \
|
|
BOOL))aSyscall[64].pCurrent)
|
|
|
|
#if SQLITE_OS_WINRT
|
|
{ "SetFilePointerEx", (SYSCALL)SetFilePointerEx, 0 },
|
|
#else
|
|
{ "SetFilePointerEx", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \
|
|
PLARGE_INTEGER,DWORD))aSyscall[65].pCurrent)
|
|
|
|
#if SQLITE_OS_WINRT
|
|
{ "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 },
|
|
#else
|
|
{ "GetFileInformationByHandleEx", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \
|
|
FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[66].pCurrent)
|
|
|
|
#if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)
|
|
{ "MapViewOfFileFromApp", (SYSCALL)MapViewOfFileFromApp, 0 },
|
|
#else
|
|
{ "MapViewOfFileFromApp", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osMapViewOfFileFromApp ((LPVOID(WINAPI*)(HANDLE,ULONG,ULONG64, \
|
|
SIZE_T))aSyscall[67].pCurrent)
|
|
|
|
#if SQLITE_OS_WINRT
|
|
{ "CreateFile2", (SYSCALL)CreateFile2, 0 },
|
|
#else
|
|
{ "CreateFile2", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osCreateFile2 ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD,DWORD, \
|
|
LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[68].pCurrent)
|
|
|
|
#if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
|
{ "LoadPackagedLibrary", (SYSCALL)LoadPackagedLibrary, 0 },
|
|
#else
|
|
{ "LoadPackagedLibrary", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osLoadPackagedLibrary ((HMODULE(WINAPI*)(LPCWSTR, \
|
|
DWORD))aSyscall[69].pCurrent)
|
|
|
|
#if SQLITE_OS_WINRT
|
|
{ "GetTickCount64", (SYSCALL)GetTickCount64, 0 },
|
|
#else
|
|
{ "GetTickCount64", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[70].pCurrent)
|
|
|
|
#if SQLITE_OS_WINRT
|
|
{ "GetNativeSystemInfo", (SYSCALL)GetNativeSystemInfo, 0 },
|
|
#else
|
|
{ "GetNativeSystemInfo", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osGetNativeSystemInfo ((VOID(WINAPI*)( \
|
|
LPSYSTEM_INFO))aSyscall[71].pCurrent)
|
|
|
|
#if defined(SQLITE_WIN32_HAS_ANSI)
|
|
{ "OutputDebugStringA", (SYSCALL)OutputDebugStringA, 0 },
|
|
#else
|
|
{ "OutputDebugStringA", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[72].pCurrent)
|
|
|
|
#if defined(SQLITE_WIN32_HAS_WIDE)
|
|
{ "OutputDebugStringW", (SYSCALL)OutputDebugStringW, 0 },
|
|
#else
|
|
{ "OutputDebugStringW", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[73].pCurrent)
|
|
|
|
{ "GetProcessHeap", (SYSCALL)GetProcessHeap, 0 },
|
|
|
|
#define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[74].pCurrent)
|
|
|
|
#if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)
|
|
{ "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 },
|
|
#else
|
|
{ "CreateFileMappingFromApp", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \
|
|
LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[75].pCurrent)
|
|
|
|
/*
|
|
** NOTE: On some sub-platforms, the InterlockedCompareExchange "function"
|
|
** is really just a macro that uses a compiler intrinsic (e.g. x64).
|
|
** So do not try to make this is into a redefinable interface.
|
|
*/
|
|
#if defined(InterlockedCompareExchange)
|
|
{ "InterlockedCompareExchange", (SYSCALL)0, 0 },
|
|
|
|
#define osInterlockedCompareExchange InterlockedCompareExchange
|
|
#else
|
|
{ "InterlockedCompareExchange", (SYSCALL)InterlockedCompareExchange, 0 },
|
|
|
|
#define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG \
|
|
SQLITE_WIN32_VOLATILE*, LONG,LONG))aSyscall[76].pCurrent)
|
|
#endif /* defined(InterlockedCompareExchange) */
|
|
|
|
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID
|
|
{ "UuidCreate", (SYSCALL)UuidCreate, 0 },
|
|
#else
|
|
{ "UuidCreate", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osUuidCreate ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[77].pCurrent)
|
|
|
|
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID
|
|
{ "UuidCreateSequential", (SYSCALL)UuidCreateSequential, 0 },
|
|
#else
|
|
{ "UuidCreateSequential", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osUuidCreateSequential \
|
|
((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[78].pCurrent)
|
|
|
|
#if !defined(SQLITE_NO_SYNC) && SQLITE_MAX_MMAP_SIZE>0
|
|
{ "FlushViewOfFile", (SYSCALL)FlushViewOfFile, 0 },
|
|
#else
|
|
{ "FlushViewOfFile", (SYSCALL)0, 0 },
|
|
#endif
|
|
|
|
#define osFlushViewOfFile \
|
|
((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[79].pCurrent)
|
|
|
|
}; /* End of the overrideable system calls */
|
|
|
|
/*
|
|
** This is the xSetSystemCall() method of sqlite3_vfs for all of the
|
|
** "win32" VFSes. Return SQLITE_OK upon successfully updating the
|
|
** system call pointer, or SQLITE_NOTFOUND if there is no configurable
|
|
** system call named zName.
|
|
*/
|
|
static int winSetSystemCall(
|
|
sqlite3_vfs *pNotUsed, /* The VFS pointer. Not used */
|
|
const char *zName, /* Name of system call to override */
|
|
sqlite3_syscall_ptr pNewFunc /* Pointer to new system call value */
|
|
){
|
|
unsigned int i;
|
|
int rc = SQLITE_NOTFOUND;
|
|
|
|
UNUSED_PARAMETER(pNotUsed);
|
|
if( zName==0 ){
|
|
/* If no zName is given, restore all system calls to their default
|
|
** settings and return NULL
|
|
*/
|
|
rc = SQLITE_OK;
|
|
for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
|
|
if( aSyscall[i].pDefault ){
|
|
aSyscall[i].pCurrent = aSyscall[i].pDefault;
|
|
}
|
|
}
|
|
}else{
|
|
/* If zName is specified, operate on only the one system call
|
|
** specified.
|
|
*/
|
|
for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
|
|
if( strcmp(zName, aSyscall[i].zName)==0 ){
|
|
if( aSyscall[i].pDefault==0 ){
|
|
aSyscall[i].pDefault = aSyscall[i].pCurrent;
|
|
}
|
|
rc = SQLITE_OK;
|
|
if( pNewFunc==0 ) pNewFunc = aSyscall[i].pDefault;
|
|
aSyscall[i].pCurrent = pNewFunc;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Return the value of a system call. Return NULL if zName is not a
|
|
** recognized system call name. NULL is also returned if the system call
|
|
** is currently undefined.
|
|
*/
|
|
static sqlite3_syscall_ptr winGetSystemCall(
|
|
sqlite3_vfs *pNotUsed,
|
|
const char *zName
|
|
){
|
|
unsigned int i;
|
|
|
|
UNUSED_PARAMETER(pNotUsed);
|
|
for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
|
|
if( strcmp(zName, aSyscall[i].zName)==0 ) return aSyscall[i].pCurrent;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
** Return the name of the first system call after zName. If zName==NULL
|
|
** then return the name of the first system call. Return NULL if zName
|
|
** is the last system call or if zName is not the name of a valid
|
|
** system call.
|
|
*/
|
|
static const char *winNextSystemCall(sqlite3_vfs *p, const char *zName){
|
|
int i = -1;
|
|
|
|
UNUSED_PARAMETER(p);
|
|
if( zName ){
|
|
for(i=0; i<ArraySize(aSyscall)-1; i++){
|
|
if( strcmp(zName, aSyscall[i].zName)==0 ) break;
|
|
}
|
|
}
|
|
for(i++; i<ArraySize(aSyscall); i++){
|
|
if( aSyscall[i].pCurrent!=0 ) return aSyscall[i].zName;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#ifdef SQLITE_WIN32_MALLOC
|
|
/*
|
|
** If a Win32 native heap has been configured, this function will attempt to
|
|
** compact it. Upon success, SQLITE_OK will be returned. Upon failure, one
|
|
** of SQLITE_NOMEM, SQLITE_ERROR, or SQLITE_NOTFOUND will be returned. The
|
|
** "pnLargest" argument, if non-zero, will be used to return the size of the
|
|
** largest committed free block in the heap, in bytes.
|
|
*/
|
|
SQLITE_API int sqlite3_win32_compact_heap(LPUINT pnLargest){
|
|
int rc = SQLITE_OK;
|
|
UINT nLargest = 0;
|
|
HANDLE hHeap;
|
|
|
|
winMemAssertMagic();
|
|
hHeap = winMemGetHeap();
|
|
assert( hHeap!=0 );
|
|
assert( hHeap!=INVALID_HANDLE_VALUE );
|
|
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
|
|
assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
|
|
#endif
|
|
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT
|
|
if( (nLargest=osHeapCompact(hHeap, SQLITE_WIN32_HEAP_FLAGS))==0 ){
|
|
DWORD lastErrno = osGetLastError();
|
|
if( lastErrno==NO_ERROR ){
|
|
sqlite3_log(SQLITE_NOMEM, "failed to HeapCompact (no space), heap=%p",
|
|
(void*)hHeap);
|
|
rc = SQLITE_NOMEM_BKPT;
|
|
}else{
|
|
sqlite3_log(SQLITE_ERROR, "failed to HeapCompact (%lu), heap=%p",
|
|
osGetLastError(), (void*)hHeap);
|
|
rc = SQLITE_ERROR;
|
|
}
|
|
}
|
|
#else
|
|
sqlite3_log(SQLITE_NOTFOUND, "failed to HeapCompact, heap=%p",
|
|
(void*)hHeap);
|
|
rc = SQLITE_NOTFOUND;
|
|
#endif
|
|
if( pnLargest ) *pnLargest = nLargest;
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** If a Win32 native heap has been configured, this function will attempt to
|
|
** destroy and recreate it. If the Win32 native heap is not isolated and/or
|
|
** the sqlite3_memory_used() function does not return zero, SQLITE_BUSY will
|
|
** be returned and no changes will be made to the Win32 native heap.
|
|
*/
|
|
SQLITE_API int sqlite3_win32_reset_heap(){
|
|
int rc;
|
|
MUTEX_LOGIC( sqlite3_mutex *pMainMtx; ) /* The main static mutex */
|
|
MUTEX_LOGIC( sqlite3_mutex *pMem; ) /* The memsys static mutex */
|
|
MUTEX_LOGIC( pMainMtx = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); )
|
|
MUTEX_LOGIC( pMem = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); )
|
|
sqlite3_mutex_enter(pMainMtx);
|
|
sqlite3_mutex_enter(pMem);
|
|
winMemAssertMagic();
|
|
if( winMemGetHeap()!=NULL && winMemGetOwned() && sqlite3_memory_used()==0 ){
|
|
/*
|
|
** At this point, there should be no outstanding memory allocations on
|
|
** the heap. Also, since both the main and memsys locks are currently
|
|
** being held by us, no other function (i.e. from another thread) should
|
|
** be able to even access the heap. Attempt to destroy and recreate our
|
|
** isolated Win32 native heap now.
|
|
*/
|
|
assert( winMemGetHeap()!=NULL );
|
|
assert( winMemGetOwned() );
|
|
assert( sqlite3_memory_used()==0 );
|
|
winMemShutdown(winMemGetDataPtr());
|
|
assert( winMemGetHeap()==NULL );
|
|
assert( !winMemGetOwned() );
|
|
assert( sqlite3_memory_used()==0 );
|
|
rc = winMemInit(winMemGetDataPtr());
|
|
assert( rc!=SQLITE_OK || winMemGetHeap()!=NULL );
|
|
assert( rc!=SQLITE_OK || winMemGetOwned() );
|
|
assert( rc!=SQLITE_OK || sqlite3_memory_used()==0 );
|
|
}else{
|
|
/*
|
|
** The Win32 native heap cannot be modified because it may be in use.
|
|
*/
|
|
rc = SQLITE_BUSY;
|
|
}
|
|
sqlite3_mutex_leave(pMem);
|
|
sqlite3_mutex_leave(pMainMtx);
|
|
return rc;
|
|
}
|
|
#endif /* SQLITE_WIN32_MALLOC */
|
|
|
|
/*
|
|
** This function outputs the specified (ANSI) string to the Win32 debugger
|
|
** (if available).
|
|
*/
|
|
|
|
SQLITE_API void sqlite3_win32_write_debug(const char *zBuf, int nBuf){
|
|
char zDbgBuf[SQLITE_WIN32_DBG_BUF_SIZE];
|
|
int nMin = MIN(nBuf, (SQLITE_WIN32_DBG_BUF_SIZE - 1)); /* may be negative. */
|
|
if( nMin<-1 ) nMin = -1; /* all negative values become -1. */
|
|
assert( nMin==-1 || nMin==0 || nMin<SQLITE_WIN32_DBG_BUF_SIZE );
|
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
|
if( !zBuf ){
|
|
(void)SQLITE_MISUSE_BKPT;
|
|
return;
|
|
}
|
|
#endif
|
|
#if defined(SQLITE_WIN32_HAS_ANSI)
|
|
if( nMin>0 ){
|
|
memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);
|
|
memcpy(zDbgBuf, zBuf, nMin);
|
|
osOutputDebugStringA(zDbgBuf);
|
|
}else{
|
|
osOutputDebugStringA(zBuf);
|
|
}
|
|
#elif defined(SQLITE_WIN32_HAS_WIDE)
|
|
memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);
|
|
if ( osMultiByteToWideChar(
|
|
osAreFileApisANSI() ? CP_ACP : CP_OEMCP, 0, zBuf,
|
|
nMin, (LPWSTR)zDbgBuf, SQLITE_WIN32_DBG_BUF_SIZE/sizeof(WCHAR))<=0 ){
|
|
return;
|
|
}
|
|
osOutputDebugStringW((LPCWSTR)zDbgBuf);
|
|
#else
|
|
if( nMin>0 ){
|
|
memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE);
|
|
memcpy(zDbgBuf, zBuf, nMin);
|
|
fprintf(stderr, "%s", zDbgBuf);
|
|
}else{
|
|
fprintf(stderr, "%s", zBuf);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
** The following routine suspends the current thread for at least ms
|
|
** milliseconds. This is equivalent to the Win32 Sleep() interface.
|
|
*/
|
|
#if SQLITE_OS_WINRT
|
|
static HANDLE sleepObj = NULL;
|
|
#endif
|
|
|
|
SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds){
|
|
#if SQLITE_OS_WINRT
|
|
if ( sleepObj==NULL ){
|
|
sleepObj = osCreateEventExW(NULL, NULL, CREATE_EVENT_MANUAL_RESET,
|
|
SYNCHRONIZE);
|
|
}
|
|
assert( sleepObj!=NULL );
|
|
osWaitForSingleObjectEx(sleepObj, milliseconds, FALSE);
|
|
#else
|
|
osSleep(milliseconds);
|
|
#endif
|
|
}
|
|
|
|
#if SQLITE_MAX_WORKER_THREADS>0 && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \
|
|
SQLITE_THREADSAFE>0
|
|
SQLITE_PRIVATE DWORD sqlite3Win32Wait(HANDLE hObject){
|
|
DWORD rc;
|
|
while( (rc = osWaitForSingleObjectEx(hObject, INFINITE,
|
|
TRUE))==WAIT_IO_COMPLETION ){}
|
|
return rc;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
** 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 when 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 !SQLITE_WIN32_GETVERSIONEX
|
|
# define osIsNT() (1)
|
|
#elif SQLITE_OS_WINCE || SQLITE_OS_WINRT || !defined(SQLITE_WIN32_HAS_ANSI)
|
|
# define osIsNT() (1)
|
|
#elif !defined(SQLITE_WIN32_HAS_WIDE)
|
|
# define osIsNT() (0)
|
|
#else
|
|
# define osIsNT() ((sqlite3_os_type==2) || sqlite3_win32_is_nt())
|
|
#endif
|
|
|
|
/*
|
|
** This function determines if the machine is running a version of Windows
|
|
** based on the NT kernel.
|
|
*/
|
|
SQLITE_API int sqlite3_win32_is_nt(void){
|
|
#if SQLITE_OS_WINRT
|
|
/*
|
|
** NOTE: The WinRT sub-platform is always assumed to be based on the NT
|
|
** kernel.
|
|
*/
|
|
return 1;
|
|
#elif SQLITE_WIN32_GETVERSIONEX
|
|
if( osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 ){
|
|
#if defined(SQLITE_WIN32_HAS_ANSI)
|
|
OSVERSIONINFOA sInfo;
|
|
sInfo.dwOSVersionInfoSize = sizeof(sInfo);
|
|
osGetVersionExA(&sInfo);
|
|
osInterlockedCompareExchange(&sqlite3_os_type,
|
|
(sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);
|
|
#elif defined(SQLITE_WIN32_HAS_WIDE)
|
|
OSVERSIONINFOW sInfo;
|
|
sInfo.dwOSVersionInfoSize = sizeof(sInfo);
|
|
osGetVersionExW(&sInfo);
|
|
osInterlockedCompareExchange(&sqlite3_os_type,
|
|
(sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);
|
|
#endif
|
|
}
|
|
return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
|
|
#elif SQLITE_TEST
|
|
return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
|
|
#else
|
|
/*
|
|
** NOTE: All sub-platforms where the GetVersionEx[AW] functions are
|
|
** deprecated are always assumed to be based on the NT kernel.
|
|
*/
|
|
return 1;
|
|
#endif
|
|
}
|
|
|
|
#ifdef SQLITE_WIN32_MALLOC
|
|
/*
|
|
** Allocate nBytes of memory.
|
|
*/
|
|
static void *winMemMalloc(int nBytes){
|
|
HANDLE hHeap;
|
|
void *p;
|
|
|
|
winMemAssertMagic();
|
|
hHeap = winMemGetHeap();
|
|
assert( hHeap!=0 );
|
|
assert( hHeap!=INVALID_HANDLE_VALUE );
|
|
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
|
|
assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
|
|
#endif
|
|
assert( nBytes>=0 );
|
|
p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
|
|
if( !p ){
|
|
sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%lu), heap=%p",
|
|
nBytes, osGetLastError(), (void*)hHeap);
|
|
}
|
|
return p;
|
|
}
|
|
|
|
/*
|
|
** Free memory.
|
|
*/
|
|
static void winMemFree(void *pPrior){
|
|
HANDLE hHeap;
|
|
|
|
winMemAssertMagic();
|
|
hHeap = winMemGetHeap();
|
|
assert( hHeap!=0 );
|
|
assert( hHeap!=INVALID_HANDLE_VALUE );
|
|
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
|
|
assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
|
|
#endif
|
|
if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */
|
|
if( !osHeapFree(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ){
|
|
sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%lu), heap=%p",
|
|
pPrior, osGetLastError(), (void*)hHeap);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Change the size of an existing memory allocation
|
|
*/
|
|
static void *winMemRealloc(void *pPrior, int nBytes){
|
|
HANDLE hHeap;
|
|
void *p;
|
|
|
|
winMemAssertMagic();
|
|
hHeap = winMemGetHeap();
|
|
assert( hHeap!=0 );
|
|
assert( hHeap!=INVALID_HANDLE_VALUE );
|
|
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
|
|
assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
|
|
#endif
|
|
assert( nBytes>=0 );
|
|
if( !pPrior ){
|
|
p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
|
|
}else{
|
|
p = osHeapReAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior, (SIZE_T)nBytes);
|
|
}
|
|
if( !p ){
|
|
sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%lu), heap=%p",
|
|
pPrior ? "HeapReAlloc" : "HeapAlloc", nBytes, osGetLastError(),
|
|
(void*)hHeap);
|
|
}
|
|
return p;
|
|
}
|
|
|
|
/*
|
|
** Return the size of an outstanding allocation, in bytes.
|
|
*/
|
|
static int winMemSize(void *p){
|
|
HANDLE hHeap;
|
|
SIZE_T n;
|
|
|
|
winMemAssertMagic();
|
|
hHeap = winMemGetHeap();
|
|
assert( hHeap!=0 );
|
|
assert( hHeap!=INVALID_HANDLE_VALUE );
|
|
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
|
|
assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, p) );
|
|
#endif
|
|
if( !p ) return 0;
|
|
n = osHeapSize(hHeap, SQLITE_WIN32_HEAP_FLAGS, p);
|
|
if( n==(SIZE_T)-1 ){
|
|
sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%lu), heap=%p",
|
|
p, osGetLastError(), (void*)hHeap);
|
|
return 0;
|
|
}
|
|
return (int)n;
|
|
}
|
|
|
|
/*
|
|
** Round up a request size to the next valid allocation size.
|
|
*/
|
|
static int winMemRoundup(int n){
|
|
return n;
|
|
}
|
|
|
|
/*
|
|
** Initialize this module.
|
|
*/
|
|
static int winMemInit(void *pAppData){
|
|
winMemData *pWinMemData = (winMemData *)pAppData;
|
|
|
|
if( !pWinMemData ) return SQLITE_ERROR;
|
|
assert( pWinMemData->magic1==WINMEM_MAGIC1 );
|
|
assert( pWinMemData->magic2==WINMEM_MAGIC2 );
|
|
|
|
#if !SQLITE_OS_WINRT && SQLITE_WIN32_HEAP_CREATE
|
|
if( !pWinMemData->hHeap ){
|
|
DWORD dwInitialSize = SQLITE_WIN32_HEAP_INIT_SIZE;
|
|
DWORD dwMaximumSize = (DWORD)sqlite3GlobalConfig.nHeap;
|
|
if( dwMaximumSize==0 ){
|
|
dwMaximumSize = SQLITE_WIN32_HEAP_MAX_SIZE;
|
|
}else if( dwInitialSize>dwMaximumSize ){
|
|
dwInitialSize = dwMaximumSize;
|
|
}
|
|
pWinMemData->hHeap = osHeapCreate(SQLITE_WIN32_HEAP_FLAGS,
|
|
dwInitialSize, dwMaximumSize);
|
|
if( !pWinMemData->hHeap ){
|
|
sqlite3_log(SQLITE_NOMEM,
|
|
"failed to HeapCreate (%lu), flags=%u, initSize=%lu, maxSize=%lu",
|
|
osGetLastError(), SQLITE_WIN32_HEAP_FLAGS, dwInitialSize,
|
|
dwMaximumSize);
|
|
return SQLITE_NOMEM_BKPT;
|
|
}
|
|
pWinMemData->bOwned = TRUE;
|
|
assert( pWinMemData->bOwned );
|
|
}
|
|
#else
|
|
pWinMemData->hHeap = osGetProcessHeap();
|
|
if( !pWinMemData->hHeap ){
|
|
sqlite3_log(SQLITE_NOMEM,
|
|
"failed to GetProcessHeap (%lu)", osGetLastError());
|
|
return SQLITE_NOMEM_BKPT;
|
|
}
|
|
pWinMemData->bOwned = FALSE;
|
|
assert( !pWinMemData->bOwned );
|
|
#endif
|
|
assert( pWinMemData->hHeap!=0 );
|
|
assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
|
|
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
|
|
assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
|
|
#endif
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Deinitialize this module.
|
|
*/
|
|
static void winMemShutdown(void *pAppData){
|
|
winMemData *pWinMemData = (winMemData *)pAppData;
|
|
|
|
if( !pWinMemData ) return;
|
|
assert( pWinMemData->magic1==WINMEM_MAGIC1 );
|
|
assert( pWinMemData->magic2==WINMEM_MAGIC2 );
|
|
|
|
if( pWinMemData->hHeap ){
|
|
assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
|
|
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE)
|
|
assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
|
|
#endif
|
|
if( pWinMemData->bOwned ){
|
|
if( !osHeapDestroy(pWinMemData->hHeap) ){
|
|
sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%lu), heap=%p",
|
|
osGetLastError(), (void*)pWinMemData->hHeap);
|
|
}
|
|
pWinMemData->bOwned = FALSE;
|
|
}
|
|
pWinMemData->hHeap = NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Populate the low-level memory allocation function pointers in
|
|
** sqlite3GlobalConfig.m with pointers to the routines in this file. The
|
|
** arguments specify the block of memory to manage.
|
|
**
|
|
** This routine is only called by sqlite3_config(), and therefore
|
|
** is not required to be threadsafe (it is not).
|
|
*/
|
|
SQLITE_PRIVATE const sqlite3_mem_methods *sqlite3MemGetWin32(void){
|
|
static const sqlite3_mem_methods winMemMethods = {
|
|
winMemMalloc,
|
|
winMemFree,
|
|
winMemRealloc,
|
|
winMemSize,
|
|
winMemRoundup,
|
|
winMemInit,
|
|
winMemShutdown,
|
|
&win_mem_data
|
|
};
|
|
return &winMemMethods;
|
|
}
|
|
|
|
SQLITE_PRIVATE void sqlite3MemSetDefault(void){
|
|
sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetWin32());
|
|
}
|
|
#endif /* SQLITE_WIN32_MALLOC */
|
|
|
|
/*
|
|
** Convert a UTF-8 string to Microsoft Unicode.
|
|
**
|
|
** Space to hold the returned string is obtained from sqlite3_malloc().
|
|
*/
|
|
static LPWSTR winUtf8ToUnicode(const char *zText){
|
|
int nChar;
|
|
LPWSTR zWideText;
|
|
|
|
nChar = osMultiByteToWideChar(CP_UTF8, 0, zText, -1, NULL, 0);
|
|
if( nChar==0 ){
|
|
return 0;
|
|
}
|
|
zWideText = sqlite3MallocZero( nChar*sizeof(WCHAR) );
|
|
if( zWideText==0 ){
|
|
return 0;
|
|
}
|
|
nChar = osMultiByteToWideChar(CP_UTF8, 0, zText, -1, zWideText,
|
|
nChar);
|
|
if( nChar==0 ){
|
|
sqlite3_free(zWideText);
|
|
zWideText = 0;
|
|
}
|
|
return zWideText;
|
|
}
|
|
|
|
/*
|
|
** Convert a Microsoft Unicode string to UTF-8.
|
|
**
|
|
** Space to hold the returned string is obtained from sqlite3_malloc().
|
|
*/
|
|
static char *winUnicodeToUtf8(LPCWSTR zWideText){
|
|
int nByte;
|
|
char *zText;
|
|
|
|
nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideText, -1, 0, 0, 0, 0);
|
|
if( nByte == 0 ){
|
|
return 0;
|
|
}
|
|
zText = sqlite3MallocZero( nByte );
|
|
if( zText==0 ){
|
|
return 0;
|
|
}
|
|
nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideText, -1, zText, nByte,
|
|
0, 0);
|
|
if( nByte == 0 ){
|
|
sqlite3_free(zText);
|
|
zText = 0;
|
|
}
|
|
return zText;
|
|
}
|
|
|
|
/*
|
|
** Convert an ANSI string to Microsoft Unicode, using the ANSI or OEM
|
|
** code page.
|
|
**
|
|
** Space to hold the returned string is obtained from sqlite3_malloc().
|
|
*/
|
|
static LPWSTR winMbcsToUnicode(const char *zText, int useAnsi){
|
|
int nByte;
|
|
LPWSTR zMbcsText;
|
|
int codepage = useAnsi ? CP_ACP : CP_OEMCP;
|
|
|
|
nByte = osMultiByteToWideChar(codepage, 0, zText, -1, NULL,
|
|
0)*sizeof(WCHAR);
|
|
if( nByte==0 ){
|
|
return 0;
|
|
}
|
|
zMbcsText = sqlite3MallocZero( nByte*sizeof(WCHAR) );
|
|
if( zMbcsText==0 ){
|
|
return 0;
|
|
}
|
|
nByte = osMultiByteToWideChar(codepage, 0, zText, -1, zMbcsText,
|
|
nByte);
|
|
if( nByte==0 ){
|
|
sqlite3_free(zMbcsText);
|
|
zMbcsText = 0;
|
|
}
|
|
return zMbcsText;
|
|
}
|
|
|
|
/*
|
|
** Convert a Microsoft Unicode string to a multi-byte character string,
|
|
** using the ANSI or OEM code page.
|
|
**
|
|
** Space to hold the returned string is obtained from sqlite3_malloc().
|
|
*/
|
|
static char *winUnicodeToMbcs(LPCWSTR zWideText, int useAnsi){
|
|
int nByte;
|
|
char *zText;
|
|
int codepage = useAnsi ? CP_ACP : CP_OEMCP;
|
|
|
|
nByte = osWideCharToMultiByte(codepage, 0, zWideText, -1, 0, 0, 0, 0);
|
|
if( nByte == 0 ){
|
|
return 0;
|
|
}
|
|
zText = sqlite3MallocZero( nByte );
|
|
if( zText==0 ){
|
|
return 0;
|
|
}
|
|
nByte = osWideCharToMultiByte(codepage, 0, zWideText, -1, zText,
|
|
nByte, 0, 0);
|
|
if( nByte == 0 ){
|
|
sqlite3_free(zText);
|
|
zText = 0;
|
|
}
|
|
return zText;
|
|
}
|
|
|
|
/*
|
|
** Convert a multi-byte character string to UTF-8.
|
|
**
|
|
** Space to hold the returned string is obtained from sqlite3_malloc().
|
|
*/
|
|
static char *winMbcsToUtf8(const char *zText, int useAnsi){
|
|
char *zTextUtf8;
|
|
LPWSTR zTmpWide;
|
|
|
|
zTmpWide = winMbcsToUnicode(zText, useAnsi);
|
|
if( zTmpWide==0 ){
|
|
return 0;
|
|
}
|
|
zTextUtf8 = winUnicodeToUtf8(zTmpWide);
|
|
sqlite3_free(zTmpWide);
|
|
return zTextUtf8;
|
|
}
|
|
|
|
/*
|
|
** Convert a UTF-8 string to a multi-byte character string.
|
|
**
|
|
** Space to hold the returned string is obtained from sqlite3_malloc().
|
|
*/
|
|
static char *winUtf8ToMbcs(const char *zText, int useAnsi){
|
|
char *zTextMbcs;
|
|
LPWSTR zTmpWide;
|
|
|
|
zTmpWide = winUtf8ToUnicode(zText);
|
|
if( zTmpWide==0 ){
|
|
return 0;
|
|
}
|
|
zTextMbcs = winUnicodeToMbcs(zTmpWide, useAnsi);
|
|
sqlite3_free(zTmpWide);
|
|
return zTextMbcs;
|
|
}
|
|
|
|
/*
|
|
** This is a public wrapper for the winUtf8ToUnicode() function.
|
|
*/
|
|
SQLITE_API LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText){
|
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
|
if( !zText ){
|
|
(void)SQLITE_MISUSE_BKPT;
|
|
return 0;
|
|
}
|
|
#endif
|
|
#ifndef SQLITE_OMIT_AUTOINIT
|
|
if( sqlite3_initialize() ) return 0;
|
|
#endif
|
|
return winUtf8ToUnicode(zText);
|
|
}
|
|
|
|
/*
|
|
** This is a public wrapper for the winUnicodeToUtf8() function.
|
|
*/
|
|
SQLITE_API char *sqlite3_win32_unicode_to_utf8(LPCWSTR zWideText){
|
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
|
if( !zWideText ){
|
|
(void)SQLITE_MISUSE_BKPT;
|
|
return 0;
|
|
}
|
|
#endif
|
|
#ifndef SQLITE_OMIT_AUTOINIT
|
|
if( sqlite3_initialize() ) return 0;
|
|
#endif
|
|
return winUnicodeToUtf8(zWideText);
|
|
}
|
|
|
|
/*
|
|
** This is a public wrapper for the winMbcsToUtf8() function.
|
|
*/
|
|
SQLITE_API char *sqlite3_win32_mbcs_to_utf8(const char *zText){
|
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
|
if( !zText ){
|
|
(void)SQLITE_MISUSE_BKPT;
|
|
return 0;
|
|
}
|
|
#endif
|
|
#ifndef SQLITE_OMIT_AUTOINIT
|
|
if( sqlite3_initialize() ) return 0;
|
|
#endif
|
|
return winMbcsToUtf8(zText, osAreFileApisANSI());
|
|
}
|
|
|
|
/*
|
|
** This is a public wrapper for the winMbcsToUtf8() function.
|
|
*/
|
|
SQLITE_API char *sqlite3_win32_mbcs_to_utf8_v2(const char *zText, int useAnsi){
|
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
|
if( !zText ){
|
|
(void)SQLITE_MISUSE_BKPT;
|
|
return 0;
|
|
}
|
|
#endif
|
|
#ifndef SQLITE_OMIT_AUTOINIT
|
|
if( sqlite3_initialize() ) return 0;
|
|
#endif
|
|
return winMbcsToUtf8(zText, useAnsi);
|
|
}
|
|
|
|
/*
|
|
** This is a public wrapper for the winUtf8ToMbcs() function.
|
|
*/
|
|
SQLITE_API char *sqlite3_win32_utf8_to_mbcs(const char *zText){
|
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
|
if( !zText ){
|
|
(void)SQLITE_MISUSE_BKPT;
|
|
return 0;
|
|
}
|
|
#endif
|
|
#ifndef SQLITE_OMIT_AUTOINIT
|
|
if( sqlite3_initialize() ) return 0;
|
|
#endif
|
|
return winUtf8ToMbcs(zText, osAreFileApisANSI());
|
|
}
|
|
|
|
/*
|
|
** This is a public wrapper for the winUtf8ToMbcs() function.
|
|
*/
|
|
SQLITE_API char *sqlite3_win32_utf8_to_mbcs_v2(const char *zText, int useAnsi){
|
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
|
if( !zText ){
|
|
(void)SQLITE_MISUSE_BKPT;
|
|
return 0;
|
|
}
|
|
#endif
|
|
#ifndef SQLITE_OMIT_AUTOINIT
|
|
if( sqlite3_initialize() ) return 0;
|
|
#endif
|
|
return winUtf8ToMbcs(zText, useAnsi);
|
|
}
|
|
|
|
/*
|
|
** This function is the same as sqlite3_win32_set_directory (below); however,
|
|
** it accepts a UTF-8 string.
|
|
*/
|
|
SQLITE_API int sqlite3_win32_set_directory8(
|
|
unsigned long type, /* Identifier for directory being set or reset */
|
|
const char *zValue /* New value for directory being set or reset */
|
|
){
|
|
char **ppDirectory = 0;
|
|
int rc;
|
|
#ifndef SQLITE_OMIT_AUTOINIT
|
|
rc = sqlite3_initialize();
|
|
if( rc ) return rc;
|
|
#endif
|
|
sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
|
|
if( type==SQLITE_WIN32_DATA_DIRECTORY_TYPE ){
|
|
ppDirectory = &sqlite3_data_directory;
|
|
}else if( type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE ){
|
|
ppDirectory = &sqlite3_temp_directory;
|
|
}
|
|
assert( !ppDirectory || type==SQLITE_WIN32_DATA_DIRECTORY_TYPE
|
|
|| type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE
|
|
);
|
|
assert( !ppDirectory || sqlite3MemdebugHasType(*ppDirectory, MEMTYPE_HEAP) );
|
|
if( ppDirectory ){
|
|
char *zCopy = 0;
|
|
if( zValue && zValue[0] ){
|
|
zCopy = sqlite3_mprintf("%s", zValue);
|
|
if ( zCopy==0 ){
|
|
rc = SQLITE_NOMEM_BKPT;
|
|
goto set_directory8_done;
|
|
}
|
|
}
|
|
sqlite3_free(*ppDirectory);
|
|
*ppDirectory = zCopy;
|
|
rc = SQLITE_OK;
|
|
}else{
|
|
rc = SQLITE_ERROR;
|
|
}
|
|
set_directory8_done:
|
|
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** This function is the same as sqlite3_win32_set_directory (below); however,
|
|
** it accepts a UTF-16 string.
|
|
*/
|
|
SQLITE_API int sqlite3_win32_set_directory16(
|
|
unsigned long type, /* Identifier for directory being set or reset */
|
|
const void *zValue /* New value for directory being set or reset */
|
|
){
|
|
int rc;
|
|
char *zUtf8 = 0;
|
|
if( zValue ){
|
|
zUtf8 = sqlite3_win32_unicode_to_utf8(zValue);
|
|
if( zUtf8==0 ) return SQLITE_NOMEM_BKPT;
|
|
}
|
|
rc = sqlite3_win32_set_directory8(type, zUtf8);
|
|
if( zUtf8 ) sqlite3_free(zUtf8);
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** This function sets the data directory or the temporary directory based on
|
|
** the provided arguments. The type argument must be 1 in order to set the
|
|
** data directory or 2 in order to set the temporary directory. The zValue
|
|
** argument is the name of the directory to use. The return value will be
|
|
** SQLITE_OK if successful.
|
|
*/
|
|
SQLITE_API int sqlite3_win32_set_directory(
|
|
unsigned long type, /* Identifier for directory being set or reset */
|
|
void *zValue /* New value for directory being set or reset */
|
|
){
|
|
return sqlite3_win32_set_directory16(type, zValue);
|
|
}
|
|
|
|
/*
|
|
** The return value of winGetLastErrorMsg
|
|
** is zero if the error message fits in the buffer, or non-zero
|
|
** otherwise (if the message was truncated).
|
|
*/
|
|
static int winGetLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
|
|
/* FormatMessage returns 0 on failure. Otherwise it
|
|
** returns the number of TCHARs written to the output
|
|
** buffer, excluding the terminating null char.
|
|
*/
|
|
DWORD dwLen = 0;
|
|
char *zOut = 0;
|
|
|
|
if( osIsNT() ){
|
|
#if SQLITE_OS_WINRT
|
|
WCHAR zTempWide[SQLITE_WIN32_MAX_ERRMSG_CHARS+1];
|
|
dwLen = osFormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
|
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL,
|
|
lastErrno,
|
|
0,
|
|
zTempWide,
|
|
SQLITE_WIN32_MAX_ERRMSG_CHARS,
|
|
0);
|
|
#else
|
|
LPWSTR zTempWide = NULL;
|
|
dwLen = osFormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL,
|
|
lastErrno,
|
|
0,
|
|
(LPWSTR) &zTempWide,
|
|
0,
|
|
0);
|
|
#endif
|
|
if( dwLen > 0 ){
|
|
/* allocate a buffer and convert to UTF8 */
|
|
sqlite3BeginBenignMalloc();
|
|
zOut = winUnicodeToUtf8(zTempWide);
|
|
sqlite3EndBenignMalloc();
|
|
#if !SQLITE_OS_WINRT
|
|
/* free the system buffer allocated by FormatMessage */
|
|
osLocalFree(zTempWide);
|
|
#endif
|
|
}
|
|
}
|
|
#ifdef SQLITE_WIN32_HAS_ANSI
|
|
else{
|
|
char *zTemp = NULL;
|
|
dwLen = osFormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL,
|
|
lastErrno,
|
|
0,
|
|
(LPSTR) &zTemp,
|
|
0,
|
|
0);
|
|
if( dwLen > 0 ){
|
|
/* allocate a buffer and convert to UTF8 */
|
|
sqlite3BeginBenignMalloc();
|
|
zOut = winMbcsToUtf8(zTemp, osAreFileApisANSI());
|
|
sqlite3EndBenignMalloc();
|
|
/* free the system buffer allocated by FormatMessage */
|
|
osLocalFree(zTemp);
|
|
}
|
|
}
|
|
#endif
|
|
if( 0 == dwLen ){
|
|
sqlite3_snprintf(nBuf, zBuf, "OsError 0x%lx (%lu)", lastErrno, lastErrno);
|
|
}else{
|
|
/* copy a maximum of nBuf chars to output buffer */
|
|
sqlite3_snprintf(nBuf, zBuf, "%s", zOut);
|
|
/* free the UTF8 buffer */
|
|
sqlite3_free(zOut);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
**
|
|
** This function - winLogErrorAtLine() - is only ever called via the macro
|
|
** winLogError().
|
|
**
|
|
** This routine is invoked after an error occurs in an OS function.
|
|
** It logs a message using sqlite3_log() containing the current value of
|
|
** error code and, if possible, the human-readable equivalent from
|
|
** FormatMessage.
|
|
**
|
|
** The first argument passed to the macro should be the error code that
|
|
** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
|
|
** The two subsequent arguments should be the name of the OS function that
|
|
** failed and the associated file-system path, if any.
|
|
*/
|
|
#define winLogError(a,b,c,d) winLogErrorAtLine(a,b,c,d,__LINE__)
|
|
static int winLogErrorAtLine(
|
|
int errcode, /* SQLite error code */
|
|
DWORD lastErrno, /* Win32 last error */
|
|
const char *zFunc, /* Name of OS function that failed */
|
|
const char *zPath, /* File path associated with error */
|
|
int iLine /* Source line number where error occurred */
|
|
){
|
|
char zMsg[500]; /* Human readable error text */
|
|
int i; /* Loop counter */
|
|
|
|
zMsg[0] = 0;
|
|
winGetLastErrorMsg(lastErrno, sizeof(zMsg), zMsg);
|
|
assert( errcode!=SQLITE_OK );
|
|
if( zPath==0 ) zPath = "";
|
|
for(i=0; zMsg[i] && zMsg[i]!='\r' && zMsg[i]!='\n'; i++){}
|
|
zMsg[i] = 0;
|
|
sqlite3_log(errcode,
|
|
"os_win.c:%d: (%lu) %s(%s) - %s",
|
|
iLine, lastErrno, zFunc, zPath, zMsg
|
|
);
|
|
|
|
return errcode;
|
|
}
|
|
|
|
/*
|
|
** The number of times that a ReadFile(), WriteFile(), and DeleteFile()
|
|
** will be retried following a locking error - probably caused by
|
|
** antivirus software. Also the initial delay before the first retry.
|
|
** The delay increases linearly with each retry.
|
|
*/
|
|
#ifndef SQLITE_WIN32_IOERR_RETRY
|
|
# define SQLITE_WIN32_IOERR_RETRY 10
|
|
#endif
|
|
#ifndef SQLITE_WIN32_IOERR_RETRY_DELAY
|
|
# define SQLITE_WIN32_IOERR_RETRY_DELAY 25
|
|
#endif
|
|
static int winIoerrRetry = SQLITE_WIN32_IOERR_RETRY;
|
|
static int winIoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY;
|
|
|
|
/*
|
|
** The "winIoerrCanRetry1" macro is used to determine if a particular I/O
|
|
** error code obtained via GetLastError() is eligible to be retried. It
|
|
** must accept the error code DWORD as its only argument and should return
|
|
** non-zero if the error code is transient in nature and the operation
|
|
** responsible for generating the original error might succeed upon being
|
|
** retried. The argument to this macro should be a variable.
|
|
**
|
|
** Additionally, a macro named "winIoerrCanRetry2" may be defined. If it
|
|
** is defined, it will be consulted only when the macro "winIoerrCanRetry1"
|
|
** returns zero. The "winIoerrCanRetry2" macro is completely optional and
|
|
** may be used to include additional error codes in the set that should
|
|
** result in the failing I/O operation being retried by the caller. If
|
|
** defined, the "winIoerrCanRetry2" macro must exhibit external semantics
|
|
** identical to those of the "winIoerrCanRetry1" macro.
|
|
*/
|
|
#if !defined(winIoerrCanRetry1)
|
|
#define winIoerrCanRetry1(a) (((a)==ERROR_ACCESS_DENIED) || \
|
|
((a)==ERROR_SHARING_VIOLATION) || \
|
|
((a)==ERROR_LOCK_VIOLATION) || \
|
|
((a)==ERROR_DEV_NOT_EXIST) || \
|
|
((a)==ERROR_NETNAME_DELETED) || \
|
|
((a)==ERROR_SEM_TIMEOUT) || \
|
|
((a)==ERROR_NETWORK_UNREACHABLE))
|
|
#endif
|
|
|
|
/*
|
|
** If a ReadFile() or WriteFile() error occurs, invoke this routine
|
|
** to see if it should be retried. Return TRUE to retry. Return FALSE
|
|
** to give up with an error.
|
|
*/
|
|
static int winRetryIoerr(int *pnRetry, DWORD *pError){
|
|
DWORD e = osGetLastError();
|
|
if( *pnRetry>=winIoerrRetry ){
|
|
if( pError ){
|
|
*pError = e;
|
|
}
|
|
return 0;
|
|
}
|
|
if( winIoerrCanRetry1(e) ){
|
|
sqlite3_win32_sleep(winIoerrRetryDelay*(1+*pnRetry));
|
|
++*pnRetry;
|
|
return 1;
|
|
}
|
|
#if defined(winIoerrCanRetry2)
|
|
else if( winIoerrCanRetry2(e) ){
|
|
sqlite3_win32_sleep(winIoerrRetryDelay*(1+*pnRetry));
|
|
++*pnRetry;
|
|
return 1;
|
|
}
|
|
#endif
|
|
if( pError ){
|
|
*pError = e;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
** Log a I/O error retry episode.
|
|
*/
|
|
static void winLogIoerr(int nRetry, int lineno){
|
|
if( nRetry ){
|
|
sqlite3_log(SQLITE_NOTICE,
|
|
"delayed %dms for lock/sharing conflict at line %d",
|
|
winIoerrRetryDelay*nRetry*(nRetry+1)/2, lineno
|
|
);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** This #if does not rely on the SQLITE_OS_WINCE define because the
|
|
** corresponding section in "date.c" cannot use it.
|
|
*/
|
|
#if !defined(SQLITE_OMIT_LOCALTIME) && defined(_WIN32_WCE) && \
|
|
(!defined(SQLITE_MSVC_LOCALTIME_API) || !SQLITE_MSVC_LOCALTIME_API)
|
|
/*
|
|
** The MSVC CRT on Windows CE may not have a localtime() function.
|
|
** So define a substitute.
|
|
*/
|
|
/* # include <time.h> */
|
|
struct tm *__cdecl localtime(const time_t *t)
|
|
{
|
|
static struct tm y;
|
|
FILETIME uTm, lTm;
|
|
SYSTEMTIME pTm;
|
|
sqlite3_int64 t64;
|
|
t64 = *t;
|
|
t64 = (t64 + 11644473600)*10000000;
|
|
uTm.dwLowDateTime = (DWORD)(t64 & 0xFFFFFFFF);
|
|
uTm.dwHighDateTime= (DWORD)(t64 >> 32);
|
|
osFileTimeToLocalFileTime(&uTm,&lTm);
|
|
osFileTimeToSystemTime(&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;
|
|
}
|
|
#endif
|
|
|
|
#if SQLITE_OS_WINCE
|
|
/*************************************************************************
|
|
** This section contains code for WinCE only.
|
|
*/
|
|
#define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,h)]
|
|
|
|
/*
|
|
** Acquire a lock on the handle h
|
|
*/
|
|
static void winceMutexAcquire(HANDLE h){
|
|
DWORD dwErr;
|
|
do {
|
|
dwErr = osWaitForSingleObject(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 int winceCreateLock(const char *zFilename, winFile *pFile){
|
|
LPWSTR zTok;
|
|
LPWSTR zName;
|
|
DWORD lastErrno;
|
|
BOOL bLogged = FALSE;
|
|
BOOL bInit = TRUE;
|
|
|
|
zName = winUtf8ToUnicode(zFilename);
|
|
if( zName==0 ){
|
|
/* out of memory */
|
|
return SQLITE_IOERR_NOMEM_BKPT;
|
|
}
|
|
|
|
/* Initialize the local lockdata */
|
|
memset(&pFile->local, 0, sizeof(pFile->local));
|
|
|
|
/* Replace the backslashes from the filename and lowercase it
|
|
** to derive a mutex name. */
|
|
zTok = osCharLowerW(zName);
|
|
for (;*zTok;zTok++){
|
|
if (*zTok == '\\') *zTok = '_';
|
|
}
|
|
|
|
/* Create/open the named mutex */
|
|
pFile->hMutex = osCreateMutexW(NULL, FALSE, zName);
|
|
if (!pFile->hMutex){
|
|
pFile->lastErrno = osGetLastError();
|
|
sqlite3_free(zName);
|
|
return winLogError(SQLITE_IOERR, pFile->lastErrno,
|
|
"winceCreateLock1", zFilename);
|
|
}
|
|
|
|
/* 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.
|
|
*/
|
|
osCharUpperW(zName);
|
|
pFile->hShared = osCreateFileMappingW(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 */
|
|
lastErrno = osGetLastError();
|
|
if (lastErrno == ERROR_ALREADY_EXISTS){
|
|
bInit = FALSE;
|
|
}
|
|
|
|
sqlite3_free(zName);
|
|
|
|
/* If we succeeded in making the shared memory handle, map it. */
|
|
if( pFile->hShared ){
|
|
pFile->shared = (winceLock*)osMapViewOfFile(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 ){
|
|
pFile->lastErrno = osGetLastError();
|
|
winLogError(SQLITE_IOERR, pFile->lastErrno,
|
|
"winceCreateLock2", zFilename);
|
|
bLogged = TRUE;
|
|
osCloseHandle(pFile->hShared);
|
|
pFile->hShared = NULL;
|
|
}
|
|
}
|
|
|
|
/* If shared memory could not be created, then close the mutex and fail */
|
|
if( pFile->hShared==NULL ){
|
|
if( !bLogged ){
|
|
pFile->lastErrno = lastErrno;
|
|
winLogError(SQLITE_IOERR, pFile->lastErrno,
|
|
"winceCreateLock3", zFilename);
|
|
bLogged = TRUE;
|
|
}
|
|
winceMutexRelease(pFile->hMutex);
|
|
osCloseHandle(pFile->hMutex);
|
|
pFile->hMutex = NULL;
|
|
return SQLITE_IOERR;
|
|
}
|
|
|
|
/* Initialize the shared memory if we're supposed to */
|
|
if( bInit ){
|
|
memset(pFile->shared, 0, sizeof(winceLock));
|
|
}
|
|
|
|
winceMutexRelease(pFile->hMutex);
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** 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 */
|
|
osUnmapViewOfFile(pFile->shared);
|
|
osCloseHandle(pFile->hShared);
|
|
|
|
/* Done with the mutex */
|
|
winceMutexRelease(pFile->hMutex);
|
|
osCloseHandle(pFile->hMutex);
|
|
pFile->hMutex = NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** An implementation of the LockFile() API of Windows for CE
|
|
*/
|
|
static BOOL winceLockFile(
|
|
LPHANDLE phFile,
|
|
DWORD dwFileOffsetLow,
|
|
DWORD dwFileOffsetHigh,
|
|
DWORD nNumberOfBytesToLockLow,
|
|
DWORD nNumberOfBytesToLockHigh
|
|
){
|
|
winFile *pFile = HANDLE_TO_WINFILE(phFile);
|
|
BOOL bReturn = FALSE;
|
|
|
|
UNUSED_PARAMETER(dwFileOffsetHigh);
|
|
UNUSED_PARAMETER(nNumberOfBytesToLockHigh);
|
|
|
|
if (!pFile->hMutex) return TRUE;
|
|
winceMutexAcquire(pFile->hMutex);
|
|
|
|
/* Wanting an exclusive lock? */
|
|
if (dwFileOffsetLow == (DWORD)SHARED_FIRST
|
|
&& nNumberOfBytesToLockLow == (DWORD)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 == (DWORD)SHARED_FIRST &&
|
|
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 == (DWORD)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 == (DWORD)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 CE
|
|
*/
|
|
static BOOL winceUnlockFile(
|
|
LPHANDLE phFile,
|
|
DWORD dwFileOffsetLow,
|
|
DWORD dwFileOffsetHigh,
|
|
DWORD nNumberOfBytesToUnlockLow,
|
|
DWORD nNumberOfBytesToUnlockHigh
|
|
){
|
|
winFile *pFile = HANDLE_TO_WINFILE(phFile);
|
|
BOOL bReturn = FALSE;
|
|
|
|
UNUSED_PARAMETER(dwFileOffsetHigh);
|
|
UNUSED_PARAMETER(nNumberOfBytesToUnlockHigh);
|
|
|
|
if (!pFile->hMutex) return TRUE;
|
|
winceMutexAcquire(pFile->hMutex);
|
|
|
|
/* Releasing a reader lock or an exclusive lock */
|
|
if (dwFileOffsetLow == (DWORD)SHARED_FIRST){
|
|
/* Did we have an exclusive lock? */
|
|
if (pFile->local.bExclusive){
|
|
assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE);
|
|
pFile->local.bExclusive = FALSE;
|
|
pFile->shared->bExclusive = FALSE;
|
|
bReturn = TRUE;
|
|
}
|
|
|
|
/* Did we just have a reader lock? */
|
|
else if (pFile->local.nReaders){
|
|
assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE
|
|
|| nNumberOfBytesToUnlockLow == 1);
|
|
pFile->local.nReaders --;
|
|
if (pFile->local.nReaders == 0)
|
|
{
|
|
pFile->shared->nReaders --;
|
|
}
|
|
bReturn = TRUE;
|
|
}
|
|
}
|
|
|
|
/* Releasing a pending lock */
|
|
else if (dwFileOffsetLow == (DWORD)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 == (DWORD)RESERVED_BYTE
|
|
&& nNumberOfBytesToUnlockLow == 1){
|
|
if (pFile->local.bReserved) {
|
|
pFile->local.bReserved = FALSE;
|
|
pFile->shared->bReserved = FALSE;
|
|
bReturn = TRUE;
|
|
}
|
|
}
|
|
|
|
winceMutexRelease(pFile->hMutex);
|
|
return bReturn;
|
|
}
|
|
/*
|
|
** End of the special code for wince
|
|
*****************************************************************************/
|
|
#endif /* SQLITE_OS_WINCE */
|
|
|
|
/*
|
|
** Lock a file region.
|
|
*/
|
|
static BOOL winLockFile(
|
|
LPHANDLE phFile,
|
|
DWORD flags,
|
|
DWORD offsetLow,
|
|
DWORD offsetHigh,
|
|
DWORD numBytesLow,
|
|
DWORD numBytesHigh
|
|
){
|
|
#if SQLITE_OS_WINCE
|
|
/*
|
|
** NOTE: Windows CE is handled differently here due its lack of the Win32
|
|
** API LockFile.
|
|
*/
|
|
return winceLockFile(phFile, offsetLow, offsetHigh,
|
|
numBytesLow, numBytesHigh);
|
|
#else
|
|
if( osIsNT() ){
|
|
OVERLAPPED ovlp;
|
|
memset(&ovlp, 0, sizeof(OVERLAPPED));
|
|
ovlp.Offset = offsetLow;
|
|
ovlp.OffsetHigh = offsetHigh;
|
|
return osLockFileEx(*phFile, flags, 0, numBytesLow, numBytesHigh, &ovlp);
|
|
}else{
|
|
return osLockFile(*phFile, offsetLow, offsetHigh, numBytesLow,
|
|
numBytesHigh);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
** Unlock a file region.
|
|
*/
|
|
static BOOL winUnlockFile(
|
|
LPHANDLE phFile,
|
|
DWORD offsetLow,
|
|
DWORD offsetHigh,
|
|
DWORD numBytesLow,
|
|
DWORD numBytesHigh
|
|
){
|
|
#if SQLITE_OS_WINCE
|
|
/*
|
|
** NOTE: Windows CE is handled differently here due its lack of the Win32
|
|
** API UnlockFile.
|
|
*/
|
|
return winceUnlockFile(phFile, offsetLow, offsetHigh,
|
|
numBytesLow, numBytesHigh);
|
|
#else
|
|
if( osIsNT() ){
|
|
OVERLAPPED ovlp;
|
|
memset(&ovlp, 0, sizeof(OVERLAPPED));
|
|
ovlp.Offset = offsetLow;
|
|
ovlp.OffsetHigh = offsetHigh;
|
|
return osUnlockFileEx(*phFile, 0, numBytesLow, numBytesHigh, &ovlp);
|
|
}else{
|
|
return osUnlockFile(*phFile, offsetLow, offsetHigh, numBytesLow,
|
|
numBytesHigh);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*****************************************************************************
|
|
** The next group of routines implement the I/O methods specified
|
|
** by the sqlite3_io_methods object.
|
|
******************************************************************************/
|
|
|
|
/*
|
|
** Some Microsoft compilers lack this definition.
|
|
*/
|
|
#ifndef INVALID_SET_FILE_POINTER
|
|
# define INVALID_SET_FILE_POINTER ((DWORD)-1)
|
|
#endif
|
|
|
|
/*
|
|
** Move the current position of the file handle passed as the first
|
|
** argument to offset iOffset within the file. If successful, return 0.
|
|
** Otherwise, set pFile->lastErrno and return non-zero.
|
|
*/
|
|
static int winSeekFile(winFile *pFile, sqlite3_int64 iOffset){
|
|
#if !SQLITE_OS_WINRT
|
|
LONG upperBits; /* Most sig. 32 bits of new offset */
|
|
LONG lowerBits; /* Least sig. 32 bits of new offset */
|
|
DWORD dwRet; /* Value returned by SetFilePointer() */
|
|
DWORD lastErrno; /* Value returned by GetLastError() */
|
|
|
|
OSTRACE(("SEEK file=%p, offset=%lld\n", pFile->h, iOffset));
|
|
|
|
upperBits = (LONG)((iOffset>>32) & 0x7fffffff);
|
|
lowerBits = (LONG)(iOffset & 0xffffffff);
|
|
|
|
/* API oddity: If successful, SetFilePointer() returns a dword
|
|
** containing the lower 32-bits of the new file-offset. Or, if it fails,
|
|
** it returns INVALID_SET_FILE_POINTER. However according to MSDN,
|
|
** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine
|
|
** whether an error has actually occurred, it is also necessary to call
|
|
** GetLastError().
|
|
*/
|
|
dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
|
|
|
|
if( (dwRet==INVALID_SET_FILE_POINTER
|
|
&& ((lastErrno = osGetLastError())!=NO_ERROR)) ){
|
|
pFile->lastErrno = lastErrno;
|
|
winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
|
|
"winSeekFile", pFile->zPath);
|
|
OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
|
|
return 1;
|
|
}
|
|
|
|
OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h));
|
|
return 0;
|
|
#else
|
|
/*
|
|
** Same as above, except that this implementation works for WinRT.
|
|
*/
|
|
|
|
LARGE_INTEGER x; /* The new offset */
|
|
BOOL bRet; /* Value returned by SetFilePointerEx() */
|
|
|
|
x.QuadPart = iOffset;
|
|
bRet = osSetFilePointerEx(pFile->h, x, 0, FILE_BEGIN);
|
|
|
|
if(!bRet){
|
|
pFile->lastErrno = osGetLastError();
|
|
winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
|
|
"winSeekFile", pFile->zPath);
|
|
OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h));
|
|
return 1;
|
|
}
|
|
|
|
OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h));
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
/* Forward references to VFS helper methods used for memory mapped files */
|
|
static int winMapfile(winFile*, sqlite3_int64);
|
|
static int winUnmapfile(winFile*);
|
|
#endif
|
|
|
|
/*
|
|
** 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(sqlite3_file *id){
|
|
int rc, cnt = 0;
|
|
winFile *pFile = (winFile*)id;
|
|
|
|
assert( id!=0 );
|
|
#ifndef SQLITE_OMIT_WAL
|
|
assert( pFile->pShm==0 );
|
|
#endif
|
|
assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE );
|
|
OSTRACE(("CLOSE pid=%lu, pFile=%p, file=%p\n",
|
|
osGetCurrentProcessId(), pFile, pFile->h));
|
|
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
winUnmapfile(pFile);
|
|
#endif
|
|
|
|
do{
|
|
rc = osCloseHandle(pFile->h);
|
|
/* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */
|
|
}while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (sqlite3_win32_sleep(100), 1) );
|
|
#if SQLITE_OS_WINCE
|
|
#define WINCE_DELETION_ATTEMPTS 3
|
|
{
|
|
winVfsAppData *pAppData = (winVfsAppData*)pFile->pVfs->pAppData;
|
|
if( pAppData==NULL || !pAppData->bNoLock ){
|
|
winceDestroyLock(pFile);
|
|
}
|
|
}
|
|
if( pFile->zDeleteOnClose ){
|
|
int cnt = 0;
|
|
while(
|
|
osDeleteFileW(pFile->zDeleteOnClose)==0
|
|
&& osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff
|
|
&& cnt++ < WINCE_DELETION_ATTEMPTS
|
|
){
|
|
sqlite3_win32_sleep(100); /* Wait a little before trying again */
|
|
}
|
|
sqlite3_free(pFile->zDeleteOnClose);
|
|
}
|
|
#endif
|
|
if( rc ){
|
|
pFile->h = NULL;
|
|
}
|
|
OpenCounter(-1);
|
|
OSTRACE(("CLOSE pid=%lu, pFile=%p, file=%p, rc=%s\n",
|
|
osGetCurrentProcessId(), pFile, pFile->h, rc ? "ok" : "failed"));
|
|
return rc ? SQLITE_OK
|
|
: winLogError(SQLITE_IOERR_CLOSE, osGetLastError(),
|
|
"winClose", pFile->zPath);
|
|
}
|
|
|
|
/*
|
|
** 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(
|
|
sqlite3_file *id, /* File to read from */
|
|
void *pBuf, /* Write content into this buffer */
|
|
int amt, /* Number of bytes to read */
|
|
sqlite3_int64 offset /* Begin reading at this offset */
|
|
){
|
|
#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
|
|
OVERLAPPED overlapped; /* The offset for ReadFile. */
|
|
#endif
|
|
winFile *pFile = (winFile*)id; /* file handle */
|
|
DWORD nRead; /* Number of bytes actually read from file */
|
|
int nRetry = 0; /* Number of retrys */
|
|
|
|
assert( id!=0 );
|
|
assert( amt>0 );
|
|
assert( offset>=0 );
|
|
SimulateIOError(return SQLITE_IOERR_READ);
|
|
OSTRACE(("READ pid=%lu, pFile=%p, file=%p, buffer=%p, amount=%d, "
|
|
"offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile,
|
|
pFile->h, pBuf, amt, offset, pFile->locktype));
|
|
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
/* Deal with as much of this read request as possible by transferring
|
|
** data from the memory mapping using memcpy(). */
|
|
if( offset<pFile->mmapSize ){
|
|
if( offset+amt <= pFile->mmapSize ){
|
|
memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt);
|
|
OSTRACE(("READ-MMAP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
|
|
osGetCurrentProcessId(), pFile, pFile->h));
|
|
return SQLITE_OK;
|
|
}else{
|
|
int nCopy = (int)(pFile->mmapSize - offset);
|
|
memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], nCopy);
|
|
pBuf = &((u8 *)pBuf)[nCopy];
|
|
amt -= nCopy;
|
|
offset += nCopy;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED)
|
|
if( winSeekFile(pFile, offset) ){
|
|
OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_FULL\n",
|
|
osGetCurrentProcessId(), pFile, pFile->h));
|
|
return SQLITE_FULL;
|
|
}
|
|
while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
|
|
#else
|
|
memset(&overlapped, 0, sizeof(OVERLAPPED));
|
|
overlapped.Offset = (LONG)(offset & 0xffffffff);
|
|
overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
|
|
while( !osReadFile(pFile->h, pBuf, amt, &nRead, &overlapped) &&
|
|
osGetLastError()!=ERROR_HANDLE_EOF ){
|
|
#endif
|
|
DWORD lastErrno;
|
|
if( winRetryIoerr(&nRetry, &lastErrno) ) continue;
|
|
pFile->lastErrno = lastErrno;
|
|
OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_READ\n",
|
|
osGetCurrentProcessId(), pFile, pFile->h));
|
|
return winLogError(SQLITE_IOERR_READ, pFile->lastErrno,
|
|
"winRead", pFile->zPath);
|
|
}
|
|
winLogIoerr(nRetry, __LINE__);
|
|
if( nRead<(DWORD)amt ){
|
|
/* Unread parts of the buffer must be zero-filled */
|
|
memset(&((char*)pBuf)[nRead], 0, amt-nRead);
|
|
OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_SHORT_READ\n",
|
|
osGetCurrentProcessId(), pFile, pFile->h));
|
|
return SQLITE_IOERR_SHORT_READ;
|
|
}
|
|
|
|
OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
|
|
osGetCurrentProcessId(), pFile, pFile->h));
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Write data from a buffer into a file. Return SQLITE_OK on success
|
|
** or some other error code on failure.
|
|
*/
|
|
static int winWrite(
|
|
sqlite3_file *id, /* File to write into */
|
|
const void *pBuf, /* The bytes to be written */
|
|
int amt, /* Number of bytes to write */
|
|
sqlite3_int64 offset /* Offset into the file to begin writing at */
|
|
){
|
|
int rc = 0; /* True if error has occurred, else false */
|
|
winFile *pFile = (winFile*)id; /* File handle */
|
|
int nRetry = 0; /* Number of retries */
|
|
|
|
assert( amt>0 );
|
|
assert( pFile );
|
|
SimulateIOError(return SQLITE_IOERR_WRITE);
|
|
SimulateDiskfullError(return SQLITE_FULL);
|
|
|
|
OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, buffer=%p, amount=%d, "
|
|
"offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile,
|
|
pFile->h, pBuf, amt, offset, pFile->locktype));
|
|
|
|
#if defined(SQLITE_MMAP_READWRITE) && SQLITE_MAX_MMAP_SIZE>0
|
|
/* Deal with as much of this write request as possible by transferring
|
|
** data from the memory mapping using memcpy(). */
|
|
if( offset<pFile->mmapSize ){
|
|
if( offset+amt <= pFile->mmapSize ){
|
|
memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt);
|
|
OSTRACE(("WRITE-MMAP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
|
|
osGetCurrentProcessId(), pFile, pFile->h));
|
|
return SQLITE_OK;
|
|
}else{
|
|
int nCopy = (int)(pFile->mmapSize - offset);
|
|
memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, nCopy);
|
|
pBuf = &((u8 *)pBuf)[nCopy];
|
|
amt -= nCopy;
|
|
offset += nCopy;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED)
|
|
rc = winSeekFile(pFile, offset);
|
|
if( rc==0 ){
|
|
#else
|
|
{
|
|
#endif
|
|
#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
|
|
OVERLAPPED overlapped; /* The offset for WriteFile. */
|
|
#endif
|
|
u8 *aRem = (u8 *)pBuf; /* Data yet to be written */
|
|
int nRem = amt; /* Number of bytes yet to be written */
|
|
DWORD nWrite; /* Bytes written by each WriteFile() call */
|
|
DWORD lastErrno = NO_ERROR; /* Value returned by GetLastError() */
|
|
|
|
#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
|
|
memset(&overlapped, 0, sizeof(OVERLAPPED));
|
|
overlapped.Offset = (LONG)(offset & 0xffffffff);
|
|
overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
|
|
#endif
|
|
|
|
while( nRem>0 ){
|
|
#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED)
|
|
if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
|
|
#else
|
|
if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){
|
|
#endif
|
|
if( winRetryIoerr(&nRetry, &lastErrno) ) continue;
|
|
break;
|
|
}
|
|
assert( nWrite==0 || nWrite<=(DWORD)nRem );
|
|
if( nWrite==0 || nWrite>(DWORD)nRem ){
|
|
lastErrno = osGetLastError();
|
|
break;
|
|
}
|
|
#if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED)
|
|
offset += nWrite;
|
|
overlapped.Offset = (LONG)(offset & 0xffffffff);
|
|
overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff);
|
|
#endif
|
|
aRem += nWrite;
|
|
nRem -= nWrite;
|
|
}
|
|
if( nRem>0 ){
|
|
pFile->lastErrno = lastErrno;
|
|
rc = 1;
|
|
}
|
|
}
|
|
|
|
if( rc ){
|
|
if( ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL )
|
|
|| ( pFile->lastErrno==ERROR_DISK_FULL )){
|
|
OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_FULL\n",
|
|
osGetCurrentProcessId(), pFile, pFile->h));
|
|
return winLogError(SQLITE_FULL, pFile->lastErrno,
|
|
"winWrite1", pFile->zPath);
|
|
}
|
|
OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_WRITE\n",
|
|
osGetCurrentProcessId(), pFile, pFile->h));
|
|
return winLogError(SQLITE_IOERR_WRITE, pFile->lastErrno,
|
|
"winWrite2", pFile->zPath);
|
|
}else{
|
|
winLogIoerr(nRetry, __LINE__);
|
|
}
|
|
OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
|
|
osGetCurrentProcessId(), pFile, pFile->h));
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Truncate an open file to a specified size
|
|
*/
|
|
static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
|
|
winFile *pFile = (winFile*)id; /* File handle object */
|
|
int rc = SQLITE_OK; /* Return code for this function */
|
|
DWORD lastErrno;
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
sqlite3_int64 oldMmapSize;
|
|
if( pFile->nFetchOut>0 ){
|
|
/* File truncation is a no-op if there are outstanding memory mapped
|
|
** pages. This is because truncating the file means temporarily unmapping
|
|
** the file, and that might delete memory out from under existing cursors.
|
|
**
|
|
** This can result in incremental vacuum not truncating the file,
|
|
** if there is an active read cursor when the incremental vacuum occurs.
|
|
** No real harm comes of this - the database file is not corrupted,
|
|
** though some folks might complain that the file is bigger than it
|
|
** needs to be.
|
|
**
|
|
** The only feasible work-around is to defer the truncation until after
|
|
** all references to memory-mapped content are closed. That is doable,
|
|
** but involves adding a few branches in the common write code path which
|
|
** could slow down normal operations slightly. Hence, we have decided for
|
|
** now to simply make transactions a no-op if there are pending reads. We
|
|
** can maybe revisit this decision in the future.
|
|
*/
|
|
return SQLITE_OK;
|
|
}
|
|
#endif
|
|
|
|
assert( pFile );
|
|
SimulateIOError(return SQLITE_IOERR_TRUNCATE);
|
|
OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, size=%lld, lock=%d\n",
|
|
osGetCurrentProcessId(), pFile, pFile->h, nByte, pFile->locktype));
|
|
|
|
/* If the user has configured a chunk-size for this file, truncate the
|
|
** file so that it consists of an integer number of chunks (i.e. the
|
|
** actual file size after the operation may be larger than the requested
|
|
** size).
|
|
*/
|
|
if( pFile->szChunk>0 ){
|
|
nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
|
|
}
|
|
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
if( pFile->pMapRegion ){
|
|
oldMmapSize = pFile->mmapSize;
|
|
}else{
|
|
oldMmapSize = 0;
|
|
}
|
|
winUnmapfile(pFile);
|
|
#endif
|
|
|
|
/* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
|
|
if( winSeekFile(pFile, nByte) ){
|
|
rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
|
|
"winTruncate1", pFile->zPath);
|
|
}else if( 0==osSetEndOfFile(pFile->h) &&
|
|
((lastErrno = osGetLastError())!=ERROR_USER_MAPPED_FILE) ){
|
|
pFile->lastErrno = lastErrno;
|
|
rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
|
|
"winTruncate2", pFile->zPath);
|
|
}
|
|
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
if( rc==SQLITE_OK && oldMmapSize>0 ){
|
|
if( oldMmapSize>nByte ){
|
|
winMapfile(pFile, -1);
|
|
}else{
|
|
winMapfile(pFile, oldMmapSize);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, rc=%s\n",
|
|
osGetCurrentProcessId(), pFile, pFile->h, sqlite3ErrName(rc)));
|
|
return rc;
|
|
}
|
|
|
|
#ifdef SQLITE_TEST
|
|
/*
|
|
** Count the number of fullsyncs and normal syncs. This is used to test
|
|
** that syncs and fullsyncs are occurring at the right times.
|
|
*/
|
|
SQLITE_API int sqlite3_sync_count = 0;
|
|
SQLITE_API int sqlite3_fullsync_count = 0;
|
|
#endif
|
|
|
|
/*
|
|
** Make sure all writes to a particular file are committed to disk.
|
|
*/
|
|
static int winSync(sqlite3_file *id, int flags){
|
|
#ifndef SQLITE_NO_SYNC
|
|
/*
|
|
** Used only when SQLITE_NO_SYNC is not defined.
|
|
*/
|
|
BOOL rc;
|
|
#endif
|
|
#if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || \
|
|
defined(SQLITE_HAVE_OS_TRACE)
|
|
/*
|
|
** Used when SQLITE_NO_SYNC is not defined and by the assert() and/or
|
|
** OSTRACE() macros.
|
|
*/
|
|
winFile *pFile = (winFile*)id;
|
|
#else
|
|
UNUSED_PARAMETER(id);
|
|
#endif
|
|
|
|
assert( pFile );
|
|
/* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */
|
|
assert((flags&0x0F)==SQLITE_SYNC_NORMAL
|
|
|| (flags&0x0F)==SQLITE_SYNC_FULL
|
|
);
|
|
|
|
/* Unix cannot, but some systems may return SQLITE_FULL from here. This
|
|
** line is to test that doing so does not cause any problems.
|
|
*/
|
|
SimulateDiskfullError( return SQLITE_FULL );
|
|
|
|
OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, flags=%x, lock=%d\n",
|
|
osGetCurrentProcessId(), pFile, pFile->h, flags,
|
|
pFile->locktype));
|
|
|
|
#ifndef SQLITE_TEST
|
|
UNUSED_PARAMETER(flags);
|
|
#else
|
|
if( (flags&0x0F)==SQLITE_SYNC_FULL ){
|
|
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
|
|
OSTRACE(("SYNC-NOP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
|
|
osGetCurrentProcessId(), pFile, pFile->h));
|
|
return SQLITE_OK;
|
|
#else
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
if( pFile->pMapRegion ){
|
|
if( osFlushViewOfFile(pFile->pMapRegion, 0) ){
|
|
OSTRACE(("SYNC-MMAP pid=%lu, pFile=%p, pMapRegion=%p, "
|
|
"rc=SQLITE_OK\n", osGetCurrentProcessId(),
|
|
pFile, pFile->pMapRegion));
|
|
}else{
|
|
pFile->lastErrno = osGetLastError();
|
|
OSTRACE(("SYNC-MMAP pid=%lu, pFile=%p, pMapRegion=%p, "
|
|
"rc=SQLITE_IOERR_MMAP\n", osGetCurrentProcessId(),
|
|
pFile, pFile->pMapRegion));
|
|
return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno,
|
|
"winSync1", pFile->zPath);
|
|
}
|
|
}
|
|
#endif
|
|
rc = osFlushFileBuffers(pFile->h);
|
|
SimulateIOError( rc=FALSE );
|
|
if( rc ){
|
|
OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
|
|
osGetCurrentProcessId(), pFile, pFile->h));
|
|
return SQLITE_OK;
|
|
}else{
|
|
pFile->lastErrno = osGetLastError();
|
|
OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_FSYNC\n",
|
|
osGetCurrentProcessId(), pFile, pFile->h));
|
|
return winLogError(SQLITE_IOERR_FSYNC, pFile->lastErrno,
|
|
"winSync2", pFile->zPath);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
** Determine the current size of a file in bytes
|
|
*/
|
|
static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
|
|
winFile *pFile = (winFile*)id;
|
|
int rc = SQLITE_OK;
|
|
|
|
assert( id!=0 );
|
|
assert( pSize!=0 );
|
|
SimulateIOError(return SQLITE_IOERR_FSTAT);
|
|
OSTRACE(("SIZE file=%p, pSize=%p\n", pFile->h, pSize));
|
|
|
|
#if SQLITE_OS_WINRT
|
|
{
|
|
FILE_STANDARD_INFO info;
|
|
if( osGetFileInformationByHandleEx(pFile->h, FileStandardInfo,
|
|
&info, sizeof(info)) ){
|
|
*pSize = info.EndOfFile.QuadPart;
|
|
}else{
|
|
pFile->lastErrno = osGetLastError();
|
|
rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
|
|
"winFileSize", pFile->zPath);
|
|
}
|
|
}
|
|
#else
|
|
{
|
|
DWORD upperBits;
|
|
DWORD lowerBits;
|
|
DWORD lastErrno;
|
|
|
|
lowerBits = osGetFileSize(pFile->h, &upperBits);
|
|
*pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits;
|
|
if( (lowerBits == INVALID_FILE_SIZE)
|
|
&& ((lastErrno = osGetLastError())!=NO_ERROR) ){
|
|
pFile->lastErrno = lastErrno;
|
|
rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
|
|
"winFileSize", pFile->zPath);
|
|
}
|
|
}
|
|
#endif
|
|
OSTRACE(("SIZE file=%p, pSize=%p, *pSize=%lld, rc=%s\n",
|
|
pFile->h, pSize, *pSize, sqlite3ErrName(rc)));
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems.
|
|
*/
|
|
#ifndef LOCKFILE_FAIL_IMMEDIATELY
|
|
# define LOCKFILE_FAIL_IMMEDIATELY 1
|
|
#endif
|
|
|
|
#ifndef LOCKFILE_EXCLUSIVE_LOCK
|
|
# define LOCKFILE_EXCLUSIVE_LOCK 2
|
|
#endif
|
|
|
|
/*
|
|
** Historically, SQLite has used both the LockFile and LockFileEx functions.
|
|
** When the LockFile function was used, it was always expected to fail
|
|
** immediately if the lock could not be obtained. Also, it always expected to
|
|
** obtain an exclusive lock. These flags are used with the LockFileEx function
|
|
** and reflect those expectations; therefore, they should not be changed.
|
|
*/
|
|
#ifndef SQLITE_LOCKFILE_FLAGS
|
|
# define SQLITE_LOCKFILE_FLAGS (LOCKFILE_FAIL_IMMEDIATELY | \
|
|
LOCKFILE_EXCLUSIVE_LOCK)
|
|
#endif
|
|
|
|
/*
|
|
** Currently, SQLite never calls the LockFileEx function without wanting the
|
|
** call to fail immediately if the lock cannot be obtained.
|
|
*/
|
|
#ifndef SQLITE_LOCKFILEEX_FLAGS
|
|
# define SQLITE_LOCKFILEEX_FLAGS (LOCKFILE_FAIL_IMMEDIATELY)
|
|
#endif
|
|
|
|
/*
|
|
** Acquire a reader lock.
|
|
** Different API routines are called depending on whether or not this
|
|
** is Win9x or WinNT.
|
|
*/
|
|
static int winGetReadLock(winFile *pFile){
|
|
int res;
|
|
OSTRACE(("READ-LOCK file=%p, lock=%d\n", pFile->h, pFile->locktype));
|
|
if( osIsNT() ){
|
|
#if SQLITE_OS_WINCE
|
|
/*
|
|
** NOTE: Windows CE is handled differently here due its lack of the Win32
|
|
** API LockFileEx.
|
|
*/
|
|
res = winceLockFile(&pFile->h, SHARED_FIRST, 0, 1, 0);
|
|
#else
|
|
res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS, SHARED_FIRST, 0,
|
|
SHARED_SIZE, 0);
|
|
#endif
|
|
}
|
|
#ifdef SQLITE_WIN32_HAS_ANSI
|
|
else{
|
|
int lk;
|
|
sqlite3_randomness(sizeof(lk), &lk);
|
|
pFile->sharedLockByte = (short)((lk & 0x7fffffff)%(SHARED_SIZE - 1));
|
|
res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS,
|
|
SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
|
|
}
|
|
#endif
|
|
if( res == 0 ){
|
|
pFile->lastErrno = osGetLastError();
|
|
/* No need to log a failure to lock */
|
|
}
|
|
OSTRACE(("READ-LOCK file=%p, result=%d\n", pFile->h, res));
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
** Undo a readlock
|
|
*/
|
|
static int winUnlockReadLock(winFile *pFile){
|
|
int res;
|
|
DWORD lastErrno;
|
|
OSTRACE(("READ-UNLOCK file=%p, lock=%d\n", pFile->h, pFile->locktype));
|
|
if( osIsNT() ){
|
|
res = winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
|
|
}
|
|
#ifdef SQLITE_WIN32_HAS_ANSI
|
|
else{
|
|
res = winUnlockFile(&pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
|
|
}
|
|
#endif
|
|
if( res==0 && ((lastErrno = osGetLastError())!=ERROR_NOT_LOCKED) ){
|
|
pFile->lastErrno = lastErrno;
|
|
winLogError(SQLITE_IOERR_UNLOCK, pFile->lastErrno,
|
|
"winUnlockReadLock", pFile->zPath);
|
|
}
|
|
OSTRACE(("READ-UNLOCK file=%p, result=%d\n", pFile->h, res));
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
** 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(sqlite3_file *id, int locktype){
|
|
int rc = SQLITE_OK; /* Return code from subroutines */
|
|
int res = 1; /* Result of a Windows lock call */
|
|
int newLocktype; /* Set pFile->locktype to this value before exiting */
|
|
int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */
|
|
winFile *pFile = (winFile*)id;
|
|
DWORD lastErrno = NO_ERROR;
|
|
|
|
assert( id!=0 );
|
|
OSTRACE(("LOCK file=%p, oldLock=%d(%d), newLock=%d\n",
|
|
pFile->h, pFile->locktype, pFile->sharedLockByte, locktype));
|
|
|
|
/* 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 ){
|
|
OSTRACE(("LOCK-HELD file=%p, rc=SQLITE_OK\n", pFile->h));
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/* Do not allow any kind of write-lock on a read-only database
|
|
*/
|
|
if( (pFile->ctrlFlags & WINFILE_RDONLY)!=0 && locktype>=RESERVED_LOCK ){
|
|
return SQLITE_IOERR_LOCK;
|
|
}
|
|
|
|
/* 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 = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS,
|
|
PENDING_BYTE, 0, 1, 0))==0 ){
|
|
/* Try 3 times to get the pending lock. This is needed to work
|
|
** around problems caused by indexing and/or anti-virus software on
|
|
** Windows systems.
|
|
** If you are using this code as a model for alternative VFSes, do not
|
|
** copy this retry logic. It is a hack intended for Windows only.
|
|
*/
|
|
lastErrno = osGetLastError();
|
|
OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, result=%d\n",
|
|
pFile->h, cnt, res));
|
|
if( lastErrno==ERROR_INVALID_HANDLE ){
|
|
pFile->lastErrno = lastErrno;
|
|
rc = SQLITE_IOERR_LOCK;
|
|
OSTRACE(("LOCK-FAIL file=%p, count=%d, rc=%s\n",
|
|
pFile->h, cnt, sqlite3ErrName(rc)));
|
|
return rc;
|
|
}
|
|
if( cnt ) sqlite3_win32_sleep(1);
|
|
}
|
|
gotPendingLock = res;
|
|
if( !res ){
|
|
lastErrno = osGetLastError();
|
|
}
|
|
}
|
|
|
|
/* Acquire a shared lock
|
|
*/
|
|
if( locktype==SHARED_LOCK && res ){
|
|
assert( pFile->locktype==NO_LOCK );
|
|
res = winGetReadLock(pFile);
|
|
if( res ){
|
|
newLocktype = SHARED_LOCK;
|
|
}else{
|
|
lastErrno = osGetLastError();
|
|
}
|
|
}
|
|
|
|
/* Acquire a RESERVED lock
|
|
*/
|
|
if( locktype==RESERVED_LOCK && res ){
|
|
assert( pFile->locktype==SHARED_LOCK );
|
|
res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, RESERVED_BYTE, 0, 1, 0);
|
|
if( res ){
|
|
newLocktype = RESERVED_LOCK;
|
|
}else{
|
|
lastErrno = osGetLastError();
|
|
}
|
|
}
|
|
|
|
/* 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 );
|
|
(void)winUnlockReadLock(pFile);
|
|
res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, SHARED_FIRST, 0,
|
|
SHARED_SIZE, 0);
|
|
if( res ){
|
|
newLocktype = EXCLUSIVE_LOCK;
|
|
}else{
|
|
lastErrno = osGetLastError();
|
|
winGetReadLock(pFile);
|
|
}
|
|
}
|
|
|
|
/* If we are holding a PENDING lock that ought to be released, then
|
|
** release it now.
|
|
*/
|
|
if( gotPendingLock && locktype==SHARED_LOCK ){
|
|
winUnlockFile(&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{
|
|
pFile->lastErrno = lastErrno;
|
|
rc = SQLITE_BUSY;
|
|
OSTRACE(("LOCK-FAIL file=%p, wanted=%d, got=%d\n",
|
|
pFile->h, locktype, newLocktype));
|
|
}
|
|
pFile->locktype = (u8)newLocktype;
|
|
OSTRACE(("LOCK file=%p, lock=%d, rc=%s\n",
|
|
pFile->h, pFile->locktype, sqlite3ErrName(rc)));
|
|
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(sqlite3_file *id, int *pResOut){
|
|
int res;
|
|
winFile *pFile = (winFile*)id;
|
|
|
|
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
|
|
OSTRACE(("TEST-WR-LOCK file=%p, pResOut=%p\n", pFile->h, pResOut));
|
|
|
|
assert( id!=0 );
|
|
if( pFile->locktype>=RESERVED_LOCK ){
|
|
res = 1;
|
|
OSTRACE(("TEST-WR-LOCK file=%p, result=%d (local)\n", pFile->h, res));
|
|
}else{
|
|
res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS,RESERVED_BYTE,0,1,0);
|
|
if( res ){
|
|
winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0);
|
|
}
|
|
res = !res;
|
|
OSTRACE(("TEST-WR-LOCK file=%p, result=%d (remote)\n", pFile->h, res));
|
|
}
|
|
*pResOut = res;
|
|
OSTRACE(("TEST-WR-LOCK file=%p, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n",
|
|
pFile->h, pResOut, *pResOut));
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** 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(sqlite3_file *id, int locktype){
|
|
int type;
|
|
winFile *pFile = (winFile*)id;
|
|
int rc = SQLITE_OK;
|
|
assert( pFile!=0 );
|
|
assert( locktype<=SHARED_LOCK );
|
|
OSTRACE(("UNLOCK file=%p, oldLock=%d(%d), newLock=%d\n",
|
|
pFile->h, pFile->locktype, pFile->sharedLockByte, locktype));
|
|
type = pFile->locktype;
|
|
if( type>=EXCLUSIVE_LOCK ){
|
|
winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
|
|
if( locktype==SHARED_LOCK && !winGetReadLock(pFile) ){
|
|
/* This should never happen. We should always be able to
|
|
** reacquire the read lock */
|
|
rc = winLogError(SQLITE_IOERR_UNLOCK, osGetLastError(),
|
|
"winUnlock", pFile->zPath);
|
|
}
|
|
}
|
|
if( type>=RESERVED_LOCK ){
|
|
winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0);
|
|
}
|
|
if( locktype==NO_LOCK && type>=SHARED_LOCK ){
|
|
winUnlockReadLock(pFile);
|
|
}
|
|
if( type>=PENDING_LOCK ){
|
|
winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0);
|
|
}
|
|
pFile->locktype = (u8)locktype;
|
|
OSTRACE(("UNLOCK file=%p, lock=%d, rc=%s\n",
|
|
pFile->h, pFile->locktype, sqlite3ErrName(rc)));
|
|
return rc;
|
|
}
|
|
|
|
/******************************************************************************
|
|
****************************** No-op Locking **********************************
|
|
**
|
|
** Of the various locking implementations available, this is by far the
|
|
** simplest: locking is ignored. No attempt is made to lock the database
|
|
** file for reading or writing.
|
|
**
|
|
** This locking mode is appropriate for use on read-only databases
|
|
** (ex: databases that are burned into CD-ROM, for example.) It can
|
|
** also be used if the application employs some external mechanism to
|
|
** prevent simultaneous access of the same database by two or more
|
|
** database connections. But there is a serious risk of database
|
|
** corruption if this locking mode is used in situations where multiple
|
|
** database connections are accessing the same database file at the same
|
|
** time and one or more of those connections are writing.
|
|
*/
|
|
|
|
static int winNolockLock(sqlite3_file *id, int locktype){
|
|
UNUSED_PARAMETER(id);
|
|
UNUSED_PARAMETER(locktype);
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
static int winNolockCheckReservedLock(sqlite3_file *id, int *pResOut){
|
|
UNUSED_PARAMETER(id);
|
|
UNUSED_PARAMETER(pResOut);
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
static int winNolockUnlock(sqlite3_file *id, int locktype){
|
|
UNUSED_PARAMETER(id);
|
|
UNUSED_PARAMETER(locktype);
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/******************* End of the no-op lock implementation *********************
|
|
******************************************************************************/
|
|
|
|
/*
|
|
** If *pArg is initially negative then this is a query. Set *pArg to
|
|
** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set.
|
|
**
|
|
** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags.
|
|
*/
|
|
static void winModeBit(winFile *pFile, unsigned char mask, int *pArg){
|
|
if( *pArg<0 ){
|
|
*pArg = (pFile->ctrlFlags & mask)!=0;
|
|
}else if( (*pArg)==0 ){
|
|
pFile->ctrlFlags &= ~mask;
|
|
}else{
|
|
pFile->ctrlFlags |= mask;
|
|
}
|
|
}
|
|
|
|
/* Forward references to VFS helper methods used for temporary files */
|
|
static int winGetTempname(sqlite3_vfs *, char **);
|
|
static int winIsDir(const void *);
|
|
static BOOL winIsLongPathPrefix(const char *);
|
|
static BOOL winIsDriveLetterAndColon(const char *);
|
|
|
|
/*
|
|
** Control and query of the open file handle.
|
|
*/
|
|
static int winFileControl(sqlite3_file *id, int op, void *pArg){
|
|
winFile *pFile = (winFile*)id;
|
|
OSTRACE(("FCNTL file=%p, op=%d, pArg=%p\n", pFile->h, op, pArg));
|
|
switch( op ){
|
|
case SQLITE_FCNTL_LOCKSTATE: {
|
|
*(int*)pArg = pFile->locktype;
|
|
OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
|
|
return SQLITE_OK;
|
|
}
|
|
case SQLITE_FCNTL_LAST_ERRNO: {
|
|
*(int*)pArg = (int)pFile->lastErrno;
|
|
OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
|
|
return SQLITE_OK;
|
|
}
|
|
case SQLITE_FCNTL_CHUNK_SIZE: {
|
|
pFile->szChunk = *(int *)pArg;
|
|
OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
|
|
return SQLITE_OK;
|
|
}
|
|
case SQLITE_FCNTL_SIZE_HINT: {
|
|
if( pFile->szChunk>0 ){
|
|
sqlite3_int64 oldSz;
|
|
int rc = winFileSize(id, &oldSz);
|
|
if( rc==SQLITE_OK ){
|
|
sqlite3_int64 newSz = *(sqlite3_int64*)pArg;
|
|
if( newSz>oldSz ){
|
|
SimulateIOErrorBenign(1);
|
|
rc = winTruncate(id, newSz);
|
|
SimulateIOErrorBenign(0);
|
|
}
|
|
}
|
|
OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));
|
|
return rc;
|
|
}
|
|
OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
|
|
return SQLITE_OK;
|
|
}
|
|
case SQLITE_FCNTL_PERSIST_WAL: {
|
|
winModeBit(pFile, WINFILE_PERSIST_WAL, (int*)pArg);
|
|
OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
|
|
return SQLITE_OK;
|
|
}
|
|
case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
|
|
winModeBit(pFile, WINFILE_PSOW, (int*)pArg);
|
|
OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
|
|
return SQLITE_OK;
|
|
}
|
|
case SQLITE_FCNTL_VFSNAME: {
|
|
*(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName);
|
|
OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
|
|
return SQLITE_OK;
|
|
}
|
|
case SQLITE_FCNTL_WIN32_AV_RETRY: {
|
|
int *a = (int*)pArg;
|
|
if( a[0]>0 ){
|
|
winIoerrRetry = a[0];
|
|
}else{
|
|
a[0] = winIoerrRetry;
|
|
}
|
|
if( a[1]>0 ){
|
|
winIoerrRetryDelay = a[1];
|
|
}else{
|
|
a[1] = winIoerrRetryDelay;
|
|
}
|
|
OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
|
|
return SQLITE_OK;
|
|
}
|
|
case SQLITE_FCNTL_WIN32_GET_HANDLE: {
|
|
LPHANDLE phFile = (LPHANDLE)pArg;
|
|
*phFile = pFile->h;
|
|
OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
|
|
return SQLITE_OK;
|
|
}
|
|
#ifdef SQLITE_TEST
|
|
case SQLITE_FCNTL_WIN32_SET_HANDLE: {
|
|
LPHANDLE phFile = (LPHANDLE)pArg;
|
|
HANDLE hOldFile = pFile->h;
|
|
pFile->h = *phFile;
|
|
*phFile = hOldFile;
|
|
OSTRACE(("FCNTL oldFile=%p, newFile=%p, rc=SQLITE_OK\n",
|
|
hOldFile, pFile->h));
|
|
return SQLITE_OK;
|
|
}
|
|
#endif
|
|
case SQLITE_FCNTL_TEMPFILENAME: {
|
|
char *zTFile = 0;
|
|
int rc = winGetTempname(pFile->pVfs, &zTFile);
|
|
if( rc==SQLITE_OK ){
|
|
*(char**)pArg = zTFile;
|
|
}
|
|
OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));
|
|
return rc;
|
|
}
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
case SQLITE_FCNTL_MMAP_SIZE: {
|
|
i64 newLimit = *(i64*)pArg;
|
|
int rc = SQLITE_OK;
|
|
if( newLimit>sqlite3GlobalConfig.mxMmap ){
|
|
newLimit = sqlite3GlobalConfig.mxMmap;
|
|
}
|
|
|
|
/* The value of newLimit may be eventually cast to (SIZE_T) and passed
|
|
** to MapViewOfFile(). Restrict its value to 2GB if (SIZE_T) is not at
|
|
** least a 64-bit type. */
|
|
if( newLimit>0 && sizeof(SIZE_T)<8 ){
|
|
newLimit = (newLimit & 0x7FFFFFFF);
|
|
}
|
|
|
|
*(i64*)pArg = pFile->mmapSizeMax;
|
|
if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){
|
|
pFile->mmapSizeMax = newLimit;
|
|
if( pFile->mmapSize>0 ){
|
|
winUnmapfile(pFile);
|
|
rc = winMapfile(pFile, -1);
|
|
}
|
|
}
|
|
OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));
|
|
return rc;
|
|
}
|
|
#endif
|
|
}
|
|
OSTRACE(("FCNTL file=%p, rc=SQLITE_NOTFOUND\n", pFile->h));
|
|
return SQLITE_NOTFOUND;
|
|
}
|
|
|
|
/*
|
|
** 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 its journal file) that the sector size will be the
|
|
** same for both.
|
|
*/
|
|
static int winSectorSize(sqlite3_file *id){
|
|
(void)id;
|
|
return SQLITE_DEFAULT_SECTOR_SIZE;
|
|
}
|
|
|
|
/*
|
|
** Return a vector of device characteristics.
|
|
*/
|
|
static int winDeviceCharacteristics(sqlite3_file *id){
|
|
winFile *p = (winFile*)id;
|
|
return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN |
|
|
((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0);
|
|
}
|
|
|
|
/*
|
|
** Windows will only let you create file view mappings
|
|
** on allocation size granularity boundaries.
|
|
** During sqlite3_os_init() we do a GetSystemInfo()
|
|
** to get the granularity size.
|
|
*/
|
|
static SYSTEM_INFO winSysInfo;
|
|
|
|
#ifndef SQLITE_OMIT_WAL
|
|
|
|
/*
|
|
** Helper functions to obtain and relinquish the global mutex. The
|
|
** global mutex is used to protect the winLockInfo objects used by
|
|
** this file, all of which may be shared by multiple threads.
|
|
**
|
|
** Function winShmMutexHeld() is used to assert() that the global mutex
|
|
** is held when required. This function is only used as part of assert()
|
|
** statements. e.g.
|
|
**
|
|
** winShmEnterMutex()
|
|
** assert( winShmMutexHeld() );
|
|
** winShmLeaveMutex()
|
|
*/
|
|
static sqlite3_mutex *winBigLock = 0;
|
|
static void winShmEnterMutex(void){
|
|
sqlite3_mutex_enter(winBigLock);
|
|
}
|
|
static void winShmLeaveMutex(void){
|
|
sqlite3_mutex_leave(winBigLock);
|
|
}
|
|
#ifndef NDEBUG
|
|
static int winShmMutexHeld(void) {
|
|
return sqlite3_mutex_held(winBigLock);
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
** Object used to represent a single file opened and mmapped to provide
|
|
** shared memory. When multiple threads all reference the same
|
|
** log-summary, each thread has its own winFile object, but they all
|
|
** point to a single instance of this object. In other words, each
|
|
** log-summary is opened only once per process.
|
|
**
|
|
** winShmMutexHeld() must be true when creating or destroying
|
|
** this object or while reading or writing the following fields:
|
|
**
|
|
** nRef
|
|
** pNext
|
|
**
|
|
** The following fields are read-only after the object is created:
|
|
**
|
|
** fid
|
|
** zFilename
|
|
**
|
|
** Either winShmNode.mutex must be held or winShmNode.nRef==0 and
|
|
** winShmMutexHeld() is true when reading or writing any other field
|
|
** in this structure.
|
|
**
|
|
*/
|
|
struct winShmNode {
|
|
sqlite3_mutex *mutex; /* Mutex to access this object */
|
|
char *zFilename; /* Name of the file */
|
|
winFile hFile; /* File handle from winOpen */
|
|
|
|
int szRegion; /* Size of shared-memory regions */
|
|
int nRegion; /* Size of array apRegion */
|
|
u8 isReadonly; /* True if read-only */
|
|
u8 isUnlocked; /* True if no DMS lock held */
|
|
|
|
struct ShmRegion {
|
|
HANDLE hMap; /* File handle from CreateFileMapping */
|
|
void *pMap;
|
|
} *aRegion;
|
|
DWORD lastErrno; /* The Windows errno from the last I/O error */
|
|
|
|
int nRef; /* Number of winShm objects pointing to this */
|
|
winShm *pFirst; /* All winShm objects pointing to this */
|
|
winShmNode *pNext; /* Next in list of all winShmNode objects */
|
|
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
|
|
u8 nextShmId; /* Next available winShm.id value */
|
|
#endif
|
|
};
|
|
|
|
/*
|
|
** A global array of all winShmNode objects.
|
|
**
|
|
** The winShmMutexHeld() must be true while reading or writing this list.
|
|
*/
|
|
static winShmNode *winShmNodeList = 0;
|
|
|
|
/*
|
|
** Structure used internally by this VFS to record the state of an
|
|
** open shared memory connection.
|
|
**
|
|
** The following fields are initialized when this object is created and
|
|
** are read-only thereafter:
|
|
**
|
|
** winShm.pShmNode
|
|
** winShm.id
|
|
**
|
|
** All other fields are read/write. The winShm.pShmNode->mutex must be held
|
|
** while accessing any read/write fields.
|
|
*/
|
|
struct winShm {
|
|
winShmNode *pShmNode; /* The underlying winShmNode object */
|
|
winShm *pNext; /* Next winShm with the same winShmNode */
|
|
u8 hasMutex; /* True if holding the winShmNode mutex */
|
|
u16 sharedMask; /* Mask of shared locks held */
|
|
u16 exclMask; /* Mask of exclusive locks held */
|
|
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
|
|
u8 id; /* Id of this connection with its winShmNode */
|
|
#endif
|
|
};
|
|
|
|
/*
|
|
** Constants used for locking
|
|
*/
|
|
#define WIN_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */
|
|
#define WIN_SHM_DMS (WIN_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */
|
|
|
|
/*
|
|
** Apply advisory locks for all n bytes beginning at ofst.
|
|
*/
|
|
#define WINSHM_UNLCK 1
|
|
#define WINSHM_RDLCK 2
|
|
#define WINSHM_WRLCK 3
|
|
static int winShmSystemLock(
|
|
winShmNode *pFile, /* Apply locks to this open shared-memory segment */
|
|
int lockType, /* WINSHM_UNLCK, WINSHM_RDLCK, or WINSHM_WRLCK */
|
|
int ofst, /* Offset to first byte to be locked/unlocked */
|
|
int nByte /* Number of bytes to lock or unlock */
|
|
){
|
|
int rc = 0; /* Result code form Lock/UnlockFileEx() */
|
|
|
|
/* Access to the winShmNode object is serialized by the caller */
|
|
assert( pFile->nRef==0 || sqlite3_mutex_held(pFile->mutex) );
|
|
|
|
OSTRACE(("SHM-LOCK file=%p, lock=%d, offset=%d, size=%d\n",
|
|
pFile->hFile.h, lockType, ofst, nByte));
|
|
|
|
/* Release/Acquire the system-level lock */
|
|
if( lockType==WINSHM_UNLCK ){
|
|
rc = winUnlockFile(&pFile->hFile.h, ofst, 0, nByte, 0);
|
|
}else{
|
|
/* Initialize the locking parameters */
|
|
DWORD dwFlags = LOCKFILE_FAIL_IMMEDIATELY;
|
|
if( lockType == WINSHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
|
|
rc = winLockFile(&pFile->hFile.h, dwFlags, ofst, 0, nByte, 0);
|
|
}
|
|
|
|
if( rc!= 0 ){
|
|
rc = SQLITE_OK;
|
|
}else{
|
|
pFile->lastErrno = osGetLastError();
|
|
rc = SQLITE_BUSY;
|
|
}
|
|
|
|
OSTRACE(("SHM-LOCK file=%p, func=%s, errno=%lu, rc=%s\n",
|
|
pFile->hFile.h, (lockType == WINSHM_UNLCK) ? "winUnlockFile" :
|
|
"winLockFile", pFile->lastErrno, sqlite3ErrName(rc)));
|
|
|
|
return rc;
|
|
}
|
|
|
|
/* Forward references to VFS methods */
|
|
static int winOpen(sqlite3_vfs*,const char*,sqlite3_file*,int,int*);
|
|
static int winDelete(sqlite3_vfs *,const char*,int);
|
|
|
|
/*
|
|
** Purge the winShmNodeList list of all entries with winShmNode.nRef==0.
|
|
**
|
|
** This is not a VFS shared-memory method; it is a utility function called
|
|
** by VFS shared-memory methods.
|
|
*/
|
|
static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
|
|
winShmNode **pp;
|
|
winShmNode *p;
|
|
assert( winShmMutexHeld() );
|
|
OSTRACE(("SHM-PURGE pid=%lu, deleteFlag=%d\n",
|
|
osGetCurrentProcessId(), deleteFlag));
|
|
pp = &winShmNodeList;
|
|
while( (p = *pp)!=0 ){
|
|
if( p->nRef==0 ){
|
|
int i;
|
|
if( p->mutex ){ sqlite3_mutex_free(p->mutex); }
|
|
for(i=0; i<p->nRegion; i++){
|
|
BOOL bRc = osUnmapViewOfFile(p->aRegion[i].pMap);
|
|
OSTRACE(("SHM-PURGE-UNMAP pid=%lu, region=%d, rc=%s\n",
|
|
osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
|
|
UNUSED_VARIABLE_VALUE(bRc);
|
|
bRc = osCloseHandle(p->aRegion[i].hMap);
|
|
OSTRACE(("SHM-PURGE-CLOSE pid=%lu, region=%d, rc=%s\n",
|
|
osGetCurrentProcessId(), i, bRc ? "ok" : "failed"));
|
|
UNUSED_VARIABLE_VALUE(bRc);
|
|
}
|
|
if( p->hFile.h!=NULL && p->hFile.h!=INVALID_HANDLE_VALUE ){
|
|
SimulateIOErrorBenign(1);
|
|
winClose((sqlite3_file *)&p->hFile);
|
|
SimulateIOErrorBenign(0);
|
|
}
|
|
if( deleteFlag ){
|
|
SimulateIOErrorBenign(1);
|
|
sqlite3BeginBenignMalloc();
|
|
winDelete(pVfs, p->zFilename, 0);
|
|
sqlite3EndBenignMalloc();
|
|
SimulateIOErrorBenign(0);
|
|
}
|
|
*pp = p->pNext;
|
|
sqlite3_free(p->aRegion);
|
|
sqlite3_free(p);
|
|
}else{
|
|
pp = &p->pNext;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** The DMS lock has not yet been taken on shm file pShmNode. Attempt to
|
|
** take it now. Return SQLITE_OK if successful, or an SQLite error
|
|
** code otherwise.
|
|
**
|
|
** If the DMS cannot be locked because this is a readonly_shm=1
|
|
** connection and no other process already holds a lock, return
|
|
** SQLITE_READONLY_CANTINIT and set pShmNode->isUnlocked=1.
|
|
*/
|
|
static int winLockSharedMemory(winShmNode *pShmNode){
|
|
int rc = winShmSystemLock(pShmNode, WINSHM_WRLCK, WIN_SHM_DMS, 1);
|
|
|
|
if( rc==SQLITE_OK ){
|
|
if( pShmNode->isReadonly ){
|
|
pShmNode->isUnlocked = 1;
|
|
winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
|
|
return SQLITE_READONLY_CANTINIT;
|
|
}else if( winTruncate((sqlite3_file*)&pShmNode->hFile, 0) ){
|
|
winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
|
|
return winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(),
|
|
"winLockSharedMemory", pShmNode->zFilename);
|
|
}
|
|
}
|
|
|
|
if( rc==SQLITE_OK ){
|
|
winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
|
|
}
|
|
|
|
return winShmSystemLock(pShmNode, WINSHM_RDLCK, WIN_SHM_DMS, 1);
|
|
}
|
|
|
|
/*
|
|
** Open the shared-memory area associated with database file pDbFd.
|
|
**
|
|
** When opening a new shared-memory file, if no other instances of that
|
|
** file are currently open, in this process or in other processes, then
|
|
** the file must be truncated to zero length or have its header cleared.
|
|
*/
|
|
static int winOpenSharedMemory(winFile *pDbFd){
|
|
struct winShm *p; /* The connection to be opened */
|
|
winShmNode *pShmNode = 0; /* The underlying mmapped file */
|
|
int rc = SQLITE_OK; /* Result code */
|
|
winShmNode *pNew; /* Newly allocated winShmNode */
|
|
int nName; /* Size of zName in bytes */
|
|
|
|
assert( pDbFd->pShm==0 ); /* Not previously opened */
|
|
|
|
/* Allocate space for the new sqlite3_shm object. Also speculatively
|
|
** allocate space for a new winShmNode and filename.
|
|
*/
|
|
p = sqlite3MallocZero( sizeof(*p) );
|
|
if( p==0 ) return SQLITE_IOERR_NOMEM_BKPT;
|
|
nName = sqlite3Strlen30(pDbFd->zPath);
|
|
pNew = sqlite3MallocZero( sizeof(*pShmNode) + nName + 17 );
|
|
if( pNew==0 ){
|
|
sqlite3_free(p);
|
|
return SQLITE_IOERR_NOMEM_BKPT;
|
|
}
|
|
pNew->zFilename = (char*)&pNew[1];
|
|
sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
|
|
sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename);
|
|
|
|
/* Look to see if there is an existing winShmNode that can be used.
|
|
** If no matching winShmNode currently exists, create a new one.
|
|
*/
|
|
winShmEnterMutex();
|
|
for(pShmNode = winShmNodeList; pShmNode; pShmNode=pShmNode->pNext){
|
|
/* TBD need to come up with better match here. Perhaps
|
|
** use FILE_ID_BOTH_DIR_INFO Structure.
|
|
*/
|
|
if( sqlite3StrICmp(pShmNode->zFilename, pNew->zFilename)==0 ) break;
|
|
}
|
|
if( pShmNode ){
|
|
sqlite3_free(pNew);
|
|
}else{
|
|
int inFlags = SQLITE_OPEN_WAL;
|
|
int outFlags = 0;
|
|
|
|
pShmNode = pNew;
|
|
pNew = 0;
|
|
((winFile*)(&pShmNode->hFile))->h = INVALID_HANDLE_VALUE;
|
|
pShmNode->pNext = winShmNodeList;
|
|
winShmNodeList = pShmNode;
|
|
|
|
if( sqlite3GlobalConfig.bCoreMutex ){
|
|
pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
|
|
if( pShmNode->mutex==0 ){
|
|
rc = SQLITE_IOERR_NOMEM_BKPT;
|
|
goto shm_open_err;
|
|
}
|
|
}
|
|
|
|
if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
|
|
inFlags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
|
|
}else{
|
|
inFlags |= SQLITE_OPEN_READONLY;
|
|
}
|
|
rc = winOpen(pDbFd->pVfs, pShmNode->zFilename,
|
|
(sqlite3_file*)&pShmNode->hFile,
|
|
inFlags, &outFlags);
|
|
if( rc!=SQLITE_OK ){
|
|
rc = winLogError(rc, osGetLastError(), "winOpenShm",
|
|
pShmNode->zFilename);
|
|
goto shm_open_err;
|
|
}
|
|
if( outFlags==SQLITE_OPEN_READONLY ) pShmNode->isReadonly = 1;
|
|
|
|
rc = winLockSharedMemory(pShmNode);
|
|
if( rc!=SQLITE_OK && rc!=SQLITE_READONLY_CANTINIT ) goto shm_open_err;
|
|
}
|
|
|
|
/* Make the new connection a child of the winShmNode */
|
|
p->pShmNode = pShmNode;
|
|
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
|
|
p->id = pShmNode->nextShmId++;
|
|
#endif
|
|
pShmNode->nRef++;
|
|
pDbFd->pShm = p;
|
|
winShmLeaveMutex();
|
|
|
|
/* The reference count on pShmNode has already been incremented under
|
|
** the cover of the winShmEnterMutex() mutex and the pointer from the
|
|
** new (struct winShm) object to the pShmNode has been set. All that is
|
|
** left to do is to link the new object into the linked list starting
|
|
** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
|
|
** mutex.
|
|
*/
|
|
sqlite3_mutex_enter(pShmNode->mutex);
|
|
p->pNext = pShmNode->pFirst;
|
|
pShmNode->pFirst = p;
|
|
sqlite3_mutex_leave(pShmNode->mutex);
|
|
return rc;
|
|
|
|
/* Jump here on any error */
|
|
shm_open_err:
|
|
winShmSystemLock(pShmNode, WINSHM_UNLCK, WIN_SHM_DMS, 1);
|
|
winShmPurge(pDbFd->pVfs, 0); /* This call frees pShmNode if required */
|
|
sqlite3_free(p);
|
|
sqlite3_free(pNew);
|
|
winShmLeaveMutex();
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Close a connection to shared-memory. Delete the underlying
|
|
** storage if deleteFlag is true.
|
|
*/
|
|
static int winShmUnmap(
|
|
sqlite3_file *fd, /* Database holding shared memory */
|
|
int deleteFlag /* Delete after closing if true */
|
|
){
|
|
winFile *pDbFd; /* Database holding shared-memory */
|
|
winShm *p; /* The connection to be closed */
|
|
winShmNode *pShmNode; /* The underlying shared-memory file */
|
|
winShm **pp; /* For looping over sibling connections */
|
|
|
|
pDbFd = (winFile*)fd;
|
|
p = pDbFd->pShm;
|
|
if( p==0 ) return SQLITE_OK;
|
|
pShmNode = p->pShmNode;
|
|
|
|
/* Remove connection p from the set of connections associated
|
|
** with pShmNode */
|
|
sqlite3_mutex_enter(pShmNode->mutex);
|
|
for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
|
|
*pp = p->pNext;
|
|
|
|
/* Free the connection p */
|
|
sqlite3_free(p);
|
|
pDbFd->pShm = 0;
|
|
sqlite3_mutex_leave(pShmNode->mutex);
|
|
|
|
/* If pShmNode->nRef has reached 0, then close the underlying
|
|
** shared-memory file, too */
|
|
winShmEnterMutex();
|
|
assert( pShmNode->nRef>0 );
|
|
pShmNode->nRef--;
|
|
if( pShmNode->nRef==0 ){
|
|
winShmPurge(pDbFd->pVfs, deleteFlag);
|
|
}
|
|
winShmLeaveMutex();
|
|
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Change the lock state for a shared-memory segment.
|
|
*/
|
|
static int winShmLock(
|
|
sqlite3_file *fd, /* Database file holding the shared memory */
|
|
int ofst, /* First lock to acquire or release */
|
|
int n, /* Number of locks to acquire or release */
|
|
int flags /* What to do with the lock */
|
|
){
|
|
winFile *pDbFd = (winFile*)fd; /* Connection holding shared memory */
|
|
winShm *p = pDbFd->pShm; /* The shared memory being locked */
|
|
winShm *pX; /* For looping over all siblings */
|
|
winShmNode *pShmNode;
|
|
int rc = SQLITE_OK; /* Result code */
|
|
u16 mask; /* Mask of locks to take or release */
|
|
|
|
if( p==0 ) return SQLITE_IOERR_SHMLOCK;
|
|
pShmNode = p->pShmNode;
|
|
if( NEVER(pShmNode==0) ) return SQLITE_IOERR_SHMLOCK;
|
|
|
|
assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
|
|
assert( n>=1 );
|
|
assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
|
|
|| flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE)
|
|
|| flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
|
|
|| flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
|
|
assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
|
|
|
|
mask = (u16)((1U<<(ofst+n)) - (1U<<ofst));
|
|
assert( n>1 || mask==(1<<ofst) );
|
|
sqlite3_mutex_enter(pShmNode->mutex);
|
|
if( flags & SQLITE_SHM_UNLOCK ){
|
|
u16 allMask = 0; /* Mask of locks held by siblings */
|
|
|
|
/* See if any siblings hold this same lock */
|
|
for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
|
|
if( pX==p ) continue;
|
|
assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
|
|
allMask |= pX->sharedMask;
|
|
}
|
|
|
|
/* Unlock the system-level locks */
|
|
if( (mask & allMask)==0 ){
|
|
rc = winShmSystemLock(pShmNode, WINSHM_UNLCK, ofst+WIN_SHM_BASE, n);
|
|
}else{
|
|
rc = SQLITE_OK;
|
|
}
|
|
|
|
/* Undo the local locks */
|
|
if( rc==SQLITE_OK ){
|
|
p->exclMask &= ~mask;
|
|
p->sharedMask &= ~mask;
|
|
}
|
|
}else if( flags & SQLITE_SHM_SHARED ){
|
|
u16 allShared = 0; /* Union of locks held by connections other than "p" */
|
|
|
|
/* Find out which shared locks are already held by sibling connections.
|
|
** If any sibling already holds an exclusive lock, go ahead and return
|
|
** SQLITE_BUSY.
|
|
*/
|
|
for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
|
|
if( (pX->exclMask & mask)!=0 ){
|
|
rc = SQLITE_BUSY;
|
|
break;
|
|
}
|
|
allShared |= pX->sharedMask;
|
|
}
|
|
|
|
/* Get shared locks at the system level, if necessary */
|
|
if( rc==SQLITE_OK ){
|
|
if( (allShared & mask)==0 ){
|
|
rc = winShmSystemLock(pShmNode, WINSHM_RDLCK, ofst+WIN_SHM_BASE, n);
|
|
}else{
|
|
rc = SQLITE_OK;
|
|
}
|
|
}
|
|
|
|
/* Get the local shared locks */
|
|
if( rc==SQLITE_OK ){
|
|
p->sharedMask |= mask;
|
|
}
|
|
}else{
|
|
/* Make sure no sibling connections hold locks that will block this
|
|
** lock. If any do, return SQLITE_BUSY right away.
|
|
*/
|
|
for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
|
|
if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
|
|
rc = SQLITE_BUSY;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Get the exclusive locks at the system level. Then if successful
|
|
** also mark the local connection as being locked.
|
|
*/
|
|
if( rc==SQLITE_OK ){
|
|
rc = winShmSystemLock(pShmNode, WINSHM_WRLCK, ofst+WIN_SHM_BASE, n);
|
|
if( rc==SQLITE_OK ){
|
|
assert( (p->sharedMask & mask)==0 );
|
|
p->exclMask |= mask;
|
|
}
|
|
}
|
|
}
|
|
sqlite3_mutex_leave(pShmNode->mutex);
|
|
OSTRACE(("SHM-LOCK pid=%lu, id=%d, sharedMask=%03x, exclMask=%03x, rc=%s\n",
|
|
osGetCurrentProcessId(), p->id, p->sharedMask, p->exclMask,
|
|
sqlite3ErrName(rc)));
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Implement a memory barrier or memory fence on shared memory.
|
|
**
|
|
** All loads and stores begun before the barrier must complete before
|
|
** any load or store begun after the barrier.
|
|
*/
|
|
static void winShmBarrier(
|
|
sqlite3_file *fd /* Database holding the shared memory */
|
|
){
|
|
UNUSED_PARAMETER(fd);
|
|
sqlite3MemoryBarrier(); /* compiler-defined memory barrier */
|
|
winShmEnterMutex(); /* Also mutex, for redundancy */
|
|
winShmLeaveMutex();
|
|
}
|
|
|
|
/*
|
|
** This function is called to obtain a pointer to region iRegion of the
|
|
** shared-memory associated with the database file fd. Shared-memory regions
|
|
** are numbered starting from zero. Each shared-memory region is szRegion
|
|
** bytes in size.
|
|
**
|
|
** If an error occurs, an error code is returned and *pp is set to NULL.
|
|
**
|
|
** Otherwise, if the isWrite parameter is 0 and the requested shared-memory
|
|
** region has not been allocated (by any client, including one running in a
|
|
** separate process), then *pp is set to NULL and SQLITE_OK returned. If
|
|
** isWrite is non-zero and the requested shared-memory region has not yet
|
|
** been allocated, it is allocated by this function.
|
|
**
|
|
** If the shared-memory region has already been allocated or is allocated by
|
|
** this call as described above, then it is mapped into this processes
|
|
** address space (if it is not already), *pp is set to point to the mapped
|
|
** memory and SQLITE_OK returned.
|
|
*/
|
|
static int winShmMap(
|
|
sqlite3_file *fd, /* Handle open on database file */
|
|
int iRegion, /* Region to retrieve */
|
|
int szRegion, /* Size of regions */
|
|
int isWrite, /* True to extend file if necessary */
|
|
void volatile **pp /* OUT: Mapped memory */
|
|
){
|
|
winFile *pDbFd = (winFile*)fd;
|
|
winShm *pShm = pDbFd->pShm;
|
|
winShmNode *pShmNode;
|
|
DWORD protect = PAGE_READWRITE;
|
|
DWORD flags = FILE_MAP_WRITE | FILE_MAP_READ;
|
|
int rc = SQLITE_OK;
|
|
|
|
if( !pShm ){
|
|
rc = winOpenSharedMemory(pDbFd);
|
|
if( rc!=SQLITE_OK ) return rc;
|
|
pShm = pDbFd->pShm;
|
|
assert( pShm!=0 );
|
|
}
|
|
pShmNode = pShm->pShmNode;
|
|
|
|
sqlite3_mutex_enter(pShmNode->mutex);
|
|
if( pShmNode->isUnlocked ){
|
|
rc = winLockSharedMemory(pShmNode);
|
|
if( rc!=SQLITE_OK ) goto shmpage_out;
|
|
pShmNode->isUnlocked = 0;
|
|
}
|
|
assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
|
|
|
|
if( pShmNode->nRegion<=iRegion ){
|
|
struct ShmRegion *apNew; /* New aRegion[] array */
|
|
int nByte = (iRegion+1)*szRegion; /* Minimum required file size */
|
|
sqlite3_int64 sz; /* Current size of wal-index file */
|
|
|
|
pShmNode->szRegion = szRegion;
|
|
|
|
/* The requested region is not mapped into this processes address space.
|
|
** Check to see if it has been allocated (i.e. if the wal-index file is
|
|
** large enough to contain the requested region).
|
|
*/
|
|
rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
|
|
if( rc!=SQLITE_OK ){
|
|
rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(),
|
|
"winShmMap1", pDbFd->zPath);
|
|
goto shmpage_out;
|
|
}
|
|
|
|
if( sz<nByte ){
|
|
/* The requested memory region does not exist. If isWrite is set to
|
|
** zero, exit early. *pp will be set to NULL and SQLITE_OK returned.
|
|
**
|
|
** Alternatively, if isWrite is non-zero, use ftruncate() to allocate
|
|
** the requested memory region.
|
|
*/
|
|
if( !isWrite ) goto shmpage_out;
|
|
rc = winTruncate((sqlite3_file *)&pShmNode->hFile, nByte);
|
|
if( rc!=SQLITE_OK ){
|
|
rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(),
|
|
"winShmMap2", pDbFd->zPath);
|
|
goto shmpage_out;
|
|
}
|
|
}
|
|
|
|
/* Map the requested memory region into this processes address space. */
|
|
apNew = (struct ShmRegion *)sqlite3_realloc64(
|
|
pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0])
|
|
);
|
|
if( !apNew ){
|
|
rc = SQLITE_IOERR_NOMEM_BKPT;
|
|
goto shmpage_out;
|
|
}
|
|
pShmNode->aRegion = apNew;
|
|
|
|
if( pShmNode->isReadonly ){
|
|
protect = PAGE_READONLY;
|
|
flags = FILE_MAP_READ;
|
|
}
|
|
|
|
while( pShmNode->nRegion<=iRegion ){
|
|
HANDLE hMap = NULL; /* file-mapping handle */
|
|
void *pMap = 0; /* Mapped memory region */
|
|
|
|
#if SQLITE_OS_WINRT
|
|
hMap = osCreateFileMappingFromApp(pShmNode->hFile.h,
|
|
NULL, protect, nByte, NULL
|
|
);
|
|
#elif defined(SQLITE_WIN32_HAS_WIDE)
|
|
hMap = osCreateFileMappingW(pShmNode->hFile.h,
|
|
NULL, protect, 0, nByte, NULL
|
|
);
|
|
#elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA
|
|
hMap = osCreateFileMappingA(pShmNode->hFile.h,
|
|
NULL, protect, 0, nByte, NULL
|
|
);
|
|
#endif
|
|
OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n",
|
|
osGetCurrentProcessId(), pShmNode->nRegion, nByte,
|
|
hMap ? "ok" : "failed"));
|
|
if( hMap ){
|
|
int iOffset = pShmNode->nRegion*szRegion;
|
|
int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
|
|
#if SQLITE_OS_WINRT
|
|
pMap = osMapViewOfFileFromApp(hMap, flags,
|
|
iOffset - iOffsetShift, szRegion + iOffsetShift
|
|
);
|
|
#else
|
|
pMap = osMapViewOfFile(hMap, flags,
|
|
0, iOffset - iOffsetShift, szRegion + iOffsetShift
|
|
);
|
|
#endif
|
|
OSTRACE(("SHM-MAP-MAP pid=%lu, region=%d, offset=%d, size=%d, rc=%s\n",
|
|
osGetCurrentProcessId(), pShmNode->nRegion, iOffset,
|
|
szRegion, pMap ? "ok" : "failed"));
|
|
}
|
|
if( !pMap ){
|
|
pShmNode->lastErrno = osGetLastError();
|
|
rc = winLogError(SQLITE_IOERR_SHMMAP, pShmNode->lastErrno,
|
|
"winShmMap3", pDbFd->zPath);
|
|
if( hMap ) osCloseHandle(hMap);
|
|
goto shmpage_out;
|
|
}
|
|
|
|
pShmNode->aRegion[pShmNode->nRegion].pMap = pMap;
|
|
pShmNode->aRegion[pShmNode->nRegion].hMap = hMap;
|
|
pShmNode->nRegion++;
|
|
}
|
|
}
|
|
|
|
shmpage_out:
|
|
if( pShmNode->nRegion>iRegion ){
|
|
int iOffset = iRegion*szRegion;
|
|
int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
|
|
char *p = (char *)pShmNode->aRegion[iRegion].pMap;
|
|
*pp = (void *)&p[iOffsetShift];
|
|
}else{
|
|
*pp = 0;
|
|
}
|
|
if( pShmNode->isReadonly && rc==SQLITE_OK ) rc = SQLITE_READONLY;
|
|
sqlite3_mutex_leave(pShmNode->mutex);
|
|
return rc;
|
|
}
|
|
|
|
#else
|
|
# define winShmMap 0
|
|
# define winShmLock 0
|
|
# define winShmBarrier 0
|
|
# define winShmUnmap 0
|
|
#endif /* #ifndef SQLITE_OMIT_WAL */
|
|
|
|
/*
|
|
** Cleans up the mapped region of the specified file, if any.
|
|
*/
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
static int winUnmapfile(winFile *pFile){
|
|
assert( pFile!=0 );
|
|
OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, pMapRegion=%p, "
|
|
"mmapSize=%lld, mmapSizeMax=%lld\n",
|
|
osGetCurrentProcessId(), pFile, pFile->hMap, pFile->pMapRegion,
|
|
pFile->mmapSize, pFile->mmapSizeMax));
|
|
if( pFile->pMapRegion ){
|
|
if( !osUnmapViewOfFile(pFile->pMapRegion) ){
|
|
pFile->lastErrno = osGetLastError();
|
|
OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, pMapRegion=%p, "
|
|
"rc=SQLITE_IOERR_MMAP\n", osGetCurrentProcessId(), pFile,
|
|
pFile->pMapRegion));
|
|
return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno,
|
|
"winUnmapfile1", pFile->zPath);
|
|
}
|
|
pFile->pMapRegion = 0;
|
|
pFile->mmapSize = 0;
|
|
}
|
|
if( pFile->hMap!=NULL ){
|
|
if( !osCloseHandle(pFile->hMap) ){
|
|
pFile->lastErrno = osGetLastError();
|
|
OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, rc=SQLITE_IOERR_MMAP\n",
|
|
osGetCurrentProcessId(), pFile, pFile->hMap));
|
|
return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno,
|
|
"winUnmapfile2", pFile->zPath);
|
|
}
|
|
pFile->hMap = NULL;
|
|
}
|
|
OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n",
|
|
osGetCurrentProcessId(), pFile));
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Memory map or remap the file opened by file-descriptor pFd (if the file
|
|
** is already mapped, the existing mapping is replaced by the new). Or, if
|
|
** there already exists a mapping for this file, and there are still
|
|
** outstanding xFetch() references to it, this function is a no-op.
|
|
**
|
|
** If parameter nByte is non-negative, then it is the requested size of
|
|
** the mapping to create. Otherwise, if nByte is less than zero, then the
|
|
** requested size is the size of the file on disk. The actual size of the
|
|
** created mapping is either the requested size or the value configured
|
|
** using SQLITE_FCNTL_MMAP_SIZE, whichever is smaller.
|
|
**
|
|
** SQLITE_OK is returned if no error occurs (even if the mapping is not
|
|
** recreated as a result of outstanding references) or an SQLite error
|
|
** code otherwise.
|
|
*/
|
|
static int winMapfile(winFile *pFd, sqlite3_int64 nByte){
|
|
sqlite3_int64 nMap = nByte;
|
|
int rc;
|
|
|
|
assert( nMap>=0 || pFd->nFetchOut==0 );
|
|
OSTRACE(("MAP-FILE pid=%lu, pFile=%p, size=%lld\n",
|
|
osGetCurrentProcessId(), pFd, nByte));
|
|
|
|
if( pFd->nFetchOut>0 ) return SQLITE_OK;
|
|
|
|
if( nMap<0 ){
|
|
rc = winFileSize((sqlite3_file*)pFd, &nMap);
|
|
if( rc ){
|
|
OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_IOERR_FSTAT\n",
|
|
osGetCurrentProcessId(), pFd));
|
|
return SQLITE_IOERR_FSTAT;
|
|
}
|
|
}
|
|
if( nMap>pFd->mmapSizeMax ){
|
|
nMap = pFd->mmapSizeMax;
|
|
}
|
|
nMap &= ~(sqlite3_int64)(winSysInfo.dwPageSize - 1);
|
|
|
|
if( nMap==0 && pFd->mmapSize>0 ){
|
|
winUnmapfile(pFd);
|
|
}
|
|
if( nMap!=pFd->mmapSize ){
|
|
void *pNew = 0;
|
|
DWORD protect = PAGE_READONLY;
|
|
DWORD flags = FILE_MAP_READ;
|
|
|
|
winUnmapfile(pFd);
|
|
#ifdef SQLITE_MMAP_READWRITE
|
|
if( (pFd->ctrlFlags & WINFILE_RDONLY)==0 ){
|
|
protect = PAGE_READWRITE;
|
|
flags |= FILE_MAP_WRITE;
|
|
}
|
|
#endif
|
|
#if SQLITE_OS_WINRT
|
|
pFd->hMap = osCreateFileMappingFromApp(pFd->h, NULL, protect, nMap, NULL);
|
|
#elif defined(SQLITE_WIN32_HAS_WIDE)
|
|
pFd->hMap = osCreateFileMappingW(pFd->h, NULL, protect,
|
|
(DWORD)((nMap>>32) & 0xffffffff),
|
|
(DWORD)(nMap & 0xffffffff), NULL);
|
|
#elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA
|
|
pFd->hMap = osCreateFileMappingA(pFd->h, NULL, protect,
|
|
(DWORD)((nMap>>32) & 0xffffffff),
|
|
(DWORD)(nMap & 0xffffffff), NULL);
|
|
#endif
|
|
if( pFd->hMap==NULL ){
|
|
pFd->lastErrno = osGetLastError();
|
|
rc = winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno,
|
|
"winMapfile1", pFd->zPath);
|
|
/* Log the error, but continue normal operation using xRead/xWrite */
|
|
OSTRACE(("MAP-FILE-CREATE pid=%lu, pFile=%p, rc=%s\n",
|
|
osGetCurrentProcessId(), pFd, sqlite3ErrName(rc)));
|
|
return SQLITE_OK;
|
|
}
|
|
assert( (nMap % winSysInfo.dwPageSize)==0 );
|
|
assert( sizeof(SIZE_T)==sizeof(sqlite3_int64) || nMap<=0xffffffff );
|
|
#if SQLITE_OS_WINRT
|
|
pNew = osMapViewOfFileFromApp(pFd->hMap, flags, 0, (SIZE_T)nMap);
|
|
#else
|
|
pNew = osMapViewOfFile(pFd->hMap, flags, 0, 0, (SIZE_T)nMap);
|
|
#endif
|
|
if( pNew==NULL ){
|
|
osCloseHandle(pFd->hMap);
|
|
pFd->hMap = NULL;
|
|
pFd->lastErrno = osGetLastError();
|
|
rc = winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno,
|
|
"winMapfile2", pFd->zPath);
|
|
/* Log the error, but continue normal operation using xRead/xWrite */
|
|
OSTRACE(("MAP-FILE-MAP pid=%lu, pFile=%p, rc=%s\n",
|
|
osGetCurrentProcessId(), pFd, sqlite3ErrName(rc)));
|
|
return SQLITE_OK;
|
|
}
|
|
pFd->pMapRegion = pNew;
|
|
pFd->mmapSize = nMap;
|
|
}
|
|
|
|
OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n",
|
|
osGetCurrentProcessId(), pFd));
|
|
return SQLITE_OK;
|
|
}
|
|
#endif /* SQLITE_MAX_MMAP_SIZE>0 */
|
|
|
|
/*
|
|
** If possible, return a pointer to a mapping of file fd starting at offset
|
|
** iOff. The mapping must be valid for at least nAmt bytes.
|
|
**
|
|
** If such a pointer can be obtained, store it in *pp and return SQLITE_OK.
|
|
** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK.
|
|
** Finally, if an error does occur, return an SQLite error code. The final
|
|
** value of *pp is undefined in this case.
|
|
**
|
|
** If this function does return a pointer, the caller must eventually
|
|
** release the reference by calling winUnfetch().
|
|
*/
|
|
static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
winFile *pFd = (winFile*)fd; /* The underlying database file */
|
|
#endif
|
|
*pp = 0;
|
|
|
|
OSTRACE(("FETCH pid=%lu, pFile=%p, offset=%lld, amount=%d, pp=%p\n",
|
|
osGetCurrentProcessId(), fd, iOff, nAmt, pp));
|
|
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
if( pFd->mmapSizeMax>0 ){
|
|
/* Ensure that there is always at least a 256 byte buffer of addressable
|
|
** memory following the returned page. If the database is corrupt,
|
|
** SQLite may overread the page slightly (in practice only a few bytes,
|
|
** but 256 is safe, round, number). */
|
|
const int nEofBuffer = 256;
|
|
if( pFd->pMapRegion==0 ){
|
|
int rc = winMapfile(pFd, -1);
|
|
if( rc!=SQLITE_OK ){
|
|
OSTRACE(("FETCH pid=%lu, pFile=%p, rc=%s\n",
|
|
osGetCurrentProcessId(), pFd, sqlite3ErrName(rc)));
|
|
return rc;
|
|
}
|
|
}
|
|
if( pFd->mmapSize >= (iOff+nAmt+nEofBuffer) ){
|
|
assert( pFd->pMapRegion!=0 );
|
|
*pp = &((u8 *)pFd->pMapRegion)[iOff];
|
|
pFd->nFetchOut++;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
OSTRACE(("FETCH pid=%lu, pFile=%p, pp=%p, *pp=%p, rc=SQLITE_OK\n",
|
|
osGetCurrentProcessId(), fd, pp, *pp));
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** If the third argument is non-NULL, then this function releases a
|
|
** reference obtained by an earlier call to winFetch(). The second
|
|
** argument passed to this function must be the same as the corresponding
|
|
** argument that was passed to the winFetch() invocation.
|
|
**
|
|
** Or, if the third argument is NULL, then this function is being called
|
|
** to inform the VFS layer that, according to POSIX, any existing mapping
|
|
** may now be invalid and should be unmapped.
|
|
*/
|
|
static int winUnfetch(sqlite3_file *fd, i64 iOff, void *p){
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
winFile *pFd = (winFile*)fd; /* The underlying database file */
|
|
|
|
/* If p==0 (unmap the entire file) then there must be no outstanding
|
|
** xFetch references. Or, if p!=0 (meaning it is an xFetch reference),
|
|
** then there must be at least one outstanding. */
|
|
assert( (p==0)==(pFd->nFetchOut==0) );
|
|
|
|
/* If p!=0, it must match the iOff value. */
|
|
assert( p==0 || p==&((u8 *)pFd->pMapRegion)[iOff] );
|
|
|
|
OSTRACE(("UNFETCH pid=%lu, pFile=%p, offset=%lld, p=%p\n",
|
|
osGetCurrentProcessId(), pFd, iOff, p));
|
|
|
|
if( p ){
|
|
pFd->nFetchOut--;
|
|
}else{
|
|
/* FIXME: If Windows truly always prevents truncating or deleting a
|
|
** file while a mapping is held, then the following winUnmapfile() call
|
|
** is unnecessary can be omitted - potentially improving
|
|
** performance. */
|
|
winUnmapfile(pFd);
|
|
}
|
|
|
|
assert( pFd->nFetchOut>=0 );
|
|
#endif
|
|
|
|
OSTRACE(("UNFETCH pid=%lu, pFile=%p, rc=SQLITE_OK\n",
|
|
osGetCurrentProcessId(), fd));
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Here ends the implementation of all sqlite3_file methods.
|
|
**
|
|
********************** End sqlite3_file Methods *******************************
|
|
******************************************************************************/
|
|
|
|
/*
|
|
** This vector defines all the methods that can operate on an
|
|
** sqlite3_file for win32.
|
|
*/
|
|
static const sqlite3_io_methods winIoMethod = {
|
|
3, /* iVersion */
|
|
winClose, /* xClose */
|
|
winRead, /* xRead */
|
|
winWrite, /* xWrite */
|
|
winTruncate, /* xTruncate */
|
|
winSync, /* xSync */
|
|
winFileSize, /* xFileSize */
|
|
winLock, /* xLock */
|
|
winUnlock, /* xUnlock */
|
|
winCheckReservedLock, /* xCheckReservedLock */
|
|
winFileControl, /* xFileControl */
|
|
winSectorSize, /* xSectorSize */
|
|
winDeviceCharacteristics, /* xDeviceCharacteristics */
|
|
winShmMap, /* xShmMap */
|
|
winShmLock, /* xShmLock */
|
|
winShmBarrier, /* xShmBarrier */
|
|
winShmUnmap, /* xShmUnmap */
|
|
winFetch, /* xFetch */
|
|
winUnfetch /* xUnfetch */
|
|
};
|
|
|
|
/*
|
|
** This vector defines all the methods that can operate on an
|
|
** sqlite3_file for win32 without performing any locking.
|
|
*/
|
|
static const sqlite3_io_methods winIoNolockMethod = {
|
|
3, /* iVersion */
|
|
winClose, /* xClose */
|
|
winRead, /* xRead */
|
|
winWrite, /* xWrite */
|
|
winTruncate, /* xTruncate */
|
|
winSync, /* xSync */
|
|
winFileSize, /* xFileSize */
|
|
winNolockLock, /* xLock */
|
|
winNolockUnlock, /* xUnlock */
|
|
winNolockCheckReservedLock, /* xCheckReservedLock */
|
|
winFileControl, /* xFileControl */
|
|
winSectorSize, /* xSectorSize */
|
|
winDeviceCharacteristics, /* xDeviceCharacteristics */
|
|
winShmMap, /* xShmMap */
|
|
winShmLock, /* xShmLock */
|
|
winShmBarrier, /* xShmBarrier */
|
|
winShmUnmap, /* xShmUnmap */
|
|
winFetch, /* xFetch */
|
|
winUnfetch /* xUnfetch */
|
|
};
|
|
|
|
static winVfsAppData winAppData = {
|
|
&winIoMethod, /* pMethod */
|
|
0, /* pAppData */
|
|
0 /* bNoLock */
|
|
};
|
|
|
|
static winVfsAppData winNolockAppData = {
|
|
&winIoNolockMethod, /* pMethod */
|
|
0, /* pAppData */
|
|
1 /* bNoLock */
|
|
};
|
|
|
|
/****************************************************************************
|
|
**************************** sqlite3_vfs methods ****************************
|
|
**
|
|
** This division contains the implementation of methods on the
|
|
** sqlite3_vfs object.
|
|
*/
|
|
|
|
#if defined(__CYGWIN__)
|
|
/*
|
|
** Convert a filename from whatever the underlying operating system
|
|
** supports for filenames into UTF-8. Space to hold the result is
|
|
** obtained from malloc and must be freed by the calling function.
|
|
*/
|
|
static char *winConvertToUtf8Filename(const void *zFilename){
|
|
char *zConverted = 0;
|
|
if( osIsNT() ){
|
|
zConverted = winUnicodeToUtf8(zFilename);
|
|
}
|
|
#ifdef SQLITE_WIN32_HAS_ANSI
|
|
else{
|
|
zConverted = winMbcsToUtf8(zFilename, osAreFileApisANSI());
|
|
}
|
|
#endif
|
|
/* caller will handle out of memory */
|
|
return zConverted;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
** Convert a UTF-8 filename into whatever form the underlying
|
|
** operating system wants filenames in. Space to hold the result
|
|
** is obtained from malloc and must be freed by the calling
|
|
** function.
|
|
*/
|
|
static void *winConvertFromUtf8Filename(const char *zFilename){
|
|
void *zConverted = 0;
|
|
if( osIsNT() ){
|
|
zConverted = winUtf8ToUnicode(zFilename);
|
|
}
|
|
#ifdef SQLITE_WIN32_HAS_ANSI
|
|
else{
|
|
zConverted = winUtf8ToMbcs(zFilename, osAreFileApisANSI());
|
|
}
|
|
#endif
|
|
/* caller will handle out of memory */
|
|
return zConverted;
|
|
}
|
|
|
|
/*
|
|
** This function returns non-zero if the specified UTF-8 string buffer
|
|
** ends with a directory separator character or one was successfully
|
|
** added to it.
|
|
*/
|
|
static int winMakeEndInDirSep(int nBuf, char *zBuf){
|
|
if( zBuf ){
|
|
int nLen = sqlite3Strlen30(zBuf);
|
|
if( nLen>0 ){
|
|
if( winIsDirSep(zBuf[nLen-1]) ){
|
|
return 1;
|
|
}else if( nLen+1<nBuf ){
|
|
zBuf[nLen] = winGetDirSep();
|
|
zBuf[nLen+1] = '\0';
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
** If sqlite3_temp_directory is defined, take the mutex and return true.
|
|
**
|
|
** If sqlite3_temp_directory is NULL (undefined), omit the mutex and
|
|
** return false.
|
|
*/
|
|
static int winTempDirDefined(void){
|
|
sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
|
|
if( sqlite3_temp_directory!=0 ) return 1;
|
|
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
** Create a temporary file name and store the resulting pointer into pzBuf.
|
|
** The pointer returned in pzBuf must be freed via sqlite3_free().
|
|
*/
|
|
static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
|
|
static char zChars[] =
|
|
"abcdefghijklmnopqrstuvwxyz"
|
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
"0123456789";
|
|
size_t i, j;
|
|
DWORD pid;
|
|
int nPre = sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX);
|
|
int nMax, nBuf, nDir, nLen;
|
|
char *zBuf;
|
|
|
|
/* It's odd to simulate an io-error here, but really this is just
|
|
** using the io-error infrastructure to test that SQLite handles this
|
|
** function failing.
|
|
*/
|
|
SimulateIOError( return SQLITE_IOERR );
|
|
|
|
/* Allocate a temporary buffer to store the fully qualified file
|
|
** name for the temporary file. If this fails, we cannot continue.
|
|
*/
|
|
nMax = pVfs->mxPathname; nBuf = nMax + 2;
|
|
zBuf = sqlite3MallocZero( nBuf );
|
|
if( !zBuf ){
|
|
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
|
|
return SQLITE_IOERR_NOMEM_BKPT;
|
|
}
|
|
|
|
/* Figure out the effective temporary directory. First, check if one
|
|
** has been explicitly set by the application; otherwise, use the one
|
|
** configured by the operating system.
|
|
*/
|
|
nDir = nMax - (nPre + 15);
|
|
assert( nDir>0 );
|
|
if( winTempDirDefined() ){
|
|
int nDirLen = sqlite3Strlen30(sqlite3_temp_directory);
|
|
if( nDirLen>0 ){
|
|
if( !winIsDirSep(sqlite3_temp_directory[nDirLen-1]) ){
|
|
nDirLen++;
|
|
}
|
|
if( nDirLen>nDir ){
|
|
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
|
|
sqlite3_free(zBuf);
|
|
OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n"));
|
|
return winLogError(SQLITE_ERROR, 0, "winGetTempname1", 0);
|
|
}
|
|
sqlite3_snprintf(nMax, zBuf, "%s", sqlite3_temp_directory);
|
|
}
|
|
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR));
|
|
}
|
|
|
|
#if defined(__CYGWIN__)
|
|
else{
|
|
static const char *azDirs[] = {
|
|
0, /* getenv("SQLITE_TMPDIR") */
|
|
0, /* getenv("TMPDIR") */
|
|
0, /* getenv("TMP") */
|
|
0, /* getenv("TEMP") */
|
|
0, /* getenv("USERPROFILE") */
|
|
"/var/tmp",
|
|
"/usr/tmp",
|
|
"/tmp",
|
|
".",
|
|
0 /* List terminator */
|
|
};
|
|
unsigned int i;
|
|
const char *zDir = 0;
|
|
|
|
if( !azDirs[0] ) azDirs[0] = getenv("SQLITE_TMPDIR");
|
|
if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR");
|
|
if( !azDirs[2] ) azDirs[2] = getenv("TMP");
|
|
if( !azDirs[3] ) azDirs[3] = getenv("TEMP");
|
|
if( !azDirs[4] ) azDirs[4] = getenv("USERPROFILE");
|
|
for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); zDir=azDirs[i++]){
|
|
void *zConverted;
|
|
if( zDir==0 ) continue;
|
|
/* If the path starts with a drive letter followed by the colon
|
|
** character, assume it is already a native Win32 path; otherwise,
|
|
** it must be converted to a native Win32 path via the Cygwin API
|
|
** prior to using it.
|
|
*/
|
|
if( winIsDriveLetterAndColon(zDir) ){
|
|
zConverted = winConvertFromUtf8Filename(zDir);
|
|
if( !zConverted ){
|
|
sqlite3_free(zBuf);
|
|
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
|
|
return SQLITE_IOERR_NOMEM_BKPT;
|
|
}
|
|
if( winIsDir(zConverted) ){
|
|
sqlite3_snprintf(nMax, zBuf, "%s", zDir);
|
|
sqlite3_free(zConverted);
|
|
break;
|
|
}
|
|
sqlite3_free(zConverted);
|
|
}else{
|
|
zConverted = sqlite3MallocZero( nMax+1 );
|
|
if( !zConverted ){
|
|
sqlite3_free(zBuf);
|
|
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
|
|
return SQLITE_IOERR_NOMEM_BKPT;
|
|
}
|
|
if( cygwin_conv_path(
|
|
osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A, zDir,
|
|
zConverted, nMax+1)<0 ){
|
|
sqlite3_free(zConverted);
|
|
sqlite3_free(zBuf);
|
|
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_CONVPATH\n"));
|
|
return winLogError(SQLITE_IOERR_CONVPATH, (DWORD)errno,
|
|
"winGetTempname2", zDir);
|
|
}
|
|
if( winIsDir(zConverted) ){
|
|
/* At this point, we know the candidate directory exists and should
|
|
** be used. However, we may need to convert the string containing
|
|
** its name into UTF-8 (i.e. if it is UTF-16 right now).
|
|
*/
|
|
char *zUtf8 = winConvertToUtf8Filename(zConverted);
|
|
if( !zUtf8 ){
|
|
sqlite3_free(zConverted);
|
|
sqlite3_free(zBuf);
|
|
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
|
|
return SQLITE_IOERR_NOMEM_BKPT;
|
|
}
|
|
sqlite3_snprintf(nMax, zBuf, "%s", zUtf8);
|
|
sqlite3_free(zUtf8);
|
|
sqlite3_free(zConverted);
|
|
break;
|
|
}
|
|
sqlite3_free(zConverted);
|
|
}
|
|
}
|
|
}
|
|
#elif !SQLITE_OS_WINRT && !defined(__CYGWIN__)
|
|
else if( osIsNT() ){
|
|
char *zMulti;
|
|
LPWSTR zWidePath = sqlite3MallocZero( nMax*sizeof(WCHAR) );
|
|
if( !zWidePath ){
|
|
sqlite3_free(zBuf);
|
|
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
|
|
return SQLITE_IOERR_NOMEM_BKPT;
|
|
}
|
|
if( osGetTempPathW(nMax, zWidePath)==0 ){
|
|
sqlite3_free(zWidePath);
|
|
sqlite3_free(zBuf);
|
|
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_GETTEMPPATH\n"));
|
|
return winLogError(SQLITE_IOERR_GETTEMPPATH, osGetLastError(),
|
|
"winGetTempname2", 0);
|
|
}
|
|
zMulti = winUnicodeToUtf8(zWidePath);
|
|
if( zMulti ){
|
|
sqlite3_snprintf(nMax, zBuf, "%s", zMulti);
|
|
sqlite3_free(zMulti);
|
|
sqlite3_free(zWidePath);
|
|
}else{
|
|
sqlite3_free(zWidePath);
|
|
sqlite3_free(zBuf);
|
|
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
|
|
return SQLITE_IOERR_NOMEM_BKPT;
|
|
}
|
|
}
|
|
#ifdef SQLITE_WIN32_HAS_ANSI
|
|
else{
|
|
char *zUtf8;
|
|
char *zMbcsPath = sqlite3MallocZero( nMax );
|
|
if( !zMbcsPath ){
|
|
sqlite3_free(zBuf);
|
|
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
|
|
return SQLITE_IOERR_NOMEM_BKPT;
|
|
}
|
|
if( osGetTempPathA(nMax, zMbcsPath)==0 ){
|
|
sqlite3_free(zBuf);
|
|
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_GETTEMPPATH\n"));
|
|
return winLogError(SQLITE_IOERR_GETTEMPPATH, osGetLastError(),
|
|
"winGetTempname3", 0);
|
|
}
|
|
zUtf8 = winMbcsToUtf8(zMbcsPath, osAreFileApisANSI());
|
|
if( zUtf8 ){
|
|
sqlite3_snprintf(nMax, zBuf, "%s", zUtf8);
|
|
sqlite3_free(zUtf8);
|
|
}else{
|
|
sqlite3_free(zBuf);
|
|
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
|
|
return SQLITE_IOERR_NOMEM_BKPT;
|
|
}
|
|
}
|
|
#endif /* SQLITE_WIN32_HAS_ANSI */
|
|
#endif /* !SQLITE_OS_WINRT */
|
|
|
|
/*
|
|
** Check to make sure the temporary directory ends with an appropriate
|
|
** separator. If it does not and there is not enough space left to add
|
|
** one, fail.
|
|
*/
|
|
if( !winMakeEndInDirSep(nDir+1, zBuf) ){
|
|
sqlite3_free(zBuf);
|
|
OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n"));
|
|
return winLogError(SQLITE_ERROR, 0, "winGetTempname4", 0);
|
|
}
|
|
|
|
/*
|
|
** Check that the output buffer is large enough for the temporary file
|
|
** name in the following format:
|
|
**
|
|
** "<temporary_directory>/etilqs_XXXXXXXXXXXXXXX\0\0"
|
|
**
|
|
** If not, return SQLITE_ERROR. The number 17 is used here in order to
|
|
** account for the space used by the 15 character random suffix and the
|
|
** two trailing NUL characters. The final directory separator character
|
|
** has already added if it was not already present.
|
|
*/
|
|
nLen = sqlite3Strlen30(zBuf);
|
|
if( (nLen + nPre + 17) > nBuf ){
|
|
sqlite3_free(zBuf);
|
|
OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n"));
|
|
return winLogError(SQLITE_ERROR, 0, "winGetTempname5", 0);
|
|
}
|
|
|
|
sqlite3_snprintf(nBuf-16-nLen, zBuf+nLen, SQLITE_TEMP_FILE_PREFIX);
|
|
|
|
j = sqlite3Strlen30(zBuf);
|
|
sqlite3_randomness(15, &zBuf[j]);
|
|
pid = osGetCurrentProcessId();
|
|
for(i=0; i<15; i++, j++){
|
|
zBuf[j] += pid & 0xff;
|
|
pid >>= 8;
|
|
zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
|
|
}
|
|
zBuf[j] = 0;
|
|
zBuf[j+1] = 0;
|
|
*pzBuf = zBuf;
|
|
|
|
OSTRACE(("TEMP-FILENAME name=%s, rc=SQLITE_OK\n", zBuf));
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Return TRUE if the named file is really a directory. Return false if
|
|
** it is something other than a directory, or if there is any kind of memory
|
|
** allocation failure.
|
|
*/
|
|
static int winIsDir(const void *zConverted){
|
|
DWORD attr;
|
|
int rc = 0;
|
|
DWORD lastErrno;
|
|
|
|
if( osIsNT() ){
|
|
int cnt = 0;
|
|
WIN32_FILE_ATTRIBUTE_DATA sAttrData;
|
|
memset(&sAttrData, 0, sizeof(sAttrData));
|
|
while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
|
|
GetFileExInfoStandard,
|
|
&sAttrData)) && winRetryIoerr(&cnt, &lastErrno) ){}
|
|
if( !rc ){
|
|
return 0; /* Invalid name? */
|
|
}
|
|
attr = sAttrData.dwFileAttributes;
|
|
#if SQLITE_OS_WINCE==0
|
|
}else{
|
|
attr = osGetFileAttributesA((char*)zConverted);
|
|
#endif
|
|
}
|
|
return (attr!=INVALID_FILE_ATTRIBUTES) && (attr&FILE_ATTRIBUTE_DIRECTORY);
|
|
}
|
|
|
|
/* forward reference */
|
|
static int winAccess(
|
|
sqlite3_vfs *pVfs, /* Not used on win32 */
|
|
const char *zFilename, /* Name of file to check */
|
|
int flags, /* Type of test to make on this file */
|
|
int *pResOut /* OUT: Result */
|
|
);
|
|
|
|
/*
|
|
** Open a file.
|
|
*/
|
|
static int winOpen(
|
|
sqlite3_vfs *pVfs, /* Used to get maximum path length and AppData */
|
|
const char *zName, /* Name of the file (UTF-8) */
|
|
sqlite3_file *id, /* Write the SQLite file handle here */
|
|
int flags, /* Open mode flags */
|
|
int *pOutFlags /* Status return flags */
|
|
){
|
|
HANDLE h;
|
|
DWORD lastErrno = 0;
|
|
DWORD dwDesiredAccess;
|
|
DWORD dwShareMode;
|
|
DWORD dwCreationDisposition;
|
|
DWORD dwFlagsAndAttributes = 0;
|
|
#if SQLITE_OS_WINCE
|
|
int isTemp = 0;
|
|
#endif
|
|
winVfsAppData *pAppData;
|
|
winFile *pFile = (winFile*)id;
|
|
void *zConverted; /* Filename in OS encoding */
|
|
const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */
|
|
int cnt = 0;
|
|
|
|
/* If argument zPath is a NULL pointer, this function is required to open
|
|
** a temporary file. Use this buffer to store the file name in.
|
|
*/
|
|
char *zTmpname = 0; /* For temporary filename, if necessary. */
|
|
|
|
int rc = SQLITE_OK; /* Function Return Code */
|
|
#if !defined(NDEBUG) || SQLITE_OS_WINCE
|
|
int eType = flags&0xFFFFFF00; /* Type of file to open */
|
|
#endif
|
|
|
|
int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
|
|
int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
|
|
int isCreate = (flags & SQLITE_OPEN_CREATE);
|
|
int isReadonly = (flags & SQLITE_OPEN_READONLY);
|
|
int isReadWrite = (flags & SQLITE_OPEN_READWRITE);
|
|
|
|
#ifndef NDEBUG
|
|
int isOpenJournal = (isCreate && (
|
|
eType==SQLITE_OPEN_SUPER_JOURNAL
|
|
|| eType==SQLITE_OPEN_MAIN_JOURNAL
|
|
|| eType==SQLITE_OPEN_WAL
|
|
));
|
|
#endif
|
|
|
|
OSTRACE(("OPEN name=%s, pFile=%p, flags=%x, pOutFlags=%p\n",
|
|
zUtf8Name, id, flags, pOutFlags));
|
|
|
|
/* Check the following statements are true:
|
|
**
|
|
** (a) Exactly one of the READWRITE and READONLY flags must be set, and
|
|
** (b) if CREATE is set, then READWRITE must also be set, and
|
|
** (c) if EXCLUSIVE is set, then CREATE must also be set.
|
|
** (d) if DELETEONCLOSE is set, then CREATE must also be set.
|
|
*/
|
|
assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
|
|
assert(isCreate==0 || isReadWrite);
|
|
assert(isExclusive==0 || isCreate);
|
|
assert(isDelete==0 || isCreate);
|
|
|
|
/* The main DB, main journal, WAL file and super-journal are never
|
|
** automatically deleted. Nor are they ever temporary files. */
|
|
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
|
|
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
|
|
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_SUPER_JOURNAL );
|
|
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
|
|
|
|
/* Assert that the upper layer has set one of the "file-type" flags. */
|
|
assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
|
|
|| eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
|
|
|| eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_SUPER_JOURNAL
|
|
|| eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
|
|
);
|
|
|
|
assert( pFile!=0 );
|
|
memset(pFile, 0, sizeof(winFile));
|
|
pFile->h = INVALID_HANDLE_VALUE;
|
|
|
|
#if SQLITE_OS_WINRT
|
|
if( !zUtf8Name && !sqlite3_temp_directory ){
|
|
sqlite3_log(SQLITE_ERROR,
|
|
"sqlite3_temp_directory variable should be set for WinRT");
|
|
}
|
|
#endif
|
|
|
|
/* If the second argument to this function is NULL, generate a
|
|
** temporary file name to use
|
|
*/
|
|
if( !zUtf8Name ){
|
|
assert( isDelete && !isOpenJournal );
|
|
rc = winGetTempname(pVfs, &zTmpname);
|
|
if( rc!=SQLITE_OK ){
|
|
OSTRACE(("OPEN name=%s, rc=%s", zUtf8Name, sqlite3ErrName(rc)));
|
|
return rc;
|
|
}
|
|
zUtf8Name = zTmpname;
|
|
}
|
|
|
|
/* Database filenames are double-zero terminated if they are not
|
|
** URIs with parameters. Hence, they can always be passed into
|
|
** sqlite3_uri_parameter().
|
|
*/
|
|
assert( (eType!=SQLITE_OPEN_MAIN_DB) || (flags & SQLITE_OPEN_URI) ||
|
|
zUtf8Name[sqlite3Strlen30(zUtf8Name)+1]==0 );
|
|
|
|
/* Convert the filename to the system encoding. */
|
|
zConverted = winConvertFromUtf8Filename(zUtf8Name);
|
|
if( zConverted==0 ){
|
|
sqlite3_free(zTmpname);
|
|
OSTRACE(("OPEN name=%s, rc=SQLITE_IOERR_NOMEM", zUtf8Name));
|
|
return SQLITE_IOERR_NOMEM_BKPT;
|
|
}
|
|
|
|
if( winIsDir(zConverted) ){
|
|
sqlite3_free(zConverted);
|
|
sqlite3_free(zTmpname);
|
|
OSTRACE(("OPEN name=%s, rc=SQLITE_CANTOPEN_ISDIR", zUtf8Name));
|
|
return SQLITE_CANTOPEN_ISDIR;
|
|
}
|
|
|
|
if( isReadWrite ){
|
|
dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
|
|
}else{
|
|
dwDesiredAccess = GENERIC_READ;
|
|
}
|
|
|
|
/* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is
|
|
** created. SQLite doesn't use it to indicate "exclusive access"
|
|
** as it is usually understood.
|
|
*/
|
|
if( isExclusive ){
|
|
/* Creates a new file, only if it does not already exist. */
|
|
/* If the file exists, it fails. */
|
|
dwCreationDisposition = CREATE_NEW;
|
|
}else if( isCreate ){
|
|
/* Open existing file, or create if it doesn't exist */
|
|
dwCreationDisposition = OPEN_ALWAYS;
|
|
}else{
|
|
/* Opens a file, only if it exists. */
|
|
dwCreationDisposition = OPEN_EXISTING;
|
|
}
|
|
|
|
if( 0==sqlite3_uri_boolean(zName, "exclusive", 0) ){
|
|
dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
|
|
}else{
|
|
dwShareMode = 0;
|
|
}
|
|
|
|
if( isDelete ){
|
|
#if SQLITE_OS_WINCE
|
|
dwFlagsAndAttributes = FILE_ATTRIBUTE_HIDDEN;
|
|
isTemp = 1;
|
|
#else
|
|
dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY
|
|
| FILE_ATTRIBUTE_HIDDEN
|
|
| FILE_FLAG_DELETE_ON_CLOSE;
|
|
#endif
|
|
}else{
|
|
dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
|
|
}
|
|
/* Reports from the internet are that performance is always
|
|
** better if FILE_FLAG_RANDOM_ACCESS is used. Ticket #2699. */
|
|
#if SQLITE_OS_WINCE
|
|
dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
|
|
#endif
|
|
|
|
if( osIsNT() ){
|
|
#if SQLITE_OS_WINRT
|
|
CREATEFILE2_EXTENDED_PARAMETERS extendedParameters;
|
|
extendedParameters.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
|
|
extendedParameters.dwFileAttributes =
|
|
dwFlagsAndAttributes & FILE_ATTRIBUTE_MASK;
|
|
extendedParameters.dwFileFlags = dwFlagsAndAttributes & FILE_FLAG_MASK;
|
|
extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS;
|
|
extendedParameters.lpSecurityAttributes = NULL;
|
|
extendedParameters.hTemplateFile = NULL;
|
|
do{
|
|
h = osCreateFile2((LPCWSTR)zConverted,
|
|
dwDesiredAccess,
|
|
dwShareMode,
|
|
dwCreationDisposition,
|
|
&extendedParameters);
|
|
if( h!=INVALID_HANDLE_VALUE ) break;
|
|
if( isReadWrite ){
|
|
int rc2, isRO = 0;
|
|
sqlite3BeginBenignMalloc();
|
|
rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ, &isRO);
|
|
sqlite3EndBenignMalloc();
|
|
if( rc2==SQLITE_OK && isRO ) break;
|
|
}
|
|
}while( winRetryIoerr(&cnt, &lastErrno) );
|
|
#else
|
|
do{
|
|
h = osCreateFileW((LPCWSTR)zConverted,
|
|
dwDesiredAccess,
|
|
dwShareMode, NULL,
|
|
dwCreationDisposition,
|
|
dwFlagsAndAttributes,
|
|
NULL);
|
|
if( h!=INVALID_HANDLE_VALUE ) break;
|
|
if( isReadWrite ){
|
|
int rc2, isRO = 0;
|
|
sqlite3BeginBenignMalloc();
|
|
rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ, &isRO);
|
|
sqlite3EndBenignMalloc();
|
|
if( rc2==SQLITE_OK && isRO ) break;
|
|
}
|
|
}while( winRetryIoerr(&cnt, &lastErrno) );
|
|
#endif
|
|
}
|
|
#ifdef SQLITE_WIN32_HAS_ANSI
|
|
else{
|
|
do{
|
|
h = osCreateFileA((LPCSTR)zConverted,
|
|
dwDesiredAccess,
|
|
dwShareMode, NULL,
|
|
dwCreationDisposition,
|
|
dwFlagsAndAttributes,
|
|
NULL);
|
|
if( h!=INVALID_HANDLE_VALUE ) break;
|
|
if( isReadWrite ){
|
|
int rc2, isRO = 0;
|
|
sqlite3BeginBenignMalloc();
|
|
rc2 = winAccess(pVfs, zUtf8Name, SQLITE_ACCESS_READ, &isRO);
|
|
sqlite3EndBenignMalloc();
|
|
if( rc2==SQLITE_OK && isRO ) break;
|
|
}
|
|
}while( winRetryIoerr(&cnt, &lastErrno) );
|
|
}
|
|
#endif
|
|
winLogIoerr(cnt, __LINE__);
|
|
|
|
OSTRACE(("OPEN file=%p, name=%s, access=%lx, rc=%s\n", h, zUtf8Name,
|
|
dwDesiredAccess, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok"));
|
|
|
|
if( h==INVALID_HANDLE_VALUE ){
|
|
sqlite3_free(zConverted);
|
|
sqlite3_free(zTmpname);
|
|
if( isReadWrite && !isExclusive ){
|
|
return winOpen(pVfs, zName, id,
|
|
((flags|SQLITE_OPEN_READONLY) &
|
|
~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)),
|
|
pOutFlags);
|
|
}else{
|
|
pFile->lastErrno = lastErrno;
|
|
winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name);
|
|
return SQLITE_CANTOPEN_BKPT;
|
|
}
|
|
}
|
|
|
|
if( pOutFlags ){
|
|
if( isReadWrite ){
|
|
*pOutFlags = SQLITE_OPEN_READWRITE;
|
|
}else{
|
|
*pOutFlags = SQLITE_OPEN_READONLY;
|
|
}
|
|
}
|
|
|
|
OSTRACE(("OPEN file=%p, name=%s, access=%lx, pOutFlags=%p, *pOutFlags=%d, "
|
|
"rc=%s\n", h, zUtf8Name, dwDesiredAccess, pOutFlags, pOutFlags ?
|
|
*pOutFlags : 0, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok"));
|
|
|
|
pAppData = (winVfsAppData*)pVfs->pAppData;
|
|
|
|
#if SQLITE_OS_WINCE
|
|
{
|
|
if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB
|
|
&& ((pAppData==NULL) || !pAppData->bNoLock)
|
|
&& (rc = winceCreateLock(zName, pFile))!=SQLITE_OK
|
|
){
|
|
osCloseHandle(h);
|
|
sqlite3_free(zConverted);
|
|
sqlite3_free(zTmpname);
|
|
OSTRACE(("OPEN-CE-LOCK name=%s, rc=%s\n", zName, sqlite3ErrName(rc)));
|
|
return rc;
|
|
}
|
|
}
|
|
if( isTemp ){
|
|
pFile->zDeleteOnClose = zConverted;
|
|
}else
|
|
#endif
|
|
{
|
|
sqlite3_free(zConverted);
|
|
}
|
|
|
|
sqlite3_free(zTmpname);
|
|
id->pMethods = pAppData ? pAppData->pMethod : &winIoMethod;
|
|
pFile->pVfs = pVfs;
|
|
pFile->h = h;
|
|
if( isReadonly ){
|
|
pFile->ctrlFlags |= WINFILE_RDONLY;
|
|
}
|
|
if( (flags & SQLITE_OPEN_MAIN_DB)
|
|
&& sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE)
|
|
){
|
|
pFile->ctrlFlags |= WINFILE_PSOW;
|
|
}
|
|
pFile->lastErrno = NO_ERROR;
|
|
pFile->zPath = zName;
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
pFile->hMap = NULL;
|
|
pFile->pMapRegion = 0;
|
|
pFile->mmapSize = 0;
|
|
pFile->mmapSizeMax = sqlite3GlobalConfig.szMmap;
|
|
#endif
|
|
|
|
OpenCounter(+1);
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** 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 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.
|
|
*/
|
|
static int winDelete(
|
|
sqlite3_vfs *pVfs, /* Not used on win32 */
|
|
const char *zFilename, /* Name of file to delete */
|
|
int syncDir /* Not used on win32 */
|
|
){
|
|
int cnt = 0;
|
|
int rc;
|
|
DWORD attr;
|
|
DWORD lastErrno = 0;
|
|
void *zConverted;
|
|
UNUSED_PARAMETER(pVfs);
|
|
UNUSED_PARAMETER(syncDir);
|
|
|
|
SimulateIOError(return SQLITE_IOERR_DELETE);
|
|
OSTRACE(("DELETE name=%s, syncDir=%d\n", zFilename, syncDir));
|
|
|
|
zConverted = winConvertFromUtf8Filename(zFilename);
|
|
if( zConverted==0 ){
|
|
OSTRACE(("DELETE name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename));
|
|
return SQLITE_IOERR_NOMEM_BKPT;
|
|
}
|
|
if( osIsNT() ){
|
|
do {
|
|
#if SQLITE_OS_WINRT
|
|
WIN32_FILE_ATTRIBUTE_DATA sAttrData;
|
|
memset(&sAttrData, 0, sizeof(sAttrData));
|
|
if ( osGetFileAttributesExW(zConverted, GetFileExInfoStandard,
|
|
&sAttrData) ){
|
|
attr = sAttrData.dwFileAttributes;
|
|
}else{
|
|
lastErrno = osGetLastError();
|
|
if( lastErrno==ERROR_FILE_NOT_FOUND
|
|
|| lastErrno==ERROR_PATH_NOT_FOUND ){
|
|
rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
|
|
}else{
|
|
rc = SQLITE_ERROR;
|
|
}
|
|
break;
|
|
}
|
|
#else
|
|
attr = osGetFileAttributesW(zConverted);
|
|
#endif
|
|
if ( attr==INVALID_FILE_ATTRIBUTES ){
|
|
lastErrno = osGetLastError();
|
|
if( lastErrno==ERROR_FILE_NOT_FOUND
|
|
|| lastErrno==ERROR_PATH_NOT_FOUND ){
|
|
rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
|
|
}else{
|
|
rc = SQLITE_ERROR;
|
|
}
|
|
break;
|
|
}
|
|
if ( attr&FILE_ATTRIBUTE_DIRECTORY ){
|
|
rc = SQLITE_ERROR; /* Files only. */
|
|
break;
|
|
}
|
|
if ( osDeleteFileW(zConverted) ){
|
|
rc = SQLITE_OK; /* Deleted OK. */
|
|
break;
|
|
}
|
|
if ( !winRetryIoerr(&cnt, &lastErrno) ){
|
|
rc = SQLITE_ERROR; /* No more retries. */
|
|
break;
|
|
}
|
|
} while(1);
|
|
}
|
|
#ifdef SQLITE_WIN32_HAS_ANSI
|
|
else{
|
|
do {
|
|
attr = osGetFileAttributesA(zConverted);
|
|
if ( attr==INVALID_FILE_ATTRIBUTES ){
|
|
lastErrno = osGetLastError();
|
|
if( lastErrno==ERROR_FILE_NOT_FOUND
|
|
|| lastErrno==ERROR_PATH_NOT_FOUND ){
|
|
rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
|
|
}else{
|
|
rc = SQLITE_ERROR;
|
|
}
|
|
break;
|
|
}
|
|
if ( attr&FILE_ATTRIBUTE_DIRECTORY ){
|
|
rc = SQLITE_ERROR; /* Files only. */
|
|
break;
|
|
}
|
|
if ( osDeleteFileA(zConverted) ){
|
|
rc = SQLITE_OK; /* Deleted OK. */
|
|
break;
|
|
}
|
|
if ( !winRetryIoerr(&cnt, &lastErrno) ){
|
|
rc = SQLITE_ERROR; /* No more retries. */
|
|
break;
|
|
}
|
|
} while(1);
|
|
}
|
|
#endif
|
|
if( rc && rc!=SQLITE_IOERR_DELETE_NOENT ){
|
|
rc = winLogError(SQLITE_IOERR_DELETE, lastErrno, "winDelete", zFilename);
|
|
}else{
|
|
winLogIoerr(cnt, __LINE__);
|
|
}
|
|
sqlite3_free(zConverted);
|
|
OSTRACE(("DELETE name=%s, rc=%s\n", zFilename, sqlite3ErrName(rc)));
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Check the existence and status of a file.
|
|
*/
|
|
static int winAccess(
|
|
sqlite3_vfs *pVfs, /* Not used on win32 */
|
|
const char *zFilename, /* Name of file to check */
|
|
int flags, /* Type of test to make on this file */
|
|
int *pResOut /* OUT: Result */
|
|
){
|
|
DWORD attr;
|
|
int rc = 0;
|
|
DWORD lastErrno = 0;
|
|
void *zConverted;
|
|
UNUSED_PARAMETER(pVfs);
|
|
|
|
SimulateIOError( return SQLITE_IOERR_ACCESS; );
|
|
OSTRACE(("ACCESS name=%s, flags=%x, pResOut=%p\n",
|
|
zFilename, flags, pResOut));
|
|
|
|
if( zFilename==0 ){
|
|
*pResOut = 0;
|
|
OSTRACE(("ACCESS name=%s, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n",
|
|
zFilename, pResOut, *pResOut));
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
zConverted = winConvertFromUtf8Filename(zFilename);
|
|
if( zConverted==0 ){
|
|
OSTRACE(("ACCESS name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename));
|
|
return SQLITE_IOERR_NOMEM_BKPT;
|
|
}
|
|
if( osIsNT() ){
|
|
int cnt = 0;
|
|
WIN32_FILE_ATTRIBUTE_DATA sAttrData;
|
|
memset(&sAttrData, 0, sizeof(sAttrData));
|
|
while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
|
|
GetFileExInfoStandard,
|
|
&sAttrData)) && winRetryIoerr(&cnt, &lastErrno) ){}
|
|
if( rc ){
|
|
/* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
|
|
** as if it does not exist.
|
|
*/
|
|
if( flags==SQLITE_ACCESS_EXISTS
|
|
&& sAttrData.nFileSizeHigh==0
|
|
&& sAttrData.nFileSizeLow==0 ){
|
|
attr = INVALID_FILE_ATTRIBUTES;
|
|
}else{
|
|
attr = sAttrData.dwFileAttributes;
|
|
}
|
|
}else{
|
|
winLogIoerr(cnt, __LINE__);
|
|
if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){
|
|
sqlite3_free(zConverted);
|
|
return winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess",
|
|
zFilename);
|
|
}else{
|
|
attr = INVALID_FILE_ATTRIBUTES;
|
|
}
|
|
}
|
|
}
|
|
#ifdef SQLITE_WIN32_HAS_ANSI
|
|
else{
|
|
attr = osGetFileAttributesA((char*)zConverted);
|
|
}
|
|
#endif
|
|
sqlite3_free(zConverted);
|
|
switch( flags ){
|
|
case SQLITE_ACCESS_READ:
|
|
case SQLITE_ACCESS_EXISTS:
|
|
rc = attr!=INVALID_FILE_ATTRIBUTES;
|
|
break;
|
|
case SQLITE_ACCESS_READWRITE:
|
|
rc = attr!=INVALID_FILE_ATTRIBUTES &&
|
|
(attr & FILE_ATTRIBUTE_READONLY)==0;
|
|
break;
|
|
default:
|
|
assert(!"Invalid flags argument");
|
|
}
|
|
*pResOut = rc;
|
|
OSTRACE(("ACCESS name=%s, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n",
|
|
zFilename, pResOut, *pResOut));
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Returns non-zero if the specified path name starts with the "long path"
|
|
** prefix.
|
|
*/
|
|
static BOOL winIsLongPathPrefix(
|
|
const char *zPathname
|
|
){
|
|
return ( zPathname[0]=='\\' && zPathname[1]=='\\'
|
|
&& zPathname[2]=='?' && zPathname[3]=='\\' );
|
|
}
|
|
|
|
/*
|
|
** Returns non-zero if the specified path name starts with a drive letter
|
|
** followed by a colon character.
|
|
*/
|
|
static BOOL winIsDriveLetterAndColon(
|
|
const char *zPathname
|
|
){
|
|
return ( sqlite3Isalpha(zPathname[0]) && zPathname[1]==':' );
|
|
}
|
|
|
|
/*
|
|
** Returns non-zero if the specified path name should be used verbatim. If
|
|
** non-zero is returned from this function, the calling function must simply
|
|
** use the provided path name verbatim -OR- resolve it into a full path name
|
|
** using the GetFullPathName Win32 API function (if available).
|
|
*/
|
|
static BOOL winIsVerbatimPathname(
|
|
const char *zPathname
|
|
){
|
|
/*
|
|
** If the path name starts with a forward slash or a backslash, it is either
|
|
** a legal UNC name, a volume relative path, or an absolute path name in the
|
|
** "Unix" format on Windows. There is no easy way to differentiate between
|
|
** the final two cases; therefore, we return the safer return value of TRUE
|
|
** so that callers of this function will simply use it verbatim.
|
|
*/
|
|
if ( winIsDirSep(zPathname[0]) ){
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
** If the path name starts with a letter and a colon it is either a volume
|
|
** relative path or an absolute path. Callers of this function must not
|
|
** attempt to treat it as a relative path name (i.e. they should simply use
|
|
** it verbatim).
|
|
*/
|
|
if ( winIsDriveLetterAndColon(zPathname) ){
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
** If we get to this point, the path name should almost certainly be a purely
|
|
** relative one (i.e. not a UNC name, not absolute, and not volume relative).
|
|
*/
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
** Turn a relative pathname into a full pathname. Write the full
|
|
** pathname into zOut[]. zOut[] will be at least pVfs->mxPathname
|
|
** bytes in size.
|
|
*/
|
|
static int winFullPathnameNoMutex(
|
|
sqlite3_vfs *pVfs, /* Pointer to vfs object */
|
|
const char *zRelative, /* Possibly relative input path */
|
|
int nFull, /* Size of output buffer in bytes */
|
|
char *zFull /* Output buffer */
|
|
){
|
|
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__)
|
|
DWORD nByte;
|
|
void *zConverted;
|
|
char *zOut;
|
|
#endif
|
|
|
|
/* If this path name begins with "/X:" or "\\?\", where "X" is any
|
|
** alphabetic character, discard the initial "/" from the pathname.
|
|
*/
|
|
if( zRelative[0]=='/' && (winIsDriveLetterAndColon(zRelative+1)
|
|
|| winIsLongPathPrefix(zRelative+1)) ){
|
|
zRelative++;
|
|
}
|
|
|
|
#if defined(__CYGWIN__)
|
|
SimulateIOError( return SQLITE_ERROR );
|
|
UNUSED_PARAMETER(nFull);
|
|
assert( nFull>=pVfs->mxPathname );
|
|
if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
|
|
/*
|
|
** NOTE: We are dealing with a relative path name and the data
|
|
** directory has been set. Therefore, use it as the basis
|
|
** for converting the relative path name to an absolute
|
|
** one by prepending the data directory and a slash.
|
|
*/
|
|
char *zOut = sqlite3MallocZero( pVfs->mxPathname+1 );
|
|
if( !zOut ){
|
|
return SQLITE_IOERR_NOMEM_BKPT;
|
|
}
|
|
if( cygwin_conv_path(
|
|
(osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A) |
|
|
CCP_RELATIVE, zRelative, zOut, pVfs->mxPathname+1)<0 ){
|
|
sqlite3_free(zOut);
|
|
return winLogError(SQLITE_CANTOPEN_CONVPATH, (DWORD)errno,
|
|
"winFullPathname1", zRelative);
|
|
}else{
|
|
char *zUtf8 = winConvertToUtf8Filename(zOut);
|
|
if( !zUtf8 ){
|
|
sqlite3_free(zOut);
|
|
return SQLITE_IOERR_NOMEM_BKPT;
|
|
}
|
|
sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s",
|
|
sqlite3_data_directory, winGetDirSep(), zUtf8);
|
|
sqlite3_free(zUtf8);
|
|
sqlite3_free(zOut);
|
|
}
|
|
}else{
|
|
char *zOut = sqlite3MallocZero( pVfs->mxPathname+1 );
|
|
if( !zOut ){
|
|
return SQLITE_IOERR_NOMEM_BKPT;
|
|
}
|
|
if( cygwin_conv_path(
|
|
(osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A),
|
|
zRelative, zOut, pVfs->mxPathname+1)<0 ){
|
|
sqlite3_free(zOut);
|
|
return winLogError(SQLITE_CANTOPEN_CONVPATH, (DWORD)errno,
|
|
"winFullPathname2", zRelative);
|
|
}else{
|
|
char *zUtf8 = winConvertToUtf8Filename(zOut);
|
|
if( !zUtf8 ){
|
|
sqlite3_free(zOut);
|
|
return SQLITE_IOERR_NOMEM_BKPT;
|
|
}
|
|
sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zUtf8);
|
|
sqlite3_free(zUtf8);
|
|
sqlite3_free(zOut);
|
|
}
|
|
}
|
|
return SQLITE_OK;
|
|
#endif
|
|
|
|
#if (SQLITE_OS_WINCE || SQLITE_OS_WINRT) && !defined(__CYGWIN__)
|
|
SimulateIOError( return SQLITE_ERROR );
|
|
/* WinCE has no concept of a relative pathname, or so I am told. */
|
|
/* WinRT has no way to convert a relative path to an absolute one. */
|
|
if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
|
|
/*
|
|
** NOTE: We are dealing with a relative path name and the data
|
|
** directory has been set. Therefore, use it as the basis
|
|
** for converting the relative path name to an absolute
|
|
** one by prepending the data directory and a backslash.
|
|
*/
|
|
sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s",
|
|
sqlite3_data_directory, winGetDirSep(), zRelative);
|
|
}else{
|
|
sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zRelative);
|
|
}
|
|
return SQLITE_OK;
|
|
#endif
|
|
|
|
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__)
|
|
/* It's odd to simulate an io-error here, but really this is just
|
|
** using the io-error infrastructure to test that SQLite handles this
|
|
** function failing. This function could fail if, for example, the
|
|
** current working directory has been unlinked.
|
|
*/
|
|
SimulateIOError( return SQLITE_ERROR );
|
|
if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){
|
|
/*
|
|
** NOTE: We are dealing with a relative path name and the data
|
|
** directory has been set. Therefore, use it as the basis
|
|
** for converting the relative path name to an absolute
|
|
** one by prepending the data directory and a backslash.
|
|
*/
|
|
sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s",
|
|
sqlite3_data_directory, winGetDirSep(), zRelative);
|
|
return SQLITE_OK;
|
|
}
|
|
zConverted = winConvertFromUtf8Filename(zRelative);
|
|
if( zConverted==0 ){
|
|
return SQLITE_IOERR_NOMEM_BKPT;
|
|
}
|
|
if( osIsNT() ){
|
|
LPWSTR zTemp;
|
|
nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0);
|
|
if( nByte==0 ){
|
|
sqlite3_free(zConverted);
|
|
return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(),
|
|
"winFullPathname1", zRelative);
|
|
}
|
|
nByte += 3;
|
|
zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) );
|
|
if( zTemp==0 ){
|
|
sqlite3_free(zConverted);
|
|
return SQLITE_IOERR_NOMEM_BKPT;
|
|
}
|
|
nByte = osGetFullPathNameW((LPCWSTR)zConverted, nByte, zTemp, 0);
|
|
if( nByte==0 ){
|
|
sqlite3_free(zConverted);
|
|
sqlite3_free(zTemp);
|
|
return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(),
|
|
"winFullPathname2", zRelative);
|
|
}
|
|
sqlite3_free(zConverted);
|
|
zOut = winUnicodeToUtf8(zTemp);
|
|
sqlite3_free(zTemp);
|
|
}
|
|
#ifdef SQLITE_WIN32_HAS_ANSI
|
|
else{
|
|
char *zTemp;
|
|
nByte = osGetFullPathNameA((char*)zConverted, 0, 0, 0);
|
|
if( nByte==0 ){
|
|
sqlite3_free(zConverted);
|
|
return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(),
|
|
"winFullPathname3", zRelative);
|
|
}
|
|
nByte += 3;
|
|
zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) );
|
|
if( zTemp==0 ){
|
|
sqlite3_free(zConverted);
|
|
return SQLITE_IOERR_NOMEM_BKPT;
|
|
}
|
|
nByte = osGetFullPathNameA((char*)zConverted, nByte, zTemp, 0);
|
|
if( nByte==0 ){
|
|
sqlite3_free(zConverted);
|
|
sqlite3_free(zTemp);
|
|
return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(),
|
|
"winFullPathname4", zRelative);
|
|
}
|
|
sqlite3_free(zConverted);
|
|
zOut = winMbcsToUtf8(zTemp, osAreFileApisANSI());
|
|
sqlite3_free(zTemp);
|
|
}
|
|
#endif
|
|
if( zOut ){
|
|
sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut);
|
|
sqlite3_free(zOut);
|
|
return SQLITE_OK;
|
|
}else{
|
|
return SQLITE_IOERR_NOMEM_BKPT;
|
|
}
|
|
#endif
|
|
}
|
|
static int winFullPathname(
|
|
sqlite3_vfs *pVfs, /* Pointer to vfs object */
|
|
const char *zRelative, /* Possibly relative input path */
|
|
int nFull, /* Size of output buffer in bytes */
|
|
char *zFull /* Output buffer */
|
|
){
|
|
int rc;
|
|
MUTEX_LOGIC( sqlite3_mutex *pMutex; )
|
|
MUTEX_LOGIC( pMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR); )
|
|
sqlite3_mutex_enter(pMutex);
|
|
rc = winFullPathnameNoMutex(pVfs, zRelative, nFull, zFull);
|
|
sqlite3_mutex_leave(pMutex);
|
|
return rc;
|
|
}
|
|
|
|
#ifndef SQLITE_OMIT_LOAD_EXTENSION
|
|
/*
|
|
** Interfaces for opening a shared library, finding entry points
|
|
** within the shared library, and closing the shared library.
|
|
*/
|
|
static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
|
|
HANDLE h;
|
|
#if defined(__CYGWIN__)
|
|
int nFull = pVfs->mxPathname+1;
|
|
char *zFull = sqlite3MallocZero( nFull );
|
|
void *zConverted = 0;
|
|
if( zFull==0 ){
|
|
OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
|
|
return 0;
|
|
}
|
|
if( winFullPathname(pVfs, zFilename, nFull, zFull)!=SQLITE_OK ){
|
|
sqlite3_free(zFull);
|
|
OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
|
|
return 0;
|
|
}
|
|
zConverted = winConvertFromUtf8Filename(zFull);
|
|
sqlite3_free(zFull);
|
|
#else
|
|
void *zConverted = winConvertFromUtf8Filename(zFilename);
|
|
UNUSED_PARAMETER(pVfs);
|
|
#endif
|
|
if( zConverted==0 ){
|
|
OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0));
|
|
return 0;
|
|
}
|
|
if( osIsNT() ){
|
|
#if SQLITE_OS_WINRT
|
|
h = osLoadPackagedLibrary((LPCWSTR)zConverted, 0);
|
|
#else
|
|
h = osLoadLibraryW((LPCWSTR)zConverted);
|
|
#endif
|
|
}
|
|
#ifdef SQLITE_WIN32_HAS_ANSI
|
|
else{
|
|
h = osLoadLibraryA((char*)zConverted);
|
|
}
|
|
#endif
|
|
OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)h));
|
|
sqlite3_free(zConverted);
|
|
return (void*)h;
|
|
}
|
|
static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
|
|
UNUSED_PARAMETER(pVfs);
|
|
winGetLastErrorMsg(osGetLastError(), nBuf, zBufOut);
|
|
}
|
|
static void (*winDlSym(sqlite3_vfs *pVfs,void *pH,const char *zSym))(void){
|
|
FARPROC proc;
|
|
UNUSED_PARAMETER(pVfs);
|
|
proc = osGetProcAddressA((HANDLE)pH, zSym);
|
|
OSTRACE(("DLSYM handle=%p, symbol=%s, address=%p\n",
|
|
(void*)pH, zSym, (void*)proc));
|
|
return (void(*)(void))proc;
|
|
}
|
|
static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){
|
|
UNUSED_PARAMETER(pVfs);
|
|
osFreeLibrary((HANDLE)pHandle);
|
|
OSTRACE(("DLCLOSE handle=%p\n", (void*)pHandle));
|
|
}
|
|
#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
|
|
#define winDlOpen 0
|
|
#define winDlError 0
|
|
#define winDlSym 0
|
|
#define winDlClose 0
|
|
#endif
|
|
|
|
/* State information for the randomness gatherer. */
|
|
typedef struct EntropyGatherer EntropyGatherer;
|
|
struct EntropyGatherer {
|
|
unsigned char *a; /* Gather entropy into this buffer */
|
|
int na; /* Size of a[] in bytes */
|
|
int i; /* XOR next input into a[i] */
|
|
int nXor; /* Number of XOR operations done */
|
|
};
|
|
|
|
#if !defined(SQLITE_TEST) && !defined(SQLITE_OMIT_RANDOMNESS)
|
|
/* Mix sz bytes of entropy into p. */
|
|
static void xorMemory(EntropyGatherer *p, unsigned char *x, int sz){
|
|
int j, k;
|
|
for(j=0, k=p->i; j<sz; j++){
|
|
p->a[k++] ^= x[j];
|
|
if( k>=p->na ) k = 0;
|
|
}
|
|
p->i = k;
|
|
p->nXor += sz;
|
|
}
|
|
#endif /* !defined(SQLITE_TEST) && !defined(SQLITE_OMIT_RANDOMNESS) */
|
|
|
|
/*
|
|
** Write up to nBuf bytes of randomness into zBuf.
|
|
*/
|
|
static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
|
|
#if defined(SQLITE_TEST) || defined(SQLITE_OMIT_RANDOMNESS)
|
|
UNUSED_PARAMETER(pVfs);
|
|
memset(zBuf, 0, nBuf);
|
|
return nBuf;
|
|
#else
|
|
EntropyGatherer e;
|
|
UNUSED_PARAMETER(pVfs);
|
|
memset(zBuf, 0, nBuf);
|
|
e.a = (unsigned char*)zBuf;
|
|
e.na = nBuf;
|
|
e.nXor = 0;
|
|
e.i = 0;
|
|
{
|
|
SYSTEMTIME x;
|
|
osGetSystemTime(&x);
|
|
xorMemory(&e, (unsigned char*)&x, sizeof(SYSTEMTIME));
|
|
}
|
|
{
|
|
DWORD pid = osGetCurrentProcessId();
|
|
xorMemory(&e, (unsigned char*)&pid, sizeof(DWORD));
|
|
}
|
|
#if SQLITE_OS_WINRT
|
|
{
|
|
ULONGLONG cnt = osGetTickCount64();
|
|
xorMemory(&e, (unsigned char*)&cnt, sizeof(ULONGLONG));
|
|
}
|
|
#else
|
|
{
|
|
DWORD cnt = osGetTickCount();
|
|
xorMemory(&e, (unsigned char*)&cnt, sizeof(DWORD));
|
|
}
|
|
#endif /* SQLITE_OS_WINRT */
|
|
{
|
|
LARGE_INTEGER i;
|
|
osQueryPerformanceCounter(&i);
|
|
xorMemory(&e, (unsigned char*)&i, sizeof(LARGE_INTEGER));
|
|
}
|
|
#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID
|
|
{
|
|
UUID id;
|
|
memset(&id, 0, sizeof(UUID));
|
|
osUuidCreate(&id);
|
|
xorMemory(&e, (unsigned char*)&id, sizeof(UUID));
|
|
memset(&id, 0, sizeof(UUID));
|
|
osUuidCreateSequential(&id);
|
|
xorMemory(&e, (unsigned char*)&id, sizeof(UUID));
|
|
}
|
|
#endif /* !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID */
|
|
return e.nXor>nBuf ? nBuf : e.nXor;
|
|
#endif /* defined(SQLITE_TEST) || defined(SQLITE_OMIT_RANDOMNESS) */
|
|
}
|
|
|
|
|
|
/*
|
|
** Sleep for a little while. Return the amount of time slept.
|
|
*/
|
|
static int winSleep(sqlite3_vfs *pVfs, int microsec){
|
|
sqlite3_win32_sleep((microsec+999)/1000);
|
|
UNUSED_PARAMETER(pVfs);
|
|
return ((microsec+999)/1000)*1000;
|
|
}
|
|
|
|
/*
|
|
** The following variable, if set to a non-zero value, is interpreted as
|
|
** the number of seconds since 1970 and is used to set the result of
|
|
** sqlite3OsCurrentTime() during testing.
|
|
*/
|
|
#ifdef SQLITE_TEST
|
|
SQLITE_API int sqlite3_current_time = 0; /* Fake system time in seconds since 1970. */
|
|
#endif
|
|
|
|
/*
|
|
** Find the current time (in Universal Coordinated Time). Write into *piNow
|
|
** the current time and date as a Julian Day number times 86_400_000. In
|
|
** other words, write into *piNow the number of milliseconds since the Julian
|
|
** epoch of noon in Greenwich on November 24, 4714 B.C according to the
|
|
** proleptic Gregorian calendar.
|
|
**
|
|
** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date
|
|
** cannot be found.
|
|
*/
|
|
static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
|
|
/* FILETIME structure is a 64-bit value representing the number of
|
|
100-nanosecond intervals since January 1, 1601 (= JD 2305813.5).
|
|
*/
|
|
FILETIME ft;
|
|
static const sqlite3_int64 winFiletimeEpoch = 23058135*(sqlite3_int64)8640000;
|
|
#ifdef SQLITE_TEST
|
|
static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
|
|
#endif
|
|
/* 2^32 - to avoid use of LL and warnings in gcc */
|
|
static const sqlite3_int64 max32BitValue =
|
|
(sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 +
|
|
(sqlite3_int64)294967296;
|
|
|
|
#if SQLITE_OS_WINCE
|
|
SYSTEMTIME time;
|
|
osGetSystemTime(&time);
|
|
/* if SystemTimeToFileTime() fails, it returns zero. */
|
|
if (!osSystemTimeToFileTime(&time,&ft)){
|
|
return SQLITE_ERROR;
|
|
}
|
|
#else
|
|
osGetSystemTimeAsFileTime( &ft );
|
|
#endif
|
|
|
|
*piNow = winFiletimeEpoch +
|
|
((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) +
|
|
(sqlite3_int64)ft.dwLowDateTime)/(sqlite3_int64)10000;
|
|
|
|
#ifdef SQLITE_TEST
|
|
if( sqlite3_current_time ){
|
|
*piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch;
|
|
}
|
|
#endif
|
|
UNUSED_PARAMETER(pVfs);
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** 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.
|
|
*/
|
|
static int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){
|
|
int rc;
|
|
sqlite3_int64 i;
|
|
rc = winCurrentTimeInt64(pVfs, &i);
|
|
if( !rc ){
|
|
*prNow = i/86400000.0;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** The idea is that this function works like a combination of
|
|
** GetLastError() and FormatMessage() on Windows (or errno and
|
|
** strerror_r() on Unix). After an error is returned by an OS
|
|
** function, SQLite calls this function with zBuf pointing to
|
|
** a buffer of nBuf bytes. The OS layer should populate the
|
|
** buffer with a nul-terminated UTF-8 encoded error message
|
|
** describing the last IO error to have occurred within the calling
|
|
** thread.
|
|
**
|
|
** If the error message is too large for the supplied buffer,
|
|
** it should be truncated. The return value of xGetLastError
|
|
** is zero if the error message fits in the buffer, or non-zero
|
|
** otherwise (if the message was truncated). If non-zero is returned,
|
|
** then it is not necessary to include the nul-terminator character
|
|
** in the output buffer.
|
|
**
|
|
** Not supplying an error message will have no adverse effect
|
|
** on SQLite. It is fine to have an implementation that never
|
|
** returns an error message:
|
|
**
|
|
** int xGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
|
|
** assert(zBuf[0]=='\0');
|
|
** return 0;
|
|
** }
|
|
**
|
|
** However if an error message is supplied, it will be incorporated
|
|
** by sqlite into the error message available to the user using
|
|
** sqlite3_errmsg(), possibly making IO errors easier to debug.
|
|
*/
|
|
static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
|
|
DWORD e = osGetLastError();
|
|
UNUSED_PARAMETER(pVfs);
|
|
if( nBuf>0 ) winGetLastErrorMsg(e, nBuf, zBuf);
|
|
return e;
|
|
}
|
|
|
|
/*
|
|
** Initialize and deinitialize the operating system interface.
|
|
*/
|
|
SQLITE_API int sqlite3_os_init(void){
|
|
static sqlite3_vfs winVfs = {
|
|
3, /* iVersion */
|
|
sizeof(winFile), /* szOsFile */
|
|
SQLITE_WIN32_MAX_PATH_BYTES, /* mxPathname */
|
|
0, /* pNext */
|
|
"win32", /* zName */
|
|
&winAppData, /* pAppData */
|
|
winOpen, /* xOpen */
|
|
winDelete, /* xDelete */
|
|
winAccess, /* xAccess */
|
|
winFullPathname, /* xFullPathname */
|
|
winDlOpen, /* xDlOpen */
|
|
winDlError, /* xDlError */
|
|
winDlSym, /* xDlSym */
|
|
winDlClose, /* xDlClose */
|
|
winRandomness, /* xRandomness */
|
|
winSleep, /* xSleep */
|
|
winCurrentTime, /* xCurrentTime */
|
|
winGetLastError, /* xGetLastError */
|
|
winCurrentTimeInt64, /* xCurrentTimeInt64 */
|
|
winSetSystemCall, /* xSetSystemCall */
|
|
winGetSystemCall, /* xGetSystemCall */
|
|
winNextSystemCall, /* xNextSystemCall */
|
|
};
|
|
#if defined(SQLITE_WIN32_HAS_WIDE)
|
|
static sqlite3_vfs winLongPathVfs = {
|
|
3, /* iVersion */
|
|
sizeof(winFile), /* szOsFile */
|
|
SQLITE_WINNT_MAX_PATH_BYTES, /* mxPathname */
|
|
0, /* pNext */
|
|
"win32-longpath", /* zName */
|
|
&winAppData, /* pAppData */
|
|
winOpen, /* xOpen */
|
|
winDelete, /* xDelete */
|
|
winAccess, /* xAccess */
|
|
winFullPathname, /* xFullPathname */
|
|
winDlOpen, /* xDlOpen */
|
|
winDlError, /* xDlError */
|
|
winDlSym, /* xDlSym */
|
|
winDlClose, /* xDlClose */
|
|
winRandomness, /* xRandomness */
|
|
winSleep, /* xSleep */
|
|
winCurrentTime, /* xCurrentTime */
|
|
winGetLastError, /* xGetLastError */
|
|
winCurrentTimeInt64, /* xCurrentTimeInt64 */
|
|
winSetSystemCall, /* xSetSystemCall */
|
|
winGetSystemCall, /* xGetSystemCall */
|
|
winNextSystemCall, /* xNextSystemCall */
|
|
};
|
|
#endif
|
|
static sqlite3_vfs winNolockVfs = {
|
|
3, /* iVersion */
|
|
sizeof(winFile), /* szOsFile */
|
|
SQLITE_WIN32_MAX_PATH_BYTES, /* mxPathname */
|
|
0, /* pNext */
|
|
"win32-none", /* zName */
|
|
&winNolockAppData, /* pAppData */
|
|
winOpen, /* xOpen */
|
|
winDelete, /* xDelete */
|
|
winAccess, /* xAccess */
|
|
winFullPathname, /* xFullPathname */
|
|
winDlOpen, /* xDlOpen */
|
|
winDlError, /* xDlError */
|
|
winDlSym, /* xDlSym */
|
|
winDlClose, /* xDlClose */
|
|
winRandomness, /* xRandomness */
|
|
winSleep, /* xSleep */
|
|
winCurrentTime, /* xCurrentTime */
|
|
winGetLastError, /* xGetLastError */
|
|
winCurrentTimeInt64, /* xCurrentTimeInt64 */
|
|
winSetSystemCall, /* xSetSystemCall */
|
|
winGetSystemCall, /* xGetSystemCall */
|
|
winNextSystemCall, /* xNextSystemCall */
|
|
};
|
|
#if defined(SQLITE_WIN32_HAS_WIDE)
|
|
static sqlite3_vfs winLongPathNolockVfs = {
|
|
3, /* iVersion */
|
|
sizeof(winFile), /* szOsFile */
|
|
SQLITE_WINNT_MAX_PATH_BYTES, /* mxPathname */
|
|
0, /* pNext */
|
|
"win32-longpath-none", /* zName */
|
|
&winNolockAppData, /* pAppData */
|
|
winOpen, /* xOpen */
|
|
winDelete, /* xDelete */
|
|
winAccess, /* xAccess */
|
|
winFullPathname, /* xFullPathname */
|
|
winDlOpen, /* xDlOpen */
|
|
winDlError, /* xDlError */
|
|
winDlSym, /* xDlSym */
|
|
winDlClose, /* xDlClose */
|
|
winRandomness, /* xRandomness */
|
|
winSleep, /* xSleep */
|
|
winCurrentTime, /* xCurrentTime */
|
|
winGetLastError, /* xGetLastError */
|
|
winCurrentTimeInt64, /* xCurrentTimeInt64 */
|
|
winSetSystemCall, /* xSetSystemCall */
|
|
winGetSystemCall, /* xGetSystemCall */
|
|
winNextSystemCall, /* xNextSystemCall */
|
|
};
|
|
#endif
|
|
|
|
/* Double-check that the aSyscall[] array has been constructed
|
|
** correctly. See ticket [bb3a86e890c8e96ab] */
|
|
assert( ArraySize(aSyscall)==80 );
|
|
|
|
/* get memory map allocation granularity */
|
|
memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
|
|
#if SQLITE_OS_WINRT
|
|
osGetNativeSystemInfo(&winSysInfo);
|
|
#else
|
|
osGetSystemInfo(&winSysInfo);
|
|
#endif
|
|
assert( winSysInfo.dwAllocationGranularity>0 );
|
|
assert( winSysInfo.dwPageSize>0 );
|
|
|
|
sqlite3_vfs_register(&winVfs, 1);
|
|
|
|
#if defined(SQLITE_WIN32_HAS_WIDE)
|
|
sqlite3_vfs_register(&winLongPathVfs, 0);
|
|
#endif
|
|
|
|
sqlite3_vfs_register(&winNolockVfs, 0);
|
|
|
|
#if defined(SQLITE_WIN32_HAS_WIDE)
|
|
sqlite3_vfs_register(&winLongPathNolockVfs, 0);
|
|
#endif
|
|
|
|
#ifndef SQLITE_OMIT_WAL
|
|
winBigLock = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
|
|
#endif
|
|
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
SQLITE_API int sqlite3_os_end(void){
|
|
#if SQLITE_OS_WINRT
|
|
if( sleepObj!=NULL ){
|
|
osCloseHandle(sleepObj);
|
|
sleepObj = NULL;
|
|
}
|
|
#endif
|
|
|
|
#ifndef SQLITE_OMIT_WAL
|
|
winBigLock = 0;
|
|
#endif
|
|
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
#endif /* SQLITE_OS_WIN */
|
|
|
|
/************** End of os_win.c **********************************************/
|
|
/************** Begin file memdb.c *******************************************/
|
|
/*
|
|
** 2016-09-07
|
|
**
|
|
** The author disclaims copyright to this source code. In place of
|
|
** a legal notice, here is a blessing:
|
|
**
|
|
** May you do good and not evil.
|
|
** May you find forgiveness for yourself and forgive others.
|
|
** May you share freely, never taking more than you give.
|
|
**
|
|
******************************************************************************
|
|
**
|
|
** This file implements an in-memory VFS. A database is held as a contiguous
|
|
** block of memory.
|
|
**
|
|
** This file also implements interface sqlite3_serialize() and
|
|
** sqlite3_deserialize().
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
#ifndef SQLITE_OMIT_DESERIALIZE
|
|
|
|
/*
|
|
** Forward declaration of objects used by this utility
|
|
*/
|
|
typedef struct sqlite3_vfs MemVfs;
|
|
typedef struct MemFile MemFile;
|
|
typedef struct MemStore MemStore;
|
|
|
|
/* Access to a lower-level VFS that (might) implement dynamic loading,
|
|
** access to randomness, etc.
|
|
*/
|
|
#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))
|
|
|
|
/* Storage for a memdb file.
|
|
**
|
|
** An memdb object can be shared or separate. Shared memdb objects can be
|
|
** used by more than one database connection. Mutexes are used by shared
|
|
** memdb objects to coordinate access. Separate memdb objects are only
|
|
** connected to a single database connection and do not require additional
|
|
** mutexes.
|
|
**
|
|
** Shared memdb objects have .zFName!=0 and .pMutex!=0. They are created
|
|
** using "file:/name?vfs=memdb". The first character of the name must be
|
|
** "/" or else the object will be a separate memdb object. All shared
|
|
** memdb objects are stored in memdb_g.apMemStore[] in an arbitrary order.
|
|
**
|
|
** Separate memdb objects are created using a name that does not begin
|
|
** with "/" or using sqlite3_deserialize().
|
|
**
|
|
** Access rules for shared MemStore objects:
|
|
**
|
|
** * .zFName is initialized when the object is created and afterwards
|
|
** is unchanged until the object is destroyed. So it can be accessed
|
|
** at any time as long as we know the object is not being destroyed,
|
|
** which means while either the SQLITE_MUTEX_STATIC_VFS1 or
|
|
** .pMutex is held or the object is not part of memdb_g.apMemStore[].
|
|
**
|
|
** * Can .pMutex can only be changed while holding the
|
|
** SQLITE_MUTEX_STATIC_VFS1 mutex or while the object is not part
|
|
** of memdb_g.apMemStore[].
|
|
**
|
|
** * Other fields can only be changed while holding the .pMutex mutex
|
|
** or when the .nRef is less than zero and the object is not part of
|
|
** memdb_g.apMemStore[].
|
|
**
|
|
** * The .aData pointer has the added requirement that it can can only
|
|
** be changed (for resizing) when nMmap is zero.
|
|
**
|
|
*/
|
|
struct MemStore {
|
|
sqlite3_int64 sz; /* Size of the file */
|
|
sqlite3_int64 szAlloc; /* Space allocated to aData */
|
|
sqlite3_int64 szMax; /* Maximum allowed size of the file */
|
|
unsigned char *aData; /* content of the file */
|
|
sqlite3_mutex *pMutex; /* Used by shared stores only */
|
|
int nMmap; /* Number of memory mapped pages */
|
|
unsigned mFlags; /* Flags */
|
|
int nRdLock; /* Number of readers */
|
|
int nWrLock; /* Number of writers. (Always 0 or 1) */
|
|
int nRef; /* Number of users of this MemStore */
|
|
char *zFName; /* The filename for shared stores */
|
|
};
|
|
|
|
/* An open file */
|
|
struct MemFile {
|
|
sqlite3_file base; /* IO methods */
|
|
MemStore *pStore; /* The storage */
|
|
int eLock; /* Most recent lock against this file */
|
|
};
|
|
|
|
/*
|
|
** File-scope variables for holding the memdb files that are accessible
|
|
** to multiple database connections in separate threads.
|
|
**
|
|
** Must hold SQLITE_MUTEX_STATIC_VFS1 to access any part of this object.
|
|
*/
|
|
static struct MemFS {
|
|
int nMemStore; /* Number of shared MemStore objects */
|
|
MemStore **apMemStore; /* Array of all shared MemStore objects */
|
|
} memdb_g;
|
|
|
|
/*
|
|
** Methods for MemFile
|
|
*/
|
|
static int memdbClose(sqlite3_file*);
|
|
static int memdbRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
|
|
static int memdbWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
|
|
static int memdbTruncate(sqlite3_file*, sqlite3_int64 size);
|
|
static int memdbSync(sqlite3_file*, int flags);
|
|
static int memdbFileSize(sqlite3_file*, sqlite3_int64 *pSize);
|
|
static int memdbLock(sqlite3_file*, int);
|
|
static int memdbUnlock(sqlite3_file*, int);
|
|
/* static int memdbCheckReservedLock(sqlite3_file*, int *pResOut);// not used */
|
|
static int memdbFileControl(sqlite3_file*, int op, void *pArg);
|
|
/* static int memdbSectorSize(sqlite3_file*); // not used */
|
|
static int memdbDeviceCharacteristics(sqlite3_file*);
|
|
static int memdbFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
|
|
static int memdbUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p);
|
|
|
|
/*
|
|
** Methods for MemVfs
|
|
*/
|
|
static int memdbOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
|
|
/* static int memdbDelete(sqlite3_vfs*, const char *zName, int syncDir); */
|
|
static int memdbAccess(sqlite3_vfs*, const char *zName, int flags, int *);
|
|
static int memdbFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
|
|
static void *memdbDlOpen(sqlite3_vfs*, const char *zFilename);
|
|
static void memdbDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
|
|
static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
|
|
static void memdbDlClose(sqlite3_vfs*, void*);
|
|
static int memdbRandomness(sqlite3_vfs*, int nByte, char *zOut);
|
|
static int memdbSleep(sqlite3_vfs*, int microseconds);
|
|
/* static int memdbCurrentTime(sqlite3_vfs*, double*); */
|
|
static int memdbGetLastError(sqlite3_vfs*, int, char *);
|
|
static int memdbCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
|
|
|
|
static sqlite3_vfs memdb_vfs = {
|
|
2, /* iVersion */
|
|
0, /* szOsFile (set when registered) */
|
|
1024, /* mxPathname */
|
|
0, /* pNext */
|
|
"memdb", /* zName */
|
|
0, /* pAppData (set when registered) */
|
|
memdbOpen, /* xOpen */
|
|
0, /* memdbDelete, */ /* xDelete */
|
|
memdbAccess, /* xAccess */
|
|
memdbFullPathname, /* xFullPathname */
|
|
memdbDlOpen, /* xDlOpen */
|
|
memdbDlError, /* xDlError */
|
|
memdbDlSym, /* xDlSym */
|
|
memdbDlClose, /* xDlClose */
|
|
memdbRandomness, /* xRandomness */
|
|
memdbSleep, /* xSleep */
|
|
0, /* memdbCurrentTime, */ /* xCurrentTime */
|
|
memdbGetLastError, /* xGetLastError */
|
|
memdbCurrentTimeInt64, /* xCurrentTimeInt64 */
|
|
0, /* xSetSystemCall */
|
|
0, /* xGetSystemCall */
|
|
0, /* xNextSystemCall */
|
|
};
|
|
|
|
static const sqlite3_io_methods memdb_io_methods = {
|
|
3, /* iVersion */
|
|
memdbClose, /* xClose */
|
|
memdbRead, /* xRead */
|
|
memdbWrite, /* xWrite */
|
|
memdbTruncate, /* xTruncate */
|
|
memdbSync, /* xSync */
|
|
memdbFileSize, /* xFileSize */
|
|
memdbLock, /* xLock */
|
|
memdbUnlock, /* xUnlock */
|
|
0, /* memdbCheckReservedLock, */ /* xCheckReservedLock */
|
|
memdbFileControl, /* xFileControl */
|
|
0, /* memdbSectorSize,*/ /* xSectorSize */
|
|
memdbDeviceCharacteristics, /* xDeviceCharacteristics */
|
|
0, /* xShmMap */
|
|
0, /* xShmLock */
|
|
0, /* xShmBarrier */
|
|
0, /* xShmUnmap */
|
|
memdbFetch, /* xFetch */
|
|
memdbUnfetch /* xUnfetch */
|
|
};
|
|
|
|
/*
|
|
** Enter/leave the mutex on a MemStore
|
|
*/
|
|
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE==0
|
|
static void memdbEnter(MemStore *p){
|
|
UNUSED_PARAMETER(p);
|
|
}
|
|
static void memdbLeave(MemStore *p){
|
|
UNUSED_PARAMETER(p);
|
|
}
|
|
#else
|
|
static void memdbEnter(MemStore *p){
|
|
sqlite3_mutex_enter(p->pMutex);
|
|
}
|
|
static void memdbLeave(MemStore *p){
|
|
sqlite3_mutex_leave(p->pMutex);
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
** Close an memdb-file.
|
|
** Free the underlying MemStore object when its refcount drops to zero
|
|
** or less.
|
|
*/
|
|
static int memdbClose(sqlite3_file *pFile){
|
|
MemStore *p = ((MemFile*)pFile)->pStore;
|
|
if( p->zFName ){
|
|
int i;
|
|
#ifndef SQLITE_MUTEX_OMIT
|
|
sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
|
|
#endif
|
|
sqlite3_mutex_enter(pVfsMutex);
|
|
for(i=0; ALWAYS(i<memdb_g.nMemStore); i++){
|
|
if( memdb_g.apMemStore[i]==p ){
|
|
memdbEnter(p);
|
|
if( p->nRef==1 ){
|
|
memdb_g.apMemStore[i] = memdb_g.apMemStore[--memdb_g.nMemStore];
|
|
if( memdb_g.nMemStore==0 ){
|
|
sqlite3_free(memdb_g.apMemStore);
|
|
memdb_g.apMemStore = 0;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
sqlite3_mutex_leave(pVfsMutex);
|
|
}else{
|
|
memdbEnter(p);
|
|
}
|
|
p->nRef--;
|
|
if( p->nRef<=0 ){
|
|
if( p->mFlags & SQLITE_DESERIALIZE_FREEONCLOSE ){
|
|
sqlite3_free(p->aData);
|
|
}
|
|
memdbLeave(p);
|
|
sqlite3_mutex_free(p->pMutex);
|
|
sqlite3_free(p);
|
|
}else{
|
|
memdbLeave(p);
|
|
}
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Read data from an memdb-file.
|
|
*/
|
|
static int memdbRead(
|
|
sqlite3_file *pFile,
|
|
void *zBuf,
|
|
int iAmt,
|
|
sqlite_int64 iOfst
|
|
){
|
|
MemStore *p = ((MemFile*)pFile)->pStore;
|
|
memdbEnter(p);
|
|
if( iOfst+iAmt>p->sz ){
|
|
memset(zBuf, 0, iAmt);
|
|
if( iOfst<p->sz ) memcpy(zBuf, p->aData+iOfst, p->sz - iOfst);
|
|
memdbLeave(p);
|
|
return SQLITE_IOERR_SHORT_READ;
|
|
}
|
|
memcpy(zBuf, p->aData+iOfst, iAmt);
|
|
memdbLeave(p);
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Try to enlarge the memory allocation to hold at least sz bytes
|
|
*/
|
|
static int memdbEnlarge(MemStore *p, sqlite3_int64 newSz){
|
|
unsigned char *pNew;
|
|
if( (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)==0 || NEVER(p->nMmap>0) ){
|
|
return SQLITE_FULL;
|
|
}
|
|
if( newSz>p->szMax ){
|
|
return SQLITE_FULL;
|
|
}
|
|
newSz *= 2;
|
|
if( newSz>p->szMax ) newSz = p->szMax;
|
|
pNew = sqlite3Realloc(p->aData, newSz);
|
|
if( pNew==0 ) return SQLITE_IOERR_NOMEM;
|
|
p->aData = pNew;
|
|
p->szAlloc = newSz;
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Write data to an memdb-file.
|
|
*/
|
|
static int memdbWrite(
|
|
sqlite3_file *pFile,
|
|
const void *z,
|
|
int iAmt,
|
|
sqlite_int64 iOfst
|
|
){
|
|
MemStore *p = ((MemFile*)pFile)->pStore;
|
|
memdbEnter(p);
|
|
if( NEVER(p->mFlags & SQLITE_DESERIALIZE_READONLY) ){
|
|
/* Can't happen: memdbLock() will return SQLITE_READONLY before
|
|
** reaching this point */
|
|
memdbLeave(p);
|
|
return SQLITE_IOERR_WRITE;
|
|
}
|
|
if( iOfst+iAmt>p->sz ){
|
|
int rc;
|
|
if( iOfst+iAmt>p->szAlloc
|
|
&& (rc = memdbEnlarge(p, iOfst+iAmt))!=SQLITE_OK
|
|
){
|
|
memdbLeave(p);
|
|
return rc;
|
|
}
|
|
if( iOfst>p->sz ) memset(p->aData+p->sz, 0, iOfst-p->sz);
|
|
p->sz = iOfst+iAmt;
|
|
}
|
|
memcpy(p->aData+iOfst, z, iAmt);
|
|
memdbLeave(p);
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Truncate an memdb-file.
|
|
**
|
|
** In rollback mode (which is always the case for memdb, as it does not
|
|
** support WAL mode) the truncate() method is only used to reduce
|
|
** the size of a file, never to increase the size.
|
|
*/
|
|
static int memdbTruncate(sqlite3_file *pFile, sqlite_int64 size){
|
|
MemStore *p = ((MemFile*)pFile)->pStore;
|
|
int rc = SQLITE_OK;
|
|
memdbEnter(p);
|
|
if( size>p->sz ){
|
|
/* This can only happen with a corrupt wal mode db */
|
|
rc = SQLITE_CORRUPT;
|
|
}else{
|
|
p->sz = size;
|
|
}
|
|
memdbLeave(p);
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Sync an memdb-file.
|
|
*/
|
|
static int memdbSync(sqlite3_file *pFile, int flags){
|
|
UNUSED_PARAMETER(pFile);
|
|
UNUSED_PARAMETER(flags);
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Return the current file-size of an memdb-file.
|
|
*/
|
|
static int memdbFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
|
|
MemStore *p = ((MemFile*)pFile)->pStore;
|
|
memdbEnter(p);
|
|
*pSize = p->sz;
|
|
memdbLeave(p);
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Lock an memdb-file.
|
|
*/
|
|
static int memdbLock(sqlite3_file *pFile, int eLock){
|
|
MemFile *pThis = (MemFile*)pFile;
|
|
MemStore *p = pThis->pStore;
|
|
int rc = SQLITE_OK;
|
|
if( eLock<=pThis->eLock ) return SQLITE_OK;
|
|
memdbEnter(p);
|
|
|
|
assert( p->nWrLock==0 || p->nWrLock==1 );
|
|
assert( pThis->eLock<=SQLITE_LOCK_SHARED || p->nWrLock==1 );
|
|
assert( pThis->eLock==SQLITE_LOCK_NONE || p->nRdLock>=1 );
|
|
|
|
if( eLock>SQLITE_LOCK_SHARED && (p->mFlags & SQLITE_DESERIALIZE_READONLY) ){
|
|
rc = SQLITE_READONLY;
|
|
}else{
|
|
switch( eLock ){
|
|
case SQLITE_LOCK_SHARED: {
|
|
assert( pThis->eLock==SQLITE_LOCK_NONE );
|
|
if( p->nWrLock>0 ){
|
|
rc = SQLITE_BUSY;
|
|
}else{
|
|
p->nRdLock++;
|
|
}
|
|
break;
|
|
};
|
|
|
|
case SQLITE_LOCK_RESERVED:
|
|
case SQLITE_LOCK_PENDING: {
|
|
assert( pThis->eLock>=SQLITE_LOCK_SHARED );
|
|
if( ALWAYS(pThis->eLock==SQLITE_LOCK_SHARED) ){
|
|
if( p->nWrLock>0 ){
|
|
rc = SQLITE_BUSY;
|
|
}else{
|
|
p->nWrLock = 1;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
default: {
|
|
assert( eLock==SQLITE_LOCK_EXCLUSIVE );
|
|
assert( pThis->eLock>=SQLITE_LOCK_SHARED );
|
|
if( p->nRdLock>1 ){
|
|
rc = SQLITE_BUSY;
|
|
}else if( pThis->eLock==SQLITE_LOCK_SHARED ){
|
|
p->nWrLock = 1;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if( rc==SQLITE_OK ) pThis->eLock = eLock;
|
|
memdbLeave(p);
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Unlock an memdb-file.
|
|
*/
|
|
static int memdbUnlock(sqlite3_file *pFile, int eLock){
|
|
MemFile *pThis = (MemFile*)pFile;
|
|
MemStore *p = pThis->pStore;
|
|
if( eLock>=pThis->eLock ) return SQLITE_OK;
|
|
memdbEnter(p);
|
|
|
|
assert( eLock==SQLITE_LOCK_SHARED || eLock==SQLITE_LOCK_NONE );
|
|
if( eLock==SQLITE_LOCK_SHARED ){
|
|
if( ALWAYS(pThis->eLock>SQLITE_LOCK_SHARED) ){
|
|
p->nWrLock--;
|
|
}
|
|
}else{
|
|
if( pThis->eLock>SQLITE_LOCK_SHARED ){
|
|
p->nWrLock--;
|
|
}
|
|
p->nRdLock--;
|
|
}
|
|
|
|
pThis->eLock = eLock;
|
|
memdbLeave(p);
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
#if 0
|
|
/*
|
|
** This interface is only used for crash recovery, which does not
|
|
** occur on an in-memory database.
|
|
*/
|
|
static int memdbCheckReservedLock(sqlite3_file *pFile, int *pResOut){
|
|
*pResOut = 0;
|
|
return SQLITE_OK;
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
** File control method. For custom operations on an memdb-file.
|
|
*/
|
|
static int memdbFileControl(sqlite3_file *pFile, int op, void *pArg){
|
|
MemStore *p = ((MemFile*)pFile)->pStore;
|
|
int rc = SQLITE_NOTFOUND;
|
|
memdbEnter(p);
|
|
if( op==SQLITE_FCNTL_VFSNAME ){
|
|
*(char**)pArg = sqlite3_mprintf("memdb(%p,%lld)", p->aData, p->sz);
|
|
rc = SQLITE_OK;
|
|
}
|
|
if( op==SQLITE_FCNTL_SIZE_LIMIT ){
|
|
sqlite3_int64 iLimit = *(sqlite3_int64*)pArg;
|
|
if( iLimit<p->sz ){
|
|
if( iLimit<0 ){
|
|
iLimit = p->szMax;
|
|
}else{
|
|
iLimit = p->sz;
|
|
}
|
|
}
|
|
p->szMax = iLimit;
|
|
*(sqlite3_int64*)pArg = iLimit;
|
|
rc = SQLITE_OK;
|
|
}
|
|
memdbLeave(p);
|
|
return rc;
|
|
}
|
|
|
|
#if 0 /* Not used because of SQLITE_IOCAP_POWERSAFE_OVERWRITE */
|
|
/*
|
|
** Return the sector-size in bytes for an memdb-file.
|
|
*/
|
|
static int memdbSectorSize(sqlite3_file *pFile){
|
|
return 1024;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
** Return the device characteristic flags supported by an memdb-file.
|
|
*/
|
|
static int memdbDeviceCharacteristics(sqlite3_file *pFile){
|
|
UNUSED_PARAMETER(pFile);
|
|
return SQLITE_IOCAP_ATOMIC |
|
|
SQLITE_IOCAP_POWERSAFE_OVERWRITE |
|
|
SQLITE_IOCAP_SAFE_APPEND |
|
|
SQLITE_IOCAP_SEQUENTIAL;
|
|
}
|
|
|
|
/* Fetch a page of a memory-mapped file */
|
|
static int memdbFetch(
|
|
sqlite3_file *pFile,
|
|
sqlite3_int64 iOfst,
|
|
int iAmt,
|
|
void **pp
|
|
){
|
|
MemStore *p = ((MemFile*)pFile)->pStore;
|
|
memdbEnter(p);
|
|
if( iOfst+iAmt>p->sz || (p->mFlags & SQLITE_DESERIALIZE_RESIZEABLE)!=0 ){
|
|
*pp = 0;
|
|
}else{
|
|
p->nMmap++;
|
|
*pp = (void*)(p->aData + iOfst);
|
|
}
|
|
memdbLeave(p);
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/* Release a memory-mapped page */
|
|
static int memdbUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
|
|
MemStore *p = ((MemFile*)pFile)->pStore;
|
|
UNUSED_PARAMETER(iOfst);
|
|
UNUSED_PARAMETER(pPage);
|
|
memdbEnter(p);
|
|
p->nMmap--;
|
|
memdbLeave(p);
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Open an mem file handle.
|
|
*/
|
|
static int memdbOpen(
|
|
sqlite3_vfs *pVfs,
|
|
const char *zName,
|
|
sqlite3_file *pFd,
|
|
int flags,
|
|
int *pOutFlags
|
|
){
|
|
MemFile *pFile = (MemFile*)pFd;
|
|
MemStore *p = 0;
|
|
int szName;
|
|
UNUSED_PARAMETER(pVfs);
|
|
|
|
memset(pFile, 0, sizeof(*pFile));
|
|
szName = sqlite3Strlen30(zName);
|
|
if( szName>1 && (zName[0]=='/' || zName[0]=='\\') ){
|
|
int i;
|
|
#ifndef SQLITE_MUTEX_OMIT
|
|
sqlite3_mutex *pVfsMutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1);
|
|
#endif
|
|
sqlite3_mutex_enter(pVfsMutex);
|
|
for(i=0; i<memdb_g.nMemStore; i++){
|
|
if( strcmp(memdb_g.apMemStore[i]->zFName,zName)==0 ){
|
|
p = memdb_g.apMemStore[i];
|
|
break;
|
|
}
|
|
}
|
|
if( p==0 ){
|
|
MemStore **apNew;
|
|
p = sqlite3Malloc( sizeof(*p) + szName + 3 );
|
|
if( p==0 ){
|
|
sqlite3_mutex_leave(pVfsMutex);
|
|
return SQLITE_NOMEM;
|
|
}
|
|
apNew = sqlite3Realloc(memdb_g.apMemStore,
|
|
sizeof(apNew[0])*(memdb_g.nMemStore+1) );
|
|
if( apNew==0 ){
|
|
sqlite3_free(p);
|
|
sqlite3_mutex_leave(pVfsMutex);
|
|
return SQLITE_NOMEM;
|
|
}
|
|
apNew[memdb_g.nMemStore++] = p;
|
|
memdb_g.apMemStore = apNew;
|
|
memset(p, 0, sizeof(*p));
|
|
p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE|SQLITE_DESERIALIZE_FREEONCLOSE;
|
|
p->szMax = sqlite3GlobalConfig.mxMemdbSize;
|
|
p->zFName = (char*)&p[1];
|
|
memcpy(p->zFName, zName, szName+1);
|
|
p->pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
|
|
if( p->pMutex==0 ){
|
|
memdb_g.nMemStore--;
|
|
sqlite3_free(p);
|
|
sqlite3_mutex_leave(pVfsMutex);
|
|
return SQLITE_NOMEM;
|
|
}
|
|
p->nRef = 1;
|
|
memdbEnter(p);
|
|
}else{
|
|
memdbEnter(p);
|
|
p->nRef++;
|
|
}
|
|
sqlite3_mutex_leave(pVfsMutex);
|
|
}else{
|
|
p = sqlite3Malloc( sizeof(*p) );
|
|
if( p==0 ){
|
|
return SQLITE_NOMEM;
|
|
}
|
|
memset(p, 0, sizeof(*p));
|
|
p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
|
|
p->szMax = sqlite3GlobalConfig.mxMemdbSize;
|
|
}
|
|
pFile->pStore = p;
|
|
if( pOutFlags!=0 ){
|
|
*pOutFlags = flags | SQLITE_OPEN_MEMORY;
|
|
}
|
|
pFd->pMethods = &memdb_io_methods;
|
|
memdbLeave(p);
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
#if 0 /* Only used to delete rollback journals, super-journals, and WAL
|
|
** files, none of which exist in memdb. So this routine is never used */
|
|
/*
|
|
** Delete the file located at zPath. If the dirSync argument is true,
|
|
** ensure the file-system modifications are synced to disk before
|
|
** returning.
|
|
*/
|
|
static int memdbDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
|
|
return SQLITE_IOERR_DELETE;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
** Test for access permissions. Return true if the requested permission
|
|
** is available, or false otherwise.
|
|
**
|
|
** With memdb, no files ever exist on disk. So always return false.
|
|
*/
|
|
static int memdbAccess(
|
|
sqlite3_vfs *pVfs,
|
|
const char *zPath,
|
|
int flags,
|
|
int *pResOut
|
|
){
|
|
UNUSED_PARAMETER(pVfs);
|
|
UNUSED_PARAMETER(zPath);
|
|
UNUSED_PARAMETER(flags);
|
|
*pResOut = 0;
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Populate buffer zOut with the full canonical pathname corresponding
|
|
** to the pathname in zPath. zOut is guaranteed to point to a buffer
|
|
** of at least (INST_MAX_PATHNAME+1) bytes.
|
|
*/
|
|
static int memdbFullPathname(
|
|
sqlite3_vfs *pVfs,
|
|
const char *zPath,
|
|
int nOut,
|
|
char *zOut
|
|
){
|
|
UNUSED_PARAMETER(pVfs);
|
|
sqlite3_snprintf(nOut, zOut, "%s", zPath);
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Open the dynamic library located at zPath and return a handle.
|
|
*/
|
|
static void *memdbDlOpen(sqlite3_vfs *pVfs, const char *zPath){
|
|
return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath);
|
|
}
|
|
|
|
/*
|
|
** Populate the buffer zErrMsg (size nByte bytes) with a human readable
|
|
** utf-8 string describing the most recent error encountered associated
|
|
** with dynamic libraries.
|
|
*/
|
|
static void memdbDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
|
|
ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg);
|
|
}
|
|
|
|
/*
|
|
** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
|
|
*/
|
|
static void (*memdbDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
|
|
return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym);
|
|
}
|
|
|
|
/*
|
|
** Close the dynamic library handle pHandle.
|
|
*/
|
|
static void memdbDlClose(sqlite3_vfs *pVfs, void *pHandle){
|
|
ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle);
|
|
}
|
|
|
|
/*
|
|
** Populate the buffer pointed to by zBufOut with nByte bytes of
|
|
** random data.
|
|
*/
|
|
static int memdbRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
|
|
return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut);
|
|
}
|
|
|
|
/*
|
|
** Sleep for nMicro microseconds. Return the number of microseconds
|
|
** actually slept.
|
|
*/
|
|
static int memdbSleep(sqlite3_vfs *pVfs, int nMicro){
|
|
return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro);
|
|
}
|
|
|
|
#if 0 /* Never used. Modern cores only call xCurrentTimeInt64() */
|
|
/*
|
|
** Return the current time as a Julian Day number in *pTimeOut.
|
|
*/
|
|
static int memdbCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
|
|
return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut);
|
|
}
|
|
#endif
|
|
|
|
static int memdbGetLastError(sqlite3_vfs *pVfs, int a, char *b){
|
|
return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b);
|
|
}
|
|
static int memdbCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
|
|
return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p);
|
|
}
|
|
|
|
/*
|
|
** Translate a database connection pointer and schema name into a
|
|
** MemFile pointer.
|
|
*/
|
|
static MemFile *memdbFromDbSchema(sqlite3 *db, const char *zSchema){
|
|
MemFile *p = 0;
|
|
MemStore *pStore;
|
|
int rc = sqlite3_file_control(db, zSchema, SQLITE_FCNTL_FILE_POINTER, &p);
|
|
if( rc ) return 0;
|
|
if( p->base.pMethods!=&memdb_io_methods ) return 0;
|
|
pStore = p->pStore;
|
|
memdbEnter(pStore);
|
|
if( pStore->zFName!=0 ) p = 0;
|
|
memdbLeave(pStore);
|
|
return p;
|
|
}
|
|
|
|
/*
|
|
** Return the serialization of a database
|
|
*/
|
|
SQLITE_API unsigned char *sqlite3_serialize(
|
|
sqlite3 *db, /* The database connection */
|
|
const char *zSchema, /* Which database within the connection */
|
|
sqlite3_int64 *piSize, /* Write size here, if not NULL */
|
|
unsigned int mFlags /* Maybe SQLITE_SERIALIZE_NOCOPY */
|
|
){
|
|
MemFile *p;
|
|
int iDb;
|
|
Btree *pBt;
|
|
sqlite3_int64 sz;
|
|
int szPage = 0;
|
|
sqlite3_stmt *pStmt = 0;
|
|
unsigned char *pOut;
|
|
char *zSql;
|
|
int rc;
|
|
|
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
|
if( !sqlite3SafetyCheckOk(db) ){
|
|
(void)SQLITE_MISUSE_BKPT;
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
|
|
p = memdbFromDbSchema(db, zSchema);
|
|
iDb = sqlite3FindDbName(db, zSchema);
|
|
if( piSize ) *piSize = -1;
|
|
if( iDb<0 ) return 0;
|
|
if( p ){
|
|
MemStore *pStore = p->pStore;
|
|
assert( pStore->pMutex==0 );
|
|
if( piSize ) *piSize = pStore->sz;
|
|
if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
|
|
pOut = pStore->aData;
|
|
}else{
|
|
pOut = sqlite3_malloc64( pStore->sz );
|
|
if( pOut ) memcpy(pOut, pStore->aData, pStore->sz);
|
|
}
|
|
return pOut;
|
|
}
|
|
pBt = db->aDb[iDb].pBt;
|
|
if( pBt==0 ) return 0;
|
|
szPage = sqlite3BtreeGetPageSize(pBt);
|
|
zSql = sqlite3_mprintf("PRAGMA \"%w\".page_count", zSchema);
|
|
rc = zSql ? sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0) : SQLITE_NOMEM;
|
|
sqlite3_free(zSql);
|
|
if( rc ) return 0;
|
|
rc = sqlite3_step(pStmt);
|
|
if( rc!=SQLITE_ROW ){
|
|
pOut = 0;
|
|
}else{
|
|
sz = sqlite3_column_int64(pStmt, 0)*szPage;
|
|
if( sz==0 ){
|
|
sqlite3_reset(pStmt);
|
|
sqlite3_exec(db, "BEGIN IMMEDIATE; COMMIT;", 0, 0, 0);
|
|
rc = sqlite3_step(pStmt);
|
|
if( rc==SQLITE_ROW ){
|
|
sz = sqlite3_column_int64(pStmt, 0)*szPage;
|
|
}
|
|
}
|
|
if( piSize ) *piSize = sz;
|
|
if( mFlags & SQLITE_SERIALIZE_NOCOPY ){
|
|
pOut = 0;
|
|
}else{
|
|
pOut = sqlite3_malloc64( sz );
|
|
if( pOut ){
|
|
int nPage = sqlite3_column_int(pStmt, 0);
|
|
Pager *pPager = sqlite3BtreePager(pBt);
|
|
int pgno;
|
|
for(pgno=1; pgno<=nPage; pgno++){
|
|
DbPage *pPage = 0;
|
|
unsigned char *pTo = pOut + szPage*(sqlite3_int64)(pgno-1);
|
|
rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pPage, 0);
|
|
if( rc==SQLITE_OK ){
|
|
memcpy(pTo, sqlite3PagerGetData(pPage), szPage);
|
|
}else{
|
|
memset(pTo, 0, szPage);
|
|
}
|
|
sqlite3PagerUnref(pPage);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
sqlite3_finalize(pStmt);
|
|
return pOut;
|
|
}
|
|
|
|
/* Convert zSchema to a MemDB and initialize its content.
|
|
*/
|
|
SQLITE_API int sqlite3_deserialize(
|
|
sqlite3 *db, /* The database connection */
|
|
const char *zSchema, /* Which DB to reopen with the deserialization */
|
|
unsigned char *pData, /* The serialized database content */
|
|
sqlite3_int64 szDb, /* Number bytes in the deserialization */
|
|
sqlite3_int64 szBuf, /* Total size of buffer pData[] */
|
|
unsigned mFlags /* Zero or more SQLITE_DESERIALIZE_* flags */
|
|
){
|
|
MemFile *p;
|
|
char *zSql;
|
|
sqlite3_stmt *pStmt = 0;
|
|
int rc;
|
|
int iDb;
|
|
|
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
|
if( !sqlite3SafetyCheckOk(db) ){
|
|
return SQLITE_MISUSE_BKPT;
|
|
}
|
|
if( szDb<0 ) return SQLITE_MISUSE_BKPT;
|
|
if( szBuf<0 ) return SQLITE_MISUSE_BKPT;
|
|
#endif
|
|
|
|
sqlite3_mutex_enter(db->mutex);
|
|
if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
|
|
iDb = sqlite3FindDbName(db, zSchema);
|
|
testcase( iDb==1 );
|
|
if( iDb<2 && iDb!=0 ){
|
|
rc = SQLITE_ERROR;
|
|
goto end_deserialize;
|
|
}
|
|
zSql = sqlite3_mprintf("ATTACH x AS %Q", zSchema);
|
|
if( zSql==0 ){
|
|
rc = SQLITE_NOMEM;
|
|
}else{
|
|
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
|
|
sqlite3_free(zSql);
|
|
}
|
|
if( rc ) goto end_deserialize;
|
|
db->init.iDb = (u8)iDb;
|
|
db->init.reopenMemdb = 1;
|
|
rc = sqlite3_step(pStmt);
|
|
db->init.reopenMemdb = 0;
|
|
if( rc!=SQLITE_DONE ){
|
|
rc = SQLITE_ERROR;
|
|
goto end_deserialize;
|
|
}
|
|
p = memdbFromDbSchema(db, zSchema);
|
|
if( p==0 ){
|
|
rc = SQLITE_ERROR;
|
|
}else{
|
|
MemStore *pStore = p->pStore;
|
|
pStore->aData = pData;
|
|
pData = 0;
|
|
pStore->sz = szDb;
|
|
pStore->szAlloc = szBuf;
|
|
pStore->szMax = szBuf;
|
|
if( pStore->szMax<sqlite3GlobalConfig.mxMemdbSize ){
|
|
pStore->szMax = sqlite3GlobalConfig.mxMemdbSize;
|
|
}
|
|
pStore->mFlags = mFlags;
|
|
rc = SQLITE_OK;
|
|
}
|
|
|
|
end_deserialize:
|
|
sqlite3_finalize(pStmt);
|
|
if( pData && (mFlags & SQLITE_DESERIALIZE_FREEONCLOSE)!=0 ){
|
|
sqlite3_free(pData);
|
|
}
|
|
sqlite3_mutex_leave(db->mutex);
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Return true if the VFS is the memvfs.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3IsMemdb(const sqlite3_vfs *pVfs){
|
|
return pVfs==&memdb_vfs;
|
|
}
|
|
|
|
/*
|
|
** This routine is called when the extension is loaded.
|
|
** Register the new VFS.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3MemdbInit(void){
|
|
sqlite3_vfs *pLower = sqlite3_vfs_find(0);
|
|
unsigned int sz;
|
|
if( NEVER(pLower==0) ) return SQLITE_ERROR;
|
|
sz = pLower->szOsFile;
|
|
memdb_vfs.pAppData = pLower;
|
|
/* The following conditional can only be true when compiled for
|
|
** Windows x86 and SQLITE_MAX_MMAP_SIZE=0. We always leave
|
|
** it in, to be safe, but it is marked as NO_TEST since there
|
|
** is no way to reach it under most builds. */
|
|
if( sz<sizeof(MemFile) ) sz = sizeof(MemFile); /*NO_TEST*/
|
|
memdb_vfs.szOsFile = sz;
|
|
return sqlite3_vfs_register(&memdb_vfs, 0);
|
|
}
|
|
#endif /* SQLITE_OMIT_DESERIALIZE */
|
|
|
|
/************** End of memdb.c ***********************************************/
|
|
/************** Begin file bitvec.c ******************************************/
|
|
/*
|
|
** 2008 February 16
|
|
**
|
|
** The author disclaims copyright to this source code. In place of
|
|
** a legal notice, here is a blessing:
|
|
**
|
|
** May you do good and not evil.
|
|
** May you find forgiveness for yourself and forgive others.
|
|
** May you share freely, never taking more than you give.
|
|
**
|
|
*************************************************************************
|
|
** This file implements an object that represents a fixed-length
|
|
** bitmap. Bits are numbered starting with 1.
|
|
**
|
|
** A bitmap is used to record which pages of a database file have been
|
|
** journalled during a transaction, or which pages have the "dont-write"
|
|
** property. Usually only a few pages are meet either condition.
|
|
** So the bitmap is usually sparse and has low cardinality.
|
|
** But sometimes (for example when during a DROP of a large table) most
|
|
** or all of the pages in a database can get journalled. In those cases,
|
|
** the bitmap becomes dense with high cardinality. The algorithm needs
|
|
** to handle both cases well.
|
|
**
|
|
** The size of the bitmap is fixed when the object is created.
|
|
**
|
|
** All bits are clear when the bitmap is created. Individual bits
|
|
** may be set or cleared one at a time.
|
|
**
|
|
** Test operations are about 100 times more common that set operations.
|
|
** Clear operations are exceedingly rare. There are usually between
|
|
** 5 and 500 set operations per Bitvec object, though the number of sets can
|
|
** sometimes grow into tens of thousands or larger. The size of the
|
|
** Bitvec object is the number of pages in the database file at the
|
|
** start of a transaction, and is thus usually less than a few thousand,
|
|
** but can be as large as 2 billion for a really big database.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
|
|
/* Size of the Bitvec structure in bytes. */
|
|
#define BITVEC_SZ 512
|
|
|
|
/* Round the union size down to the nearest pointer boundary, since that's how
|
|
** it will be aligned within the Bitvec struct. */
|
|
#define BITVEC_USIZE \
|
|
(((BITVEC_SZ-(3*sizeof(u32)))/sizeof(Bitvec*))*sizeof(Bitvec*))
|
|
|
|
/* Type of the array "element" for the bitmap representation.
|
|
** Should be a power of 2, and ideally, evenly divide into BITVEC_USIZE.
|
|
** Setting this to the "natural word" size of your CPU may improve
|
|
** performance. */
|
|
#define BITVEC_TELEM u8
|
|
/* Size, in bits, of the bitmap element. */
|
|
#define BITVEC_SZELEM 8
|
|
/* Number of elements in a bitmap array. */
|
|
#define BITVEC_NELEM (BITVEC_USIZE/sizeof(BITVEC_TELEM))
|
|
/* Number of bits in the bitmap array. */
|
|
#define BITVEC_NBIT (BITVEC_NELEM*BITVEC_SZELEM)
|
|
|
|
/* Number of u32 values in hash table. */
|
|
#define BITVEC_NINT (BITVEC_USIZE/sizeof(u32))
|
|
/* Maximum number of entries in hash table before
|
|
** sub-dividing and re-hashing. */
|
|
#define BITVEC_MXHASH (BITVEC_NINT/2)
|
|
/* Hashing function for the aHash representation.
|
|
** Empirical testing showed that the *37 multiplier
|
|
** (an arbitrary prime)in the hash function provided
|
|
** no fewer collisions than the no-op *1. */
|
|
#define BITVEC_HASH(X) (((X)*1)%BITVEC_NINT)
|
|
|
|
#define BITVEC_NPTR (BITVEC_USIZE/sizeof(Bitvec *))
|
|
|
|
|
|
/*
|
|
** A bitmap is an instance of the following structure.
|
|
**
|
|
** This bitmap records the existence of zero or more bits
|
|
** with values between 1 and iSize, inclusive.
|
|
**
|
|
** There are three possible representations of the bitmap.
|
|
** If iSize<=BITVEC_NBIT, then Bitvec.u.aBitmap[] is a straight
|
|
** bitmap. The least significant bit is bit 1.
|
|
**
|
|
** If iSize>BITVEC_NBIT and iDivisor==0 then Bitvec.u.aHash[] is
|
|
** a hash table that will hold up to BITVEC_MXHASH distinct values.
|
|
**
|
|
** Otherwise, the value i is redirected into one of BITVEC_NPTR
|
|
** sub-bitmaps pointed to by Bitvec.u.apSub[]. Each subbitmap
|
|
** handles up to iDivisor separate values of i. apSub[0] holds
|
|
** values between 1 and iDivisor. apSub[1] holds values between
|
|
** iDivisor+1 and 2*iDivisor. apSub[N] holds values between
|
|
** N*iDivisor+1 and (N+1)*iDivisor. Each subbitmap is normalized
|
|
** to hold deal with values between 1 and iDivisor.
|
|
*/
|
|
struct Bitvec {
|
|
u32 iSize; /* Maximum bit index. Max iSize is 4,294,967,296. */
|
|
u32 nSet; /* Number of bits that are set - only valid for aHash
|
|
** element. Max is BITVEC_NINT. For BITVEC_SZ of 512,
|
|
** this would be 125. */
|
|
u32 iDivisor; /* Number of bits handled by each apSub[] entry. */
|
|
/* Should >=0 for apSub element. */
|
|
/* Max iDivisor is max(u32) / BITVEC_NPTR + 1. */
|
|
/* For a BITVEC_SZ of 512, this would be 34,359,739. */
|
|
union {
|
|
BITVEC_TELEM aBitmap[BITVEC_NELEM]; /* Bitmap representation */
|
|
u32 aHash[BITVEC_NINT]; /* Hash table representation */
|
|
Bitvec *apSub[BITVEC_NPTR]; /* Recursive representation */
|
|
} u;
|
|
};
|
|
|
|
/*
|
|
** Create a new bitmap object able to handle bits between 0 and iSize,
|
|
** inclusive. Return a pointer to the new object. Return NULL if
|
|
** malloc fails.
|
|
*/
|
|
SQLITE_PRIVATE Bitvec *sqlite3BitvecCreate(u32 iSize){
|
|
Bitvec *p;
|
|
assert( sizeof(*p)==BITVEC_SZ );
|
|
p = sqlite3MallocZero( sizeof(*p) );
|
|
if( p ){
|
|
p->iSize = iSize;
|
|
}
|
|
return p;
|
|
}
|
|
|
|
/*
|
|
** Check to see if the i-th bit is set. Return true or false.
|
|
** If p is NULL (if the bitmap has not been created) or if
|
|
** i is out of range, then return false.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3BitvecTestNotNull(Bitvec *p, u32 i){
|
|
assert( p!=0 );
|
|
i--;
|
|
if( i>=p->iSize ) return 0;
|
|
while( p->iDivisor ){
|
|
u32 bin = i/p->iDivisor;
|
|
i = i%p->iDivisor;
|
|
p = p->u.apSub[bin];
|
|
if (!p) {
|
|
return 0;
|
|
}
|
|
}
|
|
if( p->iSize<=BITVEC_NBIT ){
|
|
return (p->u.aBitmap[i/BITVEC_SZELEM] & (1<<(i&(BITVEC_SZELEM-1))))!=0;
|
|
} else{
|
|
u32 h = BITVEC_HASH(i++);
|
|
while( p->u.aHash[h] ){
|
|
if( p->u.aHash[h]==i ) return 1;
|
|
h = (h+1) % BITVEC_NINT;
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
SQLITE_PRIVATE int sqlite3BitvecTest(Bitvec *p, u32 i){
|
|
return p!=0 && sqlite3BitvecTestNotNull(p,i);
|
|
}
|
|
|
|
/*
|
|
** Set the i-th bit. Return 0 on success and an error code if
|
|
** anything goes wrong.
|
|
**
|
|
** This routine might cause sub-bitmaps to be allocated. Failing
|
|
** to get the memory needed to hold the sub-bitmap is the only
|
|
** that can go wrong with an insert, assuming p and i are valid.
|
|
**
|
|
** The calling function must ensure that p is a valid Bitvec object
|
|
** and that the value for "i" is within range of the Bitvec object.
|
|
** Otherwise the behavior is undefined.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3BitvecSet(Bitvec *p, u32 i){
|
|
u32 h;
|
|
if( p==0 ) return SQLITE_OK;
|
|
assert( i>0 );
|
|
assert( i<=p->iSize );
|
|
i--;
|
|
while((p->iSize > BITVEC_NBIT) && p->iDivisor) {
|
|
u32 bin = i/p->iDivisor;
|
|
i = i%p->iDivisor;
|
|
if( p->u.apSub[bin]==0 ){
|
|
p->u.apSub[bin] = sqlite3BitvecCreate( p->iDivisor );
|
|
if( p->u.apSub[bin]==0 ) return SQLITE_NOMEM_BKPT;
|
|
}
|
|
p = p->u.apSub[bin];
|
|
}
|
|
if( p->iSize<=BITVEC_NBIT ){
|
|
p->u.aBitmap[i/BITVEC_SZELEM] |= 1 << (i&(BITVEC_SZELEM-1));
|
|
return SQLITE_OK;
|
|
}
|
|
h = BITVEC_HASH(i++);
|
|
/* if there wasn't a hash collision, and this doesn't */
|
|
/* completely fill the hash, then just add it without */
|
|
/* worrying about sub-dividing and re-hashing. */
|
|
if( !p->u.aHash[h] ){
|
|
if (p->nSet<(BITVEC_NINT-1)) {
|
|
goto bitvec_set_end;
|
|
} else {
|
|
goto bitvec_set_rehash;
|
|
}
|
|
}
|
|
/* there was a collision, check to see if it's already */
|
|
/* in hash, if not, try to find a spot for it */
|
|
do {
|
|
if( p->u.aHash[h]==i ) return SQLITE_OK;
|
|
h++;
|
|
if( h>=BITVEC_NINT ) h = 0;
|
|
} while( p->u.aHash[h] );
|
|
/* we didn't find it in the hash. h points to the first */
|
|
/* available free spot. check to see if this is going to */
|
|
/* make our hash too "full". */
|
|
bitvec_set_rehash:
|
|
if( p->nSet>=BITVEC_MXHASH ){
|
|
unsigned int j;
|
|
int rc;
|
|
u32 *aiValues = sqlite3StackAllocRaw(0, sizeof(p->u.aHash));
|
|
if( aiValues==0 ){
|
|
return SQLITE_NOMEM_BKPT;
|
|
}else{
|
|
memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash));
|
|
memset(p->u.apSub, 0, sizeof(p->u.apSub));
|
|
p->iDivisor = (p->iSize + BITVEC_NPTR - 1)/BITVEC_NPTR;
|
|
rc = sqlite3BitvecSet(p, i);
|
|
for(j=0; j<BITVEC_NINT; j++){
|
|
if( aiValues[j] ) rc |= sqlite3BitvecSet(p, aiValues[j]);
|
|
}
|
|
sqlite3StackFree(0, aiValues);
|
|
return rc;
|
|
}
|
|
}
|
|
bitvec_set_end:
|
|
p->nSet++;
|
|
p->u.aHash[h] = i;
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Clear the i-th bit.
|
|
**
|
|
** pBuf must be a pointer to at least BITVEC_SZ bytes of temporary storage
|
|
** that BitvecClear can use to rebuilt its hash table.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3BitvecClear(Bitvec *p, u32 i, void *pBuf){
|
|
if( p==0 ) return;
|
|
assert( i>0 );
|
|
i--;
|
|
while( p->iDivisor ){
|
|
u32 bin = i/p->iDivisor;
|
|
i = i%p->iDivisor;
|
|
p = p->u.apSub[bin];
|
|
if (!p) {
|
|
return;
|
|
}
|
|
}
|
|
if( p->iSize<=BITVEC_NBIT ){
|
|
p->u.aBitmap[i/BITVEC_SZELEM] &= ~(1 << (i&(BITVEC_SZELEM-1)));
|
|
}else{
|
|
unsigned int j;
|
|
u32 *aiValues = pBuf;
|
|
memcpy(aiValues, p->u.aHash, sizeof(p->u.aHash));
|
|
memset(p->u.aHash, 0, sizeof(p->u.aHash));
|
|
p->nSet = 0;
|
|
for(j=0; j<BITVEC_NINT; j++){
|
|
if( aiValues[j] && aiValues[j]!=(i+1) ){
|
|
u32 h = BITVEC_HASH(aiValues[j]-1);
|
|
p->nSet++;
|
|
while( p->u.aHash[h] ){
|
|
h++;
|
|
if( h>=BITVEC_NINT ) h = 0;
|
|
}
|
|
p->u.aHash[h] = aiValues[j];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Destroy a bitmap object. Reclaim all memory used.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3BitvecDestroy(Bitvec *p){
|
|
if( p==0 ) return;
|
|
if( p->iDivisor ){
|
|
unsigned int i;
|
|
for(i=0; i<BITVEC_NPTR; i++){
|
|
sqlite3BitvecDestroy(p->u.apSub[i]);
|
|
}
|
|
}
|
|
sqlite3_free(p);
|
|
}
|
|
|
|
/*
|
|
** Return the value of the iSize parameter specified when Bitvec *p
|
|
** was created.
|
|
*/
|
|
SQLITE_PRIVATE u32 sqlite3BitvecSize(Bitvec *p){
|
|
return p->iSize;
|
|
}
|
|
|
|
#ifndef SQLITE_UNTESTABLE
|
|
/*
|
|
** Let V[] be an array of unsigned characters sufficient to hold
|
|
** up to N bits. Let I be an integer between 0 and N. 0<=I<N.
|
|
** Then the following macros can be used to set, clear, or test
|
|
** individual bits within V.
|
|
*/
|
|
#define SETBIT(V,I) V[I>>3] |= (1<<(I&7))
|
|
#define CLEARBIT(V,I) V[I>>3] &= ~(1<<(I&7))
|
|
#define TESTBIT(V,I) (V[I>>3]&(1<<(I&7)))!=0
|
|
|
|
/*
|
|
** This routine runs an extensive test of the Bitvec code.
|
|
**
|
|
** The input is an array of integers that acts as a program
|
|
** to test the Bitvec. The integers are opcodes followed
|
|
** by 0, 1, or 3 operands, depending on the opcode. Another
|
|
** opcode follows immediately after the last operand.
|
|
**
|
|
** There are 6 opcodes numbered from 0 through 5. 0 is the
|
|
** "halt" opcode and causes the test to end.
|
|
**
|
|
** 0 Halt and return the number of errors
|
|
** 1 N S X Set N bits beginning with S and incrementing by X
|
|
** 2 N S X Clear N bits beginning with S and incrementing by X
|
|
** 3 N Set N randomly chosen bits
|
|
** 4 N Clear N randomly chosen bits
|
|
** 5 N S X Set N bits from S increment X in array only, not in bitvec
|
|
**
|
|
** The opcodes 1 through 4 perform set and clear operations are performed
|
|
** on both a Bitvec object and on a linear array of bits obtained from malloc.
|
|
** Opcode 5 works on the linear array only, not on the Bitvec.
|
|
** Opcode 5 is used to deliberately induce a fault in order to
|
|
** confirm that error detection works.
|
|
**
|
|
** At the conclusion of the test the linear array is compared
|
|
** against the Bitvec object. If there are any differences,
|
|
** an error is returned. If they are the same, zero is returned.
|
|
**
|
|
** If a memory allocation error occurs, return -1.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){
|
|
Bitvec *pBitvec = 0;
|
|
unsigned char *pV = 0;
|
|
int rc = -1;
|
|
int i, nx, pc, op;
|
|
void *pTmpSpace;
|
|
|
|
/* Allocate the Bitvec to be tested and a linear array of
|
|
** bits to act as the reference */
|
|
pBitvec = sqlite3BitvecCreate( sz );
|
|
pV = sqlite3MallocZero( (sz+7)/8 + 1 );
|
|
pTmpSpace = sqlite3_malloc64(BITVEC_SZ);
|
|
if( pBitvec==0 || pV==0 || pTmpSpace==0 ) goto bitvec_end;
|
|
|
|
/* NULL pBitvec tests */
|
|
sqlite3BitvecSet(0, 1);
|
|
sqlite3BitvecClear(0, 1, pTmpSpace);
|
|
|
|
/* Run the program */
|
|
pc = i = 0;
|
|
while( (op = aOp[pc])!=0 ){
|
|
switch( op ){
|
|
case 1:
|
|
case 2:
|
|
case 5: {
|
|
nx = 4;
|
|
i = aOp[pc+2] - 1;
|
|
aOp[pc+2] += aOp[pc+3];
|
|
break;
|
|
}
|
|
case 3:
|
|
case 4:
|
|
default: {
|
|
nx = 2;
|
|
sqlite3_randomness(sizeof(i), &i);
|
|
break;
|
|
}
|
|
}
|
|
if( (--aOp[pc+1]) > 0 ) nx = 0;
|
|
pc += nx;
|
|
i = (i & 0x7fffffff)%sz;
|
|
if( (op & 1)!=0 ){
|
|
SETBIT(pV, (i+1));
|
|
if( op!=5 ){
|
|
if( sqlite3BitvecSet(pBitvec, i+1) ) goto bitvec_end;
|
|
}
|
|
}else{
|
|
CLEARBIT(pV, (i+1));
|
|
sqlite3BitvecClear(pBitvec, i+1, pTmpSpace);
|
|
}
|
|
}
|
|
|
|
/* Test to make sure the linear array exactly matches the
|
|
** Bitvec object. Start with the assumption that they do
|
|
** match (rc==0). Change rc to non-zero if a discrepancy
|
|
** is found.
|
|
*/
|
|
rc = sqlite3BitvecTest(0,0) + sqlite3BitvecTest(pBitvec, sz+1)
|
|
+ sqlite3BitvecTest(pBitvec, 0)
|
|
+ (sqlite3BitvecSize(pBitvec) - sz);
|
|
for(i=1; i<=sz; i++){
|
|
if( (TESTBIT(pV,i))!=sqlite3BitvecTest(pBitvec,i) ){
|
|
rc = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Free allocated structure */
|
|
bitvec_end:
|
|
sqlite3_free(pTmpSpace);
|
|
sqlite3_free(pV);
|
|
sqlite3BitvecDestroy(pBitvec);
|
|
return rc;
|
|
}
|
|
#endif /* SQLITE_UNTESTABLE */
|
|
|
|
/************** End of bitvec.c **********************************************/
|
|
/************** Begin file pcache.c ******************************************/
|
|
/*
|
|
** 2008 August 05
|
|
**
|
|
** The author disclaims copyright to this source code. In place of
|
|
** a legal notice, here is a blessing:
|
|
**
|
|
** May you do good and not evil.
|
|
** May you find forgiveness for yourself and forgive others.
|
|
** May you share freely, never taking more than you give.
|
|
**
|
|
*************************************************************************
|
|
** This file implements that page cache.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
|
|
/*
|
|
** A complete page cache is an instance of this structure. Every
|
|
** entry in the cache holds a single page of the database file. The
|
|
** btree layer only operates on the cached copy of the database pages.
|
|
**
|
|
** A page cache entry is "clean" if it exactly matches what is currently
|
|
** on disk. A page is "dirty" if it has been modified and needs to be
|
|
** persisted to disk.
|
|
**
|
|
** pDirty, pDirtyTail, pSynced:
|
|
** All dirty pages are linked into the doubly linked list using
|
|
** PgHdr.pDirtyNext and pDirtyPrev. The list is maintained in LRU order
|
|
** such that p was added to the list more recently than p->pDirtyNext.
|
|
** PCache.pDirty points to the first (newest) element in the list and
|
|
** pDirtyTail to the last (oldest).
|
|
**
|
|
** The PCache.pSynced variable is used to optimize searching for a dirty
|
|
** page to eject from the cache mid-transaction. It is better to eject
|
|
** a page that does not require a journal sync than one that does.
|
|
** Therefore, pSynced is maintained so that it *almost* always points
|
|
** to either the oldest page in the pDirty/pDirtyTail list that has a
|
|
** clear PGHDR_NEED_SYNC flag or to a page that is older than this one
|
|
** (so that the right page to eject can be found by following pDirtyPrev
|
|
** pointers).
|
|
*/
|
|
struct PCache {
|
|
PgHdr *pDirty, *pDirtyTail; /* List of dirty pages in LRU order */
|
|
PgHdr *pSynced; /* Last synced page in dirty page list */
|
|
i64 nRefSum; /* Sum of ref counts over all pages */
|
|
int szCache; /* Configured cache size */
|
|
int szSpill; /* Size before spilling occurs */
|
|
int szPage; /* Size of every page in this cache */
|
|
int szExtra; /* Size of extra space for each page */
|
|
u8 bPurgeable; /* True if pages are on backing store */
|
|
u8 eCreate; /* eCreate value for for xFetch() */
|
|
int (*xStress)(void*,PgHdr*); /* Call to try make a page clean */
|
|
void *pStress; /* Argument to xStress */
|
|
sqlite3_pcache *pCache; /* Pluggable cache module */
|
|
};
|
|
|
|
/********************************** Test and Debug Logic **********************/
|
|
/*
|
|
** Debug tracing macros. Enable by by changing the "0" to "1" and
|
|
** recompiling.
|
|
**
|
|
** When sqlite3PcacheTrace is 1, single line trace messages are issued.
|
|
** When sqlite3PcacheTrace is 2, a dump of the pcache showing all cache entries
|
|
** is displayed for many operations, resulting in a lot of output.
|
|
*/
|
|
#if defined(SQLITE_DEBUG) && 0
|
|
int sqlite3PcacheTrace = 2; /* 0: off 1: simple 2: cache dumps */
|
|
int sqlite3PcacheMxDump = 9999; /* Max cache entries for pcacheDump() */
|
|
# define pcacheTrace(X) if(sqlite3PcacheTrace){sqlite3DebugPrintf X;}
|
|
static void pcachePageTrace(int i, sqlite3_pcache_page *pLower){
|
|
PgHdr *pPg;
|
|
unsigned char *a;
|
|
int j;
|
|
if( pLower==0 ){
|
|
printf("%3d: NULL\n", i);
|
|
}else{
|
|
pPg = (PgHdr*)pLower->pExtra;
|
|
printf("%3d: nRef %2lld flgs %02x data ", i, pPg->nRef, pPg->flags);
|
|
a = (unsigned char *)pLower->pBuf;
|
|
for(j=0; j<12; j++) printf("%02x", a[j]);
|
|
printf(" ptr %p\n", pPg);
|
|
}
|
|
}
|
|
static void pcacheDump(PCache *pCache){
|
|
int N;
|
|
int i;
|
|
sqlite3_pcache_page *pLower;
|
|
|
|
if( sqlite3PcacheTrace<2 ) return;
|
|
if( pCache->pCache==0 ) return;
|
|
N = sqlite3PcachePagecount(pCache);
|
|
if( N>sqlite3PcacheMxDump ) N = sqlite3PcacheMxDump;
|
|
for(i=1; i<=N; i++){
|
|
pLower = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, i, 0);
|
|
pcachePageTrace(i, pLower);
|
|
if( pLower && ((PgHdr*)pLower)->pPage==0 ){
|
|
sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, pLower, 0);
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
# define pcacheTrace(X)
|
|
# define pcachePageTrace(PGNO, X)
|
|
# define pcacheDump(X)
|
|
#endif
|
|
|
|
/*
|
|
** Return 1 if pPg is on the dirty list for pCache. Return 0 if not.
|
|
** This routine runs inside of assert() statements only.
|
|
*/
|
|
#if defined(SQLITE_ENABLE_EXPENSIVE_ASSERT)
|
|
static int pageOnDirtyList(PCache *pCache, PgHdr *pPg){
|
|
PgHdr *p;
|
|
for(p=pCache->pDirty; p; p=p->pDirtyNext){
|
|
if( p==pPg ) return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
static int pageNotOnDirtyList(PCache *pCache, PgHdr *pPg){
|
|
PgHdr *p;
|
|
for(p=pCache->pDirty; p; p=p->pDirtyNext){
|
|
if( p==pPg ) return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
#else
|
|
# define pageOnDirtyList(A,B) 1
|
|
# define pageNotOnDirtyList(A,B) 1
|
|
#endif
|
|
|
|
/*
|
|
** Check invariants on a PgHdr entry. Return true if everything is OK.
|
|
** Return false if any invariant is violated.
|
|
**
|
|
** This routine is for use inside of assert() statements only. For
|
|
** example:
|
|
**
|
|
** assert( sqlite3PcachePageSanity(pPg) );
|
|
*/
|
|
#ifdef SQLITE_DEBUG
|
|
SQLITE_PRIVATE int sqlite3PcachePageSanity(PgHdr *pPg){
|
|
PCache *pCache;
|
|
assert( pPg!=0 );
|
|
assert( pPg->pgno>0 || pPg->pPager==0 ); /* Page number is 1 or more */
|
|
pCache = pPg->pCache;
|
|
assert( pCache!=0 ); /* Every page has an associated PCache */
|
|
if( pPg->flags & PGHDR_CLEAN ){
|
|
assert( (pPg->flags & PGHDR_DIRTY)==0 );/* Cannot be both CLEAN and DIRTY */
|
|
assert( pageNotOnDirtyList(pCache, pPg) );/* CLEAN pages not on dirtylist */
|
|
}else{
|
|
assert( (pPg->flags & PGHDR_DIRTY)!=0 );/* If not CLEAN must be DIRTY */
|
|
assert( pPg->pDirtyNext==0 || pPg->pDirtyNext->pDirtyPrev==pPg );
|
|
assert( pPg->pDirtyPrev==0 || pPg->pDirtyPrev->pDirtyNext==pPg );
|
|
assert( pPg->pDirtyPrev!=0 || pCache->pDirty==pPg );
|
|
assert( pageOnDirtyList(pCache, pPg) );
|
|
}
|
|
/* WRITEABLE pages must also be DIRTY */
|
|
if( pPg->flags & PGHDR_WRITEABLE ){
|
|
assert( pPg->flags & PGHDR_DIRTY ); /* WRITEABLE implies DIRTY */
|
|
}
|
|
/* NEED_SYNC can be set independently of WRITEABLE. This can happen,
|
|
** for example, when using the sqlite3PagerDontWrite() optimization:
|
|
** (1) Page X is journalled, and gets WRITEABLE and NEED_SEEK.
|
|
** (2) Page X moved to freelist, WRITEABLE is cleared
|
|
** (3) Page X reused, WRITEABLE is set again
|
|
** If NEED_SYNC had been cleared in step 2, then it would not be reset
|
|
** in step 3, and page might be written into the database without first
|
|
** syncing the rollback journal, which might cause corruption on a power
|
|
** loss.
|
|
**
|
|
** Another example is when the database page size is smaller than the
|
|
** disk sector size. When any page of a sector is journalled, all pages
|
|
** in that sector are marked NEED_SYNC even if they are still CLEAN, just
|
|
** in case they are later modified, since all pages in the same sector
|
|
** must be journalled and synced before any of those pages can be safely
|
|
** written.
|
|
*/
|
|
return 1;
|
|
}
|
|
#endif /* SQLITE_DEBUG */
|
|
|
|
|
|
/********************************** Linked List Management ********************/
|
|
|
|
/* Allowed values for second argument to pcacheManageDirtyList() */
|
|
#define PCACHE_DIRTYLIST_REMOVE 1 /* Remove pPage from dirty list */
|
|
#define PCACHE_DIRTYLIST_ADD 2 /* Add pPage to the dirty list */
|
|
#define PCACHE_DIRTYLIST_FRONT 3 /* Move pPage to the front of the list */
|
|
|
|
/*
|
|
** Manage pPage's participation on the dirty list. Bits of the addRemove
|
|
** argument determines what operation to do. The 0x01 bit means first
|
|
** remove pPage from the dirty list. The 0x02 means add pPage back to
|
|
** the dirty list. Doing both moves pPage to the front of the dirty list.
|
|
*/
|
|
static void pcacheManageDirtyList(PgHdr *pPage, u8 addRemove){
|
|
PCache *p = pPage->pCache;
|
|
|
|
pcacheTrace(("%p.DIRTYLIST.%s %d\n", p,
|
|
addRemove==1 ? "REMOVE" : addRemove==2 ? "ADD" : "FRONT",
|
|
pPage->pgno));
|
|
if( addRemove & PCACHE_DIRTYLIST_REMOVE ){
|
|
assert( pPage->pDirtyNext || pPage==p->pDirtyTail );
|
|
assert( pPage->pDirtyPrev || pPage==p->pDirty );
|
|
|
|
/* Update the PCache1.pSynced variable if necessary. */
|
|
if( p->pSynced==pPage ){
|
|
p->pSynced = pPage->pDirtyPrev;
|
|
}
|
|
|
|
if( pPage->pDirtyNext ){
|
|
pPage->pDirtyNext->pDirtyPrev = pPage->pDirtyPrev;
|
|
}else{
|
|
assert( pPage==p->pDirtyTail );
|
|
p->pDirtyTail = pPage->pDirtyPrev;
|
|
}
|
|
if( pPage->pDirtyPrev ){
|
|
pPage->pDirtyPrev->pDirtyNext = pPage->pDirtyNext;
|
|
}else{
|
|
/* If there are now no dirty pages in the cache, set eCreate to 2.
|
|
** This is an optimization that allows sqlite3PcacheFetch() to skip
|
|
** searching for a dirty page to eject from the cache when it might
|
|
** otherwise have to. */
|
|
assert( pPage==p->pDirty );
|
|
p->pDirty = pPage->pDirtyNext;
|
|
assert( p->bPurgeable || p->eCreate==2 );
|
|
if( p->pDirty==0 ){ /*OPTIMIZATION-IF-TRUE*/
|
|
assert( p->bPurgeable==0 || p->eCreate==1 );
|
|
p->eCreate = 2;
|
|
}
|
|
}
|
|
}
|
|
if( addRemove & PCACHE_DIRTYLIST_ADD ){
|
|
pPage->pDirtyPrev = 0;
|
|
pPage->pDirtyNext = p->pDirty;
|
|
if( pPage->pDirtyNext ){
|
|
assert( pPage->pDirtyNext->pDirtyPrev==0 );
|
|
pPage->pDirtyNext->pDirtyPrev = pPage;
|
|
}else{
|
|
p->pDirtyTail = pPage;
|
|
if( p->bPurgeable ){
|
|
assert( p->eCreate==2 );
|
|
p->eCreate = 1;
|
|
}
|
|
}
|
|
p->pDirty = pPage;
|
|
|
|
/* If pSynced is NULL and this page has a clear NEED_SYNC flag, set
|
|
** pSynced to point to it. Checking the NEED_SYNC flag is an
|
|
** optimization, as if pSynced points to a page with the NEED_SYNC
|
|
** flag set sqlite3PcacheFetchStress() searches through all newer
|
|
** entries of the dirty-list for a page with NEED_SYNC clear anyway. */
|
|
if( !p->pSynced
|
|
&& 0==(pPage->flags&PGHDR_NEED_SYNC) /*OPTIMIZATION-IF-FALSE*/
|
|
){
|
|
p->pSynced = pPage;
|
|
}
|
|
}
|
|
pcacheDump(p);
|
|
}
|
|
|
|
/*
|
|
** Wrapper around the pluggable caches xUnpin method. If the cache is
|
|
** being used for an in-memory database, this function is a no-op.
|
|
*/
|
|
static void pcacheUnpin(PgHdr *p){
|
|
if( p->pCache->bPurgeable ){
|
|
pcacheTrace(("%p.UNPIN %d\n", p->pCache, p->pgno));
|
|
sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 0);
|
|
pcacheDump(p->pCache);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Compute the number of pages of cache requested. p->szCache is the
|
|
** cache size requested by the "PRAGMA cache_size" statement.
|
|
*/
|
|
static int numberOfCachePages(PCache *p){
|
|
if( p->szCache>=0 ){
|
|
/* IMPLEMENTATION-OF: R-42059-47211 If the argument N is positive then the
|
|
** suggested cache size is set to N. */
|
|
return p->szCache;
|
|
}else{
|
|
i64 n;
|
|
/* IMPLEMENTATION-OF: R-59858-46238 If the argument N is negative, then the
|
|
** number of cache pages is adjusted to be a number of pages that would
|
|
** use approximately abs(N*1024) bytes of memory based on the current
|
|
** page size. */
|
|
n = ((-1024*(i64)p->szCache)/(p->szPage+p->szExtra));
|
|
if( n>1000000000 ) n = 1000000000;
|
|
return (int)n;
|
|
}
|
|
}
|
|
|
|
/*************************************************** General Interfaces ******
|
|
**
|
|
** Initialize and shutdown the page cache subsystem. Neither of these
|
|
** functions are threadsafe.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3PcacheInitialize(void){
|
|
if( sqlite3GlobalConfig.pcache2.xInit==0 ){
|
|
/* IMPLEMENTATION-OF: R-26801-64137 If the xInit() method is NULL, then the
|
|
** built-in default page cache is used instead of the application defined
|
|
** page cache. */
|
|
sqlite3PCacheSetDefault();
|
|
assert( sqlite3GlobalConfig.pcache2.xInit!=0 );
|
|
}
|
|
return sqlite3GlobalConfig.pcache2.xInit(sqlite3GlobalConfig.pcache2.pArg);
|
|
}
|
|
SQLITE_PRIVATE void sqlite3PcacheShutdown(void){
|
|
if( sqlite3GlobalConfig.pcache2.xShutdown ){
|
|
/* IMPLEMENTATION-OF: R-26000-56589 The xShutdown() method may be NULL. */
|
|
sqlite3GlobalConfig.pcache2.xShutdown(sqlite3GlobalConfig.pcache2.pArg);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Return the size in bytes of a PCache object.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3PcacheSize(void){ return sizeof(PCache); }
|
|
|
|
/*
|
|
** Create a new PCache object. Storage space to hold the object
|
|
** has already been allocated and is passed in as the p pointer.
|
|
** The caller discovers how much space needs to be allocated by
|
|
** calling sqlite3PcacheSize().
|
|
**
|
|
** szExtra is some extra space allocated for each page. The first
|
|
** 8 bytes of the extra space will be zeroed as the page is allocated,
|
|
** but remaining content will be uninitialized. Though it is opaque
|
|
** to this module, the extra space really ends up being the MemPage
|
|
** structure in the pager.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3PcacheOpen(
|
|
int szPage, /* Size of every page */
|
|
int szExtra, /* Extra space associated with each page */
|
|
int bPurgeable, /* True if pages are on backing store */
|
|
int (*xStress)(void*,PgHdr*),/* Call to try to make pages clean */
|
|
void *pStress, /* Argument to xStress */
|
|
PCache *p /* Preallocated space for the PCache */
|
|
){
|
|
memset(p, 0, sizeof(PCache));
|
|
p->szPage = 1;
|
|
p->szExtra = szExtra;
|
|
assert( szExtra>=8 ); /* First 8 bytes will be zeroed */
|
|
p->bPurgeable = bPurgeable;
|
|
p->eCreate = 2;
|
|
p->xStress = xStress;
|
|
p->pStress = pStress;
|
|
p->szCache = 100;
|
|
p->szSpill = 1;
|
|
pcacheTrace(("%p.OPEN szPage %d bPurgeable %d\n",p,szPage,bPurgeable));
|
|
return sqlite3PcacheSetPageSize(p, szPage);
|
|
}
|
|
|
|
/*
|
|
** Change the page size for PCache object. The caller must ensure that there
|
|
** are no outstanding page references when this function is called.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3PcacheSetPageSize(PCache *pCache, int szPage){
|
|
assert( pCache->nRefSum==0 && pCache->pDirty==0 );
|
|
if( pCache->szPage ){
|
|
sqlite3_pcache *pNew;
|
|
pNew = sqlite3GlobalConfig.pcache2.xCreate(
|
|
szPage, pCache->szExtra + ROUND8(sizeof(PgHdr)),
|
|
pCache->bPurgeable
|
|
);
|
|
if( pNew==0 ) return SQLITE_NOMEM_BKPT;
|
|
sqlite3GlobalConfig.pcache2.xCachesize(pNew, numberOfCachePages(pCache));
|
|
if( pCache->pCache ){
|
|
sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
|
|
}
|
|
pCache->pCache = pNew;
|
|
pCache->szPage = szPage;
|
|
pcacheTrace(("%p.PAGESIZE %d\n",pCache,szPage));
|
|
}
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Try to obtain a page from the cache.
|
|
**
|
|
** This routine returns a pointer to an sqlite3_pcache_page object if
|
|
** such an object is already in cache, or if a new one is created.
|
|
** This routine returns a NULL pointer if the object was not in cache
|
|
** and could not be created.
|
|
**
|
|
** The createFlags should be 0 to check for existing pages and should
|
|
** be 3 (not 1, but 3) to try to create a new page.
|
|
**
|
|
** If the createFlag is 0, then NULL is always returned if the page
|
|
** is not already in the cache. If createFlag is 1, then a new page
|
|
** is created only if that can be done without spilling dirty pages
|
|
** and without exceeding the cache size limit.
|
|
**
|
|
** The caller needs to invoke sqlite3PcacheFetchFinish() to properly
|
|
** initialize the sqlite3_pcache_page object and convert it into a
|
|
** PgHdr object. The sqlite3PcacheFetch() and sqlite3PcacheFetchFinish()
|
|
** routines are split this way for performance reasons. When separated
|
|
** they can both (usually) operate without having to push values to
|
|
** the stack on entry and pop them back off on exit, which saves a
|
|
** lot of pushing and popping.
|
|
*/
|
|
SQLITE_PRIVATE sqlite3_pcache_page *sqlite3PcacheFetch(
|
|
PCache *pCache, /* Obtain the page from this cache */
|
|
Pgno pgno, /* Page number to obtain */
|
|
int createFlag /* If true, create page if it does not exist already */
|
|
){
|
|
int eCreate;
|
|
sqlite3_pcache_page *pRes;
|
|
|
|
assert( pCache!=0 );
|
|
assert( pCache->pCache!=0 );
|
|
assert( createFlag==3 || createFlag==0 );
|
|
assert( pCache->eCreate==((pCache->bPurgeable && pCache->pDirty) ? 1 : 2) );
|
|
|
|
/* eCreate defines what to do if the page does not exist.
|
|
** 0 Do not allocate a new page. (createFlag==0)
|
|
** 1 Allocate a new page if doing so is inexpensive.
|
|
** (createFlag==1 AND bPurgeable AND pDirty)
|
|
** 2 Allocate a new page even it doing so is difficult.
|
|
** (createFlag==1 AND !(bPurgeable AND pDirty)
|
|
*/
|
|
eCreate = createFlag & pCache->eCreate;
|
|
assert( eCreate==0 || eCreate==1 || eCreate==2 );
|
|
assert( createFlag==0 || pCache->eCreate==eCreate );
|
|
assert( createFlag==0 || eCreate==1+(!pCache->bPurgeable||!pCache->pDirty) );
|
|
pRes = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, eCreate);
|
|
pcacheTrace(("%p.FETCH %d%s (result: %p) ",pCache,pgno,
|
|
createFlag?" create":"",pRes));
|
|
pcachePageTrace(pgno, pRes);
|
|
return pRes;
|
|
}
|
|
|
|
/*
|
|
** If the sqlite3PcacheFetch() routine is unable to allocate a new
|
|
** page because no clean pages are available for reuse and the cache
|
|
** size limit has been reached, then this routine can be invoked to
|
|
** try harder to allocate a page. This routine might invoke the stress
|
|
** callback to spill dirty pages to the journal. It will then try to
|
|
** allocate the new page and will only fail to allocate a new page on
|
|
** an OOM error.
|
|
**
|
|
** This routine should be invoked only after sqlite3PcacheFetch() fails.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3PcacheFetchStress(
|
|
PCache *pCache, /* Obtain the page from this cache */
|
|
Pgno pgno, /* Page number to obtain */
|
|
sqlite3_pcache_page **ppPage /* Write result here */
|
|
){
|
|
PgHdr *pPg;
|
|
if( pCache->eCreate==2 ) return 0;
|
|
|
|
if( sqlite3PcachePagecount(pCache)>pCache->szSpill ){
|
|
/* Find a dirty page to write-out and recycle. First try to find a
|
|
** page that does not require a journal-sync (one with PGHDR_NEED_SYNC
|
|
** cleared), but if that is not possible settle for any other
|
|
** unreferenced dirty page.
|
|
**
|
|
** If the LRU page in the dirty list that has a clear PGHDR_NEED_SYNC
|
|
** flag is currently referenced, then the following may leave pSynced
|
|
** set incorrectly (pointing to other than the LRU page with NEED_SYNC
|
|
** cleared). This is Ok, as pSynced is just an optimization. */
|
|
for(pPg=pCache->pSynced;
|
|
pPg && (pPg->nRef || (pPg->flags&PGHDR_NEED_SYNC));
|
|
pPg=pPg->pDirtyPrev
|
|
);
|
|
pCache->pSynced = pPg;
|
|
if( !pPg ){
|
|
for(pPg=pCache->pDirtyTail; pPg && pPg->nRef; pPg=pPg->pDirtyPrev);
|
|
}
|
|
if( pPg ){
|
|
int rc;
|
|
#ifdef SQLITE_LOG_CACHE_SPILL
|
|
sqlite3_log(SQLITE_FULL,
|
|
"spill page %d making room for %d - cache used: %d/%d",
|
|
pPg->pgno, pgno,
|
|
sqlite3GlobalConfig.pcache2.xPagecount(pCache->pCache),
|
|
numberOfCachePages(pCache));
|
|
#endif
|
|
pcacheTrace(("%p.SPILL %d\n",pCache,pPg->pgno));
|
|
rc = pCache->xStress(pCache->pStress, pPg);
|
|
pcacheDump(pCache);
|
|
if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
|
|
return rc;
|
|
}
|
|
}
|
|
}
|
|
*ppPage = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, pgno, 2);
|
|
return *ppPage==0 ? SQLITE_NOMEM_BKPT : SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** This is a helper routine for sqlite3PcacheFetchFinish()
|
|
**
|
|
** In the uncommon case where the page being fetched has not been
|
|
** initialized, this routine is invoked to do the initialization.
|
|
** This routine is broken out into a separate function since it
|
|
** requires extra stack manipulation that can be avoided in the common
|
|
** case.
|
|
*/
|
|
static SQLITE_NOINLINE PgHdr *pcacheFetchFinishWithInit(
|
|
PCache *pCache, /* Obtain the page from this cache */
|
|
Pgno pgno, /* Page number obtained */
|
|
sqlite3_pcache_page *pPage /* Page obtained by prior PcacheFetch() call */
|
|
){
|
|
PgHdr *pPgHdr;
|
|
assert( pPage!=0 );
|
|
pPgHdr = (PgHdr*)pPage->pExtra;
|
|
assert( pPgHdr->pPage==0 );
|
|
memset(&pPgHdr->pDirty, 0, sizeof(PgHdr) - offsetof(PgHdr,pDirty));
|
|
pPgHdr->pPage = pPage;
|
|
pPgHdr->pData = pPage->pBuf;
|
|
pPgHdr->pExtra = (void *)&pPgHdr[1];
|
|
memset(pPgHdr->pExtra, 0, 8);
|
|
pPgHdr->pCache = pCache;
|
|
pPgHdr->pgno = pgno;
|
|
pPgHdr->flags = PGHDR_CLEAN;
|
|
return sqlite3PcacheFetchFinish(pCache,pgno,pPage);
|
|
}
|
|
|
|
/*
|
|
** This routine converts the sqlite3_pcache_page object returned by
|
|
** sqlite3PcacheFetch() into an initialized PgHdr object. This routine
|
|
** must be called after sqlite3PcacheFetch() in order to get a usable
|
|
** result.
|
|
*/
|
|
SQLITE_PRIVATE PgHdr *sqlite3PcacheFetchFinish(
|
|
PCache *pCache, /* Obtain the page from this cache */
|
|
Pgno pgno, /* Page number obtained */
|
|
sqlite3_pcache_page *pPage /* Page obtained by prior PcacheFetch() call */
|
|
){
|
|
PgHdr *pPgHdr;
|
|
|
|
assert( pPage!=0 );
|
|
pPgHdr = (PgHdr *)pPage->pExtra;
|
|
|
|
if( !pPgHdr->pPage ){
|
|
return pcacheFetchFinishWithInit(pCache, pgno, pPage);
|
|
}
|
|
pCache->nRefSum++;
|
|
pPgHdr->nRef++;
|
|
assert( sqlite3PcachePageSanity(pPgHdr) );
|
|
return pPgHdr;
|
|
}
|
|
|
|
/*
|
|
** Decrement the reference count on a page. If the page is clean and the
|
|
** reference count drops to 0, then it is made eligible for recycling.
|
|
*/
|
|
SQLITE_PRIVATE void SQLITE_NOINLINE sqlite3PcacheRelease(PgHdr *p){
|
|
assert( p->nRef>0 );
|
|
p->pCache->nRefSum--;
|
|
if( (--p->nRef)==0 ){
|
|
if( p->flags&PGHDR_CLEAN ){
|
|
pcacheUnpin(p);
|
|
}else{
|
|
pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT);
|
|
assert( sqlite3PcachePageSanity(p) );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Increase the reference count of a supplied page by 1.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3PcacheRef(PgHdr *p){
|
|
assert(p->nRef>0);
|
|
assert( sqlite3PcachePageSanity(p) );
|
|
p->nRef++;
|
|
p->pCache->nRefSum++;
|
|
}
|
|
|
|
/*
|
|
** Drop a page from the cache. There must be exactly one reference to the
|
|
** page. This function deletes that reference, so after it returns the
|
|
** page pointed to by p is invalid.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3PcacheDrop(PgHdr *p){
|
|
assert( p->nRef==1 );
|
|
assert( sqlite3PcachePageSanity(p) );
|
|
if( p->flags&PGHDR_DIRTY ){
|
|
pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE);
|
|
}
|
|
p->pCache->nRefSum--;
|
|
sqlite3GlobalConfig.pcache2.xUnpin(p->pCache->pCache, p->pPage, 1);
|
|
}
|
|
|
|
/*
|
|
** Make sure the page is marked as dirty. If it isn't dirty already,
|
|
** make it so.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3PcacheMakeDirty(PgHdr *p){
|
|
assert( p->nRef>0 );
|
|
assert( sqlite3PcachePageSanity(p) );
|
|
if( p->flags & (PGHDR_CLEAN|PGHDR_DONT_WRITE) ){ /*OPTIMIZATION-IF-FALSE*/
|
|
p->flags &= ~PGHDR_DONT_WRITE;
|
|
if( p->flags & PGHDR_CLEAN ){
|
|
p->flags ^= (PGHDR_DIRTY|PGHDR_CLEAN);
|
|
pcacheTrace(("%p.DIRTY %d\n",p->pCache,p->pgno));
|
|
assert( (p->flags & (PGHDR_DIRTY|PGHDR_CLEAN))==PGHDR_DIRTY );
|
|
pcacheManageDirtyList(p, PCACHE_DIRTYLIST_ADD);
|
|
assert( sqlite3PcachePageSanity(p) );
|
|
}
|
|
assert( sqlite3PcachePageSanity(p) );
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Make sure the page is marked as clean. If it isn't clean already,
|
|
** make it so.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3PcacheMakeClean(PgHdr *p){
|
|
assert( sqlite3PcachePageSanity(p) );
|
|
assert( (p->flags & PGHDR_DIRTY)!=0 );
|
|
assert( (p->flags & PGHDR_CLEAN)==0 );
|
|
pcacheManageDirtyList(p, PCACHE_DIRTYLIST_REMOVE);
|
|
p->flags &= ~(PGHDR_DIRTY|PGHDR_NEED_SYNC|PGHDR_WRITEABLE);
|
|
p->flags |= PGHDR_CLEAN;
|
|
pcacheTrace(("%p.CLEAN %d\n",p->pCache,p->pgno));
|
|
assert( sqlite3PcachePageSanity(p) );
|
|
if( p->nRef==0 ){
|
|
pcacheUnpin(p);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Make every page in the cache clean.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3PcacheCleanAll(PCache *pCache){
|
|
PgHdr *p;
|
|
pcacheTrace(("%p.CLEAN-ALL\n",pCache));
|
|
while( (p = pCache->pDirty)!=0 ){
|
|
sqlite3PcacheMakeClean(p);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Clear the PGHDR_NEED_SYNC and PGHDR_WRITEABLE flag from all dirty pages.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3PcacheClearWritable(PCache *pCache){
|
|
PgHdr *p;
|
|
pcacheTrace(("%p.CLEAR-WRITEABLE\n",pCache));
|
|
for(p=pCache->pDirty; p; p=p->pDirtyNext){
|
|
p->flags &= ~(PGHDR_NEED_SYNC|PGHDR_WRITEABLE);
|
|
}
|
|
pCache->pSynced = pCache->pDirtyTail;
|
|
}
|
|
|
|
/*
|
|
** Clear the PGHDR_NEED_SYNC flag from all dirty pages.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3PcacheClearSyncFlags(PCache *pCache){
|
|
PgHdr *p;
|
|
for(p=pCache->pDirty; p; p=p->pDirtyNext){
|
|
p->flags &= ~PGHDR_NEED_SYNC;
|
|
}
|
|
pCache->pSynced = pCache->pDirtyTail;
|
|
}
|
|
|
|
/*
|
|
** Change the page number of page p to newPgno.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3PcacheMove(PgHdr *p, Pgno newPgno){
|
|
PCache *pCache = p->pCache;
|
|
sqlite3_pcache_page *pOther;
|
|
assert( p->nRef>0 );
|
|
assert( newPgno>0 );
|
|
assert( sqlite3PcachePageSanity(p) );
|
|
pcacheTrace(("%p.MOVE %d -> %d\n",pCache,p->pgno,newPgno));
|
|
pOther = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, newPgno, 0);
|
|
if( pOther ){
|
|
PgHdr *pXPage = (PgHdr*)pOther->pExtra;
|
|
assert( pXPage->nRef==0 );
|
|
pXPage->nRef++;
|
|
pCache->nRefSum++;
|
|
sqlite3PcacheDrop(pXPage);
|
|
}
|
|
sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno);
|
|
p->pgno = newPgno;
|
|
if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){
|
|
pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT);
|
|
assert( sqlite3PcachePageSanity(p) );
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Drop every cache entry whose page number is greater than "pgno". The
|
|
** caller must ensure that there are no outstanding references to any pages
|
|
** other than page 1 with a page number greater than pgno.
|
|
**
|
|
** If there is a reference to page 1 and the pgno parameter passed to this
|
|
** function is 0, then the data area associated with page 1 is zeroed, but
|
|
** the page object is not dropped.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3PcacheTruncate(PCache *pCache, Pgno pgno){
|
|
if( pCache->pCache ){
|
|
PgHdr *p;
|
|
PgHdr *pNext;
|
|
pcacheTrace(("%p.TRUNCATE %d\n",pCache,pgno));
|
|
for(p=pCache->pDirty; p; p=pNext){
|
|
pNext = p->pDirtyNext;
|
|
/* This routine never gets call with a positive pgno except right
|
|
** after sqlite3PcacheCleanAll(). So if there are dirty pages,
|
|
** it must be that pgno==0.
|
|
*/
|
|
assert( p->pgno>0 );
|
|
if( p->pgno>pgno ){
|
|
assert( p->flags&PGHDR_DIRTY );
|
|
sqlite3PcacheMakeClean(p);
|
|
}
|
|
}
|
|
if( pgno==0 && pCache->nRefSum ){
|
|
sqlite3_pcache_page *pPage1;
|
|
pPage1 = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache,1,0);
|
|
if( ALWAYS(pPage1) ){ /* Page 1 is always available in cache, because
|
|
** pCache->nRefSum>0 */
|
|
memset(pPage1->pBuf, 0, pCache->szPage);
|
|
pgno = 1;
|
|
}
|
|
}
|
|
sqlite3GlobalConfig.pcache2.xTruncate(pCache->pCache, pgno+1);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Close a cache.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3PcacheClose(PCache *pCache){
|
|
assert( pCache->pCache!=0 );
|
|
pcacheTrace(("%p.CLOSE\n",pCache));
|
|
sqlite3GlobalConfig.pcache2.xDestroy(pCache->pCache);
|
|
}
|
|
|
|
/*
|
|
** Discard the contents of the cache.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3PcacheClear(PCache *pCache){
|
|
sqlite3PcacheTruncate(pCache, 0);
|
|
}
|
|
|
|
/*
|
|
** Merge two lists of pages connected by pDirty and in pgno order.
|
|
** Do not bother fixing the pDirtyPrev pointers.
|
|
*/
|
|
static PgHdr *pcacheMergeDirtyList(PgHdr *pA, PgHdr *pB){
|
|
PgHdr result, *pTail;
|
|
pTail = &result;
|
|
assert( pA!=0 && pB!=0 );
|
|
for(;;){
|
|
if( pA->pgno<pB->pgno ){
|
|
pTail->pDirty = pA;
|
|
pTail = pA;
|
|
pA = pA->pDirty;
|
|
if( pA==0 ){
|
|
pTail->pDirty = pB;
|
|
break;
|
|
}
|
|
}else{
|
|
pTail->pDirty = pB;
|
|
pTail = pB;
|
|
pB = pB->pDirty;
|
|
if( pB==0 ){
|
|
pTail->pDirty = pA;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return result.pDirty;
|
|
}
|
|
|
|
/*
|
|
** Sort the list of pages in ascending order by pgno. Pages are
|
|
** connected by pDirty pointers. The pDirtyPrev pointers are
|
|
** corrupted by this sort.
|
|
**
|
|
** Since there cannot be more than 2^31 distinct pages in a database,
|
|
** there cannot be more than 31 buckets required by the merge sorter.
|
|
** One extra bucket is added to catch overflow in case something
|
|
** ever changes to make the previous sentence incorrect.
|
|
*/
|
|
#define N_SORT_BUCKET 32
|
|
static PgHdr *pcacheSortDirtyList(PgHdr *pIn){
|
|
PgHdr *a[N_SORT_BUCKET], *p;
|
|
int i;
|
|
memset(a, 0, sizeof(a));
|
|
while( pIn ){
|
|
p = pIn;
|
|
pIn = p->pDirty;
|
|
p->pDirty = 0;
|
|
for(i=0; ALWAYS(i<N_SORT_BUCKET-1); i++){
|
|
if( a[i]==0 ){
|
|
a[i] = p;
|
|
break;
|
|
}else{
|
|
p = pcacheMergeDirtyList(a[i], p);
|
|
a[i] = 0;
|
|
}
|
|
}
|
|
if( NEVER(i==N_SORT_BUCKET-1) ){
|
|
/* To get here, there need to be 2^(N_SORT_BUCKET) elements in
|
|
** the input list. But that is impossible.
|
|
*/
|
|
a[i] = pcacheMergeDirtyList(a[i], p);
|
|
}
|
|
}
|
|
p = a[0];
|
|
for(i=1; i<N_SORT_BUCKET; i++){
|
|
if( a[i]==0 ) continue;
|
|
p = p ? pcacheMergeDirtyList(p, a[i]) : a[i];
|
|
}
|
|
return p;
|
|
}
|
|
|
|
/*
|
|
** Return a list of all dirty pages in the cache, sorted by page number.
|
|
*/
|
|
SQLITE_PRIVATE PgHdr *sqlite3PcacheDirtyList(PCache *pCache){
|
|
PgHdr *p;
|
|
for(p=pCache->pDirty; p; p=p->pDirtyNext){
|
|
p->pDirty = p->pDirtyNext;
|
|
}
|
|
return pcacheSortDirtyList(pCache->pDirty);
|
|
}
|
|
|
|
/*
|
|
** Return the total number of references to all pages held by the cache.
|
|
**
|
|
** This is not the total number of pages referenced, but the sum of the
|
|
** reference count for all pages.
|
|
*/
|
|
SQLITE_PRIVATE i64 sqlite3PcacheRefCount(PCache *pCache){
|
|
return pCache->nRefSum;
|
|
}
|
|
|
|
/*
|
|
** Return the number of references to the page supplied as an argument.
|
|
*/
|
|
SQLITE_PRIVATE i64 sqlite3PcachePageRefcount(PgHdr *p){
|
|
return p->nRef;
|
|
}
|
|
|
|
/*
|
|
** Return the total number of pages in the cache.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3PcachePagecount(PCache *pCache){
|
|
assert( pCache->pCache!=0 );
|
|
return sqlite3GlobalConfig.pcache2.xPagecount(pCache->pCache);
|
|
}
|
|
|
|
#ifdef SQLITE_TEST
|
|
/*
|
|
** Get the suggested cache-size value.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3PcacheGetCachesize(PCache *pCache){
|
|
return numberOfCachePages(pCache);
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
** Set the suggested cache-size value.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3PcacheSetCachesize(PCache *pCache, int mxPage){
|
|
assert( pCache->pCache!=0 );
|
|
pCache->szCache = mxPage;
|
|
sqlite3GlobalConfig.pcache2.xCachesize(pCache->pCache,
|
|
numberOfCachePages(pCache));
|
|
}
|
|
|
|
/*
|
|
** Set the suggested cache-spill value. Make no changes if if the
|
|
** argument is zero. Return the effective cache-spill size, which will
|
|
** be the larger of the szSpill and szCache.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3PcacheSetSpillsize(PCache *p, int mxPage){
|
|
int res;
|
|
assert( p->pCache!=0 );
|
|
if( mxPage ){
|
|
if( mxPage<0 ){
|
|
mxPage = (int)((-1024*(i64)mxPage)/(p->szPage+p->szExtra));
|
|
}
|
|
p->szSpill = mxPage;
|
|
}
|
|
res = numberOfCachePages(p);
|
|
if( res<p->szSpill ) res = p->szSpill;
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
** Free up as much memory as possible from the page cache.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3PcacheShrink(PCache *pCache){
|
|
assert( pCache->pCache!=0 );
|
|
sqlite3GlobalConfig.pcache2.xShrink(pCache->pCache);
|
|
}
|
|
|
|
/*
|
|
** Return the size of the header added by this middleware layer
|
|
** in the page-cache hierarchy.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3HeaderSizePcache(void){ return ROUND8(sizeof(PgHdr)); }
|
|
|
|
/*
|
|
** Return the number of dirty pages currently in the cache, as a percentage
|
|
** of the configured cache size.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3PCachePercentDirty(PCache *pCache){
|
|
PgHdr *pDirty;
|
|
int nDirty = 0;
|
|
int nCache = numberOfCachePages(pCache);
|
|
for(pDirty=pCache->pDirty; pDirty; pDirty=pDirty->pDirtyNext) nDirty++;
|
|
return nCache ? (int)(((i64)nDirty * 100) / nCache) : 0;
|
|
}
|
|
|
|
#ifdef SQLITE_DIRECT_OVERFLOW_READ
|
|
/*
|
|
** Return true if there are one or more dirty pages in the cache. Else false.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3PCacheIsDirty(PCache *pCache){
|
|
return (pCache->pDirty!=0);
|
|
}
|
|
#endif
|
|
|
|
#if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG)
|
|
/*
|
|
** For all dirty pages currently in the cache, invoke the specified
|
|
** callback. This is only used if the SQLITE_CHECK_PAGES macro is
|
|
** defined.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3PcacheIterateDirty(PCache *pCache, void (*xIter)(PgHdr *)){
|
|
PgHdr *pDirty;
|
|
for(pDirty=pCache->pDirty; pDirty; pDirty=pDirty->pDirtyNext){
|
|
xIter(pDirty);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/************** End of pcache.c **********************************************/
|
|
/************** Begin file pcache1.c *****************************************/
|
|
/*
|
|
** 2008 November 05
|
|
**
|
|
** The author disclaims copyright to this source code. In place of
|
|
** a legal notice, here is a blessing:
|
|
**
|
|
** May you do good and not evil.
|
|
** May you find forgiveness for yourself and forgive others.
|
|
** May you share freely, never taking more than you give.
|
|
**
|
|
*************************************************************************
|
|
**
|
|
** This file implements the default page cache implementation (the
|
|
** sqlite3_pcache interface). It also contains part of the implementation
|
|
** of the SQLITE_CONFIG_PAGECACHE and sqlite3_release_memory() features.
|
|
** If the default page cache implementation is overridden, then neither of
|
|
** these two features are available.
|
|
**
|
|
** A Page cache line looks like this:
|
|
**
|
|
** -------------------------------------------------------------
|
|
** | database page content | PgHdr1 | MemPage | PgHdr |
|
|
** -------------------------------------------------------------
|
|
**
|
|
** The database page content is up front (so that buffer overreads tend to
|
|
** flow harmlessly into the PgHdr1, MemPage, and PgHdr extensions). MemPage
|
|
** is the extension added by the btree.c module containing information such
|
|
** as the database page number and how that database page is used. PgHdr
|
|
** is added by the pcache.c layer and contains information used to keep track
|
|
** of which pages are "dirty". PgHdr1 is an extension added by this
|
|
** module (pcache1.c). The PgHdr1 header is a subclass of sqlite3_pcache_page.
|
|
** PgHdr1 contains information needed to look up a page by its page number.
|
|
** The superclass sqlite3_pcache_page.pBuf points to the start of the
|
|
** database page content and sqlite3_pcache_page.pExtra points to PgHdr.
|
|
**
|
|
** The size of the extension (MemPage+PgHdr+PgHdr1) can be determined at
|
|
** runtime using sqlite3_config(SQLITE_CONFIG_PCACHE_HDRSZ, &size). The
|
|
** sizes of the extensions sum to 272 bytes on x64 for 3.8.10, but this
|
|
** size can vary according to architecture, compile-time options, and
|
|
** SQLite library version number.
|
|
**
|
|
** Historical note: It used to be that if the SQLITE_PCACHE_SEPARATE_HEADER
|
|
** was defined, then the page content would be held in a separate memory
|
|
** allocation from the PgHdr1. This was intended to avoid clownshoe memory
|
|
** allocations. However, the btree layer needs a small (16-byte) overrun
|
|
** area after the page content buffer. The header serves as that overrun
|
|
** area. Therefore SQLITE_PCACHE_SEPARATE_HEADER was discontinued to avoid
|
|
** any possibility of a memory error.
|
|
**
|
|
** This module tracks pointers to PgHdr1 objects. Only pcache.c communicates
|
|
** with this module. Information is passed back and forth as PgHdr1 pointers.
|
|
**
|
|
** The pcache.c and pager.c modules deal pointers to PgHdr objects.
|
|
** The btree.c module deals with pointers to MemPage objects.
|
|
**
|
|
** SOURCE OF PAGE CACHE MEMORY:
|
|
**
|
|
** Memory for a page might come from any of three sources:
|
|
**
|
|
** (1) The general-purpose memory allocator - sqlite3Malloc()
|
|
** (2) Global page-cache memory provided using sqlite3_config() with
|
|
** SQLITE_CONFIG_PAGECACHE.
|
|
** (3) PCache-local bulk allocation.
|
|
**
|
|
** The third case is a chunk of heap memory (defaulting to 100 pages worth)
|
|
** that is allocated when the page cache is created. The size of the local
|
|
** bulk allocation can be adjusted using
|
|
**
|
|
** sqlite3_config(SQLITE_CONFIG_PAGECACHE, (void*)0, 0, N).
|
|
**
|
|
** If N is positive, then N pages worth of memory are allocated using a single
|
|
** sqlite3Malloc() call and that memory is used for the first N pages allocated.
|
|
** Or if N is negative, then -1024*N bytes of memory are allocated and used
|
|
** for as many pages as can be accommodated.
|
|
**
|
|
** Only one of (2) or (3) can be used. Once the memory available to (2) or
|
|
** (3) is exhausted, subsequent allocations fail over to the general-purpose
|
|
** memory allocator (1).
|
|
**
|
|
** Earlier versions of SQLite used only methods (1) and (2). But experiments
|
|
** show that method (3) with N==100 provides about a 5% performance boost for
|
|
** common workloads.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
|
|
typedef struct PCache1 PCache1;
|
|
typedef struct PgHdr1 PgHdr1;
|
|
typedef struct PgFreeslot PgFreeslot;
|
|
typedef struct PGroup PGroup;
|
|
|
|
/*
|
|
** Each cache entry is represented by an instance of the following
|
|
** structure. A buffer of PgHdr1.pCache->szPage bytes is allocated
|
|
** directly before this structure and is used to cache the page content.
|
|
**
|
|
** When reading a corrupt database file, it is possible that SQLite might
|
|
** read a few bytes (no more than 16 bytes) past the end of the page buffer.
|
|
** It will only read past the end of the page buffer, never write. This
|
|
** object is positioned immediately after the page buffer to serve as an
|
|
** overrun area, so that overreads are harmless.
|
|
**
|
|
** Variables isBulkLocal and isAnchor were once type "u8". That works,
|
|
** but causes a 2-byte gap in the structure for most architectures (since
|
|
** pointers must be either 4 or 8-byte aligned). As this structure is located
|
|
** in memory directly after the associated page data, if the database is
|
|
** corrupt, code at the b-tree layer may overread the page buffer and
|
|
** read part of this structure before the corruption is detected. This
|
|
** can cause a valgrind error if the uninitialized gap is accessed. Using u16
|
|
** ensures there is no such gap, and therefore no bytes of uninitialized
|
|
** memory in the structure.
|
|
**
|
|
** The pLruNext and pLruPrev pointers form a double-linked circular list
|
|
** of all pages that are unpinned. The PGroup.lru element (which should be
|
|
** the only element on the list with PgHdr1.isAnchor set to 1) forms the
|
|
** beginning and the end of the list.
|
|
*/
|
|
struct PgHdr1 {
|
|
sqlite3_pcache_page page; /* Base class. Must be first. pBuf & pExtra */
|
|
unsigned int iKey; /* Key value (page number) */
|
|
u16 isBulkLocal; /* This page from bulk local storage */
|
|
u16 isAnchor; /* This is the PGroup.lru element */
|
|
PgHdr1 *pNext; /* Next in hash table chain */
|
|
PCache1 *pCache; /* Cache that currently owns this page */
|
|
PgHdr1 *pLruNext; /* Next in circular LRU list of unpinned pages */
|
|
PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */
|
|
/* NB: pLruPrev is only valid if pLruNext!=0 */
|
|
};
|
|
|
|
/*
|
|
** A page is pinned if it is not on the LRU list. To be "pinned" means
|
|
** that the page is in active use and must not be deallocated.
|
|
*/
|
|
#define PAGE_IS_PINNED(p) ((p)->pLruNext==0)
|
|
#define PAGE_IS_UNPINNED(p) ((p)->pLruNext!=0)
|
|
|
|
/* Each page cache (or PCache) belongs to a PGroup. A PGroup is a set
|
|
** of one or more PCaches that are able to recycle each other's unpinned
|
|
** pages when they are under memory pressure. A PGroup is an instance of
|
|
** the following object.
|
|
**
|
|
** This page cache implementation works in one of two modes:
|
|
**
|
|
** (1) Every PCache is the sole member of its own PGroup. There is
|
|
** one PGroup per PCache.
|
|
**
|
|
** (2) There is a single global PGroup that all PCaches are a member
|
|
** of.
|
|
**
|
|
** Mode 1 uses more memory (since PCache instances are not able to rob
|
|
** unused pages from other PCaches) but it also operates without a mutex,
|
|
** and is therefore often faster. Mode 2 requires a mutex in order to be
|
|
** threadsafe, but recycles pages more efficiently.
|
|
**
|
|
** For mode (1), PGroup.mutex is NULL. For mode (2) there is only a single
|
|
** PGroup which is the pcache1.grp global variable and its mutex is
|
|
** SQLITE_MUTEX_STATIC_LRU.
|
|
*/
|
|
struct PGroup {
|
|
sqlite3_mutex *mutex; /* MUTEX_STATIC_LRU or NULL */
|
|
unsigned int nMaxPage; /* Sum of nMax for purgeable caches */
|
|
unsigned int nMinPage; /* Sum of nMin for purgeable caches */
|
|
unsigned int mxPinned; /* nMaxpage + 10 - nMinPage */
|
|
unsigned int nPurgeable; /* Number of purgeable pages allocated */
|
|
PgHdr1 lru; /* The beginning and end of the LRU list */
|
|
};
|
|
|
|
/* Each page cache is an instance of the following object. Every
|
|
** open database file (including each in-memory database and each
|
|
** temporary or transient database) has a single page cache which
|
|
** is an instance of this object.
|
|
**
|
|
** Pointers to structures of this type are cast and returned as
|
|
** opaque sqlite3_pcache* handles.
|
|
*/
|
|
struct PCache1 {
|
|
/* Cache configuration parameters. Page size (szPage) and the purgeable
|
|
** flag (bPurgeable) and the pnPurgeable pointer are all set when the
|
|
** cache is created and are never changed thereafter. nMax may be
|
|
** modified at any time by a call to the pcache1Cachesize() method.
|
|
** The PGroup mutex must be held when accessing nMax.
|
|
*/
|
|
PGroup *pGroup; /* PGroup this cache belongs to */
|
|
unsigned int *pnPurgeable; /* Pointer to pGroup->nPurgeable */
|
|
int szPage; /* Size of database content section */
|
|
int szExtra; /* sizeof(MemPage)+sizeof(PgHdr) */
|
|
int szAlloc; /* Total size of one pcache line */
|
|
int bPurgeable; /* True if cache is purgeable */
|
|
unsigned int nMin; /* Minimum number of pages reserved */
|
|
unsigned int nMax; /* Configured "cache_size" value */
|
|
unsigned int n90pct; /* nMax*9/10 */
|
|
unsigned int iMaxKey; /* Largest key seen since xTruncate() */
|
|
unsigned int nPurgeableDummy; /* pnPurgeable points here when not used*/
|
|
|
|
/* Hash table of all pages. The following variables may only be accessed
|
|
** when the accessor is holding the PGroup mutex.
|
|
*/
|
|
unsigned int nRecyclable; /* Number of pages in the LRU list */
|
|
unsigned int nPage; /* Total number of pages in apHash */
|
|
unsigned int nHash; /* Number of slots in apHash[] */
|
|
PgHdr1 **apHash; /* Hash table for fast lookup by key */
|
|
PgHdr1 *pFree; /* List of unused pcache-local pages */
|
|
void *pBulk; /* Bulk memory used by pcache-local */
|
|
};
|
|
|
|
/*
|
|
** Free slots in the allocator used to divide up the global page cache
|
|
** buffer provided using the SQLITE_CONFIG_PAGECACHE mechanism.
|
|
*/
|
|
struct PgFreeslot {
|
|
PgFreeslot *pNext; /* Next free slot */
|
|
};
|
|
|
|
/*
|
|
** Global data used by this cache.
|
|
*/
|
|
static SQLITE_WSD struct PCacheGlobal {
|
|
PGroup grp; /* The global PGroup for mode (2) */
|
|
|
|
/* Variables related to SQLITE_CONFIG_PAGECACHE settings. The
|
|
** szSlot, nSlot, pStart, pEnd, nReserve, and isInit values are all
|
|
** fixed at sqlite3_initialize() time and do not require mutex protection.
|
|
** The nFreeSlot and pFree values do require mutex protection.
|
|
*/
|
|
int isInit; /* True if initialized */
|
|
int separateCache; /* Use a new PGroup for each PCache */
|
|
int nInitPage; /* Initial bulk allocation size */
|
|
int szSlot; /* Size of each free slot */
|
|
int nSlot; /* The number of pcache slots */
|
|
int nReserve; /* Try to keep nFreeSlot above this */
|
|
void *pStart, *pEnd; /* Bounds of global page cache memory */
|
|
/* Above requires no mutex. Use mutex below for variable that follow. */
|
|
sqlite3_mutex *mutex; /* Mutex for accessing the following: */
|
|
PgFreeslot *pFree; /* Free page blocks */
|
|
int nFreeSlot; /* Number of unused pcache slots */
|
|
/* The following value requires a mutex to change. We skip the mutex on
|
|
** reading because (1) most platforms read a 32-bit integer atomically and
|
|
** (2) even if an incorrect value is read, no great harm is done since this
|
|
** is really just an optimization. */
|
|
int bUnderPressure; /* True if low on PAGECACHE memory */
|
|
} pcache1_g;
|
|
|
|
/*
|
|
** All code in this file should access the global structure above via the
|
|
** alias "pcache1". This ensures that the WSD emulation is used when
|
|
** compiling for systems that do not support real WSD.
|
|
*/
|
|
#define pcache1 (GLOBAL(struct PCacheGlobal, pcache1_g))
|
|
|
|
/*
|
|
** Macros to enter and leave the PCache LRU mutex.
|
|
*/
|
|
#if !defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) || SQLITE_THREADSAFE==0
|
|
# define pcache1EnterMutex(X) assert((X)->mutex==0)
|
|
# define pcache1LeaveMutex(X) assert((X)->mutex==0)
|
|
# define PCACHE1_MIGHT_USE_GROUP_MUTEX 0
|
|
#else
|
|
# define pcache1EnterMutex(X) sqlite3_mutex_enter((X)->mutex)
|
|
# define pcache1LeaveMutex(X) sqlite3_mutex_leave((X)->mutex)
|
|
# define PCACHE1_MIGHT_USE_GROUP_MUTEX 1
|
|
#endif
|
|
|
|
/******************************************************************************/
|
|
/******** Page Allocation/SQLITE_CONFIG_PCACHE Related Functions **************/
|
|
|
|
|
|
/*
|
|
** This function is called during initialization if a static buffer is
|
|
** supplied to use for the page-cache by passing the SQLITE_CONFIG_PAGECACHE
|
|
** verb to sqlite3_config(). Parameter pBuf points to an allocation large
|
|
** enough to contain 'n' buffers of 'sz' bytes each.
|
|
**
|
|
** This routine is called from sqlite3_initialize() and so it is guaranteed
|
|
** to be serialized already. There is no need for further mutexing.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
|
|
if( pcache1.isInit ){
|
|
PgFreeslot *p;
|
|
if( pBuf==0 ) sz = n = 0;
|
|
if( n==0 ) sz = 0;
|
|
sz = ROUNDDOWN8(sz);
|
|
pcache1.szSlot = sz;
|
|
pcache1.nSlot = pcache1.nFreeSlot = n;
|
|
pcache1.nReserve = n>90 ? 10 : (n/10 + 1);
|
|
pcache1.pStart = pBuf;
|
|
pcache1.pFree = 0;
|
|
pcache1.bUnderPressure = 0;
|
|
while( n-- ){
|
|
p = (PgFreeslot*)pBuf;
|
|
p->pNext = pcache1.pFree;
|
|
pcache1.pFree = p;
|
|
pBuf = (void*)&((char*)pBuf)[sz];
|
|
}
|
|
pcache1.pEnd = pBuf;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Try to initialize the pCache->pFree and pCache->pBulk fields. Return
|
|
** true if pCache->pFree ends up containing one or more free pages.
|
|
*/
|
|
static int pcache1InitBulk(PCache1 *pCache){
|
|
i64 szBulk;
|
|
char *zBulk;
|
|
if( pcache1.nInitPage==0 ) return 0;
|
|
/* Do not bother with a bulk allocation if the cache size very small */
|
|
if( pCache->nMax<3 ) return 0;
|
|
sqlite3BeginBenignMalloc();
|
|
if( pcache1.nInitPage>0 ){
|
|
szBulk = pCache->szAlloc * (i64)pcache1.nInitPage;
|
|
}else{
|
|
szBulk = -1024 * (i64)pcache1.nInitPage;
|
|
}
|
|
if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){
|
|
szBulk = pCache->szAlloc*(i64)pCache->nMax;
|
|
}
|
|
zBulk = pCache->pBulk = sqlite3Malloc( szBulk );
|
|
sqlite3EndBenignMalloc();
|
|
if( zBulk ){
|
|
int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc;
|
|
do{
|
|
PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage];
|
|
pX->page.pBuf = zBulk;
|
|
pX->page.pExtra = &pX[1];
|
|
pX->isBulkLocal = 1;
|
|
pX->isAnchor = 0;
|
|
pX->pNext = pCache->pFree;
|
|
pX->pLruPrev = 0; /* Initializing this saves a valgrind error */
|
|
pCache->pFree = pX;
|
|
zBulk += pCache->szAlloc;
|
|
}while( --nBulk );
|
|
}
|
|
return pCache->pFree!=0;
|
|
}
|
|
|
|
/*
|
|
** Malloc function used within this file to allocate space from the buffer
|
|
** configured using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no
|
|
** such buffer exists or there is no space left in it, this function falls
|
|
** back to sqlite3Malloc().
|
|
**
|
|
** Multiple threads can run this routine at the same time. Global variables
|
|
** in pcache1 need to be protected via mutex.
|
|
*/
|
|
static void *pcache1Alloc(int nByte){
|
|
void *p = 0;
|
|
assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
|
|
if( nByte<=pcache1.szSlot ){
|
|
sqlite3_mutex_enter(pcache1.mutex);
|
|
p = (PgHdr1 *)pcache1.pFree;
|
|
if( p ){
|
|
pcache1.pFree = pcache1.pFree->pNext;
|
|
pcache1.nFreeSlot--;
|
|
pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
|
|
assert( pcache1.nFreeSlot>=0 );
|
|
sqlite3StatusHighwater(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
|
|
sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_USED, 1);
|
|
}
|
|
sqlite3_mutex_leave(pcache1.mutex);
|
|
}
|
|
if( p==0 ){
|
|
/* Memory is not available in the SQLITE_CONFIG_PAGECACHE pool. Get
|
|
** it from sqlite3Malloc instead.
|
|
*/
|
|
p = sqlite3Malloc(nByte);
|
|
#ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
|
|
if( p ){
|
|
int sz = sqlite3MallocSize(p);
|
|
sqlite3_mutex_enter(pcache1.mutex);
|
|
sqlite3StatusHighwater(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
|
|
sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
|
|
sqlite3_mutex_leave(pcache1.mutex);
|
|
}
|
|
#endif
|
|
sqlite3MemdebugSetType(p, MEMTYPE_PCACHE);
|
|
}
|
|
return p;
|
|
}
|
|
|
|
/*
|
|
** Free an allocated buffer obtained from pcache1Alloc().
|
|
*/
|
|
static void pcache1Free(void *p){
|
|
if( p==0 ) return;
|
|
if( SQLITE_WITHIN(p, pcache1.pStart, pcache1.pEnd) ){
|
|
PgFreeslot *pSlot;
|
|
sqlite3_mutex_enter(pcache1.mutex);
|
|
sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_USED, 1);
|
|
pSlot = (PgFreeslot*)p;
|
|
pSlot->pNext = pcache1.pFree;
|
|
pcache1.pFree = pSlot;
|
|
pcache1.nFreeSlot++;
|
|
pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
|
|
assert( pcache1.nFreeSlot<=pcache1.nSlot );
|
|
sqlite3_mutex_leave(pcache1.mutex);
|
|
}else{
|
|
assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) );
|
|
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
|
|
#ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
|
|
{
|
|
int nFreed = 0;
|
|
nFreed = sqlite3MallocSize(p);
|
|
sqlite3_mutex_enter(pcache1.mutex);
|
|
sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_OVERFLOW, nFreed);
|
|
sqlite3_mutex_leave(pcache1.mutex);
|
|
}
|
|
#endif
|
|
sqlite3_free(p);
|
|
}
|
|
}
|
|
|
|
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
|
/*
|
|
** Return the size of a pcache allocation
|
|
*/
|
|
static int pcache1MemSize(void *p){
|
|
if( p>=pcache1.pStart && p<pcache1.pEnd ){
|
|
return pcache1.szSlot;
|
|
}else{
|
|
int iSize;
|
|
assert( sqlite3MemdebugHasType(p, MEMTYPE_PCACHE) );
|
|
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
|
|
iSize = sqlite3MallocSize(p);
|
|
sqlite3MemdebugSetType(p, MEMTYPE_PCACHE);
|
|
return iSize;
|
|
}
|
|
}
|
|
#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
|
|
|
|
/*
|
|
** Allocate a new page object initially associated with cache pCache.
|
|
*/
|
|
static PgHdr1 *pcache1AllocPage(PCache1 *pCache, int benignMalloc){
|
|
PgHdr1 *p = 0;
|
|
void *pPg;
|
|
|
|
assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
|
|
if( pCache->pFree || (pCache->nPage==0 && pcache1InitBulk(pCache)) ){
|
|
assert( pCache->pFree!=0 );
|
|
p = pCache->pFree;
|
|
pCache->pFree = p->pNext;
|
|
p->pNext = 0;
|
|
}else{
|
|
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
|
/* The group mutex must be released before pcache1Alloc() is called. This
|
|
** is because it might call sqlite3_release_memory(), which assumes that
|
|
** this mutex is not held. */
|
|
assert( pcache1.separateCache==0 );
|
|
assert( pCache->pGroup==&pcache1.grp );
|
|
pcache1LeaveMutex(pCache->pGroup);
|
|
#endif
|
|
if( benignMalloc ){ sqlite3BeginBenignMalloc(); }
|
|
pPg = pcache1Alloc(pCache->szAlloc);
|
|
if( benignMalloc ){ sqlite3EndBenignMalloc(); }
|
|
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
|
pcache1EnterMutex(pCache->pGroup);
|
|
#endif
|
|
if( pPg==0 ) return 0;
|
|
p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
|
|
p->page.pBuf = pPg;
|
|
p->page.pExtra = &p[1];
|
|
p->isBulkLocal = 0;
|
|
p->isAnchor = 0;
|
|
p->pLruPrev = 0; /* Initializing this saves a valgrind error */
|
|
}
|
|
(*pCache->pnPurgeable)++;
|
|
return p;
|
|
}
|
|
|
|
/*
|
|
** Free a page object allocated by pcache1AllocPage().
|
|
*/
|
|
static void pcache1FreePage(PgHdr1 *p){
|
|
PCache1 *pCache;
|
|
assert( p!=0 );
|
|
pCache = p->pCache;
|
|
assert( sqlite3_mutex_held(p->pCache->pGroup->mutex) );
|
|
if( p->isBulkLocal ){
|
|
p->pNext = pCache->pFree;
|
|
pCache->pFree = p;
|
|
}else{
|
|
pcache1Free(p->page.pBuf);
|
|
}
|
|
(*pCache->pnPurgeable)--;
|
|
}
|
|
|
|
/*
|
|
** Malloc function used by SQLite to obtain space from the buffer configured
|
|
** using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no such buffer
|
|
** exists, this function falls back to sqlite3Malloc().
|
|
*/
|
|
SQLITE_PRIVATE void *sqlite3PageMalloc(int sz){
|
|
assert( sz<=65536+8 ); /* These allocations are never very large */
|
|
return pcache1Alloc(sz);
|
|
}
|
|
|
|
/*
|
|
** Free an allocated buffer obtained from sqlite3PageMalloc().
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3PageFree(void *p){
|
|
pcache1Free(p);
|
|
}
|
|
|
|
|
|
/*
|
|
** Return true if it desirable to avoid allocating a new page cache
|
|
** entry.
|
|
**
|
|
** If memory was allocated specifically to the page cache using
|
|
** SQLITE_CONFIG_PAGECACHE but that memory has all been used, then
|
|
** it is desirable to avoid allocating a new page cache entry because
|
|
** presumably SQLITE_CONFIG_PAGECACHE was suppose to be sufficient
|
|
** for all page cache needs and we should not need to spill the
|
|
** allocation onto the heap.
|
|
**
|
|
** Or, the heap is used for all page cache memory but the heap is
|
|
** under memory pressure, then again it is desirable to avoid
|
|
** allocating a new page cache entry in order to avoid stressing
|
|
** the heap even further.
|
|
*/
|
|
static int pcache1UnderMemoryPressure(PCache1 *pCache){
|
|
if( pcache1.nSlot && (pCache->szPage+pCache->szExtra)<=pcache1.szSlot ){
|
|
return pcache1.bUnderPressure;
|
|
}else{
|
|
return sqlite3HeapNearlyFull();
|
|
}
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/******** General Implementation Functions ************************************/
|
|
|
|
/*
|
|
** This function is used to resize the hash table used by the cache passed
|
|
** as the first argument.
|
|
**
|
|
** The PCache mutex must be held when this function is called.
|
|
*/
|
|
static void pcache1ResizeHash(PCache1 *p){
|
|
PgHdr1 **apNew;
|
|
unsigned int nNew;
|
|
unsigned int i;
|
|
|
|
assert( sqlite3_mutex_held(p->pGroup->mutex) );
|
|
|
|
nNew = p->nHash*2;
|
|
if( nNew<256 ){
|
|
nNew = 256;
|
|
}
|
|
|
|
pcache1LeaveMutex(p->pGroup);
|
|
if( p->nHash ){ sqlite3BeginBenignMalloc(); }
|
|
apNew = (PgHdr1 **)sqlite3MallocZero(sizeof(PgHdr1 *)*nNew);
|
|
if( p->nHash ){ sqlite3EndBenignMalloc(); }
|
|
pcache1EnterMutex(p->pGroup);
|
|
if( apNew ){
|
|
for(i=0; i<p->nHash; i++){
|
|
PgHdr1 *pPage;
|
|
PgHdr1 *pNext = p->apHash[i];
|
|
while( (pPage = pNext)!=0 ){
|
|
unsigned int h = pPage->iKey % nNew;
|
|
pNext = pPage->pNext;
|
|
pPage->pNext = apNew[h];
|
|
apNew[h] = pPage;
|
|
}
|
|
}
|
|
sqlite3_free(p->apHash);
|
|
p->apHash = apNew;
|
|
p->nHash = nNew;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** This function is used internally to remove the page pPage from the
|
|
** PGroup LRU list, if is part of it. If pPage is not part of the PGroup
|
|
** LRU list, then this function is a no-op.
|
|
**
|
|
** The PGroup mutex must be held when this function is called.
|
|
*/
|
|
static PgHdr1 *pcache1PinPage(PgHdr1 *pPage){
|
|
assert( pPage!=0 );
|
|
assert( PAGE_IS_UNPINNED(pPage) );
|
|
assert( pPage->pLruNext );
|
|
assert( pPage->pLruPrev );
|
|
assert( sqlite3_mutex_held(pPage->pCache->pGroup->mutex) );
|
|
pPage->pLruPrev->pLruNext = pPage->pLruNext;
|
|
pPage->pLruNext->pLruPrev = pPage->pLruPrev;
|
|
pPage->pLruNext = 0;
|
|
/* pPage->pLruPrev = 0;
|
|
** No need to clear pLruPrev as it is never accessed if pLruNext is 0 */
|
|
assert( pPage->isAnchor==0 );
|
|
assert( pPage->pCache->pGroup->lru.isAnchor==1 );
|
|
pPage->pCache->nRecyclable--;
|
|
return pPage;
|
|
}
|
|
|
|
|
|
/*
|
|
** Remove the page supplied as an argument from the hash table
|
|
** (PCache1.apHash structure) that it is currently stored in.
|
|
** Also free the page if freePage is true.
|
|
**
|
|
** The PGroup mutex must be held when this function is called.
|
|
*/
|
|
static void pcache1RemoveFromHash(PgHdr1 *pPage, int freeFlag){
|
|
unsigned int h;
|
|
PCache1 *pCache = pPage->pCache;
|
|
PgHdr1 **pp;
|
|
|
|
assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
|
|
h = pPage->iKey % pCache->nHash;
|
|
for(pp=&pCache->apHash[h]; (*pp)!=pPage; pp=&(*pp)->pNext);
|
|
*pp = (*pp)->pNext;
|
|
|
|
pCache->nPage--;
|
|
if( freeFlag ) pcache1FreePage(pPage);
|
|
}
|
|
|
|
/*
|
|
** If there are currently more than nMaxPage pages allocated, try
|
|
** to recycle pages to reduce the number allocated to nMaxPage.
|
|
*/
|
|
static void pcache1EnforceMaxPage(PCache1 *pCache){
|
|
PGroup *pGroup = pCache->pGroup;
|
|
PgHdr1 *p;
|
|
assert( sqlite3_mutex_held(pGroup->mutex) );
|
|
while( pGroup->nPurgeable>pGroup->nMaxPage
|
|
&& (p=pGroup->lru.pLruPrev)->isAnchor==0
|
|
){
|
|
assert( p->pCache->pGroup==pGroup );
|
|
assert( PAGE_IS_UNPINNED(p) );
|
|
pcache1PinPage(p);
|
|
pcache1RemoveFromHash(p, 1);
|
|
}
|
|
if( pCache->nPage==0 && pCache->pBulk ){
|
|
sqlite3_free(pCache->pBulk);
|
|
pCache->pBulk = pCache->pFree = 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Discard all pages from cache pCache with a page number (key value)
|
|
** greater than or equal to iLimit. Any pinned pages that meet this
|
|
** criteria are unpinned before they are discarded.
|
|
**
|
|
** The PCache mutex must be held when this function is called.
|
|
*/
|
|
static void pcache1TruncateUnsafe(
|
|
PCache1 *pCache, /* The cache to truncate */
|
|
unsigned int iLimit /* Drop pages with this pgno or larger */
|
|
){
|
|
TESTONLY( int nPage = 0; ) /* To assert pCache->nPage is correct */
|
|
unsigned int h, iStop;
|
|
assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
|
|
assert( pCache->iMaxKey >= iLimit );
|
|
assert( pCache->nHash > 0 );
|
|
if( pCache->iMaxKey - iLimit < pCache->nHash ){
|
|
/* If we are just shaving the last few pages off the end of the
|
|
** cache, then there is no point in scanning the entire hash table.
|
|
** Only scan those hash slots that might contain pages that need to
|
|
** be removed. */
|
|
h = iLimit % pCache->nHash;
|
|
iStop = pCache->iMaxKey % pCache->nHash;
|
|
TESTONLY( nPage = -10; ) /* Disable the pCache->nPage validity check */
|
|
}else{
|
|
/* This is the general case where many pages are being removed.
|
|
** It is necessary to scan the entire hash table */
|
|
h = pCache->nHash/2;
|
|
iStop = h - 1;
|
|
}
|
|
for(;;){
|
|
PgHdr1 **pp;
|
|
PgHdr1 *pPage;
|
|
assert( h<pCache->nHash );
|
|
pp = &pCache->apHash[h];
|
|
while( (pPage = *pp)!=0 ){
|
|
if( pPage->iKey>=iLimit ){
|
|
pCache->nPage--;
|
|
*pp = pPage->pNext;
|
|
if( PAGE_IS_UNPINNED(pPage) ) pcache1PinPage(pPage);
|
|
pcache1FreePage(pPage);
|
|
}else{
|
|
pp = &pPage->pNext;
|
|
TESTONLY( if( nPage>=0 ) nPage++; )
|
|
}
|
|
}
|
|
if( h==iStop ) break;
|
|
h = (h+1) % pCache->nHash;
|
|
}
|
|
assert( nPage<0 || pCache->nPage==(unsigned)nPage );
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/******** sqlite3_pcache Methods **********************************************/
|
|
|
|
/*
|
|
** Implementation of the sqlite3_pcache.xInit method.
|
|
*/
|
|
static int pcache1Init(void *NotUsed){
|
|
UNUSED_PARAMETER(NotUsed);
|
|
assert( pcache1.isInit==0 );
|
|
memset(&pcache1, 0, sizeof(pcache1));
|
|
|
|
|
|
/*
|
|
** The pcache1.separateCache variable is true if each PCache has its own
|
|
** private PGroup (mode-1). pcache1.separateCache is false if the single
|
|
** PGroup in pcache1.grp is used for all page caches (mode-2).
|
|
**
|
|
** * Always use a unified cache (mode-2) if ENABLE_MEMORY_MANAGEMENT
|
|
**
|
|
** * Use a unified cache in single-threaded applications that have
|
|
** configured a start-time buffer for use as page-cache memory using
|
|
** sqlite3_config(SQLITE_CONFIG_PAGECACHE, pBuf, sz, N) with non-NULL
|
|
** pBuf argument.
|
|
**
|
|
** * Otherwise use separate caches (mode-1)
|
|
*/
|
|
#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT)
|
|
pcache1.separateCache = 0;
|
|
#elif SQLITE_THREADSAFE
|
|
pcache1.separateCache = sqlite3GlobalConfig.pPage==0
|
|
|| sqlite3GlobalConfig.bCoreMutex>0;
|
|
#else
|
|
pcache1.separateCache = sqlite3GlobalConfig.pPage==0;
|
|
#endif
|
|
|
|
#if SQLITE_THREADSAFE
|
|
if( sqlite3GlobalConfig.bCoreMutex ){
|
|
pcache1.grp.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_LRU);
|
|
pcache1.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PMEM);
|
|
}
|
|
#endif
|
|
if( pcache1.separateCache
|
|
&& sqlite3GlobalConfig.nPage!=0
|
|
&& sqlite3GlobalConfig.pPage==0
|
|
){
|
|
pcache1.nInitPage = sqlite3GlobalConfig.nPage;
|
|
}else{
|
|
pcache1.nInitPage = 0;
|
|
}
|
|
pcache1.grp.mxPinned = 10;
|
|
pcache1.isInit = 1;
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Implementation of the sqlite3_pcache.xShutdown method.
|
|
** Note that the static mutex allocated in xInit does
|
|
** not need to be freed.
|
|
*/
|
|
static void pcache1Shutdown(void *NotUsed){
|
|
UNUSED_PARAMETER(NotUsed);
|
|
assert( pcache1.isInit!=0 );
|
|
memset(&pcache1, 0, sizeof(pcache1));
|
|
}
|
|
|
|
/* forward declaration */
|
|
static void pcache1Destroy(sqlite3_pcache *p);
|
|
|
|
/*
|
|
** Implementation of the sqlite3_pcache.xCreate method.
|
|
**
|
|
** Allocate a new cache.
|
|
*/
|
|
static sqlite3_pcache *pcache1Create(int szPage, int szExtra, int bPurgeable){
|
|
PCache1 *pCache; /* The newly created page cache */
|
|
PGroup *pGroup; /* The group the new page cache will belong to */
|
|
int sz; /* Bytes of memory required to allocate the new cache */
|
|
|
|
assert( (szPage & (szPage-1))==0 && szPage>=512 && szPage<=65536 );
|
|
assert( szExtra < 300 );
|
|
|
|
sz = sizeof(PCache1) + sizeof(PGroup)*pcache1.separateCache;
|
|
pCache = (PCache1 *)sqlite3MallocZero(sz);
|
|
if( pCache ){
|
|
if( pcache1.separateCache ){
|
|
pGroup = (PGroup*)&pCache[1];
|
|
pGroup->mxPinned = 10;
|
|
}else{
|
|
pGroup = &pcache1.grp;
|
|
}
|
|
pcache1EnterMutex(pGroup);
|
|
if( pGroup->lru.isAnchor==0 ){
|
|
pGroup->lru.isAnchor = 1;
|
|
pGroup->lru.pLruPrev = pGroup->lru.pLruNext = &pGroup->lru;
|
|
}
|
|
pCache->pGroup = pGroup;
|
|
pCache->szPage = szPage;
|
|
pCache->szExtra = szExtra;
|
|
pCache->szAlloc = szPage + szExtra + ROUND8(sizeof(PgHdr1));
|
|
pCache->bPurgeable = (bPurgeable ? 1 : 0);
|
|
pcache1ResizeHash(pCache);
|
|
if( bPurgeable ){
|
|
pCache->nMin = 10;
|
|
pGroup->nMinPage += pCache->nMin;
|
|
pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
|
|
pCache->pnPurgeable = &pGroup->nPurgeable;
|
|
}else{
|
|
pCache->pnPurgeable = &pCache->nPurgeableDummy;
|
|
}
|
|
pcache1LeaveMutex(pGroup);
|
|
if( pCache->nHash==0 ){
|
|
pcache1Destroy((sqlite3_pcache*)pCache);
|
|
pCache = 0;
|
|
}
|
|
}
|
|
return (sqlite3_pcache *)pCache;
|
|
}
|
|
|
|
/*
|
|
** Implementation of the sqlite3_pcache.xCachesize method.
|
|
**
|
|
** Configure the cache_size limit for a cache.
|
|
*/
|
|
static void pcache1Cachesize(sqlite3_pcache *p, int nMax){
|
|
PCache1 *pCache = (PCache1 *)p;
|
|
u32 n;
|
|
assert( nMax>=0 );
|
|
if( pCache->bPurgeable ){
|
|
PGroup *pGroup = pCache->pGroup;
|
|
pcache1EnterMutex(pGroup);
|
|
n = (u32)nMax;
|
|
if( n > 0x7fff0000 - pGroup->nMaxPage + pCache->nMax ){
|
|
n = 0x7fff0000 - pGroup->nMaxPage + pCache->nMax;
|
|
}
|
|
pGroup->nMaxPage += (n - pCache->nMax);
|
|
pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
|
|
pCache->nMax = n;
|
|
pCache->n90pct = pCache->nMax*9/10;
|
|
pcache1EnforceMaxPage(pCache);
|
|
pcache1LeaveMutex(pGroup);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Implementation of the sqlite3_pcache.xShrink method.
|
|
**
|
|
** Free up as much memory as possible.
|
|
*/
|
|
static void pcache1Shrink(sqlite3_pcache *p){
|
|
PCache1 *pCache = (PCache1*)p;
|
|
if( pCache->bPurgeable ){
|
|
PGroup *pGroup = pCache->pGroup;
|
|
unsigned int savedMaxPage;
|
|
pcache1EnterMutex(pGroup);
|
|
savedMaxPage = pGroup->nMaxPage;
|
|
pGroup->nMaxPage = 0;
|
|
pcache1EnforceMaxPage(pCache);
|
|
pGroup->nMaxPage = savedMaxPage;
|
|
pcache1LeaveMutex(pGroup);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Implementation of the sqlite3_pcache.xPagecount method.
|
|
*/
|
|
static int pcache1Pagecount(sqlite3_pcache *p){
|
|
int n;
|
|
PCache1 *pCache = (PCache1*)p;
|
|
pcache1EnterMutex(pCache->pGroup);
|
|
n = pCache->nPage;
|
|
pcache1LeaveMutex(pCache->pGroup);
|
|
return n;
|
|
}
|
|
|
|
|
|
/*
|
|
** Implement steps 3, 4, and 5 of the pcache1Fetch() algorithm described
|
|
** in the header of the pcache1Fetch() procedure.
|
|
**
|
|
** This steps are broken out into a separate procedure because they are
|
|
** usually not needed, and by avoiding the stack initialization required
|
|
** for these steps, the main pcache1Fetch() procedure can run faster.
|
|
*/
|
|
static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
|
|
PCache1 *pCache,
|
|
unsigned int iKey,
|
|
int createFlag
|
|
){
|
|
unsigned int nPinned;
|
|
PGroup *pGroup = pCache->pGroup;
|
|
PgHdr1 *pPage = 0;
|
|
|
|
/* Step 3: Abort if createFlag is 1 but the cache is nearly full */
|
|
assert( pCache->nPage >= pCache->nRecyclable );
|
|
nPinned = pCache->nPage - pCache->nRecyclable;
|
|
assert( pGroup->mxPinned == pGroup->nMaxPage + 10 - pGroup->nMinPage );
|
|
assert( pCache->n90pct == pCache->nMax*9/10 );
|
|
if( createFlag==1 && (
|
|
nPinned>=pGroup->mxPinned
|
|
|| nPinned>=pCache->n90pct
|
|
|| (pcache1UnderMemoryPressure(pCache) && pCache->nRecyclable<nPinned)
|
|
)){
|
|
return 0;
|
|
}
|
|
|
|
if( pCache->nPage>=pCache->nHash ) pcache1ResizeHash(pCache);
|
|
assert( pCache->nHash>0 && pCache->apHash );
|
|
|
|
/* Step 4. Try to recycle a page. */
|
|
if( pCache->bPurgeable
|
|
&& !pGroup->lru.pLruPrev->isAnchor
|
|
&& ((pCache->nPage+1>=pCache->nMax) || pcache1UnderMemoryPressure(pCache))
|
|
){
|
|
PCache1 *pOther;
|
|
pPage = pGroup->lru.pLruPrev;
|
|
assert( PAGE_IS_UNPINNED(pPage) );
|
|
pcache1RemoveFromHash(pPage, 0);
|
|
pcache1PinPage(pPage);
|
|
pOther = pPage->pCache;
|
|
if( pOther->szAlloc != pCache->szAlloc ){
|
|
pcache1FreePage(pPage);
|
|
pPage = 0;
|
|
}else{
|
|
pGroup->nPurgeable -= (pOther->bPurgeable - pCache->bPurgeable);
|
|
}
|
|
}
|
|
|
|
/* Step 5. If a usable page buffer has still not been found,
|
|
** attempt to allocate a new one.
|
|
*/
|
|
if( !pPage ){
|
|
pPage = pcache1AllocPage(pCache, createFlag==1);
|
|
}
|
|
|
|
if( pPage ){
|
|
unsigned int h = iKey % pCache->nHash;
|
|
pCache->nPage++;
|
|
pPage->iKey = iKey;
|
|
pPage->pNext = pCache->apHash[h];
|
|
pPage->pCache = pCache;
|
|
pPage->pLruNext = 0;
|
|
/* pPage->pLruPrev = 0;
|
|
** No need to clear pLruPrev since it is not accessed when pLruNext==0 */
|
|
*(void **)pPage->page.pExtra = 0;
|
|
pCache->apHash[h] = pPage;
|
|
if( iKey>pCache->iMaxKey ){
|
|
pCache->iMaxKey = iKey;
|
|
}
|
|
}
|
|
return pPage;
|
|
}
|
|
|
|
/*
|
|
** Implementation of the sqlite3_pcache.xFetch method.
|
|
**
|
|
** Fetch a page by key value.
|
|
**
|
|
** Whether or not a new page may be allocated by this function depends on
|
|
** the value of the createFlag argument. 0 means do not allocate a new
|
|
** page. 1 means allocate a new page if space is easily available. 2
|
|
** means to try really hard to allocate a new page.
|
|
**
|
|
** For a non-purgeable cache (a cache used as the storage for an in-memory
|
|
** database) there is really no difference between createFlag 1 and 2. So
|
|
** the calling function (pcache.c) will never have a createFlag of 1 on
|
|
** a non-purgeable cache.
|
|
**
|
|
** There are three different approaches to obtaining space for a page,
|
|
** depending on the value of parameter createFlag (which may be 0, 1 or 2).
|
|
**
|
|
** 1. Regardless of the value of createFlag, the cache is searched for a
|
|
** copy of the requested page. If one is found, it is returned.
|
|
**
|
|
** 2. If createFlag==0 and the page is not already in the cache, NULL is
|
|
** returned.
|
|
**
|
|
** 3. If createFlag is 1, and the page is not already in the cache, then
|
|
** return NULL (do not allocate a new page) if any of the following
|
|
** conditions are true:
|
|
**
|
|
** (a) the number of pages pinned by the cache is greater than
|
|
** PCache1.nMax, or
|
|
**
|
|
** (b) the number of pages pinned by the cache is greater than
|
|
** the sum of nMax for all purgeable caches, less the sum of
|
|
** nMin for all other purgeable caches, or
|
|
**
|
|
** 4. If none of the first three conditions apply and the cache is marked
|
|
** as purgeable, and if one of the following is true:
|
|
**
|
|
** (a) The number of pages allocated for the cache is already
|
|
** PCache1.nMax, or
|
|
**
|
|
** (b) The number of pages allocated for all purgeable caches is
|
|
** already equal to or greater than the sum of nMax for all
|
|
** purgeable caches,
|
|
**
|
|
** (c) The system is under memory pressure and wants to avoid
|
|
** unnecessary pages cache entry allocations
|
|
**
|
|
** then attempt to recycle a page from the LRU list. If it is the right
|
|
** size, return the recycled buffer. Otherwise, free the buffer and
|
|
** proceed to step 5.
|
|
**
|
|
** 5. Otherwise, allocate and return a new page buffer.
|
|
**
|
|
** There are two versions of this routine. pcache1FetchWithMutex() is
|
|
** the general case. pcache1FetchNoMutex() is a faster implementation for
|
|
** the common case where pGroup->mutex is NULL. The pcache1Fetch() wrapper
|
|
** invokes the appropriate routine.
|
|
*/
|
|
static PgHdr1 *pcache1FetchNoMutex(
|
|
sqlite3_pcache *p,
|
|
unsigned int iKey,
|
|
int createFlag
|
|
){
|
|
PCache1 *pCache = (PCache1 *)p;
|
|
PgHdr1 *pPage = 0;
|
|
|
|
/* Step 1: Search the hash table for an existing entry. */
|
|
pPage = pCache->apHash[iKey % pCache->nHash];
|
|
while( pPage && pPage->iKey!=iKey ){ pPage = pPage->pNext; }
|
|
|
|
/* Step 2: If the page was found in the hash table, then return it.
|
|
** If the page was not in the hash table and createFlag is 0, abort.
|
|
** Otherwise (page not in hash and createFlag!=0) continue with
|
|
** subsequent steps to try to create the page. */
|
|
if( pPage ){
|
|
if( PAGE_IS_UNPINNED(pPage) ){
|
|
return pcache1PinPage(pPage);
|
|
}else{
|
|
return pPage;
|
|
}
|
|
}else if( createFlag ){
|
|
/* Steps 3, 4, and 5 implemented by this subroutine */
|
|
return pcache1FetchStage2(pCache, iKey, createFlag);
|
|
}else{
|
|
return 0;
|
|
}
|
|
}
|
|
#if PCACHE1_MIGHT_USE_GROUP_MUTEX
|
|
static PgHdr1 *pcache1FetchWithMutex(
|
|
sqlite3_pcache *p,
|
|
unsigned int iKey,
|
|
int createFlag
|
|
){
|
|
PCache1 *pCache = (PCache1 *)p;
|
|
PgHdr1 *pPage;
|
|
|
|
pcache1EnterMutex(pCache->pGroup);
|
|
pPage = pcache1FetchNoMutex(p, iKey, createFlag);
|
|
assert( pPage==0 || pCache->iMaxKey>=iKey );
|
|
pcache1LeaveMutex(pCache->pGroup);
|
|
return pPage;
|
|
}
|
|
#endif
|
|
static sqlite3_pcache_page *pcache1Fetch(
|
|
sqlite3_pcache *p,
|
|
unsigned int iKey,
|
|
int createFlag
|
|
){
|
|
#if PCACHE1_MIGHT_USE_GROUP_MUTEX || defined(SQLITE_DEBUG)
|
|
PCache1 *pCache = (PCache1 *)p;
|
|
#endif
|
|
|
|
assert( offsetof(PgHdr1,page)==0 );
|
|
assert( pCache->bPurgeable || createFlag!=1 );
|
|
assert( pCache->bPurgeable || pCache->nMin==0 );
|
|
assert( pCache->bPurgeable==0 || pCache->nMin==10 );
|
|
assert( pCache->nMin==0 || pCache->bPurgeable );
|
|
assert( pCache->nHash>0 );
|
|
#if PCACHE1_MIGHT_USE_GROUP_MUTEX
|
|
if( pCache->pGroup->mutex ){
|
|
return (sqlite3_pcache_page*)pcache1FetchWithMutex(p, iKey, createFlag);
|
|
}else
|
|
#endif
|
|
{
|
|
return (sqlite3_pcache_page*)pcache1FetchNoMutex(p, iKey, createFlag);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
** Implementation of the sqlite3_pcache.xUnpin method.
|
|
**
|
|
** Mark a page as unpinned (eligible for asynchronous recycling).
|
|
*/
|
|
static void pcache1Unpin(
|
|
sqlite3_pcache *p,
|
|
sqlite3_pcache_page *pPg,
|
|
int reuseUnlikely
|
|
){
|
|
PCache1 *pCache = (PCache1 *)p;
|
|
PgHdr1 *pPage = (PgHdr1 *)pPg;
|
|
PGroup *pGroup = pCache->pGroup;
|
|
|
|
assert( pPage->pCache==pCache );
|
|
pcache1EnterMutex(pGroup);
|
|
|
|
/* It is an error to call this function if the page is already
|
|
** part of the PGroup LRU list.
|
|
*/
|
|
assert( pPage->pLruNext==0 );
|
|
assert( PAGE_IS_PINNED(pPage) );
|
|
|
|
if( reuseUnlikely || pGroup->nPurgeable>pGroup->nMaxPage ){
|
|
pcache1RemoveFromHash(pPage, 1);
|
|
}else{
|
|
/* Add the page to the PGroup LRU list. */
|
|
PgHdr1 **ppFirst = &pGroup->lru.pLruNext;
|
|
pPage->pLruPrev = &pGroup->lru;
|
|
(pPage->pLruNext = *ppFirst)->pLruPrev = pPage;
|
|
*ppFirst = pPage;
|
|
pCache->nRecyclable++;
|
|
}
|
|
|
|
pcache1LeaveMutex(pCache->pGroup);
|
|
}
|
|
|
|
/*
|
|
** Implementation of the sqlite3_pcache.xRekey method.
|
|
*/
|
|
static void pcache1Rekey(
|
|
sqlite3_pcache *p,
|
|
sqlite3_pcache_page *pPg,
|
|
unsigned int iOld,
|
|
unsigned int iNew
|
|
){
|
|
PCache1 *pCache = (PCache1 *)p;
|
|
PgHdr1 *pPage = (PgHdr1 *)pPg;
|
|
PgHdr1 **pp;
|
|
unsigned int hOld, hNew;
|
|
assert( pPage->iKey==iOld );
|
|
assert( pPage->pCache==pCache );
|
|
assert( iOld!=iNew ); /* The page number really is changing */
|
|
|
|
pcache1EnterMutex(pCache->pGroup);
|
|
|
|
assert( pcache1FetchNoMutex(p, iOld, 0)==pPage ); /* pPg really is iOld */
|
|
hOld = iOld%pCache->nHash;
|
|
pp = &pCache->apHash[hOld];
|
|
while( (*pp)!=pPage ){
|
|
pp = &(*pp)->pNext;
|
|
}
|
|
*pp = pPage->pNext;
|
|
|
|
assert( pcache1FetchNoMutex(p, iNew, 0)==0 ); /* iNew not in cache */
|
|
hNew = iNew%pCache->nHash;
|
|
pPage->iKey = iNew;
|
|
pPage->pNext = pCache->apHash[hNew];
|
|
pCache->apHash[hNew] = pPage;
|
|
if( iNew>pCache->iMaxKey ){
|
|
pCache->iMaxKey = iNew;
|
|
}
|
|
|
|
pcache1LeaveMutex(pCache->pGroup);
|
|
}
|
|
|
|
/*
|
|
** Implementation of the sqlite3_pcache.xTruncate method.
|
|
**
|
|
** Discard all unpinned pages in the cache with a page number equal to
|
|
** or greater than parameter iLimit. Any pinned pages with a page number
|
|
** equal to or greater than iLimit are implicitly unpinned.
|
|
*/
|
|
static void pcache1Truncate(sqlite3_pcache *p, unsigned int iLimit){
|
|
PCache1 *pCache = (PCache1 *)p;
|
|
pcache1EnterMutex(pCache->pGroup);
|
|
if( iLimit<=pCache->iMaxKey ){
|
|
pcache1TruncateUnsafe(pCache, iLimit);
|
|
pCache->iMaxKey = iLimit-1;
|
|
}
|
|
pcache1LeaveMutex(pCache->pGroup);
|
|
}
|
|
|
|
/*
|
|
** Implementation of the sqlite3_pcache.xDestroy method.
|
|
**
|
|
** Destroy a cache allocated using pcache1Create().
|
|
*/
|
|
static void pcache1Destroy(sqlite3_pcache *p){
|
|
PCache1 *pCache = (PCache1 *)p;
|
|
PGroup *pGroup = pCache->pGroup;
|
|
assert( pCache->bPurgeable || (pCache->nMax==0 && pCache->nMin==0) );
|
|
pcache1EnterMutex(pGroup);
|
|
if( pCache->nPage ) pcache1TruncateUnsafe(pCache, 0);
|
|
assert( pGroup->nMaxPage >= pCache->nMax );
|
|
pGroup->nMaxPage -= pCache->nMax;
|
|
assert( pGroup->nMinPage >= pCache->nMin );
|
|
pGroup->nMinPage -= pCache->nMin;
|
|
pGroup->mxPinned = pGroup->nMaxPage + 10 - pGroup->nMinPage;
|
|
pcache1EnforceMaxPage(pCache);
|
|
pcache1LeaveMutex(pGroup);
|
|
sqlite3_free(pCache->pBulk);
|
|
sqlite3_free(pCache->apHash);
|
|
sqlite3_free(pCache);
|
|
}
|
|
|
|
/*
|
|
** This function is called during initialization (sqlite3_initialize()) to
|
|
** install the default pluggable cache module, assuming the user has not
|
|
** already provided an alternative.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3PCacheSetDefault(void){
|
|
static const sqlite3_pcache_methods2 defaultMethods = {
|
|
1, /* iVersion */
|
|
0, /* pArg */
|
|
pcache1Init, /* xInit */
|
|
pcache1Shutdown, /* xShutdown */
|
|
pcache1Create, /* xCreate */
|
|
pcache1Cachesize, /* xCachesize */
|
|
pcache1Pagecount, /* xPagecount */
|
|
pcache1Fetch, /* xFetch */
|
|
pcache1Unpin, /* xUnpin */
|
|
pcache1Rekey, /* xRekey */
|
|
pcache1Truncate, /* xTruncate */
|
|
pcache1Destroy, /* xDestroy */
|
|
pcache1Shrink /* xShrink */
|
|
};
|
|
sqlite3_config(SQLITE_CONFIG_PCACHE2, &defaultMethods);
|
|
}
|
|
|
|
/*
|
|
** Return the size of the header on each page of this PCACHE implementation.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3HeaderSizePcache1(void){ return ROUND8(sizeof(PgHdr1)); }
|
|
|
|
/*
|
|
** Return the global mutex used by this PCACHE implementation. The
|
|
** sqlite3_status() routine needs access to this mutex.
|
|
*/
|
|
SQLITE_PRIVATE sqlite3_mutex *sqlite3Pcache1Mutex(void){
|
|
return pcache1.mutex;
|
|
}
|
|
|
|
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
|
/*
|
|
** 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 sqlite3_free()ed.
|
|
**
|
|
** nReq is the number of bytes of memory required. Once this much has
|
|
** been released, the function returns. The return value is the total number
|
|
** of bytes of memory released.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){
|
|
int nFree = 0;
|
|
assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
|
|
assert( sqlite3_mutex_notheld(pcache1.mutex) );
|
|
if( sqlite3GlobalConfig.pPage==0 ){
|
|
PgHdr1 *p;
|
|
pcache1EnterMutex(&pcache1.grp);
|
|
while( (nReq<0 || nFree<nReq)
|
|
&& (p=pcache1.grp.lru.pLruPrev)!=0
|
|
&& p->isAnchor==0
|
|
){
|
|
nFree += pcache1MemSize(p->page.pBuf);
|
|
assert( PAGE_IS_UNPINNED(p) );
|
|
pcache1PinPage(p);
|
|
pcache1RemoveFromHash(p, 1);
|
|
}
|
|
pcache1LeaveMutex(&pcache1.grp);
|
|
}
|
|
return nFree;
|
|
}
|
|
#endif /* SQLITE_ENABLE_MEMORY_MANAGEMENT */
|
|
|
|
#ifdef SQLITE_TEST
|
|
/*
|
|
** This function is used by test procedures to inspect the internal state
|
|
** of the global cache.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3PcacheStats(
|
|
int *pnCurrent, /* OUT: Total number of pages cached */
|
|
int *pnMax, /* OUT: Global maximum cache size */
|
|
int *pnMin, /* OUT: Sum of PCache1.nMin for purgeable caches */
|
|
int *pnRecyclable /* OUT: Total number of pages available for recycling */
|
|
){
|
|
PgHdr1 *p;
|
|
int nRecyclable = 0;
|
|
for(p=pcache1.grp.lru.pLruNext; p && !p->isAnchor; p=p->pLruNext){
|
|
assert( PAGE_IS_UNPINNED(p) );
|
|
nRecyclable++;
|
|
}
|
|
*pnCurrent = pcache1.grp.nPurgeable;
|
|
*pnMax = (int)pcache1.grp.nMaxPage;
|
|
*pnMin = (int)pcache1.grp.nMinPage;
|
|
*pnRecyclable = nRecyclable;
|
|
}
|
|
#endif
|
|
|
|
/************** End of pcache1.c *********************************************/
|
|
/************** Begin file rowset.c ******************************************/
|
|
/*
|
|
** 2008 December 3
|
|
**
|
|
** 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 module implements an object we call a "RowSet".
|
|
**
|
|
** The RowSet object is a collection of rowids. Rowids
|
|
** are inserted into the RowSet in an arbitrary order. Inserts
|
|
** can be intermixed with tests to see if a given rowid has been
|
|
** previously inserted into the RowSet.
|
|
**
|
|
** After all inserts are finished, it is possible to extract the
|
|
** elements of the RowSet in sorted order. Once this extraction
|
|
** process has started, no new elements may be inserted.
|
|
**
|
|
** Hence, the primitive operations for a RowSet are:
|
|
**
|
|
** CREATE
|
|
** INSERT
|
|
** TEST
|
|
** SMALLEST
|
|
** DESTROY
|
|
**
|
|
** The CREATE and DESTROY primitives are the constructor and destructor,
|
|
** obviously. The INSERT primitive adds a new element to the RowSet.
|
|
** TEST checks to see if an element is already in the RowSet. SMALLEST
|
|
** extracts the least value from the RowSet.
|
|
**
|
|
** The INSERT primitive might allocate additional memory. Memory is
|
|
** allocated in chunks so most INSERTs do no allocation. There is an
|
|
** upper bound on the size of allocated memory. No memory is freed
|
|
** until DESTROY.
|
|
**
|
|
** The TEST primitive includes a "batch" number. The TEST primitive
|
|
** will only see elements that were inserted before the last change
|
|
** in the batch number. In other words, if an INSERT occurs between
|
|
** two TESTs where the TESTs have the same batch number, then the
|
|
** value added by the INSERT will not be visible to the second TEST.
|
|
** The initial batch number is zero, so if the very first TEST contains
|
|
** a non-zero batch number, it will see all prior INSERTs.
|
|
**
|
|
** No INSERTs may occurs after a SMALLEST. An assertion will fail if
|
|
** that is attempted.
|
|
**
|
|
** The cost of an INSERT is roughly constant. (Sometimes new memory
|
|
** has to be allocated on an INSERT.) The cost of a TEST with a new
|
|
** batch number is O(NlogN) where N is the number of elements in the RowSet.
|
|
** The cost of a TEST using the same batch number is O(logN). The cost
|
|
** of the first SMALLEST is O(NlogN). Second and subsequent SMALLEST
|
|
** primitives are constant time. The cost of DESTROY is O(N).
|
|
**
|
|
** TEST and SMALLEST may not be used by the same RowSet. This used to
|
|
** be possible, but the feature was not used, so it was removed in order
|
|
** to simplify the code.
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
|
|
|
|
/*
|
|
** Target size for allocation chunks.
|
|
*/
|
|
#define ROWSET_ALLOCATION_SIZE 1024
|
|
|
|
/*
|
|
** The number of rowset entries per allocation chunk.
|
|
*/
|
|
#define ROWSET_ENTRY_PER_CHUNK \
|
|
((ROWSET_ALLOCATION_SIZE-8)/sizeof(struct RowSetEntry))
|
|
|
|
/*
|
|
** Each entry in a RowSet is an instance of the following object.
|
|
**
|
|
** This same object is reused to store a linked list of trees of RowSetEntry
|
|
** objects. In that alternative use, pRight points to the next entry
|
|
** in the list, pLeft points to the tree, and v is unused. The
|
|
** RowSet.pForest value points to the head of this forest list.
|
|
*/
|
|
struct RowSetEntry {
|
|
i64 v; /* ROWID value for this entry */
|
|
struct RowSetEntry *pRight; /* Right subtree (larger entries) or list */
|
|
struct RowSetEntry *pLeft; /* Left subtree (smaller entries) */
|
|
};
|
|
|
|
/*
|
|
** RowSetEntry objects are allocated in large chunks (instances of the
|
|
** following structure) to reduce memory allocation overhead. The
|
|
** chunks are kept on a linked list so that they can be deallocated
|
|
** when the RowSet is destroyed.
|
|
*/
|
|
struct RowSetChunk {
|
|
struct RowSetChunk *pNextChunk; /* Next chunk on list of them all */
|
|
struct RowSetEntry aEntry[ROWSET_ENTRY_PER_CHUNK]; /* Allocated entries */
|
|
};
|
|
|
|
/*
|
|
** A RowSet in an instance of the following structure.
|
|
**
|
|
** A typedef of this structure if found in sqliteInt.h.
|
|
*/
|
|
struct RowSet {
|
|
struct RowSetChunk *pChunk; /* List of all chunk allocations */
|
|
sqlite3 *db; /* The database connection */
|
|
struct RowSetEntry *pEntry; /* List of entries using pRight */
|
|
struct RowSetEntry *pLast; /* Last entry on the pEntry list */
|
|
struct RowSetEntry *pFresh; /* Source of new entry objects */
|
|
struct RowSetEntry *pForest; /* List of binary trees of entries */
|
|
u16 nFresh; /* Number of objects on pFresh */
|
|
u16 rsFlags; /* Various flags */
|
|
int iBatch; /* Current insert batch */
|
|
};
|
|
|
|
/*
|
|
** Allowed values for RowSet.rsFlags
|
|
*/
|
|
#define ROWSET_SORTED 0x01 /* True if RowSet.pEntry is sorted */
|
|
#define ROWSET_NEXT 0x02 /* True if sqlite3RowSetNext() has been called */
|
|
|
|
/*
|
|
** Allocate a RowSet object. Return NULL if a memory allocation
|
|
** error occurs.
|
|
*/
|
|
SQLITE_PRIVATE RowSet *sqlite3RowSetInit(sqlite3 *db){
|
|
RowSet *p = sqlite3DbMallocRawNN(db, sizeof(*p));
|
|
if( p ){
|
|
int N = sqlite3DbMallocSize(db, p);
|
|
p->pChunk = 0;
|
|
p->db = db;
|
|
p->pEntry = 0;
|
|
p->pLast = 0;
|
|
p->pForest = 0;
|
|
p->pFresh = (struct RowSetEntry*)(ROUND8(sizeof(*p)) + (char*)p);
|
|
p->nFresh = (u16)((N - ROUND8(sizeof(*p)))/sizeof(struct RowSetEntry));
|
|
p->rsFlags = ROWSET_SORTED;
|
|
p->iBatch = 0;
|
|
}
|
|
return p;
|
|
}
|
|
|
|
/*
|
|
** Deallocate all chunks from a RowSet. This frees all memory that
|
|
** the RowSet has allocated over its lifetime. This routine is
|
|
** the destructor for the RowSet.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3RowSetClear(void *pArg){
|
|
RowSet *p = (RowSet*)pArg;
|
|
struct RowSetChunk *pChunk, *pNextChunk;
|
|
for(pChunk=p->pChunk; pChunk; pChunk = pNextChunk){
|
|
pNextChunk = pChunk->pNextChunk;
|
|
sqlite3DbFree(p->db, pChunk);
|
|
}
|
|
p->pChunk = 0;
|
|
p->nFresh = 0;
|
|
p->pEntry = 0;
|
|
p->pLast = 0;
|
|
p->pForest = 0;
|
|
p->rsFlags = ROWSET_SORTED;
|
|
}
|
|
|
|
/*
|
|
** Deallocate all chunks from a RowSet. This frees all memory that
|
|
** the RowSet has allocated over its lifetime. This routine is
|
|
** the destructor for the RowSet.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3RowSetDelete(void *pArg){
|
|
sqlite3RowSetClear(pArg);
|
|
sqlite3DbFree(((RowSet*)pArg)->db, pArg);
|
|
}
|
|
|
|
/*
|
|
** Allocate a new RowSetEntry object that is associated with the
|
|
** given RowSet. Return a pointer to the new and completely uninitialized
|
|
** object.
|
|
**
|
|
** In an OOM situation, the RowSet.db->mallocFailed flag is set and this
|
|
** routine returns NULL.
|
|
*/
|
|
static struct RowSetEntry *rowSetEntryAlloc(RowSet *p){
|
|
assert( p!=0 );
|
|
if( p->nFresh==0 ){ /*OPTIMIZATION-IF-FALSE*/
|
|
/* We could allocate a fresh RowSetEntry each time one is needed, but it
|
|
** is more efficient to pull a preallocated entry from the pool */
|
|
struct RowSetChunk *pNew;
|
|
pNew = sqlite3DbMallocRawNN(p->db, sizeof(*pNew));
|
|
if( pNew==0 ){
|
|
return 0;
|
|
}
|
|
pNew->pNextChunk = p->pChunk;
|
|
p->pChunk = pNew;
|
|
p->pFresh = pNew->aEntry;
|
|
p->nFresh = ROWSET_ENTRY_PER_CHUNK;
|
|
}
|
|
p->nFresh--;
|
|
return p->pFresh++;
|
|
}
|
|
|
|
/*
|
|
** Insert a new value into a RowSet.
|
|
**
|
|
** The mallocFailed flag of the database connection is set if a
|
|
** memory allocation fails.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3RowSetInsert(RowSet *p, i64 rowid){
|
|
struct RowSetEntry *pEntry; /* The new entry */
|
|
struct RowSetEntry *pLast; /* The last prior entry */
|
|
|
|
/* This routine is never called after sqlite3RowSetNext() */
|
|
assert( p!=0 && (p->rsFlags & ROWSET_NEXT)==0 );
|
|
|
|
pEntry = rowSetEntryAlloc(p);
|
|
if( pEntry==0 ) return;
|
|
pEntry->v = rowid;
|
|
pEntry->pRight = 0;
|
|
pLast = p->pLast;
|
|
if( pLast ){
|
|
if( rowid<=pLast->v ){ /*OPTIMIZATION-IF-FALSE*/
|
|
/* Avoid unnecessary sorts by preserving the ROWSET_SORTED flags
|
|
** where possible */
|
|
p->rsFlags &= ~ROWSET_SORTED;
|
|
}
|
|
pLast->pRight = pEntry;
|
|
}else{
|
|
p->pEntry = pEntry;
|
|
}
|
|
p->pLast = pEntry;
|
|
}
|
|
|
|
/*
|
|
** Merge two lists of RowSetEntry objects. Remove duplicates.
|
|
**
|
|
** The input lists are connected via pRight pointers and are
|
|
** assumed to each already be in sorted order.
|
|
*/
|
|
static struct RowSetEntry *rowSetEntryMerge(
|
|
struct RowSetEntry *pA, /* First sorted list to be merged */
|
|
struct RowSetEntry *pB /* Second sorted list to be merged */
|
|
){
|
|
struct RowSetEntry head;
|
|
struct RowSetEntry *pTail;
|
|
|
|
pTail = &head;
|
|
assert( pA!=0 && pB!=0 );
|
|
for(;;){
|
|
assert( pA->pRight==0 || pA->v<=pA->pRight->v );
|
|
assert( pB->pRight==0 || pB->v<=pB->pRight->v );
|
|
if( pA->v<=pB->v ){
|
|
if( pA->v<pB->v ) pTail = pTail->pRight = pA;
|
|
pA = pA->pRight;
|
|
if( pA==0 ){
|
|
pTail->pRight = pB;
|
|
break;
|
|
}
|
|
}else{
|
|
pTail = pTail->pRight = pB;
|
|
pB = pB->pRight;
|
|
if( pB==0 ){
|
|
pTail->pRight = pA;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return head.pRight;
|
|
}
|
|
|
|
/*
|
|
** Sort all elements on the list of RowSetEntry objects into order of
|
|
** increasing v.
|
|
*/
|
|
static struct RowSetEntry *rowSetEntrySort(struct RowSetEntry *pIn){
|
|
unsigned int i;
|
|
struct RowSetEntry *pNext, *aBucket[40];
|
|
|
|
memset(aBucket, 0, sizeof(aBucket));
|
|
while( pIn ){
|
|
pNext = pIn->pRight;
|
|
pIn->pRight = 0;
|
|
for(i=0; aBucket[i]; i++){
|
|
pIn = rowSetEntryMerge(aBucket[i], pIn);
|
|
aBucket[i] = 0;
|
|
}
|
|
aBucket[i] = pIn;
|
|
pIn = pNext;
|
|
}
|
|
pIn = aBucket[0];
|
|
for(i=1; i<sizeof(aBucket)/sizeof(aBucket[0]); i++){
|
|
if( aBucket[i]==0 ) continue;
|
|
pIn = pIn ? rowSetEntryMerge(pIn, aBucket[i]) : aBucket[i];
|
|
}
|
|
return pIn;
|
|
}
|
|
|
|
|
|
/*
|
|
** The input, pIn, is a binary tree (or subtree) of RowSetEntry objects.
|
|
** Convert this tree into a linked list connected by the pRight pointers
|
|
** and return pointers to the first and last elements of the new list.
|
|
*/
|
|
static void rowSetTreeToList(
|
|
struct RowSetEntry *pIn, /* Root of the input tree */
|
|
struct RowSetEntry **ppFirst, /* Write head of the output list here */
|
|
struct RowSetEntry **ppLast /* Write tail of the output list here */
|
|
){
|
|
assert( pIn!=0 );
|
|
if( pIn->pLeft ){
|
|
struct RowSetEntry *p;
|
|
rowSetTreeToList(pIn->pLeft, ppFirst, &p);
|
|
p->pRight = pIn;
|
|
}else{
|
|
*ppFirst = pIn;
|
|
}
|
|
if( pIn->pRight ){
|
|
rowSetTreeToList(pIn->pRight, &pIn->pRight, ppLast);
|
|
}else{
|
|
*ppLast = pIn;
|
|
}
|
|
assert( (*ppLast)->pRight==0 );
|
|
}
|
|
|
|
|
|
/*
|
|
** Convert a sorted list of elements (connected by pRight) into a binary
|
|
** tree with depth of iDepth. A depth of 1 means the tree contains a single
|
|
** node taken from the head of *ppList. A depth of 2 means a tree with
|
|
** three nodes. And so forth.
|
|
**
|
|
** Use as many entries from the input list as required and update the
|
|
** *ppList to point to the unused elements of the list. If the input
|
|
** list contains too few elements, then construct an incomplete tree
|
|
** and leave *ppList set to NULL.
|
|
**
|
|
** Return a pointer to the root of the constructed binary tree.
|
|
*/
|
|
static struct RowSetEntry *rowSetNDeepTree(
|
|
struct RowSetEntry **ppList,
|
|
int iDepth
|
|
){
|
|
struct RowSetEntry *p; /* Root of the new tree */
|
|
struct RowSetEntry *pLeft; /* Left subtree */
|
|
if( *ppList==0 ){ /*OPTIMIZATION-IF-TRUE*/
|
|
/* Prevent unnecessary deep recursion when we run out of entries */
|
|
return 0;
|
|
}
|
|
if( iDepth>1 ){ /*OPTIMIZATION-IF-TRUE*/
|
|
/* This branch causes a *balanced* tree to be generated. A valid tree
|
|
** is still generated without this branch, but the tree is wildly
|
|
** unbalanced and inefficient. */
|
|
pLeft = rowSetNDeepTree(ppList, iDepth-1);
|
|
p = *ppList;
|
|
if( p==0 ){ /*OPTIMIZATION-IF-FALSE*/
|
|
/* It is safe to always return here, but the resulting tree
|
|
** would be unbalanced */
|
|
return pLeft;
|
|
}
|
|
p->pLeft = pLeft;
|
|
*ppList = p->pRight;
|
|
p->pRight = rowSetNDeepTree(ppList, iDepth-1);
|
|
}else{
|
|
p = *ppList;
|
|
*ppList = p->pRight;
|
|
p->pLeft = p->pRight = 0;
|
|
}
|
|
return p;
|
|
}
|
|
|
|
/*
|
|
** Convert a sorted list of elements into a binary tree. Make the tree
|
|
** as deep as it needs to be in order to contain the entire list.
|
|
*/
|
|
static struct RowSetEntry *rowSetListToTree(struct RowSetEntry *pList){
|
|
int iDepth; /* Depth of the tree so far */
|
|
struct RowSetEntry *p; /* Current tree root */
|
|
struct RowSetEntry *pLeft; /* Left subtree */
|
|
|
|
assert( pList!=0 );
|
|
p = pList;
|
|
pList = p->pRight;
|
|
p->pLeft = p->pRight = 0;
|
|
for(iDepth=1; pList; iDepth++){
|
|
pLeft = p;
|
|
p = pList;
|
|
pList = p->pRight;
|
|
p->pLeft = pLeft;
|
|
p->pRight = rowSetNDeepTree(&pList, iDepth);
|
|
}
|
|
return p;
|
|
}
|
|
|
|
/*
|
|
** Extract the smallest element from the RowSet.
|
|
** Write the element into *pRowid. Return 1 on success. Return
|
|
** 0 if the RowSet is already empty.
|
|
**
|
|
** After this routine has been called, the sqlite3RowSetInsert()
|
|
** routine may not be called again.
|
|
**
|
|
** This routine may not be called after sqlite3RowSetTest() has
|
|
** been used. Older versions of RowSet allowed that, but as the
|
|
** capability was not used by the code generator, it was removed
|
|
** for code economy.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3RowSetNext(RowSet *p, i64 *pRowid){
|
|
assert( p!=0 );
|
|
assert( p->pForest==0 ); /* Cannot be used with sqlite3RowSetText() */
|
|
|
|
/* Merge the forest into a single sorted list on first call */
|
|
if( (p->rsFlags & ROWSET_NEXT)==0 ){ /*OPTIMIZATION-IF-FALSE*/
|
|
if( (p->rsFlags & ROWSET_SORTED)==0 ){ /*OPTIMIZATION-IF-FALSE*/
|
|
p->pEntry = rowSetEntrySort(p->pEntry);
|
|
}
|
|
p->rsFlags |= ROWSET_SORTED|ROWSET_NEXT;
|
|
}
|
|
|
|
/* Return the next entry on the list */
|
|
if( p->pEntry ){
|
|
*pRowid = p->pEntry->v;
|
|
p->pEntry = p->pEntry->pRight;
|
|
if( p->pEntry==0 ){ /*OPTIMIZATION-IF-TRUE*/
|
|
/* Free memory immediately, rather than waiting on sqlite3_finalize() */
|
|
sqlite3RowSetClear(p);
|
|
}
|
|
return 1;
|
|
}else{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Check to see if element iRowid was inserted into the rowset as
|
|
** part of any insert batch prior to iBatch. Return 1 or 0.
|
|
**
|
|
** If this is the first test of a new batch and if there exist entries
|
|
** on pRowSet->pEntry, then sort those entries into the forest at
|
|
** pRowSet->pForest so that they can be tested.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64 iRowid){
|
|
struct RowSetEntry *p, *pTree;
|
|
|
|
/* This routine is never called after sqlite3RowSetNext() */
|
|
assert( pRowSet!=0 && (pRowSet->rsFlags & ROWSET_NEXT)==0 );
|
|
|
|
/* Sort entries into the forest on the first test of a new batch.
|
|
** To save unnecessary work, only do this when the batch number changes.
|
|
*/
|
|
if( iBatch!=pRowSet->iBatch ){ /*OPTIMIZATION-IF-FALSE*/
|
|
p = pRowSet->pEntry;
|
|
if( p ){
|
|
struct RowSetEntry **ppPrevTree = &pRowSet->pForest;
|
|
if( (pRowSet->rsFlags & ROWSET_SORTED)==0 ){ /*OPTIMIZATION-IF-FALSE*/
|
|
/* Only sort the current set of entries if they need it */
|
|
p = rowSetEntrySort(p);
|
|
}
|
|
for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){
|
|
ppPrevTree = &pTree->pRight;
|
|
if( pTree->pLeft==0 ){
|
|
pTree->pLeft = rowSetListToTree(p);
|
|
break;
|
|
}else{
|
|
struct RowSetEntry *pAux, *pTail;
|
|
rowSetTreeToList(pTree->pLeft, &pAux, &pTail);
|
|
pTree->pLeft = 0;
|
|
p = rowSetEntryMerge(pAux, p);
|
|
}
|
|
}
|
|
if( pTree==0 ){
|
|
*ppPrevTree = pTree = rowSetEntryAlloc(pRowSet);
|
|
if( pTree ){
|
|
pTree->v = 0;
|
|
pTree->pRight = 0;
|
|
pTree->pLeft = rowSetListToTree(p);
|
|
}
|
|
}
|
|
pRowSet->pEntry = 0;
|
|
pRowSet->pLast = 0;
|
|
pRowSet->rsFlags |= ROWSET_SORTED;
|
|
}
|
|
pRowSet->iBatch = iBatch;
|
|
}
|
|
|
|
/* Test to see if the iRowid value appears anywhere in the forest.
|
|
** Return 1 if it does and 0 if not.
|
|
*/
|
|
for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){
|
|
p = pTree->pLeft;
|
|
while( p ){
|
|
if( p->v<iRowid ){
|
|
p = p->pRight;
|
|
}else if( p->v>iRowid ){
|
|
p = p->pLeft;
|
|
}else{
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/************** End of rowset.c **********************************************/
|
|
/************** Begin file pager.c *******************************************/
|
|
/*
|
|
** 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.
|
|
*/
|
|
#ifndef SQLITE_OMIT_DISKIO
|
|
/* #include "sqliteInt.h" */
|
|
/************** Include wal.h in the middle of pager.c ***********************/
|
|
/************** Begin file wal.h *********************************************/
|
|
/*
|
|
** 2010 February 1
|
|
**
|
|
** 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 to the write-ahead logging
|
|
** system. Refer to the comments below and the header comment attached to
|
|
** the implementation of each function in log.c for further details.
|
|
*/
|
|
|
|
#ifndef SQLITE_WAL_H
|
|
#define SQLITE_WAL_H
|
|
|
|
/* #include "sqliteInt.h" */
|
|
|
|
/* Macros for extracting appropriate sync flags for either transaction
|
|
** commits (WAL_SYNC_FLAGS(X)) or for checkpoint ops (CKPT_SYNC_FLAGS(X)):
|
|
*/
|
|
#define WAL_SYNC_FLAGS(X) ((X)&0x03)
|
|
#define CKPT_SYNC_FLAGS(X) (((X)>>2)&0x03)
|
|
|
|
#ifdef SQLITE_OMIT_WAL
|
|
# define sqlite3WalOpen(x,y,z) 0
|
|
# define sqlite3WalLimit(x,y)
|
|
# define sqlite3WalClose(v,w,x,y,z) 0
|
|
# define sqlite3WalBeginReadTransaction(y,z) 0
|
|
# define sqlite3WalEndReadTransaction(z)
|
|
# define sqlite3WalDbsize(y) 0
|
|
# define sqlite3WalBeginWriteTransaction(y) 0
|
|
# define sqlite3WalEndWriteTransaction(x) 0
|
|
# define sqlite3WalUndo(x,y,z) 0
|
|
# define sqlite3WalSavepoint(y,z)
|
|
# define sqlite3WalSavepointUndo(y,z) 0
|
|
# define sqlite3WalFrames(u,v,w,x,y,z) 0
|
|
# define sqlite3WalCheckpoint(q,r,s,t,u,v,w,x,y,z) 0
|
|
# define sqlite3WalCallback(z) 0
|
|
# define sqlite3WalExclusiveMode(y,z) 0
|
|
# define sqlite3WalHeapMemory(z) 0
|
|
# define sqlite3WalFramesize(z) 0
|
|
# define sqlite3WalFindFrame(x,y,z) 0
|
|
# define sqlite3WalFile(x) 0
|
|
# undef SQLITE_USE_SEH
|
|
#else
|
|
|
|
#define WAL_SAVEPOINT_NDATA 4
|
|
|
|
/* Connection to a write-ahead log (WAL) file.
|
|
** There is one object of this type for each pager.
|
|
*/
|
|
typedef struct Wal Wal;
|
|
|
|
/* Open and close a connection to a write-ahead log. */
|
|
SQLITE_PRIVATE int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *, int, i64, Wal**);
|
|
SQLITE_PRIVATE int sqlite3WalClose(Wal *pWal, sqlite3*, int sync_flags, int, u8 *);
|
|
|
|
/* Set the limiting size of a WAL file. */
|
|
SQLITE_PRIVATE void sqlite3WalLimit(Wal*, i64);
|
|
|
|
/* Used by readers to open (lock) and close (unlock) a snapshot. A
|
|
** snapshot is like a read-transaction. It is the state of the database
|
|
** at an instant in time. sqlite3WalOpenSnapshot gets a read lock and
|
|
** preserves the current state even if the other threads or processes
|
|
** write to or checkpoint the WAL. sqlite3WalCloseSnapshot() closes the
|
|
** transaction and releases the lock.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *);
|
|
SQLITE_PRIVATE void sqlite3WalEndReadTransaction(Wal *pWal);
|
|
|
|
/* Read a page from the write-ahead log, if it is present. */
|
|
SQLITE_PRIVATE int sqlite3WalFindFrame(Wal *, Pgno, u32 *);
|
|
SQLITE_PRIVATE int sqlite3WalReadFrame(Wal *, u32, int, u8 *);
|
|
|
|
/* If the WAL is not empty, return the size of the database. */
|
|
SQLITE_PRIVATE Pgno sqlite3WalDbsize(Wal *pWal);
|
|
|
|
/* Obtain or release the WRITER lock. */
|
|
SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal);
|
|
SQLITE_PRIVATE int sqlite3WalEndWriteTransaction(Wal *pWal);
|
|
|
|
/* Undo any frames written (but not committed) to the log */
|
|
SQLITE_PRIVATE int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx);
|
|
|
|
/* Return an integer that records the current (uncommitted) write
|
|
** position in the WAL */
|
|
SQLITE_PRIVATE void sqlite3WalSavepoint(Wal *pWal, u32 *aWalData);
|
|
|
|
/* Move the write position of the WAL back to iFrame. Called in
|
|
** response to a ROLLBACK TO command. */
|
|
SQLITE_PRIVATE int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData);
|
|
|
|
/* Write a frame or frames to the log. */
|
|
SQLITE_PRIVATE int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int);
|
|
|
|
/* Copy pages from the log to the database file */
|
|
SQLITE_PRIVATE int sqlite3WalCheckpoint(
|
|
Wal *pWal, /* Write-ahead log connection */
|
|
sqlite3 *db, /* Check this handle's interrupt flag */
|
|
int eMode, /* One of PASSIVE, FULL and RESTART */
|
|
int (*xBusy)(void*), /* Function to call when busy */
|
|
void *pBusyArg, /* Context argument for xBusyHandler */
|
|
int sync_flags, /* Flags to sync db file with (or 0) */
|
|
int nBuf, /* Size of buffer nBuf */
|
|
u8 *zBuf, /* Temporary buffer to use */
|
|
int *pnLog, /* OUT: Number of frames in WAL */
|
|
int *pnCkpt /* OUT: Number of backfilled frames in WAL */
|
|
);
|
|
|
|
/* Return the value to pass to a sqlite3_wal_hook callback, the
|
|
** number of frames in the WAL at the point of the last commit since
|
|
** sqlite3WalCallback() was called. If no commits have occurred since
|
|
** the last call, then return 0.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3WalCallback(Wal *pWal);
|
|
|
|
/* Tell the wal layer that an EXCLUSIVE lock has been obtained (or released)
|
|
** by the pager layer on the database file.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3WalExclusiveMode(Wal *pWal, int op);
|
|
|
|
/* Return true if the argument is non-NULL and the WAL module is using
|
|
** heap-memory for the wal-index. Otherwise, if the argument is NULL or the
|
|
** WAL module is using shared-memory, return false.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3WalHeapMemory(Wal *pWal);
|
|
|
|
#ifdef SQLITE_ENABLE_SNAPSHOT
|
|
SQLITE_PRIVATE int sqlite3WalSnapshotGet(Wal *pWal, sqlite3_snapshot **ppSnapshot);
|
|
SQLITE_PRIVATE void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapshot);
|
|
SQLITE_PRIVATE int sqlite3WalSnapshotRecover(Wal *pWal);
|
|
SQLITE_PRIVATE int sqlite3WalSnapshotCheck(Wal *pWal, sqlite3_snapshot *pSnapshot);
|
|
SQLITE_PRIVATE void sqlite3WalSnapshotUnlock(Wal *pWal);
|
|
#endif
|
|
|
|
#ifdef SQLITE_ENABLE_ZIPVFS
|
|
/* If the WAL file is not empty, return the number of bytes of content
|
|
** stored in each frame (i.e. the db page-size when the WAL was created).
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3WalFramesize(Wal *pWal);
|
|
#endif
|
|
|
|
/* Return the sqlite3_file object for the WAL file */
|
|
SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal);
|
|
|
|
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
SQLITE_PRIVATE int sqlite3WalWriteLock(Wal *pWal, int bLock);
|
|
SQLITE_PRIVATE void sqlite3WalDb(Wal *pWal, sqlite3 *db);
|
|
#endif
|
|
|
|
#ifdef SQLITE_USE_SEH
|
|
SQLITE_PRIVATE int sqlite3WalSystemErrno(Wal*);
|
|
#endif
|
|
|
|
#endif /* ifndef SQLITE_OMIT_WAL */
|
|
#endif /* SQLITE_WAL_H */
|
|
|
|
/************** End of wal.h *************************************************/
|
|
/************** Continuing where we left off in pager.c **********************/
|
|
|
|
|
|
/******************* NOTES ON THE DESIGN OF THE PAGER ************************
|
|
**
|
|
** This comment block describes invariants that hold when using a rollback
|
|
** journal. These invariants do not apply for journal_mode=WAL,
|
|
** journal_mode=MEMORY, or journal_mode=OFF.
|
|
**
|
|
** Within this comment block, a page is deemed to have been synced
|
|
** automatically as soon as it is written when PRAGMA synchronous=OFF.
|
|
** Otherwise, the page is not synced until the xSync method of the VFS
|
|
** is called successfully on the file containing the page.
|
|
**
|
|
** Definition: A page of the database file is said to be "overwriteable" if
|
|
** one or more of the following are true about the page:
|
|
**
|
|
** (a) The original content of the page as it was at the beginning of
|
|
** the transaction has been written into the rollback journal and
|
|
** synced.
|
|
**
|
|
** (b) The page was a freelist leaf page at the start of the transaction.
|
|
**
|
|
** (c) The page number is greater than the largest page that existed in
|
|
** the database file at the start of the transaction.
|
|
**
|
|
** (1) A page of the database file is never overwritten unless one of the
|
|
** following are true:
|
|
**
|
|
** (a) The page and all other pages on the same sector are overwriteable.
|
|
**
|
|
** (b) The atomic page write optimization is enabled, and the entire
|
|
** transaction other than the update of the transaction sequence
|
|
** number consists of a single page change.
|
|
**
|
|
** (2) The content of a page written into the rollback journal exactly matches
|
|
** both the content in the database when the rollback journal was written
|
|
** and the content in the database at the beginning of the current
|
|
** transaction.
|
|
**
|
|
** (3) Writes to the database file are an integer multiple of the page size
|
|
** in length and are aligned on a page boundary.
|
|
**
|
|
** (4) Reads from the database file are either aligned on a page boundary and
|
|
** an integer multiple of the page size in length or are taken from the
|
|
** first 100 bytes of the database file.
|
|
**
|
|
** (5) All writes to the database file are synced prior to the rollback journal
|
|
** being deleted, truncated, or zeroed.
|
|
**
|
|
** (6) If a super-journal file is used, then all writes to the database file
|
|
** are synced prior to the super-journal being deleted.
|
|
**
|
|
** Definition: Two databases (or the same database at two points it time)
|
|
** are said to be "logically equivalent" if they give the same answer to
|
|
** all queries. Note in particular the content of freelist leaf
|
|
** pages can be changed arbitrarily without affecting the logical equivalence
|
|
** of the database.
|
|
**
|
|
** (7) At any time, if any subset, including the empty set and the total set,
|
|
** of the unsynced changes to a rollback journal are removed and the
|
|
** journal is rolled back, the resulting database file will be logically
|
|
** equivalent to the database file at the beginning of the transaction.
|
|
**
|
|
** (8) When a transaction is rolled back, the xTruncate method of the VFS
|
|
** is called to restore the database file to the same size it was at
|
|
** the beginning of the transaction. (In some VFSes, the xTruncate
|
|
** method is a no-op, but that does not change the fact the SQLite will
|
|
** invoke it.)
|
|
**
|
|
** (9) Whenever the database file is modified, at least one bit in the range
|
|
** of bytes from 24 through 39 inclusive will be changed prior to releasing
|
|
** the EXCLUSIVE lock, thus signaling other connections on the same
|
|
** database to flush their caches.
|
|
**
|
|
** (10) The pattern of bits in bytes 24 through 39 shall not repeat in less
|
|
** than one billion transactions.
|
|
**
|
|
** (11) A database file is well-formed at the beginning and at the conclusion
|
|
** of every transaction.
|
|
**
|
|
** (12) An EXCLUSIVE lock is held on the database file when writing to
|
|
** the database file.
|
|
**
|
|
** (13) A SHARED lock is held on the database file while reading any
|
|
** content out of the database file.
|
|
**
|
|
******************************************************************************/
|
|
|
|
/*
|
|
** Macros for troubleshooting. Normally turned off
|
|
*/
|
|
#if 0
|
|
int sqlite3PagerTrace=1; /* True to enable tracing */
|
|
#define sqlite3DebugPrintf printf
|
|
#define PAGERTRACE(X) if( sqlite3PagerTrace ){ sqlite3DebugPrintf X; }
|
|
#else
|
|
#define PAGERTRACE(X)
|
|
#endif
|
|
|
|
/*
|
|
** The following two macros are used within the PAGERTRACE() macros above
|
|
** to print out file-descriptors.
|
|
**
|
|
** PAGERID() takes a pointer to a Pager struct as its argument. The
|
|
** associated file-descriptor is returned. FILEHANDLEID() takes an sqlite3_file
|
|
** struct as its argument.
|
|
*/
|
|
#define PAGERID(p) (SQLITE_PTR_TO_INT(p->fd))
|
|
#define FILEHANDLEID(fd) (SQLITE_PTR_TO_INT(fd))
|
|
|
|
/*
|
|
** The Pager.eState variable stores the current 'state' of a pager. A
|
|
** pager may be in any one of the seven states shown in the following
|
|
** state diagram.
|
|
**
|
|
** OPEN <------+------+
|
|
** | | |
|
|
** V | |
|
|
** +---------> READER-------+ |
|
|
** | | |
|
|
** | V |
|
|
** |<-------WRITER_LOCKED------> ERROR
|
|
** | | ^
|
|
** | V |
|
|
** |<------WRITER_CACHEMOD-------->|
|
|
** | | |
|
|
** | V |
|
|
** |<-------WRITER_DBMOD---------->|
|
|
** | | |
|
|
** | V |
|
|
** +<------WRITER_FINISHED-------->+
|
|
**
|
|
**
|
|
** List of state transitions and the C [function] that performs each:
|
|
**
|
|
** OPEN -> READER [sqlite3PagerSharedLock]
|
|
** READER -> OPEN [pager_unlock]
|
|
**
|
|
** READER -> WRITER_LOCKED [sqlite3PagerBegin]
|
|
** WRITER_LOCKED -> WRITER_CACHEMOD [pager_open_journal]
|
|
** WRITER_CACHEMOD -> WRITER_DBMOD [syncJournal]
|
|
** WRITER_DBMOD -> WRITER_FINISHED [sqlite3PagerCommitPhaseOne]
|
|
** WRITER_*** -> READER [pager_end_transaction]
|
|
**
|
|
** WRITER_*** -> ERROR [pager_error]
|
|
** ERROR -> OPEN [pager_unlock]
|
|
**
|
|
**
|
|
** OPEN:
|
|
**
|
|
** The pager starts up in this state. Nothing is guaranteed in this
|
|
** state - the file may or may not be locked and the database size is
|
|
** unknown. The database may not be read or written.
|
|
**
|
|
** * No read or write transaction is active.
|
|
** * Any lock, or no lock at all, may be held on the database file.
|
|
** * The dbSize, dbOrigSize and dbFileSize variables may not be trusted.
|
|
**
|
|
** READER:
|
|
**
|
|
** In this state all the requirements for reading the database in
|
|
** rollback (non-WAL) mode are met. Unless the pager is (or recently
|
|
** was) in exclusive-locking mode, a user-level read transaction is
|
|
** open. The database size is known in this state.
|
|
**
|
|
** A connection running with locking_mode=normal enters this state when
|
|
** it opens a read-transaction on the database and returns to state
|
|
** OPEN after the read-transaction is completed. However a connection
|
|
** running in locking_mode=exclusive (including temp databases) remains in
|
|
** this state even after the read-transaction is closed. The only way
|
|
** a locking_mode=exclusive connection can transition from READER to OPEN
|
|
** is via the ERROR state (see below).
|
|
**
|
|
** * A read transaction may be active (but a write-transaction cannot).
|
|
** * A SHARED or greater lock is held on the database file.
|
|
** * The dbSize variable may be trusted (even if a user-level read
|
|
** transaction is not active). The dbOrigSize and dbFileSize variables
|
|
** may not be trusted at this point.
|
|
** * If the database is a WAL database, then the WAL connection is open.
|
|
** * Even if a read-transaction is not open, it is guaranteed that
|
|
** there is no hot-journal in the file-system.
|
|
**
|
|
** WRITER_LOCKED:
|
|
**
|
|
** The pager moves to this state from READER when a write-transaction
|
|
** is first opened on the database. In WRITER_LOCKED state, all locks
|
|
** required to start a write-transaction are held, but no actual
|
|
** modifications to the cache or database have taken place.
|
|
**
|
|
** In rollback mode, a RESERVED or (if the transaction was opened with
|
|
** BEGIN EXCLUSIVE) EXCLUSIVE lock is obtained on the database file when
|
|
** moving to this state, but the journal file is not written to or opened
|
|
** to in this state. If the transaction is committed or rolled back while
|
|
** in WRITER_LOCKED state, all that is required is to unlock the database
|
|
** file.
|
|
**
|
|
** IN WAL mode, WalBeginWriteTransaction() is called to lock the log file.
|
|
** If the connection is running with locking_mode=exclusive, an attempt
|
|
** is made to obtain an EXCLUSIVE lock on the database file.
|
|
**
|
|
** * A write transaction is active.
|
|
** * If the connection is open in rollback-mode, a RESERVED or greater
|
|
** lock is held on the database file.
|
|
** * If the connection is open in WAL-mode, a WAL write transaction
|
|
** is open (i.e. sqlite3WalBeginWriteTransaction() has been successfully
|
|
** called).
|
|
** * The dbSize, dbOrigSize and dbFileSize variables are all valid.
|
|
** * The contents of the pager cache have not been modified.
|
|
** * The journal file may or may not be open.
|
|
** * Nothing (not even the first header) has been written to the journal.
|
|
**
|
|
** WRITER_CACHEMOD:
|
|
**
|
|
** A pager moves from WRITER_LOCKED state to this state when a page is
|
|
** first modified by the upper layer. In rollback mode the journal file
|
|
** is opened (if it is not already open) and a header written to the
|
|
** start of it. The database file on disk has not been modified.
|
|
**
|
|
** * A write transaction is active.
|
|
** * A RESERVED or greater lock is held on the database file.
|
|
** * The journal file is open and the first header has been written
|
|
** to it, but the header has not been synced to disk.
|
|
** * The contents of the page cache have been modified.
|
|
**
|
|
** WRITER_DBMOD:
|
|
**
|
|
** The pager transitions from WRITER_CACHEMOD into WRITER_DBMOD state
|
|
** when it modifies the contents of the database file. WAL connections
|
|
** never enter this state (since they do not modify the database file,
|
|
** just the log file).
|
|
**
|
|
** * A write transaction is active.
|
|
** * An EXCLUSIVE or greater lock is held on the database file.
|
|
** * The journal file is open and the first header has been written
|
|
** and synced to disk.
|
|
** * The contents of the page cache have been modified (and possibly
|
|
** written to disk).
|
|
**
|
|
** WRITER_FINISHED:
|
|
**
|
|
** It is not possible for a WAL connection to enter this state.
|
|
**
|
|
** A rollback-mode pager changes to WRITER_FINISHED state from WRITER_DBMOD
|
|
** state after the entire transaction has been successfully written into the
|
|
** database file. In this state the transaction may be committed simply
|
|
** by finalizing the journal file. Once in WRITER_FINISHED state, it is
|
|
** not possible to modify the database further. At this point, the upper
|
|
** layer must either commit or rollback the transaction.
|
|
**
|
|
** * A write transaction is active.
|
|
** * An EXCLUSIVE or greater lock is held on the database file.
|
|
** * All writing and syncing of journal and database data has finished.
|
|
** If no error occurred, all that remains is to finalize the journal to
|
|
** commit the transaction. If an error did occur, the caller will need
|
|
** to rollback the transaction.
|
|
**
|
|
** ERROR:
|
|
**
|
|
** The ERROR state is entered when an IO or disk-full error (including
|
|
** SQLITE_IOERR_NOMEM) occurs at a point in the code that makes it
|
|
** difficult to be sure that the in-memory pager state (cache contents,
|
|
** db size etc.) are consistent with the contents of the file-system.
|
|
**
|
|
** Temporary pager files may enter the ERROR state, but in-memory pagers
|
|
** cannot.
|
|
**
|
|
** For example, if an IO error occurs while performing a rollback,
|
|
** the contents of the page-cache may be left in an inconsistent state.
|
|
** At this point it would be dangerous to change back to READER state
|
|
** (as usually happens after a rollback). Any subsequent readers might
|
|
** report database corruption (due to the inconsistent cache), and if
|
|
** they upgrade to writers, they may inadvertently corrupt the database
|
|
** file. To avoid this hazard, the pager switches into the ERROR state
|
|
** instead of READER following such an error.
|
|
**
|
|
** Once it has entered the ERROR state, any attempt to use the pager
|
|
** to read or write data returns an error. Eventually, once all
|
|
** outstanding transactions have been abandoned, the pager is able to
|
|
** transition back to OPEN state, discarding the contents of the
|
|
** page-cache and any other in-memory state at the same time. Everything
|
|
** is reloaded from disk (and, if necessary, hot-journal rollback performed)
|
|
** when a read-transaction is next opened on the pager (transitioning
|
|
** the pager into READER state). At that point the system has recovered
|
|
** from the error.
|
|
**
|
|
** Specifically, the pager jumps into the ERROR state if:
|
|
**
|
|
** 1. An error occurs while attempting a rollback. This happens in
|
|
** function sqlite3PagerRollback().
|
|
**
|
|
** 2. An error occurs while attempting to finalize a journal file
|
|
** following a commit in function sqlite3PagerCommitPhaseTwo().
|
|
**
|
|
** 3. An error occurs while attempting to write to the journal or
|
|
** database file in function pagerStress() in order to free up
|
|
** memory.
|
|
**
|
|
** In other cases, the error is returned to the b-tree layer. The b-tree
|
|
** layer then attempts a rollback operation. If the error condition
|
|
** persists, the pager enters the ERROR state via condition (1) above.
|
|
**
|
|
** Condition (3) is necessary because it can be triggered by a read-only
|
|
** statement executed within a transaction. In this case, if the error
|
|
** code were simply returned to the user, the b-tree layer would not
|
|
** automatically attempt a rollback, as it assumes that an error in a
|
|
** read-only statement cannot leave the pager in an internally inconsistent
|
|
** state.
|
|
**
|
|
** * The Pager.errCode variable is set to something other than SQLITE_OK.
|
|
** * There are one or more outstanding references to pages (after the
|
|
** last reference is dropped the pager should move back to OPEN state).
|
|
** * The pager is not an in-memory pager.
|
|
**
|
|
**
|
|
** Notes:
|
|
**
|
|
** * A pager is never in WRITER_DBMOD or WRITER_FINISHED state if the
|
|
** connection is open in WAL mode. A WAL connection is always in one
|
|
** of the first four states.
|
|
**
|
|
** * Normally, a connection open in exclusive mode is never in PAGER_OPEN
|
|
** state. There are two exceptions: immediately after exclusive-mode has
|
|
** been turned on (and before any read or write transactions are
|
|
** executed), and when the pager is leaving the "error state".
|
|
**
|
|
** * See also: assert_pager_state().
|
|
*/
|
|
#define PAGER_OPEN 0
|
|
#define PAGER_READER 1
|
|
#define PAGER_WRITER_LOCKED 2
|
|
#define PAGER_WRITER_CACHEMOD 3
|
|
#define PAGER_WRITER_DBMOD 4
|
|
#define PAGER_WRITER_FINISHED 5
|
|
#define PAGER_ERROR 6
|
|
|
|
/*
|
|
** The Pager.eLock variable is almost always set to one of the
|
|
** following locking-states, according to the lock currently held on
|
|
** the database file: NO_LOCK, SHARED_LOCK, RESERVED_LOCK or EXCLUSIVE_LOCK.
|
|
** This variable is kept up to date as locks are taken and released by
|
|
** the pagerLockDb() and pagerUnlockDb() wrappers.
|
|
**
|
|
** If the VFS xLock() or xUnlock() returns an error other than SQLITE_BUSY
|
|
** (i.e. one of the SQLITE_IOERR subtypes), it is not clear whether or not
|
|
** the operation was successful. In these circumstances pagerLockDb() and
|
|
** pagerUnlockDb() take a conservative approach - eLock is always updated
|
|
** when unlocking the file, and only updated when locking the file if the
|
|
** VFS call is successful. This way, the Pager.eLock variable may be set
|
|
** to a less exclusive (lower) value than the lock that is actually held
|
|
** at the system level, but it is never set to a more exclusive value.
|
|
**
|
|
** This is usually safe. If an xUnlock fails or appears to fail, there may
|
|
** be a few redundant xLock() calls or a lock may be held for longer than
|
|
** required, but nothing really goes wrong.
|
|
**
|
|
** The exception is when the database file is unlocked as the pager moves
|
|
** from ERROR to OPEN state. At this point there may be a hot-journal file
|
|
** in the file-system that needs to be rolled back (as part of an OPEN->SHARED
|
|
** transition, by the same pager or any other). If the call to xUnlock()
|
|
** fails at this point and the pager is left holding an EXCLUSIVE lock, this
|
|
** can confuse the call to xCheckReservedLock() call made later as part
|
|
** of hot-journal detection.
|
|
**
|
|
** xCheckReservedLock() is defined as returning true "if there is a RESERVED
|
|
** lock held by this process or any others". So xCheckReservedLock may
|
|
** return true because the caller itself is holding an EXCLUSIVE lock (but
|
|
** doesn't know it because of a previous error in xUnlock). If this happens
|
|
** a hot-journal may be mistaken for a journal being created by an active
|
|
** transaction in another process, causing SQLite to read from the database
|
|
** without rolling it back.
|
|
**
|
|
** To work around this, if a call to xUnlock() fails when unlocking the
|
|
** database in the ERROR state, Pager.eLock is set to UNKNOWN_LOCK. It
|
|
** is only changed back to a real locking state after a successful call
|
|
** to xLock(EXCLUSIVE). Also, the code to do the OPEN->SHARED state transition
|
|
** omits the check for a hot-journal if Pager.eLock is set to UNKNOWN_LOCK
|
|
** lock. Instead, it assumes a hot-journal exists and obtains an EXCLUSIVE
|
|
** lock on the database file before attempting to roll it back. See function
|
|
** PagerSharedLock() for more detail.
|
|
**
|
|
** Pager.eLock may only be set to UNKNOWN_LOCK when the pager is in
|
|
** PAGER_OPEN state.
|
|
*/
|
|
#define UNKNOWN_LOCK (EXCLUSIVE_LOCK+1)
|
|
|
|
/*
|
|
** The maximum allowed sector size. 64KiB. If the xSectorsize() method
|
|
** returns a value larger than this, then MAX_SECTOR_SIZE is used instead.
|
|
** This could conceivably cause corruption following a power failure on
|
|
** such a system. This is currently an undocumented limit.
|
|
*/
|
|
#define MAX_SECTOR_SIZE 0x10000
|
|
|
|
|
|
/*
|
|
** An instance of the following structure is allocated for each active
|
|
** savepoint and statement transaction in the system. All such structures
|
|
** are stored in the Pager.aSavepoint[] array, which is allocated and
|
|
** resized using sqlite3Realloc().
|
|
**
|
|
** When a savepoint is created, the PagerSavepoint.iHdrOffset field is
|
|
** set to 0. If a journal-header is written into the main journal while
|
|
** the savepoint is active, then iHdrOffset is set to the byte offset
|
|
** immediately following the last journal record written into the main
|
|
** journal before the journal-header. This is required during savepoint
|
|
** rollback (see pagerPlaybackSavepoint()).
|
|
*/
|
|
typedef struct PagerSavepoint PagerSavepoint;
|
|
struct PagerSavepoint {
|
|
i64 iOffset; /* Starting offset in main journal */
|
|
i64 iHdrOffset; /* See above */
|
|
Bitvec *pInSavepoint; /* Set of pages in this savepoint */
|
|
Pgno nOrig; /* Original number of pages in file */
|
|
Pgno iSubRec; /* Index of first record in sub-journal */
|
|
int bTruncateOnRelease; /* If stmt journal may be truncated on RELEASE */
|
|
#ifndef SQLITE_OMIT_WAL
|
|
u32 aWalData[WAL_SAVEPOINT_NDATA]; /* WAL savepoint context */
|
|
#endif
|
|
};
|
|
|
|
/*
|
|
** Bits of the Pager.doNotSpill flag. See further description below.
|
|
*/
|
|
#define SPILLFLAG_OFF 0x01 /* Never spill cache. Set via pragma */
|
|
#define SPILLFLAG_ROLLBACK 0x02 /* Current rolling back, so do not spill */
|
|
#define SPILLFLAG_NOSYNC 0x04 /* Spill is ok, but do not sync */
|
|
|
|
/*
|
|
** An open page cache is an instance of struct Pager. A description of
|
|
** some of the more important member variables follows:
|
|
**
|
|
** eState
|
|
**
|
|
** The current 'state' of the pager object. See the comment and state
|
|
** diagram above for a description of the pager state.
|
|
**
|
|
** eLock
|
|
**
|
|
** For a real on-disk database, the current lock held on the database file -
|
|
** NO_LOCK, SHARED_LOCK, RESERVED_LOCK or EXCLUSIVE_LOCK.
|
|
**
|
|
** For a temporary or in-memory database (neither of which require any
|
|
** locks), this variable is always set to EXCLUSIVE_LOCK. Since such
|
|
** databases always have Pager.exclusiveMode==1, this tricks the pager
|
|
** logic into thinking that it already has all the locks it will ever
|
|
** need (and no reason to release them).
|
|
**
|
|
** In some (obscure) circumstances, this variable may also be set to
|
|
** UNKNOWN_LOCK. See the comment above the #define of UNKNOWN_LOCK for
|
|
** details.
|
|
**
|
|
** changeCountDone
|
|
**
|
|
** This boolean variable is used to make sure that the change-counter
|
|
** (the 4-byte header field at byte offset 24 of the database file) is
|
|
** not updated more often than necessary.
|
|
**
|
|
** It is set to true when the change-counter field is updated, which
|
|
** can only happen if an exclusive lock is held on the database file.
|
|
** It is cleared (set to false) whenever an exclusive lock is
|
|
** relinquished on the database file. Each time a transaction is committed,
|
|
** The changeCountDone flag is inspected. If it is true, the work of
|
|
** updating the change-counter is omitted for the current transaction.
|
|
**
|
|
** This mechanism means that when running in exclusive mode, a connection
|
|
** need only update the change-counter once, for the first transaction
|
|
** committed.
|
|
**
|
|
** setSuper
|
|
**
|
|
** When PagerCommitPhaseOne() is called to commit a transaction, it may
|
|
** (or may not) specify a super-journal name to be written into the
|
|
** journal file before it is synced to disk.
|
|
**
|
|
** Whether or not a journal file contains a super-journal pointer affects
|
|
** the way in which the journal file is finalized after the transaction is
|
|
** committed or rolled back when running in "journal_mode=PERSIST" mode.
|
|
** If a journal file does not contain a super-journal pointer, it is
|
|
** finalized by overwriting the first journal header with zeroes. If
|
|
** it does contain a super-journal pointer the journal file is finalized
|
|
** by truncating it to zero bytes, just as if the connection were
|
|
** running in "journal_mode=truncate" mode.
|
|
**
|
|
** Journal files that contain super-journal pointers cannot be finalized
|
|
** simply by overwriting the first journal-header with zeroes, as the
|
|
** super-journal pointer could interfere with hot-journal rollback of any
|
|
** subsequently interrupted transaction that reuses the journal file.
|
|
**
|
|
** The flag is cleared as soon as the journal file is finalized (either
|
|
** by PagerCommitPhaseTwo or PagerRollback). If an IO error prevents the
|
|
** journal file from being successfully finalized, the setSuper flag
|
|
** is cleared anyway (and the pager will move to ERROR state).
|
|
**
|
|
** doNotSpill
|
|
**
|
|
** This variables control the behavior of cache-spills (calls made by
|
|
** the pcache module to the pagerStress() routine to write cached data
|
|
** to the file-system in order to free up memory).
|
|
**
|
|
** When bits SPILLFLAG_OFF or SPILLFLAG_ROLLBACK of doNotSpill are set,
|
|
** writing to the database from pagerStress() is disabled altogether.
|
|
** The SPILLFLAG_ROLLBACK case is done in a very obscure case that
|
|
** comes up during savepoint rollback that requires the pcache module
|
|
** to allocate a new page to prevent the journal file from being written
|
|
** while it is being traversed by code in pager_playback(). The SPILLFLAG_OFF
|
|
** case is a user preference.
|
|
**
|
|
** If the SPILLFLAG_NOSYNC bit is set, writing to the database from
|
|
** pagerStress() is permitted, but syncing the journal file is not.
|
|
** This flag is set by sqlite3PagerWrite() when the file-system sector-size
|
|
** is larger than the database page-size in order to prevent a journal sync
|
|
** from happening in between the journalling of two pages on the same sector.
|
|
**
|
|
** subjInMemory
|
|
**
|
|
** This is a boolean variable. If true, then any required sub-journal
|
|
** is opened as an in-memory journal file. If false, then in-memory
|
|
** sub-journals are only used for in-memory pager files.
|
|
**
|
|
** This variable is updated by the upper layer each time a new
|
|
** write-transaction is opened.
|
|
**
|
|
** dbSize, dbOrigSize, dbFileSize
|
|
**
|
|
** Variable dbSize is set to the number of pages in the database file.
|
|
** It is valid in PAGER_READER and higher states (all states except for
|
|
** OPEN and ERROR).
|
|
**
|
|
** dbSize is set based on the size of the database file, which may be
|
|
** larger than the size of the database (the value stored at offset
|
|
** 28 of the database header by the btree). If the size of the file
|
|
** is not an integer multiple of the page-size, the value stored in
|
|
** dbSize is rounded down (i.e. a 5KB file with 2K page-size has dbSize==2).
|
|
** Except, any file that is greater than 0 bytes in size is considered
|
|
** to have at least one page. (i.e. a 1KB file with 2K page-size leads
|
|
** to dbSize==1).
|
|
**
|
|
** During a write-transaction, if pages with page-numbers greater than
|
|
** dbSize are modified in the cache, dbSize is updated accordingly.
|
|
** Similarly, if the database is truncated using PagerTruncateImage(),
|
|
** dbSize is updated.
|
|
**
|
|
** Variables dbOrigSize and dbFileSize are valid in states
|
|
** PAGER_WRITER_LOCKED and higher. dbOrigSize is a copy of the dbSize
|
|
** variable at the start of the transaction. It is used during rollback,
|
|
** and to determine whether or not pages need to be journalled before
|
|
** being modified.
|
|
**
|
|
** Throughout a write-transaction, dbFileSize contains the size of
|
|
** the file on disk in pages. It is set to a copy of dbSize when the
|
|
** write-transaction is first opened, and updated when VFS calls are made
|
|
** to write or truncate the database file on disk.
|
|
**
|
|
** The only reason the dbFileSize variable is required is to suppress
|
|
** unnecessary calls to xTruncate() after committing a transaction. If,
|
|
** when a transaction is committed, the dbFileSize variable indicates
|
|
** that the database file is larger than the database image (Pager.dbSize),
|
|
** pager_truncate() is called. The pager_truncate() call uses xFilesize()
|
|
** to measure the database file on disk, and then truncates it if required.
|
|
** dbFileSize is not used when rolling back a transaction. In this case
|
|
** pager_truncate() is called unconditionally (which means there may be
|
|
** a call to xFilesize() that is not strictly required). In either case,
|
|
** pager_truncate() may cause the file to become smaller or larger.
|
|
**
|
|
** dbHintSize
|
|
**
|
|
** The dbHintSize variable is used to limit the number of calls made to
|
|
** the VFS xFileControl(FCNTL_SIZE_HINT) method.
|
|
**
|
|
** dbHintSize is set to a copy of the dbSize variable when a
|
|
** write-transaction is opened (at the same time as dbFileSize and
|
|
** dbOrigSize). If the xFileControl(FCNTL_SIZE_HINT) method is called,
|
|
** dbHintSize is increased to the number of pages that correspond to the
|
|
** size-hint passed to the method call. See pager_write_pagelist() for
|
|
** details.
|
|
**
|
|
** errCode
|
|
**
|
|
** The Pager.errCode variable is only ever used in PAGER_ERROR state. It
|
|
** is set to zero in all other states. In PAGER_ERROR state, Pager.errCode
|
|
** is always set to SQLITE_FULL, SQLITE_IOERR or one of the SQLITE_IOERR_XXX
|
|
** sub-codes.
|
|
**
|
|
** syncFlags, walSyncFlags
|
|
**
|
|
** syncFlags is either SQLITE_SYNC_NORMAL (0x02) or SQLITE_SYNC_FULL (0x03).
|
|
** syncFlags is used for rollback mode. walSyncFlags is used for WAL mode
|
|
** and contains the flags used to sync the checkpoint operations in the
|
|
** lower two bits, and sync flags used for transaction commits in the WAL
|
|
** file in bits 0x04 and 0x08. In other words, to get the correct sync flags
|
|
** for checkpoint operations, use (walSyncFlags&0x03) and to get the correct
|
|
** sync flags for transaction commit, use ((walSyncFlags>>2)&0x03). Note
|
|
** that with synchronous=NORMAL in WAL mode, transaction commit is not synced
|
|
** meaning that the 0x04 and 0x08 bits are both zero.
|
|
*/
|
|
struct Pager {
|
|
sqlite3_vfs *pVfs; /* OS functions to use for IO */
|
|
u8 exclusiveMode; /* Boolean. True if locking_mode==EXCLUSIVE */
|
|
u8 journalMode; /* One of the PAGER_JOURNALMODE_* values */
|
|
u8 useJournal; /* Use a rollback journal on this file */
|
|
u8 noSync; /* Do not sync the journal if true */
|
|
u8 fullSync; /* Do extra syncs of the journal for robustness */
|
|
u8 extraSync; /* sync directory after journal delete */
|
|
u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */
|
|
u8 walSyncFlags; /* See description above */
|
|
u8 tempFile; /* zFilename is a temporary or immutable file */
|
|
u8 noLock; /* Do not lock (except in WAL mode) */
|
|
u8 readOnly; /* True for a read-only database */
|
|
u8 memDb; /* True to inhibit all file I/O */
|
|
u8 memVfs; /* VFS-implemented memory database */
|
|
|
|
/**************************************************************************
|
|
** The following block contains those class members that change during
|
|
** routine operation. Class members not in this block are either fixed
|
|
** when the pager is first created or else only change when there is a
|
|
** significant mode change (such as changing the page_size, locking_mode,
|
|
** or the journal_mode). From another view, these class members describe
|
|
** the "state" of the pager, while other class members describe the
|
|
** "configuration" of the pager.
|
|
*/
|
|
u8 eState; /* Pager state (OPEN, READER, WRITER_LOCKED..) */
|
|
u8 eLock; /* Current lock held on database file */
|
|
u8 changeCountDone; /* Set after incrementing the change-counter */
|
|
u8 setSuper; /* Super-jrnl name is written into jrnl */
|
|
u8 doNotSpill; /* Do not spill the cache when non-zero */
|
|
u8 subjInMemory; /* True to use in-memory sub-journals */
|
|
u8 bUseFetch; /* True to use xFetch() */
|
|
u8 hasHeldSharedLock; /* True if a shared lock has ever been held */
|
|
Pgno dbSize; /* Number of pages in the database */
|
|
Pgno dbOrigSize; /* dbSize before the current transaction */
|
|
Pgno dbFileSize; /* Number of pages in the database file */
|
|
Pgno dbHintSize; /* Value passed to FCNTL_SIZE_HINT call */
|
|
int errCode; /* One of several kinds of errors */
|
|
int nRec; /* Pages journalled since last j-header written */
|
|
u32 cksumInit; /* Quasi-random value added to every checksum */
|
|
u32 nSubRec; /* Number of records written to sub-journal */
|
|
Bitvec *pInJournal; /* One bit for each page in the database file */
|
|
sqlite3_file *fd; /* File descriptor for database */
|
|
sqlite3_file *jfd; /* File descriptor for main journal */
|
|
sqlite3_file *sjfd; /* File descriptor for sub-journal */
|
|
i64 journalOff; /* Current write offset in the journal file */
|
|
i64 journalHdr; /* Byte offset to previous journal header */
|
|
sqlite3_backup *pBackup; /* Pointer to list of ongoing backup processes */
|
|
PagerSavepoint *aSavepoint; /* Array of active savepoints */
|
|
int nSavepoint; /* Number of elements in aSavepoint[] */
|
|
u32 iDataVersion; /* Changes whenever database content changes */
|
|
char dbFileVers[16]; /* Changes whenever database file changes */
|
|
|
|
int nMmapOut; /* Number of mmap pages currently outstanding */
|
|
sqlite3_int64 szMmap; /* Desired maximum mmap size */
|
|
PgHdr *pMmapFreelist; /* List of free mmap page headers (pDirty) */
|
|
/*
|
|
** End of the routinely-changing class members
|
|
***************************************************************************/
|
|
|
|
u16 nExtra; /* Add this many bytes to each in-memory page */
|
|
i16 nReserve; /* Number of unused bytes at end of each page */
|
|
u32 vfsFlags; /* Flags for sqlite3_vfs.xOpen() */
|
|
u32 sectorSize; /* Assumed sector size during rollback */
|
|
Pgno mxPgno; /* Maximum allowed size of the database */
|
|
Pgno lckPgno; /* Page number for the locking page */
|
|
i64 pageSize; /* Number of bytes in a page */
|
|
i64 journalSizeLimit; /* Size limit for persistent journal files */
|
|
char *zFilename; /* Name of the database file */
|
|
char *zJournal; /* Name of the journal file */
|
|
int (*xBusyHandler)(void*); /* Function to call when busy */
|
|
void *pBusyHandlerArg; /* Context argument for xBusyHandler */
|
|
u32 aStat[4]; /* Total cache hits, misses, writes, spills */
|
|
#ifdef SQLITE_TEST
|
|
int nRead; /* Database pages read */
|
|
#endif
|
|
void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */
|
|
int (*xGet)(Pager*,Pgno,DbPage**,int); /* Routine to fetch a patch */
|
|
char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */
|
|
PCache *pPCache; /* Pointer to page cache object */
|
|
#ifndef SQLITE_OMIT_WAL
|
|
Wal *pWal; /* Write-ahead log used by "journal_mode=wal" */
|
|
char *zWal; /* File name for write-ahead log */
|
|
#endif
|
|
};
|
|
|
|
/*
|
|
** Indexes for use with Pager.aStat[]. The Pager.aStat[] array contains
|
|
** the values accessed by passing SQLITE_DBSTATUS_CACHE_HIT, CACHE_MISS
|
|
** or CACHE_WRITE to sqlite3_db_status().
|
|
*/
|
|
#define PAGER_STAT_HIT 0
|
|
#define PAGER_STAT_MISS 1
|
|
#define PAGER_STAT_WRITE 2
|
|
#define PAGER_STAT_SPILL 3
|
|
|
|
/*
|
|
** 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
|
|
SQLITE_API int sqlite3_pager_readdb_count = 0; /* Number of full pages read from DB */
|
|
SQLITE_API int sqlite3_pager_writedb_count = 0; /* Number of full pages written to DB */
|
|
SQLITE_API int sqlite3_pager_writej_count = 0; /* Number of pages written to journal */
|
|
# 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 being
|
|
** 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 of each page record in the journal is given by
|
|
** the following macro.
|
|
*/
|
|
#define JOURNAL_PG_SZ(pPager) ((pPager->pageSize) + 8)
|
|
|
|
/*
|
|
** The journal header size for this pager. This is usually the same
|
|
** size as a single disk sector. See also setSectorSize().
|
|
*/
|
|
#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
|
|
|
|
/*
|
|
** The macro USEFETCH is true if we are allowed to use the xFetch and xUnfetch
|
|
** interfaces to access the database using memory-mapped I/O.
|
|
*/
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
# define USEFETCH(x) ((x)->bUseFetch)
|
|
#else
|
|
# define USEFETCH(x) 0
|
|
#endif
|
|
|
|
/*
|
|
** The argument to this macro is a file descriptor (type sqlite3_file*).
|
|
** Return 0 if it is not open, or non-zero (but not 1) if it is.
|
|
**
|
|
** This is so that expressions can be written as:
|
|
**
|
|
** if( isOpen(pPager->jfd) ){ ...
|
|
**
|
|
** instead of
|
|
**
|
|
** if( pPager->jfd->pMethods ){ ...
|
|
*/
|
|
#define isOpen(pFd) ((pFd)->pMethods!=0)
|
|
|
|
#ifdef SQLITE_DIRECT_OVERFLOW_READ
|
|
/*
|
|
** Return true if page pgno can be read directly from the database file
|
|
** by the b-tree layer. This is the case if:
|
|
**
|
|
** * the database file is open,
|
|
** * there are no dirty pages in the cache, and
|
|
** * the desired page is not currently in the wal file.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){
|
|
if( pPager->fd->pMethods==0 ) return 0;
|
|
if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0;
|
|
#ifndef SQLITE_OMIT_WAL
|
|
if( pPager->pWal ){
|
|
u32 iRead = 0;
|
|
(void)sqlite3WalFindFrame(pPager->pWal, pgno, &iRead);
|
|
return iRead==0;
|
|
}
|
|
#endif
|
|
return 1;
|
|
}
|
|
#endif
|
|
|
|
#ifndef SQLITE_OMIT_WAL
|
|
# define pagerUseWal(x) ((x)->pWal!=0)
|
|
#else
|
|
# define pagerUseWal(x) 0
|
|
# define pagerRollbackWal(x) 0
|
|
# define pagerWalFrames(v,w,x,y) 0
|
|
# define pagerOpenWalIfPresent(z) SQLITE_OK
|
|
# define pagerBeginReadTransaction(z) SQLITE_OK
|
|
#endif
|
|
|
|
#ifndef NDEBUG
|
|
/*
|
|
** Usage:
|
|
**
|
|
** assert( assert_pager_state(pPager) );
|
|
**
|
|
** This function runs many asserts to try to find inconsistencies in
|
|
** the internal state of the Pager object.
|
|
*/
|
|
static int assert_pager_state(Pager *p){
|
|
Pager *pPager = p;
|
|
|
|
/* State must be valid. */
|
|
assert( p->eState==PAGER_OPEN
|
|
|| p->eState==PAGER_READER
|
|
|| p->eState==PAGER_WRITER_LOCKED
|
|
|| p->eState==PAGER_WRITER_CACHEMOD
|
|
|| p->eState==PAGER_WRITER_DBMOD
|
|
|| p->eState==PAGER_WRITER_FINISHED
|
|
|| p->eState==PAGER_ERROR
|
|
);
|
|
|
|
/* Regardless of the current state, a temp-file connection always behaves
|
|
** as if it has an exclusive lock on the database file. It never updates
|
|
** the change-counter field, so the changeCountDone flag is always set.
|
|
*/
|
|
assert( p->tempFile==0 || p->eLock==EXCLUSIVE_LOCK );
|
|
assert( p->tempFile==0 || pPager->changeCountDone );
|
|
|
|
/* If the useJournal flag is clear, the journal-mode must be "OFF".
|
|
** And if the journal-mode is "OFF", the journal file must not be open.
|
|
*/
|
|
assert( p->journalMode==PAGER_JOURNALMODE_OFF || p->useJournal );
|
|
assert( p->journalMode!=PAGER_JOURNALMODE_OFF || !isOpen(p->jfd) );
|
|
|
|
/* Check that MEMDB implies noSync. And an in-memory journal. Since
|
|
** this means an in-memory pager performs no IO at all, it cannot encounter
|
|
** either SQLITE_IOERR or SQLITE_FULL during rollback or while finalizing
|
|
** a journal file. (although the in-memory journal implementation may
|
|
** return SQLITE_IOERR_NOMEM while the journal file is being written). It
|
|
** is therefore not possible for an in-memory pager to enter the ERROR
|
|
** state.
|
|
*/
|
|
if( MEMDB ){
|
|
assert( !isOpen(p->fd) );
|
|
assert( p->noSync );
|
|
assert( p->journalMode==PAGER_JOURNALMODE_OFF
|
|
|| p->journalMode==PAGER_JOURNALMODE_MEMORY
|
|
);
|
|
assert( p->eState!=PAGER_ERROR && p->eState!=PAGER_OPEN );
|
|
assert( pagerUseWal(p)==0 );
|
|
}
|
|
|
|
/* If changeCountDone is set, a RESERVED lock or greater must be held
|
|
** on the file.
|
|
*/
|
|
assert( pPager->changeCountDone==0 || pPager->eLock>=RESERVED_LOCK );
|
|
assert( p->eLock!=PENDING_LOCK );
|
|
|
|
switch( p->eState ){
|
|
case PAGER_OPEN:
|
|
assert( !MEMDB );
|
|
assert( pPager->errCode==SQLITE_OK );
|
|
assert( sqlite3PcacheRefCount(pPager->pPCache)==0 || pPager->tempFile );
|
|
break;
|
|
|
|
case PAGER_READER:
|
|
assert( pPager->errCode==SQLITE_OK );
|
|
assert( p->eLock!=UNKNOWN_LOCK );
|
|
assert( p->eLock>=SHARED_LOCK );
|
|
break;
|
|
|
|
case PAGER_WRITER_LOCKED:
|
|
assert( p->eLock!=UNKNOWN_LOCK );
|
|
assert( pPager->errCode==SQLITE_OK );
|
|
if( !pagerUseWal(pPager) ){
|
|
assert( p->eLock>=RESERVED_LOCK );
|
|
}
|
|
assert( pPager->dbSize==pPager->dbOrigSize );
|
|
assert( pPager->dbOrigSize==pPager->dbFileSize );
|
|
assert( pPager->dbOrigSize==pPager->dbHintSize );
|
|
assert( pPager->setSuper==0 );
|
|
break;
|
|
|
|
case PAGER_WRITER_CACHEMOD:
|
|
assert( p->eLock!=UNKNOWN_LOCK );
|
|
assert( pPager->errCode==SQLITE_OK );
|
|
if( !pagerUseWal(pPager) ){
|
|
/* It is possible that if journal_mode=wal here that neither the
|
|
** journal file nor the WAL file are open. This happens during
|
|
** a rollback transaction that switches from journal_mode=off
|
|
** to journal_mode=wal.
|
|
*/
|
|
assert( p->eLock>=RESERVED_LOCK );
|
|
assert( isOpen(p->jfd)
|
|
|| p->journalMode==PAGER_JOURNALMODE_OFF
|
|
|| p->journalMode==PAGER_JOURNALMODE_WAL
|
|
);
|
|
}
|
|
assert( pPager->dbOrigSize==pPager->dbFileSize );
|
|
assert( pPager->dbOrigSize==pPager->dbHintSize );
|
|
break;
|
|
|
|
case PAGER_WRITER_DBMOD:
|
|
assert( p->eLock==EXCLUSIVE_LOCK );
|
|
assert( pPager->errCode==SQLITE_OK );
|
|
assert( !pagerUseWal(pPager) );
|
|
assert( p->eLock>=EXCLUSIVE_LOCK );
|
|
assert( isOpen(p->jfd)
|
|
|| p->journalMode==PAGER_JOURNALMODE_OFF
|
|
|| p->journalMode==PAGER_JOURNALMODE_WAL
|
|
|| (sqlite3OsDeviceCharacteristics(p->fd)&SQLITE_IOCAP_BATCH_ATOMIC)
|
|
);
|
|
assert( pPager->dbOrigSize<=pPager->dbHintSize );
|
|
break;
|
|
|
|
case PAGER_WRITER_FINISHED:
|
|
assert( p->eLock==EXCLUSIVE_LOCK );
|
|
assert( pPager->errCode==SQLITE_OK );
|
|
assert( !pagerUseWal(pPager) );
|
|
assert( isOpen(p->jfd)
|
|
|| p->journalMode==PAGER_JOURNALMODE_OFF
|
|
|| p->journalMode==PAGER_JOURNALMODE_WAL
|
|
|| (sqlite3OsDeviceCharacteristics(p->fd)&SQLITE_IOCAP_BATCH_ATOMIC)
|
|
);
|
|
break;
|
|
|
|
case PAGER_ERROR:
|
|
/* There must be at least one outstanding reference to the pager if
|
|
** in ERROR state. Otherwise the pager should have already dropped
|
|
** back to OPEN state.
|
|
*/
|
|
assert( pPager->errCode!=SQLITE_OK );
|
|
assert( sqlite3PcacheRefCount(pPager->pPCache)>0 || pPager->tempFile );
|
|
break;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
#endif /* ifndef NDEBUG */
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
/*
|
|
** Return a pointer to a human readable string in a static buffer
|
|
** containing the state of the Pager object passed as an argument. This
|
|
** is intended to be used within debuggers. For example, as an alternative
|
|
** to "print *pPager" in gdb:
|
|
**
|
|
** (gdb) printf "%s", print_pager_state(pPager)
|
|
**
|
|
** This routine has external linkage in order to suppress compiler warnings
|
|
** about an unused function. It is enclosed within SQLITE_DEBUG and so does
|
|
** not appear in normal builds.
|
|
*/
|
|
char *print_pager_state(Pager *p){
|
|
static char zRet[1024];
|
|
|
|
sqlite3_snprintf(1024, zRet,
|
|
"Filename: %s\n"
|
|
"State: %s errCode=%d\n"
|
|
"Lock: %s\n"
|
|
"Locking mode: locking_mode=%s\n"
|
|
"Journal mode: journal_mode=%s\n"
|
|
"Backing store: tempFile=%d memDb=%d useJournal=%d\n"
|
|
"Journal: journalOff=%lld journalHdr=%lld\n"
|
|
"Size: dbsize=%d dbOrigSize=%d dbFileSize=%d\n"
|
|
, p->zFilename
|
|
, p->eState==PAGER_OPEN ? "OPEN" :
|
|
p->eState==PAGER_READER ? "READER" :
|
|
p->eState==PAGER_WRITER_LOCKED ? "WRITER_LOCKED" :
|
|
p->eState==PAGER_WRITER_CACHEMOD ? "WRITER_CACHEMOD" :
|
|
p->eState==PAGER_WRITER_DBMOD ? "WRITER_DBMOD" :
|
|
p->eState==PAGER_WRITER_FINISHED ? "WRITER_FINISHED" :
|
|
p->eState==PAGER_ERROR ? "ERROR" : "?error?"
|
|
, (int)p->errCode
|
|
, p->eLock==NO_LOCK ? "NO_LOCK" :
|
|
p->eLock==RESERVED_LOCK ? "RESERVED" :
|
|
p->eLock==EXCLUSIVE_LOCK ? "EXCLUSIVE" :
|
|
p->eLock==SHARED_LOCK ? "SHARED" :
|
|
p->eLock==UNKNOWN_LOCK ? "UNKNOWN" : "?error?"
|
|
, p->exclusiveMode ? "exclusive" : "normal"
|
|
, p->journalMode==PAGER_JOURNALMODE_MEMORY ? "memory" :
|
|
p->journalMode==PAGER_JOURNALMODE_OFF ? "off" :
|
|
p->journalMode==PAGER_JOURNALMODE_DELETE ? "delete" :
|
|
p->journalMode==PAGER_JOURNALMODE_PERSIST ? "persist" :
|
|
p->journalMode==PAGER_JOURNALMODE_TRUNCATE ? "truncate" :
|
|
p->journalMode==PAGER_JOURNALMODE_WAL ? "wal" : "?error?"
|
|
, (int)p->tempFile, (int)p->memDb, (int)p->useJournal
|
|
, p->journalOff, p->journalHdr
|
|
, (int)p->dbSize, (int)p->dbOrigSize, (int)p->dbFileSize
|
|
);
|
|
|
|
return zRet;
|
|
}
|
|
#endif
|
|
|
|
/* Forward references to the various page getters */
|
|
static int getPageNormal(Pager*,Pgno,DbPage**,int);
|
|
static int getPageError(Pager*,Pgno,DbPage**,int);
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
static int getPageMMap(Pager*,Pgno,DbPage**,int);
|
|
#endif
|
|
|
|
/*
|
|
** Set the Pager.xGet method for the appropriate routine used to fetch
|
|
** content from the pager.
|
|
*/
|
|
static void setGetterMethod(Pager *pPager){
|
|
if( pPager->errCode ){
|
|
pPager->xGet = getPageError;
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
}else if( USEFETCH(pPager) ){
|
|
pPager->xGet = getPageMMap;
|
|
#endif /* SQLITE_MAX_MMAP_SIZE>0 */
|
|
}else{
|
|
pPager->xGet = getPageNormal;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Return true if it is necessary to write page *pPg into the sub-journal.
|
|
** A page needs to be written into the sub-journal if there exists one
|
|
** or more open savepoints for which:
|
|
**
|
|
** * The page-number is less than or equal to PagerSavepoint.nOrig, and
|
|
** * The bit corresponding to the page-number is not set in
|
|
** PagerSavepoint.pInSavepoint.
|
|
*/
|
|
static int subjRequiresPage(PgHdr *pPg){
|
|
Pager *pPager = pPg->pPager;
|
|
PagerSavepoint *p;
|
|
Pgno pgno = pPg->pgno;
|
|
int i;
|
|
for(i=0; i<pPager->nSavepoint; i++){
|
|
p = &pPager->aSavepoint[i];
|
|
if( p->nOrig>=pgno && 0==sqlite3BitvecTestNotNull(p->pInSavepoint, pgno) ){
|
|
for(i=i+1; i<pPager->nSavepoint; i++){
|
|
pPager->aSavepoint[i].bTruncateOnRelease = 0;
|
|
}
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
/*
|
|
** Return true if the page is already in the journal file.
|
|
*/
|
|
static int pageInJournal(Pager *pPager, PgHdr *pPg){
|
|
return sqlite3BitvecTest(pPager->pInJournal, pPg->pgno);
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
** 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(sqlite3_file *fd, i64 offset, u32 *pRes){
|
|
unsigned char ac[4];
|
|
int rc = sqlite3OsRead(fd, ac, sizeof(ac), offset);
|
|
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(sqlite3_file *fd, i64 offset, u32 val){
|
|
char ac[4];
|
|
put32bits(ac, val);
|
|
return sqlite3OsWrite(fd, ac, 4, offset);
|
|
}
|
|
|
|
/*
|
|
** Unlock the database file to level eLock, which must be either NO_LOCK
|
|
** or SHARED_LOCK. Regardless of whether or not the call to xUnlock()
|
|
** succeeds, set the Pager.eLock variable to match the (attempted) new lock.
|
|
**
|
|
** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is
|
|
** called, do not modify it. See the comment above the #define of
|
|
** UNKNOWN_LOCK for an explanation of this.
|
|
*/
|
|
static int pagerUnlockDb(Pager *pPager, int eLock){
|
|
int rc = SQLITE_OK;
|
|
|
|
assert( !pPager->exclusiveMode || pPager->eLock==eLock );
|
|
assert( eLock==NO_LOCK || eLock==SHARED_LOCK );
|
|
assert( eLock!=NO_LOCK || pagerUseWal(pPager)==0 );
|
|
if( isOpen(pPager->fd) ){
|
|
assert( pPager->eLock>=eLock );
|
|
rc = pPager->noLock ? SQLITE_OK : sqlite3OsUnlock(pPager->fd, eLock);
|
|
if( pPager->eLock!=UNKNOWN_LOCK ){
|
|
pPager->eLock = (u8)eLock;
|
|
}
|
|
IOTRACE(("UNLOCK %p %d\n", pPager, eLock))
|
|
}
|
|
pPager->changeCountDone = pPager->tempFile; /* ticket fb3b3024ea238d5c */
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Lock the database file to level eLock, which must be either SHARED_LOCK,
|
|
** RESERVED_LOCK or EXCLUSIVE_LOCK. If the caller is successful, set the
|
|
** Pager.eLock variable to the new locking state.
|
|
**
|
|
** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is
|
|
** called, do not modify it unless the new locking state is EXCLUSIVE_LOCK.
|
|
** See the comment above the #define of UNKNOWN_LOCK for an explanation
|
|
** of this.
|
|
*/
|
|
static int pagerLockDb(Pager *pPager, int eLock){
|
|
int rc = SQLITE_OK;
|
|
|
|
assert( eLock==SHARED_LOCK || eLock==RESERVED_LOCK || eLock==EXCLUSIVE_LOCK );
|
|
if( pPager->eLock<eLock || pPager->eLock==UNKNOWN_LOCK ){
|
|
rc = pPager->noLock ? SQLITE_OK : sqlite3OsLock(pPager->fd, eLock);
|
|
if( rc==SQLITE_OK && (pPager->eLock!=UNKNOWN_LOCK||eLock==EXCLUSIVE_LOCK) ){
|
|
pPager->eLock = (u8)eLock;
|
|
IOTRACE(("LOCK %p %d\n", pPager, eLock))
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** This function determines whether or not the atomic-write or
|
|
** atomic-batch-write optimizations can be used with this pager. The
|
|
** atomic-write optimization can be used if:
|
|
**
|
|
** (a) the value returned by OsDeviceCharacteristics() indicates that
|
|
** a database page may be written atomically, and
|
|
** (b) the value returned by OsSectorSize() is less than or equal
|
|
** to the page size.
|
|
**
|
|
** If it can be used, then the value returned is the size of the journal
|
|
** file when it contains rollback data for exactly one page.
|
|
**
|
|
** The atomic-batch-write optimization can be used if OsDeviceCharacteristics()
|
|
** returns a value with the SQLITE_IOCAP_BATCH_ATOMIC bit set. -1 is
|
|
** returned in this case.
|
|
**
|
|
** If neither optimization can be used, 0 is returned.
|
|
*/
|
|
static int jrnlBufferSize(Pager *pPager){
|
|
assert( !MEMDB );
|
|
|
|
#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
|
|
|| defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
|
|
int dc; /* Device characteristics */
|
|
|
|
assert( isOpen(pPager->fd) );
|
|
dc = sqlite3OsDeviceCharacteristics(pPager->fd);
|
|
#else
|
|
UNUSED_PARAMETER(pPager);
|
|
#endif
|
|
|
|
#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
|
|
if( pPager->dbSize>0 && (dc&SQLITE_IOCAP_BATCH_ATOMIC) ){
|
|
return -1;
|
|
}
|
|
#endif
|
|
|
|
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
|
|
{
|
|
int nSector = pPager->sectorSize;
|
|
int szPage = pPager->pageSize;
|
|
|
|
assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
|
|
assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
|
|
if( 0==(dc&(SQLITE_IOCAP_ATOMIC|(szPage>>8)) || nSector>szPage) ){
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
** 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; i<nByte; i++){
|
|
hash = (hash*1039) + pData[i];
|
|
}
|
|
return hash;
|
|
}
|
|
static u32 pager_pagehash(PgHdr *pPage){
|
|
return pager_datahash(pPage->pPager->pageSize, (unsigned char *)pPage->pData);
|
|
}
|
|
static void pager_set_pagehash(PgHdr *pPage){
|
|
pPage->pageHash = pager_pagehash(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( pPager->eState!=PAGER_ERROR );
|
|
assert( (pPg->flags&PGHDR_DIRTY) || pPg->pageHash==pager_pagehash(pPg) );
|
|
}
|
|
|
|
#else
|
|
#define pager_datahash(X,Y) 0
|
|
#define pager_pagehash(X) 0
|
|
#define pager_set_pagehash(X)
|
|
#define CHECK_PAGE(x)
|
|
#endif /* SQLITE_CHECK_PAGES */
|
|
|
|
/*
|
|
** When this is called the journal file for pager pPager must be open.
|
|
** This function attempts to read a super-journal file name from the
|
|
** end of the file and, if successful, copies it into memory supplied
|
|
** by the caller. See comments above writeSuperJournal() for the format
|
|
** used to store a super-journal file name at the end of a journal file.
|
|
**
|
|
** zSuper must point to a buffer of at least nSuper bytes allocated by
|
|
** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is
|
|
** enough space to write the super-journal name). If the super-journal
|
|
** name in the journal is longer than nSuper bytes (including a
|
|
** nul-terminator), then this is handled as if no super-journal name
|
|
** were present in the journal.
|
|
**
|
|
** If a super-journal file name is present at the end of the journal
|
|
** file, then it is copied into the buffer pointed to by zSuper. A
|
|
** nul-terminator byte is appended to the buffer following the
|
|
** super-journal file name.
|
|
**
|
|
** If it is determined that no super-journal file name is present
|
|
** zSuper[0] is set to 0 and SQLITE_OK returned.
|
|
**
|
|
** If an error occurs while reading from the journal file, an SQLite
|
|
** error code is returned.
|
|
*/
|
|
static int readSuperJournal(sqlite3_file *pJrnl, char *zSuper, u32 nSuper){
|
|
int rc; /* Return code */
|
|
u32 len; /* Length in bytes of super-journal name */
|
|
i64 szJ; /* Total size in bytes of journal file pJrnl */
|
|
u32 cksum; /* MJ checksum value read from journal */
|
|
u32 u; /* Unsigned loop counter */
|
|
unsigned char aMagic[8]; /* A buffer to hold the magic header */
|
|
zSuper[0] = '\0';
|
|
|
|
if( SQLITE_OK!=(rc = sqlite3OsFileSize(pJrnl, &szJ))
|
|
|| szJ<16
|
|
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len))
|
|
|| len>=nSuper
|
|
|| len>szJ-16
|
|
|| len==0
|
|
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum))
|
|
|| SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8))
|
|
|| memcmp(aMagic, aJournalMagic, 8)
|
|
|| SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, zSuper, len, szJ-16-len))
|
|
){
|
|
return rc;
|
|
}
|
|
|
|
/* See if the checksum matches the super-journal name */
|
|
for(u=0; u<len; u++){
|
|
cksum -= zSuper[u];
|
|
}
|
|
if( cksum ){
|
|
/* If the checksum doesn't add up, then one or more of the disk sectors
|
|
** containing the super-journal filename is corrupted. This means
|
|
** definitely roll back, so just return SQLITE_OK and report a (nul)
|
|
** super-journal filename.
|
|
*/
|
|
len = 0;
|
|
}
|
|
zSuper[len] = '\0';
|
|
zSuper[len+1] = '\0';
|
|
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
** Return the offset of the sector boundary at or immediately
|
|
** following the value in pPager->journalOff, assuming a sector
|
|
** size of pPager->sectorSize bytes.
|
|
**
|
|
** i.e for a sector size of 512:
|
|
**
|
|
** Pager.journalOff Return value
|
|
** ---------------------------------------
|
|
** 0 0
|
|
** 512 512
|
|
** 100 512
|
|
** 2000 2048
|
|
**
|
|
*/
|
|
static i64 journalHdrOffset(Pager *pPager){
|
|
i64 offset = 0;
|
|
i64 c = pPager->journalOff;
|
|
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)<JOURNAL_HDR_SZ(pPager) );
|
|
return offset;
|
|
}
|
|
|
|
/*
|
|
** The journal file must be open when this function is called.
|
|
**
|
|
** This function is a no-op if the journal file has not been written to
|
|
** within the current transaction (i.e. if Pager.journalOff==0).
|
|
**
|
|
** If doTruncate is non-zero or the Pager.journalSizeLimit variable is
|
|
** set to 0, then truncate the journal file to zero bytes in size. Otherwise,
|
|
** zero the 28-byte header at the start of the journal file. In either case,
|
|
** if the pager is not in no-sync mode, sync the journal file immediately
|
|
** after writing or truncating it.
|
|
**
|
|
** If Pager.journalSizeLimit is set to a positive, non-zero value, and
|
|
** following the truncation or zeroing described above the size of the
|
|
** journal file in bytes is larger than this value, then truncate the
|
|
** journal file to Pager.journalSizeLimit bytes. The journal file does
|
|
** not need to be synced following this operation.
|
|
**
|
|
** If an IO error occurs, abandon processing and return the IO error code.
|
|
** Otherwise, return SQLITE_OK.
|
|
*/
|
|
static int zeroJournalHdr(Pager *pPager, int doTruncate){
|
|
int rc = SQLITE_OK; /* Return code */
|
|
assert( isOpen(pPager->jfd) );
|
|
assert( !sqlite3JournalIsInMemory(pPager->jfd) );
|
|
if( pPager->journalOff ){
|
|
const i64 iLimit = pPager->journalSizeLimit; /* Local cache of jsl */
|
|
|
|
IOTRACE(("JZEROHDR %p\n", pPager))
|
|
if( doTruncate || iLimit==0 ){
|
|
rc = sqlite3OsTruncate(pPager->jfd, 0);
|
|
}else{
|
|
static const char zeroHdr[28] = {0};
|
|
rc = sqlite3OsWrite(pPager->jfd, zeroHdr, sizeof(zeroHdr), 0);
|
|
}
|
|
if( rc==SQLITE_OK && !pPager->noSync ){
|
|
rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_DATAONLY|pPager->syncFlags);
|
|
}
|
|
|
|
/* At this point the transaction is committed but the write lock
|
|
** is still held on the file. If there is a size limit configured for
|
|
** the persistent journal and the journal file currently consumes more
|
|
** space than that limit allows for, truncate it now. There is no need
|
|
** to sync the file following this operation.
|
|
*/
|
|
if( rc==SQLITE_OK && iLimit>0 ){
|
|
i64 sz;
|
|
rc = sqlite3OsFileSize(pPager->jfd, &sz);
|
|
if( rc==SQLITE_OK && sz>iLimit ){
|
|
rc = sqlite3OsTruncate(pPager->jfd, iLimit);
|
|
}
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** 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.
|
|
** - 4 bytes: Database page size.
|
|
**
|
|
** Followed by (JOURNAL_HDR_SZ - 28) bytes of unused space.
|
|
*/
|
|
static int writeJournalHdr(Pager *pPager){
|
|
int rc = SQLITE_OK; /* Return code */
|
|
char *zHeader = pPager->pTmpSpace; /* Temporary space used to build header */
|
|
u32 nHeader = (u32)pPager->pageSize;/* Size of buffer pointed to by zHeader */
|
|
u32 nWrite; /* Bytes of header sector written */
|
|
int ii; /* Loop counter */
|
|
|
|
assert( isOpen(pPager->jfd) ); /* Journal file must be open. */
|
|
|
|
if( nHeader>JOURNAL_HDR_SZ(pPager) ){
|
|
nHeader = JOURNAL_HDR_SZ(pPager);
|
|
}
|
|
|
|
/* If there are active savepoints and any of them were created
|
|
** since the most recent journal header was written, update the
|
|
** PagerSavepoint.iHdrOffset fields now.
|
|
*/
|
|
for(ii=0; ii<pPager->nSavepoint; ii++){
|
|
if( pPager->aSavepoint[ii].iHdrOffset==0 ){
|
|
pPager->aSavepoint[ii].iHdrOffset = pPager->journalOff;
|
|
}
|
|
}
|
|
|
|
pPager->journalHdr = pPager->journalOff = journalHdrOffset(pPager);
|
|
|
|
/*
|
|
** Write the nRec Field - the number of page records that follow this
|
|
** journal header. Normally, zero is written to this value at this time.
|
|
** After the records are added to the journal (and the journal synced,
|
|
** if in full-sync mode), the zero is overwritten with the true number
|
|
** of records (see syncJournal()).
|
|
**
|
|
** A faster alternative is to write 0xFFFFFFFF to the nRec field. When
|
|
** reading the journal this value tells SQLite to assume that the
|
|
** rest of the journal file contains valid page records. This assumption
|
|
** is dangerous, as if a failure occurred whilst writing to the journal
|
|
** file it may contain some garbage data. There are two scenarios
|
|
** where this risk can be ignored:
|
|
**
|
|
** * When the pager is in no-sync mode. Corruption can follow a
|
|
** power failure in this case anyway.
|
|
**
|
|
** * When the SQLITE_IOCAP_SAFE_APPEND flag is set. This guarantees
|
|
** that garbage data is never appended to the journal file.
|
|
*/
|
|
assert( isOpen(pPager->fd) || pPager->noSync );
|
|
if( pPager->noSync || (pPager->journalMode==PAGER_JOURNALMODE_MEMORY)
|
|
|| (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_SAFE_APPEND)
|
|
){
|
|
memcpy(zHeader, aJournalMagic, sizeof(aJournalMagic));
|
|
put32bits(&zHeader[sizeof(aJournalMagic)], 0xffffffff);
|
|
}else{
|
|
memset(zHeader, 0, sizeof(aJournalMagic)+4);
|
|
}
|
|
|
|
|
|
|
|
/* The random check-hash initializer */
|
|
if( pPager->journalMode!=PAGER_JOURNALMODE_MEMORY ){
|
|
sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit);
|
|
}
|
|
#ifdef SQLITE_DEBUG
|
|
else{
|
|
/* The Pager.cksumInit variable is usually randomized above to protect
|
|
** against there being existing records in the journal file. This is
|
|
** dangerous, as following a crash they may be mistaken for records
|
|
** written by the current transaction and rolled back into the database
|
|
** file, causing corruption. The following assert statements verify
|
|
** that this is not required in "journal_mode=memory" mode, as in that
|
|
** case the journal file is always 0 bytes in size at this point.
|
|
** It is advantageous to avoid the sqlite3_randomness() call if possible
|
|
** as it takes the global PRNG mutex. */
|
|
i64 sz = 0;
|
|
sqlite3OsFileSize(pPager->jfd, &sz);
|
|
assert( sz==0 );
|
|
assert( pPager->journalOff==journalHdrOffset(pPager) );
|
|
assert( sqlite3JournalIsInMemory(pPager->jfd) );
|
|
}
|
|
#endif
|
|
put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit);
|
|
|
|
/* The initial database size */
|
|
put32bits(&zHeader[sizeof(aJournalMagic)+8], pPager->dbOrigSize);
|
|
/* The assumed sector size for this process */
|
|
put32bits(&zHeader[sizeof(aJournalMagic)+12], pPager->sectorSize);
|
|
|
|
/* The page size */
|
|
put32bits(&zHeader[sizeof(aJournalMagic)+16], pPager->pageSize);
|
|
|
|
/* Initializing the tail of the buffer is not necessary. Everything
|
|
** works find if the following memset() is omitted. But initializing
|
|
** the memory prevents valgrind from complaining, so we are willing to
|
|
** take the performance hit.
|
|
*/
|
|
memset(&zHeader[sizeof(aJournalMagic)+20], 0,
|
|
nHeader-(sizeof(aJournalMagic)+20));
|
|
|
|
/* In theory, it is only necessary to write the 28 bytes that the
|
|
** journal header consumes to the journal file here. Then increment the
|
|
** Pager.journalOff variable by JOURNAL_HDR_SZ so that the next
|
|
** record is written to the following sector (leaving a gap in the file
|
|
** that will be implicitly filled in by the OS).
|
|
**
|
|
** However it has been discovered that on some systems this pattern can
|
|
** be significantly slower than contiguously writing data to the file,
|
|
** even if that means explicitly writing data to the block of
|
|
** (JOURNAL_HDR_SZ - 28) bytes that will not be used. So that is what
|
|
** is done.
|
|
**
|
|
** The loop is required here in case the sector-size is larger than the
|
|
** database page size. Since the zHeader buffer is only Pager.pageSize
|
|
** bytes in size, more than one call to sqlite3OsWrite() may be required
|
|
** to populate the entire journal header sector.
|
|
*/
|
|
for(nWrite=0; rc==SQLITE_OK&&nWrite<JOURNAL_HDR_SZ(pPager); nWrite+=nHeader){
|
|
IOTRACE(("JHDR %p %lld %d\n", pPager, pPager->journalHdr, nHeader))
|
|
rc = sqlite3OsWrite(pPager->jfd, zHeader, nHeader, pPager->journalOff);
|
|
assert( pPager->journalHdr <= pPager->journalOff );
|
|
pPager->journalOff += nHeader;
|
|
}
|
|
|
|
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. The current location in the journal file is given by
|
|
** pPager->journalOff. See comments above function writeJournalHdr() for
|
|
** a description of the journal header format.
|
|
**
|
|
** If the header is read successfully, *pNRec is set to the number of
|
|
** page records following this header and *pDbSize 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 *pNRec and *PDbSize are undefined. If JOURNAL_HDR_SZ bytes
|
|
** cannot be read from the journal file an error code is returned.
|
|
*/
|
|
static int readJournalHdr(
|
|
Pager *pPager, /* Pager object */
|
|
int isHot,
|
|
i64 journalSize, /* Size of the open journal file in bytes */
|
|
u32 *pNRec, /* OUT: Value read from the nRec field */
|
|
u32 *pDbSize /* OUT: Value of original database size field */
|
|
){
|
|
int rc; /* Return code */
|
|
unsigned char aMagic[8]; /* A buffer to hold the magic header */
|
|
i64 iHdrOff; /* Offset of journal header being read */
|
|
|
|
assert( isOpen(pPager->jfd) ); /* Journal file must be open. */
|
|
|
|
/* Advance Pager.journalOff to the start of the next sector. If the
|
|
** journal file is too small for there to be a header stored at this
|
|
** point, return SQLITE_DONE.
|
|
*/
|
|
pPager->journalOff = journalHdrOffset(pPager);
|
|
if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){
|
|
return SQLITE_DONE;
|
|
}
|
|
iHdrOff = pPager->journalOff;
|
|
|
|
/* Read in the first 8 bytes of the journal header. If they do not match
|
|
** the magic string found at the start of each journal header, return
|
|
** SQLITE_DONE. If an IO error occurs, return an error code. Otherwise,
|
|
** proceed.
|
|
*/
|
|
if( isHot || iHdrOff!=pPager->journalHdr ){
|
|
rc = sqlite3OsRead(pPager->jfd, aMagic, sizeof(aMagic), iHdrOff);
|
|
if( rc ){
|
|
return rc;
|
|
}
|
|
if( memcmp(aMagic, aJournalMagic, sizeof(aMagic))!=0 ){
|
|
return SQLITE_DONE;
|
|
}
|
|
}
|
|
|
|
/* Read the first three 32-bit fields of the journal header: The nRec
|
|
** field, the checksum-initializer and the database size at the start
|
|
** of the transaction. Return an error code if anything goes wrong.
|
|
*/
|
|
if( SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+8, pNRec))
|
|
|| SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+12, &pPager->cksumInit))
|
|
|| SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+16, pDbSize))
|
|
){
|
|
return rc;
|
|
}
|
|
|
|
if( pPager->journalOff==0 ){
|
|
u32 iPageSize; /* Page-size field of journal header */
|
|
u32 iSectorSize; /* Sector-size field of journal header */
|
|
|
|
/* Read the page-size and sector-size journal header fields. */
|
|
if( SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+20, &iSectorSize))
|
|
|| SQLITE_OK!=(rc = read32bits(pPager->jfd, iHdrOff+24, &iPageSize))
|
|
){
|
|
return rc;
|
|
}
|
|
|
|
/* Versions of SQLite prior to 3.5.8 set the page-size field of the
|
|
** journal header to zero. In this case, assume that the Pager.pageSize
|
|
** variable is already set to the correct page size.
|
|
*/
|
|
if( iPageSize==0 ){
|
|
iPageSize = pPager->pageSize;
|
|
}
|
|
|
|
/* Check that the values read from the page-size and sector-size fields
|
|
** are within range. To be 'in range', both values need to be a power
|
|
** of two greater than or equal to 512 or 32, and not greater than their
|
|
** respective compile time maximum limits.
|
|
*/
|
|
if( iPageSize<512 || iSectorSize<32
|
|
|| iPageSize>SQLITE_MAX_PAGE_SIZE || iSectorSize>MAX_SECTOR_SIZE
|
|
|| ((iPageSize-1)&iPageSize)!=0 || ((iSectorSize-1)&iSectorSize)!=0
|
|
){
|
|
/* If the either the page-size or sector-size in the journal-header is
|
|
** invalid, then the process that wrote the journal-header must have
|
|
** crashed before the header was synced. In this case stop reading
|
|
** the journal file here.
|
|
*/
|
|
return SQLITE_DONE;
|
|
}
|
|
|
|
/* Update the page-size to match the value read from the journal.
|
|
** Use a testcase() macro to make sure that malloc failure within
|
|
** PagerSetPagesize() is tested.
|
|
*/
|
|
rc = sqlite3PagerSetPagesize(pPager, &iPageSize, -1);
|
|
testcase( rc!=SQLITE_OK );
|
|
|
|
/* 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.
|
|
*/
|
|
pPager->sectorSize = iSectorSize;
|
|
}
|
|
|
|
pPager->journalOff += JOURNAL_HDR_SZ(pPager);
|
|
return rc;
|
|
}
|
|
|
|
|
|
/*
|
|
** Write the supplied super-journal name into the journal file for pager
|
|
** pPager at the current location. The super-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_SJ_PGNO.
|
|
** + N bytes: super-journal filename in utf-8.
|
|
** + 4 bytes: N (length of super-journal name in bytes, no nul-terminator).
|
|
** + 4 bytes: super-journal name checksum.
|
|
** + 8 bytes: aJournalMagic[].
|
|
**
|
|
** The super-journal page checksum is the sum of the bytes in the super-journal
|
|
** name, where each byte is interpreted as a signed 8-bit integer.
|
|
**
|
|
** If zSuper is a NULL pointer (occurs for a single database transaction),
|
|
** this call is a no-op.
|
|
*/
|
|
static int writeSuperJournal(Pager *pPager, const char *zSuper){
|
|
int rc; /* Return code */
|
|
int nSuper; /* Length of string zSuper */
|
|
i64 iHdrOff; /* Offset of header in journal file */
|
|
i64 jrnlSize; /* Size of journal file on disk */
|
|
u32 cksum = 0; /* Checksum of string zSuper */
|
|
|
|
assert( pPager->setSuper==0 );
|
|
assert( !pagerUseWal(pPager) );
|
|
|
|
if( !zSuper
|
|
|| pPager->journalMode==PAGER_JOURNALMODE_MEMORY
|
|
|| !isOpen(pPager->jfd)
|
|
){
|
|
return SQLITE_OK;
|
|
}
|
|
pPager->setSuper = 1;
|
|
assert( pPager->journalHdr <= pPager->journalOff );
|
|
|
|
/* Calculate the length in bytes and the checksum of zSuper */
|
|
for(nSuper=0; zSuper[nSuper]; nSuper++){
|
|
cksum += zSuper[nSuper];
|
|
}
|
|
|
|
/* If in full-sync mode, advance to the next disk sector before writing
|
|
** the super-journal name. This is in case the previous page written to
|
|
** the journal has already been synced.
|
|
*/
|
|
if( pPager->fullSync ){
|
|
pPager->journalOff = journalHdrOffset(pPager);
|
|
}
|
|
iHdrOff = pPager->journalOff;
|
|
|
|
/* Write the super-journal data to the end of the journal file. If
|
|
** an error occurs, return the error code to the caller.
|
|
*/
|
|
if( (0 != (rc = write32bits(pPager->jfd, iHdrOff, PAGER_SJ_PGNO(pPager))))
|
|
|| (0 != (rc = sqlite3OsWrite(pPager->jfd, zSuper, nSuper, iHdrOff+4)))
|
|
|| (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nSuper, nSuper)))
|
|
|| (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nSuper+4, cksum)))
|
|
|| (0 != (rc = sqlite3OsWrite(pPager->jfd, aJournalMagic, 8,
|
|
iHdrOff+4+nSuper+8)))
|
|
){
|
|
return rc;
|
|
}
|
|
pPager->journalOff += (nSuper+20);
|
|
|
|
/* If the pager is in persistent-journal mode, then the physical
|
|
** journal-file may extend past the end of the super-journal name
|
|
** and 8 bytes of magic data just written to the file. This is
|
|
** dangerous because the code to rollback a hot-journal file
|
|
** will not be able to find the super-journal name to determine
|
|
** whether or not the journal is hot.
|
|
**
|
|
** Easiest thing to do in this scenario is to truncate the journal
|
|
** file to the required size.
|
|
*/
|
|
if( SQLITE_OK==(rc = sqlite3OsFileSize(pPager->jfd, &jrnlSize))
|
|
&& jrnlSize>pPager->journalOff
|
|
){
|
|
rc = sqlite3OsTruncate(pPager->jfd, pPager->journalOff);
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Discard the entire contents of the in-memory page-cache.
|
|
*/
|
|
static void pager_reset(Pager *pPager){
|
|
pPager->iDataVersion++;
|
|
sqlite3BackupRestart(pPager->pBackup);
|
|
sqlite3PcacheClear(pPager->pPCache);
|
|
}
|
|
|
|
/*
|
|
** Return the pPager->iDataVersion value
|
|
*/
|
|
SQLITE_PRIVATE u32 sqlite3PagerDataVersion(Pager *pPager){
|
|
return pPager->iDataVersion;
|
|
}
|
|
|
|
/*
|
|
** Free all structures in the Pager.aSavepoint[] array and set both
|
|
** Pager.aSavepoint and Pager.nSavepoint to zero. Close the sub-journal
|
|
** if it is open and the pager is not in exclusive mode.
|
|
*/
|
|
static void releaseAllSavepoints(Pager *pPager){
|
|
int ii; /* Iterator for looping through Pager.aSavepoint */
|
|
for(ii=0; ii<pPager->nSavepoint; ii++){
|
|
sqlite3BitvecDestroy(pPager->aSavepoint[ii].pInSavepoint);
|
|
}
|
|
if( !pPager->exclusiveMode || sqlite3JournalIsInMemory(pPager->sjfd) ){
|
|
sqlite3OsClose(pPager->sjfd);
|
|
}
|
|
sqlite3_free(pPager->aSavepoint);
|
|
pPager->aSavepoint = 0;
|
|
pPager->nSavepoint = 0;
|
|
pPager->nSubRec = 0;
|
|
}
|
|
|
|
/*
|
|
** Set the bit number pgno in the PagerSavepoint.pInSavepoint
|
|
** bitvecs of all open savepoints. Return SQLITE_OK if successful
|
|
** or SQLITE_NOMEM if a malloc failure occurs.
|
|
*/
|
|
static int addToSavepointBitvecs(Pager *pPager, Pgno pgno){
|
|
int ii; /* Loop counter */
|
|
int rc = SQLITE_OK; /* Result code */
|
|
|
|
for(ii=0; ii<pPager->nSavepoint; ii++){
|
|
PagerSavepoint *p = &pPager->aSavepoint[ii];
|
|
if( pgno<=p->nOrig ){
|
|
rc |= sqlite3BitvecSet(p->pInSavepoint, pgno);
|
|
testcase( rc==SQLITE_NOMEM );
|
|
assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** This function is a no-op if the pager is in exclusive mode and not
|
|
** in the ERROR state. Otherwise, it switches the pager to PAGER_OPEN
|
|
** state.
|
|
**
|
|
** If the pager is not in exclusive-access mode, the database file is
|
|
** completely unlocked. If the file is unlocked and the file-system does
|
|
** not exhibit the UNDELETABLE_WHEN_OPEN property, the journal file is
|
|
** closed (if it is open).
|
|
**
|
|
** If the pager is in ERROR state when this function is called, the
|
|
** contents of the pager cache are discarded before switching back to
|
|
** the OPEN state. Regardless of whether the pager is in exclusive-mode
|
|
** or not, any journal file left in the file-system will be treated
|
|
** as a hot-journal and rolled back the next time a read-transaction
|
|
** is opened (by this or by any other connection).
|
|
*/
|
|
static void pager_unlock(Pager *pPager){
|
|
|
|
assert( pPager->eState==PAGER_READER
|
|
|| pPager->eState==PAGER_OPEN
|
|
|| pPager->eState==PAGER_ERROR
|
|
);
|
|
|
|
sqlite3BitvecDestroy(pPager->pInJournal);
|
|
pPager->pInJournal = 0;
|
|
releaseAllSavepoints(pPager);
|
|
|
|
if( pagerUseWal(pPager) ){
|
|
assert( !isOpen(pPager->jfd) );
|
|
sqlite3WalEndReadTransaction(pPager->pWal);
|
|
pPager->eState = PAGER_OPEN;
|
|
}else if( !pPager->exclusiveMode ){
|
|
int rc; /* Error code returned by pagerUnlockDb() */
|
|
int iDc = isOpen(pPager->fd)?sqlite3OsDeviceCharacteristics(pPager->fd):0;
|
|
|
|
/* If the operating system support deletion of open files, then
|
|
** close the journal file when dropping the database lock. Otherwise
|
|
** another connection with journal_mode=delete might delete the file
|
|
** out from under us.
|
|
*/
|
|
assert( (PAGER_JOURNALMODE_MEMORY & 5)!=1 );
|
|
assert( (PAGER_JOURNALMODE_OFF & 5)!=1 );
|
|
assert( (PAGER_JOURNALMODE_WAL & 5)!=1 );
|
|
assert( (PAGER_JOURNALMODE_DELETE & 5)!=1 );
|
|
assert( (PAGER_JOURNALMODE_TRUNCATE & 5)==1 );
|
|
assert( (PAGER_JOURNALMODE_PERSIST & 5)==1 );
|
|
if( 0==(iDc & SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN)
|
|
|| 1!=(pPager->journalMode & 5)
|
|
){
|
|
sqlite3OsClose(pPager->jfd);
|
|
}
|
|
|
|
/* If the pager is in the ERROR state and the call to unlock the database
|
|
** file fails, set the current lock to UNKNOWN_LOCK. See the comment
|
|
** above the #define for UNKNOWN_LOCK for an explanation of why this
|
|
** is necessary.
|
|
*/
|
|
rc = pagerUnlockDb(pPager, NO_LOCK);
|
|
if( rc!=SQLITE_OK && pPager->eState==PAGER_ERROR ){
|
|
pPager->eLock = UNKNOWN_LOCK;
|
|
}
|
|
|
|
/* The pager state may be changed from PAGER_ERROR to PAGER_OPEN here
|
|
** without clearing the error code. This is intentional - the error
|
|
** code is cleared and the cache reset in the block below.
|
|
*/
|
|
assert( pPager->errCode || pPager->eState!=PAGER_ERROR );
|
|
pPager->eState = PAGER_OPEN;
|
|
}
|
|
|
|
/* If Pager.errCode is set, the contents of the pager cache cannot be
|
|
** trusted. Now that there are no outstanding references to the pager,
|
|
** it can safely move back to PAGER_OPEN state. This happens in both
|
|
** normal and exclusive-locking mode.
|
|
*/
|
|
assert( pPager->errCode==SQLITE_OK || !MEMDB );
|
|
if( pPager->errCode ){
|
|
if( pPager->tempFile==0 ){
|
|
pager_reset(pPager);
|
|
pPager->changeCountDone = 0;
|
|
pPager->eState = PAGER_OPEN;
|
|
}else{
|
|
pPager->eState = (isOpen(pPager->jfd) ? PAGER_OPEN : PAGER_READER);
|
|
}
|
|
if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0);
|
|
pPager->errCode = SQLITE_OK;
|
|
setGetterMethod(pPager);
|
|
}
|
|
|
|
pPager->journalOff = 0;
|
|
pPager->journalHdr = 0;
|
|
pPager->setSuper = 0;
|
|
}
|
|
|
|
/*
|
|
** This function is called whenever an IOERR or FULL error that requires
|
|
** the pager to transition into the ERROR state may have occurred.
|
|
** 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_FULL, SQLITE_IOERR or one of the
|
|
** IOERR sub-codes, the pager enters the ERROR state and the error code
|
|
** is stored in Pager.errCode. While the pager remains in the ERROR state,
|
|
** all major API calls on the Pager will immediately return Pager.errCode.
|
|
**
|
|
** The ERROR state indicates that the contents of the pager-cache
|
|
** cannot be trusted. This state can be cleared by completely discarding
|
|
** the contents of the pager-cache. If a transaction was active when
|
|
** the persistent error occurred, then the rollback journal may need
|
|
** to be replayed to restore the contents of the database file (as if
|
|
** it were a hot-journal).
|
|
*/
|
|
static int pager_error(Pager *pPager, int rc){
|
|
int rc2 = rc & 0xff;
|
|
assert( rc==SQLITE_OK || !MEMDB );
|
|
assert(
|
|
pPager->errCode==SQLITE_FULL ||
|
|
pPager->errCode==SQLITE_OK ||
|
|
(pPager->errCode & 0xff)==SQLITE_IOERR
|
|
);
|
|
if( rc2==SQLITE_FULL || rc2==SQLITE_IOERR ){
|
|
pPager->errCode = rc;
|
|
pPager->eState = PAGER_ERROR;
|
|
setGetterMethod(pPager);
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
static int pager_truncate(Pager *pPager, Pgno nPage);
|
|
|
|
/*
|
|
** The write transaction open on pPager is being committed (bCommit==1)
|
|
** or rolled back (bCommit==0).
|
|
**
|
|
** Return TRUE if and only if all dirty pages should be flushed to disk.
|
|
**
|
|
** Rules:
|
|
**
|
|
** * For non-TEMP databases, always sync to disk. This is necessary
|
|
** for transactions to be durable.
|
|
**
|
|
** * Sync TEMP database only on a COMMIT (not a ROLLBACK) when the backing
|
|
** file has been created already (via a spill on pagerStress()) and
|
|
** when the number of dirty pages in memory exceeds 25% of the total
|
|
** cache size.
|
|
*/
|
|
static int pagerFlushOnCommit(Pager *pPager, int bCommit){
|
|
if( pPager->tempFile==0 ) return 1;
|
|
if( !bCommit ) return 0;
|
|
if( !isOpen(pPager->fd) ) return 0;
|
|
return (sqlite3PCachePercentDirty(pPager->pPCache)>=25);
|
|
}
|
|
|
|
/*
|
|
** This routine ends a transaction. A transaction is usually ended by
|
|
** either a COMMIT or a ROLLBACK operation. This routine may be called
|
|
** after rollback of a hot-journal, or if an error occurs while opening
|
|
** the journal file or writing the very first journal-header of a
|
|
** database transaction.
|
|
**
|
|
** This routine is never called in PAGER_ERROR state. If it is called
|
|
** in PAGER_NONE or PAGER_SHARED state and the lock held is less
|
|
** exclusive than a RESERVED lock, it is a no-op.
|
|
**
|
|
** Otherwise, any active savepoints are released.
|
|
**
|
|
** If the journal file is open, then it is "finalized". Once a journal
|
|
** file has been finalized it is not possible to use it to roll back a
|
|
** transaction. Nor will it be considered to be a hot-journal by this
|
|
** or any other database connection. Exactly how a journal is finalized
|
|
** depends on whether or not the pager is running in exclusive mode and
|
|
** the current journal-mode (Pager.journalMode value), as follows:
|
|
**
|
|
** journalMode==MEMORY
|
|
** Journal file descriptor is simply closed. This destroys an
|
|
** in-memory journal.
|
|
**
|
|
** journalMode==TRUNCATE
|
|
** Journal file is truncated to zero bytes in size.
|
|
**
|
|
** journalMode==PERSIST
|
|
** The first 28 bytes of the journal file are zeroed. This invalidates
|
|
** the first journal header in the file, and hence the entire journal
|
|
** file. An invalid journal file cannot be rolled back.
|
|
**
|
|
** journalMode==DELETE
|
|
** The journal file is closed and deleted using sqlite3OsDelete().
|
|
**
|
|
** If the pager is running in exclusive mode, this method of finalizing
|
|
** the journal file is never used. Instead, if the journalMode is
|
|
** DELETE and the pager is in exclusive mode, the method described under
|
|
** journalMode==PERSIST is used instead.
|
|
**
|
|
** After the journal is finalized, the pager moves to PAGER_READER state.
|
|
** If running in non-exclusive rollback mode, the lock on the file is
|
|
** downgraded to a SHARED_LOCK.
|
|
**
|
|
** SQLITE_OK is returned if no error occurs. If an error occurs during
|
|
** any of the IO operations to finalize the journal file or unlock the
|
|
** database then the IO error code is returned to the user. If the
|
|
** operation to finalize the journal file fails, then the code still
|
|
** tries to unlock the database file if not in exclusive mode. If the
|
|
** unlock operation fails as well, then the first error code related
|
|
** to the first error encountered (the journal finalization one) is
|
|
** returned.
|
|
*/
|
|
static int pager_end_transaction(Pager *pPager, int hasSuper, int bCommit){
|
|
int rc = SQLITE_OK; /* Error code from journal finalization operation */
|
|
int rc2 = SQLITE_OK; /* Error code from db file unlock operation */
|
|
|
|
/* Do nothing if the pager does not have an open write transaction
|
|
** or at least a RESERVED lock. This function may be called when there
|
|
** is no write-transaction active but a RESERVED or greater lock is
|
|
** held under two circumstances:
|
|
**
|
|
** 1. After a successful hot-journal rollback, it is called with
|
|
** eState==PAGER_NONE and eLock==EXCLUSIVE_LOCK.
|
|
**
|
|
** 2. If a connection with locking_mode=exclusive holding an EXCLUSIVE
|
|
** lock switches back to locking_mode=normal and then executes a
|
|
** read-transaction, this function is called with eState==PAGER_READER
|
|
** and eLock==EXCLUSIVE_LOCK when the read-transaction is closed.
|
|
*/
|
|
assert( assert_pager_state(pPager) );
|
|
assert( pPager->eState!=PAGER_ERROR );
|
|
if( pPager->eState<PAGER_WRITER_LOCKED && pPager->eLock<RESERVED_LOCK ){
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
releaseAllSavepoints(pPager);
|
|
assert( isOpen(pPager->jfd) || pPager->pInJournal==0
|
|
|| (sqlite3OsDeviceCharacteristics(pPager->fd)&SQLITE_IOCAP_BATCH_ATOMIC)
|
|
);
|
|
if( isOpen(pPager->jfd) ){
|
|
assert( !pagerUseWal(pPager) );
|
|
|
|
/* Finalize the journal file. */
|
|
if( sqlite3JournalIsInMemory(pPager->jfd) ){
|
|
/* assert( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ); */
|
|
sqlite3OsClose(pPager->jfd);
|
|
}else if( pPager->journalMode==PAGER_JOURNALMODE_TRUNCATE ){
|
|
if( pPager->journalOff==0 ){
|
|
rc = SQLITE_OK;
|
|
}else{
|
|
rc = sqlite3OsTruncate(pPager->jfd, 0);
|
|
if( rc==SQLITE_OK && pPager->fullSync ){
|
|
/* Make sure the new file size is written into the inode right away.
|
|
** Otherwise the journal might resurrect following a power loss and
|
|
** cause the last transaction to roll back. See
|
|
** https://bugzilla.mozilla.org/show_bug.cgi?id=1072773
|
|
*/
|
|
rc = sqlite3OsSync(pPager->jfd, pPager->syncFlags);
|
|
}
|
|
}
|
|
pPager->journalOff = 0;
|
|
}else if( pPager->journalMode==PAGER_JOURNALMODE_PERSIST
|
|
|| (pPager->exclusiveMode && pPager->journalMode!=PAGER_JOURNALMODE_WAL)
|
|
){
|
|
rc = zeroJournalHdr(pPager, hasSuper||pPager->tempFile);
|
|
pPager->journalOff = 0;
|
|
}else{
|
|
/* This branch may be executed with Pager.journalMode==MEMORY if
|
|
** a hot-journal was just rolled back. In this case the journal
|
|
** file should be closed and deleted. If this connection writes to
|
|
** the database file, it will do so using an in-memory journal.
|
|
*/
|
|
int bDelete = !pPager->tempFile;
|
|
assert( sqlite3JournalIsInMemory(pPager->jfd)==0 );
|
|
assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE
|
|
|| pPager->journalMode==PAGER_JOURNALMODE_MEMORY
|
|
|| pPager->journalMode==PAGER_JOURNALMODE_WAL
|
|
);
|
|
sqlite3OsClose(pPager->jfd);
|
|
if( bDelete ){
|
|
rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, pPager->extraSync);
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef SQLITE_CHECK_PAGES
|
|
sqlite3PcacheIterateDirty(pPager->pPCache, pager_set_pagehash);
|
|
if( pPager->dbSize==0 && sqlite3PcacheRefCount(pPager->pPCache)>0 ){
|
|
PgHdr *p = sqlite3PagerLookup(pPager, 1);
|
|
if( p ){
|
|
p->pageHash = 0;
|
|
sqlite3PagerUnrefNotNull(p);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
sqlite3BitvecDestroy(pPager->pInJournal);
|
|
pPager->pInJournal = 0;
|
|
pPager->nRec = 0;
|
|
if( rc==SQLITE_OK ){
|
|
if( MEMDB || pagerFlushOnCommit(pPager, bCommit) ){
|
|
sqlite3PcacheCleanAll(pPager->pPCache);
|
|
}else{
|
|
sqlite3PcacheClearWritable(pPager->pPCache);
|
|
}
|
|
sqlite3PcacheTruncate(pPager->pPCache, pPager->dbSize);
|
|
}
|
|
|
|
if( pagerUseWal(pPager) ){
|
|
/* Drop the WAL write-lock, if any. Also, if the connection was in
|
|
** locking_mode=exclusive mode but is no longer, drop the EXCLUSIVE
|
|
** lock held on the database file.
|
|
*/
|
|
rc2 = sqlite3WalEndWriteTransaction(pPager->pWal);
|
|
assert( rc2==SQLITE_OK );
|
|
}else if( rc==SQLITE_OK && bCommit && pPager->dbFileSize>pPager->dbSize ){
|
|
/* This branch is taken when committing a transaction in rollback-journal
|
|
** mode if the database file on disk is larger than the database image.
|
|
** At this point the journal has been finalized and the transaction
|
|
** successfully committed, but the EXCLUSIVE lock is still held on the
|
|
** file. So it is safe to truncate the database file to its minimum
|
|
** required size. */
|
|
assert( pPager->eLock==EXCLUSIVE_LOCK );
|
|
rc = pager_truncate(pPager, pPager->dbSize);
|
|
}
|
|
|
|
if( rc==SQLITE_OK && bCommit ){
|
|
rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_COMMIT_PHASETWO, 0);
|
|
if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
|
|
}
|
|
|
|
if( !pPager->exclusiveMode
|
|
&& (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0))
|
|
){
|
|
rc2 = pagerUnlockDb(pPager, SHARED_LOCK);
|
|
}
|
|
pPager->eState = PAGER_READER;
|
|
pPager->setSuper = 0;
|
|
|
|
return (rc==SQLITE_OK?rc2:rc);
|
|
}
|
|
|
|
/* Forward reference */
|
|
static int pager_playback(Pager *pPager, int isHot);
|
|
|
|
/*
|
|
** Execute a rollback if a transaction is active and unlock the
|
|
** database file.
|
|
**
|
|
** If the pager has already entered the ERROR state, do not attempt
|
|
** the rollback at this time. Instead, pager_unlock() is called. The
|
|
** call to pager_unlock() will discard all in-memory pages, unlock
|
|
** the database file and move the pager back to OPEN state. If this
|
|
** means that there is a hot-journal left in the file-system, the next
|
|
** connection to obtain a shared lock on the pager (which may be this one)
|
|
** will roll it back.
|
|
**
|
|
** If the pager has not already entered the ERROR state, but an IO or
|
|
** malloc error occurs during a rollback, then this will itself cause
|
|
** the pager to enter the ERROR state. Which will be cleared by the
|
|
** call to pager_unlock(), as described above.
|
|
*/
|
|
static void pagerUnlockAndRollback(Pager *pPager){
|
|
if( pPager->eState!=PAGER_ERROR && pPager->eState!=PAGER_OPEN ){
|
|
assert( assert_pager_state(pPager) );
|
|
if( pPager->eState>=PAGER_WRITER_LOCKED ){
|
|
sqlite3BeginBenignMalloc();
|
|
sqlite3PagerRollback(pPager);
|
|
sqlite3EndBenignMalloc();
|
|
}else if( !pPager->exclusiveMode ){
|
|
assert( pPager->eState==PAGER_READER );
|
|
pager_end_transaction(pPager, 0, 0);
|
|
}
|
|
}else if( pPager->eState==PAGER_ERROR
|
|
&& pPager->journalMode==PAGER_JOURNALMODE_MEMORY
|
|
&& isOpen(pPager->jfd)
|
|
){
|
|
/* Special case for a ROLLBACK due to I/O error with an in-memory
|
|
** journal: We have to rollback immediately, before the journal is
|
|
** closed, because once it is closed, all content is forgotten. */
|
|
int errCode = pPager->errCode;
|
|
u8 eLock = pPager->eLock;
|
|
pPager->eState = PAGER_OPEN;
|
|
pPager->errCode = SQLITE_OK;
|
|
pPager->eLock = EXCLUSIVE_LOCK;
|
|
pager_playback(pPager, 1);
|
|
pPager->errCode = errCode;
|
|
pPager->eLock = eLock;
|
|
}
|
|
pager_unlock(pPager);
|
|
}
|
|
|
|
/*
|
|
** Parameter aData must point to a buffer of pPager->pageSize bytes
|
|
** of data. Compute and return a checksum based on the contents of the
|
|
** page of data and the current value of pPager->cksumInit.
|
|
**
|
|
** This is not a real checksum. It is really just the sum of the
|
|
** random initial value (pPager->cksumInit) and every 200th byte
|
|
** of the page data, starting with byte offset (pPager->pageSize%200).
|
|
** Each byte is interpreted as an 8-bit unsigned integer.
|
|
**
|
|
** Changing the formula used to compute this checksum results in an
|
|
** incompatible journal file format.
|
|
**
|
|
** 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.
|
|
*/
|
|
static u32 pager_cksum(Pager *pPager, const u8 *aData){
|
|
u32 cksum = pPager->cksumInit; /* Checksum value to return */
|
|
int i = pPager->pageSize-200; /* Loop counter */
|
|
while( i>0 ){
|
|
cksum += aData[i];
|
|
i -= 200;
|
|
}
|
|
return cksum;
|
|
}
|
|
|
|
/*
|
|
** Read a single page from either the journal file (if isMainJrnl==1) or
|
|
** from the sub-journal (if isMainJrnl==0) and playback that page.
|
|
** The page begins at offset *pOffset into the file. The *pOffset
|
|
** value is increased to the start of the next page in the journal.
|
|
**
|
|
** The main rollback journal uses checksums - the statement journal does
|
|
** not.
|
|
**
|
|
** If the page number of the page record read from the (sub-)journal file
|
|
** is greater than the current value of Pager.dbSize, then playback is
|
|
** skipped and SQLITE_OK is returned.
|
|
**
|
|
** If pDone is not NULL, then it is a record of pages that have already
|
|
** been played back. If the page at *pOffset has already been played back
|
|
** (if the corresponding pDone bit is set) then skip the playback.
|
|
** Make sure the pDone bit corresponding to the *pOffset page is set
|
|
** prior to returning.
|
|
**
|
|
** If the page record is successfully read from the (sub-)journal file
|
|
** and played back, then SQLITE_OK is returned. If an IO error occurs
|
|
** while reading the record from the (sub-)journal file or while writing
|
|
** to the database file, then the IO error code is returned. If data
|
|
** is successfully read from the (sub-)journal file but appears to be
|
|
** corrupted, SQLITE_DONE is returned. Data is considered corrupted in
|
|
** two circumstances:
|
|
**
|
|
** * If the record page-number is illegal (0 or PAGER_SJ_PGNO), or
|
|
** * If the record is being rolled back from the main journal file
|
|
** and the checksum field does not match the record content.
|
|
**
|
|
** Neither of these two scenarios are possible during a savepoint rollback.
|
|
**
|
|
** If this is a savepoint rollback, then memory may have to be dynamically
|
|
** allocated by this function. If this is the case and an allocation fails,
|
|
** SQLITE_NOMEM is returned.
|
|
*/
|
|
static int pager_playback_one_page(
|
|
Pager *pPager, /* The pager being played back */
|
|
i64 *pOffset, /* Offset of record to playback */
|
|
Bitvec *pDone, /* Bitvec of pages already played back */
|
|
int isMainJrnl, /* 1 -> main journal. 0 -> sub-journal. */
|
|
int isSavepnt /* True for a savepoint rollback */
|
|
){
|
|
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 */
|
|
char *aData; /* Temporary storage for the page */
|
|
sqlite3_file *jfd; /* The file descriptor for the journal file */
|
|
int isSynced; /* True if journal page is synced */
|
|
|
|
assert( (isMainJrnl&~1)==0 ); /* isMainJrnl is 0 or 1 */
|
|
assert( (isSavepnt&~1)==0 ); /* isSavepnt is 0 or 1 */
|
|
assert( isMainJrnl || pDone ); /* pDone always used on sub-journals */
|
|
assert( isSavepnt || pDone==0 ); /* pDone never used on non-savepoint */
|
|
|
|
aData = pPager->pTmpSpace;
|
|
assert( aData ); /* Temp storage must have already been allocated */
|
|
assert( pagerUseWal(pPager)==0 || (!isMainJrnl && isSavepnt) );
|
|
|
|
/* Either the state is greater than PAGER_WRITER_CACHEMOD (a transaction
|
|
** or savepoint rollback done at the request of the caller) or this is
|
|
** a hot-journal rollback. If it is a hot-journal rollback, the pager
|
|
** is in state OPEN and holds an EXCLUSIVE lock. Hot-journal rollback
|
|
** only reads from the main journal, not the sub-journal.
|
|
*/
|
|
assert( pPager->eState>=PAGER_WRITER_CACHEMOD
|
|
|| (pPager->eState==PAGER_OPEN && pPager->eLock==EXCLUSIVE_LOCK)
|
|
);
|
|
assert( pPager->eState>=PAGER_WRITER_CACHEMOD || isMainJrnl );
|
|
|
|
/* Read the page number and page data from the journal or sub-journal
|
|
** file. Return an error code to the caller if an IO error occurs.
|
|
*/
|
|
jfd = isMainJrnl ? pPager->jfd : pPager->sjfd;
|
|
rc = read32bits(jfd, *pOffset, &pgno);
|
|
if( rc!=SQLITE_OK ) return rc;
|
|
rc = sqlite3OsRead(jfd, (u8*)aData, pPager->pageSize, (*pOffset)+4);
|
|
if( rc!=SQLITE_OK ) return rc;
|
|
*pOffset += pPager->pageSize + 4 + isMainJrnl*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_SJ_PGNO(pPager) ){
|
|
assert( !isSavepnt );
|
|
return SQLITE_DONE;
|
|
}
|
|
if( pgno>(Pgno)pPager->dbSize || sqlite3BitvecTest(pDone, pgno) ){
|
|
return SQLITE_OK;
|
|
}
|
|
if( isMainJrnl ){
|
|
rc = read32bits(jfd, (*pOffset)-4, &cksum);
|
|
if( rc ) return rc;
|
|
if( !isSavepnt && pager_cksum(pPager, (u8*)aData)!=cksum ){
|
|
return SQLITE_DONE;
|
|
}
|
|
}
|
|
|
|
/* If this page has already been played back before during the current
|
|
** rollback, then don't bother to play it back again.
|
|
*/
|
|
if( pDone && (rc = sqlite3BitvecSet(pDone, pgno))!=SQLITE_OK ){
|
|
return rc;
|
|
}
|
|
|
|
/* When playing back page 1, restore the nReserve setting
|
|
*/
|
|
if( pgno==1 && pPager->nReserve!=((u8*)aData)[20] ){
|
|
pPager->nReserve = ((u8*)aData)[20];
|
|
}
|
|
|
|
/* If the pager is in CACHEMOD 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 WRITER_DBMOD, WRITER_FINISHED or OPEN state, then we update the
|
|
** pager cache if it exists and the main file. The page is then marked
|
|
** not dirty. Since this code is only executed in PAGER_OPEN state for
|
|
** a hot-journal rollback, it is guaranteed that the page-cache is empty
|
|
** if the pager is in OPEN state.
|
|
**
|
|
** 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.
|
|
**
|
|
** 2008-04-14: When attempting to vacuum a corrupt database file, it
|
|
** is possible to fail a statement on a database that does not yet exist.
|
|
** Do not attempt to write if database file has never been opened.
|
|
*/
|
|
if( pagerUseWal(pPager) ){
|
|
pPg = 0;
|
|
}else{
|
|
pPg = sqlite3PagerLookup(pPager, pgno);
|
|
}
|
|
assert( pPg || !MEMDB );
|
|
assert( pPager->eState!=PAGER_OPEN || pPg==0 || pPager->tempFile );
|
|
PAGERTRACE(("PLAYBACK %d page %d hash(%08x) %s\n",
|
|
PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, (u8*)aData),
|
|
(isMainJrnl?"main-journal":"sub-journal")
|
|
));
|
|
if( isMainJrnl ){
|
|
isSynced = pPager->noSync || (*pOffset <= pPager->journalHdr);
|
|
}else{
|
|
isSynced = (pPg==0 || 0==(pPg->flags & PGHDR_NEED_SYNC));
|
|
}
|
|
if( isOpen(pPager->fd)
|
|
&& (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
|
|
&& isSynced
|
|
){
|
|
i64 ofst = (pgno-1)*(i64)pPager->pageSize;
|
|
testcase( !isSavepnt && pPg!=0 && (pPg->flags&PGHDR_NEED_SYNC)!=0 );
|
|
assert( !pagerUseWal(pPager) );
|
|
|
|
/* Write the data read from the journal back into the database file.
|
|
** This is usually safe even for an encrypted database - as the data
|
|
** was encrypted before it was written to the journal file. The exception
|
|
** is if the data was just read from an in-memory sub-journal. In that
|
|
** case it must be encrypted here before it is copied into the database
|
|
** file. */
|
|
rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst);
|
|
|
|
if( pgno>pPager->dbFileSize ){
|
|
pPager->dbFileSize = pgno;
|
|
}
|
|
if( pPager->pBackup ){
|
|
sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData);
|
|
}
|
|
}else if( !isMainJrnl && pPg==0 ){
|
|
/* If this is a rollback of a savepoint and data was not written to
|
|
** the database and the page is not in-memory, there is a potential
|
|
** problem. When the page is next fetched by the b-tree layer, it
|
|
** will be read from the database file, which may or may not be
|
|
** current.
|
|
**
|
|
** There are a couple of different ways this can happen. All are quite
|
|
** obscure. When running in synchronous mode, this can only happen
|
|
** if the page is on the free-list at the start of the transaction, then
|
|
** populated, then moved using sqlite3PagerMovepage().
|
|
**
|
|
** The solution is to add an in-memory page to the cache containing
|
|
** the data just read from the sub-journal. Mark the page as dirty
|
|
** and if the pager requires a journal-sync, then mark the page as
|
|
** requiring a journal-sync before it is written.
|
|
*/
|
|
assert( isSavepnt );
|
|
assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)==0 );
|
|
pPager->doNotSpill |= SPILLFLAG_ROLLBACK;
|
|
rc = sqlite3PagerGet(pPager, pgno, &pPg, 1);
|
|
assert( (pPager->doNotSpill & SPILLFLAG_ROLLBACK)!=0 );
|
|
pPager->doNotSpill &= ~SPILLFLAG_ROLLBACK;
|
|
if( rc!=SQLITE_OK ) return rc;
|
|
sqlite3PcacheMakeDirty(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;
|
|
pData = pPg->pData;
|
|
memcpy(pData, (u8*)aData, pPager->pageSize);
|
|
pPager->xReiniter(pPg);
|
|
/* It used to be that sqlite3PcacheMakeClean(pPg) was called here. But
|
|
** that call was dangerous and had no detectable benefit since the cache
|
|
** is normally cleaned by sqlite3PcacheCleanAll() after rollback and so
|
|
** has been removed. */
|
|
pager_set_pagehash(pPg);
|
|
|
|
/* 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));
|
|
}
|
|
sqlite3PcacheRelease(pPg);
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Parameter zSuper is the name of a super-journal file. A single journal
|
|
** file that referred to the super-journal file has just been rolled back.
|
|
** This routine checks if it is possible to delete the super-journal file,
|
|
** and does so if it is.
|
|
**
|
|
** Argument zSuper may point to Pager.pTmpSpace. So that buffer is not
|
|
** available for use within this function.
|
|
**
|
|
** When a super-journal file is created, it is populated with the names
|
|
** of all of its child journals, one after another, formatted as utf-8
|
|
** encoded text. The end of each child journal file is marked with a
|
|
** nul-terminator byte (0x00). i.e. the entire contents of a super-journal
|
|
** file for a transaction involving two databases might be:
|
|
**
|
|
** "/home/bill/a.db-journal\x00/home/bill/b.db-journal\x00"
|
|
**
|
|
** A super-journal file may only be deleted once all of its child
|
|
** journals have been rolled back.
|
|
**
|
|
** This function reads the contents of the super-journal file into
|
|
** memory and loops through each of the child journal names. For
|
|
** each child journal, it checks if:
|
|
**
|
|
** * if the child journal exists, and if so
|
|
** * if the child journal contains a reference to super-journal
|
|
** file zSuper
|
|
**
|
|
** If a child journal can be found that matches both of the criteria
|
|
** above, this function returns without doing anything. Otherwise, if
|
|
** no such child journal can be found, file zSuper is deleted from
|
|
** the file-system using sqlite3OsDelete().
|
|
**
|
|
** If an IO error within this function, an error code is returned. This
|
|
** function allocates memory by calling sqlite3Malloc(). If an allocation
|
|
** fails, SQLITE_NOMEM is returned. Otherwise, if no IO or malloc errors
|
|
** occur, SQLITE_OK is returned.
|
|
**
|
|
** TODO: This function allocates a single block of memory to load
|
|
** the entire contents of the super-journal file. This could be
|
|
** a couple of kilobytes or so - potentially larger than the page
|
|
** size.
|
|
*/
|
|
static int pager_delsuper(Pager *pPager, const char *zSuper){
|
|
sqlite3_vfs *pVfs = pPager->pVfs;
|
|
int rc; /* Return code */
|
|
sqlite3_file *pSuper; /* Malloc'd super-journal file descriptor */
|
|
sqlite3_file *pJournal; /* Malloc'd child-journal file descriptor */
|
|
char *zSuperJournal = 0; /* Contents of super-journal file */
|
|
i64 nSuperJournal; /* Size of super-journal file */
|
|
char *zJournal; /* Pointer to one journal within MJ file */
|
|
char *zSuperPtr; /* Space to hold super-journal filename */
|
|
char *zFree = 0; /* Free this buffer */
|
|
int nSuperPtr; /* Amount of space allocated to zSuperPtr[] */
|
|
|
|
/* Allocate space for both the pJournal and pSuper file descriptors.
|
|
** If successful, open the super-journal file for reading.
|
|
*/
|
|
pSuper = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile * 2);
|
|
if( !pSuper ){
|
|
rc = SQLITE_NOMEM_BKPT;
|
|
pJournal = 0;
|
|
}else{
|
|
const int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_SUPER_JOURNAL);
|
|
rc = sqlite3OsOpen(pVfs, zSuper, pSuper, flags, 0);
|
|
pJournal = (sqlite3_file *)(((u8 *)pSuper) + pVfs->szOsFile);
|
|
}
|
|
if( rc!=SQLITE_OK ) goto delsuper_out;
|
|
|
|
/* Load the entire super-journal file into space obtained from
|
|
** sqlite3_malloc() and pointed to by zSuperJournal. Also obtain
|
|
** sufficient space (in zSuperPtr) to hold the names of super-journal
|
|
** files extracted from regular rollback-journals.
|
|
*/
|
|
rc = sqlite3OsFileSize(pSuper, &nSuperJournal);
|
|
if( rc!=SQLITE_OK ) goto delsuper_out;
|
|
nSuperPtr = pVfs->mxPathname+1;
|
|
zFree = sqlite3Malloc(4 + nSuperJournal + nSuperPtr + 2);
|
|
if( !zFree ){
|
|
rc = SQLITE_NOMEM_BKPT;
|
|
goto delsuper_out;
|
|
}
|
|
zFree[0] = zFree[1] = zFree[2] = zFree[3] = 0;
|
|
zSuperJournal = &zFree[4];
|
|
zSuperPtr = &zSuperJournal[nSuperJournal+2];
|
|
rc = sqlite3OsRead(pSuper, zSuperJournal, (int)nSuperJournal, 0);
|
|
if( rc!=SQLITE_OK ) goto delsuper_out;
|
|
zSuperJournal[nSuperJournal] = 0;
|
|
zSuperJournal[nSuperJournal+1] = 0;
|
|
|
|
zJournal = zSuperJournal;
|
|
while( (zJournal-zSuperJournal)<nSuperJournal ){
|
|
int exists;
|
|
rc = sqlite3OsAccess(pVfs, zJournal, SQLITE_ACCESS_EXISTS, &exists);
|
|
if( rc!=SQLITE_OK ){
|
|
goto delsuper_out;
|
|
}
|
|
if( exists ){
|
|
/* One of the journals pointed to by the super-journal exists.
|
|
** Open it and check if it points at the super-journal. If
|
|
** so, return without deleting the super-journal file.
|
|
** NB: zJournal is really a MAIN_JOURNAL. But call it a
|
|
** SUPER_JOURNAL here so that the VFS will not send the zJournal
|
|
** name into sqlite3_database_file_object().
|
|
*/
|
|
int c;
|
|
int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_SUPER_JOURNAL);
|
|
rc = sqlite3OsOpen(pVfs, zJournal, pJournal, flags, 0);
|
|
if( rc!=SQLITE_OK ){
|
|
goto delsuper_out;
|
|
}
|
|
|
|
rc = readSuperJournal(pJournal, zSuperPtr, nSuperPtr);
|
|
sqlite3OsClose(pJournal);
|
|
if( rc!=SQLITE_OK ){
|
|
goto delsuper_out;
|
|
}
|
|
|
|
c = zSuperPtr[0]!=0 && strcmp(zSuperPtr, zSuper)==0;
|
|
if( c ){
|
|
/* We have a match. Do not delete the super-journal file. */
|
|
goto delsuper_out;
|
|
}
|
|
}
|
|
zJournal += (sqlite3Strlen30(zJournal)+1);
|
|
}
|
|
|
|
sqlite3OsClose(pSuper);
|
|
rc = sqlite3OsDelete(pVfs, zSuper, 0);
|
|
|
|
delsuper_out:
|
|
sqlite3_free(zFree);
|
|
if( pSuper ){
|
|
sqlite3OsClose(pSuper);
|
|
assert( !isOpen(pJournal) );
|
|
sqlite3_free(pSuper);
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
|
|
/*
|
|
** This function is used to change the actual size of the database
|
|
** file in the file-system. This only happens when committing a transaction,
|
|
** or rolling back a transaction (including rolling back a hot-journal).
|
|
**
|
|
** If the main database file is not open, or the pager is not in either
|
|
** DBMOD or OPEN state, this function is a no-op. Otherwise, the size
|
|
** of the file is changed to nPage pages (nPage*pPager->pageSize bytes).
|
|
** If the file on disk is currently larger than nPage pages, then use the VFS
|
|
** xTruncate() method to truncate it.
|
|
**
|
|
** Or, it might be the case that the file on disk is smaller than
|
|
** nPage pages. Some operating system implementations can get confused if
|
|
** you try to truncate a file to some size that is larger than it
|
|
** currently is, so detect this case and write a single zero byte to
|
|
** the end of the new file instead.
|
|
**
|
|
** If successful, return SQLITE_OK. If an IO error occurs while modifying
|
|
** the database file, return the error code to the caller.
|
|
*/
|
|
static int pager_truncate(Pager *pPager, Pgno nPage){
|
|
int rc = SQLITE_OK;
|
|
assert( pPager->eState!=PAGER_ERROR );
|
|
assert( pPager->eState!=PAGER_READER );
|
|
PAGERTRACE(("Truncate %d npage %u\n", PAGERID(pPager), nPage));
|
|
|
|
|
|
if( isOpen(pPager->fd)
|
|
&& (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
|
|
){
|
|
i64 currentSize, newSize;
|
|
int szPage = pPager->pageSize;
|
|
assert( pPager->eLock==EXCLUSIVE_LOCK );
|
|
/* TODO: Is it safe to use Pager.dbFileSize here? */
|
|
rc = sqlite3OsFileSize(pPager->fd, ¤tSize);
|
|
newSize = szPage*(i64)nPage;
|
|
if( rc==SQLITE_OK && currentSize!=newSize ){
|
|
if( currentSize>newSize ){
|
|
rc = sqlite3OsTruncate(pPager->fd, newSize);
|
|
}else if( (currentSize+szPage)<=newSize ){
|
|
char *pTmp = pPager->pTmpSpace;
|
|
memset(pTmp, 0, szPage);
|
|
testcase( (newSize-szPage) == currentSize );
|
|
testcase( (newSize-szPage) > currentSize );
|
|
sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_SIZE_HINT, &newSize);
|
|
rc = sqlite3OsWrite(pPager->fd, pTmp, szPage, newSize-szPage);
|
|
}
|
|
if( rc==SQLITE_OK ){
|
|
pPager->dbFileSize = nPage;
|
|
}
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Return a sanitized version of the sector-size of OS file pFile. The
|
|
** return value is guaranteed to lie between 32 and MAX_SECTOR_SIZE.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *pFile){
|
|
int iRet = sqlite3OsSectorSize(pFile);
|
|
if( iRet<32 ){
|
|
iRet = 512;
|
|
}else if( iRet>MAX_SECTOR_SIZE ){
|
|
assert( MAX_SECTOR_SIZE>=512 );
|
|
iRet = MAX_SECTOR_SIZE;
|
|
}
|
|
return iRet;
|
|
}
|
|
|
|
/*
|
|
** Set the value of the Pager.sectorSize variable for the given
|
|
** pager based on the value returned by the xSectorSize method
|
|
** of the open database file. The sector size will be used
|
|
** to determine the size and alignment of journal header and
|
|
** super-journal pointers within created journal files.
|
|
**
|
|
** For temporary files the effective sector size is always 512 bytes.
|
|
**
|
|
** Otherwise, for non-temporary files, the effective sector size is
|
|
** the value returned by the xSectorSize() method rounded up to 32 if
|
|
** it is less than 32, or rounded down to MAX_SECTOR_SIZE if it
|
|
** is greater than MAX_SECTOR_SIZE.
|
|
**
|
|
** If the file has the SQLITE_IOCAP_POWERSAFE_OVERWRITE property, then set
|
|
** the effective sector size to its minimum value (512). The purpose of
|
|
** pPager->sectorSize is to define the "blast radius" of bytes that
|
|
** might change if a crash occurs while writing to a single byte in
|
|
** that range. But with POWERSAFE_OVERWRITE, the blast radius is zero
|
|
** (that is what POWERSAFE_OVERWRITE means), so we minimize the sector
|
|
** size. For backwards compatibility of the rollback journal file format,
|
|
** we cannot reduce the effective sector size below 512.
|
|
*/
|
|
static void setSectorSize(Pager *pPager){
|
|
assert( isOpen(pPager->fd) || pPager->tempFile );
|
|
|
|
if( pPager->tempFile
|
|
|| (sqlite3OsDeviceCharacteristics(pPager->fd) &
|
|
SQLITE_IOCAP_POWERSAFE_OVERWRITE)!=0
|
|
){
|
|
/* Sector size doesn't matter for temporary files. Also, the file
|
|
** may not have been opened yet, in which case the OsSectorSize()
|
|
** call will segfault. */
|
|
pPager->sectorSize = 512;
|
|
}else{
|
|
pPager->sectorSize = sqlite3SectorSize(pPager->fd);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** 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 big-endian integer which is the sector size. The header
|
|
** is this many bytes in size.
|
|
** (6) 4 byte big-endian integer which is the page size.
|
|
** (7) zero padding out to the next sector size.
|
|
** (8) 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 7 items above.
|
|
** Each entry in the journal is an instance of the 8th 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.
|
|
**
|
|
** The isHot parameter indicates that we are trying to rollback a journal
|
|
** that might be a hot journal. Or, it could be that the journal is
|
|
** preserved because of JOURNALMODE_PERSIST or JOURNALMODE_TRUNCATE.
|
|
** If the journal really is hot, reset the pager cache prior rolling
|
|
** back any content. If the journal is merely persistent, no reset is
|
|
** needed.
|
|
*/
|
|
static int pager_playback(Pager *pPager, int isHot){
|
|
sqlite3_vfs *pVfs = pPager->pVfs;
|
|
i64 szJ; /* Size of the journal file in bytes */
|
|
u32 nRec; /* Number of Records in the journal */
|
|
u32 u; /* Unsigned loop counter */
|
|
Pgno mxPg = 0; /* Size of the original file in pages */
|
|
int rc; /* Result code of a subroutine */
|
|
int res = 1; /* Value returned by sqlite3OsAccess() */
|
|
char *zSuper = 0; /* Name of super-journal file if any */
|
|
int needPagerReset; /* True to reset page prior to first page rollback */
|
|
int nPlayback = 0; /* Total number of pages restored from journal */
|
|
u32 savedPageSize = pPager->pageSize;
|
|
|
|
/* Figure out how many records are in the journal. Abort early if
|
|
** the journal is empty.
|
|
*/
|
|
assert( isOpen(pPager->jfd) );
|
|
rc = sqlite3OsFileSize(pPager->jfd, &szJ);
|
|
if( rc!=SQLITE_OK ){
|
|
goto end_playback;
|
|
}
|
|
|
|
/* Read the super-journal name from the journal, if it is present.
|
|
** If a super-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.
|
|
**
|
|
** TODO: Technically the following is an error because it assumes that
|
|
** buffer Pager.pTmpSpace is (mxPathname+1) bytes or larger. i.e. that
|
|
** (pPager->pageSize >= pPager->pVfs->mxPathname+1). Using os_unix.c,
|
|
** mxPathname is 512, which is the same as the minimum allowable value
|
|
** for pageSize.
|
|
*/
|
|
zSuper = pPager->pTmpSpace;
|
|
rc = readSuperJournal(pPager->jfd, zSuper, pPager->pVfs->mxPathname+1);
|
|
if( rc==SQLITE_OK && zSuper[0] ){
|
|
rc = sqlite3OsAccess(pVfs, zSuper, SQLITE_ACCESS_EXISTS, &res);
|
|
}
|
|
zSuper = 0;
|
|
if( rc!=SQLITE_OK || !res ){
|
|
goto end_playback;
|
|
}
|
|
pPager->journalOff = 0;
|
|
needPagerReset = isHot;
|
|
|
|
/* This loop terminates either when a readJournalHdr() or
|
|
** pager_playback_one_page() 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 have failed while writing it.
|
|
** This indicates nothing more needs to be rolled back.
|
|
*/
|
|
rc = readJournalHdr(pPager, isHot, 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 = (int)((szJ - JOURNAL_HDR_SZ(pPager))/JOURNAL_PG_SZ(pPager));
|
|
}
|
|
|
|
/* If nRec is 0 and this rollback is of a transaction created by this
|
|
** process and if this is the final header in the journal, then it means
|
|
** that this part of the journal was being filled but has not yet been
|
|
** synced to disk. Compute the number of pages based on the remaining
|
|
** size of the file.
|
|
**
|
|
** The third term of the test was added to fix ticket #2565.
|
|
** When rolling back a hot journal, nRec==0 always means that the next
|
|
** chunk of the journal contains zero pages to be rolled back. But
|
|
** when doing a ROLLBACK and the nRec==0 chunk is the last chunk in
|
|
** the journal, it means that the journal might contain additional
|
|
** pages that need to be rolled back and that the number of pages
|
|
** should be computed based on the journal file size.
|
|
*/
|
|
if( nRec==0 && !isHot &&
|
|
pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff ){
|
|
nRec = (int)((szJ - pPager->journalOff) / JOURNAL_PG_SZ(pPager));
|
|
}
|
|
|
|
/* If this is the first header read from the journal, truncate the
|
|
** database file back to its original size.
|
|
*/
|
|
if( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){
|
|
rc = pager_truncate(pPager, mxPg);
|
|
if( rc!=SQLITE_OK ){
|
|
goto end_playback;
|
|
}
|
|
pPager->dbSize = mxPg;
|
|
if( pPager->mxPgno<mxPg ){
|
|
pPager->mxPgno = mxPg;
|
|
}
|
|
}
|
|
|
|
/* Copy original pages out of the journal and back into the
|
|
** database file and/or page cache.
|
|
*/
|
|
for(u=0; u<nRec; u++){
|
|
if( needPagerReset ){
|
|
pager_reset(pPager);
|
|
needPagerReset = 0;
|
|
}
|
|
rc = pager_playback_one_page(pPager,&pPager->journalOff,0,1,0);
|
|
if( rc==SQLITE_OK ){
|
|
nPlayback++;
|
|
}else{
|
|
if( rc==SQLITE_DONE ){
|
|
pPager->journalOff = szJ;
|
|
break;
|
|
}else if( rc==SQLITE_IOERR_SHORT_READ ){
|
|
/* If the journal has been truncated, simply stop reading and
|
|
** processing the journal. This might happen if the journal was
|
|
** not completely written and synced prior to a crash. In that
|
|
** case, the database should have never been written in the
|
|
** first place so it is OK to simply abandon the rollback. */
|
|
rc = SQLITE_OK;
|
|
goto end_playback;
|
|
}else{
|
|
/* If we are unable to rollback, quit and return the error
|
|
** code. This will cause the pager to enter the error state
|
|
** so that no further harm will be done. Perhaps the next
|
|
** process to come along will be able to rollback the database.
|
|
*/
|
|
goto end_playback;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/*NOTREACHED*/
|
|
assert( 0 );
|
|
|
|
end_playback:
|
|
if( rc==SQLITE_OK ){
|
|
rc = sqlite3PagerSetPagesize(pPager, &savedPageSize, -1);
|
|
}
|
|
/* Following a rollback, the database file should be back in its original
|
|
** state prior to the start of the transaction, so invoke the
|
|
** SQLITE_FCNTL_DB_UNCHANGED file-control method to disable the
|
|
** assertion that the transaction counter was modified.
|
|
*/
|
|
#ifdef SQLITE_DEBUG
|
|
sqlite3OsFileControlHint(pPager->fd,SQLITE_FCNTL_DB_UNCHANGED,0);
|
|
#endif
|
|
|
|
/* If this playback is happening automatically as a result of an IO or
|
|
** malloc error that occurred after the change-counter was updated but
|
|
** before the transaction was committed, then the change-counter
|
|
** modification may just have been reverted. If this happens in exclusive
|
|
** mode, then subsequent transactions performed by the connection will not
|
|
** update the change-counter at all. This may lead to cache inconsistency
|
|
** problems for other processes at some point in the future. So, just
|
|
** in case this has happened, clear the changeCountDone flag now.
|
|
*/
|
|
pPager->changeCountDone = pPager->tempFile;
|
|
|
|
if( rc==SQLITE_OK ){
|
|
/* Leave 4 bytes of space before the super-journal filename in memory.
|
|
** This is because it may end up being passed to sqlite3OsOpen(), in
|
|
** which case it requires 4 0x00 bytes in memory immediately before
|
|
** the filename. */
|
|
zSuper = &pPager->pTmpSpace[4];
|
|
rc = readSuperJournal(pPager->jfd, zSuper, pPager->pVfs->mxPathname+1);
|
|
testcase( rc!=SQLITE_OK );
|
|
}
|
|
if( rc==SQLITE_OK
|
|
&& (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
|
|
){
|
|
rc = sqlite3PagerSync(pPager, 0);
|
|
}
|
|
if( rc==SQLITE_OK ){
|
|
rc = pager_end_transaction(pPager, zSuper[0]!='\0', 0);
|
|
testcase( rc!=SQLITE_OK );
|
|
}
|
|
if( rc==SQLITE_OK && zSuper[0] && res ){
|
|
/* If there was a super-journal and this routine will return success,
|
|
** see if it is possible to delete the super-journal.
|
|
*/
|
|
assert( zSuper==&pPager->pTmpSpace[4] );
|
|
memset(pPager->pTmpSpace, 0, 4);
|
|
rc = pager_delsuper(pPager, zSuper);
|
|
testcase( rc!=SQLITE_OK );
|
|
}
|
|
if( isHot && nPlayback ){
|
|
sqlite3_log(SQLITE_NOTICE_RECOVER_ROLLBACK, "recovered %d pages from %s",
|
|
nPlayback, pPager->zJournal);
|
|
}
|
|
|
|
/* 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;
|
|
}
|
|
|
|
|
|
/*
|
|
** Read the content for page pPg out of the database file (or out of
|
|
** the WAL if that is where the most recent copy if found) into
|
|
** pPg->pData. A shared lock or greater must be held on the database
|
|
** file before this function is called.
|
|
**
|
|
** If page 1 is read, then the value of Pager.dbFileVers[] is set to
|
|
** the value read from the database file.
|
|
**
|
|
** If an IO error occurs, then the IO error is returned to the caller.
|
|
** Otherwise, SQLITE_OK is returned.
|
|
*/
|
|
static int readDbPage(PgHdr *pPg){
|
|
Pager *pPager = pPg->pPager; /* Pager object associated with page pPg */
|
|
int rc = SQLITE_OK; /* Return code */
|
|
|
|
#ifndef SQLITE_OMIT_WAL
|
|
u32 iFrame = 0; /* Frame of WAL containing pgno */
|
|
|
|
assert( pPager->eState>=PAGER_READER && !MEMDB );
|
|
assert( isOpen(pPager->fd) );
|
|
|
|
if( pagerUseWal(pPager) ){
|
|
rc = sqlite3WalFindFrame(pPager->pWal, pPg->pgno, &iFrame);
|
|
if( rc ) return rc;
|
|
}
|
|
if( iFrame ){
|
|
rc = sqlite3WalReadFrame(pPager->pWal, iFrame,pPager->pageSize,pPg->pData);
|
|
}else
|
|
#endif
|
|
{
|
|
i64 iOffset = (pPg->pgno-1)*(i64)pPager->pageSize;
|
|
rc = sqlite3OsRead(pPager->fd, pPg->pData, pPager->pageSize, iOffset);
|
|
if( rc==SQLITE_IOERR_SHORT_READ ){
|
|
rc = SQLITE_OK;
|
|
}
|
|
}
|
|
|
|
if( pPg->pgno==1 ){
|
|
if( rc ){
|
|
/* If the read is unsuccessful, set the dbFileVers[] to something
|
|
** that will never be a valid file version. dbFileVers[] is a copy
|
|
** of bytes 24..39 of the database. Bytes 28..31 should always be
|
|
** zero or the size of the database in page. Bytes 32..35 and 35..39
|
|
** should be page numbers which are never 0xffffffff. So filling
|
|
** pPager->dbFileVers[] with all 0xff bytes should suffice.
|
|
**
|
|
** For an encrypted database, the situation is more complex: bytes
|
|
** 24..39 of the database are white noise. But the probability of
|
|
** white noise equaling 16 bytes of 0xff is vanishingly small so
|
|
** we should still be ok.
|
|
*/
|
|
memset(pPager->dbFileVers, 0xff, sizeof(pPager->dbFileVers));
|
|
}else{
|
|
u8 *dbFileVers = &((u8*)pPg->pData)[24];
|
|
memcpy(&pPager->dbFileVers, dbFileVers, sizeof(pPager->dbFileVers));
|
|
}
|
|
}
|
|
PAGER_INCR(sqlite3_pager_readdb_count);
|
|
PAGER_INCR(pPager->nRead);
|
|
IOTRACE(("PGIN %p %d\n", pPager, pPg->pgno));
|
|
PAGERTRACE(("FETCH %d page %d hash(%08x)\n",
|
|
PAGERID(pPager), pPg->pgno, pager_pagehash(pPg)));
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Update the value of the change-counter at offsets 24 and 92 in
|
|
** the header and the sqlite version number at offset 96.
|
|
**
|
|
** This is an unconditional update. See also the pager_incr_changecounter()
|
|
** routine which only updates the change-counter if the update is actually
|
|
** needed, as determined by the pPager->changeCountDone state variable.
|
|
*/
|
|
static void pager_write_changecounter(PgHdr *pPg){
|
|
u32 change_counter;
|
|
if( NEVER(pPg==0) ) return;
|
|
|
|
/* Increment the value just read and write it back to byte 24. */
|
|
change_counter = sqlite3Get4byte((u8*)pPg->pPager->dbFileVers)+1;
|
|
put32bits(((char*)pPg->pData)+24, change_counter);
|
|
|
|
/* Also store the SQLite version number in bytes 96..99 and in
|
|
** bytes 92..95 store the change counter for which the version number
|
|
** is valid. */
|
|
put32bits(((char*)pPg->pData)+92, change_counter);
|
|
put32bits(((char*)pPg->pData)+96, SQLITE_VERSION_NUMBER);
|
|
}
|
|
|
|
#ifndef SQLITE_OMIT_WAL
|
|
/*
|
|
** This function is invoked once for each page that has already been
|
|
** written into the log file when a WAL transaction is rolled back.
|
|
** Parameter iPg is the page number of said page. The pCtx argument
|
|
** is actually a pointer to the Pager structure.
|
|
**
|
|
** If page iPg is present in the cache, and has no outstanding references,
|
|
** it is discarded. Otherwise, if there are one or more outstanding
|
|
** references, the page content is reloaded from the database. If the
|
|
** attempt to reload content from the database is required and fails,
|
|
** return an SQLite error code. Otherwise, SQLITE_OK.
|
|
*/
|
|
static int pagerUndoCallback(void *pCtx, Pgno iPg){
|
|
int rc = SQLITE_OK;
|
|
Pager *pPager = (Pager *)pCtx;
|
|
PgHdr *pPg;
|
|
|
|
assert( pagerUseWal(pPager) );
|
|
pPg = sqlite3PagerLookup(pPager, iPg);
|
|
if( pPg ){
|
|
if( sqlite3PcachePageRefcount(pPg)==1 ){
|
|
sqlite3PcacheDrop(pPg);
|
|
}else{
|
|
rc = readDbPage(pPg);
|
|
if( rc==SQLITE_OK ){
|
|
pPager->xReiniter(pPg);
|
|
}
|
|
sqlite3PagerUnrefNotNull(pPg);
|
|
}
|
|
}
|
|
|
|
/* Normally, if a transaction is rolled back, any backup processes are
|
|
** updated as data is copied out of the rollback journal and into the
|
|
** database. This is not generally possible with a WAL database, as
|
|
** rollback involves simply truncating the log file. Therefore, if one
|
|
** or more frames have already been written to the log (and therefore
|
|
** also copied into the backup databases) as part of this transaction,
|
|
** the backups must be restarted.
|
|
*/
|
|
sqlite3BackupRestart(pPager->pBackup);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** This function is called to rollback a transaction on a WAL database.
|
|
*/
|
|
static int pagerRollbackWal(Pager *pPager){
|
|
int rc; /* Return Code */
|
|
PgHdr *pList; /* List of dirty pages to revert */
|
|
|
|
/* For all pages in the cache that are currently dirty or have already
|
|
** been written (but not committed) to the log file, do one of the
|
|
** following:
|
|
**
|
|
** + Discard the cached page (if refcount==0), or
|
|
** + Reload page content from the database (if refcount>0).
|
|
*/
|
|
pPager->dbSize = pPager->dbOrigSize;
|
|
rc = sqlite3WalUndo(pPager->pWal, pagerUndoCallback, (void *)pPager);
|
|
pList = sqlite3PcacheDirtyList(pPager->pPCache);
|
|
while( pList && rc==SQLITE_OK ){
|
|
PgHdr *pNext = pList->pDirty;
|
|
rc = pagerUndoCallback((void *)pPager, pList->pgno);
|
|
pList = pNext;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** This function is a wrapper around sqlite3WalFrames(). As well as logging
|
|
** the contents of the list of pages headed by pList (connected by pDirty),
|
|
** this function notifies any active backup processes that the pages have
|
|
** changed.
|
|
**
|
|
** The list of pages passed into this routine is always sorted by page number.
|
|
** Hence, if page 1 appears anywhere on the list, it will be the first page.
|
|
*/
|
|
static int pagerWalFrames(
|
|
Pager *pPager, /* Pager object */
|
|
PgHdr *pList, /* List of frames to log */
|
|
Pgno nTruncate, /* Database size after this commit */
|
|
int isCommit /* True if this is a commit */
|
|
){
|
|
int rc; /* Return code */
|
|
int nList; /* Number of pages in pList */
|
|
PgHdr *p; /* For looping over pages */
|
|
|
|
assert( pPager->pWal );
|
|
assert( pList );
|
|
#ifdef SQLITE_DEBUG
|
|
/* Verify that the page list is in ascending order */
|
|
for(p=pList; p && p->pDirty; p=p->pDirty){
|
|
assert( p->pgno < p->pDirty->pgno );
|
|
}
|
|
#endif
|
|
|
|
assert( pList->pDirty==0 || isCommit );
|
|
if( isCommit ){
|
|
/* If a WAL transaction is being committed, there is no point in writing
|
|
** any pages with page numbers greater than nTruncate into the WAL file.
|
|
** They will never be read by any client. So remove them from the pDirty
|
|
** list here. */
|
|
PgHdr **ppNext = &pList;
|
|
nList = 0;
|
|
for(p=pList; (*ppNext = p)!=0; p=p->pDirty){
|
|
if( p->pgno<=nTruncate ){
|
|
ppNext = &p->pDirty;
|
|
nList++;
|
|
}
|
|
}
|
|
assert( pList );
|
|
}else{
|
|
nList = 1;
|
|
}
|
|
pPager->aStat[PAGER_STAT_WRITE] += nList;
|
|
|
|
if( pList->pgno==1 ) pager_write_changecounter(pList);
|
|
rc = sqlite3WalFrames(pPager->pWal,
|
|
pPager->pageSize, pList, nTruncate, isCommit, pPager->walSyncFlags
|
|
);
|
|
if( rc==SQLITE_OK && pPager->pBackup ){
|
|
for(p=pList; p; p=p->pDirty){
|
|
sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData);
|
|
}
|
|
}
|
|
|
|
#ifdef SQLITE_CHECK_PAGES
|
|
pList = sqlite3PcacheDirtyList(pPager->pPCache);
|
|
for(p=pList; p; p=p->pDirty){
|
|
pager_set_pagehash(p);
|
|
}
|
|
#endif
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Begin a read transaction on the WAL.
|
|
**
|
|
** This routine used to be called "pagerOpenSnapshot()" because it essentially
|
|
** makes a snapshot of the database at the current point in time and preserves
|
|
** that snapshot for use by the reader in spite of concurrently changes by
|
|
** other writers or checkpointers.
|
|
*/
|
|
static int pagerBeginReadTransaction(Pager *pPager){
|
|
int rc; /* Return code */
|
|
int changed = 0; /* True if cache must be reset */
|
|
|
|
assert( pagerUseWal(pPager) );
|
|
assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER );
|
|
|
|
/* sqlite3WalEndReadTransaction() was not called for the previous
|
|
** transaction in locking_mode=EXCLUSIVE. So call it now. If we
|
|
** are in locking_mode=NORMAL and EndRead() was previously called,
|
|
** the duplicate call is harmless.
|
|
*/
|
|
sqlite3WalEndReadTransaction(pPager->pWal);
|
|
|
|
rc = sqlite3WalBeginReadTransaction(pPager->pWal, &changed);
|
|
if( rc!=SQLITE_OK || changed ){
|
|
pager_reset(pPager);
|
|
if( USEFETCH(pPager) ) sqlite3OsUnfetch(pPager->fd, 0, 0);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
** This function is called as part of the transition from PAGER_OPEN
|
|
** to PAGER_READER state to determine the size of the database file
|
|
** in pages (assuming the page size currently stored in Pager.pageSize).
|
|
**
|
|
** If no error occurs, SQLITE_OK is returned and the size of the database
|
|
** in pages is stored in *pnPage. Otherwise, an error code (perhaps
|
|
** SQLITE_IOERR_FSTAT) is returned and *pnPage is left unmodified.
|
|
*/
|
|
static int pagerPagecount(Pager *pPager, Pgno *pnPage){
|
|
Pgno nPage; /* Value to return via *pnPage */
|
|
|
|
/* Query the WAL sub-system for the database size. The WalDbsize()
|
|
** function returns zero if the WAL is not open (i.e. Pager.pWal==0), or
|
|
** if the database size is not available. The database size is not
|
|
** available from the WAL sub-system if the log file is empty or
|
|
** contains no valid committed transactions.
|
|
*/
|
|
assert( pPager->eState==PAGER_OPEN );
|
|
assert( pPager->eLock>=SHARED_LOCK );
|
|
assert( isOpen(pPager->fd) );
|
|
assert( pPager->tempFile==0 );
|
|
nPage = sqlite3WalDbsize(pPager->pWal);
|
|
|
|
/* If the number of pages in the database is not available from the
|
|
** WAL sub-system, determine the page count based on the size of
|
|
** the database file. If the size of the database file is not an
|
|
** integer multiple of the page-size, round up the result.
|
|
*/
|
|
if( nPage==0 && ALWAYS(isOpen(pPager->fd)) ){
|
|
i64 n = 0; /* Size of db file in bytes */
|
|
int rc = sqlite3OsFileSize(pPager->fd, &n);
|
|
if( rc!=SQLITE_OK ){
|
|
return rc;
|
|
}
|
|
nPage = (Pgno)((n+pPager->pageSize-1) / pPager->pageSize);
|
|
}
|
|
|
|
/* If the current number of pages in the file is greater than the
|
|
** configured maximum pager number, increase the allowed limit so
|
|
** that the file can be read.
|
|
*/
|
|
if( nPage>pPager->mxPgno ){
|
|
pPager->mxPgno = (Pgno)nPage;
|
|
}
|
|
|
|
*pnPage = nPage;
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
#ifndef SQLITE_OMIT_WAL
|
|
/*
|
|
** Check if the *-wal file that corresponds to the database opened by pPager
|
|
** exists if the database is not empty, or verify that the *-wal file does
|
|
** not exist (by deleting it) if the database file is empty.
|
|
**
|
|
** If the database is not empty and the *-wal file exists, open the pager
|
|
** in WAL mode. If the database is empty or if no *-wal file exists and
|
|
** if no error occurs, make sure Pager.journalMode is not set to
|
|
** PAGER_JOURNALMODE_WAL.
|
|
**
|
|
** Return SQLITE_OK or an error code.
|
|
**
|
|
** The caller must hold a SHARED lock on the database file to call this
|
|
** function. Because an EXCLUSIVE lock on the db file is required to delete
|
|
** a WAL on a none-empty database, this ensures there is no race condition
|
|
** between the xAccess() below and an xDelete() being executed by some
|
|
** other connection.
|
|
*/
|
|
static int pagerOpenWalIfPresent(Pager *pPager){
|
|
int rc = SQLITE_OK;
|
|
assert( pPager->eState==PAGER_OPEN );
|
|
assert( pPager->eLock>=SHARED_LOCK );
|
|
|
|
if( !pPager->tempFile ){
|
|
int isWal; /* True if WAL file exists */
|
|
rc = sqlite3OsAccess(
|
|
pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal
|
|
);
|
|
if( rc==SQLITE_OK ){
|
|
if( isWal ){
|
|
Pgno nPage; /* Size of the database file */
|
|
|
|
rc = pagerPagecount(pPager, &nPage);
|
|
if( rc ) return rc;
|
|
if( nPage==0 ){
|
|
rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0);
|
|
}else{
|
|
testcase( sqlite3PcachePagecount(pPager->pPCache)==0 );
|
|
rc = sqlite3PagerOpenWal(pPager, 0);
|
|
}
|
|
}else if( pPager->journalMode==PAGER_JOURNALMODE_WAL ){
|
|
pPager->journalMode = PAGER_JOURNALMODE_DELETE;
|
|
}
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
** Playback savepoint pSavepoint. Or, if pSavepoint==NULL, then playback
|
|
** the entire super-journal file. The case pSavepoint==NULL occurs when
|
|
** a ROLLBACK TO command is invoked on a SAVEPOINT that is a transaction
|
|
** savepoint.
|
|
**
|
|
** When pSavepoint is not NULL (meaning a non-transaction savepoint is
|
|
** being rolled back), then the rollback consists of up to three stages,
|
|
** performed in the order specified:
|
|
**
|
|
** * Pages are played back from the main journal starting at byte
|
|
** offset PagerSavepoint.iOffset and continuing to
|
|
** PagerSavepoint.iHdrOffset, or to the end of the main journal
|
|
** file if PagerSavepoint.iHdrOffset is zero.
|
|
**
|
|
** * If PagerSavepoint.iHdrOffset is not zero, then pages are played
|
|
** back starting from the journal header immediately following
|
|
** PagerSavepoint.iHdrOffset to the end of the main journal file.
|
|
**
|
|
** * Pages are then played back from the sub-journal file, starting
|
|
** with the PagerSavepoint.iSubRec and continuing to the end of
|
|
** the journal file.
|
|
**
|
|
** Throughout the rollback process, each time a page is rolled back, the
|
|
** corresponding bit is set in a bitvec structure (variable pDone in the
|
|
** implementation below). This is used to ensure that a page is only
|
|
** rolled back the first time it is encountered in either journal.
|
|
**
|
|
** If pSavepoint is NULL, then pages are only played back from the main
|
|
** journal file. There is no need for a bitvec in this case.
|
|
**
|
|
** In either case, before playback commences the Pager.dbSize variable
|
|
** is reset to the value that it held at the start of the savepoint
|
|
** (or transaction). No page with a page-number greater than this value
|
|
** is played back. If one is encountered it is simply skipped.
|
|
*/
|
|
static int pagerPlaybackSavepoint(Pager *pPager, PagerSavepoint *pSavepoint){
|
|
i64 szJ; /* Effective size of the main journal */
|
|
i64 iHdrOff; /* End of first segment of main-journal records */
|
|
int rc = SQLITE_OK; /* Return code */
|
|
Bitvec *pDone = 0; /* Bitvec to ensure pages played back only once */
|
|
|
|
assert( pPager->eState!=PAGER_ERROR );
|
|
assert( pPager->eState>=PAGER_WRITER_LOCKED );
|
|
|
|
/* Allocate a bitvec to use to store the set of pages rolled back */
|
|
if( pSavepoint ){
|
|
pDone = sqlite3BitvecCreate(pSavepoint->nOrig);
|
|
if( !pDone ){
|
|
return SQLITE_NOMEM_BKPT;
|
|
}
|
|
}
|
|
|
|
/* Set the database size back to the value it was before the savepoint
|
|
** being reverted was opened.
|
|
*/
|
|
pPager->dbSize = pSavepoint ? pSavepoint->nOrig : pPager->dbOrigSize;
|
|
pPager->changeCountDone = pPager->tempFile;
|
|
|
|
if( !pSavepoint && pagerUseWal(pPager) ){
|
|
return pagerRollbackWal(pPager);
|
|
}
|
|
|
|
/* Use pPager->journalOff as the effective size of the main rollback
|
|
** journal. The actual file might be larger than this in
|
|
** PAGER_JOURNALMODE_TRUNCATE or PAGER_JOURNALMODE_PERSIST. But anything
|
|
** past pPager->journalOff is off-limits to us.
|
|
*/
|
|
szJ = pPager->journalOff;
|
|
assert( pagerUseWal(pPager)==0 || szJ==0 );
|
|
|
|
/* Begin by rolling back records from the main journal starting at
|
|
** PagerSavepoint.iOffset and continuing to the next journal header.
|
|
** There might be records in the main journal that have a page number
|
|
** greater than the current database size (pPager->dbSize) but those
|
|
** will be skipped automatically. Pages are added to pDone as they
|
|
** are played back.
|
|
*/
|
|
if( pSavepoint && !pagerUseWal(pPager) ){
|
|
iHdrOff = pSavepoint->iHdrOffset ? pSavepoint->iHdrOffset : szJ;
|
|
pPager->journalOff = pSavepoint->iOffset;
|
|
while( rc==SQLITE_OK && pPager->journalOff<iHdrOff ){
|
|
rc = pager_playback_one_page(pPager, &pPager->journalOff, pDone, 1, 1);
|
|
}
|
|
assert( rc!=SQLITE_DONE );
|
|
}else{
|
|
pPager->journalOff = 0;
|
|
}
|
|
|
|
/* Continue rolling back records out of the main journal starting at
|
|
** the first journal header seen and continuing until the effective end
|
|
** of the main journal file. Continue to skip out-of-range pages and
|
|
** continue adding pages rolled back to pDone.
|
|
*/
|
|
while( rc==SQLITE_OK && pPager->journalOff<szJ ){
|
|
u32 ii; /* Loop counter */
|
|
u32 nJRec = 0; /* Number of Journal Records */
|
|
u32 dummy;
|
|
rc = readJournalHdr(pPager, 0, szJ, &nJRec, &dummy);
|
|
assert( rc!=SQLITE_DONE );
|
|
|
|
/*
|
|
** The "pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff"
|
|
** test is related to ticket #2565. See the discussion in the
|
|
** pager_playback() function for additional information.
|
|
*/
|
|
if( nJRec==0
|
|
&& pPager->journalHdr+JOURNAL_HDR_SZ(pPager)==pPager->journalOff
|
|
){
|
|
nJRec = (u32)((szJ - pPager->journalOff)/JOURNAL_PG_SZ(pPager));
|
|
}
|
|
for(ii=0; rc==SQLITE_OK && ii<nJRec && pPager->journalOff<szJ; ii++){
|
|
rc = pager_playback_one_page(pPager, &pPager->journalOff, pDone, 1, 1);
|
|
}
|
|
assert( rc!=SQLITE_DONE );
|
|
}
|
|
assert( rc!=SQLITE_OK || pPager->journalOff>=szJ );
|
|
|
|
/* Finally, rollback pages from the sub-journal. Page that were
|
|
** previously rolled back out of the main journal (and are hence in pDone)
|
|
** will be skipped. Out-of-range pages are also skipped.
|
|
*/
|
|
if( pSavepoint ){
|
|
u32 ii; /* Loop counter */
|
|
i64 offset = (i64)pSavepoint->iSubRec*(4+pPager->pageSize);
|
|
|
|
if( pagerUseWal(pPager) ){
|
|
rc = sqlite3WalSavepointUndo(pPager->pWal, pSavepoint->aWalData);
|
|
}
|
|
for(ii=pSavepoint->iSubRec; rc==SQLITE_OK && ii<pPager->nSubRec; ii++){
|
|
assert( offset==(i64)ii*(4+pPager->pageSize) );
|
|
rc = pager_playback_one_page(pPager, &offset, pDone, 0, 1);
|
|
}
|
|
assert( rc!=SQLITE_DONE );
|
|
}
|
|
|
|
sqlite3BitvecDestroy(pDone);
|
|
if( rc==SQLITE_OK ){
|
|
pPager->journalOff = szJ;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Change the maximum number of in-memory pages that are allowed
|
|
** before attempting to recycle clean and unused pages.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager *pPager, int mxPage){
|
|
sqlite3PcacheSetCachesize(pPager->pPCache, mxPage);
|
|
}
|
|
|
|
/*
|
|
** Change the maximum number of in-memory pages that are allowed
|
|
** before attempting to spill pages to journal.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3PagerSetSpillsize(Pager *pPager, int mxPage){
|
|
return sqlite3PcacheSetSpillsize(pPager->pPCache, mxPage);
|
|
}
|
|
|
|
/*
|
|
** Invoke SQLITE_FCNTL_MMAP_SIZE based on the current value of szMmap.
|
|
*/
|
|
static void pagerFixMaplimit(Pager *pPager){
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
sqlite3_file *fd = pPager->fd;
|
|
if( isOpen(fd) && fd->pMethods->iVersion>=3 ){
|
|
sqlite3_int64 sz;
|
|
sz = pPager->szMmap;
|
|
pPager->bUseFetch = (sz>0);
|
|
setGetterMethod(pPager);
|
|
sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_MMAP_SIZE, &sz);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
** Change the maximum size of any memory mapping made of the database file.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3PagerSetMmapLimit(Pager *pPager, sqlite3_int64 szMmap){
|
|
pPager->szMmap = szMmap;
|
|
pagerFixMaplimit(pPager);
|
|
}
|
|
|
|
/*
|
|
** Free as much memory as possible from the pager.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3PagerShrink(Pager *pPager){
|
|
sqlite3PcacheShrink(pPager->pPCache);
|
|
}
|
|
|
|
/*
|
|
** Adjust settings of the pager to those specified in the pgFlags parameter.
|
|
**
|
|
** The "level" in pgFlags & PAGER_SYNCHRONOUS_MASK sets the robustness
|
|
** of the database to damage due to OS crashes or power failures by
|
|
** changing the number of syncs()s when writing the journals.
|
|
** There are four 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.
|
|
**
|
|
** EXTRA This is like FULL except that is also syncs the directory
|
|
** that contains the rollback journal after the rollback
|
|
** journal is unlinked.
|
|
**
|
|
** The above is for a rollback-journal mode. For WAL mode, OFF continues
|
|
** to mean that no syncs ever occur. NORMAL means that the WAL is synced
|
|
** prior to the start of checkpoint and that the database file is synced
|
|
** at the conclusion of the checkpoint if the entire content of the WAL
|
|
** was written back into the database. But no sync operations occur for
|
|
** an ordinary commit in NORMAL mode with WAL. FULL means that the WAL
|
|
** file is synced following each commit operation, in addition to the
|
|
** syncs associated with NORMAL. There is no difference between FULL
|
|
** and EXTRA for WAL mode.
|
|
**
|
|
** Do not confuse synchronous=FULL with SQLITE_SYNC_FULL. The
|
|
** SQLITE_SYNC_FULL macro means to use the MacOSX-style full-fsync
|
|
** using fcntl(F_FULLFSYNC). SQLITE_SYNC_NORMAL means to do an
|
|
** ordinary fsync() call. There is no difference between SQLITE_SYNC_FULL
|
|
** and SQLITE_SYNC_NORMAL on platforms other than MacOSX. But the
|
|
** synchronous=FULL versus synchronous=NORMAL setting determines when
|
|
** the xSync primitive is called and is relevant to all platforms.
|
|
**
|
|
** Numeric values associated with these states are OFF==1, NORMAL=2,
|
|
** and FULL=3.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3PagerSetFlags(
|
|
Pager *pPager, /* The pager to set safety level for */
|
|
unsigned pgFlags /* Various flags */
|
|
){
|
|
unsigned level = pgFlags & PAGER_SYNCHRONOUS_MASK;
|
|
if( pPager->tempFile ){
|
|
pPager->noSync = 1;
|
|
pPager->fullSync = 0;
|
|
pPager->extraSync = 0;
|
|
}else{
|
|
pPager->noSync = level==PAGER_SYNCHRONOUS_OFF ?1:0;
|
|
pPager->fullSync = level>=PAGER_SYNCHRONOUS_FULL ?1:0;
|
|
pPager->extraSync = level==PAGER_SYNCHRONOUS_EXTRA ?1:0;
|
|
}
|
|
if( pPager->noSync ){
|
|
pPager->syncFlags = 0;
|
|
}else if( pgFlags & PAGER_FULLFSYNC ){
|
|
pPager->syncFlags = SQLITE_SYNC_FULL;
|
|
}else{
|
|
pPager->syncFlags = SQLITE_SYNC_NORMAL;
|
|
}
|
|
pPager->walSyncFlags = (pPager->syncFlags<<2);
|
|
if( pPager->fullSync ){
|
|
pPager->walSyncFlags |= pPager->syncFlags;
|
|
}
|
|
if( (pgFlags & PAGER_CKPT_FULLFSYNC) && !pPager->noSync ){
|
|
pPager->walSyncFlags |= (SQLITE_SYNC_FULL<<2);
|
|
}
|
|
if( pgFlags & PAGER_CACHESPILL ){
|
|
pPager->doNotSpill &= ~SPILLFLAG_OFF;
|
|
}else{
|
|
pPager->doNotSpill |= SPILLFLAG_OFF;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** 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
|
|
SQLITE_API int sqlite3_opentemp_count = 0;
|
|
#endif
|
|
|
|
/*
|
|
** Open a temporary file.
|
|
**
|
|
** Write the file descriptor into *pFile. 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.
|
|
**
|
|
** The flags passed to the VFS layer xOpen() call are those specified
|
|
** by parameter vfsFlags ORed with the following:
|
|
**
|
|
** SQLITE_OPEN_READWRITE
|
|
** SQLITE_OPEN_CREATE
|
|
** SQLITE_OPEN_EXCLUSIVE
|
|
** SQLITE_OPEN_DELETEONCLOSE
|
|
*/
|
|
static int pagerOpentemp(
|
|
Pager *pPager, /* The pager object */
|
|
sqlite3_file *pFile, /* Write the file descriptor here */
|
|
int vfsFlags /* Flags passed through to the VFS */
|
|
){
|
|
int rc; /* Return code */
|
|
|
|
#ifdef SQLITE_TEST
|
|
sqlite3_opentemp_count++; /* Used for testing and analysis only */
|
|
#endif
|
|
|
|
vfsFlags |= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
|
|
SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE;
|
|
rc = sqlite3OsOpen(pPager->pVfs, 0, pFile, vfsFlags, 0);
|
|
assert( rc!=SQLITE_OK || isOpen(pFile) );
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Set the busy handler function.
|
|
**
|
|
** The pager invokes the busy-handler if sqlite3OsLock() returns
|
|
** SQLITE_BUSY when trying to upgrade from no-lock to a SHARED lock,
|
|
** or when trying to upgrade from a RESERVED lock to an EXCLUSIVE
|
|
** lock. It does *not* invoke the busy handler when upgrading from
|
|
** SHARED to RESERVED, or when upgrading from SHARED to EXCLUSIVE
|
|
** (which occurs during hot-journal rollback). Summary:
|
|
**
|
|
** Transition | Invokes xBusyHandler
|
|
** --------------------------------------------------------
|
|
** NO_LOCK -> SHARED_LOCK | Yes
|
|
** SHARED_LOCK -> RESERVED_LOCK | No
|
|
** SHARED_LOCK -> EXCLUSIVE_LOCK | No
|
|
** RESERVED_LOCK -> EXCLUSIVE_LOCK | Yes
|
|
**
|
|
** If the busy-handler callback returns non-zero, the lock is
|
|
** retried. If it returns zero, then the SQLITE_BUSY error is
|
|
** returned to the caller of the pager API function.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3PagerSetBusyHandler(
|
|
Pager *pPager, /* Pager object */
|
|
int (*xBusyHandler)(void *), /* Pointer to busy-handler function */
|
|
void *pBusyHandlerArg /* Argument to pass to xBusyHandler */
|
|
){
|
|
void **ap;
|
|
pPager->xBusyHandler = xBusyHandler;
|
|
pPager->pBusyHandlerArg = pBusyHandlerArg;
|
|
ap = (void **)&pPager->xBusyHandler;
|
|
assert( ((int(*)(void *))(ap[0]))==xBusyHandler );
|
|
assert( ap[1]==pBusyHandlerArg );
|
|
sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap);
|
|
}
|
|
|
|
/*
|
|
** Change the page size used by the Pager object. The new page size
|
|
** is passed in *pPageSize.
|
|
**
|
|
** If the pager is in the error state when this function is called, it
|
|
** is a no-op. The value returned is the error state error code (i.e.
|
|
** one of SQLITE_IOERR, an SQLITE_IOERR_xxx sub-code or SQLITE_FULL).
|
|
**
|
|
** Otherwise, if all of the following are true:
|
|
**
|
|
** * the new page size (value of *pPageSize) is valid (a power
|
|
** of two between 512 and SQLITE_MAX_PAGE_SIZE, inclusive), and
|
|
**
|
|
** * there are no outstanding page references, and
|
|
**
|
|
** * the database is either not an in-memory database or it is
|
|
** an in-memory database that currently consists of zero pages.
|
|
**
|
|
** then the pager object page size is set to *pPageSize.
|
|
**
|
|
** If the page size is changed, then this function uses sqlite3PagerMalloc()
|
|
** to obtain a new Pager.pTmpSpace buffer. If this allocation attempt
|
|
** fails, SQLITE_NOMEM is returned and the page size remains unchanged.
|
|
** In all other cases, SQLITE_OK is returned.
|
|
**
|
|
** If the page size is not changed, either because one of the enumerated
|
|
** conditions above is not true, the pager was in error state when this
|
|
** function was called, or because the memory allocation attempt failed,
|
|
** then *pPageSize is set to the old, retained page size before returning.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager *pPager, u32 *pPageSize, int nReserve){
|
|
int rc = SQLITE_OK;
|
|
|
|
/* It is not possible to do a full assert_pager_state() here, as this
|
|
** function may be called from within PagerOpen(), before the state
|
|
** of the Pager object is internally consistent.
|
|
**
|
|
** At one point this function returned an error if the pager was in
|
|
** PAGER_ERROR state. But since PAGER_ERROR state guarantees that
|
|
** there is at least one outstanding page reference, this function
|
|
** is a no-op for that case anyhow.
|
|
*/
|
|
|
|
u32 pageSize = *pPageSize;
|
|
assert( pageSize==0 || (pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE) );
|
|
if( (pPager->memDb==0 || pPager->dbSize==0)
|
|
&& sqlite3PcacheRefCount(pPager->pPCache)==0
|
|
&& pageSize && pageSize!=(u32)pPager->pageSize
|
|
){
|
|
char *pNew = NULL; /* New temp space */
|
|
i64 nByte = 0;
|
|
|
|
if( pPager->eState>PAGER_OPEN && isOpen(pPager->fd) ){
|
|
rc = sqlite3OsFileSize(pPager->fd, &nByte);
|
|
}
|
|
if( rc==SQLITE_OK ){
|
|
/* 8 bytes of zeroed overrun space is sufficient so that the b-tree
|
|
* cell header parser will never run off the end of the allocation */
|
|
pNew = (char *)sqlite3PageMalloc(pageSize+8);
|
|
if( !pNew ){
|
|
rc = SQLITE_NOMEM_BKPT;
|
|
}else{
|
|
memset(pNew+pageSize, 0, 8);
|
|
}
|
|
}
|
|
|
|
if( rc==SQLITE_OK ){
|
|
pager_reset(pPager);
|
|
rc = sqlite3PcacheSetPageSize(pPager->pPCache, pageSize);
|
|
}
|
|
if( rc==SQLITE_OK ){
|
|
sqlite3PageFree(pPager->pTmpSpace);
|
|
pPager->pTmpSpace = pNew;
|
|
pPager->dbSize = (Pgno)((nByte+pageSize-1)/pageSize);
|
|
pPager->pageSize = pageSize;
|
|
pPager->lckPgno = (Pgno)(PENDING_BYTE/pageSize) + 1;
|
|
}else{
|
|
sqlite3PageFree(pNew);
|
|
}
|
|
}
|
|
|
|
*pPageSize = pPager->pageSize;
|
|
if( rc==SQLITE_OK ){
|
|
if( nReserve<0 ) nReserve = pPager->nReserve;
|
|
assert( nReserve>=0 && nReserve<1000 );
|
|
pPager->nReserve = (i16)nReserve;
|
|
pagerFixMaplimit(pPager);
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Return a pointer to the "temporary page" buffer held internally
|
|
** by the pager. This is a buffer that is big enough to hold the
|
|
** entire content of a database page. This buffer is used internally
|
|
** during rollback and will be overwritten whenever a rollback
|
|
** occurs. But other modules are free to use it too, as long as
|
|
** no rollbacks are happening.
|
|
*/
|
|
SQLITE_PRIVATE void *sqlite3PagerTempSpace(Pager *pPager){
|
|
return pPager->pTmpSpace;
|
|
}
|
|
|
|
/*
|
|
** 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.
|
|
*/
|
|
SQLITE_PRIVATE Pgno sqlite3PagerMaxPageCount(Pager *pPager, Pgno mxPage){
|
|
if( mxPage>0 ){
|
|
pPager->mxPgno = mxPage;
|
|
}
|
|
assert( pPager->eState!=PAGER_OPEN ); /* Called only by OP_MaxPgcnt */
|
|
/* assert( pPager->mxPgno>=pPager->dbSize ); */
|
|
/* OP_MaxPgcnt ensures that the parameter passed to this function is not
|
|
** less than the total number of valid pages in the database. But this
|
|
** may be less than Pager.dbSize, and so the assert() above is not valid */
|
|
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
|
|
SQLITE_API extern int sqlite3_io_error_pending;
|
|
SQLITE_API 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.
|
|
**
|
|
** If the pager was opened on a transient file (zFilename==""), or
|
|
** opened on a file less than N bytes in size, the output buffer is
|
|
** zeroed and SQLITE_OK returned. The rationale for this is that this
|
|
** function is used to read database headers, and a new transient or
|
|
** zero sized database has a header than consists entirely of zeroes.
|
|
**
|
|
** If any IO error apart from SQLITE_IOERR_SHORT_READ is encountered,
|
|
** the error code is returned to the caller and the contents of the
|
|
** output buffer undefined.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3PagerReadFileheader(Pager *pPager, int N, unsigned char *pDest){
|
|
int rc = SQLITE_OK;
|
|
memset(pDest, 0, N);
|
|
assert( isOpen(pPager->fd) || pPager->tempFile );
|
|
|
|
/* This routine is only called by btree immediately after creating
|
|
** the Pager object. There has not been an opportunity to transition
|
|
** to WAL mode yet.
|
|
*/
|
|
assert( !pagerUseWal(pPager) );
|
|
|
|
if( isOpen(pPager->fd) ){
|
|
IOTRACE(("DBHDR %p 0 %d\n", pPager, N))
|
|
rc = sqlite3OsRead(pPager->fd, pDest, N, 0);
|
|
if( rc==SQLITE_IOERR_SHORT_READ ){
|
|
rc = SQLITE_OK;
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** This function may only be called when a read-transaction is open on
|
|
** the pager. It returns the total number of pages in the database.
|
|
**
|
|
** However, if the file is between 1 and <page-size> bytes in size, then
|
|
** this is considered a 1 page file.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3PagerPagecount(Pager *pPager, int *pnPage){
|
|
assert( pPager->eState>=PAGER_READER );
|
|
assert( pPager->eState!=PAGER_WRITER_FINISHED );
|
|
*pnPage = (int)pPager->dbSize;
|
|
}
|
|
|
|
|
|
/*
|
|
** Try to obtain a lock of type locktype on the database file. If
|
|
** a similar or greater lock is already held, this function is a no-op
|
|
** (returning SQLITE_OK immediately).
|
|
**
|
|
** Otherwise, attempt to obtain the lock using sqlite3OsLock(). Invoke
|
|
** the busy callback if the lock is currently not available. Repeat
|
|
** until the busy callback returns false or until the attempt to
|
|
** obtain the lock succeeds.
|
|
**
|
|
** Return SQLITE_OK on success and an error code if we cannot obtain
|
|
** the lock. If the lock is obtained successfully, set the Pager.state
|
|
** variable to locktype before returning.
|
|
*/
|
|
static int pager_wait_on_lock(Pager *pPager, int locktype){
|
|
int rc; /* Return code */
|
|
|
|
/* Check that this is either a no-op (because the requested lock is
|
|
** already held), or one of the transitions that the busy-handler
|
|
** may be invoked during, according to the comment above
|
|
** sqlite3PagerSetBusyhandler().
|
|
*/
|
|
assert( (pPager->eLock>=locktype)
|
|
|| (pPager->eLock==NO_LOCK && locktype==SHARED_LOCK)
|
|
|| (pPager->eLock==RESERVED_LOCK && locktype==EXCLUSIVE_LOCK)
|
|
);
|
|
|
|
do {
|
|
rc = pagerLockDb(pPager, locktype);
|
|
}while( rc==SQLITE_BUSY && pPager->xBusyHandler(pPager->pBusyHandlerArg) );
|
|
return rc;
|
|
}
|
|
|
|
/*
|
|
** Function assertTruncateConstraint(pPager) checks that one of the
|
|
** following is true for all dirty pages currently in the page-cache:
|
|
**
|
|
** a) The page number is less than or equal to the size of the
|
|
** current database image, in pages, OR
|
|
**
|
|
** b) if the page content were written at this time, it would not
|
|
** be necessary to write the current content out to the sub-journal.
|
|
**
|
|
** If the condition asserted by this function were not true, and the
|
|
** dirty page were to be discarded from the cache via the pagerStress()
|
|
** routine, pagerStress() would not write the current page content to
|
|
** the database file. If a savepoint transaction were rolled back after
|
|
** this happened, the correct behavior would be to restore the current
|
|
** content of the page. However, since this content is not present in either
|
|
** the database file or the portion of the rollback journal and
|
|
** sub-journal rolled back the content could not be restored and the
|
|
** database image would become corrupt. It is therefore fortunate that
|
|
** this circumstance cannot arise.
|
|
*/
|
|
#if defined(SQLITE_DEBUG)
|
|
static void assertTruncateConstraintCb(PgHdr *pPg){
|
|
Pager *pPager = pPg->pPager;
|
|
assert( pPg->flags&PGHDR_DIRTY );
|
|
if( pPg->pgno>pPager->dbSize ){ /* if (a) is false */
|
|
Pgno pgno = pPg->pgno;
|
|
int i;
|
|
for(i=0; i<pPg->pPager->nSavepoint; i++){
|
|
PagerSavepoint *p = &pPager->aSavepoint[i];
|
|
assert( p->nOrig<pgno || sqlite3BitvecTestNotNull(p->pInSavepoint,pgno) );
|
|
}
|
|
}
|
|
}
|
|
static void assertTruncateConstraint(Pager *pPager){
|
|
sqlite3PcacheIterateDirty(pPager->pPCache, assertTruncateConstraintCb);
|
|
}
|
|
#else
|
|
# define assertTruncateConstraint(pPager)
|
|
#endif
|
|
|
|
/*
|
|
** Truncate the in-memory database file image to nPage pages. This
|
|
** function does not actually modify the database file on disk. It
|
|
** just sets the internal state of the pager object so that the
|
|
** truncation will be done when the current transaction is committed.
|
|
**
|
|
** This function is only called right before committing a transaction.
|
|
** Once this function has been called, the transaction must either be
|
|
** rolled back or committed. It is not safe to call this function and
|
|
** then continue writing to the database.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){
|
|
assert( pPager->dbSize>=nPage || CORRUPT_DB );
|
|
assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
|
|
pPager->dbSize = nPage;
|
|
|
|
/* At one point the code here called assertTruncateConstraint() to
|
|
** ensure that all pages being truncated away by this operation are,
|
|
** if one or more savepoints are open, present in the savepoint
|
|
** journal so that they can be restored if the savepoint is rolled
|
|
** back. This is no longer necessary as this function is now only
|
|
** called right before committing a transaction. So although the
|
|
** Pager object may still have open savepoints (Pager.nSavepoint!=0),
|
|
** they cannot be rolled back. So the assertTruncateConstraint() call
|
|
** is no longer correct. */
|
|
}
|
|
|
|
|
|
/*
|
|
** This function is called before attempting a hot-journal rollback. It
|
|
** syncs the journal file to disk, then sets pPager->journalHdr to the
|
|
** size of the journal file so that the pager_playback() routine knows
|
|
** that the entire journal file has been synced.
|
|
**
|
|
** Syncing a hot-journal to disk before attempting to roll it back ensures
|
|
** that if a power-failure occurs during the rollback, the process that
|
|
** attempts rollback following system recovery sees the same journal
|
|
** content as this process.
|
|
**
|
|
** If everything goes as planned, SQLITE_OK is returned. Otherwise,
|
|
** an SQLite error code.
|
|
*/
|
|
static int pagerSyncHotJournal(Pager *pPager){
|
|
int rc = SQLITE_OK;
|
|
if( !pPager->noSync ){
|
|
rc = sqlite3OsSync(pPager->jfd, SQLITE_SYNC_NORMAL);
|
|
}
|
|
if( rc==SQLITE_OK ){
|
|
rc = sqlite3OsFileSize(pPager->jfd, &pPager->journalHdr);
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
/*
|
|
** Obtain a reference to a memory mapped page object for page number pgno.
|
|
** The new object will use the pointer pData, obtained from xFetch().
|
|
** If successful, set *ppPage to point to the new page reference
|
|
** and return SQLITE_OK. Otherwise, return an SQLite error code and set
|
|
** *ppPage to zero.
|
|
**
|
|
** Page references obtained by calling this function should be released
|
|
** by calling pagerReleaseMapPage().
|
|
*/
|
|
static int pagerAcquireMapPage(
|
|
Pager *pPager, /* Pager object */
|
|
Pgno pgno, /* Page number */
|
|
void *pData, /* xFetch()'d data for this page */
|
|
PgHdr **ppPage /* OUT: Acquired page object */
|
|
){
|
|
PgHdr *p; /* Memory mapped page to return */
|
|
|
|
if( pPager->pMmapFreelist ){
|
|
*ppPage = p = pPager->pMmapFreelist;
|
|
pPager->pMmapFreelist = p->pDirty;
|
|
p->pDirty = 0;
|
|
assert( pPager->nExtra>=8 );
|
|
memset(p->pExtra, 0, 8);
|
|
}else{
|
|
*ppPage = p = (PgHdr *)sqlite3MallocZero(sizeof(PgHdr) + pPager->nExtra);
|
|
if( p==0 ){
|
|
sqlite3OsUnfetch(pPager->fd, (i64)(pgno-1) * pPager->pageSize, pData);
|
|
return SQLITE_NOMEM_BKPT;
|
|
}
|
|
p->pExtra = (void *)&p[1];
|
|
p->flags = PGHDR_MMAP;
|
|
p->nRef = 1;
|
|
p->pPager = pPager;
|
|
}
|
|
|
|
assert( p->pExtra==(void *)&p[1] );
|
|
assert( p->pPage==0 );
|
|
assert( p->flags==PGHDR_MMAP );
|
|
assert( p->pPager==pPager );
|
|
assert( p->nRef==1 );
|
|
|
|
p->pgno = pgno;
|
|
p->pData = pData;
|
|
pPager->nMmapOut++;
|
|
|
|
return SQLITE_OK;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
** Release a reference to page pPg. pPg must have been returned by an
|
|
** earlier call to pagerAcquireMapPage().
|
|
*/
|
|
static void pagerReleaseMapPage(PgHdr *pPg){
|
|
Pager *pPager = pPg->pPager;
|
|
pPager->nMmapOut--;
|
|
pPg->pDirty = pPager->pMmapFreelist;
|
|
pPager->pMmapFreelist = pPg;
|
|
|
|
assert( pPager->fd->pMethods->iVersion>=3 );
|
|
sqlite3OsUnfetch(pPager->fd, (i64)(pPg->pgno-1)*pPager->pageSize, pPg->pData);
|
|
}
|
|
|
|
/*
|
|
** Free all PgHdr objects stored in the Pager.pMmapFreelist list.
|
|
*/
|
|
static void pagerFreeMapHdrs(Pager *pPager){
|
|
PgHdr *p;
|
|
PgHdr *pNext;
|
|
for(p=pPager->pMmapFreelist; p; p=pNext){
|
|
pNext = p->pDirty;
|
|
sqlite3_free(p);
|
|
}
|
|
}
|
|
|
|
/* Verify that the database file has not be deleted or renamed out from
|
|
** under the pager. Return SQLITE_OK if the database is still where it ought
|
|
** to be on disk. Return non-zero (SQLITE_READONLY_DBMOVED or some other error
|
|
** code from sqlite3OsAccess()) if the database has gone missing.
|
|
*/
|
|
static int databaseIsUnmoved(Pager *pPager){
|
|
int bHasMoved = 0;
|
|
int rc;
|
|
|
|
if( pPager->tempFile ) return SQLITE_OK;
|
|
if( pPager->dbSize==0 ) return SQLITE_OK;
|
|
assert( pPager->zFilename && pPager->zFilename[0] );
|
|
rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_HAS_MOVED, &bHasMoved);
|
|
if( rc==SQLITE_NOTFOUND ){
|
|
/* If the HAS_MOVED file-control is unimplemented, assume that the file
|
|
** has not been moved. That is the historical behavior of SQLite: prior to
|
|
** version 3.8.3, it never checked */
|
|
rc = SQLITE_OK;
|
|
}else if( rc==SQLITE_OK && bHasMoved ){
|
|
rc = SQLITE_READONLY_DBMOVED;
|
|
}
|
|
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.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3PagerClose(Pager *pPager, sqlite3 *db){
|
|
u8 *pTmp = (u8*)pPager->pTmpSpace;
|
|
assert( db || pagerUseWal(pPager)==0 );
|
|
assert( assert_pager_state(pPager) );
|
|
disable_simulated_io_errors();
|
|
sqlite3BeginBenignMalloc();
|
|
pagerFreeMapHdrs(pPager);
|
|
/* pPager->errCode = 0; */
|
|
pPager->exclusiveMode = 0;
|
|
#ifndef SQLITE_OMIT_WAL
|
|
{
|
|
u8 *a = 0;
|
|
assert( db || pPager->pWal==0 );
|
|
if( db && 0==(db->flags & SQLITE_NoCkptOnClose)
|
|
&& SQLITE_OK==databaseIsUnmoved(pPager)
|
|
){
|
|
a = pTmp;
|
|
}
|
|
sqlite3WalClose(pPager->pWal, db, pPager->walSyncFlags, pPager->pageSize,a);
|
|
pPager->pWal = 0;
|
|
}
|
|
#endif
|
|
pager_reset(pPager);
|
|
if( MEMDB ){
|
|
pager_unlock(pPager);
|
|
}else{
|
|
/* If it is open, sync the journal file before calling UnlockAndRollback.
|
|
** If this is not done, then an unsynced portion of the open journal
|
|
** file may be played back into the database. If a power failure occurs
|
|
** while this is happening, the database could become corrupt.
|
|
**
|
|
** If an error occurs while trying to sync the journal, shift the pager
|
|
** into the ERROR state. This causes UnlockAndRollback to unlock the
|
|
** database and close the journal file without attempting to roll it
|
|
** back or finalize it. The next database user will have to do hot-journal
|
|
** rollback before accessing the database file.
|
|
*/
|
|
if( isOpen(pPager->jfd) ){
|
|
pager_error(pPager, pagerSyncHotJournal(pPager));
|
|
}
|
|
pagerUnlockAndRollback(pPager);
|
|
}
|
|
sqlite3EndBenignMalloc();
|
|
enable_simulated_io_errors();
|
|
PAGERTRACE(("CLOSE %d\n", PAGERID(pPager)));
|
|
IOTRACE(("CLOSE %p\n", pPager))
|
|
sqlite3OsClose(pPager->jfd);
|
|
sqlite3OsClose(pPager->fd);
|
|
sqlite3PageFree(pTmp);
|
|
sqlite3PcacheClose(pPager->pPCache);
|
|
assert( !pPager->aSavepoint && !pPager->pInJournal );
|
|
assert( !isOpen(pPager->jfd) && !isOpen(pPager->sjfd) );
|
|
|
|
sqlite3_free(pPager);
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
#if !defined(NDEBUG) || defined(SQLITE_TEST)
|
|
/*
|
|
** Return the page number for page pPg.
|
|
*/
|
|
SQLITE_PRIVATE Pgno sqlite3PagerPagenumber(DbPage *pPg){
|
|
return pPg->pgno;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
** Increment the reference count for page pPg.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3PagerRef(DbPage *pPg){
|
|
sqlite3PcacheRef(pPg);
|
|
}
|
|
|
|
/*
|
|
** 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 and can be restored in the event of a hot-journal rollback.
|
|
**
|
|
** If the Pager.noSync flag is set, then this function is a no-op.
|
|
** Otherwise, the actions required depend on the journal-mode and the
|
|
** device characteristics of the file-system, as follows:
|
|
**
|
|
** * If the journal file is an in-memory journal file, no action need
|
|
** be taken.
|
|
**
|
|
** * Otherwise, if the device does not support the SAFE_APPEND property,
|
|
** then the nRec field of the most recently written journal header
|
|
** is updated to contain the number of journal records that have
|
|
** been written following it. If the pager is operating in full-sync
|
|
** mode, then the journal file is synced before this field is updated.
|
|
**
|
|
** * If the device does not support the SEQUENTIAL property, then
|
|
** journal file is synced.
|
|
**
|
|
** Or, in pseudo-code:
|
|
**
|
|
** if( NOT <in-memory journal> ){
|
|
** if( NOT SAFE_APPEND ){
|
|
** if( <full-sync mode> ) xSync(<journal file>);
|
|
** <update nRec field>
|
|
** }
|
|
** if( NOT SEQUENTIAL ) xSync(<journal file>);
|
|
** }
|
|
**
|
|
** If successful, this routine clears the PGHDR_NEED_SYNC flag of every
|
|
** page currently held in memory before returning SQLITE_OK. If an IO
|
|
** error is encountered, then the IO error code is returned to the caller.
|
|
*/
|
|
static int syncJournal(Pager *pPager, int newHdr){
|
|
int rc; /* Return code */
|
|
|
|
assert( pPager->eState==PAGER_WRITER_CACHEMOD
|
|
|| pPager->eState==PAGER_WRITER_DBMOD
|
|
);
|
|
assert( assert_pager_state(pPager) );
|
|
assert( !pagerUseWal(pPager) );
|
|
|
|
rc = sqlite3PagerExclusiveLock(pPager);
|
|
if( rc!=SQLITE_OK ) return rc;
|
|
|
|
if( !pPager->noSync ){
|
|
assert( !pPager->tempFile );
|
|
if( isOpen(pPager->jfd) && pPager->journalMode!=PAGER_JOURNALMODE_MEMORY ){
|
|
c |