view release on metacpan or search on metacpan
sqlite-amalgamation.c view on Meta::CPAN
** {H12131} If an error occurs while parsing or evaluating any of the SQL
** statements in the S parameter of [sqlite3_exec(D,S,C,A,E)] and if
** the E parameter is not NULL, then [sqlite3_exec()] shall store
** in *E an appropriate error message written into memory obtained
** from [sqlite3_malloc()].
**
** {H12134} The [sqlite3_exec(D,S,C,A,E)] routine shall set the value of
** *E to NULL if E is not NULL and there are no errors.
**
** {H12137} The [sqlite3_exec(D,S,C,A,E)] function shall set the [error code]
** and message accessible via [sqlite3_errcode()],
** [sqlite3_errmsg()], and [sqlite3_errmsg16()].
**
** {H12138} If the S parameter to [sqlite3_exec(D,S,C,A,E)] is NULL or an
** empty string or contains nothing other than whitespace, comments,
** and/or semicolons, then results of [sqlite3_errcode()],
** [sqlite3_errmsg()], and [sqlite3_errmsg16()]
** shall reset to indicate no errors.
**
** ASSUMPTIONS:
**
** {A12141} The first parameter to [sqlite3_exec()] must be an valid and open
** [database connection].
**
** {A12142} The database connection must not be closed while
** [sqlite3_exec()] is running.
**
** {A12143} The calling function should use [sqlite3_free()] to free
** the memory that *errmsg is left pointing at once the error
** message is no longer needed.
**
** {A12145} The SQL statement text in the 2nd parameter to [sqlite3_exec()]
** must remain unchanged while [sqlite3_exec()] is running.
*/
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 {H10210} <S10700>
** KEYWORDS: SQLITE_OK {error code} {error codes}
** KEYWORDS: {result code} {result codes}
**
** Many SQLite functions return an integer result code from the set shown
** here in order to indicates success or failure.
**
** New error codes may be added in future versions of SQLite.
**
** See also: [SQLITE_IOERR_READ | extended result codes]
*/
#define SQLITE_OK 0 /* Successful result */
/* beginning-of-error-codes */
#define SQLITE_ERROR 1 /* SQL error or missing database */
#define SQLITE_INTERNAL 2 /* Internal logic error in SQLite */
#define SQLITE_PERM 3 /* Access permission denied */
#define SQLITE_ABORT 4 /* Callback routine requested an abort */
#define SQLITE_BUSY 5 /* The database file is locked */
#define SQLITE_LOCKED 6 /* A table in the database is locked */
#define SQLITE_NOMEM 7 /* A malloc() failed */
#define SQLITE_READONLY 8 /* Attempt to write a readonly database */
#define SQLITE_INTERRUPT 9 /* Operation terminated by sqlite3_interrupt()*/
#define SQLITE_IOERR 10 /* Some kind of disk I/O error occurred */
#define SQLITE_CORRUPT 11 /* The database disk image is malformed */
#define SQLITE_NOTFOUND 12 /* NOT USED. Table or record not found */
#define SQLITE_FULL 13 /* Insertion failed because database is full */
#define SQLITE_CANTOPEN 14 /* Unable to open the database file */
#define SQLITE_PROTOCOL 15 /* NOT USED. Database lock protocol error */
#define SQLITE_EMPTY 16 /* Database is empty */
#define SQLITE_SCHEMA 17 /* The database schema changed */
#define SQLITE_TOOBIG 18 /* String or BLOB exceeds size limit */
#define SQLITE_CONSTRAINT 19 /* Abort due to 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 /* Auxiliary database format error */
#define SQLITE_RANGE 25 /* 2nd parameter to sqlite3_bind out of range */
#define SQLITE_NOTADB 26 /* File opened that is not a database file */
#define SQLITE_ROW 100 /* sqlite3_step() has another row ready */
#define SQLITE_DONE 101 /* sqlite3_step() has finished executing */
/* end-of-error-codes */
/*
** CAPI3REF: Extended Result Codes {H10220} <S10700>
** KEYWORDS: {extended error code} {extended error codes}
** KEYWORDS: {extended result code} {extended result codes}
**
** In its default configuration, SQLite API routines return one of 26 integer
** [SQLITE_OK | 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 and later) include
** support for additional result codes that provide more detailed information
** about errors. The extended result codes are enabled or disabled
** on a per database connection basis using the
** [sqlite3_extended_result_codes()] API.
**
** Some of the available extended result codes are listed here.
** One may expect the number of extended result codes will be expand
** over time. Software that uses extended result codes should expect
** to see new result codes in future releases of SQLite.
**
** The SQLITE_OK result code will never be extended. It will always
** be exactly zero.
**
** INVARIANTS:
**
** {H10223} The symbolic name for an extended result code shall contains
** a related primary result code as a prefix.
**
** {H10224} Primary result code names shall contain a single "_" character.
**
** {H10225} Extended result code names shall contain two or more "_" characters.
**
** {H10226} The numeric value of an extended result code shall contain the
** numeric value of its corresponding primary result code in
** its least significant 8 bits.
*/
sqlite-amalgamation.c view on Meta::CPAN
**
** {H12271} The [sqlite3_interrupt()] interface will force all running
** SQL statements associated with the same database connection
** to halt after processing at most one additional row of data.
**
** {H12272} Any SQL statement that is interrupted by [sqlite3_interrupt()]
** will return [SQLITE_INTERRUPT].
**
** ASSUMPTIONS:
**
** {A12279} If the database connection closes while [sqlite3_interrupt()]
** is running then bad things will likely happen.
*/
SQLITE_API void sqlite3_interrupt(sqlite3*);
/*
** CAPI3REF: Determine If An SQL Statement Is Complete {H10510} <S70200>
**
** These routines are useful for command-line input to determine if the
** currently entered text seems to form complete a SQL statement or
** if additional input is needed before sending the text into
** SQLite for parsing. These routines return true 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 fragment of a
** 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.
**
** These routines do not parse the SQL statements thus
** will not detect syntactically incorrect SQL.
**
** INVARIANTS:
**
** {H10511} A successful evaluation of [sqlite3_complete()] or
** [sqlite3_complete16()] functions shall
** return a numeric 1 if and only if the last non-whitespace
** token in their input is a semicolon that is not in between
** the BEGIN and END of a CREATE TRIGGER statement.
**
** {H10512} If a memory allocation error occurs during an invocation
** of [sqlite3_complete()] or [sqlite3_complete16()] then the
** routine shall return [SQLITE_NOMEM].
**
** ASSUMPTIONS:
**
** {A10512} The input to [sqlite3_complete()] must be a zero-terminated
** UTF-8 string.
**
** {A10513} 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 {H12310} <S40400>
**
** This routine sets a callback function that might be invoked whenever
** an attempt is made to open a database table that another thread
** or process has locked.
**
** If the busy callback is NULL, then [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]
** is returned immediately upon encountering the lock. If the busy callback
** is not NULL, then the callback will be invoked with two arguments.
**
** The first argument to the handler is a copy of the void* pointer which
** is the third argument to sqlite3_busy_handler(). The second argument to
** the handler callback is the number of times that the busy handler has
** been invoked for this locking event. If the
** busy callback returns 0, then no additional attempts are made to
** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned.
** If the callback returns non-zero, then another attempt
** is made to open the database for reading and the cycle repeats.
**
** The presence of a busy handler does not guarantee that it will be invoked
** when there is lock contention. If SQLite determines that invoking the busy
** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY]
** or [SQLITE_IOERR_BLOCKED] 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.
**
** The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED]
** when SQLite is in the middle of a large transaction where all the
** changes will not fit into the in-memory cache. SQLite will
** already hold a RESERVED lock on the database file, but it needs
** to promote this lock to EXCLUSIVE so that it can spill cache
** pages into the database file without harm to concurrent
** readers. If it is unable to promote the lock, then the in-memory
** cache will be left in an inconsistent state and so the error
** code is promoted from the relatively benign [SQLITE_BUSY] to
** the more severe [SQLITE_IOERR_BLOCKED]. This error code promotion
** forces an automatic rollback of the changes. See the
** <a href="/cvstrac/wiki?p=CorruptionFollowingBusyError">
** CorruptionFollowingBusyError</a> wiki page for a discussion of why
** this is important.
**
** 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()]
** will also set or clear the busy handler.
**
** INVARIANTS:
**
** {H12311} The [sqlite3_busy_handler(D,C,A)] function shall replace
** busy callback in the [database connection] D with a new
** a new busy handler C and application data pointer A.
**
** {H12312} Newly created [database connections] shall have a busy
** handler of NULL.
**
** {H12314} When two or more [database connections] share a
** [sqlite3_enable_shared_cache | common cache],
** the busy handler for the database connection currently using
** the cache shall be invoked when the cache encounters a lock.
**
** {H12316} If a busy handler callback returns zero, then the SQLite interface
** that provoked the locking event shall return [SQLITE_BUSY].
**
** {H12318} SQLite shall invokes the busy handler with two arguments which
** are a copy of the pointer supplied by the 3rd parameter to
** [sqlite3_busy_handler()] and a count of the number of prior
** invocations of the busy handler for the same locking event.
**
** ASSUMPTIONS:
**
** {A12319} 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 {H12340} <S40410>
**
** 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. {H12343} After "ms" milliseconds of sleeping,
** the handler returns 0 which causes [sqlite3_step()] to return
** [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED].
**
** Calling this routine with an argument less than or equal to zero
** turns off all busy handlers.
**
** There can only be a single busy handler for a particular
** [database connection] any any given moment. If another busy handler
** was defined (using [sqlite3_busy_handler()]) prior to calling
** this routine, that other busy handler is cleared.
**
** INVARIANTS:
**
** {H12341} The [sqlite3_busy_timeout()] function shall override any prior
** [sqlite3_busy_timeout()] or [sqlite3_busy_handler()] setting
** on the same [database connection].
**
** {H12343} If the 2nd parameter to [sqlite3_busy_timeout()] is less than
** or equal to zero, then the busy handler shall be cleared so that
** all subsequent locking events immediately return [SQLITE_BUSY].
**
** {H12344} If the 2nd parameter to [sqlite3_busy_timeout()] is a positive
** number N, then a busy handler shall be set that repeatedly calls
** the xSleep() method in the [sqlite3_vfs | VFS interface] until
** either the lock clears or until the cumulative sleep time
** reported back by xSleep() exceeds N milliseconds.
*/
SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
/*
** CAPI3REF: Convenience Routines For Running Queries {H12370} <S10000>
**
** 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
** -----------------------
sqlite-amalgamation.c view on Meta::CPAN
static int winMutexInit(void){ return SQLITE_OK; }
static int winMutexEnd(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 0
** <li> SQLITE_MUTEX_RECURSIVE 1
** <li> SQLITE_MUTEX_STATIC_MASTER 2
** <li> SQLITE_MUTEX_STATIC_MEM 3
** <li> SQLITE_MUTEX_STATIC_PRNG 4
** </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. Three 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;
InitializeCriticalSection(&p->mutex);
}
break;
}
default: {
static sqlite3_mutex staticMutexes[6];
static int isInit = 0;
while( !isInit ){
static long lock = 0;
if( InterlockedIncrement(&lock)==1 ){
int i;
for(i=0; i<sizeof(staticMutexes)/sizeof(staticMutexes[0]); i++){
InitializeCriticalSection(&staticMutexes[i].mutex);
}
isInit = 1;
}else{
Sleep(1);
}
}
assert( iType-2 >= 0 );
assert( iType-2 < sizeof(staticMutexes)/sizeof(staticMutexes[0]) );
p = &staticMutexes[iType-2];
p->id = iType;
break;
}
}
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 );
assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
DeleteCriticalSection(&p->mutex);
sqlite3_free(p);
}
/*
** 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){
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) );
EnterCriticalSection(&p->mutex);
p->owner = GetCurrentThreadId();
p->nRef++;
}
static int winMutexTry(sqlite3_mutex *p){
int rc = SQLITE_BUSY;
assert( p->id==SQLITE_MUTEX_RECURSIVE || winMutexNotheld(p) );
/*
** 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
sqlite-amalgamation.c view on Meta::CPAN
** to another. This logic makes sure a user does not try to do that
** by mistake.
**
** Version 3.3.1 (2006-01-15): unixFile can be moved from one thread to
** another as long as we are running on a system that supports threads
** overriding each others locks (which now the most common behavior)
** or if no locks are held. But the unixFile.pLock field needs to be
** recomputed because its key includes the thread-id. See the
** transferOwnership() function below for additional information
*/
#if SQLITE_THREADSAFE
# define SET_THREADID(X) (X)->tid = pthread_self()
# define CHECK_THREADID(X) (threadsOverrideEachOthersLocks==0 && \
!pthread_equal((X)->tid, pthread_self()))
#else
# define SET_THREADID(X)
# define CHECK_THREADID(X) 0
#endif
/*
** Here is the dirt on POSIX advisory locks: ANSI STD 1003.1 (1996)
** section 6.5.2.2 lines 483 through 490 specify that when a process
** sets or clears a lock, that operation overrides any prior locks set
** by the same process. It does not explicitly say so, but this implies
** that it overrides locks set by the same process using a different
** file descriptor. Consider this test case:
** int fd2 = open("./file2", O_RDWR|O_CREAT, 0644);
**
** Suppose ./file1 and ./file2 are really the same file (because
** one is a hard or symbolic link to the other) then if you set
** an exclusive lock on fd1, then try to get an exclusive lock
** on fd2, it works. I would have expected the second lock to
** fail since there was already a lock on the file due to fd1.
** But not so. Since both locks came from the same process, the
** second overrides the first, even though they were on different
** file descriptors opened on different file names.
**
** Bummer. If you ask me, this is broken. Badly broken. It means
** that we cannot use POSIX locks to synchronize file access among
** competing threads of the same process. POSIX locks will work fine
** to synchronize access for threads in separate processes, but not
** threads within the same process.
**
** To work around the problem, SQLite has to manage file locks internally
** on its own. Whenever a new database is opened, we have to find the
** specific inode of the database file (the inode is determined by the
** st_dev and st_ino fields of the stat structure that fstat() fills in)
** and check for locks already existing on that inode. When locks are
** created or removed, we have to look at our own internal record of the
** locks to see if another thread has previously set a lock on that same
** inode.
**
** The 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.
**
** 2004-Jan-11:
** More recent discoveries about POSIX advisory locks. (The more
** I discover, the more I realize the a POSIX advisory locks are
** an abomination.)
**
** If you close a file descriptor that points to a file that has locks,
** all locks on that file that are owned by the current process are
** released. To work around this problem, each unixFile structure contains
** a pointer to an openCnt structure. There is one openCnt structure
** per open inode, which means that multiple unixFile can point to a single
** openCnt. 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 openCnt structure keeps a list of file descriptors that need to
** be closed and that list is walked (and cleared) when the last lock
** clears.
**
** First, under Linux threads, because each thread has a separate
** process ID, lock operations in one thread do not override locks
** to the same file in other threads. Linux threads behave like
** separate processes in this respect. But, if you close a file
** descriptor in linux threads, all locks are cleared, even locks
** on other threads and even though the other threads have different
** process IDs. Linux threads is inconsistent in this respect.
** (I'm beginning to think that linux threads is an abomination too.)
** The consequence of this all is that the hash table for the lockInfo
** structure has to include the process id as part of its key because
** locks in different threads are treated as distinct. But the
** openCnt structure should not include the process id in its
** key because close() clears lock on all threads, not just the current
** thread. Were it not for this goofiness in linux threads, we could
** combine the lockInfo and openCnt structures into a single structure.
**
** 2004-Jun-28:
** On some versions of linux, threads can override each others locks.
** On others not. Sometimes you can change the behavior on the same
** system by setting the LD_ASSUME_KERNEL environment variable. The
** POSIX standard is silent as to which behavior is correct, as far
** as I can tell, so other versions of unix might show the same
** inconsistency. There is no little doubt in my mind that posix
** advisory locks and linux threads are profoundly broken.
**
** To work around the inconsistencies, we have to test at runtime
** whether or not threads can override each others locks. This test
** is run once, the first time any lock is attempted. A static
** variable is set to record the results of this test for future
** use.
*/
/*
** An instance of the following structure serves as the key used
** to locate a particular lockInfo structure given its inode.
**
** If threads cannot override each others locks, then we set the
** lockKey.tid field to the thread ID. If threads can override
** each others locks then tid is always set to zero. tid is omitted
** if we compile without threading support.
*/
struct lockKey {
sqlite-amalgamation.c view on Meta::CPAN
** POSIX locking style fully supports shared and exclusive byte-range locks
** AFP locking only supports exclusive byte-range locks
** FLOCK only supports a single file-global exclusive lock
** DOTLOCK isn't a true locking style, it refers to the use of a special
** file named the same as the database file with a '.lock' extension, this
** can be used on file systems that do not offer any reliable file locking
** NO locking means that no locking will be attempted, this is only used for
** read-only file systems currently
** UNSUPPORTED means that no locking will be attempted, this is only used for
** file systems that are known to be unsupported
*/
#define LOCKING_STYLE_POSIX 1
#define LOCKING_STYLE_NONE 2
#define LOCKING_STYLE_DOTFILE 3
#define LOCKING_STYLE_FLOCK 4
#define LOCKING_STYLE_AFP 5
/*
** Helper functions to obtain and relinquish the global mutex.
*/
static void enterMutex(){
sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
}
static void leaveMutex(){
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
}
#if SQLITE_THREADSAFE
/*
** This variable records whether or not threads can override each others
** locks.
**
** 0: No. Threads cannot override each others locks.
** 1: Yes. Threads can override each others locks.
** -1: We don't know yet.
**
** On some systems, we know at compile-time if threads can override each
** others locks. On those systems, the SQLITE_THREAD_OVERRIDE_LOCK macro
** will be set appropriately. On other systems, we have to check at
** runtime. On these latter systems, SQLTIE_THREAD_OVERRIDE_LOCK is
** undefined.
**
** This variable normally has file scope only. But during testing, we make
** it a global so that the test code can change its value in order to verify
** that the right stuff happens in either case.
*/
#ifndef SQLITE_THREAD_OVERRIDE_LOCK
# define SQLITE_THREAD_OVERRIDE_LOCK -1
#endif
#ifdef SQLITE_TEST
int threadsOverrideEachOthersLocks = SQLITE_THREAD_OVERRIDE_LOCK;
#else
static int threadsOverrideEachOthersLocks = SQLITE_THREAD_OVERRIDE_LOCK;
#endif
/*
** This structure holds information passed into individual test
** threads by the testThreadLockingBehavior() routine.
*/
struct threadTestData {
int fd; /* File to be locked */
struct flock lock; /* The locking operation */
int result; /* Result of the locking operation */
};
#ifdef SQLITE_LOCK_TRACE
/*
** Print out information about all locking operations.
**
** This routine is used for troubleshooting locks on multithreaded
** platforms. Enable by compiling with the -DSQLITE_LOCK_TRACE
** command-line option on the compiler. This code is normally
** turned off.
*/
static int lockTrace(int fd, int op, struct flock *p){
char *zOpName, *zType;
int s;
int savedErrno;
if( op==F_GETLK ){
zOpName = "GETLK";
}else if( op==F_SETLK ){
zOpName = "SETLK";
}else{
s = fcntl(fd, op, p);
sqlite3DebugPrintf("fcntl unknown %d %d %d\n", fd, op, s);
return s;
}
if( p->l_type==F_RDLCK ){
zType = "RDLCK";
}else if( p->l_type==F_WRLCK ){
zType = "WRLCK";
}else if( p->l_type==F_UNLCK ){
zType = "UNLCK";
}else{
assert( 0 );
}
assert( p->l_whence==SEEK_SET );
s = fcntl(fd, op, p);
savedErrno = errno;
sqlite3DebugPrintf("fcntl %d %d %s %s %d %d %d %d\n",
threadid, fd, zOpName, zType, (int)p->l_start, (int)p->l_len,
(int)p->l_pid, s);
if( s==(-1) && op==F_SETLK && (p->l_type==F_RDLCK || p->l_type==F_WRLCK) ){
struct flock l2;
l2 = *p;
fcntl(fd, F_GETLK, &l2);
if( l2.l_type==F_RDLCK ){
zType = "RDLCK";
}else if( l2.l_type==F_WRLCK ){
zType = "WRLCK";
}else if( l2.l_type==F_UNLCK ){
zType = "UNLCK";
}else{
assert( 0 );
}
sqlite3DebugPrintf("fcntl-failure-reason: %s %d %d %d\n",
zType, (int)l2.l_start, (int)l2.l_len, (int)l2.l_pid);
}
errno = savedErrno;
return s;
}
sqlite-amalgamation.c view on Meta::CPAN
}
*ppLock = pLock;
if( ppOpen!=0 ){
pOpen = openList;
while( pOpen && memcmp(&key2, &pOpen->key, sizeof(key2)) ){
pOpen = pOpen->pNext;
}
if( pOpen==0 ){
pOpen = sqlite3_malloc( sizeof(*pOpen) );
if( pOpen==0 ){
releaseLockInfo(pLock);
rc = SQLITE_NOMEM;
goto exit_findlockinfo;
}
pOpen->key = key2;
pOpen->nRef = 1;
pOpen->nLock = 0;
pOpen->nPending = 0;
pOpen->aPending = 0;
pOpen->pNext = openList;
pOpen->pPrev = 0;
if( openList ) openList->pPrev = pOpen;
openList = pOpen;
}else{
pOpen->nRef++;
}
*ppOpen = pOpen;
}
exit_findlockinfo:
return rc;
}
#ifdef SQLITE_DEBUG
/*
** Helper function for printing out trace information from debugging
** binaries. This returns the string represetation of the supplied
** integer lock-type.
*/
static const char *locktypeName(int locktype){
switch( locktype ){
case NO_LOCK: return "NONE";
case SHARED_LOCK: return "SHARED";
case RESERVED_LOCK: return "RESERVED";
case PENDING_LOCK: return "PENDING";
case EXCLUSIVE_LOCK: return "EXCLUSIVE";
}
return "ERROR";
}
#endif
/*
** If we are currently in a different thread than the thread that the
** unixFile argument belongs to, then transfer ownership of the unixFile
** over to the current thread.
**
** A unixFile is only owned by a thread on systems where one thread is
** unable to override locks created by a different thread. RedHat9 is
** an example of such a system.
**
** Ownership transfer is only allowed if the unixFile is currently unlocked.
** If the unixFile is locked and an ownership is wrong, then return
** SQLITE_MISUSE. SQLITE_OK is returned if everything works.
*/
#if SQLITE_THREADSAFE
static int transferOwnership(unixFile *pFile){
int rc;
pthread_t hSelf;
if( threadsOverrideEachOthersLocks ){
/* Ownership transfers not needed on this system */
return SQLITE_OK;
}
hSelf = pthread_self();
if( pthread_equal(pFile->tid, hSelf) ){
/* We are still in the same thread */
OSTRACE1("No-transfer, same thread\n");
return SQLITE_OK;
}
if( pFile->locktype!=NO_LOCK ){
/* We cannot change ownership while we are holding a lock! */
return SQLITE_MISUSE;
}
OSTRACE4("Transfer ownership of %d from %d to %d\n",
pFile->h, pFile->tid, hSelf);
pFile->tid = hSelf;
if (pFile->pLock != NULL) {
releaseLockInfo(pFile->pLock);
rc = findLockInfo(pFile->h, &pFile->pLock, 0);
OSTRACE5("LOCK %d is now %s(%s,%d)\n", pFile->h,
locktypeName(pFile->locktype),
locktypeName(pFile->pLock->locktype), pFile->pLock->cnt);
return rc;
} else {
return SQLITE_OK;
}
}
#else
/* On single-threaded builds, ownership transfer is a no-op */
# define transferOwnership(X) SQLITE_OK
#endif
/*
** Seek to the offset passed as the second argument, then read cnt
** bytes into pBuf. Return the number of bytes actually read.
**
** NB: If you define USE_PREAD or USE_PREAD64, then it might also
** be necessary to define _XOPEN_SOURCE to be 500. This varies from
** one system to another. Since SQLite does not define USE_PREAD
** any any form by default, we will not attempt to define _XOPEN_SOURCE.
** See tickets #2741 and #2681.
*/
static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
int got;
i64 newOffset;
TIMER_START;
#if defined(USE_PREAD)
got = pread(id->h, pBuf, cnt, offset);
SimulateIOError( got = -1 );
#elif defined(USE_PREAD64)
got = pread64(id->h, pBuf, cnt, offset);
SimulateIOError( got = -1 );
#else
sqlite-amalgamation.c view on Meta::CPAN
if( (!HAVE_FULLFSYNC || !isFullsync) && full_fsync(pFile->dirfd,0,0) ){
/*
** We have received multiple reports of fsync() returning
** errors when applied to directories on certain file systems.
** A failed directory sync is not a big deal. So it seems
** better to ignore the error. Ticket #1657
*/
/* return SQLITE_IOERR; */
}
#endif
close(pFile->dirfd); /* Only need to sync once, so close the directory */
pFile->dirfd = -1; /* when we are done. */
}
return SQLITE_OK;
}
/*
** Truncate an open file to a specified size
*/
static int unixTruncate(sqlite3_file *id, i64 nByte){
int rc;
assert( id );
SimulateIOError( return SQLITE_IOERR_TRUNCATE );
rc = ftruncate(((unixFile*)id)->h, (off_t)nByte);
if( rc ){
return SQLITE_IOERR_TRUNCATE;
}else{
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 = fstat(((unixFile*)id)->h, &buf);
SimulateIOError( rc=1 );
if( rc!=0 ){
return SQLITE_IOERR_FSTAT;
}
*pSize = buf.st_size;
/* When opening a zero-size database, the findLockInfo() 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;
}
/*
** This routine checks if there is a RESERVED lock held on the specified
** file by this or any other process. If such a lock is held, return
** non-zero. If the file is unlocked or holds only SHARED locks, then
** return zero.
*/
static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
int r = 0;
unixFile *pFile = (unixFile*)id;
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
assert( pFile );
enterMutex(); /* Because pFile->pLock is shared across threads */
/* Check if a thread in this process holds such a lock */
if( pFile->pLock->locktype>SHARED_LOCK ){
r = 1;
}
/* Otherwise see if some other process holds it.
*/
if( !r ){
struct flock lock;
lock.l_whence = SEEK_SET;
lock.l_start = RESERVED_BYTE;
lock.l_len = 1;
lock.l_type = F_WRLCK;
fcntl(pFile->h, F_GETLK, &lock);
if( lock.l_type!=F_UNLCK ){
r = 1;
}
}
leaveMutex();
OSTRACE3("TEST WR-LOCK %d %d\n", pFile->h, r);
*pResOut = r;
return SQLITE_OK;
}
/*
** Lock the file with the lock specified by parameter locktype - one
** of the following:
**
** (1) SHARED_LOCK
** (2) RESERVED_LOCK
** (3) PENDING_LOCK
** (4) EXCLUSIVE_LOCK
**
** Sometimes when requesting one lock state, additional lock states
** are inserted in between. The locking might fail on one of the later
** transitions leaving the lock state different from what it started but
** still short of its goal. The following chart shows the allowed
** transitions and the inserted intermediate states:
**
** UNLOCKED -> SHARED
** SHARED -> RESERVED
** SHARED -> (PENDING) -> EXCLUSIVE
** RESERVED -> (PENDING) -> EXCLUSIVE
** PENDING -> EXCLUSIVE
**
** This routine will only increase a lock. Use the sqlite3OsUnlock()
** routine to lower a locking level.
*/
static int unixLock(sqlite3_file *id, int locktype){
/* The following describes the implementation of the various locks and
** lock transitions in terms of the POSIX advisory shared and exclusive
** lock primitives (called read-locks and write-locks below, to avoid
** confusion with SQLite lock names). The algorithms are complicated
** slightly in order to be compatible with windows systems simultaneously
** accessing the same database file, in case that is ever required.
**
** Symbols defined in os.h indentify the 'pending byte' and the 'reserved
** byte', each single bytes at well known offsets, and the 'shared byte
** range', a range of 510 bytes at a well known offset.
**
** To obtain a SHARED lock, a read-lock is obtained on the 'pending
** byte'. If this is successful, a random byte from the 'shared byte
** range' is read-locked and the lock on the 'pending byte' released.
**
** A process may only obtain a RESERVED lock after it has a SHARED lock.
** A RESERVED lock is implemented by grabbing a write-lock on the
** 'reserved byte'.
**
** A process may only obtain a PENDING lock after it has obtained a
** SHARED lock. A PENDING lock is implemented by obtaining a write-lock
** on the 'pending byte'. This ensures that no new SHARED locks can be
** obtained, but existing SHARED locks are allowed to persist. A process
** does not have to obtain a RESERVED lock on the way to a PENDING lock.
** This property is used by the algorithm for rolling back a journal file
** after a crash.
**
** An EXCLUSIVE lock, obtained after a PENDING lock is held, is
** implemented by obtaining a write-lock on the entire 'shared byte
** range'. Since all other locks require a read-lock on one of the bytes
** within this range, this ensures that no other locks are held on the
** database.
**
** The reason a single byte cannot be used instead of the 'shared byte
** range' is that some versions of windows do not support read-locks. By
** locking a random byte from a range, concurrent SHARED locks may exist
** even if the locking primitive used is always a write-lock.
*/
int rc = SQLITE_OK;
unixFile *pFile = (unixFile*)id;
struct lockInfo *pLock = pFile->pLock;
struct flock lock;
int s;
assert( pFile );
OSTRACE7("LOCK %d %s was %s(%s,%d) pid=%d\n", pFile->h,
locktypeName(locktype), locktypeName(pFile->locktype),
locktypeName(pLock->locktype), pLock->cnt , getpid());
/* If there is already a lock of this type or more restrictive on the
** unixFile, do nothing. Don't use the end_lock: exit path, as
** enterMutex() hasn't been called yet.
*/
if( pFile->locktype>=locktype ){
OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h,
locktypeName(locktype));
return SQLITE_OK;
}
/* Make sure the locking sequence is correct
*/
assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
assert( locktype!=PENDING_LOCK );
assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
/* This mutex is needed because pFile->pLock is shared across threads
*/
enterMutex();
/* Make sure the current thread owns the pFile.
*/
rc = transferOwnership(pFile);
if( rc!=SQLITE_OK ){
leaveMutex();
sqlite-amalgamation.c view on Meta::CPAN
close(pFile->h);
}
OSTRACE2("CLOSE %-3d\n", pFile->h);
OpenCounter(-1);
memset(pFile, 0, sizeof(unixFile));
}
return SQLITE_OK;
}
/*
** Close a file.
*/
static int unixClose(sqlite3_file *id){
if( id ){
unixFile *pFile = (unixFile *)id;
unixUnlock(id, NO_LOCK);
enterMutex();
if( pFile->pOpen && pFile->pOpen->nLock ){
/* If there are outstanding locks, do not actually close the file just
** yet because that would clear those locks. Instead, add the file
** descriptor to pOpen->aPending. It will be automatically closed when
** the last lock is cleared.
*/
int *aNew;
struct openCnt *pOpen = pFile->pOpen;
aNew = sqlite3_realloc(pOpen->aPending, (pOpen->nPending+1)*sizeof(int) );
if( aNew==0 ){
/* If a malloc fails, just leak the file descriptor */
}else{
pOpen->aPending = aNew;
pOpen->aPending[pOpen->nPending] = pFile->h;
pOpen->nPending++;
pFile->h = -1;
}
}
releaseLockInfo(pFile->pLock);
releaseOpenCnt(pFile->pOpen);
closeUnixFile(id);
leaveMutex();
}
return SQLITE_OK;
}
#ifdef SQLITE_ENABLE_LOCKING_STYLE
#pragma mark AFP Support
/*
** The afpLockingContext structure contains all afp lock specific state
*/
typedef struct afpLockingContext afpLockingContext;
struct afpLockingContext {
unsigned long long sharedLockByte;
const char *filePath;
};
struct ByteRangeLockPB2
{
unsigned long long offset; /* offset to first byte to lock */
unsigned long long length; /* nbr of bytes to lock */
unsigned long long retRangeStart; /* nbr of 1st byte locked if successful */
unsigned char unLockFlag; /* 1 = unlock, 0 = lock */
unsigned char startEndFlag; /* 1=rel to end of fork, 0=rel to start */
int fd; /* file desc to assoc this lock with */
};
#define afpfsByteRangeLock2FSCTL _IOWR('z', 23, struct ByteRangeLockPB2)
/*
** Return 0 on success, 1 on failure. To match the behavior of the
** normal posix file locking (used in unixLock for example), we should
** provide 'richer' return codes - specifically to differentiate between
** 'file busy' and 'file system error' results.
*/
static int _AFPFSSetLock(
const char *path,
int fd,
unsigned long long offset,
unsigned long long length,
int setLockFlag
){
struct ByteRangeLockPB2 pb;
int err;
pb.unLockFlag = setLockFlag ? 0 : 1;
pb.startEndFlag = 0;
pb.offset = offset;
pb.length = length;
pb.fd = fd;
OSTRACE5("AFPLOCK setting lock %s for %d in range %llx:%llx\n",
(setLockFlag?"ON":"OFF"), fd, offset, length);
err = fsctl(path, afpfsByteRangeLock2FSCTL, &pb, 0);
if ( err==-1 ) {
OSTRACE4("AFPLOCK failed to fsctl() '%s' %d %s\n", path, errno,
strerror(errno));
return 1; /* error */
} else {
return 0;
}
}
/*
** This routine checks if there is a RESERVED lock held on the specified
** file by this or any other process. If such a lock is held, return
** non-zero. If the file is unlocked or holds only SHARED locks, then
** return zero.
*/
static int afpCheckReservedLock(sqlite3_file *id, int *pResOut){
int r = 0;
unixFile *pFile = (unixFile*)id;
assert( pFile );
afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
/* Check if a thread in this process holds such a lock */
if( pFile->locktype>SHARED_LOCK ){
r = 1;
}
/* Otherwise see if some other process holds it.
*/
if ( !r ) {
/* lock the byte */
int failed = _AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1,1);
if (failed) {
/* if we failed to get the lock then someone else must have it */
r = 1;
} else {
/* if we succeeded in taking the reserved lock, unlock it to restore
** the original state */
_AFPFSSetLock(context->filePath, pFile->h, RESERVED_BYTE, 1, 0);
}
}
OSTRACE3("TEST WR-LOCK %d %d\n", pFile->h, r);
*pResOut = r;
return SQLITE_OK;
}
/* AFP-style locking following the behavior of unixLock, see the unixLock
** function comments for details of lock management. */
static int afpLock(sqlite3_file *id, int locktype){
int rc = SQLITE_OK;
unixFile *pFile = (unixFile*)id;
afpLockingContext *context = (afpLockingContext *) pFile->lockingContext;
assert( pFile );
OSTRACE5("LOCK %d %s was %s pid=%d\n", pFile->h,
locktypeName(locktype), locktypeName(pFile->locktype), getpid());
/* If there is already a lock of this type or more restrictive on the
** unixFile, do nothing. Don't use the afp_end_lock: exit path, as
** enterMutex() hasn't been called yet.
*/
if( pFile->locktype>=locktype ){
OSTRACE3("LOCK %d %s ok (already held)\n", pFile->h,
locktypeName(locktype));
return SQLITE_OK;
}
/* Make sure the locking sequence is correct
*/
assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
assert( locktype!=PENDING_LOCK );
assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
sqlite-amalgamation.c view on Meta::CPAN
** If the optimization cannot be used, 0 is returned. 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.
*/
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
static int jrnlBufferSize(Pager *pPager){
int dc; /* Device characteristics */
int nSector; /* Sector size */
int szPage; /* Page size */
sqlite3_file *fd = pPager->fd;
if( fd->pMethods ){
dc = sqlite3OsDeviceCharacteristics(fd);
nSector = sqlite3OsSectorSize(fd);
szPage = pPager->pageSize;
}
assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
if( !fd->pMethods ||
(dc & (SQLITE_IOCAP_ATOMIC|(szPage>>8)) && nSector<=szPage) ){
return JOURNAL_HDR_SZ(pPager) + JOURNAL_PG_SZ(pPager);
}
return 0;
}
#endif
/*
** This function should be called when an error occurs within the pager
** code. The first argument is a pointer to the pager structure, the
** second the error-code about to be returned by a pager API function.
** The value returned is a copy of the second argument to this function.
**
** If the second argument is SQLITE_IOERR, SQLITE_CORRUPT, or SQLITE_FULL
** the error becomes persistent. Until the persisten error is cleared,
** subsequent API calls on this Pager will immediately return the same
** error code.
**
** A persistent error 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 occured, then the rollback journal may need
** to be replayed.
*/
static void pager_unlock(Pager *pPager);
static int pager_error(Pager *pPager, int rc){
int rc2 = rc & 0xff;
assert(
pPager->errCode==SQLITE_FULL ||
pPager->errCode==SQLITE_OK ||
(pPager->errCode & 0xff)==SQLITE_IOERR
);
if(
rc2==SQLITE_FULL ||
rc2==SQLITE_IOERR ||
rc2==SQLITE_CORRUPT
){
pPager->errCode = rc;
if( pPager->state==PAGER_UNLOCK && pPager->nRef==0 ){
/* If the pager is already unlocked, call pager_unlock() now to
** clear the error state and ensure that the pager-cache is
** completely empty.
*/
pager_unlock(pPager);
}
}
return rc;
}
/*
** If SQLITE_CHECK_PAGES is defined then we do some sanity checking
** on the cache using a hash function. This is used for testing
** and debugging only.
*/
#ifdef SQLITE_CHECK_PAGES
/*
** Return a 32-bit hash of the page data for pPage.
*/
static u32 pager_datahash(int nByte, unsigned char *pData){
u32 hash = 0;
int i;
for(i=0; i<nByte; i++){
hash = (hash*1039) + pData[i];
}
return hash;
}
static u32 pager_pagehash(PgHdr *pPage){
return pager_datahash(pPage->pPager->pageSize,
(unsigned char *)PGHDR_TO_DATA(pPage));
}
/*
** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES
** is defined, and NDEBUG is not defined, an assert() statement checks
** that the page is either dirty or still matches the calculated page-hash.
*/
#define CHECK_PAGE(x) checkPage(x)
static void checkPage(PgHdr *pPg){
Pager *pPager = pPg->pPager;
assert( !pPg->pageHash || pPager->errCode || MEMDB || pPg->dirty ||
pPg->pageHash==pager_pagehash(pPg) );
}
#else
#define pager_datahash(X,Y) 0
#define pager_pagehash(X) 0
#define CHECK_PAGE(x)
#endif
/*
** When this is called the journal file for pager pPager must be open.
** The master journal file name is read from the end of the file and
** written into memory supplied by the caller.
**
** zMaster must point to a buffer of at least nMaster bytes allocated by
** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is
** enough space to write the master journal name). If the master journal
** name in the journal is longer than nMaster bytes (including a
** nul-terminator), then this is handled as if no master journal name
** were present in the journal.
sqlite-amalgamation.c view on Meta::CPAN
/*
** Clear the in-memory cache. This routine
** sets the state of the pager back to what it was when it was first
** opened. Any outstanding pages are invalidated and subsequent attempts
** to access those pages will likely result in a coredump.
*/
static void pager_reset(Pager *pPager){
PgHdr *pPg, *pNext;
if( pPager->errCode ) return;
for(pPg=pPager->pAll; pPg; pPg=pNext){
IOTRACE(("PGFREE %p %d\n", pPager, pPg->pgno));
PAGER_INCR(sqlite3_pager_pgfree_count);
pNext = pPg->pNextAll;
lruListRemove(pPg);
sqlite3PageFree(pPg->pData);
sqlite3_free(pPg);
}
assert(pPager->lru.pFirst==0);
assert(pPager->lru.pFirstSynced==0);
assert(pPager->lru.pLast==0);
pPager->pStmt = 0;
pPager->pAll = 0;
pPager->pDirty = 0;
pPager->nHash = 0;
sqlite3_free(pPager->aHash);
pPager->nPage = 0;
pPager->aHash = 0;
pPager->nRef = 0;
}
/*
** Unlock the database file.
**
** If the pager is currently in error state, discard the contents of
** the cache and reset the Pager structure internal state. If there is
** an open journal-file, then the next time a shared-lock is obtained
** on the pager file (by this or any other process), it will be
** treated as a hot-journal and rolled back.
*/
static void pager_unlock(Pager *pPager){
if( !pPager->exclusiveMode ){
if( !MEMDB ){
int rc = osUnlock(pPager->fd, NO_LOCK);
if( rc ) pPager->errCode = rc;
pPager->dbSize = -1;
IOTRACE(("UNLOCK %p\n", pPager))
/* Always close the journal file when dropping the database lock.
** Otherwise, another connection with journal_mode=delete might
** delete the file out from under us.
*/
if( pPager->journalOpen ){
sqlite3OsClose(pPager->jfd);
pPager->journalOpen = 0;
sqlite3BitvecDestroy(pPager->pInJournal);
pPager->pInJournal = 0;
}
/* If Pager.errCode is set, the contents of the pager cache cannot be
** trusted. Now that the pager file is unlocked, the contents of the
** cache can be discarded and the error code safely cleared.
*/
if( pPager->errCode ){
if( rc==SQLITE_OK ) pPager->errCode = SQLITE_OK;
pager_reset(pPager);
if( pPager->stmtOpen ){
sqlite3OsClose(pPager->stfd);
sqlite3BitvecDestroy(pPager->pInStmt);
pPager->pInStmt = 0;
}
pPager->stmtOpen = 0;
pPager->stmtInUse = 0;
pPager->journalOff = 0;
pPager->journalStarted = 0;
pPager->stmtAutoopen = 0;
pPager->origDbSize = 0;
}
}
if( !MEMDB || pPager->errCode==SQLITE_OK ){
pPager->state = PAGER_UNLOCK;
pPager->changeCountDone = 0;
}
}
}
/*
** 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.
*/
static void pagerUnlockAndRollback(Pager *p){
/* assert( p->state>=PAGER_RESERVED || p->journalOpen==0 ); */
if( p->errCode==SQLITE_OK && p->state>=PAGER_RESERVED ){
sqlite3BeginBenignMalloc();
sqlite3PagerRollback(p);
sqlite3EndBenignMalloc();
}
pager_unlock(p);
#if 0
assert( p->errCode || !p->journalOpen || (p->exclusiveMode&&!p->journalOff) );
assert( p->errCode || !p->stmtOpen || p->exclusiveMode );
#endif
}
/*
** This routine ends a transaction. A transaction is ended by either
** a COMMIT or a ROLLBACK.
**
** When this routine is called, the pager has the journal file open and
** a RESERVED or EXCLUSIVE lock on the database. This routine will release
** the database lock and acquires a SHARED lock in its place if that is
** the appropriate thing to do. Release locks usually is appropriate,
** unless we are in exclusive access mode or unless this is a
** COMMIT AND BEGIN or ROLLBACK AND BEGIN operation.
**
** The journal file is either deleted or truncated.
**
** TODO: Consider keeping the journal file open for temporary databases.
** This might give a performance improvement on windows where opening
sqlite-amalgamation.c view on Meta::CPAN
u8 *aData = (u8 *)pPager->pTmpSpace; /* Temp storage for a page */
/* useCksum should be true for the main journal and false for
** statement journals. Verify that this is always the case
*/
assert( jfd == (useCksum ? pPager->jfd : pPager->stfd) );
assert( aData );
rc = read32bits(jfd, offset, &pgno);
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3OsRead(jfd, aData, pPager->pageSize, offset+4);
if( rc!=SQLITE_OK ) return rc;
pPager->journalOff += pPager->pageSize + 4;
/* Sanity checking on the page. This is more important that I originally
** thought. If a power failure occurs while the journal is being written,
** it could cause invalid data to be written into the journal. We need to
** detect this invalid data (with high probability) and ignore it.
*/
if( pgno==0 || pgno==PAGER_MJ_PGNO(pPager) ){
return SQLITE_DONE;
}
if( pgno>(unsigned)pPager->dbSize ){
return SQLITE_OK;
}
if( useCksum ){
rc = read32bits(jfd, offset+pPager->pageSize+4, &cksum);
if( rc ) return rc;
pPager->journalOff += 4;
if( pager_cksum(pPager, aData)!=cksum ){
return SQLITE_DONE;
}
}
assert( pPager->state==PAGER_RESERVED || pPager->state>=PAGER_EXCLUSIVE );
/* If the pager is in RESERVED state, then there must be a copy of this
** page in the pager cache. In this case just update the pager cache,
** not the database file. The page is left marked dirty in this case.
**
** An exception to the above rule: If the database is in no-sync mode
** and a page is moved during an incremental vacuum then the page may
** not be in the pager cache. Later: if a malloc() or IO error occurs
** during a Movepage() call, then the page may not be in the cache
** either. So the condition described in the above paragraph is not
** assert()able.
**
** If in EXCLUSIVE state, then we update the pager cache if it exists
** and the main file. The page is then marked not dirty.
**
** Ticket #1171: The statement journal might contain page content that is
** different from the page content at the start of the transaction.
** This occurs when a page is changed prior to the start of a statement
** then changed again within the statement. When rolling back such a
** statement we must not write to the original database unless we know
** for certain that original page contents are synced into the main rollback
** journal. Otherwise, a power loss might leave modified data in the
** database file without an entry in the rollback journal that can
** restore the database to its original form. Two conditions must be
** met before writing to the database files. (1) the database must be
** locked. (2) we know that the original page content is fully synced
** in the main journal either because the page is not in cache or else
** the page is marked as needSync==0.
**
** 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.
*/
pPg = pager_lookup(pPager, pgno);
PAGERTRACE4("PLAYBACK %d page %d hash(%08x)\n",
PAGERID(pPager), pgno, pager_datahash(pPager->pageSize, aData));
if( pPager->state>=PAGER_EXCLUSIVE && (pPg==0 || pPg->needSync==0)
&& pPager->fd->pMethods ){
i64 offset = (pgno-1)*(i64)pPager->pageSize;
rc = sqlite3OsWrite(pPager->fd, aData, pPager->pageSize, offset);
if( pPg ){
makeClean(pPg);
}
}
if( pPg ){
/* No page should ever be explicitly rolled back that is in use, except
** for page 1 which is held in use in order to keep the lock on the
** database active. However such a page may be rolled back as a result
** of an internal error resulting in an automatic call to
** sqlite3PagerRollback().
*/
void *pData;
/* assert( pPg->nRef==0 || pPg->pgno==1 ); */
pData = PGHDR_TO_DATA(pPg);
memcpy(pData, aData, pPager->pageSize);
if( pPager->xReiniter ){
pPager->xReiniter(pPg, pPager->pageSize);
}
#ifdef SQLITE_CHECK_PAGES
pPg->pageHash = pager_pagehash(pPg);
#endif
/* If this was page 1, then restore the value of Pager.dbFileVers.
** Do this before any decoding. */
if( pgno==1 ){
memcpy(&pPager->dbFileVers, &((u8*)pData)[24],sizeof(pPager->dbFileVers));
}
/* Decode the page just read from disk */
CODEC1(pPager, pData, pPg->pgno, 3);
}
return rc;
}
/*
** Parameter zMaster is the name of a master journal file. A single journal
** file that referred to the master journal file has just been rolled back.
** This routine checks if it is possible to delete the master journal file,
** and does so if it is.
**
** Argument zMaster may point to Pager.pTmpSpace. So that buffer is not
** available for use within this function.
**
**
** The master journal file contains the names of all child journals.
** To tell if a master journal can be deleted, check to each of the
** children. If all children are either missing or do not refer to
sqlite-amalgamation.c view on Meta::CPAN
** that an inopertune power failure could leave the journal
** in a state which would cause damage to the database
** when it is rolled back.
**
** FULL The journal is synced twice before writes begin on the
** database (with some additional information - the nRec field
** of the journal header - being written in between the two
** syncs). If we assume that writing a
** single disk sector is atomic, then this mode provides
** assurance that the journal will not be corrupted to the
** point of causing damage to the database during rollback.
**
** Numeric values associated with these states are OFF==1, NORMAL=2,
** and FULL=3.
*/
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
SQLITE_PRIVATE void sqlite3PagerSetSafetyLevel(Pager *pPager, int level, int full_fsync){
pPager->noSync = level==1 || pPager->tempFile;
pPager->fullSync = level==3 && !pPager->tempFile;
pPager->sync_flags = (full_fsync?SQLITE_SYNC_FULL:SQLITE_SYNC_NORMAL);
if( pPager->noSync ) pPager->needSync = 0;
}
#endif
/*
** The following global variable is incremented whenever the library
** attempts to open a temporary file. This information is used for
** testing and analysis only.
*/
#ifdef SQLITE_TEST
SQLITE_API int sqlite3_opentemp_count = 0;
#endif
/*
** Open a temporary file.
**
** Write the file descriptor into *fd. Return SQLITE_OK on success or some
** other error code if we fail. The OS will automatically delete the temporary
** file when it is closed.
*/
static int sqlite3PagerOpentemp(
Pager *pPager, /* The pager object */
sqlite3_file *pFile, /* Write the file descriptor here */
int vfsFlags /* Flags passed through to the VFS */
){
int rc;
#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 || pFile->pMethods );
return rc;
}
/*
** Create a new page cache and put a pointer to the page cache in *ppPager.
** The file to be cached need not exist. The file is not locked until
** the first call to sqlite3PagerGet() and is only held open until the
** last page is released using sqlite3PagerUnref().
**
** If zFilename is NULL then a randomly-named temporary file is created
** and used as the file to be cached. The file will be deleted
** automatically when it is closed.
**
** If zFilename is ":memory:" then all information is held in cache.
** It is never written to disk. This can be used to implement an
** in-memory database.
*/
SQLITE_PRIVATE int sqlite3PagerOpen(
sqlite3_vfs *pVfs, /* The virtual file system to use */
Pager **ppPager, /* Return the Pager structure here */
const char *zFilename, /* Name of the database file to open */
int nExtra, /* Extra bytes append to each in-memory page */
int flags, /* flags controlling this file */
int vfsFlags /* flags passed through to sqlite3_vfs.xOpen() */
){
u8 *pPtr;
Pager *pPager = 0;
int rc = SQLITE_OK;
int i;
int tempFile = 0;
int memDb = 0;
int readOnly = 0;
int useJournal = (flags & PAGER_OMIT_JOURNAL)==0;
int noReadlock = (flags & PAGER_NO_READLOCK)!=0;
int journalFileSize = sqlite3JournalSize(pVfs);
int szPageDflt = SQLITE_DEFAULT_PAGE_SIZE;
char *zPathname = 0;
int nPathname = 0;
/* The default return is a NULL pointer */
*ppPager = 0;
/* Compute and store the full pathname in an allocated buffer pointed
** to by zPathname, length nPathname. Or, if this is a temporary file,
** leave both nPathname and zPathname set to 0.
*/
if( zFilename && zFilename[0] ){
nPathname = pVfs->mxPathname+1;
zPathname = sqlite3Malloc(nPathname*2);
if( zPathname==0 ){
return SQLITE_NOMEM;
}
#ifndef SQLITE_OMIT_MEMORYDB
if( strcmp(zFilename,":memory:")==0 ){
memDb = 1;
zPathname[0] = 0;
}else
#endif
{
rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname);
}
if( rc!=SQLITE_OK ){
sqlite3_free(zPathname);
return rc;
}
nPathname = strlen(zPathname);
sqlite-amalgamation.c view on Meta::CPAN
}
/*
** This routine is used to truncate the cache when a database
** is truncated. Drop from the cache all pages whose pgno is
** larger than pPager->dbSize and is unreferenced.
**
** Referenced pages larger than pPager->dbSize are zeroed.
**
** Actually, at the point this routine is called, it would be
** an error to have a referenced page. But rather than delete
** that page and guarantee a subsequent segfault, it seems better
** to zero it and hope that we error out sanely.
*/
static void pager_truncate_cache(Pager *pPager){
PgHdr *pPg;
PgHdr **ppPg;
int dbSize = pPager->dbSize;
ppPg = &pPager->pAll;
while( (pPg = *ppPg)!=0 ){
if( pPg->pgno<=dbSize ){
ppPg = &pPg->pNextAll;
}else if( pPg->nRef>0 ){
memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize);
ppPg = &pPg->pNextAll;
}else{
*ppPg = pPg->pNextAll;
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
if( *ppPg ){
(*ppPg)->pPrevAll = pPg->pPrevAll;
}
#endif
IOTRACE(("PGFREE %p %d\n", pPager, pPg->pgno));
PAGER_INCR(sqlite3_pager_pgfree_count);
unlinkPage(pPg);
makeClean(pPg);
sqlite3PageFree(pPg->pData);
sqlite3_free(pPg);
pPager->nPage--;
}
}
}
/*
** Try to obtain a lock on a file. Invoke the busy callback if the lock
** is currently not available. Repeat until the busy callback returns
** false or until the lock succeeds.
**
** Return SQLITE_OK on success and an error code if we cannot obtain
** the lock.
*/
static int pager_wait_on_lock(Pager *pPager, int locktype){
int rc;
/* The OS lock values must be the same as the Pager lock values */
assert( PAGER_SHARED==SHARED_LOCK );
assert( PAGER_RESERVED==RESERVED_LOCK );
assert( PAGER_EXCLUSIVE==EXCLUSIVE_LOCK );
/* If the file is currently unlocked then the size must be unknown */
assert( pPager->state>=PAGER_SHARED || pPager->dbSize<0 || MEMDB );
if( pPager->state>=locktype ){
rc = SQLITE_OK;
}else{
if( pPager->pBusyHandler ) pPager->pBusyHandler->nBusy = 0;
do {
rc = sqlite3OsLock(pPager->fd, locktype);
}while( rc==SQLITE_BUSY && sqlite3InvokeBusyHandler(pPager->pBusyHandler) );
if( rc==SQLITE_OK ){
pPager->state = locktype;
IOTRACE(("LOCK %p %d\n", pPager, locktype))
}
}
return rc;
}
/*
** Truncate the file to the number of pages specified.
*/
SQLITE_PRIVATE int sqlite3PagerTruncate(Pager *pPager, Pgno nPage){
int rc;
assert( pPager->state>=PAGER_SHARED || MEMDB );
sqlite3PagerPagecount(pPager, 0);
if( pPager->errCode ){
rc = pPager->errCode;
return rc;
}
if( nPage>=(unsigned)pPager->dbSize ){
return SQLITE_OK;
}
if( MEMDB ){
pPager->dbSize = nPage;
pager_truncate_cache(pPager);
return SQLITE_OK;
}
pagerEnter(pPager);
rc = syncJournal(pPager);
pagerLeave(pPager);
if( rc!=SQLITE_OK ){
return rc;
}
/* Get an exclusive lock on the database before truncating. */
pagerEnter(pPager);
rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
pagerLeave(pPager);
if( rc!=SQLITE_OK ){
return rc;
}
rc = pager_truncate(pPager, nPage);
return rc;
}
/*
** Shutdown the page cache. Free all memory and close all files.
**
** If a transaction was in progress when this routine is called, that
** transaction is rolled back. All outstanding pages are invalidated
sqlite-amalgamation.c view on Meta::CPAN
else{
PAGERTRACE3("NOSTORE %d page %d\n", PAGERID(pPager), pList->pgno);
}
#endif
if( rc ) return rc;
#ifdef SQLITE_CHECK_PAGES
pList->pageHash = pager_pagehash(pList);
#endif
pList = pList->pDirty;
}
return SQLITE_OK;
}
/*
** Collect every dirty page into a dirty list and
** return a pointer to the head of that list. All pages are
** collected even if they are still in use.
*/
static PgHdr *pager_get_all_dirty_pages(Pager *pPager){
#ifndef NDEBUG
/* Verify the sanity of the dirty list when we are running
** in debugging mode. This is expensive, so do not
** do this on a normal build. */
int n1 = 0;
int n2 = 0;
PgHdr *p;
for(p=pPager->pAll; p; p=p->pNextAll){ if( p->dirty ) n1++; }
for(p=pPager->pDirty; p; p=p->pDirty){ n2++; }
assert( n1==n2 );
#endif
return pPager->pDirty;
}
/*
** Return 1 if there is a hot journal on the given pager.
** A hot journal is one that needs to be played back.
**
** If the current size of the database file is 0 but a journal file
** exists, that is probably an old journal left over from a prior
** database with the same name. Just delete the journal.
**
** Return negative if unable to determine the status of the journal.
**
** This routine does not open the journal file to examine its
** content. Hence, the journal might contain the name of a master
** journal file that has been deleted, and hence not be hot. Or
** the header of the journal might be zeroed out. This routine
** does not discover these cases of a non-hot journal - if the
** journal file exists and is not empty this routine assumes it
** is hot. The pager_playback() routine will discover that the
** journal file is not really hot and will no-op.
*/
static int hasHotJournal(Pager *pPager, int *pExists){
sqlite3_vfs *pVfs = pPager->pVfs;
int rc = SQLITE_OK;
*pExists = 0;
if( pPager->useJournal && pPager->fd->pMethods ){
int exists;
int locked;
rc = sqlite3OsAccess(pVfs, pPager->zJournal, SQLITE_ACCESS_EXISTS, &exists);
if( rc==SQLITE_OK && exists ){
rc = sqlite3OsCheckReservedLock(pPager->fd, &locked);
}
if( rc==SQLITE_OK && exists && !locked ){
int nPage;
rc = sqlite3PagerPagecount(pPager, &nPage);
if( rc==SQLITE_OK ){
if( nPage==0 ){
sqlite3OsDelete(pVfs, pPager->zJournal, 0);
}else{
*pExists = 1;
}
}
}
}
return rc;
}
/*
** Try to find a page in the cache that can be recycled.
**
** This routine may return SQLITE_IOERR, SQLITE_FULL or SQLITE_OK. It
** does not set the pPager->errCode variable.
*/
static int pager_recycle(Pager *pPager, PgHdr **ppPg){
PgHdr *pPg;
*ppPg = 0;
/* It is illegal to call this function unless the pager object
** pointed to by pPager has at least one free page (page with nRef==0).
*/
assert(!MEMDB);
assert(pPager->lru.pFirst);
/* Find a page to recycle. Try to locate a page that does not
** require us to do an fsync() on the journal.
*/
pPg = pPager->lru.pFirstSynced;
/* If we could not find a page that does not require an fsync()
** on the journal file then fsync the journal file. This is a
** very slow operation, so we work hard to avoid it. But sometimes
** it can't be helped.
*/
if( pPg==0 && pPager->lru.pFirst ){
if( !pPager->errCode ){
int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
int rc = syncJournal(pPager);
if( rc!=0 ){
return rc;
}
if( pPager->fullSync && 0==(iDc&SQLITE_IOCAP_SAFE_APPEND) ){
/* If in full-sync mode, write a new journal header into the
** journal file. This is done to avoid ever modifying a journal
** header that is involved in the rollback of pages that have
** already been written to the database (in case the header is
** trashed when the nRec field is updated).
*/
pPager->nRec = 0;
assert( pPager->journalOff > 0 );
assert( pPager->doNotSync==0 );
rc = writeJournalHdr(pPager);
if( rc!=0 ){
sqlite-amalgamation.c view on Meta::CPAN
struct MemPage {
u8 isInit; /* True if previously initialized. MUST BE FIRST! */
u8 idxShift; /* True if Cell indices have changed */
u8 nOverflow; /* Number of overflow cell bodies in aCell[] */
u8 intKey; /* True if intkey flag is set */
u8 leaf; /* True if leaf flag is set */
u8 hasData; /* True if this page stores data */
u8 hdrOffset; /* 100 for page 1. 0 otherwise */
u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */
u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */
u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */
u16 cellOffset; /* Index in aData of first cell pointer */
u16 idxParent; /* Index in parent of this node */
u16 nFree; /* Number of free bytes on the page */
u16 nCell; /* Number of cells on this page, local and ovfl */
u16 maskPage; /* Mask for page offset */
struct _OvflCell { /* Cells that will not fit on aData[] */
u8 *pCell; /* Pointers to the body of the overflow cell */
u16 idx; /* Insert this cell before idx-th non-overflow cell */
} aOvfl[5];
BtShared *pBt; /* Pointer to BtShared that this page is part of */
u8 *aData; /* Pointer to disk image of the page data */
DbPage *pDbPage; /* Pager page handle */
Pgno pgno; /* Page number for this page */
MemPage *pParent; /* The parent of this page. NULL for root */
};
/*
** The in-memory image of a disk page has the auxiliary information appended
** to the end. EXTRA_SIZE is the number of bytes of space needed to hold
** that extra information.
*/
#define EXTRA_SIZE sizeof(MemPage)
/* A Btree handle
**
** A database connection contains a pointer to an instance of
** this object for every database file that it has open. This structure
** is opaque to the database connection. The database connection cannot
** see the internals of this structure and only deals with pointers to
** this structure.
**
** For some database files, the same underlying database cache might be
** shared between multiple connections. In that case, each contection
** has it own pointer to this object. But each instance of this object
** points to the same BtShared object. The database cache and the
** schema associated with the database file are all contained within
** the BtShared object.
**
** All fields in this structure are accessed under sqlite3.mutex.
** The pBt pointer itself may not be changed while there exists cursors
** in the referenced BtShared that point back to this Btree since those
** cursors have to do go through this Btree to find their BtShared and
** they often do so without holding sqlite3.mutex.
*/
struct Btree {
sqlite3 *db; /* The database connection holding this btree */
BtShared *pBt; /* Sharable content of this btree */
u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */
u8 sharable; /* True if we can share pBt with another db */
u8 locked; /* True if db currently has pBt locked */
int wantToLock; /* Number of nested calls to sqlite3BtreeEnter() */
Btree *pNext; /* List of other sharable Btrees from the same db */
Btree *pPrev; /* Back pointer of the same list */
};
/*
** Btree.inTrans may take one of the following values.
**
** If the shared-data extension is enabled, there may be multiple users
** of the Btree structure. At most one of these may open a write transaction,
** but any number may have active read transactions.
*/
#define TRANS_NONE 0
#define TRANS_READ 1
#define TRANS_WRITE 2
/*
** An instance of this object represents a single database file.
**
** A single database file can be in use as the same time by two
** or more database connections. When two or more connections are
** sharing the same database file, each connection has it own
** private Btree object for the file and each of those Btrees points
** to this one BtShared object. BtShared.nRef is the number of
** connections currently sharing this database file.
**
** Fields in this structure are accessed under the BtShared.mutex
** mutex, except for nRef and pNext which are accessed under the
** global SQLITE_MUTEX_STATIC_MASTER mutex. The pPager field
** may not be modified once it is initially set as long as nRef>0.
** The pSchema field may be set once under BtShared.mutex and
** thereafter is unchanged as long as nRef>0.
*/
struct BtShared {
Pager *pPager; /* The page cache */
sqlite3 *db; /* Database connection currently using this Btree */
BtCursor *pCursor; /* A list of all open cursors */
MemPage *pPage1; /* First page of the database */
u8 inStmt; /* True if we are in a statement subtransaction */
u8 readOnly; /* True if the underlying file is readonly */
u8 pageSizeFixed; /* True if the page size can no longer be changed */
#ifndef SQLITE_OMIT_AUTOVACUUM
u8 autoVacuum; /* True if auto-vacuum is enabled */
u8 incrVacuum; /* True if incr-vacuum is enabled */
Pgno nTrunc; /* Non-zero if the db will be truncated (incr vacuum) */
#endif
u16 pageSize; /* Total number of bytes on a page */
u16 usableSize; /* Number of usable bytes on each page */
int maxLocal; /* Maximum local payload in non-LEAFDATA tables */
int minLocal; /* Minimum local payload in non-LEAFDATA tables */
int maxLeaf; /* Maximum local payload in a LEAFDATA table */
int minLeaf; /* Minimum local payload in a LEAFDATA table */
u8 inTransaction; /* Transaction state */
int nTransaction; /* Number of open transactions (read + write) */
void *pSchema; /* Pointer to space allocated by sqlite3BtreeSchema() */
void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */
sqlite3_mutex *mutex; /* Non-recursive mutex required to access this struct */
BusyHandler busyHdr; /* The busy handler for this btree */
#ifndef SQLITE_OMIT_SHARED_CACHE
int nRef; /* Number of references to this structure */
sqlite-amalgamation.c view on Meta::CPAN
** (sqliteMallocRaw), it is not possible to use conditional compilation.
** So, this macro is defined instead.
*/
#ifndef SQLITE_OMIT_AUTOVACUUM
#define ISAUTOVACUUM (pBt->autoVacuum)
#else
#define ISAUTOVACUUM 0
#endif
/*
** This structure is passed around through all the sanity checking routines
** in order to keep track of some global state information.
*/
typedef struct IntegrityCk IntegrityCk;
struct IntegrityCk {
BtShared *pBt; /* The tree being checked out */
Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */
int nPage; /* Number of pages in the database */
int *anRef; /* Number of times each page is referenced */
int mxErr; /* Stop accumulating errors when this reaches zero */
int nErr; /* Number of messages written to zErrMsg so far */
int mallocFailed; /* A memory allocation error has occurred */
StrAccum errMsg; /* Accumulate the error message text here */
};
/*
** Read or write a two- and four-byte big-endian integer values.
*/
#define get2byte(x) ((x)[0]<<8 | (x)[1])
#define put2byte(p,v) ((p)[0] = (v)>>8, (p)[1] = (v))
#define get4byte sqlite3Get4byte
#define put4byte sqlite3Put4byte
/*
** Internal routines that should be accessed by the btree layer only.
*/
SQLITE_PRIVATE int sqlite3BtreeGetPage(BtShared*, Pgno, MemPage**, int);
SQLITE_PRIVATE int sqlite3BtreeInitPage(MemPage *pPage, MemPage *pParent);
SQLITE_PRIVATE void sqlite3BtreeParseCellPtr(MemPage*, u8*, CellInfo*);
SQLITE_PRIVATE void sqlite3BtreeParseCell(MemPage*, int, CellInfo*);
SQLITE_PRIVATE int sqlite3BtreeRestoreCursorPosition(BtCursor *pCur);
SQLITE_PRIVATE void sqlite3BtreeGetTempCursor(BtCursor *pCur, BtCursor *pTempCur);
SQLITE_PRIVATE void sqlite3BtreeReleaseTempCursor(BtCursor *pCur);
SQLITE_PRIVATE int sqlite3BtreeIsRootPage(MemPage *pPage);
SQLITE_PRIVATE void sqlite3BtreeMoveToParent(BtCursor *pCur);
/************** End of btreeInt.h ********************************************/
/************** Continuing where we left off in btmutex.c ********************/
#if SQLITE_THREADSAFE && !defined(SQLITE_OMIT_SHARED_CACHE)
/*
** Enter a mutex on the given BTree object.
**
** If the object is not sharable, then no mutex is ever required
** and this routine is a no-op. The underlying mutex is non-recursive.
** But we keep a reference count in Btree.wantToLock so the behavior
** of this interface is recursive.
**
** To avoid deadlocks, multiple Btrees are locked in the same order
** by all database connections. The p->pNext is a list of other
** Btrees belonging to the same database connection as the p Btree
** which need to be locked after p. If we cannot get a lock on
** p, then first unlock all of the others on p->pNext, then wait
** for the lock to become available on p, then relock all of the
** subsequent Btrees that desire a lock.
*/
SQLITE_PRIVATE void sqlite3BtreeEnter(Btree *p){
Btree *pLater;
/* Some basic sanity checking on the Btree. The list of Btrees
** connected by pNext and pPrev should be in sorted order by
** Btree.pBt value. All elements of the list should belong to
** the same connection. Only shared Btrees are on the list. */
assert( p->pNext==0 || p->pNext->pBt>p->pBt );
assert( p->pPrev==0 || p->pPrev->pBt<p->pBt );
assert( p->pNext==0 || p->pNext->db==p->db );
assert( p->pPrev==0 || p->pPrev->db==p->db );
assert( p->sharable || (p->pNext==0 && p->pPrev==0) );
/* Check for locking consistency */
assert( !p->locked || p->wantToLock>0 );
assert( p->sharable || p->wantToLock==0 );
/* We should already hold a lock on the database connection */
assert( sqlite3_mutex_held(p->db->mutex) );
if( !p->sharable ) return;
p->wantToLock++;
if( p->locked ) return;
#ifndef SQLITE_MUTEX_NOOP
/* In most cases, we should be able to acquire the lock we
** want without having to go throught the ascending lock
** procedure that follows. Just be sure not to block.
*/
if( sqlite3_mutex_try(p->pBt->mutex)==SQLITE_OK ){
p->locked = 1;
return;
}
/* To avoid deadlock, first release all locks with a larger
** BtShared address. Then acquire our lock. Then reacquire
** the other BtShared locks that we used to hold in ascending
** order.
*/
for(pLater=p->pNext; pLater; pLater=pLater->pNext){
assert( pLater->sharable );
assert( pLater->pNext==0 || pLater->pNext->pBt>pLater->pBt );
assert( !pLater->locked || pLater->wantToLock>0 );
if( pLater->locked ){
sqlite3_mutex_leave(pLater->pBt->mutex);
pLater->locked = 0;
}
}
sqlite3_mutex_enter(p->pBt->mutex);
p->locked = 1;
for(pLater=p->pNext; pLater; pLater=pLater->pNext){
if( pLater->wantToLock ){
sqlite3_mutex_enter(pLater->pBt->mutex);
pLater->locked = 1;
}
}
#endif /* SQLITE_MUTEX_NOOP */
}
/*
** Exit the recursive mutex on a Btree.
*/
SQLITE_PRIVATE void sqlite3BtreeLeave(Btree *p){
if( p->sharable ){
assert( p->wantToLock>0 );
p->wantToLock--;
if( p->wantToLock==0 ){
assert( p->locked );
sqlite3_mutex_leave(p->pBt->mutex);
p->locked = 0;
}
}
}
#ifndef NDEBUG
/*
** Return true if the BtShared mutex is held on the btree.
**
** This routine makes no determination one why or another if the
** database connection mutex is held.
**
** This routine is used only from within assert() statements.
*/
SQLITE_PRIVATE int sqlite3BtreeHoldsMutex(Btree *p){
return (p->sharable==0 ||
(p->locked && p->wantToLock && sqlite3_mutex_held(p->pBt->mutex)));
}
#endif
#ifndef SQLITE_OMIT_INCRBLOB
/*
** Enter and leave a mutex on a Btree given a cursor owned by that
** Btree. These entry points are used by incremental I/O and can be
** omitted if that module is not used.
*/
SQLITE_PRIVATE void sqlite3BtreeEnterCursor(BtCursor *pCur){
sqlite3BtreeEnter(pCur->pBtree);
}
SQLITE_PRIVATE void sqlite3BtreeLeaveCursor(BtCursor *pCur){
sqlite3BtreeLeave(pCur->pBtree);
}
#endif /* SQLITE_OMIT_INCRBLOB */
/*
** Enter the mutex on every Btree associated with a database
** connection. This is needed (for example) prior to parsing
** a statement since we will be comparing table and column names
** against all schemas and we do not want those schemas being
** reset out from under us.
**
** There is a corresponding leave-all procedures.
**
** Enter the mutexes in accending order by BtShared pointer address
** to avoid the possibility of deadlock when two threads with
** two or more btrees in common both try to lock all their btrees
** at the same instant.
*/
SQLITE_PRIVATE void sqlite3BtreeEnterAll(sqlite3 *db){
int i;
Btree *p, *pLater;
assert( sqlite3_mutex_held(db->mutex) );
for(i=0; i<db->nDb; i++){
p = db->aDb[i].pBt;
if( p && p->sharable ){
p->wantToLock++;
if( !p->locked ){
assert( p->wantToLock==1 );
while( p->pPrev ) p = p->pPrev;
while( p->locked && p->pNext ) p = p->pNext;
for(pLater = p->pNext; pLater; pLater=pLater->pNext){
if( pLater->locked ){
sqlite3_mutex_leave(pLater->pBt->mutex);
pLater->locked = 0;
}
}
while( p ){
sqlite3_mutex_enter(p->pBt->mutex);
p->locked++;
p = p->pNext;
}
}
}
}
}
SQLITE_PRIVATE void sqlite3BtreeLeaveAll(sqlite3 *db){
int i;
Btree *p;
assert( sqlite3_mutex_held(db->mutex) );
for(i=0; i<db->nDb; i++){
p = db->aDb[i].pBt;
if( p && p->sharable ){
assert( p->wantToLock>0 );
p->wantToLock--;
if( p->wantToLock==0 ){
assert( p->locked );
sqlite3_mutex_leave(p->pBt->mutex);
p->locked = 0;
}
}
}
}
#ifndef NDEBUG
/*
** Return true if the current thread holds the database connection
** mutex and all required BtShared mutexes.
**
** This routine is used inside assert() statements only.
*/
SQLITE_PRIVATE int sqlite3BtreeHoldsAllMutexes(sqlite3 *db){
int i;
if( !sqlite3_mutex_held(db->mutex) ){
return 0;
}
for(i=0; i<db->nDb; i++){
Btree *p;
p = db->aDb[i].pBt;
if( p && p->sharable &&
(p->wantToLock==0 || !sqlite3_mutex_held(p->pBt->mutex)) ){
return 0;
}
}
return 1;
}
#endif /* NDEBUG */
/*
** Add a new Btree pointer to a BtreeMutexArray.
** if the pointer can possibly be shared with
** another database connection.
**
** The pointers are kept in sorted order by pBtree->pBt. That
** way when we go to enter all the mutexes, we can enter them
** in order without every having to backup and retry and without
** worrying about deadlock.
**
** The number of shared btrees will always be small (usually 0 or 1)
** so an insertion sort is an adequate algorithm here.
*/
SQLITE_PRIVATE void sqlite3BtreeMutexArrayInsert(BtreeMutexArray *pArray, Btree *pBtree){
int i, j;
BtShared *pBt;
if( pBtree==0 || pBtree->sharable==0 ) return;
#ifndef NDEBUG
{
for(i=0; i<pArray->nMutex; i++){
assert( pArray->aBtree[i]!=pBtree );
}
}
#endif
assert( pArray->nMutex>=0 );
assert( pArray->nMutex<sizeof(pArray->aBtree)/sizeof(pArray->aBtree[0])-1 );
pBt = pBtree->pBt;
for(i=0; i<pArray->nMutex; i++){
assert( pArray->aBtree[i]!=pBtree );
if( pArray->aBtree[i]->pBt>pBt ){
for(j=pArray->nMutex; j>i; j--){
pArray->aBtree[j] = pArray->aBtree[j-1];
}
pArray->aBtree[i] = pBtree;
pArray->nMutex++;
return;
}
}
pArray->aBtree[pArray->nMutex++] = pBtree;
}
/*
** Enter the mutex of every btree in the array. This routine is
** called at the beginning of sqlite3VdbeExec(). The mutexes are
** exited at the end of the same function.
*/
SQLITE_PRIVATE void sqlite3BtreeMutexArrayEnter(BtreeMutexArray *pArray){
int i;
for(i=0; i<pArray->nMutex; i++){
Btree *p = pArray->aBtree[i];
/* Some basic sanity checking */
assert( i==0 || pArray->aBtree[i-1]->pBt<p->pBt );
assert( !p->locked || p->wantToLock>0 );
/* We should already hold a lock on the database connection */
assert( sqlite3_mutex_held(p->db->mutex) );
p->wantToLock++;
if( !p->locked && p->sharable ){
sqlite3_mutex_enter(p->pBt->mutex);
p->locked = 1;
}
}
}
/*
** Leave the mutex of every btree in the group.
*/
SQLITE_PRIVATE void sqlite3BtreeMutexArrayLeave(BtreeMutexArray *pArray){
int i;
for(i=0; i<pArray->nMutex; i++){
Btree *p = pArray->aBtree[i];
/* Some basic sanity checking */
assert( i==0 || pArray->aBtree[i-1]->pBt<p->pBt );
assert( p->locked || !p->sharable );
assert( p->wantToLock>0 );
/* We should already hold a lock on the database connection */
assert( sqlite3_mutex_held(p->db->mutex) );
p->wantToLock--;
if( p->wantToLock==0 && p->locked ){
sqlite3_mutex_leave(p->pBt->mutex);
p->locked = 0;
}
}
}
#endif /* SQLITE_THREADSAFE && !SQLITE_OMIT_SHARED_CACHE */
/************** End of btmutex.c *********************************************/
/************** Begin file btree.c *******************************************/
/*
** 2004 April 6
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** $Id: btree.c,v 1.495 2008/08/02 17:36:46 danielk1977 Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
** Including a description of file format and an overview of operation.
*/
/*
** The header string that appears at the beginning of every
** SQLite database.
*/
static const char zMagicHeader[] = SQLITE_FILE_HEADER;
/*
** Set this global variable to 1 to enable tracing using the TRACE
** macro.
*/
#if 0
int sqlite3BtreeTrace=0; /* True to enable tracing */
# define TRACE(X) if(sqlite3BtreeTrace){printf X;fflush(stdout);}
#else
# define TRACE(X)
#endif
#ifndef SQLITE_OMIT_SHARED_CACHE
/*
** A flag to indicate whether or not shared cache is enabled. Also,
** a list of BtShared objects that are eligible for participation
** in shared cache. The variables have file scope during normal builds,
** but the test harness needs to access these variables so we make them
** global for test builds.
*/
#ifdef SQLITE_TEST
SQLITE_PRIVATE BtShared *sqlite3SharedCacheList = 0;
SQLITE_PRIVATE int sqlite3SharedCacheEnabled = 0;
#else
static BtShared *sqlite3SharedCacheList = 0;
static int sqlite3SharedCacheEnabled = 0;
sqlite-amalgamation.c view on Meta::CPAN
sqlite3_mutex_free(pBt->mutex);
}
removed = 1;
}
sqlite3_mutex_leave(pMaster);
return removed;
#else
return 1;
#endif
}
/*
** Make sure pBt->pTmpSpace points to an allocation of
** MX_CELL_SIZE(pBt) bytes.
*/
static void allocateTempSpace(BtShared *pBt){
if( !pBt->pTmpSpace ){
pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize );
}
}
/*
** Free the pBt->pTmpSpace allocation
*/
static void freeTempSpace(BtShared *pBt){
sqlite3PageFree( pBt->pTmpSpace);
pBt->pTmpSpace = 0;
}
/*
** Close an open database and invalidate all cursors.
*/
SQLITE_PRIVATE int sqlite3BtreeClose(Btree *p){
BtShared *pBt = p->pBt;
BtCursor *pCur;
/* Close all cursors opened via this handle. */
assert( sqlite3_mutex_held(p->db->mutex) );
sqlite3BtreeEnter(p);
pBt->db = p->db;
pCur = pBt->pCursor;
while( pCur ){
BtCursor *pTmp = pCur;
pCur = pCur->pNext;
if( pTmp->pBtree==p ){
sqlite3BtreeCloseCursor(pTmp);
}
}
/* Rollback any active transaction and free the handle structure.
** The call to sqlite3BtreeRollback() drops any table-locks held by
** this handle.
*/
sqlite3BtreeRollback(p);
sqlite3BtreeLeave(p);
/* If there are still other outstanding references to the shared-btree
** structure, return now. The remainder of this procedure cleans
** up the shared-btree.
*/
assert( p->wantToLock==0 && p->locked==0 );
if( !p->sharable || removeFromSharingList(pBt) ){
/* The pBt is no longer on the sharing list, so we can access
** it without having to hold the mutex.
**
** Clean out and delete the BtShared object.
*/
assert( !pBt->pCursor );
sqlite3PagerClose(pBt->pPager);
if( pBt->xFreeSchema && pBt->pSchema ){
pBt->xFreeSchema(pBt->pSchema);
}
sqlite3_free(pBt->pSchema);
freeTempSpace(pBt);
sqlite3_free(pBt);
}
#ifndef SQLITE_OMIT_SHARED_CACHE
assert( p->wantToLock==0 );
assert( p->locked==0 );
if( p->pPrev ) p->pPrev->pNext = p->pNext;
if( p->pNext ) p->pNext->pPrev = p->pPrev;
#endif
sqlite3_free(p);
return SQLITE_OK;
}
/*
** Change the limit on the number of pages allowed in the cache.
**
** The maximum number of cache pages is set to the absolute
** value of mxPage. If mxPage is negative, the pager will
** operate asynchronously - it will not stop to do fsync()s
** to insure data is written to the disk surface before
** continuing. Transactions still work if synchronous is off,
** and the database cannot be corrupted if this program
** crashes. But if the operating system crashes or there is
** an abrupt power failure when synchronous is off, the database
** could be left in an inconsistent and unrecoverable state.
** Synchronous is on by default so database corruption is not
** normally a worry.
*/
SQLITE_PRIVATE int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){
BtShared *pBt = p->pBt;
assert( sqlite3_mutex_held(p->db->mutex) );
sqlite3BtreeEnter(p);
sqlite3PagerSetCachesize(pBt->pPager, mxPage);
sqlite3BtreeLeave(p);
return SQLITE_OK;
}
/*
** Change the way data is synced to disk in order to increase or decrease
** how well the database resists damage due to OS crashes and power
** failures. Level 1 is the same as asynchronous (no syncs() occur and
** there is a high probability of damage) Level 2 is the default. There
** is a very low but non-zero probability of damage. Level 3 reduces the
** probability of damage to near zero but with a write performance reduction.
*/
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
SQLITE_PRIVATE int sqlite3BtreeSetSafetyLevel(Btree *p, int level, int fullSync){
BtShared *pBt = p->pBt;
assert( sqlite3_mutex_held(p->db->mutex) );
sqlite3BtreeEnter(p);
sqlite3PagerSetSafetyLevel(pBt->pPager, level, fullSync);
sqlite3BtreeLeave(p);
return SQLITE_OK;
}
#endif
/*
** Return TRUE if the given btree is set to safety level 1. In other
** words, return TRUE if no sync() occurs on the disk files.
*/
SQLITE_PRIVATE int sqlite3BtreeSyncDisabled(Btree *p){
BtShared *pBt = p->pBt;
int rc;
assert( sqlite3_mutex_held(p->db->mutex) );
sqlite3BtreeEnter(p);
sqlite-amalgamation.c view on Meta::CPAN
int n;
sqlite3BtreeEnter(p);
n = sqlite3PagerMaxPageCount(p->pBt->pPager, mxPage);
sqlite3BtreeLeave(p);
return n;
}
#endif /* !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) */
/*
** Change the 'auto-vacuum' property of the database. If the 'autoVacuum'
** parameter is non-zero, then auto-vacuum mode is enabled. If zero, it
** is disabled. The default value for the auto-vacuum property is
** determined by the SQLITE_DEFAULT_AUTOVACUUM macro.
*/
SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *p, int autoVacuum){
#ifdef SQLITE_OMIT_AUTOVACUUM
return SQLITE_READONLY;
#else
BtShared *pBt = p->pBt;
int rc = SQLITE_OK;
int av = (autoVacuum?1:0);
sqlite3BtreeEnter(p);
if( pBt->pageSizeFixed && av!=pBt->autoVacuum ){
rc = SQLITE_READONLY;
}else{
pBt->autoVacuum = av;
}
sqlite3BtreeLeave(p);
return rc;
#endif
}
/*
** Return the value of the 'auto-vacuum' property. If auto-vacuum is
** enabled 1 is returned. Otherwise 0.
*/
SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *p){
#ifdef SQLITE_OMIT_AUTOVACUUM
return BTREE_AUTOVACUUM_NONE;
#else
int rc;
sqlite3BtreeEnter(p);
rc = (
(!p->pBt->autoVacuum)?BTREE_AUTOVACUUM_NONE:
(!p->pBt->incrVacuum)?BTREE_AUTOVACUUM_FULL:
BTREE_AUTOVACUUM_INCR
);
sqlite3BtreeLeave(p);
return rc;
#endif
}
/*
** Get a reference to pPage1 of the database file. This will
** also acquire a readlock on that file.
**
** SQLITE_OK is returned on success. If the file is not a
** well-formed database file, then SQLITE_CORRUPT is returned.
** SQLITE_BUSY is returned if the database is locked. SQLITE_NOMEM
** is returned if we run out of memory.
*/
static int lockBtree(BtShared *pBt){
int rc;
MemPage *pPage1;
int nPage;
assert( sqlite3_mutex_held(pBt->mutex) );
if( pBt->pPage1 ) return SQLITE_OK;
rc = sqlite3BtreeGetPage(pBt, 1, &pPage1, 0);
if( rc!=SQLITE_OK ) return rc;
/* Do some checking to help insure the file we opened really is
** a valid database file.
*/
rc = sqlite3PagerPagecount(pBt->pPager, &nPage);
if( rc!=SQLITE_OK ){
goto page1_init_failed;
}else if( nPage>0 ){
int pageSize;
int usableSize;
u8 *page1 = pPage1->aData;
rc = SQLITE_NOTADB;
if( memcmp(page1, zMagicHeader, 16)!=0 ){
goto page1_init_failed;
}
if( page1[18]>1 ){
pBt->readOnly = 1;
}
if( page1[19]>1 ){
goto page1_init_failed;
}
/* The maximum embedded fraction must be exactly 25%. And the minimum
** embedded fraction must be 12.5% for both leaf-data and non-leaf-data.
** The original design allowed these amounts to vary, but as of
** version 3.6.0, we require them to be fixed.
*/
if( memcmp(&page1[21], "\100\040\040",3)!=0 ){
goto page1_init_failed;
}
pageSize = get2byte(&page1[16]);
if( ((pageSize-1)&pageSize)!=0 || pageSize<512 ||
(SQLITE_MAX_PAGE_SIZE<32768 && pageSize>SQLITE_MAX_PAGE_SIZE)
){
goto page1_init_failed;
}
assert( (pageSize & 7)==0 );
usableSize = pageSize - page1[20];
if( pageSize!=pBt->pageSize ){
/* After reading the first page of the database assuming a page size
** of BtShared.pageSize, we have discovered that the page-size is
** actually pageSize. Unlock the database, leave pBt->pPage1 at
** zero and return SQLITE_OK. The caller will call this function
** again with the correct page-size.
*/
releasePage(pPage1);
pBt->usableSize = usableSize;
pBt->pageSize = pageSize;
freeTempSpace(pBt);
sqlite-amalgamation.c view on Meta::CPAN
*/
static int newDatabase(BtShared *pBt){
MemPage *pP1;
unsigned char *data;
int rc;
int nPage;
assert( sqlite3_mutex_held(pBt->mutex) );
rc = sqlite3PagerPagecount(pBt->pPager, &nPage);
if( rc!=SQLITE_OK || nPage>0 ){
return rc;
}
pP1 = pBt->pPage1;
assert( pP1!=0 );
data = pP1->aData;
rc = sqlite3PagerWrite(pP1->pDbPage);
if( rc ) return rc;
memcpy(data, zMagicHeader, sizeof(zMagicHeader));
assert( sizeof(zMagicHeader)==16 );
put2byte(&data[16], pBt->pageSize);
data[18] = 1;
data[19] = 1;
data[20] = pBt->pageSize - pBt->usableSize;
data[21] = 64;
data[22] = 32;
data[23] = 32;
memset(&data[24], 0, 100-24);
zeroPage(pP1, PTF_INTKEY|PTF_LEAF|PTF_LEAFDATA );
pBt->pageSizeFixed = 1;
#ifndef SQLITE_OMIT_AUTOVACUUM
assert( pBt->autoVacuum==1 || pBt->autoVacuum==0 );
assert( pBt->incrVacuum==1 || pBt->incrVacuum==0 );
put4byte(&data[36 + 4*4], pBt->autoVacuum);
put4byte(&data[36 + 7*4], pBt->incrVacuum);
#endif
return SQLITE_OK;
}
/*
** Attempt to start a new transaction. A write-transaction
** is started if the second argument is nonzero, otherwise a read-
** transaction. If the second argument is 2 or more and exclusive
** transaction is started, meaning that no other process is allowed
** to access the database. A preexisting transaction may not be
** upgraded to exclusive by calling this routine a second time - the
** exclusivity flag only works for a new transaction.
**
** A write-transaction must be started before attempting any
** changes to the database. None of the following routines
** will work unless a transaction is started first:
**
** sqlite3BtreeCreateTable()
** sqlite3BtreeCreateIndex()
** sqlite3BtreeClearTable()
** sqlite3BtreeDropTable()
** sqlite3BtreeInsert()
** sqlite3BtreeDelete()
** sqlite3BtreeUpdateMeta()
**
** If an initial attempt to acquire the lock fails because of lock contention
** and the database was previously unlocked, then invoke the busy handler
** if there is one. But if there was previously a read-lock, do not
** invoke the busy handler - just return SQLITE_BUSY. SQLITE_BUSY is
** returned when there is already a read-lock in order to avoid a deadlock.
**
** Suppose there are two processes A and B. A has a read lock and B has
** a reserved lock. B tries to promote to exclusive but is blocked because
** of A's read lock. A tries to promote to reserved but is blocked by B.
** One or the other of the two processes must give way or there can be
** no progress. By returning SQLITE_BUSY and not invoking the busy callback
** when A already has a read lock, we encourage A to give up and let B
** proceed.
*/
SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
BtShared *pBt = p->pBt;
int rc = SQLITE_OK;
sqlite3BtreeEnter(p);
pBt->db = p->db;
btreeIntegrity(p);
/* If the btree is already in a write-transaction, or it
** is already in a read-transaction and a read-transaction
** is requested, this is a no-op.
*/
if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){
goto trans_begun;
}
/* Write transactions are not possible on a read-only database */
if( pBt->readOnly && wrflag ){
rc = SQLITE_READONLY;
goto trans_begun;
}
/* If another database handle has already opened a write transaction
** on this shared-btree structure and a second write transaction is
** requested, return SQLITE_BUSY.
*/
if( pBt->inTransaction==TRANS_WRITE && wrflag ){
rc = SQLITE_BUSY;
goto trans_begun;
}
#ifndef SQLITE_OMIT_SHARED_CACHE
if( wrflag>1 ){
BtLock *pIter;
for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
if( pIter->pBtree!=p ){
rc = SQLITE_BUSY;
goto trans_begun;
}
}
}
#endif
do {
if( pBt->pPage1==0 ){
do{
rc = lockBtree(pBt);
}while( pBt->pPage1==0 && rc==SQLITE_OK );
}
if( rc==SQLITE_OK && wrflag ){
if( pBt->readOnly ){
rc = SQLITE_READONLY;
}else{
rc = sqlite3PagerBegin(pBt->pPage1->pDbPage, wrflag>1);
sqlite-amalgamation.c view on Meta::CPAN
/*
** To compile without implementing sqlite3Hwtime() for your platform,
** you can remove the above #error and use the following
** stub function. You will lose timing support for many
** of the debugging and testing utilities, but it should at
** least compile and run.
*/
SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
#endif
#endif /* !defined(_HWTIME_H_) */
/************** End of hwtime.h **********************************************/
/************** Continuing where we left off in vdbe.c ***********************/
#endif
/*
** The CHECK_FOR_INTERRUPT macro defined here looks to see if the
** sqlite3_interrupt() routine has been called. If it has been, then
** processing of the VDBE program is interrupted.
**
** This macro added to every instruction that does a jump in order to
** implement a loop. This test used to be on every single instruction,
** but that meant we more testing that we needed. By only testing the
** flag on jump instructions, we get a (small) speed improvement.
*/
#define CHECK_FOR_INTERRUPT \
if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
#ifdef SQLITE_DEBUG
static int fileExists(sqlite3 *db, const char *zFile){
int res = 0;
int rc = SQLITE_OK;
#ifdef SQLITE_TEST
/* If we are currently testing IO errors, then do not call OsAccess() to
** test for the presence of zFile. This is because any IO error that
** occurs here will not be reported, causing the test to fail.
*/
extern int sqlite3_io_error_pending;
if( sqlite3_io_error_pending<=0 )
#endif
rc = sqlite3OsAccess(db->pVfs, zFile, SQLITE_ACCESS_EXISTS, &res);
return (res && rc==SQLITE_OK);
}
#endif
/*
** Execute as much of a VDBE program as we can then return.
**
** sqlite3VdbeMakeReady() must be called before this routine in order to
** close the program with a final OP_Halt and to set up the callbacks
** and the error message pointer.
**
** Whenever a row or result data is available, this routine will either
** invoke the result callback (if there is one) or return with
** SQLITE_ROW.
**
** If an attempt is made to open a locked database, then this routine
** will either invoke the busy callback (if there is one) or it will
** return SQLITE_BUSY.
**
** If an error occurs, an error message is written to memory obtained
** from sqlite3_malloc() and p->zErrMsg is made to point to that memory.
** The error code is stored in p->rc and this routine returns SQLITE_ERROR.
**
** If the callback ever returns non-zero, then the program exits
** immediately. There will be no error message but the p->rc field is
** set to SQLITE_ABORT and this routine will return SQLITE_ERROR.
**
** A memory allocation error causes p->rc to be set to SQLITE_NOMEM and this
** routine to return SQLITE_ERROR.
**
** Other fatal errors return SQLITE_ERROR.
**
** After this routine has finished, sqlite3VdbeFinalize() should be
** used to clean up the mess that was left behind.
*/
SQLITE_PRIVATE int sqlite3VdbeExec(
Vdbe *p /* The VDBE */
){
int pc; /* The program counter */
Op *pOp; /* Current operation */
int rc = SQLITE_OK; /* Value to return */
sqlite3 *db = p->db; /* The database */
u8 encoding = ENC(db); /* The database encoding */
Mem *pIn1, *pIn2, *pIn3; /* Input operands */
Mem *pOut; /* Output operand */
u8 opProperty;
int iCompare = 0; /* Result of last OP_Compare operation */
int *aPermute = 0; /* Permuation of columns for OP_Compare */
#ifdef VDBE_PROFILE
u64 start; /* CPU clock count at start of opcode */
int origPc; /* Program counter at start of opcode */
#endif
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
int nProgressOps = 0; /* Opcodes executed since progress callback. */
#endif
assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */
assert( db->magic==SQLITE_MAGIC_BUSY );
sqlite3BtreeMutexArrayEnter(&p->aMutex);
if( p->rc==SQLITE_NOMEM ){
/* This happens if a malloc() inside a call to sqlite3_column_text() or
** sqlite3_column_text16() failed. */
goto no_mem;
}
assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY );
p->rc = SQLITE_OK;
assert( p->explain==0 );
p->pResultSet = 0;
db->busyHandler.nBusy = 0;
CHECK_FOR_INTERRUPT;
sqlite3VdbeIOTraceSql(p);
#ifdef SQLITE_DEBUG
sqlite3BeginBenignMalloc();
if( p->pc==0
&& ((p->db->flags & SQLITE_VdbeListing) || fileExists(db, "vdbe_explain"))
){
sqlite-amalgamation.c view on Meta::CPAN
** The cookie changes its value whenever the database schema changes.
** This operation is used to detect when that the cookie has changed
** and that the current process needs to reread the schema.
**
** Either a transaction needs to have been started or an OP_Open needs
** to be executed (to establish a read lock) before this opcode is
** invoked.
*/
case OP_VerifyCookie: {
int iMeta;
Btree *pBt;
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( (p->btreeMask & (1<<pOp->p1))!=0 );
pBt = db->aDb[pOp->p1].pBt;
if( pBt ){
rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&iMeta);
}else{
rc = SQLITE_OK;
iMeta = 0;
}
if( rc==SQLITE_OK && iMeta!=pOp->p2 ){
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = sqlite3DbStrDup(db, "database schema has changed");
/* If the schema-cookie from the database file matches the cookie
** stored with the in-memory representation of the schema, do
** not reload the schema from the database file.
**
** If virtual-tables are in use, this is not just an optimization.
** Often, v-tables store their data in other SQLite tables, which
** are queried from within xNext() and other v-table methods using
** prepared queries. If such a query is out-of-date, we do not want to
** discard the database schema, as the user code implementing the
** v-table would have to be ready for the sqlite3_vtab structure itself
** to be invalidated whenever sqlite3_step() is called from within
** a v-table method.
*/
if( db->aDb[pOp->p1].pSchema->schema_cookie!=iMeta ){
sqlite3ResetInternalSchema(db, pOp->p1);
}
sqlite3ExpirePreparedStatements(db);
rc = SQLITE_SCHEMA;
}
break;
}
/* Opcode: OpenRead P1 P2 P3 P4 P5
**
** Open a read-only cursor for the database table whose root page is
** P2 in a database file. The database file is determined by P3.
** P3==0 means the main database, P3==1 means the database used for
** temporary tables, and P3>1 means used the corresponding attached
** database. Give the new cursor an identifier of P1. The P1
** values need not be contiguous but all P1 values should be small integers.
** It is an error for P1 to be negative.
**
** If P5!=0 then use the content of register P2 as the root page, not
** the value of P2 itself.
**
** There will be a read lock on the database whenever there is an
** open cursor. If the database was unlocked prior to this instruction
** then a read lock is acquired as part of this instruction. A read
** lock allows other processes to read the database but prohibits
** any other process from modifying the database. The read lock is
** released when all cursors are closed. If this instruction attempts
** to get a read lock but fails, the script terminates with an
** SQLITE_BUSY error code.
**
** The P4 value is a pointer to a KeyInfo structure that defines the
** content and collating sequence of indices. P4 is NULL for cursors
** that are not pointing to indices.
**
** See also OpenWrite.
*/
/* Opcode: OpenWrite P1 P2 P3 P4 P5
**
** Open a read/write cursor named P1 on the table or index whose root
** page is P2. Or if P5!=0 use the content of register P2 to find the
** root page.
**
** The P4 value is a pointer to a KeyInfo structure that defines the
** content and collating sequence of indices. P4 is NULL for cursors
** that are not pointing to indices.
**
** This instruction works just like OpenRead except that it opens the cursor
** in read/write mode. For a given table, there can be one or more read-only
** cursors or a single read/write cursor but not both.
**
** See also OpenRead.
*/
case OP_OpenRead:
case OP_OpenWrite: {
int i = pOp->p1;
int p2 = pOp->p2;
int iDb = pOp->p3;
int wrFlag;
Btree *pX;
Cursor *pCur;
Db *pDb;
assert( iDb>=0 && iDb<db->nDb );
assert( (p->btreeMask & (1<<iDb))!=0 );
pDb = &db->aDb[iDb];
pX = pDb->pBt;
assert( pX!=0 );
if( pOp->opcode==OP_OpenWrite ){
wrFlag = 1;
if( pDb->pSchema->file_format < p->minWriteFileFormat ){
p->minWriteFileFormat = pDb->pSchema->file_format;
}
}else{
wrFlag = 0;
}
if( pOp->p5 ){
assert( p2>0 );
assert( p2<=p->nMem );
pIn2 = &p->aMem[p2];
sqlite3VdbeMemIntegerify(pIn2);
p2 = pIn2->u.i;
assert( p2>=2 );
}
sqlite-amalgamation.c view on Meta::CPAN
case OP_Vacuum: {
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = sqlite3RunVacuum(&p->zErrMsg, db);
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
break;
}
#endif
#if !defined(SQLITE_OMIT_AUTOVACUUM)
/* Opcode: IncrVacuum P1 P2 * * *
**
** Perform a single step of the incremental vacuum procedure on
** the P1 database. If the vacuum has finished, jump to instruction
** P2. Otherwise, fall through to the next instruction.
*/
case OP_IncrVacuum: { /* jump */
Btree *pBt;
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( (p->btreeMask & (1<<pOp->p1))!=0 );
pBt = db->aDb[pOp->p1].pBt;
rc = sqlite3BtreeIncrVacuum(pBt);
if( rc==SQLITE_DONE ){
pc = pOp->p2 - 1;
rc = SQLITE_OK;
}
break;
}
#endif
/* Opcode: Expire P1 * * * *
**
** Cause precompiled statements to become expired. An expired statement
** fails with an error code of SQLITE_SCHEMA if it is ever executed
** (via sqlite3_step()).
**
** If P1 is 0, then all SQL statements become expired. If P1 is non-zero,
** then only the currently executing statement is affected.
*/
case OP_Expire: {
if( !pOp->p1 ){
sqlite3ExpirePreparedStatements(db);
}else{
p->expired = 1;
}
break;
}
#ifndef SQLITE_OMIT_SHARED_CACHE
/* Opcode: TableLock P1 P2 P3 P4 *
**
** Obtain a lock on a particular table. This instruction is only used when
** the shared-cache feature is enabled.
**
** If P1 is the index of the database in sqlite3.aDb[] of the database
** on which the lock is acquired. A readlock is obtained if P3==0 or
** a write lock if P3==1.
**
** P2 contains the root-page of the table to lock.
**
** P4 contains a pointer to the name of the table being locked. This is only
** used to generate an error message if the lock cannot be obtained.
*/
case OP_TableLock: {
int p1 = pOp->p1;
u8 isWriteLock = pOp->p3;
assert( p1>=0 && p1<db->nDb );
assert( (p->btreeMask & (1<<p1))!=0 );
assert( isWriteLock==0 || isWriteLock==1 );
rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock);
if( rc==SQLITE_LOCKED ){
const char *z = pOp->p4.z;
sqlite3SetString(&p->zErrMsg, db, "database table is locked: %s", z);
}
break;
}
#endif /* SQLITE_OMIT_SHARED_CACHE */
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VBegin * * * P4 *
**
** P4 may be a pointer to an sqlite3_vtab structure. If so, call the
** xBegin method for that table.
**
** Also, whether or not P4 is set, check that this is not being called from
** within a callback to a virtual table xSync() method. If it is, set the
** error code to SQLITE_LOCKED.
*/
case OP_VBegin: {
sqlite3_vtab *pVtab = pOp->p4.pVtab;
rc = sqlite3VtabBegin(db, pVtab);
if( pVtab ){
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = pVtab->zErrMsg;
pVtab->zErrMsg = 0;
}
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VCreate P1 * * P4 *
**
** P4 is the name of a virtual table in database P1. Call the xCreate method
** for that table.
*/
case OP_VCreate: {
rc = sqlite3VtabCallCreate(db, pOp->p1, pOp->p4.z, &p->zErrMsg);
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VDestroy P1 * * P4 *
**
** P4 is the name of a virtual table in database P1. Call the xDestroy method
** of that table.
*/
case OP_VDestroy: {
p->inVtabMethod = 2;
rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p4.z);
p->inVtabMethod = 0;
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VOpen P1 * * P4 *
**
** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
** P1 is a cursor number. This opcode opens a cursor to the virtual
** table and stores that cursor in P1.
*/
sqlite-amalgamation.c view on Meta::CPAN
}else{
sqlite3_snprintf(sizeof(zErr),zErr, "unable to open database: %s", zFile);
}
goto attach_error;
}
return;
attach_error:
/* Return an error if we get here */
if( zErrDyn ){
sqlite3_result_error(context, zErrDyn, -1);
sqlite3DbFree(db, zErrDyn);
}else{
zErr[sizeof(zErr)-1] = 0;
sqlite3_result_error(context, zErr, -1);
}
if( rc ) sqlite3_result_error_code(context, rc);
}
/*
** An SQL user-function registered to do the work of an DETACH statement. The
** three arguments to the function come directly from a detach statement:
**
** DETACH DATABASE x
**
** SELECT sqlite_detach(x)
*/
static void detachFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
const char *zName = (const char *)sqlite3_value_text(argv[0]);
sqlite3 *db = sqlite3_context_db_handle(context);
int i;
Db *pDb = 0;
char zErr[128];
if( zName==0 ) zName = "";
for(i=0; i<db->nDb; i++){
pDb = &db->aDb[i];
if( pDb->pBt==0 ) continue;
if( sqlite3StrICmp(pDb->zName, zName)==0 ) break;
}
if( i>=db->nDb ){
sqlite3_snprintf(sizeof(zErr),zErr, "no such database: %s", zName);
goto detach_error;
}
if( i<2 ){
sqlite3_snprintf(sizeof(zErr),zErr, "cannot detach database %s", zName);
goto detach_error;
}
if( !db->autoCommit ){
sqlite3_snprintf(sizeof(zErr), zErr,
"cannot DETACH database within transaction");
goto detach_error;
}
if( sqlite3BtreeIsInReadTrans(pDb->pBt) ){
sqlite3_snprintf(sizeof(zErr),zErr, "database %s is locked", zName);
goto detach_error;
}
sqlite3BtreeClose(pDb->pBt);
pDb->pBt = 0;
pDb->pSchema = 0;
sqlite3ResetInternalSchema(db, 0);
return;
detach_error:
sqlite3_result_error(context, zErr, -1);
}
/*
** This procedure generates VDBE code for a single invocation of either the
** sqlite_detach() or sqlite_attach() SQL user functions.
*/
static void codeAttach(
Parse *pParse, /* The parser context */
int type, /* Either SQLITE_ATTACH or SQLITE_DETACH */
const char *zFunc, /* Either "sqlite_attach" or "sqlite_detach */
int nFunc, /* Number of args to pass to zFunc */
Expr *pAuthArg, /* Expression to pass to authorization callback */
Expr *pFilename, /* Name of database file */
Expr *pDbname, /* Name of the database to use internally */
Expr *pKey /* Database key for encryption extension */
){
int rc;
NameContext sName;
Vdbe *v;
FuncDef *pFunc;
sqlite3* db = pParse->db;
int regArgs;
#ifndef SQLITE_OMIT_AUTHORIZATION
assert( db->mallocFailed || pAuthArg );
if( pAuthArg ){
char *zAuthArg = sqlite3NameFromToken(db, &pAuthArg->span);
if( !zAuthArg ){
goto attach_end;
}
rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0);
sqlite3DbFree(db, zAuthArg);
if(rc!=SQLITE_OK ){
goto attach_end;
}
}
#endif /* SQLITE_OMIT_AUTHORIZATION */
memset(&sName, 0, sizeof(NameContext));
sName.pParse = pParse;
if(
SQLITE_OK!=(rc = resolveAttachExpr(&sName, pFilename)) ||
SQLITE_OK!=(rc = resolveAttachExpr(&sName, pDbname)) ||
SQLITE_OK!=(rc = resolveAttachExpr(&sName, pKey))
){
pParse->nErr++;
goto attach_end;
}
sqlite-amalgamation.c view on Meta::CPAN
}
}
/*
** Pop an authorization context that was previously pushed
** by sqlite3AuthContextPush
*/
SQLITE_PRIVATE void sqlite3AuthContextPop(AuthContext *pContext){
if( pContext->pParse ){
pContext->pParse->zAuthContext = pContext->zAuthContext;
pContext->pParse = 0;
}
}
#endif /* SQLITE_OMIT_AUTHORIZATION */
/************** End of auth.c ************************************************/
/************** Begin file build.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 C code routines that are called by the SQLite parser
** when syntax rules are reduced. The routines in this file handle the
** following kinds of SQL syntax:
**
** CREATE TABLE
** DROP TABLE
** CREATE INDEX
** DROP INDEX
** creating ID lists
** BEGIN TRANSACTION
** COMMIT
** ROLLBACK
**
** $Id: build.c,v 1.493 2008/08/04 04:39:49 danielk1977 Exp $
*/
/*
** This routine is called when a new SQL statement is beginning to
** be parsed. Initialize the pParse structure as needed.
*/
SQLITE_PRIVATE void sqlite3BeginParse(Parse *pParse, int explainFlag){
pParse->explain = explainFlag;
pParse->nVar = 0;
}
#ifndef SQLITE_OMIT_SHARED_CACHE
/*
** The TableLock structure is only used by the sqlite3TableLock() and
** codeTableLocks() functions.
*/
struct TableLock {
int iDb; /* The database containing the table to be locked */
int iTab; /* The root page of the table to be locked */
u8 isWriteLock; /* True for write lock. False for a read lock */
const char *zName; /* Name of the table */
};
/*
** Record the fact that we want to lock a table at run-time.
**
** The table to be locked has root page iTab and is found in database iDb.
** A read or a write lock can be taken depending on isWritelock.
**
** This routine just records the fact that the lock is desired. The
** code to make the lock occur is generated by a later call to
** codeTableLocks() which occurs during sqlite3FinishCoding().
*/
SQLITE_PRIVATE void sqlite3TableLock(
Parse *pParse, /* Parsing context */
int iDb, /* Index of the database containing the table to lock */
int iTab, /* Root page number of the table to be locked */
u8 isWriteLock, /* True for a write lock */
const char *zName /* Name of the table to be locked */
){
int i;
int nBytes;
TableLock *p;
if( iDb<0 ){
return;
}
for(i=0; i<pParse->nTableLock; i++){
p = &pParse->aTableLock[i];
if( p->iDb==iDb && p->iTab==iTab ){
p->isWriteLock = (p->isWriteLock || isWriteLock);
return;
}
}
nBytes = sizeof(TableLock) * (pParse->nTableLock+1);
pParse->aTableLock =
sqlite3DbReallocOrFree(pParse->db, pParse->aTableLock, nBytes);
if( pParse->aTableLock ){
p = &pParse->aTableLock[pParse->nTableLock++];
p->iDb = iDb;
p->iTab = iTab;
p->isWriteLock = isWriteLock;
p->zName = zName;
}else{
pParse->nTableLock = 0;
pParse->db->mallocFailed = 1;
}
}
/*
** Code an OP_TableLock instruction for each table locked by the
** statement (configured by calls to sqlite3TableLock()).
*/
static void codeTableLocks(Parse *pParse){
int i;
Vdbe *pVdbe;
if( 0==(pVdbe = sqlite3GetVdbe(pParse)) ){
return;
}
for(i=0; i<pParse->nTableLock; i++){
TableLock *p = &pParse->aTableLock[i];
int p1 = p->iDb;
sqlite3VdbeAddOp4(pVdbe, OP_TableLock, p1, p->iTab, p->isWriteLock,
p->zName, P4_STATIC);
}
}
#else
#define codeTableLocks(x)
#endif
/*
** This routine is called after a single SQL statement has been
** parsed and a VDBE program to execute that statement has been
** prepared. This routine puts the finishing touches on the
** VDBE program and resets the pParse structure for the next
** parse.
**
** Note that if an error occurred, it might be the case that
** no VDBE code was generated.
*/
SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
sqlite3 *db;
Vdbe *v;
db = pParse->db;
if( db->mallocFailed ) return;
if( pParse->nested ) return;
if( pParse->nErr ) return;
/* Begin by generating some termination code at the end of the
** vdbe program
*/
v = sqlite3GetVdbe(pParse);
if( v ){
sqlite3VdbeAddOp0(v, OP_Halt);
/* The cookie mask contains one bit for each database file open.
** (Bit 0 is for main, bit 1 is for temp, and so forth.) Bits are
** set for each database that is used. Generate code to start a
** transaction on each used database and to verify the schema cookie
** on each used database.
*/
if( pParse->cookieGoto>0 ){
u32 mask;
int iDb;
sqlite3VdbeJumpHere(v, pParse->cookieGoto-1);
for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){
if( (mask & pParse->cookieMask)==0 ) continue;
sqlite3VdbeUsesBtree(v, iDb);
sqlite-amalgamation.c view on Meta::CPAN
** the schema-version is potentially dangerous and may lead to program
** crashes or database corruption. Use with caution!
**
** The user-version is not used internally by SQLite. It may be used by
** applications for any purpose.
*/
if( sqlite3StrICmp(zLeft, "schema_version")==0
|| sqlite3StrICmp(zLeft, "user_version")==0
|| sqlite3StrICmp(zLeft, "freelist_count")==0
){
int iCookie; /* Cookie index. 0 for schema-cookie, 6 for user-cookie. */
sqlite3VdbeUsesBtree(v, iDb);
switch( zLeft[0] ){
case 's': case 'S':
iCookie = 0;
break;
case 'f': case 'F':
iCookie = 1;
iDb = (-1*(iDb+1));
assert(iDb<=0);
break;
default:
iCookie = 5;
break;
}
if( zRight && iDb>=0 ){
/* Write the specified cookie value */
static const VdbeOpList setCookie[] = {
{ OP_Transaction, 0, 1, 0}, /* 0 */
{ OP_Integer, 0, 1, 0}, /* 1 */
{ OP_SetCookie, 0, 0, 1}, /* 2 */
};
int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie);
sqlite3VdbeChangeP1(v, addr, iDb);
sqlite3VdbeChangeP1(v, addr+1, atoi(zRight));
sqlite3VdbeChangeP1(v, addr+2, iDb);
sqlite3VdbeChangeP2(v, addr+2, iCookie);
}else{
/* Read the specified cookie value */
static const VdbeOpList readCookie[] = {
{ OP_ReadCookie, 0, 1, 0}, /* 0 */
{ OP_ResultRow, 1, 1, 0}
};
int addr = sqlite3VdbeAddOpList(v, ArraySize(readCookie), readCookie);
sqlite3VdbeChangeP1(v, addr, iDb);
sqlite3VdbeChangeP3(v, addr, iCookie);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, P4_TRANSIENT);
}
}else
#endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
/*
** Report the current state of file logs for all databases
*/
if( sqlite3StrICmp(zLeft, "lock_status")==0 ){
static const char *const azLockName[] = {
"unlocked", "shared", "reserved", "pending", "exclusive"
};
int i;
Vdbe *v = sqlite3GetVdbe(pParse);
sqlite3VdbeSetNumCols(v, 2);
pParse->nMem = 2;
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "database", P4_STATIC);
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "status", P4_STATIC);
for(i=0; i<db->nDb; i++){
Btree *pBt;
Pager *pPager;
const char *zState = "unknown";
int j;
if( db->aDb[i].zName==0 ) continue;
sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, db->aDb[i].zName, P4_STATIC);
pBt = db->aDb[i].pBt;
if( pBt==0 || (pPager = sqlite3BtreePager(pBt))==0 ){
zState = "closed";
}else if( sqlite3_file_control(db, i ? db->aDb[i].zName : 0,
SQLITE_FCNTL_LOCKSTATE, &j)==SQLITE_OK ){
zState = azLockName[j];
}
sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, zState, P4_STATIC);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 2);
}
}else
#endif
#ifdef SQLITE_SSE
/*
** Check to see if the sqlite_statements table exists. Create it
** if it does not.
*/
if( sqlite3StrICmp(zLeft, "create_sqlite_statement_table")==0 ){
extern int sqlite3CreateStatementsTable(Parse*);
sqlite3CreateStatementsTable(pParse);
}else
#endif
#if SQLITE_HAS_CODEC
if( sqlite3StrICmp(zLeft, "key")==0 ){
sqlite3_key(db, zRight, strlen(zRight));
}else
#endif
#if SQLITE_HAS_CODEC || defined(SQLITE_ENABLE_CEROD)
if( sqlite3StrICmp(zLeft, "activate_extensions")==0 ){
#if SQLITE_HAS_CODEC
if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){
extern void sqlite3_activate_see(const char*);
sqlite3_activate_see(&zRight[4]);
}
#endif
#ifdef SQLITE_ENABLE_CEROD
if( sqlite3StrNICmp(zRight, "cerod-", 6)==0 ){
extern void sqlite3_activate_cerod(const char*);
sqlite3_activate_cerod(&zRight[6]);
}
#endif
}
#endif
sqlite-amalgamation.c view on Meta::CPAN
return allOk;
}
/*
** Convert a schema pointer into the iDb index that indicates
** which database file in db->aDb[] the schema refers to.
**
** If the same database is attached more than once, the first
** attached database is returned.
*/
SQLITE_PRIVATE int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
int i = -1000000;
/* If pSchema is NULL, then return -1000000. This happens when code in
** expr.c is trying to resolve a reference to a transient table (i.e. one
** created by a sub-select). In this case the return value of this
** function should never be used.
**
** We return -1000000 instead of the more usual -1 simply because using
** -1000000 as incorrectly using -1000000 index into db->aDb[] is much
** more likely to cause a segfault than -1 (of course there are assert()
** statements too, but it never hurts to play the odds).
*/
assert( sqlite3_mutex_held(db->mutex) );
if( pSchema ){
for(i=0; i<db->nDb; i++){
if( db->aDb[i].pSchema==pSchema ){
break;
}
}
assert( i>=0 &&i>=0 && i<db->nDb );
}
return i;
}
/*
** Compile the UTF-8 encoded SQL statement zSql into a statement handle.
*/
static int sqlite3Prepare(
sqlite3 *db, /* Database handle. */
const char *zSql, /* UTF-8 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
int saveSqlFlag, /* True to copy SQL text into the sqlite3_stmt */
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
const char **pzTail /* OUT: End of parsed string */
){
Parse sParse;
char *zErrMsg = 0;
int rc = SQLITE_OK;
int i;
assert( ppStmt );
*ppStmt = 0;
if( sqlite3SafetyOn(db) ){
return SQLITE_MISUSE;
}
assert( !db->mallocFailed );
assert( sqlite3_mutex_held(db->mutex) );
/* If any attached database schemas are locked, do not proceed with
** compilation. Instead return SQLITE_LOCKED immediately.
*/
for(i=0; i<db->nDb; i++) {
Btree *pBt = db->aDb[i].pBt;
if( pBt ){
int rc;
rc = sqlite3BtreeSchemaLocked(pBt);
if( rc ){
const char *zDb = db->aDb[i].zName;
sqlite3Error(db, SQLITE_LOCKED, "database schema is locked: %s", zDb);
(void)sqlite3SafetyOff(db);
return sqlite3ApiExit(db, SQLITE_LOCKED);
}
}
}
memset(&sParse, 0, sizeof(sParse));
sParse.db = db;
if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){
char *zSqlCopy;
int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
if( nBytes>mxLen ){
sqlite3Error(db, SQLITE_TOOBIG, "statement too long");
(void)sqlite3SafetyOff(db);
return sqlite3ApiExit(db, SQLITE_TOOBIG);
}
zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes);
if( zSqlCopy ){
sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg);
sqlite3DbFree(db, zSqlCopy);
sParse.zTail = &zSql[sParse.zTail-zSqlCopy];
}else{
sParse.zTail = &zSql[nBytes];
}
}else{
sqlite3RunParser(&sParse, zSql, &zErrMsg);
}
if( db->mallocFailed ){
sParse.rc = SQLITE_NOMEM;
}
if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
if( sParse.checkSchema && !schemaIsValid(db) ){
sParse.rc = SQLITE_SCHEMA;
}
if( sParse.rc==SQLITE_SCHEMA ){
sqlite3ResetInternalSchema(db, 0);
}
if( db->mallocFailed ){
sParse.rc = SQLITE_NOMEM;
}
if( pzTail ){
*pzTail = sParse.zTail;
}
rc = sParse.rc;
#ifndef SQLITE_OMIT_EXPLAIN
if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){
if( sParse.explain==2 ){
sqlite3VdbeSetNumCols(sParse.pVdbe, 3);
sqlite3VdbeSetColName(sParse.pVdbe, 0, COLNAME_NAME, "order", P4_STATIC);
sqlite3VdbeSetColName(sParse.pVdbe, 1, COLNAME_NAME, "from", P4_STATIC);
sqlite3VdbeSetColName(sParse.pVdbe, 2, COLNAME_NAME, "detail", P4_STATIC);
}else{
sqlite3VdbeSetNumCols(sParse.pVdbe, 8);
sqlite3VdbeSetColName(sParse.pVdbe, 0, COLNAME_NAME, "addr", P4_STATIC);
sqlite3VdbeSetColName(sParse.pVdbe, 1, COLNAME_NAME, "opcode", P4_STATIC);
sqlite3VdbeSetColName(sParse.pVdbe, 2, COLNAME_NAME, "p1", P4_STATIC);
sqlite3VdbeSetColName(sParse.pVdbe, 3, COLNAME_NAME, "p2", P4_STATIC);
sqlite3VdbeSetColName(sParse.pVdbe, 4, COLNAME_NAME, "p3", P4_STATIC);
sqlite-amalgamation.c view on Meta::CPAN
int rc, nName;
Module *pMod;
sqlite3_mutex_enter(db->mutex);
nName = strlen(zName);
pMod = (Module *)sqlite3DbMallocRaw(db, sizeof(Module) + nName + 1);
if( pMod ){
Module *pDel;
char *zCopy = (char *)(&pMod[1]);
memcpy(zCopy, zName, nName+1);
pMod->zName = zCopy;
pMod->pModule = pModule;
pMod->pAux = pAux;
pMod->xDestroy = xDestroy;
pDel = (Module *)sqlite3HashInsert(&db->aModule, zCopy, nName, (void*)pMod);
if( pDel && pDel->xDestroy ){
pDel->xDestroy(pDel->pAux);
}
sqlite3DbFree(db, pDel);
if( pDel==pMod ){
db->mallocFailed = 1;
}
sqlite3ResetInternalSchema(db, 0);
}
rc = sqlite3ApiExit(db, SQLITE_OK);
sqlite3_mutex_leave(db->mutex);
return rc;
}
/*
** External API function used to create a new virtual-table module.
*/
SQLITE_API int sqlite3_create_module(
sqlite3 *db, /* Database in which module is registered */
const char *zName, /* Name assigned to this module */
const sqlite3_module *pModule, /* The definition of the module */
void *pAux /* Context pointer for xCreate/xConnect */
){
return createModule(db, zName, pModule, pAux, 0);
}
/*
** External API function used to create a new virtual-table module.
*/
SQLITE_API int sqlite3_create_module_v2(
sqlite3 *db, /* Database in which module is registered */
const char *zName, /* Name assigned to this module */
const sqlite3_module *pModule, /* The definition of the module */
void *pAux, /* Context pointer for xCreate/xConnect */
void (*xDestroy)(void *) /* Module destructor function */
){
return createModule(db, zName, pModule, pAux, xDestroy);
}
/*
** Lock the virtual table so that it cannot be disconnected.
** Locks nest. Every lock should have a corresponding unlock.
** If an unlock is omitted, resources leaks will occur.
**
** If a disconnect is attempted while a virtual table is locked,
** the disconnect is deferred until all locks have been removed.
*/
SQLITE_PRIVATE void sqlite3VtabLock(sqlite3_vtab *pVtab){
pVtab->nRef++;
}
/*
** Unlock a virtual table. When the last lock is removed,
** disconnect the virtual table.
*/
SQLITE_PRIVATE void sqlite3VtabUnlock(sqlite3 *db, sqlite3_vtab *pVtab){
pVtab->nRef--;
assert(db);
assert( sqlite3SafetyCheckOk(db) );
if( pVtab->nRef==0 ){
if( db->magic==SQLITE_MAGIC_BUSY ){
(void)sqlite3SafetyOff(db);
pVtab->pModule->xDisconnect(pVtab);
(void)sqlite3SafetyOn(db);
} else {
pVtab->pModule->xDisconnect(pVtab);
}
}
}
/*
** Clear any and all virtual-table information from the Table record.
** This routine is called, for example, just before deleting the Table
** record.
*/
SQLITE_PRIVATE void sqlite3VtabClear(Table *p){
sqlite3_vtab *pVtab = p->pVtab;
sqlite3 *db = p->db;
if( pVtab ){
assert( p->pMod && p->pMod->pModule );
sqlite3VtabUnlock(db, pVtab);
p->pVtab = 0;
}
if( p->azModuleArg ){
int i;
for(i=0; i<p->nModuleArg; i++){
sqlite3DbFree(db, p->azModuleArg[i]);
}
sqlite3DbFree(db, p->azModuleArg);
}
}
/*
** Add a new module argument to pTable->azModuleArg[].
** The string is not copied - the pointer is stored. The
** string will be freed automatically when the table is
** deleted.
*/
static void addModuleArgument(sqlite3 *db, Table *pTable, char *zArg){
int i = pTable->nModuleArg++;
int nBytes = sizeof(char *)*(1+pTable->nModuleArg);
char **azModuleArg;
azModuleArg = sqlite3DbRealloc(db, pTable->azModuleArg, nBytes);
if( azModuleArg==0 ){
int j;
sqlite-amalgamation.c view on Meta::CPAN
** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()).
** So it needs to be freed here. Todo: Why not roll the temp schema into
** the same sqliteMalloc() as the one that allocates the database
** structure?
*/
sqlite3DbFree(db, db->aDb[1].pSchema);
sqlite3_mutex_leave(db->mutex);
db->magic = SQLITE_MAGIC_CLOSED;
sqlite3_mutex_free(db->mutex);
if( db->lookaside.bMalloced ){
sqlite3_free(db->lookaside.pStart);
}
sqlite3_free(db);
return SQLITE_OK;
}
/*
** Rollback all database files.
*/
SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db){
int i;
int inTrans = 0;
assert( sqlite3_mutex_held(db->mutex) );
sqlite3BeginBenignMalloc();
for(i=0; i<db->nDb; i++){
if( db->aDb[i].pBt ){
if( sqlite3BtreeIsInTrans(db->aDb[i].pBt) ){
inTrans = 1;
}
sqlite3BtreeRollback(db->aDb[i].pBt);
db->aDb[i].inTrans = 0;
}
}
sqlite3VtabRollback(db);
sqlite3EndBenignMalloc();
if( db->flags&SQLITE_InternChanges ){
sqlite3ExpirePreparedStatements(db);
sqlite3ResetInternalSchema(db, 0);
}
/* If one has been configured, invoke the rollback-hook callback */
if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){
db->xRollbackCallback(db->pRollbackArg);
}
}
/*
** Return a static string that describes the kind of error specified in the
** argument.
*/
SQLITE_PRIVATE const char *sqlite3ErrStr(int rc){
const char *z;
switch( rc & 0xff ){
case SQLITE_ROW:
case SQLITE_DONE:
case SQLITE_OK: z = "not an error"; break;
case SQLITE_ERROR: z = "SQL logic error or missing database"; break;
case SQLITE_PERM: z = "access permission denied"; break;
case SQLITE_ABORT: z = "callback requested query abort"; break;
case SQLITE_BUSY: z = "database is locked"; break;
case SQLITE_LOCKED: z = "database table is locked"; break;
case SQLITE_NOMEM: z = "out of memory"; break;
case SQLITE_READONLY: z = "attempt to write a readonly database"; break;
case SQLITE_INTERRUPT: z = "interrupted"; break;
case SQLITE_IOERR: z = "disk I/O error"; break;
case SQLITE_CORRUPT: z = "database disk image is malformed"; break;
case SQLITE_FULL: z = "database or disk is full"; break;
case SQLITE_CANTOPEN: z = "unable to open database file"; break;
case SQLITE_EMPTY: z = "table contains no data"; break;
case SQLITE_SCHEMA: z = "database schema has changed"; break;
case SQLITE_TOOBIG: z = "String or BLOB exceeded size limit"; break;
case SQLITE_CONSTRAINT: z = "constraint failed"; break;
case SQLITE_MISMATCH: z = "datatype mismatch"; break;
case SQLITE_MISUSE: z = "library routine called out of sequence";break;
case SQLITE_NOLFS: z = "large file support is disabled"; break;
case SQLITE_AUTH: z = "authorization denied"; break;
case SQLITE_FORMAT: z = "auxiliary database format error"; break;
case SQLITE_RANGE: z = "bind or column index out of range"; break;
case SQLITE_NOTADB: z = "file is encrypted or is not a database";break;
default: z = "unknown error"; break;
}
return z;
}
/*
** This routine implements a busy callback that sleeps and tries
** again until a timeout value is reached. The timeout value is
** an integer number of milliseconds passed in as the first
** argument.
*/
static int sqliteDefaultBusyCallback(
void *ptr, /* Database connection */
int count /* Number of times table has been busy */
){
#if SQLITE_OS_WIN || (defined(HAVE_USLEEP) && HAVE_USLEEP)
static const u8 delays[] =
{ 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 100 };
static const u8 totals[] =
{ 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228 };
# define NDELAY (sizeof(delays)/sizeof(delays[0]))
sqlite3 *db = (sqlite3 *)ptr;
int timeout = db->busyTimeout;
int delay, prior;
assert( count>=0 );
if( count < NDELAY ){
delay = delays[count];
prior = totals[count];
}else{
delay = delays[NDELAY-1];
prior = totals[NDELAY-1] + delay*(count-(NDELAY-1));
}
if( prior + delay > timeout ){
delay = timeout - prior;
if( delay<=0 ) return 0;
}
sqlite3OsSleep(db->pVfs, delay*1000);
return 1;
#else
sqlite3 *db = (sqlite3 *)ptr;
int timeout = ((sqlite3 *)ptr)->busyTimeout;
sqlite-amalgamation.c view on Meta::CPAN
sqlite_int64 iDocid){
sqlite3_stmt *s;
int i;
int rc = sql_get_statement(v, CONTENT_UPDATE_STMT, &s);
if( rc!=SQLITE_OK ) return rc;
for(i=0; i<v->nColumn; ++i){
rc = sqlite3_bind_value(s, 1+i, pValues[i]);
if( rc!=SQLITE_OK ) return rc;
}
rc = sqlite3_bind_int64(s, 1+v->nColumn, iDocid);
if( rc!=SQLITE_OK ) return rc;
return sql_single_step(s);
}
static void freeStringArray(int nString, const char **pString){
int i;
for (i=0 ; i < nString ; ++i) {
if( pString[i]!=NULL ) sqlite3_free((void *) pString[i]);
}
sqlite3_free((void *) pString);
}
/* select * from %_content where docid = [iDocid]
* The caller must delete the returned array and all strings in it.
* null fields will be NULL in the returned array.
*
* TODO: Perhaps we should return pointer/length strings here for consistency
* with other code which uses pointer/length. */
static int content_select(fulltext_vtab *v, sqlite_int64 iDocid,
const char ***pValues){
sqlite3_stmt *s;
const char **values;
int i;
int rc;
*pValues = NULL;
rc = sql_get_statement(v, CONTENT_SELECT_STMT, &s);
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3_bind_int64(s, 1, iDocid);
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3_step(s);
if( rc!=SQLITE_ROW ) return rc;
values = (const char **) sqlite3_malloc(v->nColumn * sizeof(const char *));
for(i=0; i<v->nColumn; ++i){
if( sqlite3_column_type(s, i)==SQLITE_NULL ){
values[i] = NULL;
}else{
values[i] = string_dup((char*)sqlite3_column_text(s, i));
}
}
/* We expect only one row. We must execute another sqlite3_step()
* to complete the iteration; otherwise the table will remain locked. */
rc = sqlite3_step(s);
if( rc==SQLITE_DONE ){
*pValues = values;
return SQLITE_OK;
}
freeStringArray(v->nColumn, values);
return rc;
}
/* delete from %_content where docid = [iDocid ] */
static int content_delete(fulltext_vtab *v, sqlite_int64 iDocid){
sqlite3_stmt *s;
int rc = sql_get_statement(v, CONTENT_DELETE_STMT, &s);
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3_bind_int64(s, 1, iDocid);
if( rc!=SQLITE_OK ) return rc;
return sql_single_step(s);
}
/* Returns SQLITE_ROW if any rows exist in %_content, SQLITE_DONE if
** no rows exist, and any error in case of failure.
*/
static int content_exists(fulltext_vtab *v){
sqlite3_stmt *s;
int rc = sql_get_statement(v, CONTENT_EXISTS_STMT, &s);
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3_step(s);
if( rc!=SQLITE_ROW ) return rc;
/* We expect only one row. We must execute another sqlite3_step()
* to complete the iteration; otherwise the table will remain locked. */
rc = sqlite3_step(s);
if( rc==SQLITE_DONE ) return SQLITE_ROW;
if( rc==SQLITE_ROW ) return SQLITE_ERROR;
return rc;
}
/* insert into %_segments values ([pData])
** returns assigned blockid in *piBlockid
*/
static int block_insert(fulltext_vtab *v, const char *pData, int nData,
sqlite_int64 *piBlockid){
sqlite3_stmt *s;
int rc = sql_get_statement(v, BLOCK_INSERT_STMT, &s);
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3_bind_blob(s, 1, pData, nData, SQLITE_STATIC);
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3_step(s);
if( rc==SQLITE_ROW ) return SQLITE_ERROR;
if( rc!=SQLITE_DONE ) return rc;
/* blockid column is an alias for rowid. */
*piBlockid = sqlite3_last_insert_rowid(v->db);
return SQLITE_OK;
}
/* delete from %_segments
** where blockid between [iStartBlockid] and [iEndBlockid]
**
** Deletes the range of blocks, inclusive, used to delete the blocks
** which form a segment.
*/
static int block_delete(fulltext_vtab *v,
sqlite_int64 iStartBlockid, sqlite_int64 iEndBlockid){
sqlite3_stmt *s;
int rc = sql_get_statement(v, BLOCK_DELETE_STMT, &s);
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3_bind_int64(s, 1, iStartBlockid);
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3_bind_int64(s, 2, iEndBlockid);
if( rc!=SQLITE_OK ) return rc;
return sql_single_step(s);
}
/* Returns SQLITE_ROW with *pidx set to the maximum segment idx found
** at iLevel. Returns SQLITE_DONE if there are no segments at
** iLevel. Otherwise returns an error.
*/
static int segdir_max_index(fulltext_vtab *v, int iLevel, int *pidx){
sqlite3_stmt *s;
int rc = sql_get_statement(v, SEGDIR_MAX_INDEX_STMT, &s);
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3_bind_int(s, 1, iLevel);
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3_step(s);
/* Should always get at least one row due to how max() works. */
if( rc==SQLITE_DONE ) return SQLITE_DONE;
if( rc!=SQLITE_ROW ) return rc;
/* NULL means that there were no inputs to max(). */
if( SQLITE_NULL==sqlite3_column_type(s, 0) ){
rc = sqlite3_step(s);
if( rc==SQLITE_ROW ) return SQLITE_ERROR;
return rc;
}
*pidx = sqlite3_column_int(s, 0);
/* We expect only one row. We must execute another sqlite3_step()
* to complete the iteration; otherwise the table will remain locked. */
rc = sqlite3_step(s);
if( rc==SQLITE_ROW ) return SQLITE_ERROR;
if( rc!=SQLITE_DONE ) return rc;
return SQLITE_ROW;
}
/* insert into %_segdir values (
** [iLevel], [idx],
** [iStartBlockid], [iLeavesEndBlockid], [iEndBlockid],
** [pRootData]
** )
*/
static int segdir_set(fulltext_vtab *v, int iLevel, int idx,
sqlite_int64 iStartBlockid,
sqlite_int64 iLeavesEndBlockid,
sqlite_int64 iEndBlockid,
const char *pRootData, int nRootData){
sqlite3_stmt *s;
int rc = sql_get_statement(v, SEGDIR_SET_STMT, &s);
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3_bind_int(s, 1, iLevel);
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3_bind_int(s, 2, idx);
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3_bind_int64(s, 3, iStartBlockid);
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3_bind_int64(s, 4, iLeavesEndBlockid);
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3_bind_int64(s, 5, iEndBlockid);
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3_bind_blob(s, 6, pRootData, nRootData, SQLITE_STATIC);
if( rc!=SQLITE_OK ) return rc;
return sql_single_step(s);
}
/* Queries %_segdir for the block span of the segments in level
** iLevel. Returns SQLITE_DONE if there are no blocks for iLevel,
** SQLITE_ROW if there are blocks, else an error.
*/
static int segdir_span(fulltext_vtab *v, int iLevel,
sqlite_int64 *piStartBlockid,
sqlite_int64 *piEndBlockid){
sqlite3_stmt *s;
int rc = sql_get_statement(v, SEGDIR_SPAN_STMT, &s);
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3_bind_int(s, 1, iLevel);
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3_step(s);
if( rc==SQLITE_DONE ) return SQLITE_DONE; /* Should never happen */
if( rc!=SQLITE_ROW ) return rc;
/* This happens if all segments at this level are entirely inline. */
if( SQLITE_NULL==sqlite3_column_type(s, 0) ){
/* We expect only one row. We must execute another sqlite3_step()
* to complete the iteration; otherwise the table will remain locked. */
int rc2 = sqlite3_step(s);
if( rc2==SQLITE_ROW ) return SQLITE_ERROR;
return rc2;
}
*piStartBlockid = sqlite3_column_int64(s, 0);
*piEndBlockid = sqlite3_column_int64(s, 1);
/* We expect only one row. We must execute another sqlite3_step()
* to complete the iteration; otherwise the table will remain locked. */
rc = sqlite3_step(s);
if( rc==SQLITE_ROW ) return SQLITE_ERROR;
if( rc!=SQLITE_DONE ) return rc;
return SQLITE_ROW;
}
/* Delete the segment blocks and segment directory records for all
** segments at iLevel.
*/
static int segdir_delete(fulltext_vtab *v, int iLevel){
sqlite3_stmt *s;
sqlite_int64 iStartBlockid, iEndBlockid;
int rc = segdir_span(v, iLevel, &iStartBlockid, &iEndBlockid);
if( rc!=SQLITE_ROW && rc!=SQLITE_DONE ) return rc;
if( rc==SQLITE_ROW ){
rc = block_delete(v, iStartBlockid, iEndBlockid);
if( rc!=SQLITE_OK ) return rc;
}
/* Delete the segment directory itself. */
rc = sql_get_statement(v, SEGDIR_DELETE_STMT, &s);
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3_bind_int64(s, 1, iLevel);
if( rc!=SQLITE_OK ) return rc;
return sql_single_step(s);
}
/* Delete entire fts index, SQLITE_OK on success, relevant error on
** failure.
*/
static int segdir_delete_all(fulltext_vtab *v){
sqlite3_stmt *s;
int rc = sql_get_statement(v, SEGDIR_DELETE_ALL_STMT, &s);
if( rc!=SQLITE_OK ) return rc;
rc = sql_single_step(s);
if( rc!=SQLITE_OK ) return rc;
rc = sql_get_statement(v, BLOCK_DELETE_ALL_STMT, &s);
if( rc!=SQLITE_OK ) return rc;
return sql_single_step(s);
}
/* Returns SQLITE_OK with *pnSegments set to the number of entries in
** %_segdir and *piMaxLevel set to the highest level which has a
** segment. Otherwise returns the SQLite error which caused failure.
*/
static int segdir_count(fulltext_vtab *v, int *pnSegments, int *piMaxLevel){
sqlite3_stmt *s;
int rc = sql_get_statement(v, SEGDIR_COUNT_STMT, &s);
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3_step(s);
/* TODO(shess): This case should not be possible? Should stronger
** measures be taken if it happens?
*/
if( rc==SQLITE_DONE ){
*pnSegments = 0;
*piMaxLevel = 0;
return SQLITE_OK;
}
if( rc!=SQLITE_ROW ) return rc;
*pnSegments = sqlite3_column_int(s, 0);
*piMaxLevel = sqlite3_column_int(s, 1);
/* We expect only one row. We must execute another sqlite3_step()
* to complete the iteration; otherwise the table will remain locked. */
rc = sqlite3_step(s);
if( rc==SQLITE_DONE ) return SQLITE_OK;
if( rc==SQLITE_ROW ) return SQLITE_ERROR;
return rc;
}
/* TODO(shess) clearPendingTerms() is far down the file because
** writeZeroSegment() is far down the file because LeafWriter is far
** down the file. Consider refactoring the code to move the non-vtab
** code above the vtab code so that we don't need this forward
** reference.
*/
static int clearPendingTerms(fulltext_vtab *v);
/*
** Free the memory used to contain a fulltext_vtab structure.
*/
static void fulltext_vtab_destroy(fulltext_vtab *v){
int iStmt, i;
FTSTRACE(("FTS3 Destroy %p\n", v));
for( iStmt=0; iStmt<MAX_STMT; iStmt++ ){
if( v->pFulltextStatements[iStmt]!=NULL ){
sqlite3_finalize(v->pFulltextStatements[iStmt]);
v->pFulltextStatements[iStmt] = NULL;
}
}
for( i=0; i<MERGE_COUNT; i++ ){
if( v->pLeafSelectStmts[i]!=NULL ){
sqlite3_finalize(v->pLeafSelectStmts[i]);
v->pLeafSelectStmts[i] = NULL;
}
}
if( v->pTokenizer!=NULL ){
v->pTokenizer->pModule->xDestroy(v->pTokenizer);
v->pTokenizer = NULL;
}
clearPendingTerms(v);
sqlite3_free(v->azColumn);
for(i = 0; i < v->nColumn; ++i) {
sqlite3_free(v->azContentColumn[i]);
}
sqlite3_free(v->azContentColumn);
sqlite3_free(v);
}
/*
** Token types for parsing the arguments to xConnect or xCreate.
*/
#define TOKEN_EOF 0 /* End of file */
#define TOKEN_SPACE 1 /* Any kind of whitespace */
#define TOKEN_ID 2 /* An identifier */
#define TOKEN_STRING 3 /* A string literal */
#define TOKEN_PUNCT 4 /* A single punctuation character */
/*
sqlite-amalgamation.c view on Meta::CPAN
assert( *pData!='\0' );
interiorReaderInit(pData, nData, &reader);
/* Scan for the first child which could contain pTerm/nTerm. */
while( !interiorReaderAtEnd(&reader) ){
if( interiorReaderTermCmp(&reader, pTerm, nTerm, 0)>0 ) break;
interiorReaderStep(&reader);
}
*piStartChild = interiorReaderCurrentBlockid(&reader);
/* Keep scanning to find a term greater than our term, using prefix
** comparison if indicated. If isPrefix is false, this will be the
** same blockid as the starting block.
*/
while( !interiorReaderAtEnd(&reader) ){
if( interiorReaderTermCmp(&reader, pTerm, nTerm, isPrefix)>0 ) break;
interiorReaderStep(&reader);
}
*piEndChild = interiorReaderCurrentBlockid(&reader);
interiorReaderDestroy(&reader);
/* Children must ascend, and if !prefix, both must be the same. */
assert( *piEndChild>=*piStartChild );
assert( isPrefix || *piStartChild==*piEndChild );
}
/* Read block at iBlockid and pass it with other params to
** getChildrenContaining().
*/
static int loadAndGetChildrenContaining(
fulltext_vtab *v,
sqlite_int64 iBlockid,
const char *pTerm, int nTerm, int isPrefix,
sqlite_int64 *piStartChild, sqlite_int64 *piEndChild
){
sqlite3_stmt *s = NULL;
int rc;
assert( iBlockid!=0 );
assert( pTerm!=NULL );
assert( nTerm!=0 ); /* TODO(shess) Why not allow this? */
assert( piStartChild!=NULL );
assert( piEndChild!=NULL );
rc = sql_get_statement(v, BLOCK_SELECT_STMT, &s);
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3_bind_int64(s, 1, iBlockid);
if( rc!=SQLITE_OK ) return rc;
rc = sqlite3_step(s);
if( rc==SQLITE_DONE ) return SQLITE_ERROR;
if( rc!=SQLITE_ROW ) return rc;
getChildrenContaining(sqlite3_column_blob(s, 0), sqlite3_column_bytes(s, 0),
pTerm, nTerm, isPrefix, piStartChild, piEndChild);
/* We expect only one row. We must execute another sqlite3_step()
* to complete the iteration; otherwise the table will remain
* locked. */
rc = sqlite3_step(s);
if( rc==SQLITE_ROW ) return SQLITE_ERROR;
if( rc!=SQLITE_DONE ) return rc;
return SQLITE_OK;
}
/* Traverse the tree represented by pData[nData] looking for
** pTerm[nTerm], placing its doclist into *out. This is internal to
** loadSegment() to make error-handling cleaner.
*/
static int loadSegmentInt(fulltext_vtab *v, const char *pData, int nData,
sqlite_int64 iLeavesEnd,
const char *pTerm, int nTerm, int isPrefix,
DataBuffer *out){
/* Special case where root is a leaf. */
if( *pData=='\0' ){
return loadSegmentLeaf(v, pData, nData, pTerm, nTerm, isPrefix, out);
}else{
int rc;
sqlite_int64 iStartChild, iEndChild;
/* Process pData as an interior node, then loop down the tree
** until we find the set of leaf nodes to scan for the term.
*/
getChildrenContaining(pData, nData, pTerm, nTerm, isPrefix,
&iStartChild, &iEndChild);
while( iStartChild>iLeavesEnd ){
sqlite_int64 iNextStart, iNextEnd;
rc = loadAndGetChildrenContaining(v, iStartChild, pTerm, nTerm, isPrefix,
&iNextStart, &iNextEnd);
if( rc!=SQLITE_OK ) return rc;
/* If we've branched, follow the end branch, too. */
if( iStartChild!=iEndChild ){
sqlite_int64 iDummy;
rc = loadAndGetChildrenContaining(v, iEndChild, pTerm, nTerm, isPrefix,
&iDummy, &iNextEnd);
if( rc!=SQLITE_OK ) return rc;
}
assert( iNextStart<=iNextEnd );
iStartChild = iNextStart;
iEndChild = iNextEnd;
}
assert( iStartChild<=iLeavesEnd );
assert( iEndChild<=iLeavesEnd );
/* Scan through the leaf segments for doclists. */
return loadSegmentLeaves(v, iStartChild, iEndChild,
pTerm, nTerm, isPrefix, out);
}
}
/* Call loadSegmentInt() to collect the doclist for pTerm/nTerm, then
** merge its doclist over *out (any duplicate doclists read from the
** segment rooted at pData will overwrite those in *out).
*/
/* TODO(shess) Consider changing this to determine the depth of the
** leaves using either the first characters of interior nodes (when