11398 lines
268 KiB
Plaintext
11398 lines
268 KiB
Plaintext
# 1 "src/btree.c"
|
|
# 1 "<built-in>"
|
|
# 1 "<command-line>"
|
|
# 1 "src/btree.c"
|
|
# 16 "src/btree.c"
|
|
# 1 "src/btreeInt.h" 1
|
|
# 216 "src/btreeInt.h"
|
|
# 1 "src/sqliteInt.h" 1
|
|
# 59 "src/sqliteInt.h"
|
|
# 1 "src/msvc.h" 1
|
|
# 60 "src/sqliteInt.h" 2
|
|
|
|
|
|
|
|
|
|
# 1 "src/vxworks.h" 1
|
|
# 65 "src/sqliteInt.h" 2
|
|
# 167 "src/sqliteInt.h"
|
|
# 1 "./sqlite3.h" 1
|
|
# 35 "./sqlite3.h"
|
|
# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdarg.h" 1
|
|
# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
|
|
# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdarg.h" 2
|
|
# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_typedefs.h" 1
|
|
|
|
|
|
|
|
typedef int size_t;
|
|
typedef int __builtin_va_list;
|
|
typedef int __gnuc_va_list;
|
|
typedef int va_list;
|
|
typedef int __int8_t;
|
|
typedef int __uint8_t;
|
|
typedef int __int16_t;
|
|
typedef int __uint16_t;
|
|
typedef int __int_least16_t;
|
|
typedef int __uint_least16_t;
|
|
typedef int __int32_t;
|
|
typedef int __uint32_t;
|
|
typedef int __int64_t;
|
|
typedef int __uint64_t;
|
|
typedef int __int_least32_t;
|
|
typedef int __uint_least32_t;
|
|
typedef int __s8;
|
|
typedef int __u8;
|
|
typedef int __s16;
|
|
typedef int __u16;
|
|
typedef int __s32;
|
|
typedef int __u32;
|
|
typedef int __s64;
|
|
typedef int __u64;
|
|
typedef int _LOCK_T;
|
|
typedef int _LOCK_RECURSIVE_T;
|
|
typedef int _off_t;
|
|
typedef int __dev_t;
|
|
typedef int __uid_t;
|
|
typedef int __gid_t;
|
|
typedef int _off64_t;
|
|
typedef int _fpos_t;
|
|
typedef int _ssize_t;
|
|
typedef int wint_t;
|
|
typedef int _mbstate_t;
|
|
typedef int _flock_t;
|
|
typedef int _iconv_t;
|
|
typedef int __ULong;
|
|
typedef int __FILE;
|
|
typedef int ptrdiff_t;
|
|
typedef int wchar_t;
|
|
typedef int __off_t;
|
|
typedef int __pid_t;
|
|
typedef int __loff_t;
|
|
typedef int u_char;
|
|
typedef int u_short;
|
|
typedef int u_int;
|
|
typedef int u_long;
|
|
typedef int ushort;
|
|
typedef int uint;
|
|
typedef int clock_t;
|
|
typedef int time_t;
|
|
typedef int daddr_t;
|
|
typedef int caddr_t;
|
|
typedef int ino_t;
|
|
typedef int off_t;
|
|
typedef int dev_t;
|
|
typedef int uid_t;
|
|
typedef int gid_t;
|
|
typedef int pid_t;
|
|
typedef int key_t;
|
|
typedef int ssize_t;
|
|
typedef int mode_t;
|
|
typedef int nlink_t;
|
|
typedef int fd_mask;
|
|
typedef int _types_fd_set;
|
|
typedef int clockid_t;
|
|
typedef int timer_t;
|
|
typedef int useconds_t;
|
|
typedef int suseconds_t;
|
|
typedef int FILE;
|
|
typedef int fpos_t;
|
|
typedef int cookie_read_function_t;
|
|
typedef int cookie_write_function_t;
|
|
typedef int cookie_seek_function_t;
|
|
typedef int cookie_close_function_t;
|
|
typedef int cookie_io_functions_t;
|
|
typedef int div_t;
|
|
typedef int ldiv_t;
|
|
typedef int lldiv_t;
|
|
typedef int sigset_t;
|
|
typedef int __sigset_t;
|
|
typedef int _sig_func_ptr;
|
|
typedef int sig_atomic_t;
|
|
typedef int __tzrule_type;
|
|
typedef int __tzinfo_type;
|
|
typedef int mbstate_t;
|
|
typedef int sem_t;
|
|
typedef int pthread_t;
|
|
typedef int pthread_attr_t;
|
|
typedef int pthread_mutex_t;
|
|
typedef int pthread_mutexattr_t;
|
|
typedef int pthread_cond_t;
|
|
typedef int pthread_condattr_t;
|
|
typedef int pthread_key_t;
|
|
typedef int pthread_once_t;
|
|
typedef int pthread_rwlock_t;
|
|
typedef int pthread_rwlockattr_t;
|
|
typedef int pthread_spinlock_t;
|
|
typedef int pthread_barrier_t;
|
|
typedef int pthread_barrierattr_t;
|
|
typedef int jmp_buf;
|
|
typedef int rlim_t;
|
|
typedef int sa_family_t;
|
|
typedef int sigjmp_buf;
|
|
typedef int stack_t;
|
|
typedef int siginfo_t;
|
|
typedef int z_stream;
|
|
|
|
|
|
typedef int int8_t;
|
|
typedef int uint8_t;
|
|
typedef int int16_t;
|
|
typedef int uint16_t;
|
|
typedef int int32_t;
|
|
typedef int uint32_t;
|
|
typedef int int64_t;
|
|
typedef int uint64_t;
|
|
|
|
|
|
typedef int int_least8_t;
|
|
typedef int uint_least8_t;
|
|
typedef int int_least16_t;
|
|
typedef int uint_least16_t;
|
|
typedef int int_least32_t;
|
|
typedef int uint_least32_t;
|
|
typedef int int_least64_t;
|
|
typedef int uint_least64_t;
|
|
|
|
|
|
typedef int int_fast8_t;
|
|
typedef int uint_fast8_t;
|
|
typedef int int_fast16_t;
|
|
typedef int uint_fast16_t;
|
|
typedef int int_fast32_t;
|
|
typedef int uint_fast32_t;
|
|
typedef int int_fast64_t;
|
|
typedef int uint_fast64_t;
|
|
|
|
|
|
typedef int intptr_t;
|
|
typedef int uintptr_t;
|
|
|
|
|
|
typedef int intmax_t;
|
|
typedef int uintmax_t;
|
|
|
|
|
|
typedef _Bool bool;
|
|
|
|
|
|
typedef void* MirEGLNativeWindowType;
|
|
typedef void* MirEGLNativeDisplayType;
|
|
typedef struct MirConnection MirConnection;
|
|
typedef struct MirSurface MirSurface;
|
|
typedef struct MirSurfaceSpec MirSurfaceSpec;
|
|
typedef struct MirScreencast MirScreencast;
|
|
typedef struct MirPromptSession MirPromptSession;
|
|
typedef struct MirBufferStream MirBufferStream;
|
|
typedef struct MirPersistentId MirPersistentId;
|
|
typedef struct MirBlob MirBlob;
|
|
typedef struct MirDisplayConfig MirDisplayConfig;
|
|
|
|
|
|
typedef struct xcb_connection_t xcb_connection_t;
|
|
typedef uint32_t xcb_window_t;
|
|
typedef uint32_t xcb_visualid_t;
|
|
# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdarg.h" 2
|
|
# 36 "./sqlite3.h" 2
|
|
# 162 "./sqlite3.h"
|
|
extern const char sqlite3_version[];
|
|
const char *sqlite3_libversion(void);
|
|
const char *sqlite3_sourceid(void);
|
|
int sqlite3_libversion_number(void);
|
|
# 190 "./sqlite3.h"
|
|
int sqlite3_compileoption_used(const char *zOptName);
|
|
const char *sqlite3_compileoption_get(int N);
|
|
# 233 "./sqlite3.h"
|
|
int sqlite3_threadsafe(void);
|
|
# 249 "./sqlite3.h"
|
|
typedef struct sqlite3 sqlite3;
|
|
# 278 "./sqlite3.h"
|
|
typedef long long int sqlite_int64;
|
|
typedef unsigned long long int sqlite_uint64;
|
|
|
|
typedef sqlite_int64 sqlite3_int64;
|
|
typedef sqlite_uint64 sqlite3_uint64;
|
|
# 334 "./sqlite3.h"
|
|
int sqlite3_close(sqlite3*);
|
|
int sqlite3_close_v2(sqlite3*);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef int (*sqlite3_callback)(void*,int,char**, char**);
|
|
# 406 "./sqlite3.h"
|
|
int sqlite3_exec(
|
|
sqlite3*,
|
|
const char *sql,
|
|
int (*callback)(void*,int,char**,char**),
|
|
void *,
|
|
char **errmsg
|
|
);
|
|
# 677 "./sqlite3.h"
|
|
typedef struct sqlite3_file sqlite3_file;
|
|
struct sqlite3_file {
|
|
const struct sqlite3_io_methods *pMethods;
|
|
};
|
|
# 776 "./sqlite3.h"
|
|
typedef struct sqlite3_io_methods sqlite3_io_methods;
|
|
struct sqlite3_io_methods {
|
|
int iVersion;
|
|
int (*xClose)(sqlite3_file*);
|
|
int (*xRead)(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
|
|
int (*xWrite)(sqlite3_file*, const void*, int iAmt, sqlite3_int64 iOfst);
|
|
int (*xTruncate)(sqlite3_file*, sqlite3_int64 size);
|
|
int (*xSync)(sqlite3_file*, int flags);
|
|
int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize);
|
|
int (*xLock)(sqlite3_file*, int);
|
|
int (*xUnlock)(sqlite3_file*, int);
|
|
int (*xCheckReservedLock)(sqlite3_file*, int *pResOut);
|
|
int (*xFileControl)(sqlite3_file*, int op, void *pArg);
|
|
int (*xSectorSize)(sqlite3_file*);
|
|
int (*xDeviceCharacteristics)(sqlite3_file*);
|
|
|
|
int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
|
|
int (*xShmLock)(sqlite3_file*, int offset, int n, int flags);
|
|
void (*xShmBarrier)(sqlite3_file*);
|
|
int (*xShmUnmap)(sqlite3_file*, int deleteFlag);
|
|
|
|
int (*xFetch)(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
|
|
int (*xUnfetch)(sqlite3_file*, sqlite3_int64 iOfst, void *p);
|
|
|
|
|
|
};
|
|
# 1164 "./sqlite3.h"
|
|
typedef struct sqlite3_mutex sqlite3_mutex;
|
|
# 1174 "./sqlite3.h"
|
|
typedef struct sqlite3_api_routines sqlite3_api_routines;
|
|
# 1345 "./sqlite3.h"
|
|
typedef struct sqlite3_vfs sqlite3_vfs;
|
|
typedef void (*sqlite3_syscall_ptr)(void);
|
|
struct sqlite3_vfs {
|
|
int iVersion;
|
|
int szOsFile;
|
|
int mxPathname;
|
|
sqlite3_vfs *pNext;
|
|
const char *zName;
|
|
void *pAppData;
|
|
int (*xOpen)(sqlite3_vfs*, const char *zName, sqlite3_file*,
|
|
int flags, int *pOutFlags);
|
|
int (*xDelete)(sqlite3_vfs*, const char *zName, int syncDir);
|
|
int (*xAccess)(sqlite3_vfs*, const char *zName, int flags, int *pResOut);
|
|
int (*xFullPathname)(sqlite3_vfs*, const char *zName, int nOut, char *zOut);
|
|
void *(*xDlOpen)(sqlite3_vfs*, const char *zFilename);
|
|
void (*xDlError)(sqlite3_vfs*, int nByte, char *zErrMsg);
|
|
void (*(*xDlSym)(sqlite3_vfs*,void*, const char *zSymbol))(void);
|
|
void (*xDlClose)(sqlite3_vfs*, void*);
|
|
int (*xRandomness)(sqlite3_vfs*, int nByte, char *zOut);
|
|
int (*xSleep)(sqlite3_vfs*, int microseconds);
|
|
int (*xCurrentTime)(sqlite3_vfs*, double*);
|
|
int (*xGetLastError)(sqlite3_vfs*, int, char *);
|
|
|
|
|
|
|
|
|
|
int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*);
|
|
|
|
|
|
|
|
|
|
int (*xSetSystemCall)(sqlite3_vfs*, const char *zName, sqlite3_syscall_ptr);
|
|
sqlite3_syscall_ptr (*xGetSystemCall)(sqlite3_vfs*, const char *zName);
|
|
const char *(*xNextSystemCall)(sqlite3_vfs*, const char *zName);
|
|
|
|
|
|
|
|
|
|
|
|
};
|
|
# 1523 "./sqlite3.h"
|
|
int sqlite3_initialize(void);
|
|
int sqlite3_shutdown(void);
|
|
int sqlite3_os_init(void);
|
|
int sqlite3_os_end(void);
|
|
# 1559 "./sqlite3.h"
|
|
int sqlite3_config(int, ...);
|
|
# 1578 "./sqlite3.h"
|
|
int sqlite3_db_config(sqlite3*, int op, ...);
|
|
# 1643 "./sqlite3.h"
|
|
typedef struct sqlite3_mem_methods sqlite3_mem_methods;
|
|
struct sqlite3_mem_methods {
|
|
void *(*xMalloc)(int);
|
|
void (*xFree)(void*);
|
|
void *(*xRealloc)(void*,int);
|
|
int (*xSize)(void*);
|
|
int (*xRoundup)(int);
|
|
int (*xInit)(void*);
|
|
void (*xShutdown)(void*);
|
|
void *pAppData;
|
|
};
|
|
# 2278 "./sqlite3.h"
|
|
int sqlite3_extended_result_codes(sqlite3*, int onoff);
|
|
# 2340 "./sqlite3.h"
|
|
sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
|
|
# 2350 "./sqlite3.h"
|
|
void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64);
|
|
# 2408 "./sqlite3.h"
|
|
int sqlite3_changes(sqlite3*);
|
|
# 2445 "./sqlite3.h"
|
|
int sqlite3_total_changes(sqlite3*);
|
|
# 2482 "./sqlite3.h"
|
|
void sqlite3_interrupt(sqlite3*);
|
|
# 2517 "./sqlite3.h"
|
|
int sqlite3_complete(const char *sql);
|
|
int sqlite3_complete16(const void *sql);
|
|
# 2579 "./sqlite3.h"
|
|
int sqlite3_busy_handler(sqlite3*,int(*)(void*,int),void*);
|
|
# 2602 "./sqlite3.h"
|
|
int sqlite3_busy_timeout(sqlite3*, int ms);
|
|
# 2677 "./sqlite3.h"
|
|
int sqlite3_get_table(
|
|
sqlite3 *db,
|
|
const char *zSql,
|
|
char ***pazResult,
|
|
int *pnRow,
|
|
int *pnColumn,
|
|
char **pzErrmsg
|
|
);
|
|
void sqlite3_free_table(char **result);
|
|
# 2727 "./sqlite3.h"
|
|
char *sqlite3_mprintf(const char*,...);
|
|
char *sqlite3_vmprintf(const char*, va_list);
|
|
char *sqlite3_snprintf(int,char*,const char*, ...);
|
|
char *sqlite3_vsnprintf(int,char*,const char*, va_list);
|
|
# 2820 "./sqlite3.h"
|
|
void *sqlite3_malloc(int);
|
|
void *sqlite3_malloc64(sqlite3_uint64);
|
|
void *sqlite3_realloc(void*, int);
|
|
void *sqlite3_realloc64(void*, sqlite3_uint64);
|
|
void sqlite3_free(void*);
|
|
sqlite3_uint64 sqlite3_msize(void*);
|
|
# 2850 "./sqlite3.h"
|
|
sqlite3_int64 sqlite3_memory_used(void);
|
|
sqlite3_int64 sqlite3_memory_highwater(int resetFlag);
|
|
# 2874 "./sqlite3.h"
|
|
void sqlite3_randomness(int N, void *P);
|
|
# 2965 "./sqlite3.h"
|
|
int sqlite3_set_authorizer(
|
|
sqlite3*,
|
|
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
|
|
void *pUserData
|
|
);
|
|
# 3073 "./sqlite3.h"
|
|
void *sqlite3_trace(sqlite3*,
|
|
void(*xTrace)(void*,const char*), void*);
|
|
void *sqlite3_profile(sqlite3*,
|
|
void(*xProfile)(void*,const char*,sqlite3_uint64), void*);
|
|
# 3164 "./sqlite3.h"
|
|
int sqlite3_trace_v2(
|
|
sqlite3*,
|
|
unsigned uMask,
|
|
int(*xCallback)(unsigned,void*,void*,void*),
|
|
void *pCtx
|
|
);
|
|
# 3203 "./sqlite3.h"
|
|
void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
|
|
# 3432 "./sqlite3.h"
|
|
int sqlite3_open(
|
|
const char *filename,
|
|
sqlite3 **ppDb
|
|
);
|
|
int sqlite3_open16(
|
|
const void *filename,
|
|
sqlite3 **ppDb
|
|
);
|
|
int sqlite3_open_v2(
|
|
const char *filename,
|
|
sqlite3 **ppDb,
|
|
int flags,
|
|
const char *zVfs
|
|
);
|
|
# 3488 "./sqlite3.h"
|
|
const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
|
|
int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault);
|
|
sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64);
|
|
# 3545 "./sqlite3.h"
|
|
int sqlite3_errcode(sqlite3 *db);
|
|
int sqlite3_extended_errcode(sqlite3 *db);
|
|
const char *sqlite3_errmsg(sqlite3*);
|
|
const void *sqlite3_errmsg16(sqlite3*);
|
|
const char *sqlite3_errstr(int);
|
|
# 3575 "./sqlite3.h"
|
|
typedef struct sqlite3_stmt sqlite3_stmt;
|
|
# 3617 "./sqlite3.h"
|
|
int sqlite3_limit(sqlite3*, int id, int newVal);
|
|
# 3827 "./sqlite3.h"
|
|
int sqlite3_prepare(
|
|
sqlite3 *db,
|
|
const char *zSql,
|
|
int nByte,
|
|
sqlite3_stmt **ppStmt,
|
|
const char **pzTail
|
|
);
|
|
int sqlite3_prepare_v2(
|
|
sqlite3 *db,
|
|
const char *zSql,
|
|
int nByte,
|
|
sqlite3_stmt **ppStmt,
|
|
const char **pzTail
|
|
);
|
|
int sqlite3_prepare_v3(
|
|
sqlite3 *db,
|
|
const char *zSql,
|
|
int nByte,
|
|
unsigned int prepFlags,
|
|
sqlite3_stmt **ppStmt,
|
|
const char **pzTail
|
|
);
|
|
int sqlite3_prepare16(
|
|
sqlite3 *db,
|
|
const void *zSql,
|
|
int nByte,
|
|
sqlite3_stmt **ppStmt,
|
|
const void **pzTail
|
|
);
|
|
int sqlite3_prepare16_v2(
|
|
sqlite3 *db,
|
|
const void *zSql,
|
|
int nByte,
|
|
sqlite3_stmt **ppStmt,
|
|
const void **pzTail
|
|
);
|
|
int sqlite3_prepare16_v3(
|
|
sqlite3 *db,
|
|
const void *zSql,
|
|
int nByte,
|
|
unsigned int prepFlags,
|
|
sqlite3_stmt **ppStmt,
|
|
const void **pzTail
|
|
);
|
|
# 3910 "./sqlite3.h"
|
|
const char *sqlite3_sql(sqlite3_stmt *pStmt);
|
|
char *sqlite3_expanded_sql(sqlite3_stmt *pStmt);
|
|
const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt);
|
|
# 3948 "./sqlite3.h"
|
|
int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
|
|
# 3960 "./sqlite3.h"
|
|
int sqlite3_stmt_isexplain(sqlite3_stmt *pStmt);
|
|
# 3981 "./sqlite3.h"
|
|
int sqlite3_stmt_busy(sqlite3_stmt*);
|
|
# 4023 "./sqlite3.h"
|
|
typedef struct sqlite3_value sqlite3_value;
|
|
# 4037 "./sqlite3.h"
|
|
typedef struct sqlite3_context sqlite3_context;
|
|
# 4157 "./sqlite3.h"
|
|
int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
|
|
int sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64,
|
|
void(*)(void*));
|
|
int sqlite3_bind_double(sqlite3_stmt*, int, double);
|
|
int sqlite3_bind_int(sqlite3_stmt*, int, int);
|
|
int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
|
|
int sqlite3_bind_null(sqlite3_stmt*, int);
|
|
int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*));
|
|
int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
|
|
int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64,
|
|
void(*)(void*), unsigned char encoding);
|
|
int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
|
|
int sqlite3_bind_pointer(sqlite3_stmt*, int, void*, const char*,void(*)(void*));
|
|
int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
|
|
int sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64);
|
|
# 4192 "./sqlite3.h"
|
|
int sqlite3_bind_parameter_count(sqlite3_stmt*);
|
|
# 4220 "./sqlite3.h"
|
|
const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);
|
|
# 4238 "./sqlite3.h"
|
|
int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName);
|
|
# 4248 "./sqlite3.h"
|
|
int sqlite3_clear_bindings(sqlite3_stmt*);
|
|
# 4264 "./sqlite3.h"
|
|
int sqlite3_column_count(sqlite3_stmt *pStmt);
|
|
# 4293 "./sqlite3.h"
|
|
const char *sqlite3_column_name(sqlite3_stmt*, int N);
|
|
const void *sqlite3_column_name16(sqlite3_stmt*, int N);
|
|
# 4342 "./sqlite3.h"
|
|
const char *sqlite3_column_database_name(sqlite3_stmt*,int);
|
|
const void *sqlite3_column_database_name16(sqlite3_stmt*,int);
|
|
const char *sqlite3_column_table_name(sqlite3_stmt*,int);
|
|
const void *sqlite3_column_table_name16(sqlite3_stmt*,int);
|
|
const char *sqlite3_column_origin_name(sqlite3_stmt*,int);
|
|
const void *sqlite3_column_origin_name16(sqlite3_stmt*,int);
|
|
# 4379 "./sqlite3.h"
|
|
const char *sqlite3_column_decltype(sqlite3_stmt*,int);
|
|
const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
|
|
# 4464 "./sqlite3.h"
|
|
int sqlite3_step(sqlite3_stmt*);
|
|
# 4485 "./sqlite3.h"
|
|
int sqlite3_data_count(sqlite3_stmt *pStmt);
|
|
# 4728 "./sqlite3.h"
|
|
const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
|
|
double sqlite3_column_double(sqlite3_stmt*, int iCol);
|
|
int sqlite3_column_int(sqlite3_stmt*, int iCol);
|
|
sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);
|
|
const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
|
|
const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);
|
|
sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
|
|
int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
|
|
int sqlite3_column_bytes16(sqlite3_stmt*, int iCol);
|
|
int sqlite3_column_type(sqlite3_stmt*, int iCol);
|
|
# 4765 "./sqlite3.h"
|
|
int sqlite3_finalize(sqlite3_stmt *pStmt);
|
|
# 4792 "./sqlite3.h"
|
|
int sqlite3_reset(sqlite3_stmt *pStmt);
|
|
# 4904 "./sqlite3.h"
|
|
int sqlite3_create_function(
|
|
sqlite3 *db,
|
|
const char *zFunctionName,
|
|
int nArg,
|
|
int eTextRep,
|
|
void *pApp,
|
|
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
|
|
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
|
void (*xFinal)(sqlite3_context*)
|
|
);
|
|
int sqlite3_create_function16(
|
|
sqlite3 *db,
|
|
const void *zFunctionName,
|
|
int nArg,
|
|
int eTextRep,
|
|
void *pApp,
|
|
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
|
|
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
|
void (*xFinal)(sqlite3_context*)
|
|
);
|
|
int sqlite3_create_function_v2(
|
|
sqlite3 *db,
|
|
const char *zFunctionName,
|
|
int nArg,
|
|
int eTextRep,
|
|
void *pApp,
|
|
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
|
|
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
|
void (*xFinal)(sqlite3_context*),
|
|
void(*xDestroy)(void*)
|
|
);
|
|
int sqlite3_create_window_function(
|
|
sqlite3 *db,
|
|
const char *zFunctionName,
|
|
int nArg,
|
|
int eTextRep,
|
|
void *pApp,
|
|
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
|
|
void (*xFinal)(sqlite3_context*),
|
|
void (*xValue)(sqlite3_context*),
|
|
void (*xInverse)(sqlite3_context*,int,sqlite3_value**),
|
|
void(*xDestroy)(void*)
|
|
);
|
|
# 4982 "./sqlite3.h"
|
|
int sqlite3_aggregate_count(sqlite3_context*);
|
|
int sqlite3_expired(sqlite3_stmt*);
|
|
int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
|
|
int sqlite3_global_recover(void);
|
|
void sqlite3_thread_cleanup(void);
|
|
int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),
|
|
void*,sqlite3_int64);
|
|
# 5119 "./sqlite3.h"
|
|
const void *sqlite3_value_blob(sqlite3_value*);
|
|
double sqlite3_value_double(sqlite3_value*);
|
|
int sqlite3_value_int(sqlite3_value*);
|
|
sqlite3_int64 sqlite3_value_int64(sqlite3_value*);
|
|
void *sqlite3_value_pointer(sqlite3_value*, const char*);
|
|
const unsigned char *sqlite3_value_text(sqlite3_value*);
|
|
const void *sqlite3_value_text16(sqlite3_value*);
|
|
const void *sqlite3_value_text16le(sqlite3_value*);
|
|
const void *sqlite3_value_text16be(sqlite3_value*);
|
|
int sqlite3_value_bytes(sqlite3_value*);
|
|
int sqlite3_value_bytes16(sqlite3_value*);
|
|
int sqlite3_value_type(sqlite3_value*);
|
|
int sqlite3_value_numeric_type(sqlite3_value*);
|
|
int sqlite3_value_nochange(sqlite3_value*);
|
|
int sqlite3_value_frombind(sqlite3_value*);
|
|
# 5145 "./sqlite3.h"
|
|
unsigned int sqlite3_value_subtype(sqlite3_value*);
|
|
# 5161 "./sqlite3.h"
|
|
sqlite3_value *sqlite3_value_dup(const sqlite3_value*);
|
|
void sqlite3_value_free(sqlite3_value*);
|
|
# 5207 "./sqlite3.h"
|
|
void *sqlite3_aggregate_context(sqlite3_context*, int nBytes);
|
|
# 5222 "./sqlite3.h"
|
|
void *sqlite3_user_data(sqlite3_context*);
|
|
# 5234 "./sqlite3.h"
|
|
sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
|
|
# 5293 "./sqlite3.h"
|
|
void *sqlite3_get_auxdata(sqlite3_context*, int N);
|
|
void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*));
|
|
# 5311 "./sqlite3.h"
|
|
typedef void (*sqlite3_destructor_type)(void*);
|
|
# 5441 "./sqlite3.h"
|
|
void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
|
|
void sqlite3_result_blob64(sqlite3_context*,const void*,
|
|
sqlite3_uint64,void(*)(void*));
|
|
void sqlite3_result_double(sqlite3_context*, double);
|
|
void sqlite3_result_error(sqlite3_context*, const char*, int);
|
|
void sqlite3_result_error16(sqlite3_context*, const void*, int);
|
|
void sqlite3_result_error_toobig(sqlite3_context*);
|
|
void sqlite3_result_error_nomem(sqlite3_context*);
|
|
void sqlite3_result_error_code(sqlite3_context*, int);
|
|
void sqlite3_result_int(sqlite3_context*, int);
|
|
void sqlite3_result_int64(sqlite3_context*, sqlite3_int64);
|
|
void sqlite3_result_null(sqlite3_context*);
|
|
void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
|
|
void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64,
|
|
void(*)(void*), unsigned char encoding);
|
|
void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
|
|
void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
|
|
void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
|
|
void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
|
|
void sqlite3_result_pointer(sqlite3_context*, void*,const char*,void(*)(void*));
|
|
void sqlite3_result_zeroblob(sqlite3_context*, int n);
|
|
int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n);
|
|
# 5477 "./sqlite3.h"
|
|
void sqlite3_result_subtype(sqlite3_context*,unsigned int);
|
|
# 5559 "./sqlite3.h"
|
|
int sqlite3_create_collation(
|
|
sqlite3*,
|
|
const char *zName,
|
|
int eTextRep,
|
|
void *pArg,
|
|
int(*xCompare)(void*,int,const void*,int,const void*)
|
|
);
|
|
int sqlite3_create_collation_v2(
|
|
sqlite3*,
|
|
const char *zName,
|
|
int eTextRep,
|
|
void *pArg,
|
|
int(*xCompare)(void*,int,const void*,int,const void*),
|
|
void(*xDestroy)(void*)
|
|
);
|
|
int sqlite3_create_collation16(
|
|
sqlite3*,
|
|
const void *zName,
|
|
int eTextRep,
|
|
void *pArg,
|
|
int(*xCompare)(void*,int,const void*,int,const void*)
|
|
);
|
|
# 5609 "./sqlite3.h"
|
|
int sqlite3_collation_needed(
|
|
sqlite3*,
|
|
void*,
|
|
void(*)(void*,sqlite3*,int eTextRep,const char*)
|
|
);
|
|
int sqlite3_collation_needed16(
|
|
sqlite3*,
|
|
void*,
|
|
void(*)(void*,sqlite3*,int eTextRep,const void*)
|
|
);
|
|
# 5692 "./sqlite3.h"
|
|
int sqlite3_sleep(int);
|
|
# 5750 "./sqlite3.h"
|
|
extern char *sqlite3_temp_directory;
|
|
# 5787 "./sqlite3.h"
|
|
extern char *sqlite3_data_directory;
|
|
# 5808 "./sqlite3.h"
|
|
int sqlite3_win32_set_directory(
|
|
unsigned long type,
|
|
void *zValue
|
|
);
|
|
int sqlite3_win32_set_directory8(unsigned long type, const char *zValue);
|
|
int sqlite3_win32_set_directory16(unsigned long type, const void *zValue);
|
|
# 5846 "./sqlite3.h"
|
|
int sqlite3_get_autocommit(sqlite3*);
|
|
# 5859 "./sqlite3.h"
|
|
sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
|
|
# 5876 "./sqlite3.h"
|
|
const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
|
|
# 5886 "./sqlite3.h"
|
|
int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
|
|
# 5902 "./sqlite3.h"
|
|
sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt);
|
|
# 5951 "./sqlite3.h"
|
|
void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*);
|
|
void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
|
|
# 6003 "./sqlite3.h"
|
|
void *sqlite3_update_hook(
|
|
sqlite3*,
|
|
void(*)(void *,int ,char const *,char const *,sqlite3_int64),
|
|
void*
|
|
);
|
|
# 6044 "./sqlite3.h"
|
|
int sqlite3_enable_shared_cache(int);
|
|
# 6060 "./sqlite3.h"
|
|
int sqlite3_release_memory(int);
|
|
# 6074 "./sqlite3.h"
|
|
int sqlite3_db_release_memory(sqlite3*);
|
|
# 6127 "./sqlite3.h"
|
|
sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N);
|
|
# 6138 "./sqlite3.h"
|
|
void sqlite3_soft_heap_limit(int N);
|
|
# 6210 "./sqlite3.h"
|
|
int sqlite3_table_column_metadata(
|
|
sqlite3 *db,
|
|
const char *zDbName,
|
|
const char *zTableName,
|
|
const char *zColumnName,
|
|
char const **pzDataType,
|
|
char const **pzCollSeq,
|
|
int *pNotNull,
|
|
int *pPrimaryKey,
|
|
int *pAutoinc
|
|
);
|
|
# 6266 "./sqlite3.h"
|
|
int sqlite3_load_extension(
|
|
sqlite3 *db,
|
|
const char *zFile,
|
|
const char *zProc,
|
|
char **pzErrMsg
|
|
);
|
|
# 6298 "./sqlite3.h"
|
|
int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
|
|
# 6336 "./sqlite3.h"
|
|
int sqlite3_auto_extension(void(*xEntryPoint)(void));
|
|
# 6348 "./sqlite3.h"
|
|
int sqlite3_cancel_auto_extension(void(*xEntryPoint)(void));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void sqlite3_reset_auto_extension(void);
|
|
# 6370 "./sqlite3.h"
|
|
typedef struct sqlite3_vtab sqlite3_vtab;
|
|
typedef struct sqlite3_index_info sqlite3_index_info;
|
|
typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor;
|
|
typedef struct sqlite3_module sqlite3_module;
|
|
# 6391 "./sqlite3.h"
|
|
struct sqlite3_module {
|
|
int iVersion;
|
|
int (*xCreate)(sqlite3*, void *pAux,
|
|
int argc, const char *const*argv,
|
|
sqlite3_vtab **ppVTab, char**);
|
|
int (*xConnect)(sqlite3*, void *pAux,
|
|
int argc, const char *const*argv,
|
|
sqlite3_vtab **ppVTab, char**);
|
|
int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*);
|
|
int (*xDisconnect)(sqlite3_vtab *pVTab);
|
|
int (*xDestroy)(sqlite3_vtab *pVTab);
|
|
int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor);
|
|
int (*xClose)(sqlite3_vtab_cursor*);
|
|
int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr,
|
|
int argc, sqlite3_value **argv);
|
|
int (*xNext)(sqlite3_vtab_cursor*);
|
|
int (*xEof)(sqlite3_vtab_cursor*);
|
|
int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int);
|
|
int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid);
|
|
int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *);
|
|
int (*xBegin)(sqlite3_vtab *pVTab);
|
|
int (*xSync)(sqlite3_vtab *pVTab);
|
|
int (*xCommit)(sqlite3_vtab *pVTab);
|
|
int (*xRollback)(sqlite3_vtab *pVTab);
|
|
int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName,
|
|
void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
|
|
void **ppArg);
|
|
int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
|
|
|
|
|
|
int (*xSavepoint)(sqlite3_vtab *pVTab, int);
|
|
int (*xRelease)(sqlite3_vtab *pVTab, int);
|
|
int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
|
|
|
|
|
|
int (*xShadowName)(const char*);
|
|
};
|
|
# 6525 "./sqlite3.h"
|
|
struct sqlite3_index_info {
|
|
|
|
int nConstraint;
|
|
struct sqlite3_index_constraint {
|
|
int iColumn;
|
|
unsigned char op;
|
|
unsigned char usable;
|
|
int iTermOffset;
|
|
} *aConstraint;
|
|
int nOrderBy;
|
|
struct sqlite3_index_orderby {
|
|
int iColumn;
|
|
unsigned char desc;
|
|
} *aOrderBy;
|
|
|
|
struct sqlite3_index_constraint_usage {
|
|
int argvIndex;
|
|
unsigned char omit;
|
|
} *aConstraintUsage;
|
|
int idxNum;
|
|
char *idxStr;
|
|
int needToFreeIdxStr;
|
|
int orderByConsumed;
|
|
double estimatedCost;
|
|
|
|
sqlite3_int64 estimatedRows;
|
|
|
|
int idxFlags;
|
|
|
|
sqlite3_uint64 colUsed;
|
|
};
|
|
# 6616 "./sqlite3.h"
|
|
int sqlite3_create_module(
|
|
sqlite3 *db,
|
|
const char *zName,
|
|
const sqlite3_module *p,
|
|
void *pClientData
|
|
);
|
|
int sqlite3_create_module_v2(
|
|
sqlite3 *db,
|
|
const char *zName,
|
|
const sqlite3_module *p,
|
|
void *pClientData,
|
|
void(*xDestroy)(void*)
|
|
);
|
|
# 6648 "./sqlite3.h"
|
|
struct sqlite3_vtab {
|
|
const sqlite3_module *pModule;
|
|
int nRef;
|
|
char *zErrMsg;
|
|
|
|
};
|
|
# 6672 "./sqlite3.h"
|
|
struct sqlite3_vtab_cursor {
|
|
sqlite3_vtab *pVtab;
|
|
|
|
};
|
|
# 6685 "./sqlite3.h"
|
|
int sqlite3_declare_vtab(sqlite3*, const char *zSQL);
|
|
# 6704 "./sqlite3.h"
|
|
int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
|
|
# 6728 "./sqlite3.h"
|
|
typedef struct sqlite3_blob sqlite3_blob;
|
|
# 6813 "./sqlite3.h"
|
|
int sqlite3_blob_open(
|
|
sqlite3*,
|
|
const char *zDb,
|
|
const char *zTable,
|
|
const char *zColumn,
|
|
sqlite3_int64 iRow,
|
|
int flags,
|
|
sqlite3_blob **ppBlob
|
|
);
|
|
# 6846 "./sqlite3.h"
|
|
int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64);
|
|
# 6869 "./sqlite3.h"
|
|
int sqlite3_blob_close(sqlite3_blob *);
|
|
# 6885 "./sqlite3.h"
|
|
int sqlite3_blob_bytes(sqlite3_blob *);
|
|
# 6914 "./sqlite3.h"
|
|
int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset);
|
|
# 6956 "./sqlite3.h"
|
|
int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset);
|
|
# 6987 "./sqlite3.h"
|
|
sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName);
|
|
int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt);
|
|
int sqlite3_vfs_unregister(sqlite3_vfs*);
|
|
# 7105 "./sqlite3.h"
|
|
sqlite3_mutex *sqlite3_mutex_alloc(int);
|
|
void sqlite3_mutex_free(sqlite3_mutex*);
|
|
void sqlite3_mutex_enter(sqlite3_mutex*);
|
|
int sqlite3_mutex_try(sqlite3_mutex*);
|
|
void sqlite3_mutex_leave(sqlite3_mutex*);
|
|
# 7176 "./sqlite3.h"
|
|
typedef struct sqlite3_mutex_methods sqlite3_mutex_methods;
|
|
struct sqlite3_mutex_methods {
|
|
int (*xMutexInit)(void);
|
|
int (*xMutexEnd)(void);
|
|
sqlite3_mutex *(*xMutexAlloc)(int);
|
|
void (*xMutexFree)(sqlite3_mutex *);
|
|
void (*xMutexEnter)(sqlite3_mutex *);
|
|
int (*xMutexTry)(sqlite3_mutex *);
|
|
void (*xMutexLeave)(sqlite3_mutex *);
|
|
int (*xMutexHeld)(sqlite3_mutex *);
|
|
int (*xMutexNotheld)(sqlite3_mutex *);
|
|
};
|
|
# 7219 "./sqlite3.h"
|
|
int sqlite3_mutex_held(sqlite3_mutex*);
|
|
int sqlite3_mutex_notheld(sqlite3_mutex*);
|
|
# 7260 "./sqlite3.h"
|
|
sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
|
|
# 7303 "./sqlite3.h"
|
|
int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*);
|
|
# 7322 "./sqlite3.h"
|
|
int sqlite3_test_control(int op, ...);
|
|
# 7410 "./sqlite3.h"
|
|
int sqlite3_keyword_count(void);
|
|
int sqlite3_keyword_name(int,const char**,int*);
|
|
int sqlite3_keyword_check(const char*,int);
|
|
# 7430 "./sqlite3.h"
|
|
typedef struct sqlite3_str sqlite3_str;
|
|
# 7457 "./sqlite3.h"
|
|
sqlite3_str *sqlite3_str_new(sqlite3*);
|
|
# 7472 "./sqlite3.h"
|
|
char *sqlite3_str_finish(sqlite3_str*);
|
|
# 7506 "./sqlite3.h"
|
|
void sqlite3_str_appendf(sqlite3_str*, const char *zFormat, ...);
|
|
void sqlite3_str_vappendf(sqlite3_str*, const char *zFormat, va_list);
|
|
void sqlite3_str_append(sqlite3_str*, const char *zIn, int N);
|
|
void sqlite3_str_appendall(sqlite3_str*, const char *zIn);
|
|
void sqlite3_str_appendchar(sqlite3_str*, int N, char C);
|
|
void sqlite3_str_reset(sqlite3_str*);
|
|
# 7542 "./sqlite3.h"
|
|
int sqlite3_str_errcode(sqlite3_str*);
|
|
int sqlite3_str_length(sqlite3_str*);
|
|
char *sqlite3_str_value(sqlite3_str*);
|
|
# 7572 "./sqlite3.h"
|
|
int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
|
|
int sqlite3_status64(
|
|
int op,
|
|
sqlite3_int64 *pCurrent,
|
|
sqlite3_int64 *pHighwater,
|
|
int resetFlag
|
|
);
|
|
# 7682 "./sqlite3.h"
|
|
int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
|
|
# 7835 "./sqlite3.h"
|
|
int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
|
|
# 7911 "./sqlite3.h"
|
|
typedef struct sqlite3_pcache sqlite3_pcache;
|
|
# 7923 "./sqlite3.h"
|
|
typedef struct sqlite3_pcache_page sqlite3_pcache_page;
|
|
struct sqlite3_pcache_page {
|
|
void *pBuf;
|
|
void *pExtra;
|
|
};
|
|
# 8088 "./sqlite3.h"
|
|
typedef struct sqlite3_pcache_methods2 sqlite3_pcache_methods2;
|
|
struct sqlite3_pcache_methods2 {
|
|
int iVersion;
|
|
void *pArg;
|
|
int (*xInit)(void*);
|
|
void (*xShutdown)(void*);
|
|
sqlite3_pcache *(*xCreate)(int szPage, int szExtra, int bPurgeable);
|
|
void (*xCachesize)(sqlite3_pcache*, int nCachesize);
|
|
int (*xPagecount)(sqlite3_pcache*);
|
|
sqlite3_pcache_page *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag);
|
|
void (*xUnpin)(sqlite3_pcache*, sqlite3_pcache_page*, int discard);
|
|
void (*xRekey)(sqlite3_pcache*, sqlite3_pcache_page*,
|
|
unsigned oldKey, unsigned newKey);
|
|
void (*xTruncate)(sqlite3_pcache*, unsigned iLimit);
|
|
void (*xDestroy)(sqlite3_pcache*);
|
|
void (*xShrink)(sqlite3_pcache*);
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct sqlite3_pcache_methods sqlite3_pcache_methods;
|
|
struct sqlite3_pcache_methods {
|
|
void *pArg;
|
|
int (*xInit)(void*);
|
|
void (*xShutdown)(void*);
|
|
sqlite3_pcache *(*xCreate)(int szPage, int bPurgeable);
|
|
void (*xCachesize)(sqlite3_pcache*, int nCachesize);
|
|
int (*xPagecount)(sqlite3_pcache*);
|
|
void *(*xFetch)(sqlite3_pcache*, unsigned key, int createFlag);
|
|
void (*xUnpin)(sqlite3_pcache*, void*, int discard);
|
|
void (*xRekey)(sqlite3_pcache*, void*, unsigned oldKey, unsigned newKey);
|
|
void (*xTruncate)(sqlite3_pcache*, unsigned iLimit);
|
|
void (*xDestroy)(sqlite3_pcache*);
|
|
};
|
|
# 8137 "./sqlite3.h"
|
|
typedef struct sqlite3_backup sqlite3_backup;
|
|
# 8325 "./sqlite3.h"
|
|
sqlite3_backup *sqlite3_backup_init(
|
|
sqlite3 *pDest,
|
|
const char *zDestName,
|
|
sqlite3 *pSource,
|
|
const char *zSourceName
|
|
);
|
|
int sqlite3_backup_step(sqlite3_backup *p, int nPage);
|
|
int sqlite3_backup_finish(sqlite3_backup *p);
|
|
int sqlite3_backup_remaining(sqlite3_backup *p);
|
|
int sqlite3_backup_pagecount(sqlite3_backup *p);
|
|
# 8451 "./sqlite3.h"
|
|
int sqlite3_unlock_notify(
|
|
sqlite3 *pBlocked,
|
|
void (*xNotify)(void **apArg, int nArg),
|
|
void *pNotifyArg
|
|
);
|
|
# 8466 "./sqlite3.h"
|
|
int sqlite3_stricmp(const char *, const char *);
|
|
int sqlite3_strnicmp(const char *, const char *, int);
|
|
# 8484 "./sqlite3.h"
|
|
int sqlite3_strglob(const char *zGlob, const char *zStr);
|
|
# 8507 "./sqlite3.h"
|
|
int sqlite3_strlike(const char *zGlob, const char *zStr, unsigned int cEsc);
|
|
# 8530 "./sqlite3.h"
|
|
void sqlite3_log(int iErrCode, const char *zFormat, ...);
|
|
# 8566 "./sqlite3.h"
|
|
void *sqlite3_wal_hook(
|
|
sqlite3*,
|
|
int(*)(void *,sqlite3*,const char*,int),
|
|
void*
|
|
);
|
|
# 8601 "./sqlite3.h"
|
|
int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
|
|
# 8623 "./sqlite3.h"
|
|
int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
|
|
# 8717 "./sqlite3.h"
|
|
int sqlite3_wal_checkpoint_v2(
|
|
sqlite3 *db,
|
|
const char *zDb,
|
|
int eMode,
|
|
int *pnLog,
|
|
int *pnCkpt
|
|
);
|
|
# 8753 "./sqlite3.h"
|
|
int sqlite3_vtab_config(sqlite3*, int op, ...);
|
|
# 8807 "./sqlite3.h"
|
|
int sqlite3_vtab_on_conflict(sqlite3 *);
|
|
# 8826 "./sqlite3.h"
|
|
int sqlite3_vtab_nochange(sqlite3_context*);
|
|
# 8841 "./sqlite3.h"
|
|
const char *sqlite3_vtab_collation(sqlite3_index_info*,int);
|
|
# 8946 "./sqlite3.h"
|
|
int sqlite3_stmt_scanstatus(
|
|
sqlite3_stmt *pStmt,
|
|
int idx,
|
|
int iScanStatusOp,
|
|
void *pOut
|
|
);
|
|
# 8962 "./sqlite3.h"
|
|
void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
|
|
# 8994 "./sqlite3.h"
|
|
int sqlite3_db_cacheflush(sqlite3*);
|
|
# 9108 "./sqlite3.h"
|
|
int sqlite3_system_errno(sqlite3*);
|
|
# 9130 "./sqlite3.h"
|
|
typedef struct sqlite3_snapshot {
|
|
unsigned char hidden[48];
|
|
} sqlite3_snapshot;
|
|
# 9177 "./sqlite3.h"
|
|
int sqlite3_snapshot_get(
|
|
sqlite3 *db,
|
|
const char *zSchema,
|
|
sqlite3_snapshot **ppSnapshot
|
|
);
|
|
# 9226 "./sqlite3.h"
|
|
int sqlite3_snapshot_open(
|
|
sqlite3 *db,
|
|
const char *zSchema,
|
|
sqlite3_snapshot *pSnapshot
|
|
);
|
|
# 9243 "./sqlite3.h"
|
|
void sqlite3_snapshot_free(sqlite3_snapshot*);
|
|
# 9270 "./sqlite3.h"
|
|
int sqlite3_snapshot_cmp(
|
|
sqlite3_snapshot *p1,
|
|
sqlite3_snapshot *p2
|
|
);
|
|
# 9298 "./sqlite3.h"
|
|
int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);
|
|
# 9336 "./sqlite3.h"
|
|
unsigned char *sqlite3_serialize(
|
|
sqlite3 *db,
|
|
const char *zSchema,
|
|
sqlite3_int64 *piSize,
|
|
unsigned int mFlags
|
|
);
|
|
# 9388 "./sqlite3.h"
|
|
int sqlite3_deserialize(
|
|
sqlite3 *db,
|
|
const char *zSchema,
|
|
unsigned char *pData,
|
|
sqlite3_int64 szDb,
|
|
sqlite3_int64 szBuf,
|
|
unsigned mFlags
|
|
);
|
|
# 9457 "./sqlite3.h"
|
|
typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry;
|
|
typedef struct sqlite3_rtree_query_info sqlite3_rtree_query_info;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef double sqlite3_rtree_dbl;
|
|
# 9475 "./sqlite3.h"
|
|
int sqlite3_rtree_geometry_callback(
|
|
sqlite3 *db,
|
|
const char *zGeom,
|
|
int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*),
|
|
void *pContext
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct sqlite3_rtree_geometry {
|
|
void *pContext;
|
|
int nParam;
|
|
sqlite3_rtree_dbl *aParam;
|
|
void *pUser;
|
|
void (*xDelUser)(void *);
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int sqlite3_rtree_query_callback(
|
|
sqlite3 *db,
|
|
const char *zQueryFunc,
|
|
int (*xQueryFunc)(sqlite3_rtree_query_info*),
|
|
void *pContext,
|
|
void (*xDestructor)(void*)
|
|
);
|
|
# 9519 "./sqlite3.h"
|
|
struct sqlite3_rtree_query_info {
|
|
void *pContext;
|
|
int nParam;
|
|
sqlite3_rtree_dbl *aParam;
|
|
void *pUser;
|
|
void (*xDelUser)(void*);
|
|
sqlite3_rtree_dbl *aCoord;
|
|
unsigned int *anQueue;
|
|
int nCoord;
|
|
int iLevel;
|
|
int mxLevel;
|
|
sqlite3_int64 iRowid;
|
|
sqlite3_rtree_dbl rParentScore;
|
|
int eParentWithin;
|
|
int eWithin;
|
|
sqlite3_rtree_dbl rScore;
|
|
|
|
sqlite3_value **apSqlParam;
|
|
};
|
|
# 11252 "./sqlite3.h"
|
|
typedef struct Fts5ExtensionApi Fts5ExtensionApi;
|
|
typedef struct Fts5Context Fts5Context;
|
|
typedef struct Fts5PhraseIter Fts5PhraseIter;
|
|
|
|
typedef void (*fts5_extension_function)(
|
|
const Fts5ExtensionApi *pApi,
|
|
Fts5Context *pFts,
|
|
sqlite3_context *pCtx,
|
|
int nVal,
|
|
sqlite3_value **apVal
|
|
);
|
|
|
|
struct Fts5PhraseIter {
|
|
const unsigned char *a;
|
|
const unsigned char *b;
|
|
};
|
|
# 11480 "./sqlite3.h"
|
|
struct Fts5ExtensionApi {
|
|
int iVersion;
|
|
|
|
void *(*xUserData)(Fts5Context*);
|
|
|
|
int (*xColumnCount)(Fts5Context*);
|
|
int (*xRowCount)(Fts5Context*, sqlite3_int64 *pnRow);
|
|
int (*xColumnTotalSize)(Fts5Context*, int iCol, sqlite3_int64 *pnToken);
|
|
|
|
int (*xTokenize)(Fts5Context*,
|
|
const char *pText, int nText,
|
|
void *pCtx,
|
|
int (*xToken)(void*, int, const char*, int, int, int)
|
|
);
|
|
|
|
int (*xPhraseCount)(Fts5Context*);
|
|
int (*xPhraseSize)(Fts5Context*, int iPhrase);
|
|
|
|
int (*xInstCount)(Fts5Context*, int *pnInst);
|
|
int (*xInst)(Fts5Context*, int iIdx, int *piPhrase, int *piCol, int *piOff);
|
|
|
|
sqlite3_int64 (*xRowid)(Fts5Context*);
|
|
int (*xColumnText)(Fts5Context*, int iCol, const char **pz, int *pn);
|
|
int (*xColumnSize)(Fts5Context*, int iCol, int *pnToken);
|
|
|
|
int (*xQueryPhrase)(Fts5Context*, int iPhrase, void *pUserData,
|
|
int(*)(const Fts5ExtensionApi*,Fts5Context*,void*)
|
|
);
|
|
int (*xSetAuxdata)(Fts5Context*, void *pAux, void(*xDelete)(void*));
|
|
void *(*xGetAuxdata)(Fts5Context*, int bClear);
|
|
|
|
int (*xPhraseFirst)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*, int*);
|
|
void (*xPhraseNext)(Fts5Context*, Fts5PhraseIter*, int *piCol, int *piOff);
|
|
|
|
int (*xPhraseFirstColumn)(Fts5Context*, int iPhrase, Fts5PhraseIter*, int*);
|
|
void (*xPhraseNextColumn)(Fts5Context*, Fts5PhraseIter*, int *piCol);
|
|
};
|
|
# 11714 "./sqlite3.h"
|
|
typedef struct Fts5Tokenizer Fts5Tokenizer;
|
|
typedef struct fts5_tokenizer fts5_tokenizer;
|
|
struct fts5_tokenizer {
|
|
int (*xCreate)(void*, const char **azArg, int nArg, Fts5Tokenizer **ppOut);
|
|
void (*xDelete)(Fts5Tokenizer*);
|
|
int (*xTokenize)(Fts5Tokenizer*,
|
|
void *pCtx,
|
|
int flags,
|
|
const char *pText, int nText,
|
|
int (*xToken)(
|
|
void *pCtx,
|
|
int tflags,
|
|
const char *pToken,
|
|
int nToken,
|
|
int iStart,
|
|
int iEnd
|
|
)
|
|
);
|
|
};
|
|
# 11751 "./sqlite3.h"
|
|
typedef struct fts5_api fts5_api;
|
|
struct fts5_api {
|
|
int iVersion;
|
|
|
|
|
|
int (*xCreateTokenizer)(
|
|
fts5_api *pApi,
|
|
const char *zName,
|
|
void *pContext,
|
|
fts5_tokenizer *pTokenizer,
|
|
void (*xDestroy)(void*)
|
|
);
|
|
|
|
|
|
int (*xFindTokenizer)(
|
|
fts5_api *pApi,
|
|
const char *zName,
|
|
void **ppContext,
|
|
fts5_tokenizer *pTokenizer
|
|
);
|
|
|
|
|
|
int (*xCreateFunction)(
|
|
fts5_api *pApi,
|
|
const char *zName,
|
|
void *pContext,
|
|
fts5_extension_function xFunction,
|
|
void (*xDestroy)(void*)
|
|
);
|
|
};
|
|
# 168 "src/sqliteInt.h" 2
|
|
# 178 "src/sqliteInt.h"
|
|
# 1 "src/sqliteLimit.h" 1
|
|
# 179 "src/sqliteInt.h" 2
|
|
# 529 "src/sqliteInt.h"
|
|
# 1 "src/hash.h" 1
|
|
# 19 "src/hash.h"
|
|
typedef struct Hash Hash;
|
|
typedef struct HashElem HashElem;
|
|
# 43 "src/hash.h"
|
|
struct Hash {
|
|
unsigned int htsize;
|
|
unsigned int count;
|
|
HashElem *first;
|
|
struct _ht {
|
|
unsigned int count;
|
|
HashElem *chain;
|
|
} *ht;
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct HashElem {
|
|
HashElem *next, *prev;
|
|
void *data;
|
|
const char *pKey;
|
|
};
|
|
|
|
|
|
|
|
|
|
void sqlite3HashInit(Hash*);
|
|
void *sqlite3HashInsert(Hash*, const char *pKey, void *pData);
|
|
void *sqlite3HashFind(const Hash*, const char *pKey);
|
|
void sqlite3HashClear(Hash*);
|
|
# 530 "src/sqliteInt.h" 2
|
|
# 1 "./parse.h" 1
|
|
# 531 "src/sqliteInt.h" 2
|
|
# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdio.h" 1
|
|
# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
|
|
# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdio.h" 2
|
|
# 532 "src/sqliteInt.h" 2
|
|
# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdlib.h" 1
|
|
# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
|
|
# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdlib.h" 2
|
|
# 533 "src/sqliteInt.h" 2
|
|
# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/string.h" 1
|
|
# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
|
|
# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/string.h" 2
|
|
# 534 "src/sqliteInt.h" 2
|
|
# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/assert.h" 1
|
|
# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
|
|
# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/assert.h" 2
|
|
# 535 "src/sqliteInt.h" 2
|
|
# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stddef.h" 1
|
|
# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
|
|
# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stddef.h" 2
|
|
# 536 "src/sqliteInt.h" 2
|
|
# 734 "src/sqliteInt.h"
|
|
typedef sqlite_int64 i64;
|
|
typedef sqlite_uint64 u64;
|
|
typedef unsigned int u32;
|
|
typedef unsigned short int u16;
|
|
typedef short int i16;
|
|
typedef unsigned char u8;
|
|
typedef signed char i8;
|
|
# 759 "src/sqliteInt.h"
|
|
typedef u32 tRowcnt;
|
|
# 785 "src/sqliteInt.h"
|
|
typedef short int LogEst;
|
|
# 809 "src/sqliteInt.h"
|
|
typedef u64 uptr;
|
|
# 971 "src/sqliteInt.h"
|
|
typedef struct BusyHandler BusyHandler;
|
|
struct BusyHandler {
|
|
int (*xBusyHandler)(void *,int);
|
|
void *pBusyArg;
|
|
int nBusy;
|
|
u8 bExtraFileArg;
|
|
};
|
|
# 1066 "src/sqliteInt.h"
|
|
typedef struct AggInfo AggInfo;
|
|
typedef struct AuthContext AuthContext;
|
|
typedef struct AutoincInfo AutoincInfo;
|
|
typedef struct Bitvec Bitvec;
|
|
typedef struct CollSeq CollSeq;
|
|
typedef struct Column Column;
|
|
typedef struct Db Db;
|
|
typedef struct Schema Schema;
|
|
typedef struct Expr Expr;
|
|
typedef struct ExprList ExprList;
|
|
typedef struct FKey FKey;
|
|
typedef struct FuncDestructor FuncDestructor;
|
|
typedef struct FuncDef FuncDef;
|
|
typedef struct FuncDefHash FuncDefHash;
|
|
typedef struct IdList IdList;
|
|
typedef struct Index Index;
|
|
typedef struct IndexSample IndexSample;
|
|
typedef struct KeyClass KeyClass;
|
|
typedef struct KeyInfo KeyInfo;
|
|
typedef struct Lookaside Lookaside;
|
|
typedef struct LookasideSlot LookasideSlot;
|
|
typedef struct Module Module;
|
|
typedef struct NameContext NameContext;
|
|
typedef struct Parse Parse;
|
|
typedef struct PreUpdate PreUpdate;
|
|
typedef struct PrintfArguments PrintfArguments;
|
|
typedef struct RenameToken RenameToken;
|
|
typedef struct RowSet RowSet;
|
|
typedef struct Savepoint Savepoint;
|
|
typedef struct Select Select;
|
|
typedef struct SQLiteThread SQLiteThread;
|
|
typedef struct SelectDest SelectDest;
|
|
typedef struct SrcList SrcList;
|
|
typedef struct sqlite3_str StrAccum;
|
|
typedef struct Table Table;
|
|
typedef struct TableLock TableLock;
|
|
typedef struct Token Token;
|
|
typedef struct TreeView TreeView;
|
|
typedef struct Trigger Trigger;
|
|
typedef struct TriggerPrg TriggerPrg;
|
|
typedef struct TriggerStep TriggerStep;
|
|
typedef struct UnpackedRecord UnpackedRecord;
|
|
typedef struct Upsert Upsert;
|
|
typedef struct VTable VTable;
|
|
typedef struct VtabCtx VtabCtx;
|
|
typedef struct Walker Walker;
|
|
typedef struct WhereInfo WhereInfo;
|
|
typedef struct Window Window;
|
|
typedef struct With With;
|
|
# 1127 "src/sqliteInt.h"
|
|
typedef u64 Bitmask;
|
|
# 1148 "src/sqliteInt.h"
|
|
typedef int VList;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 1 "src/btree.h" 1
|
|
# 39 "src/btree.h"
|
|
typedef struct Btree Btree;
|
|
typedef struct BtCursor BtCursor;
|
|
typedef struct BtShared BtShared;
|
|
typedef struct BtreePayload BtreePayload;
|
|
|
|
|
|
int sqlite3BtreeOpen(
|
|
sqlite3_vfs *pVfs,
|
|
const char *zFilename,
|
|
sqlite3 *db,
|
|
Btree **ppBtree,
|
|
int flags,
|
|
int vfsFlags
|
|
);
|
|
# 65 "src/btree.h"
|
|
int sqlite3BtreeClose(Btree*);
|
|
int sqlite3BtreeSetCacheSize(Btree*,int);
|
|
int sqlite3BtreeSetSpillSize(Btree*,int);
|
|
|
|
int sqlite3BtreeSetMmapLimit(Btree*,sqlite3_int64);
|
|
|
|
int sqlite3BtreeSetPagerFlags(Btree*,unsigned);
|
|
int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
|
|
int sqlite3BtreeGetPageSize(Btree*);
|
|
int sqlite3BtreeMaxPageCount(Btree*,int);
|
|
u32 sqlite3BtreeLastPage(Btree*);
|
|
int sqlite3BtreeSecureDelete(Btree*,int);
|
|
int sqlite3BtreeGetOptimalReserve(Btree*);
|
|
int sqlite3BtreeGetReserveNoMutex(Btree *p);
|
|
int sqlite3BtreeSetAutoVacuum(Btree *, int);
|
|
int sqlite3BtreeGetAutoVacuum(Btree *);
|
|
int sqlite3BtreeBeginTrans(Btree*,int,int*);
|
|
int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster);
|
|
int sqlite3BtreeCommitPhaseTwo(Btree*, int);
|
|
int sqlite3BtreeCommit(Btree*);
|
|
int sqlite3BtreeRollback(Btree*,int,int);
|
|
int sqlite3BtreeBeginStmt(Btree*,int);
|
|
int sqlite3BtreeCreateTable(Btree*, int*, int flags);
|
|
int sqlite3BtreeIsInTrans(Btree*);
|
|
int sqlite3BtreeIsInReadTrans(Btree*);
|
|
int sqlite3BtreeIsInBackup(Btree*);
|
|
void *sqlite3BtreeSchema(Btree *, int, void(*)(void *));
|
|
int sqlite3BtreeSchemaLocked(Btree *pBtree);
|
|
|
|
int sqlite3BtreeLockTable(Btree *pBtree, int iTab, u8 isWriteLock);
|
|
|
|
int sqlite3BtreeSavepoint(Btree *, int, int);
|
|
|
|
const char *sqlite3BtreeGetFilename(Btree *);
|
|
const char *sqlite3BtreeGetJournalname(Btree *);
|
|
int sqlite3BtreeCopyFile(Btree *, Btree *);
|
|
|
|
int sqlite3BtreeIncrVacuum(Btree *);
|
|
# 117 "src/btree.h"
|
|
int sqlite3BtreeDropTable(Btree*, int, int*);
|
|
int sqlite3BtreeClearTable(Btree*, int, int*);
|
|
int sqlite3BtreeClearTableOfCursor(BtCursor*);
|
|
int sqlite3BtreeTripAllCursors(Btree*, int, int);
|
|
|
|
void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue);
|
|
int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
|
|
|
|
int sqlite3BtreeNewDb(Btree *p);
|
|
# 226 "src/btree.h"
|
|
int sqlite3BtreeCursor(
|
|
Btree*,
|
|
int iTable,
|
|
int wrFlag,
|
|
struct KeyInfo*,
|
|
BtCursor *pCursor
|
|
);
|
|
BtCursor *sqlite3BtreeFakeValidCursor(void);
|
|
int sqlite3BtreeCursorSize(void);
|
|
void sqlite3BtreeCursorZero(BtCursor*);
|
|
void sqlite3BtreeCursorHintFlags(BtCursor*, unsigned);
|
|
|
|
|
|
|
|
|
|
int sqlite3BtreeCloseCursor(BtCursor*);
|
|
int sqlite3BtreeMovetoUnpacked(
|
|
BtCursor*,
|
|
UnpackedRecord *pUnKey,
|
|
i64 intKey,
|
|
int bias,
|
|
int *pRes
|
|
);
|
|
int sqlite3BtreeCursorHasMoved(BtCursor*);
|
|
int sqlite3BtreeCursorRestore(BtCursor*, int*);
|
|
int sqlite3BtreeDelete(BtCursor*, u8 flags);
|
|
# 291 "src/btree.h"
|
|
struct BtreePayload {
|
|
const void *pKey;
|
|
sqlite3_int64 nKey;
|
|
const void *pData;
|
|
sqlite3_value *aMem;
|
|
u16 nMem;
|
|
int nData;
|
|
int nZero;
|
|
};
|
|
|
|
int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload,
|
|
int flags, int seekResult);
|
|
int sqlite3BtreeFirst(BtCursor*, int *pRes);
|
|
int sqlite3BtreeLast(BtCursor*, int *pRes);
|
|
int sqlite3BtreeNext(BtCursor*, int flags);
|
|
int sqlite3BtreeEof(BtCursor*);
|
|
int sqlite3BtreePrevious(BtCursor*, int flags);
|
|
i64 sqlite3BtreeIntegerKey(BtCursor*);
|
|
|
|
|
|
|
|
int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*);
|
|
const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt);
|
|
u32 sqlite3BtreePayloadSize(BtCursor*);
|
|
sqlite3_int64 sqlite3BtreeMaxRecordSize(BtCursor*);
|
|
|
|
char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*);
|
|
struct Pager *sqlite3BtreePager(Btree*);
|
|
i64 sqlite3BtreeRowCountEst(BtCursor*);
|
|
|
|
|
|
int sqlite3BtreePayloadChecked(BtCursor*, u32 offset, u32 amt, void*);
|
|
int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*);
|
|
void sqlite3BtreeIncrblobCursor(BtCursor *);
|
|
|
|
void sqlite3BtreeClearCursor(BtCursor *);
|
|
int sqlite3BtreeSetVersion(Btree *pBt, int iVersion);
|
|
int sqlite3BtreeCursorHasHint(BtCursor*, unsigned int mask);
|
|
int sqlite3BtreeIsReadonly(Btree *pBt);
|
|
int sqlite3HeaderSizeBtree(void);
|
|
|
|
|
|
|
|
|
|
int sqlite3BtreeCursorIsValidNN(BtCursor*);
|
|
|
|
|
|
int sqlite3BtreeCount(BtCursor *, i64 *);
|
|
# 347 "src/btree.h"
|
|
int sqlite3BtreeCheckpoint(Btree*, int, int *, int *);
|
|
# 356 "src/btree.h"
|
|
void sqlite3BtreeEnter(Btree*);
|
|
void sqlite3BtreeEnterAll(sqlite3*);
|
|
int sqlite3BtreeSharable(Btree*);
|
|
void sqlite3BtreeEnterCursor(BtCursor*);
|
|
int sqlite3BtreeConnectionCount(Btree*);
|
|
# 370 "src/btree.h"
|
|
void sqlite3BtreeLeave(Btree*);
|
|
void sqlite3BtreeLeaveCursor(BtCursor*);
|
|
void sqlite3BtreeLeaveAll(sqlite3*);
|
|
# 1156 "src/sqliteInt.h" 2
|
|
# 1 "src/vdbe.h" 1
|
|
# 20 "src/vdbe.h"
|
|
# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdio.h" 1
|
|
# 1 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/_fake_defines.h" 1
|
|
# 2 "/usr/local/google/home/eliben/eli/pycparser/utils/fake_libc_include/stdio.h" 2
|
|
# 21 "src/vdbe.h" 2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct Vdbe Vdbe;
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct sqlite3_value Mem;
|
|
typedef struct SubProgram SubProgram;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct VdbeOp {
|
|
u8 opcode;
|
|
signed char p4type;
|
|
u16 p5;
|
|
int p1;
|
|
int p2;
|
|
int p3;
|
|
union p4union {
|
|
int i;
|
|
void *p;
|
|
char *z;
|
|
i64 *pI64;
|
|
double *pReal;
|
|
FuncDef *pFunc;
|
|
sqlite3_context *pCtx;
|
|
CollSeq *pColl;
|
|
Mem *pMem;
|
|
VTable *pVtab;
|
|
KeyInfo *pKeyInfo;
|
|
int *ai;
|
|
SubProgram *pProgram;
|
|
Table *pTab;
|
|
|
|
|
|
|
|
int (*xAdvance)(BtCursor *, int);
|
|
} p4;
|
|
# 79 "src/vdbe.h"
|
|
};
|
|
typedef struct VdbeOp VdbeOp;
|
|
|
|
|
|
|
|
|
|
|
|
struct SubProgram {
|
|
VdbeOp *aOp;
|
|
int nOp;
|
|
int nMem;
|
|
int nCsr;
|
|
u8 *aOnce;
|
|
void *token;
|
|
SubProgram *pNext;
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct VdbeOpList {
|
|
u8 opcode;
|
|
signed char p1;
|
|
signed char p2;
|
|
signed char p3;
|
|
};
|
|
typedef struct VdbeOpList VdbeOpList;
|
|
# 169 "src/vdbe.h"
|
|
# 1 "./opcodes.h" 1
|
|
# 170 "src/vdbe.h" 2
|
|
# 181 "src/vdbe.h"
|
|
Vdbe *sqlite3VdbeCreate(Parse*);
|
|
int sqlite3VdbeAddOp0(Vdbe*,int);
|
|
int sqlite3VdbeAddOp1(Vdbe*,int,int);
|
|
int sqlite3VdbeAddOp2(Vdbe*,int,int,int);
|
|
int sqlite3VdbeGoto(Vdbe*,int);
|
|
int sqlite3VdbeLoadString(Vdbe*,int,const char*);
|
|
void sqlite3VdbeMultiLoad(Vdbe*,int,const char*,...);
|
|
int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int);
|
|
int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int);
|
|
int sqlite3VdbeAddOp4Dup8(Vdbe*,int,int,int,int,const u8*,int);
|
|
int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
|
|
void sqlite3VdbeEndCoroutine(Vdbe*,int);
|
|
# 205 "src/vdbe.h"
|
|
VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno);
|
|
|
|
void sqlite3VdbeExplain(Parse*,u8,const char*,...);
|
|
void sqlite3VdbeExplainPop(Parse*);
|
|
int sqlite3VdbeExplainParent(Parse*);
|
|
# 224 "src/vdbe.h"
|
|
void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
|
|
void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8);
|
|
void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1);
|
|
void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
|
|
void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
|
|
void sqlite3VdbeChangeP5(Vdbe*, u16 P5);
|
|
void sqlite3VdbeJumpHere(Vdbe*, int addr);
|
|
int sqlite3VdbeChangeToNoop(Vdbe*, int addr);
|
|
int sqlite3VdbeDeletePriorOpcode(Vdbe*, u8 op);
|
|
void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
|
|
void sqlite3VdbeAppendP4(Vdbe*, void *pP4, int p4type);
|
|
void sqlite3VdbeSetP4KeyInfo(Parse*, Index*);
|
|
void sqlite3VdbeUsesBtree(Vdbe*, int);
|
|
VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
|
|
int sqlite3VdbeMakeLabel(Parse*);
|
|
void sqlite3VdbeRunOnlyOnce(Vdbe*);
|
|
void sqlite3VdbeReusable(Vdbe*);
|
|
void sqlite3VdbeDelete(Vdbe*);
|
|
void sqlite3VdbeClearObject(sqlite3*,Vdbe*);
|
|
void sqlite3VdbeMakeReady(Vdbe*,Parse*);
|
|
int sqlite3VdbeFinalize(Vdbe*);
|
|
void sqlite3VdbeResolveLabel(Vdbe*, int);
|
|
int sqlite3VdbeCurrentAddr(Vdbe*);
|
|
|
|
|
|
|
|
void sqlite3VdbeResetStepResult(Vdbe*);
|
|
void sqlite3VdbeRewind(Vdbe*);
|
|
int sqlite3VdbeReset(Vdbe*);
|
|
void sqlite3VdbeSetNumCols(Vdbe*,int);
|
|
int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, void(*)(void*));
|
|
void sqlite3VdbeCountChanges(Vdbe*);
|
|
sqlite3 *sqlite3VdbeDb(Vdbe*);
|
|
u8 sqlite3VdbePrepareFlags(Vdbe*);
|
|
void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, u8);
|
|
|
|
|
|
|
|
|
|
void sqlite3VdbeSwap(Vdbe*,Vdbe*);
|
|
VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*);
|
|
sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe*, int, u8);
|
|
void sqlite3VdbeSetVarmask(Vdbe*, int);
|
|
|
|
char *sqlite3VdbeExpandSql(Vdbe*, const char*);
|
|
|
|
int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
|
|
int sqlite3BlobCompare(const Mem*, const Mem*);
|
|
|
|
void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
|
|
int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
|
|
int sqlite3VdbeRecordCompareWithSkip(int, const void *, UnpackedRecord *, int);
|
|
UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo*);
|
|
|
|
typedef int (*RecordCompare)(int,const void*,UnpackedRecord*);
|
|
RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);
|
|
|
|
|
|
void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
|
|
|
|
|
|
int sqlite3NotPureFunc(sqlite3_context*);
|
|
# 1157 "src/sqliteInt.h" 2
|
|
# 1 "src/pager.h" 1
|
|
# 33 "src/pager.h"
|
|
typedef u32 Pgno;
|
|
|
|
|
|
|
|
|
|
typedef struct Pager Pager;
|
|
|
|
|
|
|
|
|
|
typedef struct PgHdr DbPage;
|
|
# 116 "src/pager.h"
|
|
int sqlite3PagerOpen(
|
|
sqlite3_vfs*,
|
|
Pager **ppPager,
|
|
const char*,
|
|
int,
|
|
int,
|
|
int,
|
|
void(*)(DbPage*)
|
|
);
|
|
int sqlite3PagerClose(Pager *pPager, sqlite3*);
|
|
int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
|
|
|
|
|
|
void sqlite3PagerSetBusyHandler(Pager*, int(*)(void *), void *);
|
|
int sqlite3PagerSetPagesize(Pager*, u32*, int);
|
|
|
|
|
|
|
|
int sqlite3PagerMaxPageCount(Pager*, int);
|
|
void sqlite3PagerSetCachesize(Pager*, int);
|
|
int sqlite3PagerSetSpillsize(Pager*, int);
|
|
void sqlite3PagerSetMmapLimit(Pager *, sqlite3_int64);
|
|
void sqlite3PagerShrink(Pager*);
|
|
void sqlite3PagerSetFlags(Pager*,unsigned);
|
|
int sqlite3PagerLockingMode(Pager *, int);
|
|
int sqlite3PagerSetJournalMode(Pager *, int);
|
|
int sqlite3PagerGetJournalMode(Pager*);
|
|
int sqlite3PagerOkToChangeJournalMode(Pager*);
|
|
i64 sqlite3PagerJournalSizeLimit(Pager *, i64);
|
|
sqlite3_backup **sqlite3PagerBackupPtr(Pager*);
|
|
int sqlite3PagerFlush(Pager*);
|
|
|
|
|
|
int sqlite3PagerGet(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag);
|
|
DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno);
|
|
void sqlite3PagerRef(DbPage*);
|
|
void sqlite3PagerUnref(DbPage*);
|
|
void sqlite3PagerUnrefNotNull(DbPage*);
|
|
void sqlite3PagerUnrefPageOne(DbPage*);
|
|
|
|
|
|
int sqlite3PagerWrite(DbPage*);
|
|
void sqlite3PagerDontWrite(DbPage*);
|
|
int sqlite3PagerMovepage(Pager*,DbPage*,Pgno,int);
|
|
int sqlite3PagerPageRefcount(DbPage*);
|
|
void *sqlite3PagerGetData(DbPage *);
|
|
void *sqlite3PagerGetExtra(DbPage *);
|
|
|
|
|
|
void sqlite3PagerPagecount(Pager*, int*);
|
|
int sqlite3PagerBegin(Pager*, int exFlag, int);
|
|
int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, int);
|
|
int sqlite3PagerExclusiveLock(Pager*);
|
|
int sqlite3PagerSync(Pager *pPager, const char *zMaster);
|
|
int sqlite3PagerCommitPhaseTwo(Pager*);
|
|
int sqlite3PagerRollback(Pager*);
|
|
int sqlite3PagerOpenSavepoint(Pager *pPager, int n);
|
|
int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint);
|
|
int sqlite3PagerSharedLock(Pager *pPager);
|
|
|
|
|
|
int sqlite3PagerCheckpoint(Pager *pPager, sqlite3*, int, int*, int*);
|
|
int sqlite3PagerWalSupported(Pager *pPager);
|
|
int sqlite3PagerWalCallback(Pager *pPager);
|
|
int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
|
|
int sqlite3PagerCloseWal(Pager *pPager, sqlite3*);
|
|
# 200 "src/pager.h"
|
|
u8 sqlite3PagerIsreadonly(Pager*);
|
|
u32 sqlite3PagerDataVersion(Pager*);
|
|
|
|
|
|
|
|
int sqlite3PagerMemUsed(Pager*);
|
|
const char *sqlite3PagerFilename(Pager*, int);
|
|
sqlite3_vfs *sqlite3PagerVfs(Pager*);
|
|
sqlite3_file *sqlite3PagerFile(Pager*);
|
|
sqlite3_file *sqlite3PagerJrnlFile(Pager*);
|
|
const char *sqlite3PagerJournalname(Pager*);
|
|
void *sqlite3PagerTempSpace(Pager*);
|
|
int sqlite3PagerIsMemdb(Pager*);
|
|
void sqlite3PagerCacheStat(Pager *, int, int, int *);
|
|
void sqlite3PagerClearCache(Pager*);
|
|
int sqlite3SectorSize(sqlite3_file *);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void sqlite3PagerTruncateImage(Pager*,Pgno);
|
|
|
|
void sqlite3PagerRekey(DbPage*, Pgno, u16);
|
|
# 1158 "src/sqliteInt.h" 2
|
|
# 1 "src/pcache.h" 1
|
|
# 18 "src/pcache.h"
|
|
typedef struct PgHdr PgHdr;
|
|
typedef struct PCache PCache;
|
|
|
|
|
|
|
|
|
|
|
|
struct PgHdr {
|
|
sqlite3_pcache_page *pPage;
|
|
void *pData;
|
|
void *pExtra;
|
|
PCache *pCache;
|
|
PgHdr *pDirty;
|
|
Pager *pPager;
|
|
Pgno pgno;
|
|
|
|
|
|
|
|
u16 flags;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
i16 nRef;
|
|
PgHdr *pDirtyNext;
|
|
PgHdr *pDirtyPrev;
|
|
|
|
|
|
};
|
|
# 62 "src/pcache.h"
|
|
int sqlite3PcacheInitialize(void);
|
|
void sqlite3PcacheShutdown(void);
|
|
|
|
|
|
|
|
|
|
void sqlite3PCacheBufferSetup(void *, int sz, int n);
|
|
|
|
|
|
|
|
|
|
|
|
int sqlite3PcacheOpen(
|
|
int szPage,
|
|
int szExtra,
|
|
int bPurgeable,
|
|
int (*xStress)(void*, PgHdr*),
|
|
void *pStress,
|
|
PCache *pToInit
|
|
);
|
|
|
|
|
|
int sqlite3PcacheSetPageSize(PCache *, int);
|
|
|
|
|
|
|
|
|
|
int sqlite3PcacheSize(void);
|
|
|
|
|
|
|
|
|
|
sqlite3_pcache_page *sqlite3PcacheFetch(PCache*, Pgno, int createFlag);
|
|
int sqlite3PcacheFetchStress(PCache*, Pgno, sqlite3_pcache_page**);
|
|
PgHdr *sqlite3PcacheFetchFinish(PCache*, Pgno, sqlite3_pcache_page *pPage);
|
|
void sqlite3PcacheRelease(PgHdr*);
|
|
|
|
void sqlite3PcacheDrop(PgHdr*);
|
|
void sqlite3PcacheMakeDirty(PgHdr*);
|
|
void sqlite3PcacheMakeClean(PgHdr*);
|
|
void sqlite3PcacheCleanAll(PCache*);
|
|
void sqlite3PcacheClearWritable(PCache*);
|
|
|
|
|
|
void sqlite3PcacheMove(PgHdr*, Pgno);
|
|
|
|
|
|
void sqlite3PcacheTruncate(PCache*, Pgno x);
|
|
|
|
|
|
PgHdr *sqlite3PcacheDirtyList(PCache*);
|
|
|
|
|
|
void sqlite3PcacheClose(PCache*);
|
|
|
|
|
|
void sqlite3PcacheClearSyncFlags(PCache *);
|
|
|
|
|
|
void sqlite3PcacheClear(PCache*);
|
|
|
|
|
|
int sqlite3PcacheRefCount(PCache*);
|
|
|
|
|
|
void sqlite3PcacheRef(PgHdr*);
|
|
|
|
int sqlite3PcachePageRefcount(PgHdr*);
|
|
|
|
|
|
int sqlite3PcachePagecount(PCache*);
|
|
# 153 "src/pcache.h"
|
|
void sqlite3PcacheSetCachesize(PCache *, int);
|
|
# 163 "src/pcache.h"
|
|
int sqlite3PcacheSetSpillsize(PCache *, int);
|
|
|
|
|
|
void sqlite3PcacheShrink(PCache*);
|
|
# 177 "src/pcache.h"
|
|
void sqlite3PCacheSetDefault(void);
|
|
|
|
|
|
int sqlite3HeaderSizePcache(void);
|
|
int sqlite3HeaderSizePcache1(void);
|
|
|
|
|
|
int sqlite3PCachePercentDirty(PCache*);
|
|
# 1159 "src/sqliteInt.h" 2
|
|
# 1 "src/os.h" 1
|
|
# 27 "src/os.h"
|
|
# 1 "src/os_setup.h" 1
|
|
# 28 "src/os.h" 2
|
|
# 158 "src/os.h"
|
|
int sqlite3OsInit(void);
|
|
|
|
|
|
|
|
|
|
void sqlite3OsClose(sqlite3_file*);
|
|
int sqlite3OsRead(sqlite3_file*, void*, int amt, i64 offset);
|
|
int sqlite3OsWrite(sqlite3_file*, const void*, int amt, i64 offset);
|
|
int sqlite3OsTruncate(sqlite3_file*, i64 size);
|
|
int sqlite3OsSync(sqlite3_file*, int);
|
|
int sqlite3OsFileSize(sqlite3_file*, i64 *pSize);
|
|
int sqlite3OsLock(sqlite3_file*, int);
|
|
int sqlite3OsUnlock(sqlite3_file*, int);
|
|
int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut);
|
|
int sqlite3OsFileControl(sqlite3_file*,int,void*);
|
|
void sqlite3OsFileControlHint(sqlite3_file*,int,void*);
|
|
|
|
int sqlite3OsSectorSize(sqlite3_file *id);
|
|
int sqlite3OsDeviceCharacteristics(sqlite3_file *id);
|
|
|
|
int sqlite3OsShmMap(sqlite3_file *,int,int,int,void volatile **);
|
|
int sqlite3OsShmLock(sqlite3_file *id, int, int, int);
|
|
void sqlite3OsShmBarrier(sqlite3_file *id);
|
|
int sqlite3OsShmUnmap(sqlite3_file *id, int);
|
|
|
|
int sqlite3OsFetch(sqlite3_file *id, i64, int, void **);
|
|
int sqlite3OsUnfetch(sqlite3_file *, i64, void *);
|
|
|
|
|
|
|
|
|
|
|
|
int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *);
|
|
int sqlite3OsDelete(sqlite3_vfs *, const char *, int);
|
|
int sqlite3OsAccess(sqlite3_vfs *, const char *, int, int *pResOut);
|
|
int sqlite3OsFullPathname(sqlite3_vfs *, const char *, int, char *);
|
|
|
|
void *sqlite3OsDlOpen(sqlite3_vfs *, const char *);
|
|
void sqlite3OsDlError(sqlite3_vfs *, int, char *);
|
|
void (*sqlite3OsDlSym(sqlite3_vfs *, void *, const char *))(void);
|
|
void sqlite3OsDlClose(sqlite3_vfs *, void *);
|
|
|
|
int sqlite3OsRandomness(sqlite3_vfs *, int, char *);
|
|
int sqlite3OsSleep(sqlite3_vfs *, int);
|
|
int sqlite3OsGetLastError(sqlite3_vfs*);
|
|
int sqlite3OsCurrentTimeInt64(sqlite3_vfs *, sqlite3_int64*);
|
|
|
|
|
|
|
|
|
|
|
|
int sqlite3OsOpenMalloc(sqlite3_vfs *, const char *, sqlite3_file **, int,int*);
|
|
void sqlite3OsCloseFree(sqlite3_file *);
|
|
# 1160 "src/sqliteInt.h" 2
|
|
# 1 "src/mutex.h" 1
|
|
# 1161 "src/sqliteInt.h" 2
|
|
# 1200 "src/sqliteInt.h"
|
|
struct Db {
|
|
char *zDbSName;
|
|
Btree *pBt;
|
|
u8 safety_level;
|
|
u8 bSyncSet;
|
|
Schema *pSchema;
|
|
};
|
|
# 1225 "src/sqliteInt.h"
|
|
struct Schema {
|
|
int schema_cookie;
|
|
int iGeneration;
|
|
Hash tblHash;
|
|
Hash idxHash;
|
|
Hash trigHash;
|
|
Hash fkeyHash;
|
|
Table *pSeqTab;
|
|
u8 file_format;
|
|
u8 enc;
|
|
u16 schemaFlags;
|
|
int cache_size;
|
|
};
|
|
# 1289 "src/sqliteInt.h"
|
|
struct Lookaside {
|
|
u32 bDisable;
|
|
u16 sz;
|
|
u8 bMalloced;
|
|
u32 nSlot;
|
|
u32 anStat[3];
|
|
LookasideSlot *pInit;
|
|
LookasideSlot *pFree;
|
|
void *pStart;
|
|
void *pEnd;
|
|
};
|
|
struct LookasideSlot {
|
|
LookasideSlot *pNext;
|
|
};
|
|
# 1313 "src/sqliteInt.h"
|
|
struct FuncDefHash {
|
|
FuncDef *a[23];
|
|
};
|
|
# 1352 "src/sqliteInt.h"
|
|
typedef int (*sqlite3_xauth)(void*,int,const char*,const char*,const char*,
|
|
const char*);
|
|
# 1372 "src/sqliteInt.h"
|
|
struct sqlite3 {
|
|
sqlite3_vfs *pVfs;
|
|
struct Vdbe *pVdbe;
|
|
CollSeq *pDfltColl;
|
|
sqlite3_mutex *mutex;
|
|
Db *aDb;
|
|
int nDb;
|
|
u32 mDbFlags;
|
|
u64 flags;
|
|
i64 lastRowid;
|
|
i64 szMmap;
|
|
u32 nSchemaLock;
|
|
unsigned int openFlags;
|
|
int errCode;
|
|
int errMask;
|
|
int iSysErrno;
|
|
u16 dbOptFlags;
|
|
u8 enc;
|
|
u8 autoCommit;
|
|
u8 temp_store;
|
|
u8 mallocFailed;
|
|
u8 bBenignMalloc;
|
|
u8 dfltLockMode;
|
|
signed char nextAutovac;
|
|
u8 suppressErr;
|
|
u8 vtabOnConflict;
|
|
u8 isTransactionSavepoint;
|
|
u8 mTrace;
|
|
u8 noSharedCache;
|
|
u8 nSqlExec;
|
|
int nextPagesize;
|
|
u32 magic;
|
|
int nChange;
|
|
int nTotalChange;
|
|
int aLimit[(11 +1)];
|
|
int nMaxSorterMmap;
|
|
struct sqlite3InitInfo {
|
|
int newTnum;
|
|
u8 iDb;
|
|
u8 busy;
|
|
unsigned orphanTrigger : 1;
|
|
unsigned imposterTable : 1;
|
|
unsigned reopenMemdb : 1;
|
|
} init;
|
|
int nVdbeActive;
|
|
int nVdbeRead;
|
|
int nVdbeWrite;
|
|
int nVdbeExec;
|
|
int nVDestroy;
|
|
int nExtension;
|
|
void **aExtension;
|
|
int (*xTrace)(u32,void*,void*,void*);
|
|
void *pTraceArg;
|
|
|
|
void (*xProfile)(void*,const char*,u64);
|
|
void *pProfileArg;
|
|
|
|
void *pCommitArg;
|
|
int (*xCommitCallback)(void*);
|
|
void *pRollbackArg;
|
|
void (*xRollbackCallback)(void*);
|
|
void *pUpdateArg;
|
|
void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64);
|
|
Parse *pParse;
|
|
# 1444 "src/sqliteInt.h"
|
|
int (*xWalCallback)(void *, sqlite3 *, const char *, int);
|
|
void *pWalArg;
|
|
|
|
void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*);
|
|
void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*);
|
|
void *pCollNeededArg;
|
|
sqlite3_value *pErr;
|
|
union {
|
|
volatile int isInterrupted;
|
|
double notUsed1;
|
|
} u1;
|
|
Lookaside lookaside;
|
|
|
|
sqlite3_xauth xAuth;
|
|
void *pAuthArg;
|
|
|
|
|
|
int (*xProgress)(void *);
|
|
void *pProgressArg;
|
|
unsigned nProgressOps;
|
|
|
|
|
|
int nVTrans;
|
|
Hash aModule;
|
|
VtabCtx *pVtabCtx;
|
|
VTable **aVTrans;
|
|
VTable *pDisconnect;
|
|
|
|
Hash aFunc;
|
|
Hash aCollSeq;
|
|
BusyHandler busyHandler;
|
|
Db aDbStatic[2];
|
|
Savepoint *pSavepoint;
|
|
int busyTimeout;
|
|
int nSavepoint;
|
|
int nStatement;
|
|
i64 nDeferredCons;
|
|
i64 nDeferredImmCons;
|
|
int *pnBytesFreed;
|
|
# 1503 "src/sqliteInt.h"
|
|
};
|
|
# 1632 "src/sqliteInt.h"
|
|
struct FuncDef {
|
|
i8 nArg;
|
|
u32 funcFlags;
|
|
void *pUserData;
|
|
FuncDef *pNext;
|
|
void (*xSFunc)(sqlite3_context*,int,sqlite3_value**);
|
|
void (*xFinalize)(sqlite3_context*);
|
|
void (*xValue)(sqlite3_context*);
|
|
void (*xInverse)(sqlite3_context*,int,sqlite3_value**);
|
|
const char *zName;
|
|
union {
|
|
FuncDef *pHash;
|
|
FuncDestructor *pDestructor;
|
|
} u;
|
|
};
|
|
# 1662 "src/sqliteInt.h"
|
|
struct FuncDestructor {
|
|
int nRef;
|
|
void (*xDestroy)(void *);
|
|
void *pUserData;
|
|
};
|
|
# 1788 "src/sqliteInt.h"
|
|
struct Savepoint {
|
|
char *zName;
|
|
i64 nDeferredCons;
|
|
i64 nDeferredImmCons;
|
|
Savepoint *pNext;
|
|
};
|
|
# 1809 "src/sqliteInt.h"
|
|
struct Module {
|
|
const sqlite3_module *pModule;
|
|
const char *zName;
|
|
void *pAux;
|
|
void (*xDestroy)(void *);
|
|
Table *pEpoTab;
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct Column {
|
|
char *zName;
|
|
Expr *pDflt;
|
|
char *zColl;
|
|
u8 notNull;
|
|
char affinity;
|
|
u8 szEst;
|
|
u8 colFlags;
|
|
};
|
|
# 1848 "src/sqliteInt.h"
|
|
struct CollSeq {
|
|
char *zName;
|
|
u8 enc;
|
|
void *pUser;
|
|
int (*xCmp)(void*,int, const void*, int, const void*);
|
|
void (*xDel)(void*);
|
|
};
|
|
# 1948 "src/sqliteInt.h"
|
|
struct VTable {
|
|
sqlite3 *db;
|
|
Module *pMod;
|
|
sqlite3_vtab *pVtab;
|
|
int nRef;
|
|
u8 bConstraint;
|
|
int iSavepoint;
|
|
VTable *pNext;
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct Table {
|
|
char *zName;
|
|
Column *aCol;
|
|
Index *pIndex;
|
|
Select *pSelect;
|
|
FKey *pFKey;
|
|
char *zColAff;
|
|
ExprList *pCheck;
|
|
|
|
int tnum;
|
|
u32 nTabRef;
|
|
u32 tabFlags;
|
|
i16 iPKey;
|
|
i16 nCol;
|
|
LogEst nRowLogEst;
|
|
LogEst szTabRow;
|
|
|
|
|
|
|
|
u8 keyConf;
|
|
|
|
int addColOffset;
|
|
|
|
|
|
int nModuleArg;
|
|
char **azModuleArg;
|
|
VTable *pVTable;
|
|
|
|
Trigger *pTrigger;
|
|
Schema *pSchema;
|
|
Table *pNextZombie;
|
|
};
|
|
# 2078 "src/sqliteInt.h"
|
|
struct FKey {
|
|
Table *pFrom;
|
|
FKey *pNextFrom;
|
|
char *zTo;
|
|
FKey *pNextTo;
|
|
FKey *pPrevTo;
|
|
int nCol;
|
|
|
|
u8 isDeferred;
|
|
u8 aAction[2];
|
|
Trigger *apTrigger[2];
|
|
struct sColMap {
|
|
int iFrom;
|
|
char *zCol;
|
|
} aCol[1];
|
|
};
|
|
# 2143 "src/sqliteInt.h"
|
|
struct KeyInfo {
|
|
u32 nRef;
|
|
u8 enc;
|
|
u16 nKeyField;
|
|
u16 nAllField;
|
|
sqlite3 *db;
|
|
u8 *aSortOrder;
|
|
CollSeq *aColl[1];
|
|
};
|
|
# 2188 "src/sqliteInt.h"
|
|
struct UnpackedRecord {
|
|
KeyInfo *pKeyInfo;
|
|
Mem *aMem;
|
|
u16 nField;
|
|
i8 default_rc;
|
|
u8 errCode;
|
|
i8 r1;
|
|
i8 r2;
|
|
u8 eqSeen;
|
|
};
|
|
# 2234 "src/sqliteInt.h"
|
|
struct Index {
|
|
char *zName;
|
|
i16 *aiColumn;
|
|
LogEst *aiRowLogEst;
|
|
Table *pTable;
|
|
char *zColAff;
|
|
Index *pNext;
|
|
Schema *pSchema;
|
|
u8 *aSortOrder;
|
|
const char **azColl;
|
|
Expr *pPartIdxWhere;
|
|
ExprList *aColExpr;
|
|
int tnum;
|
|
LogEst szIdxRow;
|
|
u16 nKeyCol;
|
|
u16 nColumn;
|
|
u8 onError;
|
|
unsigned idxType:2;
|
|
unsigned bUnordered:1;
|
|
unsigned uniqNotNull:1;
|
|
unsigned isResized:1;
|
|
unsigned isCovering:1;
|
|
unsigned noSkipScan:1;
|
|
unsigned hasStat1:1;
|
|
unsigned bNoQuery:1;
|
|
unsigned bAscKeyBug:1;
|
|
# 2268 "src/sqliteInt.h"
|
|
Bitmask colNotIdxed;
|
|
};
|
|
# 2296 "src/sqliteInt.h"
|
|
struct IndexSample {
|
|
void *p;
|
|
int n;
|
|
tRowcnt *anEq;
|
|
tRowcnt *anLt;
|
|
tRowcnt *anDLt;
|
|
};
|
|
# 2320 "src/sqliteInt.h"
|
|
struct Token {
|
|
const char *z;
|
|
unsigned int n;
|
|
};
|
|
# 2338 "src/sqliteInt.h"
|
|
struct AggInfo {
|
|
u8 directMode;
|
|
|
|
u8 useSortingIdx;
|
|
|
|
int sortingIdx;
|
|
int sortingIdxPTab;
|
|
int nSortingColumn;
|
|
int mnReg, mxReg;
|
|
ExprList *pGroupBy;
|
|
struct AggInfo_col {
|
|
Table *pTab;
|
|
int iTable;
|
|
int iColumn;
|
|
int iSorterColumn;
|
|
int iMem;
|
|
Expr *pExpr;
|
|
} *aCol;
|
|
int nColumn;
|
|
int nAccumulator;
|
|
|
|
|
|
struct AggInfo_func {
|
|
Expr *pExpr;
|
|
FuncDef *pFunc;
|
|
int iMem;
|
|
int iDistinct;
|
|
} *aFunc;
|
|
int nFunc;
|
|
};
|
|
# 2380 "src/sqliteInt.h"
|
|
typedef i16 ynVar;
|
|
# 2448 "src/sqliteInt.h"
|
|
struct Expr {
|
|
u8 op;
|
|
char affinity;
|
|
u32 flags;
|
|
union {
|
|
char *zToken;
|
|
int iValue;
|
|
} u;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Expr *pLeft;
|
|
Expr *pRight;
|
|
union {
|
|
ExprList *pList;
|
|
Select *pSelect;
|
|
} x;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int nHeight;
|
|
|
|
int iTable;
|
|
|
|
|
|
|
|
|
|
ynVar iColumn;
|
|
|
|
|
|
i16 iAgg;
|
|
i16 iRightJoinTable;
|
|
u8 op2;
|
|
|
|
|
|
AggInfo *pAggInfo;
|
|
union {
|
|
Table *pTab;
|
|
|
|
Window *pWin;
|
|
struct {
|
|
int iAddr;
|
|
int regReturn;
|
|
} sub;
|
|
} y;
|
|
};
|
|
# 2598 "src/sqliteInt.h"
|
|
struct ExprList {
|
|
int nExpr;
|
|
struct ExprList_item {
|
|
Expr *pExpr;
|
|
char *zName;
|
|
char *zSpan;
|
|
u8 sortOrder;
|
|
unsigned done :1;
|
|
unsigned bSpanIsTab :1;
|
|
unsigned reusable :1;
|
|
unsigned bSorterRef :1;
|
|
union {
|
|
struct {
|
|
u16 iOrderByCol;
|
|
u16 iAlias;
|
|
} x;
|
|
int iConstExprReg;
|
|
} u;
|
|
} a[1];
|
|
};
|
|
# 2634 "src/sqliteInt.h"
|
|
struct IdList {
|
|
struct IdList_item {
|
|
char *zName;
|
|
int idx;
|
|
} *a;
|
|
int nId;
|
|
};
|
|
# 2661 "src/sqliteInt.h"
|
|
struct SrcList {
|
|
int nSrc;
|
|
u32 nAlloc;
|
|
struct SrcList_item {
|
|
Schema *pSchema;
|
|
char *zDatabase;
|
|
char *zName;
|
|
char *zAlias;
|
|
Table *pTab;
|
|
Select *pSelect;
|
|
int addrFillSub;
|
|
int regReturn;
|
|
int regResult;
|
|
struct {
|
|
u8 jointype;
|
|
unsigned notIndexed :1;
|
|
unsigned isIndexedBy :1;
|
|
unsigned isTabFunc :1;
|
|
unsigned isCorrelated :1;
|
|
unsigned viaCoroutine :1;
|
|
unsigned isRecursive :1;
|
|
} fg;
|
|
int iCursor;
|
|
Expr *pOn;
|
|
IdList *pUsing;
|
|
Bitmask colUsed;
|
|
union {
|
|
char *zIndexedBy;
|
|
ExprList *pFuncArg;
|
|
} u1;
|
|
Index *pIBIndex;
|
|
} a[1];
|
|
};
|
|
# 2761 "src/sqliteInt.h"
|
|
struct NameContext {
|
|
Parse *pParse;
|
|
SrcList *pSrcList;
|
|
union {
|
|
ExprList *pEList;
|
|
AggInfo *pAggInfo;
|
|
Upsert *pUpsert;
|
|
} uNC;
|
|
NameContext *pNext;
|
|
int nRef;
|
|
int nErr;
|
|
int ncFlags;
|
|
Select *pWinSelect;
|
|
};
|
|
# 2815 "src/sqliteInt.h"
|
|
struct Upsert {
|
|
ExprList *pUpsertTarget;
|
|
Expr *pUpsertTargetWhere;
|
|
ExprList *pUpsertSet;
|
|
Expr *pUpsertWhere;
|
|
|
|
|
|
|
|
|
|
Index *pUpsertIdx;
|
|
SrcList *pUpsertSrc;
|
|
int regData;
|
|
int iDataCur;
|
|
int iIdxCur;
|
|
};
|
|
# 2848 "src/sqliteInt.h"
|
|
struct Select {
|
|
ExprList *pEList;
|
|
u8 op;
|
|
LogEst nSelectRow;
|
|
u32 selFlags;
|
|
int iLimit, iOffset;
|
|
u32 selId;
|
|
int addrOpenEphm[2];
|
|
SrcList *pSrc;
|
|
Expr *pWhere;
|
|
ExprList *pGroupBy;
|
|
Expr *pHaving;
|
|
ExprList *pOrderBy;
|
|
Select *pPrior;
|
|
Select *pNext;
|
|
Expr *pLimit;
|
|
With *pWith;
|
|
|
|
Window *pWin;
|
|
Window *pWinDefn;
|
|
|
|
};
|
|
# 2987 "src/sqliteInt.h"
|
|
struct SelectDest {
|
|
u8 eDest;
|
|
int iSDParm;
|
|
int iSdst;
|
|
int nSdst;
|
|
char *zAffSdst;
|
|
ExprList *pOrderBy;
|
|
};
|
|
# 3005 "src/sqliteInt.h"
|
|
struct AutoincInfo {
|
|
AutoincInfo *pNext;
|
|
Table *pTab;
|
|
int iDb;
|
|
int regCtr;
|
|
};
|
|
# 3030 "src/sqliteInt.h"
|
|
struct TriggerPrg {
|
|
Trigger *pTrigger;
|
|
TriggerPrg *pNext;
|
|
SubProgram *pProgram;
|
|
int orconf;
|
|
u32 aColmask[2];
|
|
};
|
|
# 3049 "src/sqliteInt.h"
|
|
typedef unsigned int yDbMask;
|
|
# 3073 "src/sqliteInt.h"
|
|
struct Parse {
|
|
sqlite3 *db;
|
|
char *zErrMsg;
|
|
Vdbe *pVdbe;
|
|
int rc;
|
|
u8 colNamesSet;
|
|
u8 checkSchema;
|
|
u8 nested;
|
|
u8 nTempReg;
|
|
u8 isMultiWrite;
|
|
u8 mayAbort;
|
|
u8 hasCompound;
|
|
u8 okConstFactor;
|
|
u8 disableLookaside;
|
|
u8 disableVtab;
|
|
int nRangeReg;
|
|
int iRangeReg;
|
|
int nErr;
|
|
int nTab;
|
|
int nMem;
|
|
int szOpAlloc;
|
|
int iSelfTab;
|
|
|
|
int nLabel;
|
|
int nLabelAlloc;
|
|
int *aLabel;
|
|
ExprList *pConstExpr;
|
|
Token constraintName;
|
|
yDbMask writeMask;
|
|
yDbMask cookieMask;
|
|
int regRowid;
|
|
int regRoot;
|
|
int nMaxArg;
|
|
int nSelect;
|
|
|
|
int nTableLock;
|
|
TableLock *aTableLock;
|
|
|
|
AutoincInfo *pAinc;
|
|
Parse *pToplevel;
|
|
Table *pTriggerTab;
|
|
Parse *pParentParse;
|
|
int addrCrTab;
|
|
u32 nQueryLoop;
|
|
u32 oldmask;
|
|
u32 newmask;
|
|
u8 eTriggerOp;
|
|
u8 eOrconf;
|
|
u8 disableTriggers;
|
|
# 3130 "src/sqliteInt.h"
|
|
int aTempReg[8];
|
|
Token sNameToken;
|
|
# 3140 "src/sqliteInt.h"
|
|
Token sLastToken;
|
|
ynVar nVar;
|
|
u8 iPkSortOrder;
|
|
u8 explain;
|
|
|
|
u8 eParseMode;
|
|
|
|
|
|
int nVtabLock;
|
|
|
|
int nHeight;
|
|
|
|
int addrExplain;
|
|
|
|
VList *pVList;
|
|
Vdbe *pReprepare;
|
|
const char *zTail;
|
|
Table *pNewTable;
|
|
Index *pNewIndex;
|
|
|
|
|
|
Trigger *pNewTrigger;
|
|
const char *zAuthContext;
|
|
|
|
Token sArg;
|
|
Table **apVtabLock;
|
|
|
|
Table *pZombieTab;
|
|
TriggerPrg *pTriggerPrg;
|
|
With *pWith;
|
|
With *pWithToFree;
|
|
|
|
RenameToken *pRename;
|
|
|
|
};
|
|
# 3214 "src/sqliteInt.h"
|
|
struct AuthContext {
|
|
const char *zAuthContext;
|
|
Parse *pParse;
|
|
};
|
|
# 3266 "src/sqliteInt.h"
|
|
struct Trigger {
|
|
char *zName;
|
|
char *table;
|
|
u8 op;
|
|
u8 tr_tm;
|
|
Expr *pWhen;
|
|
IdList *pColumns;
|
|
|
|
Schema *pSchema;
|
|
Schema *pTabSchema;
|
|
TriggerStep *step_list;
|
|
Trigger *pNext;
|
|
};
|
|
# 3328 "src/sqliteInt.h"
|
|
struct TriggerStep {
|
|
u8 op;
|
|
u8 orconf;
|
|
Trigger *pTrig;
|
|
Select *pSelect;
|
|
char *zTarget;
|
|
Expr *pWhere;
|
|
ExprList *pExprList;
|
|
IdList *pIdList;
|
|
Upsert *pUpsert;
|
|
char *zSpan;
|
|
TriggerStep *pNext;
|
|
TriggerStep *pLast;
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct DbFixer DbFixer;
|
|
struct DbFixer {
|
|
Parse *pParse;
|
|
Schema *pSchema;
|
|
int bVarOnly;
|
|
const char *zDb;
|
|
const char *zType;
|
|
const Token *pName;
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct sqlite3_str {
|
|
sqlite3 *db;
|
|
char *zText;
|
|
u32 nAlloc;
|
|
u32 mxAlloc;
|
|
u32 nChar;
|
|
u8 accError;
|
|
u8 printfFlags;
|
|
};
|
|
# 3382 "src/sqliteInt.h"
|
|
typedef struct {
|
|
sqlite3 *db;
|
|
char **pzErrMsg;
|
|
int iDb;
|
|
int rc;
|
|
u32 mInitFlags;
|
|
u32 nInitRow;
|
|
} InitData;
|
|
# 3401 "src/sqliteInt.h"
|
|
struct Sqlite3Config {
|
|
int bMemstat;
|
|
int bCoreMutex;
|
|
int bFullMutex;
|
|
int bOpenUri;
|
|
int bUseCis;
|
|
int bSmallMalloc;
|
|
int mxStrlen;
|
|
int neverCorrupt;
|
|
int szLookaside;
|
|
int nLookaside;
|
|
int nStmtSpill;
|
|
sqlite3_mem_methods m;
|
|
sqlite3_mutex_methods mutex;
|
|
sqlite3_pcache_methods2 pcache2;
|
|
void *pHeap;
|
|
int nHeap;
|
|
int mnReq, mxReq;
|
|
sqlite3_int64 szMmap;
|
|
sqlite3_int64 mxMmap;
|
|
void *pPage;
|
|
int szPage;
|
|
int nPage;
|
|
int mxParserStack;
|
|
int sharedCacheEnabled;
|
|
u32 szPma;
|
|
|
|
|
|
int isInit;
|
|
int inProgress;
|
|
int isMutexInit;
|
|
int isMallocInit;
|
|
int isPCacheInit;
|
|
int nRefInitMutex;
|
|
sqlite3_mutex *pInitMutex;
|
|
void (*xLog)(void*,int,const char*);
|
|
void *pLogArg;
|
|
# 3453 "src/sqliteInt.h"
|
|
int (*xTestCallback)(int);
|
|
|
|
int bLocaltimeFault;
|
|
int bInternalFunctions;
|
|
int iOnceResetThreshold;
|
|
u32 szSorterRef;
|
|
};
|
|
# 3482 "src/sqliteInt.h"
|
|
struct Walker {
|
|
Parse *pParse;
|
|
int (*xExprCallback)(Walker*, Expr*);
|
|
int (*xSelectCallback)(Walker*,Select*);
|
|
void (*xSelectCallback2)(Walker*,Select*);
|
|
int walkerDepth;
|
|
u8 eCode;
|
|
union {
|
|
NameContext *pNC;
|
|
int n;
|
|
int iCur;
|
|
SrcList *pSrcList;
|
|
struct SrcCount *pSrcCount;
|
|
struct CCurHint *pCCurHint;
|
|
int *aiCol;
|
|
struct IdxCover *pIdxCover;
|
|
struct IdxExprTrans *pIdxTrans;
|
|
ExprList *pGroupBy;
|
|
Select *pSelect;
|
|
struct WindowRewrite *pRewrite;
|
|
struct WhereConst *pConst;
|
|
struct RenameCtx *pRename;
|
|
} u;
|
|
};
|
|
|
|
|
|
int sqlite3WalkExpr(Walker*, Expr*);
|
|
int sqlite3WalkExprList(Walker*, ExprList*);
|
|
int sqlite3WalkSelect(Walker*, Select*);
|
|
int sqlite3WalkSelectExpr(Walker*, Select*);
|
|
int sqlite3WalkSelectFrom(Walker*, Select*);
|
|
int sqlite3ExprWalkNoop(Walker*, Expr*);
|
|
int sqlite3SelectWalkNoop(Walker*, Select*);
|
|
int sqlite3SelectWalkFail(Walker*, Select*);
|
|
# 3532 "src/sqliteInt.h"
|
|
struct With {
|
|
int nCte;
|
|
With *pOuter;
|
|
struct Cte {
|
|
char *zName;
|
|
ExprList *pCols;
|
|
Select *pSelect;
|
|
const char *zCteErr;
|
|
} a[1];
|
|
};
|
|
# 3572 "src/sqliteInt.h"
|
|
struct Window {
|
|
char *zName;
|
|
char *zBase;
|
|
ExprList *pPartition;
|
|
ExprList *pOrderBy;
|
|
u8 eFrmType;
|
|
u8 eStart;
|
|
u8 eEnd;
|
|
u8 bImplicitFrame;
|
|
u8 eExclude;
|
|
Expr *pStart;
|
|
Expr *pEnd;
|
|
Window *pNextWin;
|
|
Expr *pFilter;
|
|
FuncDef *pFunc;
|
|
int iEphCsr;
|
|
int regAccum;
|
|
int regResult;
|
|
int csrApp;
|
|
int regApp;
|
|
int regPart;
|
|
Expr *pOwner;
|
|
int nBufferCol;
|
|
int iArgCol;
|
|
int regOne;
|
|
int regStartRowid;
|
|
int regEndRowid;
|
|
};
|
|
|
|
|
|
void sqlite3WindowDelete(sqlite3*, Window*);
|
|
void sqlite3WindowListDelete(sqlite3 *db, Window *p);
|
|
Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*, u8);
|
|
void sqlite3WindowAttach(Parse*, Expr*, Window*);
|
|
int sqlite3WindowCompare(Parse*, Window*, Window*);
|
|
void sqlite3WindowCodeInit(Parse*, Window*);
|
|
void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int);
|
|
int sqlite3WindowRewrite(Parse*, Select*);
|
|
int sqlite3ExpandSubquery(Parse*, struct SrcList_item*);
|
|
void sqlite3WindowUpdate(Parse*, Window*, Window*, FuncDef*);
|
|
Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p);
|
|
Window *sqlite3WindowListDup(sqlite3 *db, Window *p);
|
|
void sqlite3WindowFunctions(void);
|
|
void sqlite3WindowChain(Parse*, Window*, Window*);
|
|
Window *sqlite3WindowAssemble(Parse*, Window*, ExprList*, ExprList*, Token*);
|
|
# 3640 "src/sqliteInt.h"
|
|
int sqlite3ReportError(int iErr, int lineno, const char *zType);
|
|
int sqlite3CorruptError(int);
|
|
int sqlite3MisuseError(int);
|
|
int sqlite3CantopenError(int);
|
|
# 3710 "src/sqliteInt.h"
|
|
int sqlite3IsIdChar(u8);
|
|
|
|
|
|
|
|
|
|
int sqlite3StrICmp(const char*,const char*);
|
|
int sqlite3Strlen30(const char*);
|
|
|
|
char *sqlite3ColumnType(Column*,char*);
|
|
|
|
|
|
int sqlite3MallocInit(void);
|
|
void sqlite3MallocEnd(void);
|
|
void *sqlite3Malloc(u64);
|
|
void *sqlite3MallocZero(u64);
|
|
void *sqlite3DbMallocZero(sqlite3*, u64);
|
|
void *sqlite3DbMallocRaw(sqlite3*, u64);
|
|
void *sqlite3DbMallocRawNN(sqlite3*, u64);
|
|
char *sqlite3DbStrDup(sqlite3*,const char*);
|
|
char *sqlite3DbStrNDup(sqlite3*,const char*, u64);
|
|
char *sqlite3DbSpanDup(sqlite3*,const char*,const char*);
|
|
void *sqlite3Realloc(void*, u64);
|
|
void *sqlite3DbReallocOrFree(sqlite3 *, void *, u64);
|
|
void *sqlite3DbRealloc(sqlite3 *, void *, u64);
|
|
void sqlite3DbFree(sqlite3*, void*);
|
|
void sqlite3DbFreeNN(sqlite3*, void*);
|
|
int sqlite3MallocSize(void*);
|
|
int sqlite3DbMallocSize(sqlite3*, void*);
|
|
void *sqlite3PageMalloc(int);
|
|
void sqlite3PageFree(void*);
|
|
void sqlite3MemSetDefault(void);
|
|
|
|
void sqlite3BenignMallocHooks(void (*)(void), void (*)(void));
|
|
|
|
int sqlite3HeapNearlyFull(void);
|
|
# 3777 "src/sqliteInt.h"
|
|
sqlite3_mutex_methods const *sqlite3DefaultMutex(void);
|
|
sqlite3_mutex_methods const *sqlite3NoopMutex(void);
|
|
sqlite3_mutex *sqlite3MutexAlloc(int);
|
|
int sqlite3MutexInit(void);
|
|
int sqlite3MutexEnd(void);
|
|
|
|
|
|
void sqlite3MemoryBarrier(void);
|
|
|
|
|
|
|
|
|
|
sqlite3_int64 sqlite3StatusValue(int);
|
|
void sqlite3StatusUp(int, int);
|
|
void sqlite3StatusDown(int, int);
|
|
void sqlite3StatusHighwater(int, int);
|
|
int sqlite3LookasideUsed(sqlite3*,int*);
|
|
|
|
|
|
sqlite3_mutex *sqlite3Pcache1Mutex(void);
|
|
sqlite3_mutex *sqlite3MallocMutex(void);
|
|
# 3809 "src/sqliteInt.h"
|
|
int sqlite3IsNaN(double);
|
|
# 3819 "src/sqliteInt.h"
|
|
struct PrintfArguments {
|
|
int nArg;
|
|
int nUsed;
|
|
sqlite3_value **apArg;
|
|
};
|
|
|
|
char *sqlite3MPrintf(sqlite3*,const char*, ...);
|
|
char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
|
|
# 3848 "src/sqliteInt.h"
|
|
void sqlite3SetString(char **, sqlite3*, const char*);
|
|
void sqlite3ErrorMsg(Parse*, const char*, ...);
|
|
int sqlite3ErrorToParser(sqlite3*,int);
|
|
void sqlite3Dequote(char*);
|
|
void sqlite3DequoteExpr(Expr*);
|
|
void sqlite3TokenInit(Token*,char*);
|
|
int sqlite3KeywordCode(const unsigned char*, int);
|
|
int sqlite3RunParser(Parse*, const char*, char **);
|
|
void sqlite3FinishCoding(Parse*);
|
|
int sqlite3GetTempReg(Parse*);
|
|
void sqlite3ReleaseTempReg(Parse*,int);
|
|
int sqlite3GetTempRange(Parse*,int);
|
|
void sqlite3ReleaseTempRange(Parse*,int,int);
|
|
void sqlite3ClearTempRegCache(Parse*);
|
|
|
|
|
|
|
|
Expr *sqlite3ExprAlloc(sqlite3*,int,const Token*,int);
|
|
Expr *sqlite3Expr(sqlite3*,int,const char*);
|
|
void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*);
|
|
Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*);
|
|
void sqlite3PExprAddSelect(Parse*, Expr*, Select*);
|
|
Expr *sqlite3ExprAnd(Parse*,Expr*, Expr*);
|
|
Expr *sqlite3ExprSimplifiedAndOr(Expr*);
|
|
Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*, int);
|
|
void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
|
|
void sqlite3ExprDelete(sqlite3*, Expr*);
|
|
void sqlite3ExprUnmapAndDelete(Parse*, Expr*);
|
|
ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
|
|
ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
|
|
void sqlite3ExprListSetSortOrder(ExprList*,int);
|
|
void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
|
|
void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*);
|
|
void sqlite3ExprListDelete(sqlite3*, ExprList*);
|
|
u32 sqlite3ExprListFlags(const ExprList*);
|
|
int sqlite3IndexHasDuplicateRootPage(Index*);
|
|
int sqlite3Init(sqlite3*, char**);
|
|
int sqlite3InitCallback(void*, int, char**, char**);
|
|
int sqlite3InitOne(sqlite3*, int, char**, u32);
|
|
void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
|
|
|
|
Module *sqlite3PragmaVtabRegister(sqlite3*,const char *zName);
|
|
|
|
void sqlite3ResetAllSchemasOfConnection(sqlite3*);
|
|
void sqlite3ResetOneSchema(sqlite3*,int);
|
|
void sqlite3CollapseDatabaseArray(sqlite3*);
|
|
void sqlite3CommitInternalChanges(sqlite3*);
|
|
void sqlite3DeleteColumnNames(sqlite3*,Table*);
|
|
int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**);
|
|
void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*);
|
|
Table *sqlite3ResultSetOfSelect(Parse*,Select*);
|
|
void sqlite3OpenMasterTable(Parse *, int);
|
|
Index *sqlite3PrimaryKeyIndex(Table*);
|
|
i16 sqlite3ColumnOfIndex(Index*, i16);
|
|
void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int);
|
|
|
|
|
|
|
|
|
|
|
|
void sqlite3AddColumn(Parse*,Token*,Token*);
|
|
void sqlite3AddNotNull(Parse*, int);
|
|
void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int, int);
|
|
void sqlite3AddCheckConstraint(Parse*, Expr*);
|
|
void sqlite3AddDefaultValue(Parse*,Expr*,const char*,const char*);
|
|
void sqlite3AddCollateType(Parse*, Token*);
|
|
void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*);
|
|
int sqlite3ParseUri(const char*,const char*,unsigned int*,
|
|
sqlite3_vfs**,char**,char **);
|
|
|
|
|
|
|
|
|
|
|
|
Btree *sqlite3DbNameToBtree(sqlite3*,const char*);
|
|
|
|
|
|
|
|
|
|
int sqlite3FaultSim(int);
|
|
|
|
|
|
Bitvec *sqlite3BitvecCreate(u32);
|
|
int sqlite3BitvecTest(Bitvec*, u32);
|
|
int sqlite3BitvecTestNotNull(Bitvec*, u32);
|
|
int sqlite3BitvecSet(Bitvec*, u32);
|
|
void sqlite3BitvecClear(Bitvec*, u32, void*);
|
|
void sqlite3BitvecDestroy(Bitvec*);
|
|
u32 sqlite3BitvecSize(Bitvec*);
|
|
|
|
int sqlite3BitvecBuiltinTest(int,int*);
|
|
|
|
|
|
RowSet *sqlite3RowSetInit(sqlite3*);
|
|
void sqlite3RowSetDelete(void*);
|
|
void sqlite3RowSetClear(void*);
|
|
void sqlite3RowSetInsert(RowSet*, i64);
|
|
int sqlite3RowSetTest(RowSet*, int iBatch, i64);
|
|
int sqlite3RowSetNext(RowSet*, i64*);
|
|
|
|
void sqlite3CreateView(Parse*,Token*,Token*,Token*,ExprList*,Select*,int,int);
|
|
|
|
|
|
int sqlite3ViewGetColumnNames(Parse*,Table*);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void sqlite3DropTable(Parse*, SrcList*, int, int);
|
|
void sqlite3CodeDropTable(Parse*, Table*, int, int);
|
|
void sqlite3DeleteTable(sqlite3*, Table*);
|
|
void sqlite3FreeIndex(sqlite3*, Index*);
|
|
|
|
void sqlite3AutoincrementBegin(Parse *pParse);
|
|
void sqlite3AutoincrementEnd(Parse *pParse);
|
|
|
|
|
|
|
|
|
|
void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int, Upsert*);
|
|
void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*);
|
|
IdList *sqlite3IdListAppend(Parse*, IdList*, Token*);
|
|
int sqlite3IdListIndex(IdList*,const char*);
|
|
SrcList *sqlite3SrcListEnlarge(Parse*, SrcList*, int, int);
|
|
SrcList *sqlite3SrcListAppend(Parse*, SrcList*, Token*, Token*);
|
|
SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*,
|
|
Token*, Select*, Expr*, IdList*);
|
|
void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *);
|
|
void sqlite3SrcListFuncArgs(Parse*, SrcList*, ExprList*);
|
|
int sqlite3IndexedByLookup(Parse *, struct SrcList_item *);
|
|
void sqlite3SrcListShiftJoinType(SrcList*);
|
|
void sqlite3SrcListAssignCursors(Parse*, SrcList*);
|
|
void sqlite3IdListDelete(sqlite3*, IdList*);
|
|
void sqlite3SrcListDelete(sqlite3*, SrcList*);
|
|
Index *sqlite3AllocateIndexObject(sqlite3*,i16,int,char**);
|
|
void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
|
|
Expr*, int, int, u8);
|
|
void sqlite3DropIndex(Parse*, SrcList*, int);
|
|
int sqlite3Select(Parse*, Select*, SelectDest*);
|
|
Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
|
|
Expr*,ExprList*,u32,Expr*);
|
|
void sqlite3SelectDelete(sqlite3*, Select*);
|
|
Table *sqlite3SrcListLookup(Parse*, SrcList*);
|
|
int sqlite3IsReadOnly(Parse*, Table*, int);
|
|
void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
|
|
|
|
|
|
|
|
void sqlite3DeleteFrom(Parse*, SrcList*, Expr*, ExprList*, Expr*);
|
|
void sqlite3Update(Parse*, SrcList*, ExprList*,Expr*,int,ExprList*,Expr*,
|
|
Upsert*);
|
|
WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int);
|
|
void sqlite3WhereEnd(WhereInfo*);
|
|
LogEst sqlite3WhereOutputRowCount(WhereInfo*);
|
|
int sqlite3WhereIsDistinct(WhereInfo*);
|
|
int sqlite3WhereIsOrdered(WhereInfo*);
|
|
int sqlite3WhereOrderByLimitOptLabel(WhereInfo*);
|
|
int sqlite3WhereIsSorted(WhereInfo*);
|
|
int sqlite3WhereContinueLabel(WhereInfo*);
|
|
int sqlite3WhereBreakLabel(WhereInfo*);
|
|
int sqlite3WhereOkOnePass(WhereInfo*, int*);
|
|
|
|
|
|
|
|
void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int);
|
|
int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
|
|
void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
|
|
void sqlite3ExprCodeMove(Parse*, int, int, int);
|
|
void sqlite3ExprCode(Parse*, Expr*, int);
|
|
void sqlite3ExprCodeCopy(Parse*, Expr*, int);
|
|
void sqlite3ExprCodeFactorable(Parse*, Expr*, int);
|
|
int sqlite3ExprCodeAtInit(Parse*, Expr*, int);
|
|
int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
|
|
int sqlite3ExprCodeTarget(Parse*, Expr*, int);
|
|
void sqlite3ExprCodeAndCache(Parse*, Expr*, int);
|
|
int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int, u8);
|
|
|
|
|
|
|
|
|
|
void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
|
|
void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
|
|
void sqlite3ExprIfFalseDup(Parse*, Expr*, int, int);
|
|
Table *sqlite3FindTable(sqlite3*,const char*, const char*);
|
|
|
|
|
|
Table *sqlite3LocateTable(Parse*,u32 flags,const char*, const char*);
|
|
Table *sqlite3LocateTableItem(Parse*,u32 flags,struct SrcList_item *);
|
|
Index *sqlite3FindIndex(sqlite3*,const char*, const char*);
|
|
void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*);
|
|
void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*);
|
|
void sqlite3Vacuum(Parse*,Token*,Expr*);
|
|
int sqlite3RunVacuum(char**, sqlite3*, int, sqlite3_value*);
|
|
char *sqlite3NameFromToken(sqlite3*, Token*);
|
|
int sqlite3ExprCompare(Parse*,Expr*, Expr*, int);
|
|
int sqlite3ExprCompareSkip(Expr*, Expr*, int);
|
|
int sqlite3ExprListCompare(ExprList*, ExprList*, int);
|
|
int sqlite3ExprImpliesExpr(Parse*,Expr*, Expr*, int);
|
|
int sqlite3ExprImpliesNonNullRow(Expr*,int);
|
|
void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
|
|
void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
|
|
int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx);
|
|
int sqlite3FunctionUsesThisSrc(Expr*, SrcList*);
|
|
Vdbe *sqlite3GetVdbe(Parse*);
|
|
|
|
void sqlite3PrngSaveState(void);
|
|
void sqlite3PrngRestoreState(void);
|
|
|
|
void sqlite3RollbackAll(sqlite3*,int);
|
|
void sqlite3CodeVerifySchema(Parse*, int);
|
|
void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb);
|
|
void sqlite3BeginTransaction(Parse*, int);
|
|
void sqlite3EndTransaction(Parse*,int);
|
|
void sqlite3Savepoint(Parse*, int, Token*);
|
|
void sqlite3CloseSavepoints(sqlite3 *);
|
|
void sqlite3LeaveMutexAndCloseZombie(sqlite3*);
|
|
int sqlite3ExprIdToTrueFalse(Expr*);
|
|
int sqlite3ExprTruthValue(const Expr*);
|
|
int sqlite3ExprIsConstant(Expr*);
|
|
int sqlite3ExprIsConstantNotJoin(Expr*);
|
|
int sqlite3ExprIsConstantOrFunction(Expr*, u8);
|
|
int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*);
|
|
int sqlite3ExprIsTableConstant(Expr*,int);
|
|
|
|
|
|
|
|
int sqlite3ExprIsInteger(Expr*, int*);
|
|
int sqlite3ExprCanBeNull(const Expr*);
|
|
int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
|
|
int sqlite3IsRowid(const char*);
|
|
void sqlite3GenerateRowDelete(
|
|
Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int);
|
|
void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int);
|
|
int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int);
|
|
void sqlite3ResolvePartIdxLabel(Parse*,int);
|
|
int sqlite3ExprReferencesUpdatedColumn(Expr*,int*,int);
|
|
void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,
|
|
u8,u8,int,int*,int*,Upsert*);
|
|
|
|
|
|
|
|
|
|
|
|
void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int);
|
|
int sqlite3OpenTableAndIndices(Parse*, Table*, int, u8, int, u8*, int*, int*);
|
|
void sqlite3BeginWriteOperation(Parse*, int, int);
|
|
void sqlite3MultiWrite(Parse*);
|
|
void sqlite3MayAbort(Parse*);
|
|
void sqlite3HaltConstraint(Parse*, int, int, char*, i8, u8);
|
|
void sqlite3UniqueConstraint(Parse*, int, Index*);
|
|
void sqlite3RowidConstraint(Parse*, int, Table*);
|
|
Expr *sqlite3ExprDup(sqlite3*,Expr*,int);
|
|
ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
|
|
SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int);
|
|
IdList *sqlite3IdListDup(sqlite3*,IdList*);
|
|
Select *sqlite3SelectDup(sqlite3*,Select*,int);
|
|
FuncDef *sqlite3FunctionSearch(int,const char*);
|
|
void sqlite3InsertBuiltinFuncs(FuncDef*,int);
|
|
FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8);
|
|
void sqlite3RegisterBuiltinFunctions(void);
|
|
void sqlite3RegisterDateTimeFunctions(void);
|
|
void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3*);
|
|
int sqlite3SafetyCheckOk(sqlite3*);
|
|
int sqlite3SafetyCheckSickOrOk(sqlite3*);
|
|
void sqlite3ChangeCookie(Parse*, int);
|
|
|
|
|
|
void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int);
|
|
|
|
|
|
|
|
void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*,
|
|
Expr*,int, int);
|
|
void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*);
|
|
void sqlite3DropTrigger(Parse*, SrcList*, int);
|
|
void sqlite3DropTriggerPtr(Parse*, Trigger*);
|
|
Trigger *sqlite3TriggersExist(Parse *, Table*, int, ExprList*, int *pMask);
|
|
Trigger *sqlite3TriggerList(Parse *, Table *);
|
|
void sqlite3CodeRowTrigger(Parse*, Trigger *, int, ExprList*, int, Table *,
|
|
int, int, int);
|
|
void sqlite3CodeRowTriggerDirect(Parse *, Trigger *, Table *, int, int, int);
|
|
void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*);
|
|
void sqlite3DeleteTriggerStep(sqlite3*, TriggerStep*);
|
|
TriggerStep *sqlite3TriggerSelectStep(sqlite3*,Select*,
|
|
const char*,const char*);
|
|
TriggerStep *sqlite3TriggerInsertStep(Parse*,Token*, IdList*,
|
|
Select*,u8,Upsert*,
|
|
const char*,const char*);
|
|
TriggerStep *sqlite3TriggerUpdateStep(Parse*,Token*,ExprList*, Expr*, u8,
|
|
const char*,const char*);
|
|
TriggerStep *sqlite3TriggerDeleteStep(Parse*,Token*, Expr*,
|
|
const char*,const char*);
|
|
void sqlite3DeleteTrigger(sqlite3*, Trigger*);
|
|
void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
|
|
u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int);
|
|
# 4161 "src/sqliteInt.h"
|
|
int sqlite3JoinType(Parse*, Token*, Token*, Token*);
|
|
void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int);
|
|
void sqlite3DeferForeignKey(Parse*, int);
|
|
|
|
void sqlite3AuthRead(Parse*,Expr*,Schema*,SrcList*);
|
|
int sqlite3AuthCheck(Parse*,int, const char*, const char*, const char*);
|
|
void sqlite3AuthContextPush(Parse*, AuthContext*, const char*);
|
|
void sqlite3AuthContextPop(AuthContext*);
|
|
int sqlite3AuthReadCol(Parse*, const char *, const char *, int);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void sqlite3Attach(Parse*, Expr*, Expr*, Expr*);
|
|
void sqlite3Detach(Parse*, Expr*);
|
|
void sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*);
|
|
int sqlite3FixSrcList(DbFixer*, SrcList*);
|
|
int sqlite3FixSelect(DbFixer*, Select*);
|
|
int sqlite3FixExpr(DbFixer*, Expr*);
|
|
int sqlite3FixExprList(DbFixer*, ExprList*);
|
|
int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
|
|
int sqlite3RealSameAsInt(double,sqlite3_int64);
|
|
int sqlite3AtoF(const char *z, double*, int, u8);
|
|
int sqlite3GetInt32(const char *, int*);
|
|
int sqlite3Atoi(const char*);
|
|
|
|
int sqlite3Utf16ByteLen(const void *pData, int nChar);
|
|
|
|
int sqlite3Utf8CharLen(const char *pData, int nByte);
|
|
u32 sqlite3Utf8Read(const u8**);
|
|
LogEst sqlite3LogEst(u64);
|
|
LogEst sqlite3LogEstAdd(LogEst,LogEst);
|
|
|
|
LogEst sqlite3LogEstFromDouble(double);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VList *sqlite3VListAdd(sqlite3*,VList*,const char*,int,int);
|
|
const char *sqlite3VListNumToName(VList*,int);
|
|
int sqlite3VListNameToNum(VList*,const char*,int);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int sqlite3PutVarint(unsigned char*, u64);
|
|
u8 sqlite3GetVarint(const unsigned char *, u64 *);
|
|
u8 sqlite3GetVarint32(const unsigned char *, u32 *);
|
|
int sqlite3VarintLen(u64 v);
|
|
# 4231 "src/sqliteInt.h"
|
|
const char *sqlite3IndexAffinityStr(sqlite3*, Index*);
|
|
void sqlite3TableAffinity(Vdbe*, Table*, int);
|
|
char sqlite3CompareAffinity(Expr *pExpr, char aff2);
|
|
int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
|
|
char sqlite3TableColumnAffinity(Table*,int);
|
|
char sqlite3ExprAffinity(Expr *pExpr);
|
|
int sqlite3Atoi64(const char*, i64*, int, u8);
|
|
int sqlite3DecOrHexToI64(const char*, i64*);
|
|
void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...);
|
|
void sqlite3Error(sqlite3*,int);
|
|
void sqlite3SystemError(sqlite3*,int);
|
|
void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
|
|
u8 sqlite3HexToInt(int h);
|
|
int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
|
|
# 4254 "src/sqliteInt.h"
|
|
const char *sqlite3ErrStr(int);
|
|
int sqlite3ReadSchema(Parse *pParse);
|
|
CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
|
|
int sqlite3IsBinary(const CollSeq*);
|
|
CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
|
|
CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
|
|
CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr);
|
|
int sqlite3ExprCollSeqMatch(Parse*,Expr*,Expr*);
|
|
Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int);
|
|
Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
|
|
Expr *sqlite3ExprSkipCollate(Expr*);
|
|
int sqlite3CheckCollSeq(Parse *, CollSeq *);
|
|
int sqlite3WritableSchema(sqlite3*);
|
|
int sqlite3CheckObjectName(Parse *, const char *);
|
|
void sqlite3VdbeSetChanges(sqlite3 *, int);
|
|
int sqlite3AddInt64(i64*,i64);
|
|
int sqlite3SubInt64(i64*,i64);
|
|
int sqlite3MulInt64(i64*,i64);
|
|
int sqlite3AbsInt32(int);
|
|
|
|
|
|
|
|
|
|
|
|
u8 sqlite3GetBoolean(const char *z,u8);
|
|
|
|
const void *sqlite3ValueText(sqlite3_value*, u8);
|
|
int sqlite3ValueBytes(sqlite3_value*, u8);
|
|
void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8,
|
|
void(*)(void*));
|
|
void sqlite3ValueSetNull(sqlite3_value*);
|
|
void sqlite3ValueFree(sqlite3_value*);
|
|
|
|
void sqlite3ResultIntReal(sqlite3_context*);
|
|
|
|
sqlite3_value *sqlite3ValueNew(sqlite3 *);
|
|
|
|
char *sqlite3Utf16to8(sqlite3 *, const void*, int, u8);
|
|
|
|
int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **);
|
|
void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
|
|
|
|
extern const unsigned char sqlite3OpcodeProperty[];
|
|
extern const char sqlite3StrBINARY[];
|
|
extern const unsigned char sqlite3UpperToLower[];
|
|
extern const unsigned char sqlite3CtypeMap[];
|
|
extern const Token sqlite3IntTokens[];
|
|
extern struct Sqlite3Config sqlite3Config;
|
|
extern FuncDefHash sqlite3BuiltinFunctions;
|
|
|
|
extern int sqlite3PendingByte;
|
|
|
|
|
|
|
|
|
|
|
|
void sqlite3RootPageMoved(sqlite3*, int, int, int);
|
|
void sqlite3Reindex(Parse*, Token*, Token*);
|
|
void sqlite3AlterFunctions(void);
|
|
void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
|
|
void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*);
|
|
int sqlite3GetToken(const unsigned char *, int *);
|
|
void sqlite3NestedParse(Parse*, const char*, ...);
|
|
void sqlite3ExpirePreparedStatements(sqlite3*, int);
|
|
void sqlite3CodeRhsOfIN(Parse*, Expr*, int);
|
|
int sqlite3CodeSubselect(Parse*, Expr*);
|
|
void sqlite3SelectPrep(Parse*, Select*, NameContext*);
|
|
void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p);
|
|
int sqlite3MatchSpanName(const char*, const char*, const char*, const char*);
|
|
int sqlite3ResolveExprNames(NameContext*, Expr*);
|
|
int sqlite3ResolveExprListNames(NameContext*, ExprList*);
|
|
void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
|
|
int sqlite3ResolveSelfReference(Parse*,Table*,int,Expr*,ExprList*);
|
|
int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
|
|
void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
|
|
void sqlite3AlterFinishAddColumn(Parse *, Token *);
|
|
void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
|
|
void *sqlite3RenameTokenMap(Parse*, void*, Token*);
|
|
void sqlite3RenameTokenRemap(Parse*, void *pTo, void *pFrom);
|
|
void sqlite3RenameExprUnmap(Parse*, Expr*);
|
|
void sqlite3RenameExprlistUnmap(Parse*, ExprList*);
|
|
CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
|
|
char sqlite3AffinityType(const char*, Column*);
|
|
void sqlite3Analyze(Parse*, Token*, Token*);
|
|
int sqlite3InvokeBusyHandler(BusyHandler*, sqlite3_file*);
|
|
int sqlite3FindDb(sqlite3*, Token*);
|
|
int sqlite3FindDbName(sqlite3 *, const char *);
|
|
int sqlite3AnalysisLoad(sqlite3*,int iDB);
|
|
void sqlite3DeleteIndexSamples(sqlite3*,Index*);
|
|
void sqlite3DefaultRowEst(Index*);
|
|
void sqlite3RegisterLikeFunctions(sqlite3*, int);
|
|
int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*);
|
|
void sqlite3SchemaClear(void *);
|
|
Schema *sqlite3SchemaGet(sqlite3 *, Btree *);
|
|
int sqlite3SchemaToIndex(sqlite3 *db, Schema *);
|
|
KeyInfo *sqlite3KeyInfoAlloc(sqlite3*,int,int);
|
|
void sqlite3KeyInfoUnref(KeyInfo*);
|
|
KeyInfo *sqlite3KeyInfoRef(KeyInfo*);
|
|
KeyInfo *sqlite3KeyInfoOfIndex(Parse*, Index*);
|
|
KeyInfo *sqlite3KeyInfoFromExprList(Parse*, ExprList*, int, int);
|
|
|
|
|
|
|
|
|
|
int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *,
|
|
void (*)(sqlite3_context*,int,sqlite3_value **),
|
|
void (*)(sqlite3_context*,int,sqlite3_value **),
|
|
void (*)(sqlite3_context*),
|
|
void (*)(sqlite3_context*),
|
|
void (*)(sqlite3_context*,int,sqlite3_value **),
|
|
FuncDestructor *pDestructor
|
|
);
|
|
void sqlite3NoopDestructor(void*);
|
|
void sqlite3OomFault(sqlite3*);
|
|
void sqlite3OomClear(sqlite3*);
|
|
int sqlite3ApiExit(sqlite3 *db, int);
|
|
int sqlite3OpenTempDatabase(Parse *);
|
|
|
|
void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int);
|
|
char *sqlite3StrAccumFinish(StrAccum*);
|
|
void sqlite3SelectDestInit(SelectDest*,int,int);
|
|
Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int);
|
|
|
|
void sqlite3BackupRestart(sqlite3_backup *);
|
|
void sqlite3BackupUpdate(sqlite3_backup *, Pgno, const u8 *);
|
|
|
|
|
|
int sqlite3ExprCheckIN(Parse*, Expr*);
|
|
# 4400 "src/sqliteInt.h"
|
|
void *sqlite3ParserAlloc(void*(*)(u64), Parse*);
|
|
void sqlite3ParserFree(void*, void(*)(void*));
|
|
|
|
void sqlite3Parser(void*, int, Token);
|
|
int sqlite3ParserFallback(int);
|
|
|
|
|
|
|
|
|
|
void sqlite3AutoLoadExtensions(sqlite3*);
|
|
|
|
void sqlite3CloseExtensions(sqlite3*);
|
|
|
|
|
|
|
|
|
|
|
|
void sqlite3TableLock(Parse *, int, int, u8, const char *);
|
|
# 4438 "src/sqliteInt.h"
|
|
void sqlite3VtabClear(sqlite3 *db, Table*);
|
|
void sqlite3VtabDisconnect(sqlite3 *db, Table *p);
|
|
int sqlite3VtabSync(sqlite3 *db, Vdbe*);
|
|
int sqlite3VtabRollback(sqlite3 *db);
|
|
int sqlite3VtabCommit(sqlite3 *db);
|
|
void sqlite3VtabLock(VTable *);
|
|
void sqlite3VtabUnlock(VTable *);
|
|
void sqlite3VtabUnlockList(sqlite3*);
|
|
int sqlite3VtabSavepoint(sqlite3 *, int, int);
|
|
void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*);
|
|
VTable *sqlite3GetVTable(sqlite3*, Table*);
|
|
Module *sqlite3VtabCreateModule(
|
|
sqlite3*,
|
|
const char*,
|
|
const sqlite3_module*,
|
|
void*,
|
|
void(*)(void*)
|
|
);
|
|
|
|
|
|
int sqlite3VtabEponymousTableInit(Parse*,Module*);
|
|
void sqlite3VtabEponymousTableClear(sqlite3*,Module*);
|
|
void sqlite3VtabMakeWritable(Parse*,Table*);
|
|
void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*, int);
|
|
void sqlite3VtabFinishParse(Parse*, Token*);
|
|
void sqlite3VtabArgInit(Parse*);
|
|
void sqlite3VtabArgExtend(Parse*, Token*);
|
|
int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **);
|
|
int sqlite3VtabCallConnect(Parse*, Table*);
|
|
int sqlite3VtabCallDestroy(sqlite3*, int, const char *);
|
|
int sqlite3VtabBegin(sqlite3 *, VTable *);
|
|
FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
|
|
sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*);
|
|
int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
|
|
int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
|
|
void sqlite3ParserReset(Parse*);
|
|
|
|
|
|
|
|
int sqlite3Reprepare(Vdbe*);
|
|
void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
|
|
CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
|
|
int sqlite3TempInMemory(const sqlite3*);
|
|
const char *sqlite3JournalModename(int);
|
|
|
|
int sqlite3Checkpoint(sqlite3*, int, int, int*, int*);
|
|
int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int);
|
|
|
|
|
|
With *sqlite3WithAdd(Parse*,With*,Token*,ExprList*,Select*);
|
|
void sqlite3WithDelete(sqlite3*,With*);
|
|
void sqlite3WithPush(Parse*, With*, u8);
|
|
|
|
|
|
|
|
|
|
|
|
Upsert *sqlite3UpsertNew(sqlite3*,ExprList*,Expr*,ExprList*,Expr*);
|
|
void sqlite3UpsertDelete(sqlite3*,Upsert*);
|
|
Upsert *sqlite3UpsertDup(sqlite3*,Upsert*);
|
|
int sqlite3UpsertAnalyzeTarget(Parse*,SrcList*,Upsert*);
|
|
void sqlite3UpsertDoUpdate(Parse*,Upsert*,Table*,Index*,int);
|
|
# 4515 "src/sqliteInt.h"
|
|
void sqlite3FkCheck(Parse*, Table*, int, int, int*, int);
|
|
void sqlite3FkDropTable(Parse*, SrcList *, Table*);
|
|
void sqlite3FkActions(Parse*, Table*, ExprList*, int, int*, int);
|
|
int sqlite3FkRequired(Parse*, Table*, int*, int);
|
|
u32 sqlite3FkOldmask(Parse*, Table*);
|
|
FKey *sqlite3FkReferences(Table *);
|
|
# 4530 "src/sqliteInt.h"
|
|
void sqlite3FkDelete(sqlite3 *, Table*);
|
|
int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**);
|
|
# 4550 "src/sqliteInt.h"
|
|
void sqlite3BeginBenignMalloc(void);
|
|
void sqlite3EndBenignMalloc(void);
|
|
# 4571 "src/sqliteInt.h"
|
|
int sqlite3FindInIndex(Parse *, Expr *, u32, int*, int*, int*);
|
|
|
|
int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int);
|
|
int sqlite3JournalSize(sqlite3_vfs *);
|
|
|
|
|
|
|
|
|
|
|
|
int sqlite3JournalIsInMemory(sqlite3_file *p);
|
|
void sqlite3MemJournalOpen(sqlite3_file *);
|
|
|
|
void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p);
|
|
|
|
int sqlite3SelectExprHeight(Select *);
|
|
int sqlite3ExprCheckHeight(Parse*, int);
|
|
|
|
|
|
|
|
|
|
|
|
u32 sqlite3Get4byte(const u8*);
|
|
void sqlite3Put4byte(u8*, u32);
|
|
# 4671 "src/sqliteInt.h"
|
|
int sqlite3ThreadCreate(SQLiteThread**,void*(*)(void*),void*);
|
|
int sqlite3ThreadJoin(SQLiteThread*, void**);
|
|
# 4682 "src/sqliteInt.h"
|
|
int sqlite3ExprVectorSize(Expr *pExpr);
|
|
int sqlite3ExprIsVector(Expr *pExpr);
|
|
Expr *sqlite3VectorFieldSubexpr(Expr*, int);
|
|
Expr *sqlite3ExprForVectorField(Parse*,Expr*,int);
|
|
void sqlite3VectorErrorMsg(Parse*, Expr*);
|
|
|
|
|
|
const char **sqlite3CompileOptions(int *pnOpt);
|
|
# 217 "src/btreeInt.h" 2
|
|
# 232 "src/btreeInt.h"
|
|
typedef struct MemPage MemPage;
|
|
typedef struct BtLock BtLock;
|
|
typedef struct CellInfo CellInfo;
|
|
# 273 "src/btreeInt.h"
|
|
struct MemPage {
|
|
u8 isInit;
|
|
u8 bBusy;
|
|
u8 intKey;
|
|
u8 intKeyLeaf;
|
|
Pgno pgno;
|
|
|
|
|
|
u8 leaf;
|
|
u8 hdrOffset;
|
|
u8 childPtrSize;
|
|
u8 max1bytePayload;
|
|
u8 nOverflow;
|
|
u16 maxLocal;
|
|
u16 minLocal;
|
|
u16 cellOffset;
|
|
int nFree;
|
|
u16 nCell;
|
|
u16 maskPage;
|
|
u16 aiOvfl[4];
|
|
|
|
u8 *apOvfl[4];
|
|
BtShared *pBt;
|
|
u8 *aData;
|
|
u8 *aDataEnd;
|
|
u8 *aCellIdx;
|
|
u8 *aDataOfst;
|
|
DbPage *pDbPage;
|
|
u16 (*xCellSize)(MemPage*,u8*);
|
|
void (*xParseCell)(MemPage*,u8*,CellInfo*);
|
|
};
|
|
# 312 "src/btreeInt.h"
|
|
struct BtLock {
|
|
Btree *pBtree;
|
|
Pgno iTable;
|
|
u8 eLock;
|
|
BtLock *pNext;
|
|
};
|
|
# 344 "src/btreeInt.h"
|
|
struct Btree {
|
|
sqlite3 *db;
|
|
BtShared *pBt;
|
|
u8 inTrans;
|
|
u8 sharable;
|
|
u8 locked;
|
|
u8 hasIncrblobCur;
|
|
int wantToLock;
|
|
int nBackup;
|
|
u32 iDataVersion;
|
|
Btree *pNext;
|
|
Btree *pPrev;
|
|
|
|
BtLock lock;
|
|
|
|
};
|
|
# 407 "src/btreeInt.h"
|
|
struct BtShared {
|
|
Pager *pPager;
|
|
sqlite3 *db;
|
|
BtCursor *pCursor;
|
|
MemPage *pPage1;
|
|
u8 openFlags;
|
|
|
|
u8 autoVacuum;
|
|
u8 incrVacuum;
|
|
u8 bDoTruncate;
|
|
|
|
u8 inTransaction;
|
|
u8 max1bytePayload;
|
|
|
|
|
|
|
|
u16 btsFlags;
|
|
u16 maxLocal;
|
|
u16 minLocal;
|
|
u16 maxLeaf;
|
|
u16 minLeaf;
|
|
u32 pageSize;
|
|
u32 usableSize;
|
|
int nTransaction;
|
|
u32 nPage;
|
|
void *pSchema;
|
|
void (*xFreeSchema)(void*);
|
|
sqlite3_mutex *mutex;
|
|
Bitvec *pHasContent;
|
|
|
|
int nRef;
|
|
BtShared *pNext;
|
|
BtLock *pLock;
|
|
Btree *pWriter;
|
|
|
|
u8 *pTmpSpace;
|
|
};
|
|
# 463 "src/btreeInt.h"
|
|
struct CellInfo {
|
|
i64 nKey;
|
|
u8 *pPayload;
|
|
u32 nPayload;
|
|
u16 nLocal;
|
|
u16 nSize;
|
|
};
|
|
# 508 "src/btreeInt.h"
|
|
struct BtCursor {
|
|
u8 eState;
|
|
u8 curFlags;
|
|
u8 curPagerFlags;
|
|
u8 hints;
|
|
int skipNext;
|
|
|
|
Btree *pBtree;
|
|
Pgno *aOverflow;
|
|
void *pKey;
|
|
|
|
|
|
|
|
|
|
BtShared *pBt;
|
|
BtCursor *pNext;
|
|
CellInfo info;
|
|
i64 nKey;
|
|
Pgno pgnoRoot;
|
|
i8 iPage;
|
|
u8 curIntKey;
|
|
u16 ix;
|
|
u16 aiIdx[20 -1];
|
|
struct KeyInfo *pKeyInfo;
|
|
MemPage *pPage;
|
|
MemPage *apPage[20 -1];
|
|
};
|
|
# 675 "src/btreeInt.h"
|
|
typedef struct IntegrityCk IntegrityCk;
|
|
struct IntegrityCk {
|
|
BtShared *pBt;
|
|
Pager *pPager;
|
|
u8 *aPgRef;
|
|
Pgno nPage;
|
|
int mxErr;
|
|
int nErr;
|
|
int mallocFailed;
|
|
const char *zPfx;
|
|
int v1, v2;
|
|
StrAccum errMsg;
|
|
u32 *heap;
|
|
};
|
|
# 17 "src/btree.c" 2
|
|
|
|
|
|
|
|
|
|
|
|
static const char zMagicHeader[] = "SQLite format 3";
|
|
# 77 "src/btree.c"
|
|
static BtShared * sqlite3SharedCacheList = 0;
|
|
# 89 "src/btree.c"
|
|
int sqlite3_enable_shared_cache(int enable){
|
|
sqlite3Config.sharedCacheEnabled = enable;
|
|
return 0;
|
|
}
|
|
# 275 "src/btree.c"
|
|
static int querySharedCacheTableLock(Btree *p, Pgno iTab, u8 eLock){
|
|
BtShared *pBt = p->pBt;
|
|
BtLock *pIter;
|
|
|
|
assert( sqlite3BtreeHoldsMutex(p) );
|
|
assert( eLock==1 || eLock==2 );
|
|
assert( p->db!=0 );
|
|
assert( !(p->db->flags&0x00000400)||eLock==2||iTab==1 );
|
|
|
|
|
|
|
|
|
|
|
|
assert( eLock==1 || (p==pBt->pWriter && p->inTrans==2) );
|
|
assert( eLock==1 || pBt->inTransaction==2 );
|
|
|
|
|
|
if( !p->sharable ){
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
if( pBt->pWriter!=p && (pBt->btsFlags & 0x0040)!=0 ){
|
|
;
|
|
return (6 | (1<<8));
|
|
}
|
|
|
|
for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
|
|
# 314 "src/btree.c"
|
|
assert( pIter->eLock==1 || pIter->eLock==2 );
|
|
assert( eLock==1 || pIter->pBtree==p || pIter->eLock==1);
|
|
if( pIter->pBtree!=p && pIter->iTable==iTab && pIter->eLock!=eLock ){
|
|
;
|
|
if( eLock==2 ){
|
|
assert( p==pBt->pWriter );
|
|
pBt->btsFlags |= 0x0080;
|
|
}
|
|
return (6 | (1<<8));
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
# 347 "src/btree.c"
|
|
static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){
|
|
BtShared *pBt = p->pBt;
|
|
BtLock *pLock = 0;
|
|
BtLock *pIter;
|
|
|
|
assert( sqlite3BtreeHoldsMutex(p) );
|
|
assert( eLock==1 || eLock==2 );
|
|
assert( p->db!=0 );
|
|
|
|
|
|
|
|
|
|
|
|
assert( 0==(p->db->flags&0x00000400) || eLock==2 );
|
|
|
|
|
|
|
|
assert( p->sharable );
|
|
assert( 0==querySharedCacheTableLock(p, iTable, eLock) );
|
|
|
|
|
|
for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
|
|
if( pIter->iTable==iTable && pIter->pBtree==p ){
|
|
pLock = pIter;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
if( !pLock ){
|
|
pLock = (BtLock *)sqlite3MallocZero(sizeof(BtLock));
|
|
if( !pLock ){
|
|
return 7;
|
|
}
|
|
pLock->iTable = iTable;
|
|
pLock->pBtree = p;
|
|
pLock->pNext = pBt->pLock;
|
|
pBt->pLock = pLock;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
assert( 2>1 );
|
|
if( eLock>pLock->eLock ){
|
|
pLock->eLock = eLock;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
# 411 "src/btree.c"
|
|
static void clearAllSharedCacheTableLocks(Btree *p){
|
|
BtShared *pBt = p->pBt;
|
|
BtLock **ppIter = &pBt->pLock;
|
|
|
|
assert( sqlite3BtreeHoldsMutex(p) );
|
|
assert( p->sharable || 0==*ppIter );
|
|
assert( p->inTrans>0 );
|
|
|
|
while( *ppIter ){
|
|
BtLock *pLock = *ppIter;
|
|
assert( (pBt->btsFlags & 0x0040)==0 || pBt->pWriter==pLock->pBtree );
|
|
assert( pLock->pBtree->inTrans>=pLock->eLock );
|
|
if( pLock->pBtree==p ){
|
|
*ppIter = pLock->pNext;
|
|
assert( pLock->iTable!=1 || pLock==&p->lock );
|
|
if( pLock->iTable!=1 ){
|
|
sqlite3_free(pLock);
|
|
}
|
|
}else{
|
|
ppIter = &pLock->pNext;
|
|
}
|
|
}
|
|
|
|
assert( (pBt->btsFlags & 0x0080)==0 || pBt->pWriter );
|
|
if( pBt->pWriter==p ){
|
|
pBt->pWriter = 0;
|
|
pBt->btsFlags &= ~(0x0040|0x0080);
|
|
}else if( pBt->nTransaction==2 ){
|
|
# 448 "src/btree.c"
|
|
pBt->btsFlags &= ~0x0080;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
static void downgradeAllSharedCacheTableLocks(Btree *p){
|
|
BtShared *pBt = p->pBt;
|
|
if( pBt->pWriter==p ){
|
|
BtLock *pLock;
|
|
pBt->pWriter = 0;
|
|
pBt->btsFlags &= ~(0x0040|0x0080);
|
|
for(pLock=pBt->pLock; pLock; pLock=pLock->pNext){
|
|
assert( pLock->eLock==1 || pLock->pBtree==p );
|
|
pLock->eLock = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void releasePage(MemPage *pPage);
|
|
static void releasePageOne(MemPage *pPage);
|
|
static void releasePageNotNull(MemPage *pPage);
|
|
# 508 "src/btree.c"
|
|
static void invalidateAllOverflowCache(BtShared *pBt){
|
|
BtCursor *p;
|
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
|
for(p=pBt->pCursor; p; p=p->pNext){
|
|
(p->curFlags &= ~0x04);
|
|
}
|
|
}
|
|
# 530 "src/btree.c"
|
|
static void invalidateIncrblobCursors(
|
|
Btree *pBtree,
|
|
Pgno pgnoRoot,
|
|
i64 iRow,
|
|
int isClearTable
|
|
){
|
|
BtCursor *p;
|
|
if( pBtree->hasIncrblobCur==0 ) return;
|
|
assert( sqlite3BtreeHoldsMutex(pBtree) );
|
|
pBtree->hasIncrblobCur = 0;
|
|
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
|
|
if( (p->curFlags & 0x10)!=0 ){
|
|
pBtree->hasIncrblobCur = 1;
|
|
if( p->pgnoRoot==pgnoRoot && (isClearTable || p->info.nKey==iRow) ){
|
|
p->eState = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
# 590 "src/btree.c"
|
|
static int btreeSetHasContent(BtShared *pBt, Pgno pgno){
|
|
int rc = 0;
|
|
if( !pBt->pHasContent ){
|
|
assert( pgno<=pBt->nPage );
|
|
pBt->pHasContent = sqlite3BitvecCreate(pBt->nPage);
|
|
if( !pBt->pHasContent ){
|
|
rc = 7;
|
|
}
|
|
}
|
|
if( rc==0 && pgno<=sqlite3BitvecSize(pBt->pHasContent) ){
|
|
rc = sqlite3BitvecSet(pBt->pHasContent, pgno);
|
|
}
|
|
return rc;
|
|
}
|
|
# 612 "src/btree.c"
|
|
static int btreeGetHasContent(BtShared *pBt, Pgno pgno){
|
|
Bitvec *p = pBt->pHasContent;
|
|
return (p && (pgno>sqlite3BitvecSize(p) || sqlite3BitvecTest(p, pgno)));
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void btreeClearHasContent(BtShared *pBt){
|
|
sqlite3BitvecDestroy(pBt->pHasContent);
|
|
pBt->pHasContent = 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
static void btreeReleaseAllCursorPages(BtCursor *pCur){
|
|
int i;
|
|
if( pCur->iPage>=0 ){
|
|
for(i=0; i<pCur->iPage; i++){
|
|
releasePageNotNull(pCur->apPage[i]);
|
|
}
|
|
releasePageNotNull(pCur->pPage);
|
|
pCur->iPage = -1;
|
|
}
|
|
}
|
|
# 653 "src/btree.c"
|
|
static int saveCursorKey(BtCursor *pCur){
|
|
int rc = 0;
|
|
assert( 0==pCur->eState );
|
|
assert( 0==pCur->pKey );
|
|
assert( cursorHoldsMutex(pCur) );
|
|
|
|
if( pCur->curIntKey ){
|
|
|
|
pCur->nKey = sqlite3BtreeIntegerKey(pCur);
|
|
}else{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void *pKey;
|
|
pCur->nKey = sqlite3BtreePayloadSize(pCur);
|
|
pKey = sqlite3Malloc( pCur->nKey + 9 + 8 );
|
|
if( pKey ){
|
|
rc = sqlite3BtreePayload(pCur, 0, (int)pCur->nKey, pKey);
|
|
if( rc==0 ){
|
|
memset(((u8*)pKey)+pCur->nKey, 0, 9+8);
|
|
pCur->pKey = pKey;
|
|
}else{
|
|
sqlite3_free(pKey);
|
|
}
|
|
}else{
|
|
rc = 7;
|
|
}
|
|
}
|
|
assert( !pCur->curIntKey || !pCur->pKey );
|
|
return rc;
|
|
}
|
|
# 695 "src/btree.c"
|
|
static int saveCursorPosition(BtCursor *pCur){
|
|
int rc;
|
|
|
|
assert( 0==pCur->eState || 2==pCur->eState );
|
|
assert( 0==pCur->pKey );
|
|
assert( cursorHoldsMutex(pCur) );
|
|
|
|
if( pCur->eState==2 ){
|
|
pCur->eState = 0;
|
|
}else{
|
|
pCur->skipNext = 0;
|
|
}
|
|
|
|
rc = saveCursorKey(pCur);
|
|
if( rc==0 ){
|
|
btreeReleaseAllCursorPages(pCur);
|
|
pCur->eState = 3;
|
|
}
|
|
|
|
pCur->curFlags &= ~(0x02|0x04|0x08);
|
|
return rc;
|
|
}
|
|
|
|
|
|
static int saveCursorsOnList(BtCursor*,Pgno,BtCursor*);
|
|
# 742 "src/btree.c"
|
|
static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){
|
|
BtCursor *p;
|
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
|
assert( pExcept==0 || pExcept->pBt==pBt );
|
|
for(p=pBt->pCursor; p; p=p->pNext){
|
|
if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ) break;
|
|
}
|
|
if( p ) return saveCursorsOnList(p, iRoot, pExcept);
|
|
if( pExcept ) pExcept->curFlags &= ~0x20;
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int saveCursorsOnList(
|
|
BtCursor *p,
|
|
Pgno iRoot,
|
|
BtCursor *pExcept
|
|
){
|
|
do{
|
|
if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ){
|
|
if( p->eState==0 || p->eState==2 ){
|
|
int rc = saveCursorPosition(p);
|
|
if( 0!=rc ){
|
|
return rc;
|
|
}
|
|
}else{
|
|
;
|
|
btreeReleaseAllCursorPages(p);
|
|
}
|
|
}
|
|
p = p->pNext;
|
|
}while( p );
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
void sqlite3BtreeClearCursor(BtCursor *pCur){
|
|
assert( cursorHoldsMutex(pCur) );
|
|
sqlite3_free(pCur->pKey);
|
|
pCur->pKey = 0;
|
|
pCur->eState = 1;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int btreeMoveto(
|
|
BtCursor *pCur,
|
|
const void *pKey,
|
|
i64 nKey,
|
|
int bias,
|
|
int *pRes
|
|
){
|
|
int rc;
|
|
UnpackedRecord *pIdxKey;
|
|
|
|
if( pKey ){
|
|
KeyInfo *pKeyInfo = pCur->pKeyInfo;
|
|
assert( nKey==(i64)(int)nKey );
|
|
pIdxKey = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
|
|
if( pIdxKey==0 ) return 7;
|
|
sqlite3VdbeRecordUnpack(pKeyInfo, (int)nKey, pKey, pIdxKey);
|
|
if( pIdxKey->nField==0 || pIdxKey->nField>pKeyInfo->nAllField ){
|
|
rc = sqlite3CorruptError(813);
|
|
goto moveto_done;
|
|
}
|
|
}else{
|
|
pIdxKey = 0;
|
|
}
|
|
rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes);
|
|
moveto_done:
|
|
if( pIdxKey ){
|
|
sqlite3DbFree(pCur->pKeyInfo->db, pIdxKey);
|
|
}
|
|
return rc;
|
|
}
|
|
# 834 "src/btree.c"
|
|
static int btreeRestoreCursorPosition(BtCursor *pCur){
|
|
int rc;
|
|
int skipNext = 0;
|
|
assert( cursorOwnsBtShared(pCur) );
|
|
assert( pCur->eState>=3 );
|
|
if( pCur->eState==4 ){
|
|
return pCur->skipNext;
|
|
}
|
|
pCur->eState = 1;
|
|
if( sqlite3FaultSim(410) ){
|
|
rc = 10;
|
|
}else{
|
|
rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &skipNext);
|
|
}
|
|
if( rc==0 ){
|
|
sqlite3_free(pCur->pKey);
|
|
pCur->pKey = 0;
|
|
assert( pCur->eState==0 || pCur->eState==1 );
|
|
if( skipNext ) pCur->skipNext = skipNext;
|
|
if( pCur->skipNext && pCur->eState==0 ){
|
|
pCur->eState = 2;
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
# 877 "src/btree.c"
|
|
int sqlite3BtreeCursorHasMoved(BtCursor *pCur){
|
|
assert( ((((char*)(pCur) - (char*)0)&7)==0)
|
|
|| pCur==sqlite3BtreeFakeValidCursor() );
|
|
assert( ((int)((char*)&((BtCursor*)0)->eState))==0 );
|
|
assert( sizeof(pCur->eState)==1 );
|
|
return 0 != *(u8*)pCur;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BtCursor *sqlite3BtreeFakeValidCursor(void){
|
|
static u8 fakeCursor = 0;
|
|
assert( ((int)((char*)&((BtCursor*)0)->eState))==0 );
|
|
return (BtCursor*)&fakeCursor;
|
|
}
|
|
# 909 "src/btree.c"
|
|
int sqlite3BtreeCursorRestore(BtCursor *pCur, int *pDifferentRow){
|
|
int rc;
|
|
|
|
assert( pCur!=0 );
|
|
assert( pCur->eState!=0 );
|
|
rc = (pCur->eState>=3 ? btreeRestoreCursorPosition(pCur) : 0);
|
|
if( rc ){
|
|
*pDifferentRow = 1;
|
|
return rc;
|
|
}
|
|
if( pCur->eState!=0 ){
|
|
*pDifferentRow = 1;
|
|
}else{
|
|
*pDifferentRow = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
# 941 "src/btree.c"
|
|
void sqlite3BtreeCursorHintFlags(BtCursor *pCur, unsigned x){
|
|
assert( x==0x00000002 || x==0x00000001 || x==0 );
|
|
pCur->hints = x;
|
|
}
|
|
# 957 "src/btree.c"
|
|
static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){
|
|
int nPagesPerMapPage;
|
|
Pgno iPtrMap, ret;
|
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
|
if( pgno<2 ) return 0;
|
|
nPagesPerMapPage = (pBt->usableSize/5)+1;
|
|
iPtrMap = (pgno-2)/nPagesPerMapPage;
|
|
ret = (iPtrMap*nPagesPerMapPage) + 2;
|
|
if( ret==((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) ){
|
|
ret++;
|
|
}
|
|
return ret;
|
|
}
|
|
# 981 "src/btree.c"
|
|
static void ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent, int *pRC){
|
|
DbPage *pDbPage;
|
|
u8 *pPtrmap;
|
|
Pgno iPtrmap;
|
|
int offset;
|
|
int rc;
|
|
|
|
if( *pRC ) return;
|
|
|
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
|
|
|
assert( 0==(ptrmapPageno((pBt), (((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1))))==(((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)))) );
|
|
|
|
assert( pBt->autoVacuum );
|
|
if( key==0 ){
|
|
*pRC = sqlite3CorruptError(996);
|
|
return;
|
|
}
|
|
iPtrmap = ptrmapPageno(pBt, key);
|
|
rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage, 0);
|
|
if( rc!=0 ){
|
|
*pRC = rc;
|
|
return;
|
|
}
|
|
if( ((char*)sqlite3PagerGetExtra(pDbPage))[0]!=0 ){
|
|
|
|
|
|
|
|
*pRC = sqlite3CorruptError(1009);
|
|
goto ptrmap_exit;
|
|
}
|
|
offset = (5*(key-iPtrmap-1));
|
|
if( offset<0 ){
|
|
*pRC = sqlite3CorruptError(1014);
|
|
goto ptrmap_exit;
|
|
}
|
|
assert( offset <= (int)pBt->usableSize-5 );
|
|
pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage);
|
|
|
|
if( eType!=pPtrmap[offset] || sqlite3Get4byte(&pPtrmap[offset+1])!=parent ){
|
|
;
|
|
*pRC= rc = sqlite3PagerWrite(pDbPage);
|
|
if( rc==0 ){
|
|
pPtrmap[offset] = eType;
|
|
sqlite3Put4byte(&pPtrmap[offset+1], parent);
|
|
}
|
|
}
|
|
|
|
ptrmap_exit:
|
|
sqlite3PagerUnref(pDbPage);
|
|
}
|
|
# 1040 "src/btree.c"
|
|
static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){
|
|
DbPage *pDbPage;
|
|
int iPtrmap;
|
|
u8 *pPtrmap;
|
|
int offset;
|
|
int rc;
|
|
|
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
|
|
|
iPtrmap = ptrmapPageno(pBt, key);
|
|
rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage, 0);
|
|
if( rc!=0 ){
|
|
return rc;
|
|
}
|
|
pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage);
|
|
|
|
offset = (5*(key-iPtrmap-1));
|
|
if( offset<0 ){
|
|
sqlite3PagerUnref(pDbPage);
|
|
return sqlite3CorruptError(1059);
|
|
}
|
|
assert( offset <= (int)pBt->usableSize-5 );
|
|
assert( pEType!=0 );
|
|
*pEType = pPtrmap[offset];
|
|
if( pPgno ) *pPgno = sqlite3Get4byte(&pPtrmap[offset+1]);
|
|
|
|
sqlite3PagerUnref(pDbPage);
|
|
if( *pEType<1 || *pEType>5 ) return sqlite3CorruptError(1067);
|
|
return 0;
|
|
}
|
|
# 1099 "src/btree.c"
|
|
static void btreeParseCellAdjustSizeForOverflow(
|
|
MemPage *pPage,
|
|
u8 *pCell,
|
|
CellInfo *pInfo
|
|
){
|
|
# 1113 "src/btree.c"
|
|
int minLocal;
|
|
int maxLocal;
|
|
int surplus;
|
|
|
|
minLocal = pPage->minLocal;
|
|
maxLocal = pPage->maxLocal;
|
|
surplus = minLocal + (pInfo->nPayload - minLocal)%(pPage->pBt->usableSize-4);
|
|
;
|
|
;
|
|
if( surplus <= maxLocal ){
|
|
pInfo->nLocal = (u16)surplus;
|
|
}else{
|
|
pInfo->nLocal = (u16)minLocal;
|
|
}
|
|
pInfo->nSize = (u16)(&pInfo->pPayload[pInfo->nLocal] - pCell) + 4;
|
|
}
|
|
# 1144 "src/btree.c"
|
|
static void btreeParseCellPtrNoPayload(
|
|
MemPage *pPage,
|
|
u8 *pCell,
|
|
CellInfo *pInfo
|
|
){
|
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
|
assert( pPage->leaf==0 );
|
|
assert( pPage->childPtrSize==4 );
|
|
|
|
(void)(pPage);
|
|
|
|
pInfo->nSize = 4 + sqlite3GetVarint(&pCell[4], (u64*)&pInfo->nKey);
|
|
pInfo->nPayload = 0;
|
|
pInfo->nLocal = 0;
|
|
pInfo->pPayload = 0;
|
|
return;
|
|
}
|
|
static void btreeParseCellPtr(
|
|
MemPage *pPage,
|
|
u8 *pCell,
|
|
CellInfo *pInfo
|
|
){
|
|
u8 *pIter;
|
|
u32 nPayload;
|
|
u64 iKey;
|
|
|
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
|
assert( pPage->leaf==0 || pPage->leaf==1 );
|
|
assert( pPage->intKeyLeaf );
|
|
assert( pPage->childPtrSize==0 );
|
|
pIter = pCell;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
nPayload = *pIter;
|
|
if( nPayload>=0x80 ){
|
|
u8 *pEnd = &pIter[8];
|
|
nPayload &= 0x7f;
|
|
do{
|
|
nPayload = (nPayload<<7) | (*++pIter & 0x7f);
|
|
}while( (*pIter)>=0x80 && pIter<pEnd );
|
|
}
|
|
pIter++;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
iKey = *pIter;
|
|
if( iKey>=0x80 ){
|
|
u8 *pEnd = &pIter[7];
|
|
iKey &= 0x7f;
|
|
while(1){
|
|
iKey = (iKey<<7) | (*++pIter & 0x7f);
|
|
if( (*pIter)<0x80 ) break;
|
|
if( pIter>=pEnd ){
|
|
iKey = (iKey<<8) | *++pIter;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
pIter++;
|
|
|
|
pInfo->nKey = *(i64*)&iKey;
|
|
pInfo->nPayload = nPayload;
|
|
pInfo->pPayload = pIter;
|
|
;
|
|
;
|
|
if( nPayload<=pPage->maxLocal ){
|
|
|
|
|
|
|
|
pInfo->nSize = nPayload + (u16)(pIter - pCell);
|
|
if( pInfo->nSize<4 ) pInfo->nSize = 4;
|
|
pInfo->nLocal = (u16)nPayload;
|
|
}else{
|
|
btreeParseCellAdjustSizeForOverflow(pPage, pCell, pInfo);
|
|
}
|
|
}
|
|
static void btreeParseCellPtrIndex(
|
|
MemPage *pPage,
|
|
u8 *pCell,
|
|
CellInfo *pInfo
|
|
){
|
|
u8 *pIter;
|
|
u32 nPayload;
|
|
|
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
|
assert( pPage->leaf==0 || pPage->leaf==1 );
|
|
assert( pPage->intKeyLeaf==0 );
|
|
pIter = pCell + pPage->childPtrSize;
|
|
nPayload = *pIter;
|
|
if( nPayload>=0x80 ){
|
|
u8 *pEnd = &pIter[8];
|
|
nPayload &= 0x7f;
|
|
do{
|
|
nPayload = (nPayload<<7) | (*++pIter & 0x7f);
|
|
}while( *(pIter)>=0x80 && pIter<pEnd );
|
|
}
|
|
pIter++;
|
|
pInfo->nKey = nPayload;
|
|
pInfo->nPayload = nPayload;
|
|
pInfo->pPayload = pIter;
|
|
;
|
|
;
|
|
if( nPayload<=pPage->maxLocal ){
|
|
|
|
|
|
|
|
pInfo->nSize = nPayload + (u16)(pIter - pCell);
|
|
if( pInfo->nSize<4 ) pInfo->nSize = 4;
|
|
pInfo->nLocal = (u16)nPayload;
|
|
}else{
|
|
btreeParseCellAdjustSizeForOverflow(pPage, pCell, pInfo);
|
|
}
|
|
}
|
|
static void btreeParseCell(
|
|
MemPage *pPage,
|
|
int iCell,
|
|
CellInfo *pInfo
|
|
){
|
|
pPage->xParseCell(pPage, ((pPage)->aData + ((pPage)->maskPage & __builtin_bswap16(*(u16*)(&(pPage)->aCellIdx[2*(iCell)])))), pInfo);
|
|
}
|
|
# 1286 "src/btree.c"
|
|
static u16 cellSizePtr(MemPage *pPage, u8 *pCell){
|
|
u8 *pIter = pCell + pPage->childPtrSize;
|
|
u8 *pEnd;
|
|
u32 nSize;
|
|
# 1300 "src/btree.c"
|
|
nSize = *pIter;
|
|
if( nSize>=0x80 ){
|
|
pEnd = &pIter[8];
|
|
nSize &= 0x7f;
|
|
do{
|
|
nSize = (nSize<<7) | (*++pIter & 0x7f);
|
|
}while( *(pIter)>=0x80 && pIter<pEnd );
|
|
}
|
|
pIter++;
|
|
if( pPage->intKey ){
|
|
|
|
|
|
|
|
pEnd = &pIter[9];
|
|
while( (*pIter++)&0x80 && pIter<pEnd );
|
|
}
|
|
;
|
|
;
|
|
if( nSize<=pPage->maxLocal ){
|
|
nSize += (u32)(pIter - pCell);
|
|
if( nSize<4 ) nSize = 4;
|
|
}else{
|
|
int minLocal = pPage->minLocal;
|
|
nSize = minLocal + (nSize - minLocal) % (pPage->pBt->usableSize - 4);
|
|
;
|
|
;
|
|
if( nSize>pPage->maxLocal ){
|
|
nSize = minLocal;
|
|
}
|
|
nSize += 4 + (u16)(pIter - pCell);
|
|
}
|
|
assert( nSize==debuginfo.nSize || (sqlite3Config.neverCorrupt==0) );
|
|
return (u16)nSize;
|
|
}
|
|
static u16 cellSizePtrNoPayload(MemPage *pPage, u8 *pCell){
|
|
u8 *pIter = pCell + 4;
|
|
u8 *pEnd;
|
|
# 1346 "src/btree.c"
|
|
(void)(pPage);
|
|
|
|
|
|
assert( pPage->childPtrSize==4 );
|
|
pEnd = pIter + 9;
|
|
while( (*pIter++)&0x80 && pIter<pEnd );
|
|
assert( debuginfo.nSize==(u16)(pIter - pCell) || (sqlite3Config.neverCorrupt==0) );
|
|
return (u16)(pIter - pCell);
|
|
}
|
|
# 1372 "src/btree.c"
|
|
static void ptrmapPutOvflPtr(MemPage *pPage, MemPage *pSrc, u8 *pCell,int *pRC){
|
|
CellInfo info;
|
|
if( *pRC ) return;
|
|
assert( pCell!=0 );
|
|
pPage->xParseCell(pPage, pCell, &info);
|
|
if( info.nLocal<info.nPayload ){
|
|
Pgno ovfl;
|
|
if( (((uptr)(pSrc->aDataEnd)>=(uptr)(pCell))&&((uptr)(pSrc->aDataEnd)<(uptr)(pCell+info.nLocal))) ){
|
|
;
|
|
*pRC = sqlite3CorruptError(1381);
|
|
return;
|
|
}
|
|
ovfl = sqlite3Get4byte(&pCell[info.nSize-4]);
|
|
ptrmapPut(pPage->pBt, ovfl, 3, pPage->pgno, pRC);
|
|
}
|
|
}
|
|
# 1403 "src/btree.c"
|
|
static int defragmentPage(MemPage *pPage, int nMaxFrag){
|
|
int i;
|
|
int pc;
|
|
int hdr;
|
|
int size;
|
|
int usableSize;
|
|
int cellOffset;
|
|
int cbrk;
|
|
int nCell;
|
|
unsigned char *data;
|
|
unsigned char *temp;
|
|
unsigned char *src;
|
|
int iCellFirst;
|
|
int iCellLast;
|
|
|
|
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
|
|
assert( pPage->pBt!=0 );
|
|
assert( pPage->pBt->usableSize <= 65536 );
|
|
assert( pPage->nOverflow==0 );
|
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
|
temp = 0;
|
|
src = data = pPage->aData;
|
|
hdr = pPage->hdrOffset;
|
|
cellOffset = pPage->cellOffset;
|
|
nCell = pPage->nCell;
|
|
assert( nCell==((&data[hdr+3])[0]<<8 | (&data[hdr+3])[1]) || (sqlite3Config.neverCorrupt==0) );
|
|
iCellFirst = cellOffset + 2*nCell;
|
|
usableSize = pPage->pBt->usableSize;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( (int)data[hdr+7]<=nMaxFrag ){
|
|
int iFree = ((&data[hdr+1])[0]<<8 | (&data[hdr+1])[1]);
|
|
if( iFree>usableSize-4 ) return sqlite3CorruptError(1439);
|
|
if( iFree ){
|
|
int iFree2 = ((&data[iFree])[0]<<8 | (&data[iFree])[1]);
|
|
if( iFree2>usableSize-4 ) return sqlite3CorruptError(1442);
|
|
if( 0==iFree2 || (data[iFree2]==0 && data[iFree2+1]==0) ){
|
|
u8 *pEnd = &data[cellOffset + nCell*2];
|
|
u8 *pAddr;
|
|
int sz2 = 0;
|
|
int sz = ((&data[iFree+2])[0]<<8 | (&data[iFree+2])[1]);
|
|
int top = ((&data[hdr+5])[0]<<8 | (&data[hdr+5])[1]);
|
|
if( top>=iFree ){
|
|
return sqlite3CorruptError(1450);
|
|
}
|
|
if( iFree2 ){
|
|
if( iFree+sz>iFree2 ) return sqlite3CorruptError(1453);
|
|
sz2 = ((&data[iFree2+2])[0]<<8 | (&data[iFree2+2])[1]);
|
|
if( iFree2+sz2 > usableSize ) return sqlite3CorruptError(1455);
|
|
memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
|
|
sz += sz2;
|
|
}else if( iFree+sz>usableSize ){
|
|
return sqlite3CorruptError(1459);
|
|
}
|
|
|
|
cbrk = top+sz;
|
|
assert( cbrk+(iFree-top) <= usableSize );
|
|
memmove(&data[cbrk], &data[top], iFree-top);
|
|
for(pAddr=&data[cellOffset]; pAddr<pEnd; pAddr+=2){
|
|
pc = ((pAddr)[0]<<8 | (pAddr)[1]);
|
|
if( pc<iFree ){ ((pAddr)[0] = (u8)((pc+sz)>>8), (pAddr)[1] = (u8)(pc+sz)); }
|
|
else if( pc<iFree2 ){ ((pAddr)[0] = (u8)((pc+sz2)>>8), (pAddr)[1] = (u8)(pc+sz2)); }
|
|
}
|
|
goto defragment_out;
|
|
}
|
|
}
|
|
}
|
|
|
|
cbrk = usableSize;
|
|
iCellLast = usableSize - 4;
|
|
for(i=0; i<nCell; i++){
|
|
u8 *pAddr;
|
|
pAddr = &data[cellOffset + i*2];
|
|
pc = ((pAddr)[0]<<8 | (pAddr)[1]);
|
|
;
|
|
;
|
|
|
|
|
|
|
|
if( pc<iCellFirst || pc>iCellLast ){
|
|
return sqlite3CorruptError(1487);
|
|
}
|
|
assert( pc>=iCellFirst && pc<=iCellLast );
|
|
size = pPage->xCellSize(pPage, &src[pc]);
|
|
cbrk -= size;
|
|
if( cbrk<iCellFirst || pc+size>usableSize ){
|
|
return sqlite3CorruptError(1493);
|
|
}
|
|
assert( cbrk+size<=usableSize && cbrk>=iCellFirst );
|
|
;
|
|
;
|
|
((pAddr)[0] = (u8)((cbrk)>>8), (pAddr)[1] = (u8)(cbrk));
|
|
if( temp==0 ){
|
|
int x;
|
|
if( cbrk==pc ) continue;
|
|
temp = sqlite3PagerTempSpace(pPage->pBt->pPager);
|
|
x = ((&data[hdr+5])[0]<<8 | (&data[hdr+5])[1]);
|
|
memcpy(&temp[x], &data[x], (cbrk+size) - x);
|
|
src = temp;
|
|
}
|
|
memcpy(&data[cbrk], &src[pc], size);
|
|
}
|
|
data[hdr+7] = 0;
|
|
|
|
defragment_out:
|
|
assert( pPage->nFree>=0 );
|
|
if( data[hdr+7]+cbrk-iCellFirst!=pPage->nFree ){
|
|
return sqlite3CorruptError(1514);
|
|
}
|
|
assert( cbrk>=iCellFirst );
|
|
((&data[hdr+5])[0] = (u8)((cbrk)>>8), (&data[hdr+5])[1] = (u8)(cbrk));
|
|
data[hdr+1] = 0;
|
|
data[hdr+2] = 0;
|
|
memset(&data[iCellFirst], 0, cbrk-iCellFirst);
|
|
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
|
|
return 0;
|
|
}
|
|
# 1539 "src/btree.c"
|
|
static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
|
|
const int hdr = pPg->hdrOffset;
|
|
u8 * const aData = pPg->aData;
|
|
int iAddr = hdr + 1;
|
|
int pc = ((&aData[iAddr])[0]<<8 | (&aData[iAddr])[1]);
|
|
int x;
|
|
int maxPC = pPg->pBt->usableSize - nByte;
|
|
int size;
|
|
|
|
assert( pc>0 );
|
|
while( pc<=maxPC ){
|
|
|
|
|
|
|
|
size = ((&aData[pc+2])[0]<<8 | (&aData[pc+2])[1]);
|
|
if( (x = size - nByte)>=0 ){
|
|
;
|
|
;
|
|
if( x<4 ){
|
|
|
|
|
|
if( aData[hdr+7]>57 ) return 0;
|
|
|
|
|
|
|
|
memcpy(&aData[iAddr], &aData[pc], 2);
|
|
aData[hdr+7] += (u8)x;
|
|
}else if( x+pc > maxPC ){
|
|
|
|
*pRc = sqlite3CorruptError(1568);
|
|
return 0;
|
|
}else{
|
|
|
|
|
|
((&aData[pc+2])[0] = (u8)((x)>>8), (&aData[pc+2])[1] = (u8)(x));
|
|
}
|
|
return &aData[pc + x];
|
|
}
|
|
iAddr = pc;
|
|
pc = ((&aData[pc])[0]<<8 | (&aData[pc])[1]);
|
|
if( pc<=iAddr+size ){
|
|
if( pc ){
|
|
|
|
*pRc = sqlite3CorruptError(1582);
|
|
}
|
|
return 0;
|
|
}
|
|
}
|
|
if( pc>maxPC+nByte-4 ){
|
|
|
|
*pRc = sqlite3CorruptError(1589);
|
|
}
|
|
return 0;
|
|
}
|
|
# 1607 "src/btree.c"
|
|
static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
|
|
const int hdr = pPage->hdrOffset;
|
|
u8 * const data = pPage->aData;
|
|
int top;
|
|
int rc = 0;
|
|
int gap;
|
|
|
|
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
|
|
assert( pPage->pBt );
|
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
|
assert( nByte>=0 );
|
|
assert( pPage->nFree>=nByte );
|
|
assert( pPage->nOverflow==0 );
|
|
assert( nByte < (int)(pPage->pBt->usableSize-8) );
|
|
|
|
assert( pPage->cellOffset == hdr + 12 - 4*pPage->leaf );
|
|
gap = pPage->cellOffset + 2*pPage->nCell;
|
|
assert( gap<=65536 );
|
|
|
|
|
|
|
|
|
|
|
|
top = ((&data[hdr+5])[0]<<8 | (&data[hdr+5])[1]);
|
|
assert( top<=(int)pPage->pBt->usableSize );
|
|
if( gap>top ){
|
|
if( top==0 && pPage->pBt->usableSize==65536 ){
|
|
top = 65536;
|
|
}else{
|
|
return sqlite3CorruptError(1636);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
;
|
|
;
|
|
;
|
|
if( (data[hdr+2] || data[hdr+1]) && gap+2<=top ){
|
|
u8 *pSpace = pageFindSlot(pPage, nByte, &rc);
|
|
if( pSpace ){
|
|
assert( pSpace>=data && (pSpace - data)<65536 );
|
|
*pIdx = (int)(pSpace - data);
|
|
return 0;
|
|
}else if( rc ){
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
;
|
|
if( gap+2+nByte>top ){
|
|
assert( pPage->nCell>0 || (sqlite3Config.neverCorrupt==0) );
|
|
assert( pPage->nFree>=0 );
|
|
rc = defragmentPage(pPage, ((4)<(pPage->nFree - (2+nByte))?(4):(pPage->nFree - (2+nByte))));
|
|
if( rc ) return rc;
|
|
top = (((((int)((&data[hdr+5])[0]<<8 | (&data[hdr+5])[1]))-1)&0xffff)+1);
|
|
assert( gap+2+nByte<=top );
|
|
}
|
|
# 1678 "src/btree.c"
|
|
top -= nByte;
|
|
((&data[hdr+5])[0] = (u8)((top)>>8), (&data[hdr+5])[1] = (u8)(top));
|
|
assert( top+nByte <= (int)pPage->pBt->usableSize );
|
|
*pIdx = top;
|
|
return 0;
|
|
}
|
|
# 1698 "src/btree.c"
|
|
static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
|
|
u16 iPtr;
|
|
u16 iFreeBlk;
|
|
u8 hdr;
|
|
u8 nFrag = 0;
|
|
u16 iOrigSize = iSize;
|
|
u16 x;
|
|
u32 iEnd = iStart + iSize;
|
|
unsigned char *data = pPage->aData;
|
|
|
|
assert( pPage->pBt!=0 );
|
|
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
|
|
assert( (sqlite3Config.neverCorrupt==0) || iStart>=pPage->hdrOffset+6+pPage->childPtrSize );
|
|
assert( (sqlite3Config.neverCorrupt==0) || iEnd <= pPage->pBt->usableSize );
|
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
|
assert( iSize>=4 );
|
|
assert( iStart<=pPage->pBt->usableSize-4 );
|
|
|
|
|
|
|
|
|
|
hdr = pPage->hdrOffset;
|
|
iPtr = hdr + 1;
|
|
if( data[iPtr+1]==0 && data[iPtr]==0 ){
|
|
iFreeBlk = 0;
|
|
}else{
|
|
while( (iFreeBlk = ((&data[iPtr])[0]<<8 | (&data[iPtr])[1]))<iStart ){
|
|
if( iFreeBlk<iPtr+4 ){
|
|
if( iFreeBlk==0 ) break;
|
|
return sqlite3CorruptError(1727);
|
|
}
|
|
iPtr = iFreeBlk;
|
|
}
|
|
if( iFreeBlk>pPage->pBt->usableSize-4 ){
|
|
return sqlite3CorruptError(1732);
|
|
}
|
|
assert( iFreeBlk>iPtr || iFreeBlk==0 );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( iFreeBlk && iEnd+3>=iFreeBlk ){
|
|
nFrag = iFreeBlk - iEnd;
|
|
if( iEnd>iFreeBlk ) return sqlite3CorruptError(1744);
|
|
iEnd = iFreeBlk + ((&data[iFreeBlk+2])[0]<<8 | (&data[iFreeBlk+2])[1]);
|
|
if( iEnd > pPage->pBt->usableSize ){
|
|
return sqlite3CorruptError(1747);
|
|
}
|
|
iSize = iEnd - iStart;
|
|
iFreeBlk = ((&data[iFreeBlk])[0]<<8 | (&data[iFreeBlk])[1]);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if( iPtr>hdr+1 ){
|
|
int iPtrEnd = iPtr + ((&data[iPtr+2])[0]<<8 | (&data[iPtr+2])[1]);
|
|
if( iPtrEnd+3>=iStart ){
|
|
if( iPtrEnd>iStart ) return sqlite3CorruptError(1760);
|
|
nFrag += iStart - iPtrEnd;
|
|
iSize = iEnd - iPtr;
|
|
iStart = iPtr;
|
|
}
|
|
}
|
|
if( nFrag>data[hdr+7] ) return sqlite3CorruptError(1766);
|
|
data[hdr+7] -= nFrag;
|
|
}
|
|
x = ((&data[hdr+5])[0]<<8 | (&data[hdr+5])[1]);
|
|
if( iStart<=x ){
|
|
|
|
|
|
|
|
if( iStart<x || iPtr!=hdr+1 ) return sqlite3CorruptError(1774);
|
|
((&data[hdr+1])[0] = (u8)((iFreeBlk)>>8), (&data[hdr+1])[1] = (u8)(iFreeBlk));
|
|
((&data[hdr+5])[0] = (u8)((iEnd)>>8), (&data[hdr+5])[1] = (u8)(iEnd));
|
|
}else{
|
|
|
|
((&data[iPtr])[0] = (u8)((iStart)>>8), (&data[iPtr])[1] = (u8)(iStart));
|
|
}
|
|
if( pPage->pBt->btsFlags & 0x000c ){
|
|
|
|
|
|
memset(&data[iStart], 0, iSize);
|
|
}
|
|
((&data[iStart])[0] = (u8)((iFreeBlk)>>8), (&data[iStart])[1] = (u8)(iFreeBlk));
|
|
((&data[iStart+2])[0] = (u8)((iSize)>>8), (&data[iStart+2])[1] = (u8)(iSize));
|
|
pPage->nFree += iOrigSize;
|
|
return 0;
|
|
}
|
|
# 1804 "src/btree.c"
|
|
static int decodeFlags(MemPage *pPage, int flagByte){
|
|
BtShared *pBt;
|
|
|
|
assert( pPage->hdrOffset==(pPage->pgno==1 ? 100 : 0) );
|
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
|
pPage->leaf = (u8)(flagByte>>3); assert( 0x08 == 1<<3 );
|
|
flagByte &= ~0x08;
|
|
pPage->childPtrSize = 4-4*pPage->leaf;
|
|
pPage->xCellSize = cellSizePtr;
|
|
pBt = pPage->pBt;
|
|
if( flagByte==(0x04 | 0x01) ){
|
|
|
|
|
|
assert( (0x04|0x01)==5 );
|
|
|
|
|
|
assert( (0x04|0x01|0x08)==13 );
|
|
pPage->intKey = 1;
|
|
if( pPage->leaf ){
|
|
pPage->intKeyLeaf = 1;
|
|
pPage->xParseCell = btreeParseCellPtr;
|
|
}else{
|
|
pPage->intKeyLeaf = 0;
|
|
pPage->xCellSize = cellSizePtrNoPayload;
|
|
pPage->xParseCell = btreeParseCellPtrNoPayload;
|
|
}
|
|
pPage->maxLocal = pBt->maxLeaf;
|
|
pPage->minLocal = pBt->minLeaf;
|
|
}else if( flagByte==0x02 ){
|
|
|
|
|
|
assert( (0x02)==2 );
|
|
|
|
|
|
assert( (0x02|0x08)==10 );
|
|
pPage->intKey = 0;
|
|
pPage->intKeyLeaf = 0;
|
|
pPage->xParseCell = btreeParseCellPtrIndex;
|
|
pPage->maxLocal = pBt->maxLocal;
|
|
pPage->minLocal = pBt->minLocal;
|
|
}else{
|
|
|
|
|
|
return sqlite3CorruptError(1847);
|
|
}
|
|
pPage->max1bytePayload = pBt->max1bytePayload;
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int btreeComputeFreeSpace(MemPage *pPage){
|
|
int pc;
|
|
u8 hdr;
|
|
u8 *data;
|
|
int usableSize;
|
|
int nFree;
|
|
int top;
|
|
int iCellFirst;
|
|
int iCellLast;
|
|
|
|
assert( pPage->pBt!=0 );
|
|
assert( pPage->pBt->db!=0 );
|
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
|
assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
|
|
assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) );
|
|
assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) );
|
|
assert( pPage->isInit==1 );
|
|
assert( pPage->nFree<0 );
|
|
|
|
usableSize = pPage->pBt->usableSize;
|
|
hdr = pPage->hdrOffset;
|
|
data = pPage->aData;
|
|
|
|
|
|
|
|
top = (((((int)((&data[hdr+5])[0]<<8 | (&data[hdr+5])[1]))-1)&0xffff)+1);
|
|
iCellFirst = hdr + 8 + pPage->childPtrSize + 2*pPage->nCell;
|
|
iCellLast = usableSize - 4;
|
|
|
|
|
|
|
|
|
|
|
|
pc = ((&data[hdr+1])[0]<<8 | (&data[hdr+1])[1]);
|
|
nFree = data[hdr+7] + top;
|
|
if( pc>0 ){
|
|
u32 next, size;
|
|
if( pc<iCellFirst ){
|
|
|
|
|
|
|
|
return sqlite3CorruptError(1898);
|
|
}
|
|
while( 1 ){
|
|
if( pc>iCellLast ){
|
|
|
|
return sqlite3CorruptError(1903);
|
|
}
|
|
next = ((&data[pc])[0]<<8 | (&data[pc])[1]);
|
|
size = ((&data[pc+2])[0]<<8 | (&data[pc+2])[1]);
|
|
nFree = nFree + size;
|
|
if( next<=pc+size+3 ) break;
|
|
pc = next;
|
|
}
|
|
if( next>0 ){
|
|
|
|
return sqlite3CorruptError(1913);
|
|
}
|
|
if( pc+size>(unsigned int)usableSize ){
|
|
|
|
return sqlite3CorruptError(1917);
|
|
}
|
|
}
|
|
# 1928 "src/btree.c"
|
|
if( nFree>usableSize || nFree<iCellFirst ){
|
|
return sqlite3CorruptError(1929);
|
|
}
|
|
pPage->nFree = (u16)(nFree - iCellFirst);
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int btreeCellSizeCheck(MemPage *pPage){
|
|
int iCellFirst;
|
|
int iCellLast;
|
|
int i;
|
|
int sz;
|
|
int pc;
|
|
u8 *data;
|
|
int usableSize;
|
|
int cellOffset;
|
|
|
|
iCellFirst = pPage->cellOffset + 2*pPage->nCell;
|
|
usableSize = pPage->pBt->usableSize;
|
|
iCellLast = usableSize - 4;
|
|
data = pPage->aData;
|
|
cellOffset = pPage->cellOffset;
|
|
if( !pPage->leaf ) iCellLast--;
|
|
for(i=0; i<pPage->nCell; i++){
|
|
pc = __builtin_bswap16(*(u16*)(&data[cellOffset+i*2]));
|
|
;
|
|
;
|
|
if( pc<iCellFirst || pc>iCellLast ){
|
|
return sqlite3CorruptError(1960);
|
|
}
|
|
sz = pPage->xCellSize(pPage, &data[pc]);
|
|
;
|
|
if( pc+sz>usableSize ){
|
|
return sqlite3CorruptError(1965);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
# 1980 "src/btree.c"
|
|
static int btreeInitPage(MemPage *pPage){
|
|
u8 *data;
|
|
BtShared *pBt;
|
|
|
|
assert( pPage->pBt!=0 );
|
|
assert( pPage->pBt->db!=0 );
|
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
|
assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
|
|
assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) );
|
|
assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) );
|
|
assert( pPage->isInit==0 );
|
|
|
|
pBt = pPage->pBt;
|
|
data = pPage->aData + pPage->hdrOffset;
|
|
|
|
|
|
if( decodeFlags(pPage, data[0]) ){
|
|
return sqlite3CorruptError(1997);
|
|
}
|
|
assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
|
|
pPage->maskPage = (u16)(pBt->pageSize - 1);
|
|
pPage->nOverflow = 0;
|
|
pPage->cellOffset = pPage->hdrOffset + 8 + pPage->childPtrSize;
|
|
pPage->aCellIdx = data + pPage->childPtrSize + 8;
|
|
pPage->aDataEnd = pPage->aData + pBt->usableSize;
|
|
pPage->aDataOfst = pPage->aData + pPage->childPtrSize;
|
|
|
|
|
|
pPage->nCell = ((&data[3])[0]<<8 | (&data[3])[1]);
|
|
if( pPage->nCell>((pBt->pageSize-8)/6) ){
|
|
|
|
return sqlite3CorruptError(2011);
|
|
}
|
|
;
|
|
|
|
|
|
|
|
|
|
assert( pPage->nCell>0
|
|
|| (((((int)((&data[5])[0]<<8 | (&data[5])[1]))-1)&0xffff)+1)==(int)pBt->usableSize
|
|
|| (sqlite3Config.neverCorrupt==0) );
|
|
pPage->nFree = -1;
|
|
pPage->isInit = 1;
|
|
if( pBt->db->flags & 0x00200000 ){
|
|
return btreeCellSizeCheck(pPage);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void zeroPage(MemPage *pPage, int flags){
|
|
unsigned char *data = pPage->aData;
|
|
BtShared *pBt = pPage->pBt;
|
|
u8 hdr = pPage->hdrOffset;
|
|
u16 first;
|
|
|
|
assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno );
|
|
assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
|
|
assert( sqlite3PagerGetData(pPage->pDbPage) == data );
|
|
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
|
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
|
if( pBt->btsFlags & 0x000c ){
|
|
memset(&data[hdr], 0, pBt->usableSize - hdr);
|
|
}
|
|
data[hdr] = (char)flags;
|
|
first = hdr + ((flags&0x08)==0 ? 12 : 8);
|
|
memset(&data[hdr+1], 0, 4);
|
|
data[hdr+7] = 0;
|
|
((&data[hdr+5])[0] = (u8)((pBt->usableSize)>>8), (&data[hdr+5])[1] = (u8)(pBt->usableSize));
|
|
pPage->nFree = (u16)(pBt->usableSize - first);
|
|
decodeFlags(pPage, flags);
|
|
pPage->cellOffset = first;
|
|
pPage->aDataEnd = &data[pBt->usableSize];
|
|
pPage->aCellIdx = &data[first];
|
|
pPage->aDataOfst = &data[pPage->childPtrSize];
|
|
pPage->nOverflow = 0;
|
|
assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
|
|
pPage->maskPage = (u16)(pBt->pageSize - 1);
|
|
pPage->nCell = 0;
|
|
pPage->isInit = 1;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static MemPage *btreePageFromDbPage(DbPage *pDbPage, Pgno pgno, BtShared *pBt){
|
|
MemPage *pPage = (MemPage*)sqlite3PagerGetExtra(pDbPage);
|
|
if( pgno!=pPage->pgno ){
|
|
pPage->aData = sqlite3PagerGetData(pDbPage);
|
|
pPage->pDbPage = pDbPage;
|
|
pPage->pBt = pBt;
|
|
pPage->pgno = pgno;
|
|
pPage->hdrOffset = pgno==1 ? 100 : 0;
|
|
}
|
|
assert( pPage->aData==sqlite3PagerGetData(pDbPage) );
|
|
return pPage;
|
|
}
|
|
# 2094 "src/btree.c"
|
|
static int btreeGetPage(
|
|
BtShared *pBt,
|
|
Pgno pgno,
|
|
MemPage **ppPage,
|
|
int flags
|
|
){
|
|
int rc;
|
|
DbPage *pDbPage;
|
|
|
|
assert( flags==0 || flags==0x01 || flags==0x02 );
|
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
|
rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, flags);
|
|
if( rc ) return rc;
|
|
*ppPage = btreePageFromDbPage(pDbPage, pgno, pBt);
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static MemPage *btreePageLookup(BtShared *pBt, Pgno pgno){
|
|
DbPage *pDbPage;
|
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
|
pDbPage = sqlite3PagerLookup(pBt->pPager, pgno);
|
|
if( pDbPage ){
|
|
return btreePageFromDbPage(pDbPage, pgno, pBt);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static Pgno btreePagecount(BtShared *pBt){
|
|
return pBt->nPage;
|
|
}
|
|
u32 sqlite3BtreeLastPage(Btree *p){
|
|
assert( sqlite3BtreeHoldsMutex(p) );
|
|
assert( ((p->pBt->nPage)&0x80000000)==0 );
|
|
return btreePagecount(p->pBt);
|
|
}
|
|
# 2152 "src/btree.c"
|
|
static int getAndInitPage(
|
|
BtShared *pBt,
|
|
Pgno pgno,
|
|
MemPage **ppPage,
|
|
BtCursor *pCur,
|
|
int bReadOnly
|
|
){
|
|
int rc;
|
|
DbPage *pDbPage;
|
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
|
assert( pCur==0 || ppPage==&pCur->pPage );
|
|
assert( pCur==0 || bReadOnly==pCur->curPagerFlags );
|
|
assert( pCur==0 || pCur->iPage>0 );
|
|
|
|
if( pgno>btreePagecount(pBt) ){
|
|
rc = sqlite3CorruptError(2167);
|
|
goto getAndInitPage_error1;
|
|
}
|
|
rc = sqlite3PagerGet(pBt->pPager, pgno, (DbPage**)&pDbPage, bReadOnly);
|
|
if( rc ){
|
|
goto getAndInitPage_error1;
|
|
}
|
|
*ppPage = (MemPage*)sqlite3PagerGetExtra(pDbPage);
|
|
if( (*ppPage)->isInit==0 ){
|
|
btreePageFromDbPage(pDbPage, pgno, pBt);
|
|
rc = btreeInitPage(*ppPage);
|
|
if( rc!=0 ){
|
|
goto getAndInitPage_error2;
|
|
}
|
|
}
|
|
assert( (*ppPage)->pgno==pgno );
|
|
assert( (*ppPage)->aData==sqlite3PagerGetData(pDbPage) );
|
|
|
|
|
|
|
|
if( pCur && ((*ppPage)->nCell<1 || (*ppPage)->intKey!=pCur->curIntKey) ){
|
|
rc = sqlite3CorruptError(2188);
|
|
goto getAndInitPage_error2;
|
|
}
|
|
return 0;
|
|
|
|
getAndInitPage_error2:
|
|
releasePage(*ppPage);
|
|
getAndInitPage_error1:
|
|
if( pCur ){
|
|
pCur->iPage--;
|
|
pCur->pPage = pCur->apPage[pCur->iPage];
|
|
}
|
|
;
|
|
assert( pgno!=0 || rc==11 );
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void releasePageNotNull(MemPage *pPage){
|
|
assert( pPage->aData );
|
|
assert( pPage->pBt );
|
|
assert( pPage->pDbPage!=0 );
|
|
assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
|
|
assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData );
|
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
|
sqlite3PagerUnrefNotNull(pPage->pDbPage);
|
|
}
|
|
static void releasePage(MemPage *pPage){
|
|
if( pPage ) releasePageNotNull(pPage);
|
|
}
|
|
static void releasePageOne(MemPage *pPage){
|
|
assert( pPage!=0 );
|
|
assert( pPage->aData );
|
|
assert( pPage->pBt );
|
|
assert( pPage->pDbPage!=0 );
|
|
assert( sqlite3PagerGetExtra(pPage->pDbPage) == (void*)pPage );
|
|
assert( sqlite3PagerGetData(pPage->pDbPage)==pPage->aData );
|
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
|
sqlite3PagerUnrefPageOne(pPage->pDbPage);
|
|
}
|
|
# 2243 "src/btree.c"
|
|
static int btreeGetUnusedPage(
|
|
BtShared *pBt,
|
|
Pgno pgno,
|
|
MemPage **ppPage,
|
|
int flags
|
|
){
|
|
int rc = btreeGetPage(pBt, pgno, ppPage, flags);
|
|
if( rc==0 ){
|
|
if( sqlite3PagerPageRefcount((*ppPage)->pDbPage)>1 ){
|
|
releasePage(*ppPage);
|
|
*ppPage = 0;
|
|
return sqlite3CorruptError(2254);
|
|
}
|
|
(*ppPage)->isInit = 0;
|
|
}else{
|
|
*ppPage = 0;
|
|
}
|
|
return rc;
|
|
}
|
|
# 2272 "src/btree.c"
|
|
static void pageReinit(DbPage *pData){
|
|
MemPage *pPage;
|
|
pPage = (MemPage *)sqlite3PagerGetExtra(pData);
|
|
assert( sqlite3PagerPageRefcount(pData)>0 );
|
|
if( pPage->isInit ){
|
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
|
pPage->isInit = 0;
|
|
if( sqlite3PagerPageRefcount(pData)>1 ){
|
|
|
|
|
|
|
|
|
|
|
|
|
|
btreeInitPage(pPage);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
static int btreeInvokeBusyHandler(void *pArg){
|
|
BtShared *pBt = (BtShared*)pArg;
|
|
assert( pBt->db );
|
|
assert( sqlite3_mutex_held(pBt->db->mutex) );
|
|
return sqlite3InvokeBusyHandler(&pBt->db->busyHandler,
|
|
sqlite3PagerFile(pBt->pPager));
|
|
}
|
|
# 2323 "src/btree.c"
|
|
int sqlite3BtreeOpen(
|
|
sqlite3_vfs *pVfs,
|
|
const char *zFilename,
|
|
sqlite3 *db,
|
|
Btree **ppBtree,
|
|
int flags,
|
|
int vfsFlags
|
|
){
|
|
BtShared *pBt = 0;
|
|
Btree *p;
|
|
sqlite3_mutex *mutexOpen = 0;
|
|
int rc = 0;
|
|
u8 nReserve;
|
|
unsigned char zDbHeader[100];
|
|
|
|
|
|
const int isTempDb = zFilename==0 || zFilename[0]==0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const int isMemdb = (zFilename && strcmp(zFilename, ":memory:")==0)
|
|
|| (isTempDb && sqlite3TempInMemory(db))
|
|
|| (vfsFlags & 0x00000080)!=0;
|
|
|
|
|
|
assert( db!=0 );
|
|
assert( pVfs!=0 );
|
|
assert( sqlite3_mutex_held(db->mutex) );
|
|
assert( (flags&0xff)==flags );
|
|
|
|
|
|
assert( (flags & 8)==0 || (flags & 4)!=0 );
|
|
|
|
|
|
assert( (flags & 4)==0 || isTempDb );
|
|
|
|
if( isMemdb ){
|
|
flags |= 2;
|
|
}
|
|
if( (vfsFlags & 0x00000100)!=0 && (isMemdb || isTempDb) ){
|
|
vfsFlags = (vfsFlags & ~0x00000100) | 0x00000200;
|
|
}
|
|
p = sqlite3MallocZero(sizeof(Btree));
|
|
if( !p ){
|
|
return 7;
|
|
}
|
|
p->inTrans = 0;
|
|
p->db = db;
|
|
|
|
p->lock.pBtree = p;
|
|
p->lock.iTable = 1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( isTempDb==0 && (isMemdb==0 || (vfsFlags&0x00000040)!=0) ){
|
|
if( vfsFlags & 0x00020000 ){
|
|
int nFilename = sqlite3Strlen30(zFilename)+1;
|
|
int nFullPathname = pVfs->mxPathname+1;
|
|
char *zFullPathname = sqlite3Malloc(((nFullPathname)>(nFilename)?(nFullPathname):(nFilename)));
|
|
sqlite3_mutex *mutexShared;
|
|
|
|
p->sharable = 1;
|
|
if( !zFullPathname ){
|
|
sqlite3_free(p);
|
|
return 7;
|
|
}
|
|
if( isMemdb ){
|
|
memcpy(zFullPathname, zFilename, nFilename);
|
|
}else{
|
|
rc = sqlite3OsFullPathname(pVfs, zFilename,
|
|
nFullPathname, zFullPathname);
|
|
if( rc ){
|
|
sqlite3_free(zFullPathname);
|
|
sqlite3_free(p);
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
mutexOpen = sqlite3MutexAlloc(4);
|
|
sqlite3_mutex_enter(mutexOpen);
|
|
mutexShared = sqlite3MutexAlloc(2);
|
|
sqlite3_mutex_enter(mutexShared);
|
|
|
|
for(pBt=sqlite3SharedCacheList; pBt; pBt=pBt->pNext){
|
|
assert( pBt->nRef>0 );
|
|
if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager, 0))
|
|
&& sqlite3PagerVfs(pBt->pPager)==pVfs ){
|
|
int iDb;
|
|
for(iDb=db->nDb-1; iDb>=0; iDb--){
|
|
Btree *pExisting = db->aDb[iDb].pBt;
|
|
if( pExisting && pExisting->pBt==pBt ){
|
|
sqlite3_mutex_leave(mutexShared);
|
|
sqlite3_mutex_leave(mutexOpen);
|
|
sqlite3_free(zFullPathname);
|
|
sqlite3_free(p);
|
|
return 19;
|
|
}
|
|
}
|
|
p->pBt = pBt;
|
|
pBt->nRef++;
|
|
break;
|
|
}
|
|
}
|
|
sqlite3_mutex_leave(mutexShared);
|
|
sqlite3_free(zFullPathname);
|
|
}
|
|
# 2447 "src/btree.c"
|
|
}
|
|
|
|
if( pBt==0 ){
|
|
|
|
|
|
|
|
|
|
|
|
assert( sizeof(i64)==8 );
|
|
assert( sizeof(u64)==8 );
|
|
assert( sizeof(u32)==4 );
|
|
assert( sizeof(u16)==2 );
|
|
assert( sizeof(Pgno)==4 );
|
|
|
|
pBt = sqlite3MallocZero( sizeof(*pBt) );
|
|
if( pBt==0 ){
|
|
rc = 7;
|
|
goto btree_open_out;
|
|
}
|
|
rc = sqlite3PagerOpen(pVfs, &pBt->pPager, zFilename,
|
|
sizeof(MemPage), flags, vfsFlags, pageReinit);
|
|
if( rc==0 ){
|
|
sqlite3PagerSetMmapLimit(pBt->pPager, db->szMmap);
|
|
rc = sqlite3PagerReadFileheader(pBt->pPager,sizeof(zDbHeader),zDbHeader);
|
|
}
|
|
if( rc!=0 ){
|
|
goto btree_open_out;
|
|
}
|
|
pBt->openFlags = (u8)flags;
|
|
pBt->db = db;
|
|
sqlite3PagerSetBusyHandler(pBt->pPager, btreeInvokeBusyHandler, pBt);
|
|
p->pBt = pBt;
|
|
|
|
pBt->pCursor = 0;
|
|
pBt->pPage1 = 0;
|
|
if( sqlite3PagerIsreadonly(pBt->pPager) ) pBt->btsFlags |= 0x0001;
|
|
# 2491 "src/btree.c"
|
|
pBt->pageSize = (zDbHeader[16]<<8) | (zDbHeader[17]<<16);
|
|
if( pBt->pageSize<512 || pBt->pageSize>65536
|
|
|| ((pBt->pageSize-1)&pBt->pageSize)!=0 ){
|
|
pBt->pageSize = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( zFilename && !isMemdb ){
|
|
pBt->autoVacuum = (0 ? 1 : 0);
|
|
pBt->incrVacuum = (0==2 ? 1 : 0);
|
|
}
|
|
|
|
nReserve = 0;
|
|
}else{
|
|
|
|
|
|
|
|
nReserve = zDbHeader[20];
|
|
pBt->btsFlags |= 0x0002;
|
|
|
|
pBt->autoVacuum = (sqlite3Get4byte(&zDbHeader[36 + 4*4])?1:0);
|
|
pBt->incrVacuum = (sqlite3Get4byte(&zDbHeader[36 + 7*4])?1:0);
|
|
|
|
}
|
|
rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, nReserve);
|
|
if( rc ) goto btree_open_out;
|
|
pBt->usableSize = pBt->pageSize - nReserve;
|
|
assert( (pBt->pageSize & 7)==0 );
|
|
|
|
|
|
|
|
|
|
pBt->nRef = 1;
|
|
if( p->sharable ){
|
|
sqlite3_mutex *mutexShared;
|
|
mutexShared = sqlite3MutexAlloc(2);
|
|
if( 1 && sqlite3Config.bCoreMutex ){
|
|
pBt->mutex = sqlite3MutexAlloc(0);
|
|
if( pBt->mutex==0 ){
|
|
rc = 7;
|
|
goto btree_open_out;
|
|
}
|
|
}
|
|
sqlite3_mutex_enter(mutexShared);
|
|
pBt->pNext = sqlite3SharedCacheList;
|
|
sqlite3SharedCacheList = pBt;
|
|
sqlite3_mutex_leave(mutexShared);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( p->sharable ){
|
|
int i;
|
|
Btree *pSib;
|
|
for(i=0; i<db->nDb; i++){
|
|
if( (pSib = db->aDb[i].pBt)!=0 && pSib->sharable ){
|
|
while( pSib->pPrev ){ pSib = pSib->pPrev; }
|
|
if( (uptr)p->pBt<(uptr)pSib->pBt ){
|
|
p->pNext = pSib;
|
|
p->pPrev = 0;
|
|
pSib->pPrev = p;
|
|
}else{
|
|
while( pSib->pNext && (uptr)pSib->pNext->pBt<(uptr)p->pBt ){
|
|
pSib = pSib->pNext;
|
|
}
|
|
p->pNext = pSib->pNext;
|
|
p->pPrev = pSib;
|
|
if( p->pNext ){
|
|
p->pNext->pPrev = p;
|
|
}
|
|
pSib->pNext = p;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
*ppBtree = p;
|
|
|
|
btree_open_out:
|
|
if( rc!=0 ){
|
|
if( pBt && pBt->pPager ){
|
|
sqlite3PagerClose(pBt->pPager, 0);
|
|
}
|
|
sqlite3_free(pBt);
|
|
sqlite3_free(p);
|
|
*ppBtree = 0;
|
|
}else{
|
|
sqlite3_file *pFile;
|
|
|
|
|
|
|
|
|
|
|
|
if( sqlite3BtreeSchema(p, 0, 0)==0 ){
|
|
sqlite3PagerSetCachesize(p->pBt->pPager, -2000);
|
|
}
|
|
|
|
pFile = sqlite3PagerFile(pBt->pPager);
|
|
if( pFile->pMethods ){
|
|
sqlite3OsFileControlHint(pFile, 30, (void*)&pBt->db);
|
|
}
|
|
}
|
|
if( mutexOpen ){
|
|
assert( sqlite3_mutex_held(mutexOpen) );
|
|
sqlite3_mutex_leave(mutexOpen);
|
|
}
|
|
assert( rc!=0 || sqlite3BtreeConnectionCount(*ppBtree)>0 );
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int removeFromSharingList(BtShared *pBt){
|
|
|
|
sqlite3_mutex *pMaster;
|
|
BtShared *pList;
|
|
int removed = 0;
|
|
|
|
assert( sqlite3_mutex_notheld(pBt->mutex) );
|
|
pMaster = sqlite3MutexAlloc(2);
|
|
sqlite3_mutex_enter(pMaster);
|
|
pBt->nRef--;
|
|
if( pBt->nRef<=0 ){
|
|
if( sqlite3SharedCacheList==pBt ){
|
|
sqlite3SharedCacheList = pBt->pNext;
|
|
}else{
|
|
pList = sqlite3SharedCacheList;
|
|
while( (pList) && pList->pNext!=pBt ){
|
|
pList=pList->pNext;
|
|
}
|
|
if( (pList) ){
|
|
pList->pNext = pBt->pNext;
|
|
}
|
|
}
|
|
if( 1 ){
|
|
sqlite3_mutex_free(pBt->mutex);
|
|
}
|
|
removed = 1;
|
|
}
|
|
sqlite3_mutex_leave(pMaster);
|
|
return removed;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void allocateTempSpace(BtShared *pBt){
|
|
if( !pBt->pTmpSpace ){
|
|
pBt->pTmpSpace = sqlite3PageMalloc( pBt->pageSize );
|
|
# 2675 "src/btree.c"
|
|
if( pBt->pTmpSpace ){
|
|
memset(pBt->pTmpSpace, 0, 8);
|
|
pBt->pTmpSpace += 4;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
static void freeTempSpace(BtShared *pBt){
|
|
if( pBt->pTmpSpace ){
|
|
pBt->pTmpSpace -= 4;
|
|
sqlite3PageFree(pBt->pTmpSpace);
|
|
pBt->pTmpSpace = 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
int sqlite3BtreeClose(Btree *p){
|
|
BtShared *pBt = p->pBt;
|
|
BtCursor *pCur;
|
|
|
|
|
|
assert( sqlite3_mutex_held(p->db->mutex) );
|
|
sqlite3BtreeEnter(p);
|
|
pCur = pBt->pCursor;
|
|
while( pCur ){
|
|
BtCursor *pTmp = pCur;
|
|
pCur = pCur->pNext;
|
|
if( pTmp->pBtree==p ){
|
|
sqlite3BtreeCloseCursor(pTmp);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sqlite3BtreeRollback(p, 0, 0);
|
|
sqlite3BtreeLeave(p);
|
|
|
|
|
|
|
|
|
|
|
|
assert( p->wantToLock==0 && p->locked==0 );
|
|
if( !p->sharable || removeFromSharingList(pBt) ){
|
|
|
|
|
|
|
|
|
|
|
|
assert( !pBt->pCursor );
|
|
sqlite3PagerClose(pBt->pPager, p->db);
|
|
if( pBt->xFreeSchema && pBt->pSchema ){
|
|
pBt->xFreeSchema(pBt->pSchema);
|
|
}
|
|
sqlite3DbFree(0, pBt->pSchema);
|
|
freeTempSpace(pBt);
|
|
sqlite3_free(pBt);
|
|
}
|
|
|
|
|
|
assert( p->wantToLock==0 );
|
|
assert( p->locked==0 );
|
|
if( p->pPrev ) p->pPrev->pNext = p->pNext;
|
|
if( p->pNext ) p->pNext->pPrev = p->pPrev;
|
|
|
|
|
|
sqlite3_free(p);
|
|
return 0;
|
|
}
|
|
# 2758 "src/btree.c"
|
|
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 0;
|
|
}
|
|
# 2777 "src/btree.c"
|
|
int sqlite3BtreeSetSpillSize(Btree *p, int mxPage){
|
|
BtShared *pBt = p->pBt;
|
|
int res;
|
|
assert( sqlite3_mutex_held(p->db->mutex) );
|
|
sqlite3BtreeEnter(p);
|
|
res = sqlite3PagerSetSpillsize(pBt->pPager, mxPage);
|
|
sqlite3BtreeLeave(p);
|
|
return res;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int sqlite3BtreeSetMmapLimit(Btree *p, sqlite3_int64 szMmap){
|
|
BtShared *pBt = p->pBt;
|
|
assert( sqlite3_mutex_held(p->db->mutex) );
|
|
sqlite3BtreeEnter(p);
|
|
sqlite3PagerSetMmapLimit(pBt->pPager, szMmap);
|
|
sqlite3BtreeLeave(p);
|
|
return 0;
|
|
}
|
|
# 2811 "src/btree.c"
|
|
int sqlite3BtreeSetPagerFlags(
|
|
Btree *p,
|
|
unsigned pgFlags
|
|
){
|
|
BtShared *pBt = p->pBt;
|
|
assert( sqlite3_mutex_held(p->db->mutex) );
|
|
sqlite3BtreeEnter(p);
|
|
sqlite3PagerSetFlags(pBt->pPager, pgFlags);
|
|
sqlite3BtreeLeave(p);
|
|
return 0;
|
|
}
|
|
# 2844 "src/btree.c"
|
|
int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){
|
|
int rc = 0;
|
|
BtShared *pBt = p->pBt;
|
|
assert( nReserve>=-1 && nReserve<=255 );
|
|
sqlite3BtreeEnter(p);
|
|
|
|
|
|
|
|
if( pBt->btsFlags & 0x0002 ){
|
|
sqlite3BtreeLeave(p);
|
|
return 8;
|
|
}
|
|
if( nReserve<0 ){
|
|
nReserve = pBt->pageSize - pBt->usableSize;
|
|
}
|
|
assert( nReserve>=0 && nReserve<=255 );
|
|
if( pageSize>=512 && pageSize<=65536 &&
|
|
((pageSize-1)&pageSize)==0 ){
|
|
assert( (pageSize & 7)==0 );
|
|
assert( !pBt->pCursor );
|
|
pBt->pageSize = (u32)pageSize;
|
|
freeTempSpace(pBt);
|
|
}
|
|
rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize, nReserve);
|
|
pBt->usableSize = pBt->pageSize - (u16)nReserve;
|
|
if( iFix ) pBt->btsFlags |= 0x0002;
|
|
sqlite3BtreeLeave(p);
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
|
|
int sqlite3BtreeGetPageSize(Btree *p){
|
|
return p->pBt->pageSize;
|
|
}
|
|
# 2892 "src/btree.c"
|
|
int sqlite3BtreeGetReserveNoMutex(Btree *p){
|
|
int n;
|
|
assert( sqlite3_mutex_held(p->pBt->mutex) );
|
|
n = p->pBt->pageSize - p->pBt->usableSize;
|
|
return n;
|
|
}
|
|
# 2908 "src/btree.c"
|
|
int sqlite3BtreeGetOptimalReserve(Btree *p){
|
|
int n;
|
|
sqlite3BtreeEnter(p);
|
|
n = sqlite3BtreeGetReserveNoMutex(p);
|
|
|
|
|
|
|
|
sqlite3BtreeLeave(p);
|
|
return n;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int sqlite3BtreeMaxPageCount(Btree *p, int mxPage){
|
|
int n;
|
|
sqlite3BtreeEnter(p);
|
|
n = sqlite3PagerMaxPageCount(p->pBt->pPager, mxPage);
|
|
sqlite3BtreeLeave(p);
|
|
return n;
|
|
}
|
|
# 2951 "src/btree.c"
|
|
int sqlite3BtreeSecureDelete(Btree *p, int newFlag){
|
|
int b;
|
|
if( p==0 ) return 0;
|
|
sqlite3BtreeEnter(p);
|
|
assert( 0x0008==0x0004*2 );
|
|
assert( 0x000c==(0x0008|0x0004) );
|
|
if( newFlag>=0 ){
|
|
p->pBt->btsFlags &= ~0x000c;
|
|
p->pBt->btsFlags |= 0x0004*newFlag;
|
|
}
|
|
b = (p->pBt->btsFlags & 0x000c)/0x0004;
|
|
sqlite3BtreeLeave(p);
|
|
return b;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int sqlite3BtreeSetAutoVacuum(Btree *p, int autoVacuum){
|
|
|
|
|
|
|
|
BtShared *pBt = p->pBt;
|
|
int rc = 0;
|
|
u8 av = (u8)autoVacuum;
|
|
|
|
sqlite3BtreeEnter(p);
|
|
if( (pBt->btsFlags & 0x0002)!=0 && (av ?1:0)!=pBt->autoVacuum ){
|
|
rc = 8;
|
|
}else{
|
|
pBt->autoVacuum = av ?1:0;
|
|
pBt->incrVacuum = av==2 ?1:0;
|
|
}
|
|
sqlite3BtreeLeave(p);
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int sqlite3BtreeGetAutoVacuum(Btree *p){
|
|
|
|
|
|
|
|
int rc;
|
|
sqlite3BtreeEnter(p);
|
|
rc = (
|
|
(!p->pBt->autoVacuum)?0:
|
|
(!p->pBt->incrVacuum)?1:
|
|
2
|
|
);
|
|
sqlite3BtreeLeave(p);
|
|
return rc;
|
|
|
|
}
|
|
# 3040 "src/btree.c"
|
|
static int newDatabase(BtShared*);
|
|
# 3052 "src/btree.c"
|
|
static int lockBtree(BtShared *pBt){
|
|
int rc;
|
|
MemPage *pPage1;
|
|
u32 nPage;
|
|
u32 nPageFile = 0;
|
|
u32 nPageHeader;
|
|
|
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
|
assert( pBt->pPage1==0 );
|
|
rc = sqlite3PagerSharedLock(pBt->pPager);
|
|
if( rc!=0 ) return rc;
|
|
rc = btreeGetPage(pBt, 1, &pPage1, 0);
|
|
if( rc!=0 ) return rc;
|
|
|
|
|
|
|
|
|
|
nPage = nPageHeader = sqlite3Get4byte(28+(u8*)pPage1->aData);
|
|
sqlite3PagerPagecount(pBt->pPager, (int*)&nPageFile);
|
|
if( nPage==0 || memcmp(24+(u8*)pPage1->aData, 92+(u8*)pPage1->aData,4)!=0 ){
|
|
nPage = nPageFile;
|
|
}
|
|
if( (pBt->db->flags & 0x02000000)!=0 ){
|
|
nPage = 0;
|
|
}
|
|
if( nPage>0 ){
|
|
u32 pageSize;
|
|
u32 usableSize;
|
|
u8 *page1 = pPage1->aData;
|
|
rc = 26;
|
|
|
|
|
|
|
|
if( memcmp(page1, zMagicHeader, 16)!=0 ){
|
|
goto page1_init_failed;
|
|
}
|
|
# 3097 "src/btree.c"
|
|
if( page1[18]>2 ){
|
|
pBt->btsFlags |= 0x0001;
|
|
}
|
|
if( page1[19]>2 ){
|
|
goto page1_init_failed;
|
|
}
|
|
# 3112 "src/btree.c"
|
|
if( page1[19]==2 && (pBt->btsFlags & 0x0020)==0 ){
|
|
int isOpen = 0;
|
|
rc = sqlite3PagerOpenWal(pBt->pPager, &isOpen);
|
|
if( rc!=0 ){
|
|
goto page1_init_failed;
|
|
}else{
|
|
;
|
|
if( isOpen==0 ){
|
|
releasePageOne(pPage1);
|
|
return 0;
|
|
}
|
|
}
|
|
rc = 26;
|
|
}else{
|
|
;
|
|
}
|
|
# 3136 "src/btree.c"
|
|
if( memcmp(&page1[21], "\100\040\040",3)!=0 ){
|
|
goto page1_init_failed;
|
|
}
|
|
|
|
|
|
|
|
pageSize = (page1[16]<<8) | (page1[17]<<16);
|
|
|
|
|
|
if( ((pageSize-1)&pageSize)!=0
|
|
|| pageSize>65536
|
|
|| pageSize<=256
|
|
){
|
|
goto page1_init_failed;
|
|
}
|
|
pBt->btsFlags |= 0x0002;
|
|
assert( (pageSize & 7)==0 );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
usableSize = pageSize - page1[20];
|
|
if( (u32)pageSize!=pBt->pageSize ){
|
|
|
|
|
|
|
|
|
|
|
|
|
|
releasePageOne(pPage1);
|
|
pBt->usableSize = usableSize;
|
|
pBt->pageSize = pageSize;
|
|
freeTempSpace(pBt);
|
|
rc = sqlite3PagerSetPagesize(pBt->pPager, &pBt->pageSize,
|
|
pageSize-usableSize);
|
|
return rc;
|
|
}
|
|
if( sqlite3WritableSchema(pBt->db)==0 && nPage>nPageFile ){
|
|
rc = sqlite3CorruptError(3177);
|
|
goto page1_init_failed;
|
|
}
|
|
|
|
|
|
|
|
if( usableSize<480 ){
|
|
goto page1_init_failed;
|
|
}
|
|
pBt->pageSize = pageSize;
|
|
pBt->usableSize = usableSize;
|
|
|
|
pBt->autoVacuum = (sqlite3Get4byte(&page1[36 + 4*4])?1:0);
|
|
pBt->incrVacuum = (sqlite3Get4byte(&page1[36 + 7*4])?1:0);
|
|
|
|
}
|
|
# 3207 "src/btree.c"
|
|
pBt->maxLocal = (u16)((pBt->usableSize-12)*64/255 - 23);
|
|
pBt->minLocal = (u16)((pBt->usableSize-12)*32/255 - 23);
|
|
pBt->maxLeaf = (u16)(pBt->usableSize - 35);
|
|
pBt->minLeaf = (u16)((pBt->usableSize-12)*32/255 - 23);
|
|
if( pBt->maxLocal>127 ){
|
|
pBt->max1bytePayload = 127;
|
|
}else{
|
|
pBt->max1bytePayload = (u8)pBt->maxLocal;
|
|
}
|
|
assert( pBt->maxLeaf + 23 <= ((int)(pBt->pageSize-8)) );
|
|
pBt->pPage1 = pPage1;
|
|
pBt->nPage = nPage;
|
|
return 0;
|
|
|
|
page1_init_failed:
|
|
releasePageOne(pPage1);
|
|
pBt->pPage1 = 0;
|
|
return rc;
|
|
}
|
|
# 3259 "src/btree.c"
|
|
static void unlockBtreeIfUnused(BtShared *pBt){
|
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
|
assert( countValidCursors(pBt,0)==0 || pBt->inTransaction>0 );
|
|
if( pBt->inTransaction==0 && pBt->pPage1!=0 ){
|
|
MemPage *pPage1 = pBt->pPage1;
|
|
assert( pPage1->aData );
|
|
assert( sqlite3PagerRefcount(pBt->pPager)==1 );
|
|
pBt->pPage1 = 0;
|
|
releasePageOne(pPage1);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int newDatabase(BtShared *pBt){
|
|
MemPage *pP1;
|
|
unsigned char *data;
|
|
int rc;
|
|
|
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
|
if( pBt->nPage>0 ){
|
|
return 0;
|
|
}
|
|
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 );
|
|
data[16] = (u8)((pBt->pageSize>>8)&0xff);
|
|
data[17] = (u8)((pBt->pageSize>>16)&0xff);
|
|
data[18] = 1;
|
|
data[19] = 1;
|
|
assert( pBt->usableSize<=pBt->pageSize && pBt->usableSize+255>=pBt->pageSize);
|
|
data[20] = (u8)(pBt->pageSize - pBt->usableSize);
|
|
data[21] = 64;
|
|
data[22] = 32;
|
|
data[23] = 32;
|
|
memset(&data[24], 0, 100-24);
|
|
zeroPage(pP1, 0x01|0x08|0x04 );
|
|
pBt->btsFlags |= 0x0002;
|
|
|
|
assert( pBt->autoVacuum==1 || pBt->autoVacuum==0 );
|
|
assert( pBt->incrVacuum==1 || pBt->incrVacuum==0 );
|
|
sqlite3Put4byte(&data[36 + 4*4], pBt->autoVacuum);
|
|
sqlite3Put4byte(&data[36 + 7*4], pBt->incrVacuum);
|
|
|
|
pBt->nPage = 1;
|
|
data[31] = 1;
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int sqlite3BtreeNewDb(Btree *p){
|
|
int rc;
|
|
sqlite3BtreeEnter(p);
|
|
p->pBt->nPage = 0;
|
|
rc = newDatabase(p->pBt);
|
|
sqlite3BtreeLeave(p);
|
|
return rc;
|
|
}
|
|
# 3364 "src/btree.c"
|
|
int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){
|
|
BtShared *pBt = p->pBt;
|
|
int rc = 0;
|
|
|
|
sqlite3BtreeEnter(p);
|
|
assert( p->pBt->inTransaction!=0 || p->pBt->nTransaction==0 ); assert( p->pBt->inTransaction>=p->inTrans );;
|
|
|
|
|
|
|
|
|
|
|
|
if( p->inTrans==2 || (p->inTrans==1 && !wrflag) ){
|
|
goto trans_begun;
|
|
}
|
|
assert( pBt->inTransaction==2 || (pBt->bDoTruncate)==0 );
|
|
|
|
if( (p->db->flags & 0x02000000)
|
|
&& sqlite3PagerIsreadonly(pBt->pPager)==0
|
|
){
|
|
pBt->btsFlags &= ~0x0001;
|
|
}
|
|
|
|
|
|
if( (pBt->btsFlags & 0x0001)!=0 && wrflag ){
|
|
rc = 8;
|
|
goto trans_begun;
|
|
}
|
|
|
|
|
|
{
|
|
sqlite3 *pBlock = 0;
|
|
|
|
|
|
|
|
|
|
if( (wrflag && pBt->inTransaction==2)
|
|
|| (pBt->btsFlags & 0x0080)!=0
|
|
){
|
|
pBlock = pBt->pWriter->db;
|
|
}else if( wrflag>1 ){
|
|
BtLock *pIter;
|
|
for(pIter=pBt->pLock; pIter; pIter=pIter->pNext){
|
|
if( pIter->pBtree!=p ){
|
|
pBlock = pIter->pBtree->db;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if( pBlock ){
|
|
;
|
|
rc = (6 | (1<<8));
|
|
goto trans_begun;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
rc = querySharedCacheTableLock(p, 1, 1);
|
|
if( 0!=rc ) goto trans_begun;
|
|
|
|
pBt->btsFlags &= ~0x0010;
|
|
if( pBt->nPage==0 ) pBt->btsFlags |= 0x0010;
|
|
do {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while( pBt->pPage1==0 && 0==(rc = lockBtree(pBt)) );
|
|
|
|
if( rc==0 && wrflag ){
|
|
if( (pBt->btsFlags & 0x0001)!=0 ){
|
|
rc = 8;
|
|
}else{
|
|
rc = sqlite3PagerBegin(pBt->pPager,wrflag>1,sqlite3TempInMemory(p->db));
|
|
if( rc==0 ){
|
|
rc = newDatabase(pBt);
|
|
}else if( rc==(5 | (2<<8)) && pBt->inTransaction==0 ){
|
|
|
|
|
|
|
|
rc = 5;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( rc!=0 ){
|
|
unlockBtreeIfUnused(pBt);
|
|
}
|
|
}while( (rc&0xFF)==5 && pBt->inTransaction==0 &&
|
|
btreeInvokeBusyHandler(pBt) );
|
|
;
|
|
|
|
if( rc==0 ){
|
|
if( p->inTrans==0 ){
|
|
pBt->nTransaction++;
|
|
|
|
if( p->sharable ){
|
|
assert( p->lock.pBtree==p && p->lock.iTable==1 );
|
|
p->lock.eLock = 1;
|
|
p->lock.pNext = pBt->pLock;
|
|
pBt->pLock = &p->lock;
|
|
}
|
|
|
|
}
|
|
p->inTrans = (wrflag?2:1);
|
|
if( p->inTrans>pBt->inTransaction ){
|
|
pBt->inTransaction = p->inTrans;
|
|
}
|
|
if( wrflag ){
|
|
MemPage *pPage1 = pBt->pPage1;
|
|
|
|
assert( !pBt->pWriter );
|
|
pBt->pWriter = p;
|
|
pBt->btsFlags &= ~0x0040;
|
|
if( wrflag>1 ) pBt->btsFlags |= 0x0040;
|
|
# 3492 "src/btree.c"
|
|
if( pBt->nPage!=sqlite3Get4byte(&pPage1->aData[28]) ){
|
|
rc = sqlite3PagerWrite(pPage1->pDbPage);
|
|
if( rc==0 ){
|
|
sqlite3Put4byte(&pPage1->aData[28], pBt->nPage);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
trans_begun:
|
|
if( rc==0 ){
|
|
if( pSchemaVersion ){
|
|
*pSchemaVersion = sqlite3Get4byte(&pBt->pPage1->aData[40]);
|
|
}
|
|
if( wrflag ){
|
|
|
|
|
|
|
|
|
|
rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint);
|
|
}
|
|
}
|
|
|
|
assert( p->pBt->inTransaction!=0 || p->pBt->nTransaction==0 ); assert( p->pBt->inTransaction>=p->inTrans );;
|
|
sqlite3BtreeLeave(p);
|
|
return rc;
|
|
}
|
|
# 3527 "src/btree.c"
|
|
static int setChildPtrmaps(MemPage *pPage){
|
|
int i;
|
|
int nCell;
|
|
int rc;
|
|
BtShared *pBt = pPage->pBt;
|
|
Pgno pgno = pPage->pgno;
|
|
|
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
|
rc = pPage->isInit ? 0 : btreeInitPage(pPage);
|
|
if( rc!=0 ) return rc;
|
|
nCell = pPage->nCell;
|
|
|
|
for(i=0; i<nCell; i++){
|
|
u8 *pCell = ((pPage)->aData + ((pPage)->maskPage & __builtin_bswap16(*(u16*)(&(pPage)->aCellIdx[2*(i)]))));
|
|
|
|
ptrmapPutOvflPtr(pPage, pPage, pCell, &rc);
|
|
|
|
if( !pPage->leaf ){
|
|
Pgno childPgno = sqlite3Get4byte(pCell);
|
|
ptrmapPut(pBt, childPgno, 5, pgno, &rc);
|
|
}
|
|
}
|
|
|
|
if( !pPage->leaf ){
|
|
Pgno childPgno = sqlite3Get4byte(&pPage->aData[pPage->hdrOffset+8]);
|
|
ptrmapPut(pBt, childPgno, 5, pgno, &rc);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
# 3572 "src/btree.c"
|
|
static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
|
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
|
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
|
|
if( eType==4 ){
|
|
|
|
if( sqlite3Get4byte(pPage->aData)!=iFrom ){
|
|
return sqlite3CorruptError(3578);
|
|
}
|
|
sqlite3Put4byte(pPage->aData, iTo);
|
|
}else{
|
|
int i;
|
|
int nCell;
|
|
int rc;
|
|
|
|
rc = pPage->isInit ? 0 : btreeInitPage(pPage);
|
|
if( rc ) return rc;
|
|
nCell = pPage->nCell;
|
|
|
|
for(i=0; i<nCell; i++){
|
|
u8 *pCell = ((pPage)->aData + ((pPage)->maskPage & __builtin_bswap16(*(u16*)(&(pPage)->aCellIdx[2*(i)]))));
|
|
if( eType==3 ){
|
|
CellInfo info;
|
|
pPage->xParseCell(pPage, pCell, &info);
|
|
if( info.nLocal<info.nPayload ){
|
|
if( pCell+info.nSize > pPage->aData+pPage->pBt->usableSize ){
|
|
return sqlite3CorruptError(3597);
|
|
}
|
|
if( iFrom==sqlite3Get4byte(pCell+info.nSize-4) ){
|
|
sqlite3Put4byte(pCell+info.nSize-4, iTo);
|
|
break;
|
|
}
|
|
}
|
|
}else{
|
|
if( sqlite3Get4byte(pCell)==iFrom ){
|
|
sqlite3Put4byte(pCell, iTo);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( i==nCell ){
|
|
if( eType!=5 ||
|
|
sqlite3Get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){
|
|
return sqlite3CorruptError(3615);
|
|
}
|
|
sqlite3Put4byte(&pPage->aData[pPage->hdrOffset+8], iTo);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
# 3633 "src/btree.c"
|
|
static int relocatePage(
|
|
BtShared *pBt,
|
|
MemPage *pDbPage,
|
|
u8 eType,
|
|
Pgno iPtrPage,
|
|
Pgno iFreePage,
|
|
int isCommit
|
|
){
|
|
MemPage *pPtrPage;
|
|
Pgno iDbPage = pDbPage->pgno;
|
|
Pager *pPager = pBt->pPager;
|
|
int rc;
|
|
|
|
assert( eType==4 || eType==3 ||
|
|
eType==5 || eType==1 );
|
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
|
assert( pDbPage->pBt==pBt );
|
|
if( iDbPage<3 ) return sqlite3CorruptError(3650);
|
|
|
|
|
|
|
|
;
|
|
rc = sqlite3PagerMovepage(pPager, pDbPage->pDbPage, iFreePage, isCommit);
|
|
if( rc!=0 ){
|
|
return rc;
|
|
}
|
|
pDbPage->pgno = iFreePage;
|
|
# 3669 "src/btree.c"
|
|
if( eType==5 || eType==1 ){
|
|
rc = setChildPtrmaps(pDbPage);
|
|
if( rc!=0 ){
|
|
return rc;
|
|
}
|
|
}else{
|
|
Pgno nextOvfl = sqlite3Get4byte(pDbPage->aData);
|
|
if( nextOvfl!=0 ){
|
|
ptrmapPut(pBt, nextOvfl, 4, iFreePage, &rc);
|
|
if( rc!=0 ){
|
|
return rc;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if( eType!=1 ){
|
|
rc = btreeGetPage(pBt, iPtrPage, &pPtrPage, 0);
|
|
if( rc!=0 ){
|
|
return rc;
|
|
}
|
|
rc = sqlite3PagerWrite(pPtrPage->pDbPage);
|
|
if( rc!=0 ){
|
|
releasePage(pPtrPage);
|
|
return rc;
|
|
}
|
|
rc = modifyPagePointer(pPtrPage, iDbPage, iFreePage, eType);
|
|
releasePage(pPtrPage);
|
|
if( rc==0 ){
|
|
ptrmapPut(pBt, iFreePage, eType, iPtrPage, &rc);
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
|
|
static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8);
|
|
# 3727 "src/btree.c"
|
|
static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){
|
|
Pgno nFreeList;
|
|
int rc;
|
|
|
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
|
assert( iLastPg>nFin );
|
|
|
|
if( !(ptrmapPageno((pBt), (iLastPg))==(iLastPg)) && iLastPg!=((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) ){
|
|
u8 eType;
|
|
Pgno iPtrPage;
|
|
|
|
nFreeList = sqlite3Get4byte(&pBt->pPage1->aData[36]);
|
|
if( nFreeList==0 ){
|
|
return 101;
|
|
}
|
|
|
|
rc = ptrmapGet(pBt, iLastPg, &eType, &iPtrPage);
|
|
if( rc!=0 ){
|
|
return rc;
|
|
}
|
|
if( eType==1 ){
|
|
return sqlite3CorruptError(3748);
|
|
}
|
|
|
|
if( eType==2 ){
|
|
if( bCommit==0 ){
|
|
|
|
|
|
|
|
|
|
|
|
Pgno iFreePg;
|
|
MemPage *pFreePg;
|
|
rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iLastPg, 1);
|
|
if( rc!=0 ){
|
|
return rc;
|
|
}
|
|
assert( iFreePg==iLastPg );
|
|
releasePage(pFreePg);
|
|
}
|
|
} else {
|
|
Pgno iFreePg;
|
|
MemPage *pLastPg;
|
|
u8 eMode = 0;
|
|
Pgno iNear = 0;
|
|
|
|
rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0);
|
|
if( rc!=0 ){
|
|
return rc;
|
|
}
|
|
# 3785 "src/btree.c"
|
|
if( bCommit==0 ){
|
|
eMode = 2;
|
|
iNear = nFin;
|
|
}
|
|
do {
|
|
MemPage *pFreePg;
|
|
rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iNear, eMode);
|
|
if( rc!=0 ){
|
|
releasePage(pLastPg);
|
|
return rc;
|
|
}
|
|
releasePage(pFreePg);
|
|
}while( bCommit && iFreePg>nFin );
|
|
assert( iFreePg<iLastPg );
|
|
|
|
rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg, bCommit);
|
|
releasePage(pLastPg);
|
|
if( rc!=0 ){
|
|
return rc;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( bCommit==0 ){
|
|
do {
|
|
iLastPg--;
|
|
}while( iLastPg==((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) || (ptrmapPageno((pBt), (iLastPg))==(iLastPg)) );
|
|
pBt->bDoTruncate = 1;
|
|
pBt->nPage = iLastPg;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static Pgno finalDbSize(BtShared *pBt, Pgno nOrig, Pgno nFree){
|
|
int nEntry;
|
|
Pgno nPtrmap;
|
|
Pgno nFin;
|
|
|
|
nEntry = pBt->usableSize/5;
|
|
nPtrmap = (nFree-nOrig+ptrmapPageno(pBt, nOrig)+nEntry)/nEntry;
|
|
nFin = nOrig - nFree - nPtrmap;
|
|
if( nOrig>((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) && nFin<((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) ){
|
|
nFin--;
|
|
}
|
|
while( (ptrmapPageno((pBt), (nFin))==(nFin)) || nFin==((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) ){
|
|
nFin--;
|
|
}
|
|
|
|
return nFin;
|
|
}
|
|
# 3849 "src/btree.c"
|
|
int sqlite3BtreeIncrVacuum(Btree *p){
|
|
int rc;
|
|
BtShared *pBt = p->pBt;
|
|
|
|
sqlite3BtreeEnter(p);
|
|
assert( pBt->inTransaction==2 && p->inTrans==2 );
|
|
if( !pBt->autoVacuum ){
|
|
rc = 101;
|
|
}else{
|
|
Pgno nOrig = btreePagecount(pBt);
|
|
Pgno nFree = sqlite3Get4byte(&pBt->pPage1->aData[36]);
|
|
Pgno nFin = finalDbSize(pBt, nOrig, nFree);
|
|
|
|
if( nOrig<nFin ){
|
|
rc = sqlite3CorruptError(3863);
|
|
}else if( nFree>0 ){
|
|
rc = saveAllCursors(pBt, 0, 0);
|
|
if( rc==0 ){
|
|
invalidateAllOverflowCache(pBt);
|
|
rc = incrVacuumStep(pBt, nFin, nOrig, 0);
|
|
}
|
|
if( rc==0 ){
|
|
rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
|
|
sqlite3Put4byte(&pBt->pPage1->aData[28], pBt->nPage);
|
|
}
|
|
}else{
|
|
rc = 101;
|
|
}
|
|
}
|
|
sqlite3BtreeLeave(p);
|
|
return rc;
|
|
}
|
|
# 3891 "src/btree.c"
|
|
static int autoVacuumCommit(BtShared *pBt){
|
|
int rc = 0;
|
|
Pager *pPager = pBt->pPager;
|
|
|
|
|
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
|
invalidateAllOverflowCache(pBt);
|
|
assert(pBt->autoVacuum);
|
|
if( !pBt->incrVacuum ){
|
|
Pgno nFin;
|
|
Pgno nFree;
|
|
Pgno iFree;
|
|
Pgno nOrig;
|
|
|
|
nOrig = btreePagecount(pBt);
|
|
if( (ptrmapPageno((pBt), (nOrig))==(nOrig)) || nOrig==((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) ){
|
|
|
|
|
|
|
|
|
|
return sqlite3CorruptError(3911);
|
|
}
|
|
|
|
nFree = sqlite3Get4byte(&pBt->pPage1->aData[36]);
|
|
nFin = finalDbSize(pBt, nOrig, nFree);
|
|
if( nFin>nOrig ) return sqlite3CorruptError(3916);
|
|
if( nFin<nOrig ){
|
|
rc = saveAllCursors(pBt, 0, 0);
|
|
}
|
|
for(iFree=nOrig; iFree>nFin && rc==0; iFree--){
|
|
rc = incrVacuumStep(pBt, nFin, iFree, 1);
|
|
}
|
|
if( (rc==101 || rc==0) && nFree>0 ){
|
|
rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
|
|
sqlite3Put4byte(&pBt->pPage1->aData[32], 0);
|
|
sqlite3Put4byte(&pBt->pPage1->aData[36], 0);
|
|
sqlite3Put4byte(&pBt->pPage1->aData[28], nFin);
|
|
pBt->bDoTruncate = 1;
|
|
pBt->nPage = nFin;
|
|
}
|
|
if( rc!=0 ){
|
|
sqlite3PagerRollback(pPager);
|
|
}
|
|
}
|
|
|
|
assert( nRef>=sqlite3PagerRefcount(pPager) );
|
|
return rc;
|
|
}
|
|
# 3970 "src/btree.c"
|
|
int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){
|
|
int rc = 0;
|
|
if( p->inTrans==2 ){
|
|
BtShared *pBt = p->pBt;
|
|
sqlite3BtreeEnter(p);
|
|
|
|
if( pBt->autoVacuum ){
|
|
rc = autoVacuumCommit(pBt);
|
|
if( rc!=0 ){
|
|
sqlite3BtreeLeave(p);
|
|
return rc;
|
|
}
|
|
}
|
|
if( pBt->bDoTruncate ){
|
|
sqlite3PagerTruncateImage(pBt->pPager, pBt->nPage);
|
|
}
|
|
|
|
rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, 0);
|
|
sqlite3BtreeLeave(p);
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void btreeEndTransaction(Btree *p){
|
|
BtShared *pBt = p->pBt;
|
|
sqlite3 *db = p->db;
|
|
assert( sqlite3BtreeHoldsMutex(p) );
|
|
|
|
|
|
pBt->bDoTruncate = 0;
|
|
|
|
if( p->inTrans>0 && db->nVdbeRead>1 ){
|
|
|
|
|
|
|
|
downgradeAllSharedCacheTableLocks(p);
|
|
p->inTrans = 1;
|
|
}else{
|
|
|
|
|
|
|
|
|
|
if( p->inTrans!=0 ){
|
|
clearAllSharedCacheTableLocks(p);
|
|
pBt->nTransaction--;
|
|
if( 0==pBt->nTransaction ){
|
|
pBt->inTransaction = 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
p->inTrans = 0;
|
|
unlockBtreeIfUnused(pBt);
|
|
}
|
|
|
|
assert( p->pBt->inTransaction!=0 || p->pBt->nTransaction==0 ); assert( p->pBt->inTransaction>=p->inTrans );;
|
|
}
|
|
# 4059 "src/btree.c"
|
|
int sqlite3BtreeCommitPhaseTwo(Btree *p, int bCleanup){
|
|
|
|
if( p->inTrans==0 ) return 0;
|
|
sqlite3BtreeEnter(p);
|
|
assert( p->pBt->inTransaction!=0 || p->pBt->nTransaction==0 ); assert( p->pBt->inTransaction>=p->inTrans );;
|
|
|
|
|
|
|
|
|
|
if( p->inTrans==2 ){
|
|
int rc;
|
|
BtShared *pBt = p->pBt;
|
|
assert( pBt->inTransaction==2 );
|
|
assert( pBt->nTransaction>0 );
|
|
rc = sqlite3PagerCommitPhaseTwo(pBt->pPager);
|
|
if( rc!=0 && bCleanup==0 ){
|
|
sqlite3BtreeLeave(p);
|
|
return rc;
|
|
}
|
|
p->iDataVersion--;
|
|
pBt->inTransaction = 1;
|
|
btreeClearHasContent(pBt);
|
|
}
|
|
|
|
btreeEndTransaction(p);
|
|
sqlite3BtreeLeave(p);
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
int sqlite3BtreeCommit(Btree *p){
|
|
int rc;
|
|
sqlite3BtreeEnter(p);
|
|
rc = sqlite3BtreeCommitPhaseOne(p, 0);
|
|
if( rc==0 ){
|
|
rc = sqlite3BtreeCommitPhaseTwo(p, 0);
|
|
}
|
|
sqlite3BtreeLeave(p);
|
|
return rc;
|
|
}
|
|
# 4128 "src/btree.c"
|
|
int sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode, int writeOnly){
|
|
BtCursor *p;
|
|
int rc = 0;
|
|
|
|
assert( (writeOnly==0 || writeOnly==1) && 0x01==1 );
|
|
if( pBtree ){
|
|
sqlite3BtreeEnter(pBtree);
|
|
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
|
|
if( writeOnly && (p->curFlags & 0x01)==0 ){
|
|
if( p->eState==0 || p->eState==2 ){
|
|
rc = saveCursorPosition(p);
|
|
if( rc!=0 ){
|
|
(void)sqlite3BtreeTripAllCursors(pBtree, rc, 0);
|
|
break;
|
|
}
|
|
}
|
|
}else{
|
|
sqlite3BtreeClearCursor(p);
|
|
p->eState = 4;
|
|
p->skipNext = errCode;
|
|
}
|
|
btreeReleaseAllCursorPages(p);
|
|
}
|
|
sqlite3BtreeLeave(pBtree);
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void btreeSetNPage(BtShared *pBt, MemPage *pPage1){
|
|
int nPage = sqlite3Get4byte(&pPage1->aData[28]);
|
|
;
|
|
if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage);
|
|
;
|
|
pBt->nPage = nPage;
|
|
}
|
|
# 4179 "src/btree.c"
|
|
int sqlite3BtreeRollback(Btree *p, int tripCode, int writeOnly){
|
|
int rc;
|
|
BtShared *pBt = p->pBt;
|
|
MemPage *pPage1;
|
|
|
|
assert( writeOnly==1 || writeOnly==0 );
|
|
assert( tripCode==(4 | (2<<8)) || tripCode==0 );
|
|
sqlite3BtreeEnter(p);
|
|
if( tripCode==0 ){
|
|
rc = tripCode = saveAllCursors(pBt, 0, 0);
|
|
if( rc ) writeOnly = 0;
|
|
}else{
|
|
rc = 0;
|
|
}
|
|
if( tripCode ){
|
|
int rc2 = sqlite3BtreeTripAllCursors(p, tripCode, writeOnly);
|
|
assert( rc==0 || (writeOnly==0 && rc2==0) );
|
|
if( rc2!=0 ) rc = rc2;
|
|
}
|
|
assert( p->pBt->inTransaction!=0 || p->pBt->nTransaction==0 ); assert( p->pBt->inTransaction>=p->inTrans );;
|
|
|
|
if( p->inTrans==2 ){
|
|
int rc2;
|
|
|
|
assert( 2==pBt->inTransaction );
|
|
rc2 = sqlite3PagerRollback(pBt->pPager);
|
|
if( rc2!=0 ){
|
|
rc = rc2;
|
|
}
|
|
|
|
|
|
|
|
|
|
if( btreeGetPage(pBt, 1, &pPage1, 0)==0 ){
|
|
btreeSetNPage(pBt, pPage1);
|
|
releasePageOne(pPage1);
|
|
}
|
|
assert( countValidCursors(pBt, 1)==0 );
|
|
pBt->inTransaction = 1;
|
|
btreeClearHasContent(pBt);
|
|
}
|
|
|
|
btreeEndTransaction(p);
|
|
sqlite3BtreeLeave(p);
|
|
return rc;
|
|
}
|
|
# 4244 "src/btree.c"
|
|
int sqlite3BtreeBeginStmt(Btree *p, int iStatement){
|
|
int rc;
|
|
BtShared *pBt = p->pBt;
|
|
sqlite3BtreeEnter(p);
|
|
assert( p->inTrans==2 );
|
|
assert( (pBt->btsFlags & 0x0001)==0 );
|
|
assert( iStatement>0 );
|
|
assert( iStatement>p->db->nSavepoint );
|
|
assert( pBt->inTransaction==2 );
|
|
|
|
|
|
|
|
|
|
|
|
rc = sqlite3PagerOpenSavepoint(pBt->pPager, iStatement);
|
|
sqlite3BtreeLeave(p);
|
|
return rc;
|
|
}
|
|
# 4275 "src/btree.c"
|
|
int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){
|
|
int rc = 0;
|
|
if( p && p->inTrans==2 ){
|
|
BtShared *pBt = p->pBt;
|
|
assert( op==1 || op==2 );
|
|
assert( iSavepoint>=0 || (iSavepoint==-1 && op==2) );
|
|
sqlite3BtreeEnter(p);
|
|
if( op==2 ){
|
|
rc = saveAllCursors(pBt, 0, 0);
|
|
}
|
|
if( rc==0 ){
|
|
rc = sqlite3PagerSavepoint(pBt->pPager, op, iSavepoint);
|
|
}
|
|
if( rc==0 ){
|
|
if( iSavepoint<0 && (pBt->btsFlags & 0x0010)!=0 ){
|
|
pBt->nPage = 0;
|
|
}
|
|
rc = newDatabase(pBt);
|
|
btreeSetNPage(pBt, pBt->pPage1);
|
|
|
|
|
|
|
|
assert( (sqlite3Config.neverCorrupt==0) || pBt->nPage>0 );
|
|
}
|
|
sqlite3BtreeLeave(p);
|
|
}
|
|
return rc;
|
|
}
|
|
# 4346 "src/btree.c"
|
|
static int btreeCursor(
|
|
Btree *p,
|
|
int iTable,
|
|
int wrFlag,
|
|
struct KeyInfo *pKeyInfo,
|
|
BtCursor *pCur
|
|
){
|
|
BtShared *pBt = p->pBt;
|
|
BtCursor *pX;
|
|
|
|
assert( sqlite3BtreeHoldsMutex(p) );
|
|
assert( wrFlag==0
|
|
|| wrFlag==0x00000004
|
|
|| wrFlag==(0x00000004|0x00000008)
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, (wrFlag?2:1)) );
|
|
assert( wrFlag==0 || !hasReadConflicts(p, iTable) );
|
|
|
|
|
|
assert( p->inTrans>0 );
|
|
assert( wrFlag==0 || p->inTrans==2 );
|
|
assert( pBt->pPage1 && pBt->pPage1->aData );
|
|
assert( wrFlag==0 || (pBt->btsFlags & 0x0001)==0 );
|
|
|
|
if( wrFlag ){
|
|
allocateTempSpace(pBt);
|
|
if( pBt->pTmpSpace==0 ) return 7;
|
|
}
|
|
if( iTable==1 && btreePagecount(pBt)==0 ){
|
|
assert( wrFlag==0 );
|
|
iTable = 0;
|
|
}
|
|
|
|
|
|
|
|
pCur->pgnoRoot = (Pgno)iTable;
|
|
pCur->iPage = -1;
|
|
pCur->pKeyInfo = pKeyInfo;
|
|
pCur->pBtree = p;
|
|
pCur->pBt = pBt;
|
|
pCur->curFlags = wrFlag ? 0x01 : 0;
|
|
pCur->curPagerFlags = wrFlag ? 0 : 0x02;
|
|
|
|
|
|
for(pX=pBt->pCursor; pX; pX=pX->pNext){
|
|
if( pX->pgnoRoot==(Pgno)iTable ){
|
|
pX->curFlags |= 0x20;
|
|
pCur->curFlags |= 0x20;
|
|
}
|
|
}
|
|
pCur->pNext = pBt->pCursor;
|
|
pBt->pCursor = pCur;
|
|
pCur->eState = 1;
|
|
return 0;
|
|
}
|
|
int sqlite3BtreeCursor(
|
|
Btree *p,
|
|
int iTable,
|
|
int wrFlag,
|
|
struct KeyInfo *pKeyInfo,
|
|
BtCursor *pCur
|
|
){
|
|
int rc;
|
|
if( iTable<1 ){
|
|
rc = sqlite3CorruptError(4415);
|
|
}else{
|
|
sqlite3BtreeEnter(p);
|
|
rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur);
|
|
sqlite3BtreeLeave(p);
|
|
}
|
|
return rc;
|
|
}
|
|
# 4432 "src/btree.c"
|
|
int sqlite3BtreeCursorSize(void){
|
|
return (((sizeof(BtCursor))+7)&~7);
|
|
}
|
|
# 4444 "src/btree.c"
|
|
void sqlite3BtreeCursorZero(BtCursor *p){
|
|
memset(p, 0, ((int)((char*)&((BtCursor*)0)->pBt)));
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int sqlite3BtreeCloseCursor(BtCursor *pCur){
|
|
Btree *pBtree = pCur->pBtree;
|
|
if( pBtree ){
|
|
BtShared *pBt = pCur->pBt;
|
|
sqlite3BtreeEnter(pBtree);
|
|
assert( pBt->pCursor!=0 );
|
|
if( pBt->pCursor==pCur ){
|
|
pBt->pCursor = pCur->pNext;
|
|
}else{
|
|
BtCursor *pPrev = pBt->pCursor;
|
|
do{
|
|
if( pPrev->pNext==pCur ){
|
|
pPrev->pNext = pCur->pNext;
|
|
break;
|
|
}
|
|
pPrev = pPrev->pNext;
|
|
}while( (pPrev) );
|
|
}
|
|
btreeReleaseAllCursorPages(pCur);
|
|
unlockBtreeIfUnused(pBt);
|
|
sqlite3_free(pCur->aOverflow);
|
|
sqlite3_free(pCur->pKey);
|
|
sqlite3BtreeLeave(pBtree);
|
|
pCur->pBtree = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
# 4506 "src/btree.c"
|
|
static void getCellInfo(BtCursor *pCur){
|
|
if( pCur->info.nSize==0 ){
|
|
pCur->curFlags |= 0x02;
|
|
btreeParseCell(pCur->pPage,pCur->ix,&pCur->info);
|
|
}else{
|
|
;
|
|
}
|
|
}
|
|
# 4525 "src/btree.c"
|
|
int sqlite3BtreeCursorIsValidNN(BtCursor *pCur){
|
|
assert( pCur!=0 );
|
|
return pCur->eState==0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
i64 sqlite3BtreeIntegerKey(BtCursor *pCur){
|
|
assert( cursorHoldsMutex(pCur) );
|
|
assert( pCur->eState==0 );
|
|
assert( pCur->curIntKey );
|
|
getCellInfo(pCur);
|
|
return pCur->info.nKey;
|
|
}
|
|
# 4567 "src/btree.c"
|
|
u32 sqlite3BtreePayloadSize(BtCursor *pCur){
|
|
assert( cursorHoldsMutex(pCur) );
|
|
assert( pCur->eState==0 );
|
|
getCellInfo(pCur);
|
|
return pCur->info.nPayload;
|
|
}
|
|
# 4587 "src/btree.c"
|
|
sqlite3_int64 sqlite3BtreeMaxRecordSize(BtCursor *pCur){
|
|
assert( cursorHoldsMutex(pCur) );
|
|
assert( pCur->eState==0 );
|
|
return pCur->pBt->pageSize * (sqlite3_int64)pCur->pBt->nPage;
|
|
}
|
|
# 4612 "src/btree.c"
|
|
static int getOverflowPage(
|
|
BtShared *pBt,
|
|
Pgno ovfl,
|
|
MemPage **ppPage,
|
|
Pgno *pPgnoNext
|
|
){
|
|
Pgno next = 0;
|
|
MemPage *pPage = 0;
|
|
int rc = 0;
|
|
|
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
|
assert(pPgnoNext);
|
|
# 4632 "src/btree.c"
|
|
if( pBt->autoVacuum ){
|
|
Pgno pgno;
|
|
Pgno iGuess = ovfl+1;
|
|
u8 eType;
|
|
|
|
while( (ptrmapPageno((pBt), (iGuess))==(iGuess)) || iGuess==((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) ){
|
|
iGuess++;
|
|
}
|
|
|
|
if( iGuess<=btreePagecount(pBt) ){
|
|
rc = ptrmapGet(pBt, iGuess, &eType, &pgno);
|
|
if( rc==0 && eType==4 && pgno==ovfl ){
|
|
next = iGuess;
|
|
rc = 101;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
assert( next==0 || rc==101 );
|
|
if( rc==0 ){
|
|
rc = btreeGetPage(pBt, ovfl, &pPage, (ppPage==0) ? 0x02 : 0);
|
|
assert( rc==0 || pPage==0 );
|
|
if( rc==0 ){
|
|
next = sqlite3Get4byte(pPage->aData);
|
|
}
|
|
}
|
|
|
|
*pPgnoNext = next;
|
|
if( ppPage ){
|
|
*ppPage = pPage;
|
|
}else{
|
|
releasePage(pPage);
|
|
}
|
|
return (rc==101 ? 0 : rc);
|
|
}
|
|
# 4680 "src/btree.c"
|
|
static int copyPayload(
|
|
void *pPayload,
|
|
void *pBuf,
|
|
int nByte,
|
|
int eOp,
|
|
DbPage *pDbPage
|
|
){
|
|
if( eOp ){
|
|
|
|
int rc = sqlite3PagerWrite(pDbPage);
|
|
if( rc!=0 ){
|
|
return rc;
|
|
}
|
|
memcpy(pPayload, pBuf, nByte);
|
|
}else{
|
|
|
|
memcpy(pBuf, pPayload, nByte);
|
|
}
|
|
return 0;
|
|
}
|
|
# 4730 "src/btree.c"
|
|
static int accessPayload(
|
|
BtCursor *pCur,
|
|
u32 offset,
|
|
u32 amt,
|
|
unsigned char *pBuf,
|
|
int eOp
|
|
){
|
|
unsigned char *aPayload;
|
|
int rc = 0;
|
|
int iIdx = 0;
|
|
MemPage *pPage = pCur->pPage;
|
|
BtShared *pBt = pCur->pBt;
|
|
|
|
|
|
|
|
|
|
assert( pPage );
|
|
assert( eOp==0 || eOp==1 );
|
|
assert( pCur->eState==0 );
|
|
assert( pCur->ix<pPage->nCell );
|
|
assert( cursorHoldsMutex(pCur) );
|
|
|
|
getCellInfo(pCur);
|
|
aPayload = pCur->info.pPayload;
|
|
assert( offset+amt <= pCur->info.nPayload );
|
|
|
|
assert( aPayload > pPage->aData );
|
|
if( (uptr)(aPayload - pPage->aData) > (pBt->usableSize - pCur->info.nLocal) ){
|
|
|
|
|
|
|
|
|
|
|
|
return sqlite3CorruptError(4763);
|
|
}
|
|
|
|
|
|
if( offset<pCur->info.nLocal ){
|
|
int a = amt;
|
|
if( a+offset>pCur->info.nLocal ){
|
|
a = pCur->info.nLocal - offset;
|
|
}
|
|
rc = copyPayload(&aPayload[offset], pBuf, a, eOp, pPage->pDbPage);
|
|
offset = 0;
|
|
pBuf += a;
|
|
amt -= a;
|
|
}else{
|
|
offset -= pCur->info.nLocal;
|
|
}
|
|
|
|
|
|
if( rc==0 && amt>0 ){
|
|
const u32 ovflSize = pBt->usableSize - 4;
|
|
Pgno nextPage;
|
|
|
|
nextPage = sqlite3Get4byte(&aPayload[pCur->info.nLocal]);
|
|
# 4794 "src/btree.c"
|
|
if( (pCur->curFlags & 0x04)==0 ){
|
|
int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize;
|
|
if( pCur->aOverflow==0
|
|
|| nOvfl*(int)sizeof(Pgno) > sqlite3MallocSize(pCur->aOverflow)
|
|
){
|
|
Pgno *aNew = (Pgno*)sqlite3Realloc(
|
|
pCur->aOverflow, nOvfl*2*sizeof(Pgno)
|
|
);
|
|
if( aNew==0 ){
|
|
return 7;
|
|
}else{
|
|
pCur->aOverflow = aNew;
|
|
}
|
|
}
|
|
memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno));
|
|
pCur->curFlags |= 0x04;
|
|
}else{
|
|
|
|
|
|
|
|
|
|
if( pCur->aOverflow[offset/ovflSize] ){
|
|
iIdx = (offset/ovflSize);
|
|
nextPage = pCur->aOverflow[iIdx];
|
|
offset = (offset%ovflSize);
|
|
}
|
|
}
|
|
|
|
assert( rc==0 && amt>0 );
|
|
while( nextPage ){
|
|
|
|
assert( pCur->aOverflow[iIdx]==0
|
|
|| pCur->aOverflow[iIdx]==nextPage
|
|
|| (sqlite3Config.neverCorrupt==0) );
|
|
pCur->aOverflow[iIdx] = nextPage;
|
|
|
|
if( offset>=ovflSize ){
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert( pCur->curFlags & 0x04 );
|
|
assert( pCur->pBtree->db==pBt->db );
|
|
if( pCur->aOverflow[iIdx+1] ){
|
|
nextPage = pCur->aOverflow[iIdx+1];
|
|
}else{
|
|
rc = getOverflowPage(pBt, nextPage, 0, &nextPage);
|
|
}
|
|
offset -= ovflSize;
|
|
}else{
|
|
|
|
|
|
|
|
int a = amt;
|
|
if( a + offset > ovflSize ){
|
|
a = ovflSize - offset;
|
|
}
|
|
# 4884 "src/btree.c"
|
|
{
|
|
DbPage *pDbPage;
|
|
rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage,
|
|
(eOp==0 ? 0x02 : 0)
|
|
);
|
|
if( rc==0 ){
|
|
aPayload = sqlite3PagerGetData(pDbPage);
|
|
nextPage = sqlite3Get4byte(aPayload);
|
|
rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
|
|
sqlite3PagerUnref(pDbPage);
|
|
offset = 0;
|
|
}
|
|
}
|
|
amt -= a;
|
|
if( amt==0 ) return rc;
|
|
pBuf += a;
|
|
}
|
|
if( rc ) break;
|
|
iIdx++;
|
|
}
|
|
}
|
|
|
|
if( rc==0 && amt>0 ){
|
|
|
|
return sqlite3CorruptError(4908);
|
|
}
|
|
return rc;
|
|
}
|
|
# 4930 "src/btree.c"
|
|
int sqlite3BtreePayload(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
|
|
assert( cursorHoldsMutex(pCur) );
|
|
assert( pCur->eState==0 );
|
|
assert( pCur->iPage>=0 && pCur->pPage );
|
|
assert( pCur->ix<pCur->pPage->nCell );
|
|
return accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int accessPayloadChecked(
|
|
BtCursor *pCur,
|
|
u32 offset,
|
|
u32 amt,
|
|
void *pBuf
|
|
){
|
|
int rc;
|
|
if ( pCur->eState==1 ){
|
|
return 4;
|
|
}
|
|
assert( cursorOwnsBtShared(pCur) );
|
|
rc = btreeRestoreCursorPosition(pCur);
|
|
return rc ? rc : accessPayload(pCur, offset, amt, pBuf, 0);
|
|
}
|
|
int sqlite3BtreePayloadChecked(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
|
|
if( pCur->eState==0 ){
|
|
assert( cursorOwnsBtShared(pCur) );
|
|
return accessPayload(pCur, offset, amt, pBuf, 0);
|
|
}else{
|
|
return accessPayloadChecked(pCur, offset, amt, pBuf);
|
|
}
|
|
}
|
|
# 4987 "src/btree.c"
|
|
static const void *fetchPayload(
|
|
BtCursor *pCur,
|
|
u32 *pAmt
|
|
){
|
|
int amt;
|
|
assert( pCur!=0 && pCur->iPage>=0 && pCur->pPage);
|
|
assert( pCur->eState==0 );
|
|
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
|
|
assert( cursorOwnsBtShared(pCur) );
|
|
assert( pCur->ix<pCur->pPage->nCell );
|
|
assert( pCur->info.nSize>0 );
|
|
assert( pCur->info.pPayload>pCur->pPage->aData || (sqlite3Config.neverCorrupt==0) );
|
|
assert( pCur->info.pPayload<pCur->pPage->aDataEnd ||(sqlite3Config.neverCorrupt==0));
|
|
amt = pCur->info.nLocal;
|
|
if( amt>(int)(pCur->pPage->aDataEnd - pCur->info.pPayload) ){
|
|
|
|
|
|
assert( (sqlite3Config.neverCorrupt==0) );
|
|
amt = ((0)>((int)(pCur->pPage->aDataEnd - pCur->info.pPayload))?(0):((int)(pCur->pPage->aDataEnd - pCur->info.pPayload)));
|
|
}
|
|
*pAmt = (u32)amt;
|
|
return (void*)pCur->info.pPayload;
|
|
}
|
|
# 5026 "src/btree.c"
|
|
const void *sqlite3BtreePayloadFetch(BtCursor *pCur, u32 *pAmt){
|
|
return fetchPayload(pCur, pAmt);
|
|
}
|
|
# 5040 "src/btree.c"
|
|
static int moveToChild(BtCursor *pCur, u32 newPgno){
|
|
BtShared *pBt = pCur->pBt;
|
|
|
|
assert( cursorOwnsBtShared(pCur) );
|
|
assert( pCur->eState==0 );
|
|
assert( pCur->iPage<20 );
|
|
assert( pCur->iPage>=0 );
|
|
if( pCur->iPage>=(20 -1) ){
|
|
return sqlite3CorruptError(5048);
|
|
}
|
|
pCur->info.nSize = 0;
|
|
pCur->curFlags &= ~(0x02|0x04);
|
|
pCur->aiIdx[pCur->iPage] = pCur->ix;
|
|
pCur->apPage[pCur->iPage] = pCur->pPage;
|
|
pCur->ix = 0;
|
|
pCur->iPage++;
|
|
return getAndInitPage(pBt, newPgno, &pCur->pPage, pCur, pCur->curPagerFlags);
|
|
}
|
|
# 5089 "src/btree.c"
|
|
static void moveToParent(BtCursor *pCur){
|
|
MemPage *pLeaf;
|
|
assert( cursorOwnsBtShared(pCur) );
|
|
assert( pCur->eState==0 );
|
|
assert( pCur->iPage>0 );
|
|
assert( pCur->pPage );
|
|
|
|
|
|
|
|
|
|
;
|
|
;
|
|
pCur->info.nSize = 0;
|
|
pCur->curFlags &= ~(0x02|0x04);
|
|
pCur->ix = pCur->aiIdx[pCur->iPage-1];
|
|
pLeaf = pCur->pPage;
|
|
pCur->pPage = pCur->apPage[--pCur->iPage];
|
|
releasePageNotNull(pLeaf);
|
|
}
|
|
# 5130 "src/btree.c"
|
|
static int moveToRoot(BtCursor *pCur){
|
|
MemPage *pRoot;
|
|
int rc = 0;
|
|
|
|
assert( cursorOwnsBtShared(pCur) );
|
|
assert( 1 < 3 );
|
|
assert( 0 < 3 );
|
|
assert( 4 > 3 );
|
|
assert( pCur->eState < 3 || pCur->iPage<0 );
|
|
assert( pCur->pgnoRoot>0 || pCur->iPage<0 );
|
|
|
|
if( pCur->iPage>=0 ){
|
|
if( pCur->iPage ){
|
|
releasePageNotNull(pCur->pPage);
|
|
while( --pCur->iPage ){
|
|
releasePageNotNull(pCur->apPage[pCur->iPage]);
|
|
}
|
|
pCur->pPage = pCur->apPage[0];
|
|
goto skip_init;
|
|
}
|
|
}else if( pCur->pgnoRoot==0 ){
|
|
pCur->eState = 1;
|
|
return 16;
|
|
}else{
|
|
assert( pCur->iPage==(-1) );
|
|
if( pCur->eState>=3 ){
|
|
if( pCur->eState==4 ){
|
|
assert( pCur->skipNext!=0 );
|
|
return pCur->skipNext;
|
|
}
|
|
sqlite3BtreeClearCursor(pCur);
|
|
}
|
|
rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->pPage,
|
|
0, pCur->curPagerFlags);
|
|
if( rc!=0 ){
|
|
pCur->eState = 1;
|
|
return rc;
|
|
}
|
|
pCur->iPage = 0;
|
|
pCur->curIntKey = pCur->pPage->intKey;
|
|
}
|
|
pRoot = pCur->pPage;
|
|
assert( pRoot->pgno==pCur->pgnoRoot );
|
|
# 5184 "src/btree.c"
|
|
assert( pRoot->intKey==1 || pRoot->intKey==0 );
|
|
if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){
|
|
return sqlite3CorruptError(5186);
|
|
}
|
|
|
|
skip_init:
|
|
pCur->ix = 0;
|
|
pCur->info.nSize = 0;
|
|
pCur->curFlags &= ~(0x08|0x02|0x04);
|
|
|
|
pRoot = pCur->pPage;
|
|
if( pRoot->nCell>0 ){
|
|
pCur->eState = 0;
|
|
}else if( !pRoot->leaf ){
|
|
Pgno subpage;
|
|
if( pRoot->pgno!=1 ) return sqlite3CorruptError(5199);
|
|
subpage = sqlite3Get4byte(&pRoot->aData[pRoot->hdrOffset+8]);
|
|
pCur->eState = 0;
|
|
rc = moveToChild(pCur, subpage);
|
|
}else{
|
|
pCur->eState = 1;
|
|
rc = 16;
|
|
}
|
|
return rc;
|
|
}
|
|
# 5217 "src/btree.c"
|
|
static int moveToLeftmost(BtCursor *pCur){
|
|
Pgno pgno;
|
|
int rc = 0;
|
|
MemPage *pPage;
|
|
|
|
assert( cursorOwnsBtShared(pCur) );
|
|
assert( pCur->eState==0 );
|
|
while( rc==0 && !(pPage = pCur->pPage)->leaf ){
|
|
assert( pCur->ix<pPage->nCell );
|
|
pgno = sqlite3Get4byte(((pPage)->aData + ((pPage)->maskPage & __builtin_bswap16(*(u16*)(&(pPage)->aCellIdx[2*(pCur->ix)])))));
|
|
rc = moveToChild(pCur, pgno);
|
|
}
|
|
return rc;
|
|
}
|
|
# 5242 "src/btree.c"
|
|
static int moveToRightmost(BtCursor *pCur){
|
|
Pgno pgno;
|
|
int rc = 0;
|
|
MemPage *pPage = 0;
|
|
|
|
assert( cursorOwnsBtShared(pCur) );
|
|
assert( pCur->eState==0 );
|
|
while( !(pPage = pCur->pPage)->leaf ){
|
|
pgno = sqlite3Get4byte(&pPage->aData[pPage->hdrOffset+8]);
|
|
pCur->ix = pPage->nCell;
|
|
rc = moveToChild(pCur, pgno);
|
|
if( rc ) return rc;
|
|
}
|
|
pCur->ix = pPage->nCell-1;
|
|
assert( pCur->info.nSize==0 );
|
|
assert( (pCur->curFlags & 0x02)==0 );
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
|
|
int rc;
|
|
|
|
assert( cursorOwnsBtShared(pCur) );
|
|
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
|
|
rc = moveToRoot(pCur);
|
|
if( rc==0 ){
|
|
assert( pCur->pPage->nCell>0 );
|
|
*pRes = 0;
|
|
rc = moveToLeftmost(pCur);
|
|
}else if( rc==16 ){
|
|
assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
|
|
*pRes = 1;
|
|
rc = 0;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
|
|
int rc;
|
|
|
|
assert( cursorOwnsBtShared(pCur) );
|
|
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
|
|
|
|
|
|
if( 0==pCur->eState && (pCur->curFlags & 0x08)!=0 ){
|
|
# 5305 "src/btree.c"
|
|
*pRes = 0;
|
|
return 0;
|
|
}
|
|
|
|
rc = moveToRoot(pCur);
|
|
if( rc==0 ){
|
|
assert( pCur->eState==0 );
|
|
*pRes = 0;
|
|
rc = moveToRightmost(pCur);
|
|
if( rc==0 ){
|
|
pCur->curFlags |= 0x08;
|
|
}else{
|
|
pCur->curFlags &= ~0x08;
|
|
}
|
|
}else if( rc==16 ){
|
|
assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
|
|
*pRes = 1;
|
|
rc = 0;
|
|
}
|
|
return rc;
|
|
}
|
|
# 5357 "src/btree.c"
|
|
int sqlite3BtreeMovetoUnpacked(
|
|
BtCursor *pCur,
|
|
UnpackedRecord *pIdxKey,
|
|
i64 intKey,
|
|
int biasRight,
|
|
int *pRes
|
|
){
|
|
int rc;
|
|
RecordCompare xRecordCompare;
|
|
|
|
assert( cursorOwnsBtShared(pCur) );
|
|
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
|
|
assert( pRes );
|
|
assert( (pIdxKey==0)==(pCur->pKeyInfo==0) );
|
|
assert( pCur->eState!=0 || (pIdxKey==0)==(pCur->curIntKey!=0) );
|
|
|
|
|
|
|
|
if( pIdxKey==0
|
|
&& pCur->eState==0 && (pCur->curFlags & 0x02)!=0
|
|
){
|
|
if( pCur->info.nKey==intKey ){
|
|
*pRes = 0;
|
|
return 0;
|
|
}
|
|
if( pCur->info.nKey<intKey ){
|
|
if( (pCur->curFlags & 0x08)!=0 ){
|
|
*pRes = -1;
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
if( pCur->info.nKey+1==intKey ){
|
|
*pRes = 0;
|
|
rc = sqlite3BtreeNext(pCur, 0);
|
|
if( rc==0 ){
|
|
getCellInfo(pCur);
|
|
if( pCur->info.nKey==intKey ){
|
|
return 0;
|
|
}
|
|
}else if( rc==101 ){
|
|
rc = 0;
|
|
}else{
|
|
return rc;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if( pIdxKey ){
|
|
xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
|
|
pIdxKey->errCode = 0;
|
|
assert( pIdxKey->default_rc==1
|
|
|| pIdxKey->default_rc==0
|
|
|| pIdxKey->default_rc==-1
|
|
);
|
|
}else{
|
|
xRecordCompare = 0;
|
|
}
|
|
|
|
rc = moveToRoot(pCur);
|
|
if( rc ){
|
|
if( rc==16 ){
|
|
assert( pCur->pgnoRoot==0 || pCur->pPage->nCell==0 );
|
|
*pRes = -1;
|
|
return 0;
|
|
}
|
|
return rc;
|
|
}
|
|
assert( pCur->pPage );
|
|
assert( pCur->pPage->isInit );
|
|
assert( pCur->eState==0 );
|
|
assert( pCur->pPage->nCell > 0 );
|
|
assert( pCur->iPage==0 || pCur->apPage[0]->intKey==pCur->curIntKey );
|
|
assert( pCur->curIntKey || pIdxKey );
|
|
for(;;){
|
|
int lwr, upr, idx, c;
|
|
Pgno chldPg;
|
|
MemPage *pPage = pCur->pPage;
|
|
u8 *pCell;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert( pPage->nCell>0 );
|
|
assert( pPage->intKey==(pIdxKey==0) );
|
|
lwr = 0;
|
|
upr = pPage->nCell-1;
|
|
assert( biasRight==0 || biasRight==1 );
|
|
idx = upr>>(1-biasRight);
|
|
pCur->ix = (u16)idx;
|
|
if( xRecordCompare==0 ){
|
|
for(;;){
|
|
i64 nCellKey;
|
|
pCell = ((pPage)->aDataOfst + ((pPage)->maskPage & __builtin_bswap16(*(u16*)(&(pPage)->aCellIdx[2*(idx)]))));
|
|
if( pPage->intKeyLeaf ){
|
|
while( 0x80 <= *(pCell++) ){
|
|
if( pCell>=pPage->aDataEnd ){
|
|
return sqlite3CorruptError(5460);
|
|
}
|
|
}
|
|
}
|
|
sqlite3GetVarint(pCell, (u64*)&nCellKey);
|
|
if( nCellKey<intKey ){
|
|
lwr = idx+1;
|
|
if( lwr>upr ){ c = -1; break; }
|
|
}else if( nCellKey>intKey ){
|
|
upr = idx-1;
|
|
if( lwr>upr ){ c = +1; break; }
|
|
}else{
|
|
assert( nCellKey==intKey );
|
|
pCur->ix = (u16)idx;
|
|
if( !pPage->leaf ){
|
|
lwr = idx;
|
|
goto moveto_next_layer;
|
|
}else{
|
|
pCur->curFlags |= 0x02;
|
|
pCur->info.nKey = nCellKey;
|
|
pCur->info.nSize = 0;
|
|
*pRes = 0;
|
|
return 0;
|
|
}
|
|
}
|
|
assert( lwr+upr>=0 );
|
|
idx = (lwr+upr)>>1;
|
|
}
|
|
}else{
|
|
for(;;){
|
|
int nCell;
|
|
pCell = ((pPage)->aDataOfst + ((pPage)->maskPage & __builtin_bswap16(*(u16*)(&(pPage)->aCellIdx[2*(idx)]))));
|
|
# 5501 "src/btree.c"
|
|
nCell = pCell[0];
|
|
if( nCell<=pPage->max1bytePayload ){
|
|
|
|
|
|
|
|
;
|
|
c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
|
|
}else if( !(pCell[1] & 0x80)
|
|
&& (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
|
|
){
|
|
|
|
|
|
;
|
|
c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
|
|
}else{
|
|
# 5525 "src/btree.c"
|
|
void *pCellKey;
|
|
u8 * const pCellBody = pCell - pPage->childPtrSize;
|
|
const int nOverrun = 18;
|
|
pPage->xParseCell(pPage, pCellBody, &pCur->info);
|
|
nCell = (int)pCur->info.nKey;
|
|
;
|
|
;
|
|
;
|
|
;
|
|
if( nCell<2 || nCell/pCur->pBt->usableSize>pCur->pBt->nPage ){
|
|
rc = sqlite3CorruptError(5535);
|
|
goto moveto_finish;
|
|
}
|
|
pCellKey = sqlite3Malloc( nCell+nOverrun );
|
|
if( pCellKey==0 ){
|
|
rc = 7;
|
|
goto moveto_finish;
|
|
}
|
|
pCur->ix = (u16)idx;
|
|
rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
|
|
memset(((u8*)pCellKey)+nCell,0,nOverrun);
|
|
pCur->curFlags &= ~0x04;
|
|
if( rc ){
|
|
sqlite3_free(pCellKey);
|
|
goto moveto_finish;
|
|
}
|
|
c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey);
|
|
sqlite3_free(pCellKey);
|
|
}
|
|
assert(
|
|
(pIdxKey->errCode!=11 || c==0)
|
|
&& (pIdxKey->errCode!=7 || pCur->pBtree->db->mallocFailed)
|
|
);
|
|
if( c<0 ){
|
|
lwr = idx+1;
|
|
}else if( c>0 ){
|
|
upr = idx-1;
|
|
}else{
|
|
assert( c==0 );
|
|
*pRes = 0;
|
|
rc = 0;
|
|
pCur->ix = (u16)idx;
|
|
if( pIdxKey->errCode ) rc = sqlite3CorruptError(5567);
|
|
goto moveto_finish;
|
|
}
|
|
if( lwr>upr ) break;
|
|
assert( lwr+upr>=0 );
|
|
idx = (lwr+upr)>>1;
|
|
}
|
|
}
|
|
assert( lwr==upr+1 || (pPage->intKey && !pPage->leaf) );
|
|
assert( pPage->isInit );
|
|
if( pPage->leaf ){
|
|
assert( pCur->ix<pCur->pPage->nCell );
|
|
pCur->ix = (u16)idx;
|
|
*pRes = c;
|
|
rc = 0;
|
|
goto moveto_finish;
|
|
}
|
|
moveto_next_layer:
|
|
if( lwr>=pPage->nCell ){
|
|
chldPg = sqlite3Get4byte(&pPage->aData[pPage->hdrOffset+8]);
|
|
}else{
|
|
chldPg = sqlite3Get4byte(((pPage)->aData + ((pPage)->maskPage & __builtin_bswap16(*(u16*)(&(pPage)->aCellIdx[2*(lwr)])))));
|
|
}
|
|
pCur->ix = (u16)lwr;
|
|
rc = moveToChild(pCur, chldPg);
|
|
if( rc ) break;
|
|
}
|
|
moveto_finish:
|
|
pCur->info.nSize = 0;
|
|
assert( (pCur->curFlags & 0x04)==0 );
|
|
return rc;
|
|
}
|
|
# 5608 "src/btree.c"
|
|
int sqlite3BtreeEof(BtCursor *pCur){
|
|
|
|
|
|
|
|
|
|
return (0!=pCur->eState);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
i64 sqlite3BtreeRowCountEst(BtCursor *pCur){
|
|
i64 n;
|
|
u8 i;
|
|
|
|
assert( cursorOwnsBtShared(pCur) );
|
|
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
|
|
|
|
|
|
|
|
|
|
if( (pCur->eState!=0) ) return -1;
|
|
if( (pCur->pPage->leaf==0) ) return -1;
|
|
|
|
n = pCur->pPage->nCell;
|
|
for(i=0; i<pCur->iPage; i++){
|
|
n *= pCur->apPage[i]->nCell;
|
|
}
|
|
return n;
|
|
}
|
|
# 5661 "src/btree.c"
|
|
static int btreeNext(BtCursor *pCur){
|
|
int rc;
|
|
int idx;
|
|
MemPage *pPage;
|
|
|
|
assert( cursorOwnsBtShared(pCur) );
|
|
if( pCur->eState!=0 ){
|
|
assert( (pCur->curFlags & 0x04)==0 );
|
|
rc = (pCur->eState>=3 ? btreeRestoreCursorPosition(pCur) : 0);
|
|
if( rc!=0 ){
|
|
return rc;
|
|
}
|
|
if( 1==pCur->eState ){
|
|
return 101;
|
|
}
|
|
if( pCur->eState==2 ){
|
|
pCur->eState = 0;
|
|
if( pCur->skipNext>0 ) return 0;
|
|
}
|
|
}
|
|
|
|
pPage = pCur->pPage;
|
|
idx = ++pCur->ix;
|
|
if( !pPage->isInit ){
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return sqlite3CorruptError(5692);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;
|
|
|
|
if( idx>=pPage->nCell ){
|
|
if( !pPage->leaf ){
|
|
rc = moveToChild(pCur, sqlite3Get4byte(&pPage->aData[pPage->hdrOffset+8]));
|
|
if( rc ) return rc;
|
|
return moveToLeftmost(pCur);
|
|
}
|
|
do{
|
|
if( pCur->iPage==0 ){
|
|
pCur->eState = 1;
|
|
return 101;
|
|
}
|
|
moveToParent(pCur);
|
|
pPage = pCur->pPage;
|
|
}while( pCur->ix>=pPage->nCell );
|
|
if( pPage->intKey ){
|
|
return sqlite3BtreeNext(pCur, 0);
|
|
}else{
|
|
return 0;
|
|
}
|
|
}
|
|
if( pPage->leaf ){
|
|
return 0;
|
|
}else{
|
|
return moveToLeftmost(pCur);
|
|
}
|
|
}
|
|
int sqlite3BtreeNext(BtCursor *pCur, int flags){
|
|
MemPage *pPage;
|
|
(void)(flags);
|
|
assert( cursorOwnsBtShared(pCur) );
|
|
assert( flags==0 || flags==1 );
|
|
pCur->info.nSize = 0;
|
|
pCur->curFlags &= ~(0x02|0x04);
|
|
if( pCur->eState!=0 ) return btreeNext(pCur);
|
|
pPage = pCur->pPage;
|
|
if( (++pCur->ix)>=pPage->nCell ){
|
|
pCur->ix--;
|
|
return btreeNext(pCur);
|
|
}
|
|
if( pPage->leaf ){
|
|
return 0;
|
|
}else{
|
|
return moveToLeftmost(pCur);
|
|
}
|
|
}
|
|
# 5768 "src/btree.c"
|
|
static int btreePrevious(BtCursor *pCur){
|
|
int rc;
|
|
MemPage *pPage;
|
|
|
|
assert( cursorOwnsBtShared(pCur) );
|
|
assert( (pCur->curFlags & (0x08|0x04|0x02))==0 );
|
|
assert( pCur->info.nSize==0 );
|
|
if( pCur->eState!=0 ){
|
|
rc = (pCur->eState>=3 ? btreeRestoreCursorPosition(pCur) : 0);
|
|
if( rc!=0 ){
|
|
return rc;
|
|
}
|
|
if( 1==pCur->eState ){
|
|
return 101;
|
|
}
|
|
if( 2==pCur->eState ){
|
|
pCur->eState = 0;
|
|
if( pCur->skipNext<0 ) return 0;
|
|
}
|
|
}
|
|
|
|
pPage = pCur->pPage;
|
|
assert( pPage->isInit );
|
|
if( !pPage->leaf ){
|
|
int idx = pCur->ix;
|
|
rc = moveToChild(pCur, sqlite3Get4byte(((pPage)->aData + ((pPage)->maskPage & __builtin_bswap16(*(u16*)(&(pPage)->aCellIdx[2*(idx)]))))));
|
|
if( rc ) return rc;
|
|
rc = moveToRightmost(pCur);
|
|
}else{
|
|
while( pCur->ix==0 ){
|
|
if( pCur->iPage==0 ){
|
|
pCur->eState = 1;
|
|
return 101;
|
|
}
|
|
moveToParent(pCur);
|
|
}
|
|
assert( pCur->info.nSize==0 );
|
|
assert( (pCur->curFlags & (0x04))==0 );
|
|
|
|
pCur->ix--;
|
|
pPage = pCur->pPage;
|
|
if( pPage->intKey && !pPage->leaf ){
|
|
rc = sqlite3BtreePrevious(pCur, 0);
|
|
}else{
|
|
rc = 0;
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
int sqlite3BtreePrevious(BtCursor *pCur, int flags){
|
|
assert( cursorOwnsBtShared(pCur) );
|
|
assert( flags==0 || flags==1 );
|
|
(void)(flags);
|
|
pCur->curFlags &= ~(0x08|0x04|0x02);
|
|
pCur->info.nSize = 0;
|
|
if( pCur->eState!=0
|
|
|| pCur->ix==0
|
|
|| pCur->pPage->leaf==0
|
|
){
|
|
return btreePrevious(pCur);
|
|
}
|
|
pCur->ix--;
|
|
return 0;
|
|
}
|
|
# 5855 "src/btree.c"
|
|
static int allocateBtreePage(
|
|
BtShared *pBt,
|
|
MemPage **ppPage,
|
|
Pgno *pPgno,
|
|
Pgno nearby,
|
|
u8 eMode
|
|
){
|
|
MemPage *pPage1;
|
|
int rc;
|
|
u32 n;
|
|
u32 k;
|
|
MemPage *pTrunk = 0;
|
|
MemPage *pPrevTrunk = 0;
|
|
Pgno mxPage;
|
|
|
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
|
assert( eMode==0 || (nearby>0 && (pBt->autoVacuum)) );
|
|
pPage1 = pBt->pPage1;
|
|
mxPage = btreePagecount(pBt);
|
|
|
|
|
|
n = sqlite3Get4byte(&pPage1->aData[36]);
|
|
;
|
|
if( n>=mxPage ){
|
|
return sqlite3CorruptError(5879);
|
|
}
|
|
if( n>0 ){
|
|
|
|
Pgno iTrunk;
|
|
u8 searchList = 0;
|
|
u32 nSearch = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( eMode==1 ){
|
|
if( nearby<=mxPage ){
|
|
u8 eType;
|
|
assert( nearby>0 );
|
|
assert( pBt->autoVacuum );
|
|
rc = ptrmapGet(pBt, nearby, &eType, 0);
|
|
if( rc ) return rc;
|
|
if( eType==2 ){
|
|
searchList = 1;
|
|
}
|
|
}
|
|
}else if( eMode==2 ){
|
|
searchList = 1;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
rc = sqlite3PagerWrite(pPage1->pDbPage);
|
|
if( rc ) return rc;
|
|
sqlite3Put4byte(&pPage1->aData[36], n-1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
do {
|
|
pPrevTrunk = pTrunk;
|
|
if( pPrevTrunk ){
|
|
|
|
|
|
|
|
iTrunk = sqlite3Get4byte(&pPrevTrunk->aData[0]);
|
|
}else{
|
|
|
|
|
|
|
|
iTrunk = sqlite3Get4byte(&pPage1->aData[32]);
|
|
}
|
|
;
|
|
if( iTrunk>mxPage || nSearch++ > n ){
|
|
rc = sqlite3CorruptError(5935);
|
|
}else{
|
|
rc = btreeGetUnusedPage(pBt, iTrunk, &pTrunk, 0);
|
|
}
|
|
if( rc ){
|
|
pTrunk = 0;
|
|
goto end_allocate_page;
|
|
}
|
|
assert( pTrunk!=0 );
|
|
assert( pTrunk->aData!=0 );
|
|
|
|
|
|
k = sqlite3Get4byte(&pTrunk->aData[4]);
|
|
if( k==0 && !searchList ){
|
|
|
|
|
|
|
|
assert( pPrevTrunk==0 );
|
|
rc = sqlite3PagerWrite(pTrunk->pDbPage);
|
|
if( rc ){
|
|
goto end_allocate_page;
|
|
}
|
|
*pPgno = iTrunk;
|
|
memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4);
|
|
*ppPage = pTrunk;
|
|
pTrunk = 0;
|
|
;
|
|
}else if( k>(u32)(pBt->usableSize/4 - 2) ){
|
|
|
|
rc = sqlite3CorruptError(5964);
|
|
goto end_allocate_page;
|
|
|
|
}else if( searchList
|
|
&& (nearby==iTrunk || (iTrunk<nearby && eMode==2))
|
|
){
|
|
|
|
|
|
|
|
*pPgno = iTrunk;
|
|
*ppPage = pTrunk;
|
|
searchList = 0;
|
|
rc = sqlite3PagerWrite(pTrunk->pDbPage);
|
|
if( rc ){
|
|
goto end_allocate_page;
|
|
}
|
|
if( k==0 ){
|
|
if( !pPrevTrunk ){
|
|
memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4);
|
|
}else{
|
|
rc = sqlite3PagerWrite(pPrevTrunk->pDbPage);
|
|
if( rc!=0 ){
|
|
goto end_allocate_page;
|
|
}
|
|
memcpy(&pPrevTrunk->aData[0], &pTrunk->aData[0], 4);
|
|
}
|
|
}else{
|
|
|
|
|
|
|
|
|
|
MemPage *pNewTrunk;
|
|
Pgno iNewTrunk = sqlite3Get4byte(&pTrunk->aData[8]);
|
|
if( iNewTrunk>mxPage ){
|
|
rc = sqlite3CorruptError(5998);
|
|
goto end_allocate_page;
|
|
}
|
|
;
|
|
rc = btreeGetUnusedPage(pBt, iNewTrunk, &pNewTrunk, 0);
|
|
if( rc!=0 ){
|
|
goto end_allocate_page;
|
|
}
|
|
rc = sqlite3PagerWrite(pNewTrunk->pDbPage);
|
|
if( rc!=0 ){
|
|
releasePage(pNewTrunk);
|
|
goto end_allocate_page;
|
|
}
|
|
memcpy(&pNewTrunk->aData[0], &pTrunk->aData[0], 4);
|
|
sqlite3Put4byte(&pNewTrunk->aData[4], k-1);
|
|
memcpy(&pNewTrunk->aData[8], &pTrunk->aData[12], (k-1)*4);
|
|
releasePage(pNewTrunk);
|
|
if( !pPrevTrunk ){
|
|
assert( sqlite3PagerIswriteable(pPage1->pDbPage) );
|
|
sqlite3Put4byte(&pPage1->aData[32], iNewTrunk);
|
|
}else{
|
|
rc = sqlite3PagerWrite(pPrevTrunk->pDbPage);
|
|
if( rc ){
|
|
goto end_allocate_page;
|
|
}
|
|
sqlite3Put4byte(&pPrevTrunk->aData[0], iNewTrunk);
|
|
}
|
|
}
|
|
pTrunk = 0;
|
|
;
|
|
|
|
}else if( k>0 ){
|
|
|
|
u32 closest;
|
|
Pgno iPage;
|
|
unsigned char *aData = pTrunk->aData;
|
|
if( nearby>0 ){
|
|
u32 i;
|
|
closest = 0;
|
|
if( eMode==2 ){
|
|
for(i=0; i<k; i++){
|
|
iPage = sqlite3Get4byte(&aData[8+i*4]);
|
|
if( iPage<=nearby ){
|
|
closest = i;
|
|
break;
|
|
}
|
|
}
|
|
}else{
|
|
int dist;
|
|
dist = sqlite3AbsInt32(sqlite3Get4byte(&aData[8]) - nearby);
|
|
for(i=1; i<k; i++){
|
|
int d2 = sqlite3AbsInt32(sqlite3Get4byte(&aData[8+i*4]) - nearby);
|
|
if( d2<dist ){
|
|
closest = i;
|
|
dist = d2;
|
|
}
|
|
}
|
|
}
|
|
}else{
|
|
closest = 0;
|
|
}
|
|
|
|
iPage = sqlite3Get4byte(&aData[8+closest*4]);
|
|
;
|
|
if( iPage>mxPage ){
|
|
rc = sqlite3CorruptError(6063);
|
|
goto end_allocate_page;
|
|
}
|
|
;
|
|
if( !searchList
|
|
|| (iPage==nearby || (iPage<nearby && eMode==2))
|
|
){
|
|
int noContent;
|
|
*pPgno = iPage;
|
|
|
|
|
|
;
|
|
rc = sqlite3PagerWrite(pTrunk->pDbPage);
|
|
if( rc ) goto end_allocate_page;
|
|
if( closest<k-1 ){
|
|
memcpy(&aData[8+closest*4], &aData[4+k*4], 4);
|
|
}
|
|
sqlite3Put4byte(&aData[4], k-1);
|
|
noContent = !btreeGetHasContent(pBt, *pPgno)? 0x01 : 0;
|
|
rc = btreeGetUnusedPage(pBt, *pPgno, ppPage, noContent);
|
|
if( rc==0 ){
|
|
rc = sqlite3PagerWrite((*ppPage)->pDbPage);
|
|
if( rc!=0 ){
|
|
releasePage(*ppPage);
|
|
*ppPage = 0;
|
|
}
|
|
}
|
|
searchList = 0;
|
|
}
|
|
}
|
|
releasePage(pPrevTrunk);
|
|
pPrevTrunk = 0;
|
|
}while( searchList );
|
|
}else{
|
|
# 6115 "src/btree.c"
|
|
int bNoContent = (0==(pBt->bDoTruncate))? 0x01:0;
|
|
|
|
rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
|
|
if( rc ) return rc;
|
|
pBt->nPage++;
|
|
if( pBt->nPage==((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) ) pBt->nPage++;
|
|
|
|
|
|
if( pBt->autoVacuum && (ptrmapPageno((pBt), (pBt->nPage))==(pBt->nPage)) ){
|
|
|
|
|
|
|
|
|
|
MemPage *pPg = 0;
|
|
;
|
|
assert( pBt->nPage!=((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) );
|
|
rc = btreeGetUnusedPage(pBt, pBt->nPage, &pPg, bNoContent);
|
|
if( rc==0 ){
|
|
rc = sqlite3PagerWrite(pPg->pDbPage);
|
|
releasePage(pPg);
|
|
}
|
|
if( rc ) return rc;
|
|
pBt->nPage++;
|
|
if( pBt->nPage==((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) ){ pBt->nPage++; }
|
|
}
|
|
|
|
sqlite3Put4byte(28 + (u8*)pBt->pPage1->aData, pBt->nPage);
|
|
*pPgno = pBt->nPage;
|
|
|
|
assert( *pPgno!=((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) );
|
|
rc = btreeGetUnusedPage(pBt, *pPgno, ppPage, bNoContent);
|
|
if( rc ) return rc;
|
|
rc = sqlite3PagerWrite((*ppPage)->pDbPage);
|
|
if( rc!=0 ){
|
|
releasePage(*ppPage);
|
|
*ppPage = 0;
|
|
}
|
|
;
|
|
}
|
|
|
|
assert( (sqlite3Config.neverCorrupt==0) || *pPgno!=((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) );
|
|
|
|
end_allocate_page:
|
|
releasePage(pTrunk);
|
|
releasePage(pPrevTrunk);
|
|
assert( rc!=0 || sqlite3PagerPageRefcount((*ppPage)->pDbPage)<=1 );
|
|
assert( rc!=0 || (*ppPage)->isInit==0 );
|
|
return rc;
|
|
}
|
|
# 6177 "src/btree.c"
|
|
static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
|
|
MemPage *pTrunk = 0;
|
|
Pgno iTrunk = 0;
|
|
MemPage *pPage1 = pBt->pPage1;
|
|
MemPage *pPage;
|
|
int rc;
|
|
u32 nFree;
|
|
|
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
|
assert( (sqlite3Config.neverCorrupt==0) || iPage>1 );
|
|
assert( !pMemPage || pMemPage->pgno==iPage );
|
|
|
|
if( iPage<2 || iPage>pBt->nPage ){
|
|
return sqlite3CorruptError(6190);
|
|
}
|
|
if( pMemPage ){
|
|
pPage = pMemPage;
|
|
sqlite3PagerRef(pPage->pDbPage);
|
|
}else{
|
|
pPage = btreePageLookup(pBt, iPage);
|
|
}
|
|
|
|
|
|
rc = sqlite3PagerWrite(pPage1->pDbPage);
|
|
if( rc ) goto freepage_out;
|
|
nFree = sqlite3Get4byte(&pPage1->aData[36]);
|
|
sqlite3Put4byte(&pPage1->aData[36], nFree+1);
|
|
|
|
if( pBt->btsFlags & 0x0004 ){
|
|
|
|
|
|
|
|
if( (!pPage && ((rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0) )
|
|
|| ((rc = sqlite3PagerWrite(pPage->pDbPage))!=0)
|
|
){
|
|
goto freepage_out;
|
|
}
|
|
memset(pPage->aData, 0, pPage->pBt->pageSize);
|
|
}
|
|
|
|
|
|
|
|
|
|
if( (pBt->autoVacuum) ){
|
|
ptrmapPut(pBt, iPage, 2, 0, &rc);
|
|
if( rc ) goto freepage_out;
|
|
}
|
|
# 6232 "src/btree.c"
|
|
if( nFree!=0 ){
|
|
u32 nLeaf;
|
|
|
|
iTrunk = sqlite3Get4byte(&pPage1->aData[32]);
|
|
rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0);
|
|
if( rc!=0 ){
|
|
goto freepage_out;
|
|
}
|
|
|
|
nLeaf = sqlite3Get4byte(&pTrunk->aData[4]);
|
|
assert( pBt->usableSize>32 );
|
|
if( nLeaf > (u32)pBt->usableSize/4 - 2 ){
|
|
rc = sqlite3CorruptError(6244);
|
|
goto freepage_out;
|
|
}
|
|
if( nLeaf < (u32)pBt->usableSize/4 - 8 ){
|
|
# 6267 "src/btree.c"
|
|
rc = sqlite3PagerWrite(pTrunk->pDbPage);
|
|
if( rc==0 ){
|
|
sqlite3Put4byte(&pTrunk->aData[4], nLeaf+1);
|
|
sqlite3Put4byte(&pTrunk->aData[8+nLeaf*4], iPage);
|
|
if( pPage && (pBt->btsFlags & 0x0004)==0 ){
|
|
sqlite3PagerDontWrite(pPage->pDbPage);
|
|
}
|
|
rc = btreeSetHasContent(pBt, iPage);
|
|
}
|
|
;
|
|
goto freepage_out;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( pPage==0 && 0!=(rc = btreeGetPage(pBt, iPage, &pPage, 0)) ){
|
|
goto freepage_out;
|
|
}
|
|
rc = sqlite3PagerWrite(pPage->pDbPage);
|
|
if( rc!=0 ){
|
|
goto freepage_out;
|
|
}
|
|
sqlite3Put4byte(pPage->aData, iTrunk);
|
|
sqlite3Put4byte(&pPage->aData[4], 0);
|
|
sqlite3Put4byte(&pPage1->aData[32], iPage);
|
|
;
|
|
|
|
freepage_out:
|
|
if( pPage ){
|
|
pPage->isInit = 0;
|
|
}
|
|
releasePage(pPage);
|
|
releasePage(pTrunk);
|
|
return rc;
|
|
}
|
|
static void freePage(MemPage *pPage, int *pRC){
|
|
if( (*pRC)==0 ){
|
|
*pRC = freePage2(pPage->pBt, pPage, pPage->pgno);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int clearCell(
|
|
MemPage *pPage,
|
|
unsigned char *pCell,
|
|
CellInfo *pInfo
|
|
){
|
|
BtShared *pBt;
|
|
Pgno ovflPgno;
|
|
int rc;
|
|
int nOvfl;
|
|
u32 ovflPageSize;
|
|
|
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
|
pPage->xParseCell(pPage, pCell, pInfo);
|
|
if( pInfo->nLocal==pInfo->nPayload ){
|
|
return 0;
|
|
}
|
|
;
|
|
;
|
|
if( pCell + pInfo->nSize > pPage->aDataEnd ){
|
|
|
|
return sqlite3CorruptError(6337);
|
|
}
|
|
ovflPgno = sqlite3Get4byte(pCell + pInfo->nSize - 4);
|
|
pBt = pPage->pBt;
|
|
assert( pBt->usableSize > 4 );
|
|
ovflPageSize = pBt->usableSize - 4;
|
|
nOvfl = (pInfo->nPayload - pInfo->nLocal + ovflPageSize - 1)/ovflPageSize;
|
|
assert( nOvfl>0 ||
|
|
((sqlite3Config.neverCorrupt==0) && (pInfo->nPayload + ovflPageSize)<ovflPageSize)
|
|
);
|
|
while( nOvfl-- ){
|
|
Pgno iNext = 0;
|
|
MemPage *pOvfl = 0;
|
|
if( ovflPgno<2 || ovflPgno>btreePagecount(pBt) ){
|
|
|
|
|
|
|
|
return sqlite3CorruptError(6354);
|
|
}
|
|
if( nOvfl ){
|
|
rc = getOverflowPage(pBt, ovflPgno, &pOvfl, &iNext);
|
|
if( rc ) return rc;
|
|
}
|
|
|
|
if( ( pOvfl || ((pOvfl = btreePageLookup(pBt, ovflPgno))!=0) )
|
|
&& sqlite3PagerPageRefcount(pOvfl->pDbPage)!=1
|
|
){
|
|
# 6374 "src/btree.c"
|
|
rc = sqlite3CorruptError(6374);
|
|
}else{
|
|
rc = freePage2(pBt, pOvfl, ovflPgno);
|
|
}
|
|
|
|
if( pOvfl ){
|
|
sqlite3PagerUnref(pOvfl->pDbPage);
|
|
}
|
|
if( rc ) return rc;
|
|
ovflPgno = iNext;
|
|
}
|
|
return 0;
|
|
}
|
|
# 6400 "src/btree.c"
|
|
static int fillInCell(
|
|
MemPage *pPage,
|
|
unsigned char *pCell,
|
|
const BtreePayload *pX,
|
|
int *pnSize
|
|
){
|
|
int nPayload;
|
|
const u8 *pSrc;
|
|
int nSrc, n, rc, mn;
|
|
int spaceLeft;
|
|
MemPage *pToRelease;
|
|
unsigned char *pPrior;
|
|
unsigned char *pPayload;
|
|
BtShared *pBt;
|
|
Pgno pgnoOvfl;
|
|
int nHeader;
|
|
|
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
|
|
|
|
|
|
|
assert( pCell<pPage->aData || pCell>=&pPage->aData[pPage->pBt->pageSize]
|
|
|| sqlite3PagerIswriteable(pPage->pDbPage) );
|
|
|
|
|
|
nHeader = pPage->childPtrSize;
|
|
if( pPage->intKey ){
|
|
nPayload = pX->nData + pX->nZero;
|
|
pSrc = pX->pData;
|
|
nSrc = pX->nData;
|
|
assert( pPage->intKeyLeaf );
|
|
nHeader += (u8)(((u32)(nPayload)<(u32)0x80)?(*(&pCell[nHeader])=(unsigned char)(nPayload)),1: sqlite3PutVarint((&pCell[nHeader]),(nPayload)));
|
|
nHeader += sqlite3PutVarint(&pCell[nHeader], *(u64*)&pX->nKey);
|
|
}else{
|
|
assert( pX->nKey<=0x7fffffff && pX->pKey!=0 );
|
|
nSrc = nPayload = (int)pX->nKey;
|
|
pSrc = pX->pKey;
|
|
nHeader += (u8)(((u32)(nPayload)<(u32)0x80)?(*(&pCell[nHeader])=(unsigned char)(nPayload)),1: sqlite3PutVarint((&pCell[nHeader]),(nPayload)));
|
|
}
|
|
|
|
|
|
pPayload = &pCell[nHeader];
|
|
if( nPayload<=pPage->maxLocal ){
|
|
|
|
|
|
n = nHeader + nPayload;
|
|
;
|
|
;
|
|
if( n<4 ) n = 4;
|
|
*pnSize = n;
|
|
assert( nSrc<=nPayload );
|
|
;
|
|
memcpy(pPayload, pSrc, nSrc);
|
|
memset(pPayload+nSrc, 0, nPayload-nSrc);
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
mn = pPage->minLocal;
|
|
n = mn + (nPayload - mn) % (pPage->pBt->usableSize - 4);
|
|
;
|
|
;
|
|
if( n > pPage->maxLocal ) n = mn;
|
|
spaceLeft = n;
|
|
*pnSize = n + nHeader + 4;
|
|
pPrior = &pCell[nHeader+n];
|
|
pToRelease = 0;
|
|
pgnoOvfl = 0;
|
|
pBt = pPage->pBt;
|
|
# 6496 "src/btree.c"
|
|
while( 1 ){
|
|
n = nPayload;
|
|
if( n>spaceLeft ) n = spaceLeft;
|
|
|
|
|
|
|
|
assert( pToRelease==0 || sqlite3PagerIswriteable(pToRelease->pDbPage) );
|
|
|
|
|
|
|
|
assert( pPayload<pPage->aData || pPayload>=&pPage->aData[pBt->pageSize]
|
|
|| sqlite3PagerIswriteable(pPage->pDbPage) );
|
|
|
|
if( nSrc>=n ){
|
|
memcpy(pPayload, pSrc, n);
|
|
}else if( nSrc>0 ){
|
|
n = nSrc;
|
|
memcpy(pPayload, pSrc, n);
|
|
}else{
|
|
memset(pPayload, 0, n);
|
|
}
|
|
nPayload -= n;
|
|
if( nPayload<=0 ) break;
|
|
pPayload += n;
|
|
pSrc += n;
|
|
nSrc -= n;
|
|
spaceLeft -= n;
|
|
if( spaceLeft==0 ){
|
|
MemPage *pOvfl = 0;
|
|
|
|
Pgno pgnoPtrmap = pgnoOvfl;
|
|
if( pBt->autoVacuum ){
|
|
do{
|
|
pgnoOvfl++;
|
|
} while(
|
|
(ptrmapPageno((pBt), (pgnoOvfl))==(pgnoOvfl)) || pgnoOvfl==((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1))
|
|
);
|
|
}
|
|
|
|
rc = allocateBtreePage(pBt, &pOvfl, &pgnoOvfl, pgnoOvfl, 0);
|
|
# 6547 "src/btree.c"
|
|
if( pBt->autoVacuum && rc==0 ){
|
|
u8 eType = (pgnoPtrmap?4:3);
|
|
ptrmapPut(pBt, pgnoOvfl, eType, pgnoPtrmap, &rc);
|
|
if( rc ){
|
|
releasePage(pOvfl);
|
|
}
|
|
}
|
|
|
|
if( rc ){
|
|
releasePage(pToRelease);
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
assert( pToRelease==0 || sqlite3PagerIswriteable(pToRelease->pDbPage) );
|
|
|
|
|
|
|
|
assert( pPrior<pPage->aData || pPrior>=&pPage->aData[pBt->pageSize]
|
|
|| sqlite3PagerIswriteable(pPage->pDbPage) );
|
|
|
|
sqlite3Put4byte(pPrior, pgnoOvfl);
|
|
releasePage(pToRelease);
|
|
pToRelease = pOvfl;
|
|
pPrior = pOvfl->aData;
|
|
sqlite3Put4byte(pPrior, 0);
|
|
pPayload = &pOvfl->aData[4];
|
|
spaceLeft = pBt->usableSize - 4;
|
|
}
|
|
}
|
|
releasePage(pToRelease);
|
|
return 0;
|
|
}
|
|
# 6590 "src/btree.c"
|
|
static void dropCell(MemPage *pPage, int idx, int sz, int *pRC){
|
|
u32 pc;
|
|
u8 *data;
|
|
u8 *ptr;
|
|
int rc;
|
|
int hdr;
|
|
|
|
if( *pRC ) return;
|
|
assert( idx>=0 && idx<pPage->nCell );
|
|
assert( (sqlite3Config.neverCorrupt==0) || sz==cellSize(pPage, idx) );
|
|
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
|
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
|
assert( pPage->nFree>=0 );
|
|
data = pPage->aData;
|
|
ptr = &pPage->aCellIdx[2*idx];
|
|
pc = ((ptr)[0]<<8 | (ptr)[1]);
|
|
hdr = pPage->hdrOffset;
|
|
;
|
|
;
|
|
if( pc+sz > pPage->pBt->usableSize ){
|
|
*pRC = sqlite3CorruptError(6610);
|
|
return;
|
|
}
|
|
rc = freeSpace(pPage, pc, sz);
|
|
if( rc ){
|
|
*pRC = rc;
|
|
return;
|
|
}
|
|
pPage->nCell--;
|
|
if( pPage->nCell==0 ){
|
|
memset(&data[hdr+1], 0, 4);
|
|
data[hdr+7] = 0;
|
|
((&data[hdr+5])[0] = (u8)((pPage->pBt->usableSize)>>8), (&data[hdr+5])[1] = (u8)(pPage->pBt->usableSize));
|
|
pPage->nFree = pPage->pBt->usableSize - pPage->hdrOffset
|
|
- pPage->childPtrSize - 8;
|
|
}else{
|
|
memmove(ptr, ptr+2, 2*(pPage->nCell - idx));
|
|
((&data[hdr+3])[0] = (u8)((pPage->nCell)>>8), (&data[hdr+3])[1] = (u8)(pPage->nCell));
|
|
pPage->nFree += 2;
|
|
}
|
|
}
|
|
# 6646 "src/btree.c"
|
|
static void insertCell(
|
|
MemPage *pPage,
|
|
int i,
|
|
u8 *pCell,
|
|
int sz,
|
|
u8 *pTemp,
|
|
Pgno iChild,
|
|
int *pRC
|
|
){
|
|
int idx = 0;
|
|
int j;
|
|
u8 *data;
|
|
u8 *pIns;
|
|
|
|
assert( *pRC==0 );
|
|
assert( i>=0 && i<=pPage->nCell+pPage->nOverflow );
|
|
assert( ((pPage->pBt->pageSize-8)/6)<=10921 );
|
|
assert( pPage->nCell<=((pPage->pBt->pageSize-8)/6) || (sqlite3Config.neverCorrupt==0) );
|
|
assert( pPage->nOverflow<=((int)(sizeof(pPage->apOvfl)/sizeof(pPage->apOvfl[0]))) );
|
|
assert( ((int)(sizeof(pPage->apOvfl)/sizeof(pPage->apOvfl[0])))==((int)(sizeof(pPage->aiOvfl)/sizeof(pPage->aiOvfl[0]))) );
|
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
|
|
|
|
|
|
|
|
|
|
|
assert( sz==pPage->xCellSize(pPage, pCell) || (sz==8 && iChild>0) );
|
|
assert( pPage->nFree>=0 );
|
|
if( pPage->nOverflow || sz+2>pPage->nFree ){
|
|
if( pTemp ){
|
|
memcpy(pTemp, pCell, sz);
|
|
pCell = pTemp;
|
|
}
|
|
if( iChild ){
|
|
sqlite3Put4byte(pCell, iChild);
|
|
}
|
|
j = pPage->nOverflow++;
|
|
|
|
|
|
|
|
assert( j < ((int)(sizeof(pPage->apOvfl)/sizeof(pPage->apOvfl[0])))-1 );
|
|
pPage->apOvfl[j] = pCell;
|
|
pPage->aiOvfl[j] = (u16)i;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert( j==0 || pPage->aiOvfl[j-1]<(u16)i );
|
|
assert( j==0 || i==pPage->aiOvfl[j-1]+1 );
|
|
}else{
|
|
int rc = sqlite3PagerWrite(pPage->pDbPage);
|
|
if( rc!=0 ){
|
|
*pRC = rc;
|
|
return;
|
|
}
|
|
assert( sqlite3PagerIswriteable(pPage->pDbPage) );
|
|
data = pPage->aData;
|
|
assert( &data[pPage->cellOffset]==pPage->aCellIdx );
|
|
rc = allocateSpace(pPage, sz, &idx);
|
|
if( rc ){ *pRC = rc; return; }
|
|
|
|
|
|
assert( idx >= 0 );
|
|
assert( idx >= pPage->cellOffset+2*pPage->nCell+2 || (sqlite3Config.neverCorrupt==0) );
|
|
assert( idx+sz <= (int)pPage->pBt->usableSize );
|
|
pPage->nFree -= (u16)(2 + sz);
|
|
if( iChild ){
|
|
|
|
|
|
|
|
|
|
|
|
memcpy(&data[idx+4], pCell+4, sz-4);
|
|
sqlite3Put4byte(&data[idx], iChild);
|
|
}else{
|
|
memcpy(&data[idx], pCell, sz);
|
|
}
|
|
pIns = pPage->aCellIdx + i*2;
|
|
memmove(pIns+2, pIns, 2*(pPage->nCell - i));
|
|
((pIns)[0] = (u8)((idx)>>8), (pIns)[1] = (u8)(idx));
|
|
pPage->nCell++;
|
|
|
|
if( (++data[pPage->hdrOffset+4])==0 ) data[pPage->hdrOffset+3]++;
|
|
assert( ((&data[pPage->hdrOffset+3])[0]<<8 | (&data[pPage->hdrOffset+3])[1])==pPage->nCell || (sqlite3Config.neverCorrupt==0) );
|
|
|
|
if( pPage->pBt->autoVacuum ){
|
|
|
|
|
|
|
|
ptrmapPutOvflPtr(pPage, pPage, pCell, pRC);
|
|
}
|
|
|
|
}
|
|
}
|
|
# 6826 "src/btree.c"
|
|
typedef struct CellArray CellArray;
|
|
struct CellArray {
|
|
int nCell;
|
|
MemPage *pRef;
|
|
u8 **apCell;
|
|
u16 *szCell;
|
|
u8 *apEnd[3*2];
|
|
int ixNx[3*2];
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static void populateCellCache(CellArray *p, int idx, int N){
|
|
assert( idx>=0 && idx+N<=p->nCell );
|
|
while( N>0 ){
|
|
assert( p->apCell[idx]!=0 );
|
|
if( p->szCell[idx]==0 ){
|
|
p->szCell[idx] = p->pRef->xCellSize(p->pRef, p->apCell[idx]);
|
|
}else{
|
|
assert( (sqlite3Config.neverCorrupt==0) ||
|
|
p->szCell[idx]==p->pRef->xCellSize(p->pRef, p->apCell[idx]) );
|
|
}
|
|
idx++;
|
|
N--;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
static u16 computeCellSize(CellArray *p, int N){
|
|
assert( N>=0 && N<p->nCell );
|
|
assert( p->szCell[N]==0 );
|
|
p->szCell[N] = p->pRef->xCellSize(p->pRef, p->apCell[N]);
|
|
return p->szCell[N];
|
|
}
|
|
static u16 cachedCellSize(CellArray *p, int N){
|
|
assert( N>=0 && N<p->nCell );
|
|
if( p->szCell[N] ) return p->szCell[N];
|
|
return computeCellSize(p, N);
|
|
}
|
|
# 6883 "src/btree.c"
|
|
static int rebuildPage(
|
|
CellArray *pCArray,
|
|
int iFirst,
|
|
int nCell,
|
|
MemPage *pPg
|
|
){
|
|
const int hdr = pPg->hdrOffset;
|
|
u8 * const aData = pPg->aData;
|
|
const int usableSize = pPg->pBt->usableSize;
|
|
u8 * const pEnd = &aData[usableSize];
|
|
int i = iFirst;
|
|
u32 j;
|
|
int iEnd = i+nCell;
|
|
u8 *pCellptr = pPg->aCellIdx;
|
|
u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager);
|
|
u8 *pData;
|
|
int k;
|
|
u8 *pSrcEnd;
|
|
|
|
assert( i<iEnd );
|
|
j = ((&aData[hdr+5])[0]<<8 | (&aData[hdr+5])[1]);
|
|
if( (j>(u32)usableSize) ){ j = 0; }
|
|
memcpy(&pTmp[j], &aData[j], usableSize - j);
|
|
|
|
for(k=0; pCArray->ixNx[k]<=i && (k<3*2); k++){}
|
|
pSrcEnd = pCArray->apEnd[k];
|
|
|
|
pData = pEnd;
|
|
while( 1 ){
|
|
u8 *pCell = pCArray->apCell[i];
|
|
u16 sz = pCArray->szCell[i];
|
|
assert( sz>0 );
|
|
if( (((uptr)(pCell)>=(uptr)(aData))&&((uptr)(pCell)<(uptr)(pEnd))) ){
|
|
if( ((uptr)(pCell+sz))>(uptr)pEnd ) return sqlite3CorruptError(6916);
|
|
pCell = &pTmp[pCell - aData];
|
|
}else if( (uptr)(pCell+sz)>(uptr)pSrcEnd
|
|
&& (uptr)(pCell)<(uptr)pSrcEnd
|
|
){
|
|
return sqlite3CorruptError(6921);
|
|
}
|
|
|
|
pData -= sz;
|
|
((pCellptr)[0] = (u8)(((pData - aData))>>8), (pCellptr)[1] = (u8)((pData - aData)));
|
|
pCellptr += 2;
|
|
if( pData < pCellptr ) return sqlite3CorruptError(6927);
|
|
memcpy(pData, pCell, sz);
|
|
assert( sz==pPg->xCellSize(pPg, pCell) || (sqlite3Config.neverCorrupt==0) );
|
|
;
|
|
i++;
|
|
if( i>=iEnd ) break;
|
|
if( pCArray->ixNx[k]<=i ){
|
|
k++;
|
|
pSrcEnd = pCArray->apEnd[k];
|
|
}
|
|
}
|
|
|
|
|
|
pPg->nCell = nCell;
|
|
pPg->nOverflow = 0;
|
|
|
|
((&aData[hdr+1])[0] = (u8)((0)>>8), (&aData[hdr+1])[1] = (u8)(0));
|
|
((&aData[hdr+3])[0] = (u8)((pPg->nCell)>>8), (&aData[hdr+3])[1] = (u8)(pPg->nCell));
|
|
((&aData[hdr+5])[0] = (u8)((pData - aData)>>8), (&aData[hdr+5])[1] = (u8)(pData - aData));
|
|
aData[hdr+7] = 0x00;
|
|
return 0;
|
|
}
|
|
# 6974 "src/btree.c"
|
|
static int pageInsertArray(
|
|
MemPage *pPg,
|
|
u8 *pBegin,
|
|
u8 **ppData,
|
|
u8 *pCellptr,
|
|
int iFirst,
|
|
int nCell,
|
|
CellArray *pCArray
|
|
){
|
|
int i = iFirst;
|
|
u8 *aData = pPg->aData;
|
|
u8 *pData = *ppData;
|
|
int iEnd = iFirst + nCell;
|
|
int k;
|
|
u8 *pEnd;
|
|
assert( (sqlite3Config.neverCorrupt==0) || pPg->hdrOffset==0 );
|
|
if( iEnd<=iFirst ) return 0;
|
|
for(k=0; pCArray->ixNx[k]<=i && (k<3*2); k++){}
|
|
pEnd = pCArray->apEnd[k];
|
|
while( 1 ){
|
|
int sz, rc;
|
|
u8 *pSlot;
|
|
sz = cachedCellSize(pCArray, i);
|
|
if( (aData[1]==0 && aData[2]==0) || (pSlot = pageFindSlot(pPg,sz,&rc))==0 ){
|
|
if( (pData - pBegin)<sz ) return 1;
|
|
pData -= sz;
|
|
pSlot = pData;
|
|
}
|
|
|
|
|
|
|
|
assert( (pSlot+sz)<=pCArray->apCell[i]
|
|
|| pSlot>=(pCArray->apCell[i]+sz)
|
|
|| (sqlite3Config.neverCorrupt==0) );
|
|
if( (uptr)(pCArray->apCell[i]+sz)>(uptr)pEnd
|
|
&& (uptr)(pCArray->apCell[i])<(uptr)pEnd
|
|
){
|
|
assert( (sqlite3Config.neverCorrupt==0) );
|
|
(void)sqlite3CorruptError(7012);
|
|
return 1;
|
|
}
|
|
memmove(pSlot, pCArray->apCell[i], sz);
|
|
((pCellptr)[0] = (u8)(((pSlot - aData))>>8), (pCellptr)[1] = (u8)((pSlot - aData)));
|
|
pCellptr += 2;
|
|
i++;
|
|
if( i>=iEnd ) break;
|
|
if( pCArray->ixNx[k]<=i ){
|
|
k++;
|
|
pEnd = pCArray->apEnd[k];
|
|
}
|
|
}
|
|
*ppData = pData;
|
|
return 0;
|
|
}
|
|
# 7038 "src/btree.c"
|
|
static int pageFreeArray(
|
|
MemPage *pPg,
|
|
int iFirst,
|
|
int nCell,
|
|
CellArray *pCArray
|
|
){
|
|
u8 * const aData = pPg->aData;
|
|
u8 * const pEnd = &aData[pPg->pBt->usableSize];
|
|
u8 * const pStart = &aData[pPg->hdrOffset + 8 + pPg->childPtrSize];
|
|
int nRet = 0;
|
|
int i;
|
|
int iEnd = iFirst + nCell;
|
|
u8 *pFree = 0;
|
|
int szFree = 0;
|
|
|
|
for(i=iFirst; i<iEnd; i++){
|
|
u8 *pCell = pCArray->apCell[i];
|
|
if( (((uptr)(pCell)>=(uptr)(pStart))&&((uptr)(pCell)<(uptr)(pEnd))) ){
|
|
int sz;
|
|
|
|
|
|
|
|
sz = pCArray->szCell[i]; assert( sz>0 );
|
|
if( pFree!=(pCell + sz) ){
|
|
if( pFree ){
|
|
assert( pFree>aData && (pFree - aData)<65536 );
|
|
freeSpace(pPg, (u16)(pFree - aData), szFree);
|
|
}
|
|
pFree = pCell;
|
|
szFree = sz;
|
|
if( pFree+sz>pEnd ) return 0;
|
|
}else{
|
|
pFree = pCell;
|
|
szFree += sz;
|
|
}
|
|
nRet++;
|
|
}
|
|
}
|
|
if( pFree ){
|
|
assert( pFree>aData && (pFree - aData)<65536 );
|
|
freeSpace(pPg, (u16)(pFree - aData), szFree);
|
|
}
|
|
return nRet;
|
|
}
|
|
# 7095 "src/btree.c"
|
|
static int editPage(
|
|
MemPage *pPg,
|
|
int iOld,
|
|
int iNew,
|
|
int nNew,
|
|
CellArray *pCArray
|
|
){
|
|
u8 * const aData = pPg->aData;
|
|
const int hdr = pPg->hdrOffset;
|
|
u8 *pBegin = &pPg->aCellIdx[nNew * 2];
|
|
int nCell = pPg->nCell;
|
|
u8 *pData;
|
|
u8 *pCellptr;
|
|
int i;
|
|
int iOldEnd = iOld + pPg->nCell + pPg->nOverflow;
|
|
int iNewEnd = iNew + nNew;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert( nCell>=0 );
|
|
if( iOld<iNew ){
|
|
int nShift = pageFreeArray(pPg, iOld, iNew-iOld, pCArray);
|
|
if( nShift>nCell ) return sqlite3CorruptError(7121);
|
|
memmove(pPg->aCellIdx, &pPg->aCellIdx[nShift*2], nCell*2);
|
|
nCell -= nShift;
|
|
}
|
|
if( iNewEnd < iOldEnd ){
|
|
int nTail = pageFreeArray(pPg, iNewEnd, iOldEnd - iNewEnd, pCArray);
|
|
assert( nCell>=nTail );
|
|
nCell -= nTail;
|
|
}
|
|
|
|
pData = &aData[(((((int)((&aData[hdr+5])[0]<<8 | (&aData[hdr+5])[1]))-1)&0xffff)+1)];
|
|
if( pData<pBegin ) goto editpage_fail;
|
|
|
|
|
|
if( iNew<iOld ){
|
|
int nAdd = ((nNew)<(iOld-iNew)?(nNew):(iOld-iNew));
|
|
assert( (iOld-iNew)<nNew || nCell==0 || (sqlite3Config.neverCorrupt==0) );
|
|
assert( nAdd>=0 );
|
|
pCellptr = pPg->aCellIdx;
|
|
memmove(&pCellptr[nAdd*2], pCellptr, nCell*2);
|
|
if( pageInsertArray(
|
|
pPg, pBegin, &pData, pCellptr,
|
|
iNew, nAdd, pCArray
|
|
) ) goto editpage_fail;
|
|
nCell += nAdd;
|
|
}
|
|
|
|
|
|
for(i=0; i<pPg->nOverflow; i++){
|
|
int iCell = (iOld + pPg->aiOvfl[i]) - iNew;
|
|
if( iCell>=0 && iCell<nNew ){
|
|
pCellptr = &pPg->aCellIdx[iCell * 2];
|
|
if( nCell>iCell ){
|
|
memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2);
|
|
}
|
|
nCell++;
|
|
if( pageInsertArray(
|
|
pPg, pBegin, &pData, pCellptr,
|
|
iCell+iNew, 1, pCArray
|
|
) ) goto editpage_fail;
|
|
}
|
|
}
|
|
|
|
|
|
assert( nCell>=0 );
|
|
pCellptr = &pPg->aCellIdx[nCell*2];
|
|
if( pageInsertArray(
|
|
pPg, pBegin, &pData, pCellptr,
|
|
iNew+nCell, nNew-nCell, pCArray
|
|
) ) goto editpage_fail;
|
|
|
|
pPg->nCell = nNew;
|
|
pPg->nOverflow = 0;
|
|
|
|
((&aData[hdr+3])[0] = (u8)((pPg->nCell)>>8), (&aData[hdr+3])[1] = (u8)(pPg->nCell));
|
|
((&aData[hdr+5])[0] = (u8)((pData - aData)>>8), (&aData[hdr+5])[1] = (u8)(pData - aData));
|
|
# 7190 "src/btree.c"
|
|
return 0;
|
|
editpage_fail:
|
|
|
|
populateCellCache(pCArray, iNew, nNew);
|
|
return rebuildPage(pCArray, iNew, nNew, pPg);
|
|
}
|
|
# 7222 "src/btree.c"
|
|
static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
|
|
BtShared *const pBt = pPage->pBt;
|
|
MemPage *pNew;
|
|
int rc;
|
|
Pgno pgnoNew;
|
|
|
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
|
assert( sqlite3PagerIswriteable(pParent->pDbPage) );
|
|
assert( pPage->nOverflow==1 );
|
|
|
|
if( pPage->nCell==0 ) return sqlite3CorruptError(7232);
|
|
assert( pPage->nFree>=0 );
|
|
assert( pParent->nFree>=0 );
|
|
|
|
|
|
|
|
|
|
|
|
rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0);
|
|
|
|
if( rc==0 ){
|
|
|
|
u8 *pOut = &pSpace[4];
|
|
u8 *pCell = pPage->apOvfl[0];
|
|
u16 szCell = pPage->xCellSize(pPage, pCell);
|
|
u8 *pStop;
|
|
CellArray b;
|
|
|
|
assert( sqlite3PagerIswriteable(pNew->pDbPage) );
|
|
assert( (sqlite3Config.neverCorrupt==0) || pPage->aData[0]==(0x01|0x04|0x08) );
|
|
zeroPage(pNew, 0x01|0x04|0x08);
|
|
b.nCell = 1;
|
|
b.pRef = pPage;
|
|
b.apCell = &pCell;
|
|
b.szCell = &szCell;
|
|
b.apEnd[0] = pPage->aDataEnd;
|
|
b.ixNx[0] = 2;
|
|
rc = rebuildPage(&b, 0, 1, pNew);
|
|
if( (rc) ){
|
|
releasePage(pNew);
|
|
return rc;
|
|
}
|
|
pNew->nFree = pBt->usableSize - pNew->cellOffset - 2 - szCell;
|
|
# 7275 "src/btree.c"
|
|
if( (pBt->autoVacuum) ){
|
|
ptrmapPut(pBt, pgnoNew, 5, pParent->pgno, &rc);
|
|
if( szCell>pNew->minLocal ){
|
|
ptrmapPutOvflPtr(pNew, pNew, pCell, &rc);
|
|
}
|
|
}
|
|
# 7295 "src/btree.c"
|
|
pCell = ((pPage)->aData + ((pPage)->maskPage & __builtin_bswap16(*(u16*)(&(pPage)->aCellIdx[2*(pPage->nCell-1)]))));
|
|
pStop = &pCell[9];
|
|
while( (*(pCell++)&0x80) && pCell<pStop );
|
|
pStop = &pCell[9];
|
|
while( ((*(pOut++) = *(pCell++))&0x80) && pCell<pStop );
|
|
|
|
|
|
if( rc==0 ){
|
|
insertCell(pParent, pParent->nCell, pSpace, (int)(pOut-pSpace),
|
|
0, pPage->pgno, &rc);
|
|
}
|
|
|
|
|
|
sqlite3Put4byte(&pParent->aData[pParent->hdrOffset+8], pgnoNew);
|
|
|
|
|
|
releasePage(pNew);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
# 7377 "src/btree.c"
|
|
static void copyNodeContent(MemPage *pFrom, MemPage *pTo, int *pRC){
|
|
if( (*pRC)==0 ){
|
|
BtShared * const pBt = pFrom->pBt;
|
|
u8 * const aFrom = pFrom->aData;
|
|
u8 * const aTo = pTo->aData;
|
|
int const iFromHdr = pFrom->hdrOffset;
|
|
int const iToHdr = ((pTo->pgno==1) ? 100 : 0);
|
|
int rc;
|
|
int iData;
|
|
|
|
|
|
assert( pFrom->isInit );
|
|
assert( pFrom->nFree>=iToHdr );
|
|
assert( ((&aFrom[iFromHdr+5])[0]<<8 | (&aFrom[iFromHdr+5])[1]) <= (int)pBt->usableSize );
|
|
|
|
|
|
iData = ((&aFrom[iFromHdr+5])[0]<<8 | (&aFrom[iFromHdr+5])[1]);
|
|
memcpy(&aTo[iData], &aFrom[iData], pBt->usableSize-iData);
|
|
memcpy(&aTo[iToHdr], &aFrom[iFromHdr], pFrom->cellOffset + 2*pFrom->nCell);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pTo->isInit = 0;
|
|
rc = btreeInitPage(pTo);
|
|
if( rc==0 ) rc = btreeComputeFreeSpace(pTo);
|
|
if( rc!=0 ){
|
|
*pRC = rc;
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
if( (pBt->autoVacuum) ){
|
|
*pRC = setChildPtrmaps(pTo);
|
|
}
|
|
}
|
|
}
|
|
# 7459 "src/btree.c"
|
|
static int balance_nonroot(
|
|
MemPage *pParent,
|
|
int iParentIdx,
|
|
u8 *aOvflSpace,
|
|
int isRoot,
|
|
int bBulk
|
|
){
|
|
BtShared *pBt;
|
|
int nMaxCells = 0;
|
|
int nNew = 0;
|
|
int nOld;
|
|
int i, j, k;
|
|
int nxDiv;
|
|
int rc = 0;
|
|
u16 leafCorrection;
|
|
int leafData;
|
|
int usableSpace;
|
|
int pageFlags;
|
|
int iSpace1 = 0;
|
|
int iOvflSpace = 0;
|
|
int szScratch;
|
|
MemPage *apOld[3];
|
|
MemPage *apNew[3 +2];
|
|
u8 *pRight;
|
|
u8 *apDiv[3 -1];
|
|
int cntNew[3 +2];
|
|
int cntOld[3 +2];
|
|
int szNew[3 +2];
|
|
u8 *aSpace1;
|
|
Pgno pgno;
|
|
u8 abDone[3 +2];
|
|
Pgno aPgno[3 +2];
|
|
Pgno aPgOrder[3 +2];
|
|
u16 aPgFlags[3 +2];
|
|
CellArray b;
|
|
|
|
memset(abDone, 0, sizeof(abDone));
|
|
b.nCell = 0;
|
|
b.apCell = 0;
|
|
pBt = pParent->pBt;
|
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
|
assert( sqlite3PagerIswriteable(pParent->pDbPage) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert( pParent->nOverflow==0 || pParent->nOverflow==1 );
|
|
assert( pParent->nOverflow==0 || pParent->aiOvfl[0]==iParentIdx );
|
|
|
|
if( !aOvflSpace ){
|
|
return 7;
|
|
}
|
|
assert( pParent->nFree>=0 );
|
|
# 7526 "src/btree.c"
|
|
i = pParent->nOverflow + pParent->nCell;
|
|
if( i<2 ){
|
|
nxDiv = 0;
|
|
}else{
|
|
assert( bBulk==0 || bBulk==1 );
|
|
if( iParentIdx==0 ){
|
|
nxDiv = 0;
|
|
}else if( iParentIdx==i ){
|
|
nxDiv = i-2+bBulk;
|
|
}else{
|
|
nxDiv = iParentIdx-1;
|
|
}
|
|
i = 2-bBulk;
|
|
}
|
|
nOld = i+1;
|
|
if( (i+nxDiv-pParent->nOverflow)==pParent->nCell ){
|
|
pRight = &pParent->aData[pParent->hdrOffset+8];
|
|
}else{
|
|
pRight = ((pParent)->aData + ((pParent)->maskPage & __builtin_bswap16(*(u16*)(&(pParent)->aCellIdx[2*(i+nxDiv-pParent->nOverflow)]))));
|
|
}
|
|
pgno = sqlite3Get4byte(pRight);
|
|
while( 1 ){
|
|
rc = getAndInitPage(pBt, pgno, &apOld[i], 0, 0);
|
|
if( rc ){
|
|
memset(apOld, 0, (i+1)*sizeof(MemPage*));
|
|
goto balance_cleanup;
|
|
}
|
|
if( apOld[i]->nFree<0 ){
|
|
rc = btreeComputeFreeSpace(apOld[i]);
|
|
if( rc ){
|
|
memset(apOld, 0, (i)*sizeof(MemPage*));
|
|
goto balance_cleanup;
|
|
}
|
|
}
|
|
if( (i--)==0 ) break;
|
|
|
|
if( pParent->nOverflow && i+nxDiv==pParent->aiOvfl[0] ){
|
|
apDiv[i] = pParent->apOvfl[0];
|
|
pgno = sqlite3Get4byte(apDiv[i]);
|
|
szNew[i] = pParent->xCellSize(pParent, apDiv[i]);
|
|
pParent->nOverflow = 0;
|
|
}else{
|
|
apDiv[i] = ((pParent)->aData + ((pParent)->maskPage & __builtin_bswap16(*(u16*)(&(pParent)->aCellIdx[2*(i+nxDiv-pParent->nOverflow)]))));
|
|
pgno = sqlite3Get4byte(apDiv[i]);
|
|
szNew[i] = pParent->xCellSize(pParent, apDiv[i]);
|
|
# 7584 "src/btree.c"
|
|
if( pBt->btsFlags & 0x000c ){
|
|
int iOff;
|
|
|
|
iOff = ((int)(long int)(apDiv[i])) - ((int)(long int)(pParent->aData));
|
|
if( (iOff+szNew[i])>(int)pBt->usableSize ){
|
|
rc = sqlite3CorruptError(7589);
|
|
memset(apOld, 0, (i+1)*sizeof(MemPage*));
|
|
goto balance_cleanup;
|
|
}else{
|
|
memcpy(&aOvflSpace[iOff], apDiv[i], szNew[i]);
|
|
apDiv[i] = &aOvflSpace[apDiv[i]-pParent->aData];
|
|
}
|
|
}
|
|
dropCell(pParent, i+nxDiv-pParent->nOverflow, szNew[i], &rc);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
nMaxCells = nOld*(((pBt->pageSize-8)/6) + ((int)(sizeof(pParent->apOvfl)/sizeof(pParent->apOvfl[0]))));
|
|
nMaxCells = (nMaxCells + 3)&~3;
|
|
|
|
|
|
|
|
|
|
szScratch =
|
|
nMaxCells*sizeof(u8*)
|
|
+ nMaxCells*sizeof(u16)
|
|
+ pBt->pageSize;
|
|
|
|
assert( szScratch<=7*(int)pBt->pageSize );
|
|
b.apCell = sqlite3DbMallocRaw(0,szScratch);
|
|
if( b.apCell==0 ){
|
|
rc = 7;
|
|
goto balance_cleanup;
|
|
}
|
|
b.szCell = (u16*)&b.apCell[nMaxCells];
|
|
aSpace1 = (u8*)&b.szCell[nMaxCells];
|
|
assert( ((((char*)(aSpace1) - (char*)0)&7)==0) );
|
|
# 7640 "src/btree.c"
|
|
b.pRef = apOld[0];
|
|
leafCorrection = b.pRef->leaf*4;
|
|
leafData = b.pRef->intKeyLeaf;
|
|
for(i=0; i<nOld; i++){
|
|
MemPage *pOld = apOld[i];
|
|
int limit = pOld->nCell;
|
|
u8 *aData = pOld->aData;
|
|
u16 maskPage = pOld->maskPage;
|
|
u8 *piCell = aData + pOld->cellOffset;
|
|
u8 *piEnd;
|
|
|
|
|
|
|
|
|
|
|
|
if( pOld->aData[0]!=apOld[0]->aData[0] ){
|
|
rc = sqlite3CorruptError(7656);
|
|
goto balance_cleanup;
|
|
}
|
|
# 7677 "src/btree.c"
|
|
memset(&b.szCell[b.nCell], 0, sizeof(b.szCell[0])*(limit+pOld->nOverflow));
|
|
if( pOld->nOverflow>0 ){
|
|
if( limit<pOld->aiOvfl[0] ){
|
|
rc = sqlite3CorruptError(7680);
|
|
goto balance_cleanup;
|
|
}
|
|
limit = pOld->aiOvfl[0];
|
|
for(j=0; j<limit; j++){
|
|
b.apCell[b.nCell] = aData + (maskPage & __builtin_bswap16(*(u16*)(piCell)));
|
|
piCell += 2;
|
|
b.nCell++;
|
|
}
|
|
for(k=0; k<pOld->nOverflow; k++){
|
|
assert( k==0 || pOld->aiOvfl[k-1]+1==pOld->aiOvfl[k] );
|
|
b.apCell[b.nCell] = pOld->apOvfl[k];
|
|
b.nCell++;
|
|
}
|
|
}
|
|
piEnd = aData + pOld->cellOffset + 2*pOld->nCell;
|
|
while( piCell<piEnd ){
|
|
assert( b.nCell<nMaxCells );
|
|
b.apCell[b.nCell] = aData + (maskPage & __builtin_bswap16(*(u16*)(piCell)));
|
|
piCell += 2;
|
|
b.nCell++;
|
|
}
|
|
assert( (b.nCell-nCellAtStart)==(pOld->nCell+pOld->nOverflow) );
|
|
|
|
cntOld[i] = b.nCell;
|
|
if( i<nOld-1 && !leafData){
|
|
u16 sz = (u16)szNew[i];
|
|
u8 *pTemp;
|
|
assert( b.nCell<nMaxCells );
|
|
b.szCell[b.nCell] = sz;
|
|
pTemp = &aSpace1[iSpace1];
|
|
iSpace1 += sz;
|
|
assert( sz<=pBt->maxLocal+23 );
|
|
assert( iSpace1 <= (int)pBt->pageSize );
|
|
memcpy(pTemp, apDiv[i], sz);
|
|
b.apCell[b.nCell] = pTemp+leafCorrection;
|
|
assert( leafCorrection==0 || leafCorrection==4 );
|
|
b.szCell[b.nCell] = b.szCell[b.nCell] - leafCorrection;
|
|
if( !pOld->leaf ){
|
|
assert( leafCorrection==0 );
|
|
assert( pOld->hdrOffset==0 );
|
|
|
|
|
|
memcpy(b.apCell[b.nCell], &pOld->aData[8], 4);
|
|
}else{
|
|
assert( leafCorrection==4 );
|
|
while( b.szCell[b.nCell]<4 ){
|
|
|
|
|
|
assert( b.szCell[b.nCell]==3 || (sqlite3Config.neverCorrupt==0) );
|
|
assert( b.apCell[b.nCell]==&aSpace1[iSpace1-3] || (sqlite3Config.neverCorrupt==0) );
|
|
aSpace1[iSpace1++] = 0x00;
|
|
b.szCell[b.nCell]++;
|
|
}
|
|
}
|
|
b.nCell++;
|
|
}
|
|
}
|
|
# 7755 "src/btree.c"
|
|
usableSpace = pBt->usableSize - 12 + leafCorrection;
|
|
for(i=k=0; i<nOld; i++, k++){
|
|
MemPage *p = apOld[i];
|
|
b.apEnd[k] = p->aDataEnd;
|
|
b.ixNx[k] = cntOld[i];
|
|
if( k && b.ixNx[k]==b.ixNx[k-1] ){
|
|
k--;
|
|
}
|
|
if( !leafData ){
|
|
k++;
|
|
b.apEnd[k] = pParent->aDataEnd;
|
|
b.ixNx[k] = cntOld[i]+1;
|
|
}
|
|
assert( p->nFree>=0 );
|
|
szNew[i] = usableSpace - p->nFree;
|
|
for(j=0; j<p->nOverflow; j++){
|
|
szNew[i] += 2 + p->xCellSize(p, p->apOvfl[j]);
|
|
}
|
|
cntNew[i] = cntOld[i];
|
|
}
|
|
k = nOld;
|
|
for(i=0; i<k; i++){
|
|
int sz;
|
|
while( szNew[i]>usableSpace ){
|
|
if( i+1>=k ){
|
|
k = i+2;
|
|
if( k>3 +2 ){ rc = sqlite3CorruptError(7781); goto balance_cleanup; }
|
|
szNew[k-1] = 0;
|
|
cntNew[k-1] = b.nCell;
|
|
}
|
|
sz = 2 + cachedCellSize(&b, cntNew[i]-1);
|
|
szNew[i] -= sz;
|
|
if( !leafData ){
|
|
if( cntNew[i]<b.nCell ){
|
|
sz = 2 + cachedCellSize(&b, cntNew[i]);
|
|
}else{
|
|
sz = 0;
|
|
}
|
|
}
|
|
szNew[i+1] += sz;
|
|
cntNew[i]--;
|
|
}
|
|
while( cntNew[i]<b.nCell ){
|
|
sz = 2 + cachedCellSize(&b, cntNew[i]);
|
|
if( szNew[i]+sz>usableSpace ) break;
|
|
szNew[i] += sz;
|
|
cntNew[i]++;
|
|
if( !leafData ){
|
|
if( cntNew[i]<b.nCell ){
|
|
sz = 2 + cachedCellSize(&b, cntNew[i]);
|
|
}else{
|
|
sz = 0;
|
|
}
|
|
}
|
|
szNew[i+1] -= sz;
|
|
}
|
|
if( cntNew[i]>=b.nCell ){
|
|
k = i+1;
|
|
}else if( cntNew[i] <= (i>0 ? cntNew[i-1] : 0) ){
|
|
rc = sqlite3CorruptError(7814);
|
|
goto balance_cleanup;
|
|
}
|
|
}
|
|
# 7830 "src/btree.c"
|
|
for(i=k-1; i>0; i--){
|
|
int szRight = szNew[i];
|
|
int szLeft = szNew[i-1];
|
|
int r;
|
|
int d;
|
|
|
|
r = cntNew[i-1] - 1;
|
|
d = r + 1 - leafData;
|
|
(void)cachedCellSize(&b, d);
|
|
do{
|
|
assert( d<nMaxCells );
|
|
assert( r<nMaxCells );
|
|
(void)cachedCellSize(&b, r);
|
|
if( szRight!=0
|
|
&& (bBulk || szRight+b.szCell[d]+2 > szLeft-(b.szCell[r]+(i==k-1?0:2)))){
|
|
break;
|
|
}
|
|
szRight += b.szCell[d] + 2;
|
|
szLeft -= b.szCell[r] + 2;
|
|
cntNew[i-1] = r;
|
|
r--;
|
|
d--;
|
|
}while( r>=0 );
|
|
szNew[i] = szRight;
|
|
szNew[i-1] = szLeft;
|
|
if( cntNew[i-1] <= (i>1 ? cntNew[i-2] : 0) ){
|
|
rc = sqlite3CorruptError(7856);
|
|
goto balance_cleanup;
|
|
}
|
|
}
|
|
# 7868 "src/btree.c"
|
|
assert( cntNew[0]>0 || (pParent->pgno==1 && pParent->nCell==0) || (sqlite3Config.neverCorrupt==0));
|
|
|
|
|
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
pageFlags = apOld[0]->aData[0];
|
|
for(i=0; i<k; i++){
|
|
MemPage *pNew;
|
|
if( i<nOld ){
|
|
pNew = apNew[i] = apOld[i];
|
|
apOld[i] = 0;
|
|
rc = sqlite3PagerWrite(pNew->pDbPage);
|
|
nNew++;
|
|
if( rc ) goto balance_cleanup;
|
|
}else{
|
|
assert( i>0 );
|
|
rc = allocateBtreePage(pBt, &pNew, &pgno, (bBulk ? 1 : pgno), 0);
|
|
if( rc ) goto balance_cleanup;
|
|
zeroPage(pNew, pageFlags);
|
|
apNew[i] = pNew;
|
|
nNew++;
|
|
cntOld[i] = b.nCell;
|
|
|
|
|
|
if( (pBt->autoVacuum) ){
|
|
ptrmapPut(pBt, pNew->pgno, 5, pParent->pgno, &rc);
|
|
if( rc!=0 ){
|
|
goto balance_cleanup;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
# 7918 "src/btree.c"
|
|
for(i=0; i<nNew; i++){
|
|
aPgOrder[i] = aPgno[i] = apNew[i]->pgno;
|
|
aPgFlags[i] = apNew[i]->pDbPage->flags;
|
|
for(j=0; j<i; j++){
|
|
if( aPgno[j]==aPgno[i] ){
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert( (sqlite3Config.neverCorrupt==0) );
|
|
rc = sqlite3CorruptError(7930);
|
|
goto balance_cleanup;
|
|
}
|
|
}
|
|
}
|
|
for(i=0; i<nNew; i++){
|
|
int iBest = 0;
|
|
for(j=1; j<nNew; j++){
|
|
if( aPgOrder[j]<aPgOrder[iBest] ) iBest = j;
|
|
}
|
|
pgno = aPgOrder[iBest];
|
|
aPgOrder[iBest] = 0xffffffff;
|
|
if( iBest!=i ){
|
|
if( iBest>i ){
|
|
sqlite3PagerRekey(apNew[iBest]->pDbPage, pBt->nPage+iBest+1, 0);
|
|
}
|
|
sqlite3PagerRekey(apNew[i]->pDbPage, pgno, aPgFlags[iBest]);
|
|
apNew[i]->pgno = pgno;
|
|
}
|
|
}
|
|
|
|
|
|
# 7962 "src/btree.c"
|
|
;
|
|
|
|
assert( sqlite3PagerIswriteable(pParent->pDbPage) );
|
|
sqlite3Put4byte(pRight, apNew[nNew-1]->pgno);
|
|
|
|
|
|
|
|
|
|
if( (pageFlags & 0x08)==0 && nOld!=nNew ){
|
|
MemPage *pOld = (nNew>nOld ? apNew : apOld)[nOld-1];
|
|
memcpy(&apNew[nNew-1]->aData[8], &pOld->aData[8], 4);
|
|
}
|
|
# 7991 "src/btree.c"
|
|
if( (pBt->autoVacuum) ){
|
|
MemPage *pOld;
|
|
MemPage *pNew = pOld = apNew[0];
|
|
int cntOldNext = pNew->nCell + pNew->nOverflow;
|
|
int iNew = 0;
|
|
int iOld = 0;
|
|
|
|
for(i=0; i<b.nCell; i++){
|
|
u8 *pCell = b.apCell[i];
|
|
while( i==cntOldNext ){
|
|
iOld++;
|
|
assert( iOld<nNew || iOld<nOld );
|
|
assert( iOld>=0 && iOld<3 );
|
|
pOld = iOld<nNew ? apNew[iOld] : apOld[iOld];
|
|
cntOldNext += pOld->nCell + pOld->nOverflow + !leafData;
|
|
}
|
|
if( i==cntNew[iNew] ){
|
|
pNew = apNew[++iNew];
|
|
if( !leafData ) continue;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( iOld>=nNew
|
|
|| pNew->pgno!=aPgno[iOld]
|
|
|| !(((uptr)(pCell)>=(uptr)(pOld->aData))&&((uptr)(pCell)<(uptr)(pOld->aDataEnd)))
|
|
){
|
|
if( !leafCorrection ){
|
|
ptrmapPut(pBt, sqlite3Get4byte(pCell), 5, pNew->pgno, &rc);
|
|
}
|
|
if( cachedCellSize(&b,i)>pNew->minLocal ){
|
|
ptrmapPutOvflPtr(pNew, pOld, pCell, &rc);
|
|
}
|
|
if( rc ) goto balance_cleanup;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
for(i=0; i<nNew-1; i++){
|
|
u8 *pCell;
|
|
u8 *pTemp;
|
|
int sz;
|
|
MemPage *pNew = apNew[i];
|
|
j = cntNew[i];
|
|
|
|
assert( j<nMaxCells );
|
|
assert( b.apCell[j]!=0 );
|
|
pCell = b.apCell[j];
|
|
sz = b.szCell[j] + leafCorrection;
|
|
pTemp = &aOvflSpace[iOvflSpace];
|
|
if( !pNew->leaf ){
|
|
memcpy(&pNew->aData[8], pCell, 4);
|
|
}else if( leafData ){
|
|
|
|
|
|
|
|
|
|
|
|
CellInfo info;
|
|
j--;
|
|
pNew->xParseCell(pNew, b.apCell[j], &info);
|
|
pCell = pTemp;
|
|
sz = 4 + sqlite3PutVarint(&pCell[4], info.nKey);
|
|
pTemp = 0;
|
|
}else{
|
|
pCell -= 4;
|
|
# 8073 "src/btree.c"
|
|
if( b.szCell[j]==4 ){
|
|
assert(leafCorrection==4);
|
|
sz = pParent->xCellSize(pParent, pCell);
|
|
}
|
|
}
|
|
iOvflSpace += sz;
|
|
assert( sz<=pBt->maxLocal+23 );
|
|
assert( iOvflSpace <= (int)pBt->pageSize );
|
|
insertCell(pParent, nxDiv+i, pCell, sz, pTemp, pNew->pgno, &rc);
|
|
if( rc!=0 ) goto balance_cleanup;
|
|
assert( sqlite3PagerIswriteable(pParent->pDbPage) );
|
|
}
|
|
# 8108 "src/btree.c"
|
|
for(i=1-nNew; i<nNew; i++){
|
|
int iPg = i<0 ? -i : i;
|
|
assert( iPg>=0 && iPg<nNew );
|
|
if( abDone[iPg] ) continue;
|
|
if( i>=0
|
|
|| cntOld[iPg-1]>=cntNew[iPg-1]
|
|
){
|
|
int iNew;
|
|
int iOld;
|
|
int nNewCell;
|
|
|
|
|
|
|
|
assert( iPg==0 || cntOld[iPg-1]>=cntNew[iPg-1] || abDone[iPg-1] );
|
|
|
|
|
|
|
|
assert( cntNew[iPg]>=cntOld[iPg] || abDone[iPg+1] );
|
|
|
|
if( iPg==0 ){
|
|
iNew = iOld = 0;
|
|
nNewCell = cntNew[0];
|
|
}else{
|
|
iOld = iPg<nOld ? (cntOld[iPg-1] + !leafData) : b.nCell;
|
|
iNew = cntNew[iPg-1] + !leafData;
|
|
nNewCell = cntNew[iPg] - iNew;
|
|
}
|
|
|
|
rc = editPage(apNew[iPg], iOld, iNew, nNewCell, &b);
|
|
if( rc ) goto balance_cleanup;
|
|
abDone[iPg]++;
|
|
apNew[iPg]->nFree = usableSpace-szNew[iPg];
|
|
assert( apNew[iPg]->nOverflow==0 );
|
|
assert( apNew[iPg]->nCell==nNewCell );
|
|
}
|
|
}
|
|
|
|
|
|
assert( memcmp(abDone, "\01\01\01\01\01", nNew)==0 );
|
|
|
|
assert( nOld>0 );
|
|
assert( nNew>0 );
|
|
|
|
if( isRoot && pParent->nCell==0 && pParent->hdrOffset<=apNew[0]->nFree ){
|
|
# 8167 "src/btree.c"
|
|
assert( nNew==1 || (sqlite3Config.neverCorrupt==0) );
|
|
rc = defragmentPage(apNew[0], -1);
|
|
;
|
|
assert( apNew[0]->nFree ==
|
|
((((((int)((&apNew[0]->aData[5])[0]<<8 | (&apNew[0]->aData[5])[1]))-1)&0xffff)+1) - apNew[0]->cellOffset
|
|
- apNew[0]->nCell*2)
|
|
|| rc!=0
|
|
);
|
|
copyNodeContent(apNew[0], pParent, &rc);
|
|
freePage(apNew[0], &rc);
|
|
}else if( (pBt->autoVacuum) && !leafCorrection ){
|
|
|
|
|
|
|
|
for(i=0; i<nNew; i++){
|
|
u32 key = sqlite3Get4byte(&apNew[i]->aData[8]);
|
|
ptrmapPut(pBt, key, 5, apNew[i]->pgno, &rc);
|
|
}
|
|
}
|
|
|
|
assert( pParent->isInit );
|
|
|
|
;
|
|
|
|
|
|
|
|
for(i=nNew; i<nOld; i++){
|
|
freePage(apOld[i], &rc);
|
|
}
|
|
# 8211 "src/btree.c"
|
|
balance_cleanup:
|
|
sqlite3DbFree(0,b.apCell);
|
|
for(i=0; i<nOld; i++){
|
|
releasePage(apOld[i]);
|
|
}
|
|
for(i=0; i<nNew; i++){
|
|
releasePage(apNew[i]);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
# 8243 "src/btree.c"
|
|
static int balance_deeper(MemPage *pRoot, MemPage **ppChild){
|
|
int rc;
|
|
MemPage *pChild = 0;
|
|
Pgno pgnoChild = 0;
|
|
BtShared *pBt = pRoot->pBt;
|
|
|
|
assert( pRoot->nOverflow>0 );
|
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
|
|
|
|
|
|
|
|
|
|
|
rc = sqlite3PagerWrite(pRoot->pDbPage);
|
|
if( rc==0 ){
|
|
rc = allocateBtreePage(pBt,&pChild,&pgnoChild,pRoot->pgno,0);
|
|
copyNodeContent(pRoot, pChild, &rc);
|
|
if( (pBt->autoVacuum) ){
|
|
ptrmapPut(pBt, pgnoChild, 5, pRoot->pgno, &rc);
|
|
}
|
|
}
|
|
if( rc ){
|
|
*ppChild = 0;
|
|
releasePage(pChild);
|
|
return rc;
|
|
}
|
|
assert( sqlite3PagerIswriteable(pChild->pDbPage) );
|
|
assert( sqlite3PagerIswriteable(pRoot->pDbPage) );
|
|
assert( pChild->nCell==pRoot->nCell || (sqlite3Config.neverCorrupt==0) );
|
|
|
|
;
|
|
|
|
|
|
memcpy(pChild->aiOvfl, pRoot->aiOvfl,
|
|
pRoot->nOverflow*sizeof(pRoot->aiOvfl[0]));
|
|
memcpy(pChild->apOvfl, pRoot->apOvfl,
|
|
pRoot->nOverflow*sizeof(pRoot->apOvfl[0]));
|
|
pChild->nOverflow = pRoot->nOverflow;
|
|
|
|
|
|
zeroPage(pRoot, pChild->aData[0] & ~0x08);
|
|
sqlite3Put4byte(&pRoot->aData[pRoot->hdrOffset+8], pgnoChild);
|
|
|
|
*ppChild = pChild;
|
|
return 0;
|
|
}
|
|
# 8300 "src/btree.c"
|
|
static int balance(BtCursor *pCur){
|
|
int rc = 0;
|
|
const int nMin = pCur->pBt->usableSize * 2 / 3;
|
|
u8 aBalanceQuickSpace[13];
|
|
u8 *pFree = 0;
|
|
|
|
;
|
|
;
|
|
|
|
do {
|
|
int iPage = pCur->iPage;
|
|
MemPage *pPage = pCur->pPage;
|
|
|
|
if( (pPage->nFree<0) && btreeComputeFreeSpace(pPage) ) break;
|
|
if( iPage==0 ){
|
|
if( pPage->nOverflow ){
|
|
|
|
|
|
|
|
|
|
|
|
assert( balance_deeper_called==0 );
|
|
;
|
|
rc = balance_deeper(pPage, &pCur->apPage[1]);
|
|
if( rc==0 ){
|
|
pCur->iPage = 1;
|
|
pCur->ix = 0;
|
|
pCur->aiIdx[0] = 0;
|
|
pCur->apPage[0] = pPage;
|
|
pCur->pPage = pCur->apPage[1];
|
|
assert( pCur->pPage->nOverflow );
|
|
}
|
|
}else{
|
|
break;
|
|
}
|
|
}else if( pPage->nOverflow==0 && pPage->nFree<=nMin ){
|
|
break;
|
|
}else{
|
|
MemPage * const pParent = pCur->apPage[iPage-1];
|
|
int const iIdx = pCur->aiIdx[iPage-1];
|
|
|
|
rc = sqlite3PagerWrite(pParent->pDbPage);
|
|
if( rc==0 && pParent->nFree<0 ){
|
|
rc = btreeComputeFreeSpace(pParent);
|
|
}
|
|
if( rc==0 ){
|
|
|
|
if( pPage->intKeyLeaf
|
|
&& pPage->nOverflow==1
|
|
&& pPage->aiOvfl[0]==pPage->nCell
|
|
&& pParent->pgno!=1
|
|
&& pParent->nCell==iIdx
|
|
){
|
|
# 8366 "src/btree.c"
|
|
assert( balance_quick_called==0 );
|
|
;
|
|
rc = balance_quick(pParent, pPage, aBalanceQuickSpace);
|
|
}else
|
|
|
|
{
|
|
# 8389 "src/btree.c"
|
|
u8 *pSpace = sqlite3PageMalloc(pCur->pBt->pageSize);
|
|
rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1,
|
|
pCur->hints&0x00000001);
|
|
if( pFree ){
|
|
|
|
|
|
|
|
|
|
sqlite3PageFree(pFree);
|
|
}
|
|
|
|
|
|
|
|
|
|
pFree = pSpace;
|
|
}
|
|
}
|
|
|
|
pPage->nOverflow = 0;
|
|
|
|
|
|
releasePage(pPage);
|
|
pCur->iPage--;
|
|
assert( pCur->iPage>=0 );
|
|
pCur->pPage = pCur->apPage[pCur->iPage];
|
|
}
|
|
}while( rc==0 );
|
|
|
|
if( pFree ){
|
|
sqlite3PageFree(pFree);
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
|
|
static int btreeOverwriteContent(
|
|
MemPage *pPage,
|
|
u8 *pDest,
|
|
const BtreePayload *pX,
|
|
int iOffset,
|
|
int iAmt
|
|
){
|
|
int nData = pX->nData - iOffset;
|
|
if( nData<=0 ){
|
|
|
|
int i;
|
|
for(i=0; i<iAmt && pDest[i]==0; i++){}
|
|
if( i<iAmt ){
|
|
int rc = sqlite3PagerWrite(pPage->pDbPage);
|
|
if( rc ) return rc;
|
|
memset(pDest + i, 0, iAmt - i);
|
|
}
|
|
}else{
|
|
if( nData<iAmt ){
|
|
|
|
|
|
int rc = btreeOverwriteContent(pPage, pDest+nData, pX, iOffset+nData,
|
|
iAmt-nData);
|
|
if( rc ) return rc;
|
|
iAmt = nData;
|
|
}
|
|
if( memcmp(pDest, ((u8*)pX->pData) + iOffset, iAmt)!=0 ){
|
|
int rc = sqlite3PagerWrite(pPage->pDbPage);
|
|
if( rc ) return rc;
|
|
|
|
|
|
|
|
|
|
memmove(pDest, ((u8*)pX->pData) + iOffset, iAmt);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){
|
|
int iOffset;
|
|
int nTotal = pX->nData + pX->nZero;
|
|
int rc;
|
|
MemPage *pPage = pCur->pPage;
|
|
BtShared *pBt;
|
|
Pgno ovflPgno;
|
|
u32 ovflPageSize;
|
|
|
|
if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd ){
|
|
return sqlite3CorruptError(8479);
|
|
}
|
|
|
|
rc = btreeOverwriteContent(pPage, pCur->info.pPayload, pX,
|
|
0, pCur->info.nLocal);
|
|
if( rc ) return rc;
|
|
if( pCur->info.nLocal==nTotal ) return 0;
|
|
|
|
|
|
iOffset = pCur->info.nLocal;
|
|
assert( nTotal>=0 );
|
|
assert( iOffset>=0 );
|
|
ovflPgno = sqlite3Get4byte(pCur->info.pPayload + iOffset);
|
|
pBt = pPage->pBt;
|
|
ovflPageSize = pBt->usableSize - 4;
|
|
do{
|
|
rc = btreeGetPage(pBt, ovflPgno, &pPage, 0);
|
|
if( rc ) return rc;
|
|
if( sqlite3PagerPageRefcount(pPage->pDbPage)!=1 ){
|
|
rc = sqlite3CorruptError(8498);
|
|
}else{
|
|
if( iOffset+ovflPageSize<(u32)nTotal ){
|
|
ovflPgno = sqlite3Get4byte(pPage->aData);
|
|
}else{
|
|
ovflPageSize = nTotal - iOffset;
|
|
}
|
|
rc = btreeOverwriteContent(pPage, pPage->aData+4, pX,
|
|
iOffset, ovflPageSize);
|
|
}
|
|
sqlite3PagerUnref(pPage->pDbPage);
|
|
if( rc ) return rc;
|
|
iOffset += ovflPageSize;
|
|
}while( iOffset<nTotal );
|
|
return 0;
|
|
}
|
|
# 8546 "src/btree.c"
|
|
int sqlite3BtreeInsert(
|
|
BtCursor *pCur,
|
|
const BtreePayload *pX,
|
|
int flags,
|
|
int seekResult
|
|
){
|
|
int rc;
|
|
int loc = seekResult;
|
|
int szNew = 0;
|
|
int idx;
|
|
MemPage *pPage;
|
|
Btree *p = pCur->pBtree;
|
|
BtShared *pBt = p->pBt;
|
|
unsigned char *oldCell;
|
|
unsigned char *newCell = 0;
|
|
|
|
assert( (flags & (0x02|0x08))==flags );
|
|
|
|
if( pCur->eState==4 ){
|
|
assert( pCur->skipNext!=0 );
|
|
return pCur->skipNext;
|
|
}
|
|
|
|
assert( cursorOwnsBtShared(pCur) );
|
|
assert( (pCur->curFlags & 0x01)!=0
|
|
&& pBt->inTransaction==2
|
|
&& (pBt->btsFlags & 0x0001)==0 );
|
|
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert( (pX->pKey==0)==(pCur->pKeyInfo==0) );
|
|
# 8593 "src/btree.c"
|
|
if( pCur->curFlags & 0x20 ){
|
|
rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
|
|
if( rc ) return rc;
|
|
}
|
|
|
|
if( pCur->pKeyInfo==0 ){
|
|
assert( pX->pKey==0 );
|
|
|
|
|
|
invalidateIncrblobCursors(p, pCur->pgnoRoot, pX->nKey, 0);
|
|
# 8620 "src/btree.c"
|
|
if( (pCur->curFlags&0x02)!=0 && pX->nKey==pCur->info.nKey ){
|
|
|
|
|
|
assert( pX->nData>=0 && pX->nZero>=0 );
|
|
if( pCur->info.nSize!=0
|
|
&& pCur->info.nPayload==(u32)pX->nData+pX->nZero
|
|
){
|
|
|
|
return btreeOverwriteCell(pCur, pX);
|
|
}
|
|
assert( loc==0 );
|
|
}else if( loc==0 ){
|
|
|
|
|
|
|
|
|
|
rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, flags!=0, &loc);
|
|
if( rc ) return rc;
|
|
}
|
|
}else{
|
|
|
|
|
|
|
|
|
|
|
|
assert( (flags & 0x02)==0 || loc==0 );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( loc==0 && (flags & 0x02)==0 ){
|
|
if( pX->nMem ){
|
|
UnpackedRecord r;
|
|
r.pKeyInfo = pCur->pKeyInfo;
|
|
r.aMem = pX->aMem;
|
|
r.nField = pX->nMem;
|
|
r.default_rc = 0;
|
|
r.errCode = 0;
|
|
r.r1 = 0;
|
|
r.r2 = 0;
|
|
r.eqSeen = 0;
|
|
rc = sqlite3BtreeMovetoUnpacked(pCur, &r, 0, flags!=0, &loc);
|
|
}else{
|
|
rc = btreeMoveto(pCur, pX->pKey, pX->nKey, flags!=0, &loc);
|
|
}
|
|
if( rc ) return rc;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if( loc==0 ){
|
|
getCellInfo(pCur);
|
|
if( pCur->info.nKey==pX->nKey ){
|
|
BtreePayload x2;
|
|
x2.pData = pX->pKey;
|
|
x2.nData = pX->nKey;
|
|
x2.nZero = 0;
|
|
return btreeOverwriteCell(pCur, &x2);
|
|
}
|
|
}
|
|
|
|
}
|
|
assert( pCur->eState==0 || (pCur->eState==1 && loc) );
|
|
|
|
pPage = pCur->pPage;
|
|
assert( pPage->intKey || pX->nKey>=0 );
|
|
assert( pPage->leaf || !pPage->intKey );
|
|
if( pPage->nFree<0 ){
|
|
rc = btreeComputeFreeSpace(pPage);
|
|
if( rc ) return rc;
|
|
}
|
|
|
|
|
|
|
|
;
|
|
assert( pPage->isInit );
|
|
newCell = pBt->pTmpSpace;
|
|
assert( newCell!=0 );
|
|
rc = fillInCell(pPage, newCell, pX, &szNew);
|
|
if( rc ) goto end_insert;
|
|
assert( szNew==pPage->xCellSize(pPage, newCell) );
|
|
assert( szNew <= ((int)(pBt->pageSize-8)) );
|
|
idx = pCur->ix;
|
|
if( loc==0 ){
|
|
CellInfo info;
|
|
assert( idx<pPage->nCell );
|
|
rc = sqlite3PagerWrite(pPage->pDbPage);
|
|
if( rc ){
|
|
goto end_insert;
|
|
}
|
|
oldCell = ((pPage)->aData + ((pPage)->maskPage & __builtin_bswap16(*(u16*)(&(pPage)->aCellIdx[2*(idx)]))));
|
|
if( !pPage->leaf ){
|
|
memcpy(newCell, oldCell, 4);
|
|
}
|
|
rc = clearCell(pPage, oldCell, &info);
|
|
if( info.nSize==szNew && info.nLocal==info.nPayload
|
|
&& (!(pBt->autoVacuum) || szNew<pPage->minLocal)
|
|
){
|
|
# 8731 "src/btree.c"
|
|
assert( rc==0 );
|
|
if( oldCell+szNew > pPage->aDataEnd ) return sqlite3CorruptError(8732);
|
|
memcpy(oldCell, newCell, szNew);
|
|
return 0;
|
|
}
|
|
dropCell(pPage, idx, info.nSize, &rc);
|
|
if( rc ) goto end_insert;
|
|
}else if( loc<0 && pPage->nCell>0 ){
|
|
assert( pPage->leaf );
|
|
idx = ++pCur->ix;
|
|
pCur->curFlags &= ~0x02;
|
|
}else{
|
|
assert( pPage->leaf );
|
|
}
|
|
insertCell(pPage, idx, newCell, szNew, 0, 0, &rc);
|
|
assert( pPage->nOverflow==0 || rc==0 );
|
|
assert( rc!=0 || pPage->nCell>0 || pPage->nOverflow>0 );
|
|
# 8769 "src/btree.c"
|
|
pCur->info.nSize = 0;
|
|
if( pPage->nOverflow ){
|
|
assert( rc==0 );
|
|
pCur->curFlags &= ~(0x02);
|
|
rc = balance(pCur);
|
|
|
|
|
|
|
|
|
|
|
|
pCur->pPage->nOverflow = 0;
|
|
pCur->eState = 1;
|
|
if( (flags & 0x02) && rc==0 ){
|
|
btreeReleaseAllCursorPages(pCur);
|
|
if( pCur->pKeyInfo ){
|
|
assert( pCur->pKey==0 );
|
|
pCur->pKey = sqlite3Malloc( pX->nKey );
|
|
if( pCur->pKey==0 ){
|
|
rc = 7;
|
|
}else{
|
|
memcpy(pCur->pKey, pX->pKey, pX->nKey);
|
|
}
|
|
}
|
|
pCur->eState = 3;
|
|
pCur->nKey = pX->nKey;
|
|
}
|
|
}
|
|
assert( pCur->iPage<0 || pCur->pPage->nOverflow==0 );
|
|
|
|
end_insert:
|
|
return rc;
|
|
}
|
|
# 8819 "src/btree.c"
|
|
int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
|
|
Btree *p = pCur->pBtree;
|
|
BtShared *pBt = p->pBt;
|
|
int rc;
|
|
MemPage *pPage;
|
|
unsigned char *pCell;
|
|
int iCellIdx;
|
|
int iCellDepth;
|
|
CellInfo info;
|
|
int bSkipnext = 0;
|
|
u8 bPreserve = flags & 0x02;
|
|
|
|
assert( cursorOwnsBtShared(pCur) );
|
|
assert( pBt->inTransaction==2 );
|
|
assert( (pBt->btsFlags & 0x0001)==0 );
|
|
assert( pCur->curFlags & 0x01 );
|
|
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
|
|
assert( !hasReadConflicts(p, pCur->pgnoRoot) );
|
|
assert( (flags & ~(0x02 | 0x04))==0 );
|
|
if( pCur->eState==3 ){
|
|
rc = btreeRestoreCursorPosition(pCur);
|
|
if( rc ) return rc;
|
|
}
|
|
assert( pCur->eState==0 );
|
|
|
|
iCellDepth = pCur->iPage;
|
|
iCellIdx = pCur->ix;
|
|
pPage = pCur->pPage;
|
|
pCell = ((pPage)->aData + ((pPage)->maskPage & __builtin_bswap16(*(u16*)(&(pPage)->aCellIdx[2*(iCellIdx)]))));
|
|
if( pPage->nFree<0 && btreeComputeFreeSpace(pPage) ) return 11;
|
|
# 8859 "src/btree.c"
|
|
if( bPreserve ){
|
|
if( !pPage->leaf
|
|
|| (pPage->nFree+cellSizePtr(pPage,pCell)+2)>(int)(pBt->usableSize*2/3)
|
|
|| pPage->nCell==1
|
|
){
|
|
|
|
|
|
rc = saveCursorKey(pCur);
|
|
if( rc ) return rc;
|
|
}else{
|
|
bSkipnext = 1;
|
|
}
|
|
}
|
|
# 8880 "src/btree.c"
|
|
if( !pPage->leaf ){
|
|
rc = sqlite3BtreePrevious(pCur, 0);
|
|
assert( rc!=101 );
|
|
if( rc ) return rc;
|
|
}
|
|
|
|
|
|
|
|
if( pCur->curFlags & 0x20 ){
|
|
rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur);
|
|
if( rc ) return rc;
|
|
}
|
|
|
|
|
|
|
|
if( pCur->pKeyInfo==0 ){
|
|
invalidateIncrblobCursors(p, pCur->pgnoRoot, pCur->info.nKey, 0);
|
|
}
|
|
|
|
|
|
|
|
|
|
rc = sqlite3PagerWrite(pPage->pDbPage);
|
|
if( rc ) return rc;
|
|
rc = clearCell(pPage, pCell, &info);
|
|
dropCell(pPage, iCellIdx, info.nSize, &rc);
|
|
if( rc ) return rc;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( !pPage->leaf ){
|
|
MemPage *pLeaf = pCur->pPage;
|
|
int nCell;
|
|
Pgno n;
|
|
unsigned char *pTmp;
|
|
|
|
if( pLeaf->nFree<0 ){
|
|
rc = btreeComputeFreeSpace(pLeaf);
|
|
if( rc ) return rc;
|
|
}
|
|
if( iCellDepth<pCur->iPage-1 ){
|
|
n = pCur->apPage[iCellDepth+1]->pgno;
|
|
}else{
|
|
n = pCur->pPage->pgno;
|
|
}
|
|
pCell = ((pLeaf)->aData + ((pLeaf)->maskPage & __builtin_bswap16(*(u16*)(&(pLeaf)->aCellIdx[2*(pLeaf->nCell-1)]))));
|
|
if( pCell<&pLeaf->aData[4] ) return sqlite3CorruptError(8929);
|
|
nCell = pLeaf->xCellSize(pLeaf, pCell);
|
|
assert( ((int)(pBt->pageSize-8)) >= nCell );
|
|
pTmp = pBt->pTmpSpace;
|
|
assert( pTmp!=0 );
|
|
rc = sqlite3PagerWrite(pLeaf->pDbPage);
|
|
if( rc==0 ){
|
|
insertCell(pPage, iCellIdx, pCell-4, nCell+4, pTmp, n, &rc);
|
|
}
|
|
dropCell(pLeaf, pLeaf->nCell-1, nCell, &rc);
|
|
if( rc ) return rc;
|
|
}
|
|
# 8957 "src/btree.c"
|
|
rc = balance(pCur);
|
|
if( rc==0 && pCur->iPage>iCellDepth ){
|
|
releasePageNotNull(pCur->pPage);
|
|
pCur->iPage--;
|
|
while( pCur->iPage>iCellDepth ){
|
|
releasePage(pCur->apPage[pCur->iPage--]);
|
|
}
|
|
pCur->pPage = pCur->apPage[pCur->iPage];
|
|
rc = balance(pCur);
|
|
}
|
|
|
|
if( rc==0 ){
|
|
if( bSkipnext ){
|
|
assert( bPreserve && (pCur->iPage==iCellDepth || (sqlite3Config.neverCorrupt==0)) );
|
|
assert( pPage==pCur->pPage || (sqlite3Config.neverCorrupt==0) );
|
|
assert( (pPage->nCell>0 || (sqlite3Config.neverCorrupt==0)) && iCellIdx<=pPage->nCell );
|
|
pCur->eState = 2;
|
|
if( iCellIdx>=pPage->nCell ){
|
|
pCur->skipNext = -1;
|
|
pCur->ix = pPage->nCell-1;
|
|
}else{
|
|
pCur->skipNext = 1;
|
|
}
|
|
}else{
|
|
rc = moveToRoot(pCur);
|
|
if( bPreserve ){
|
|
btreeReleaseAllCursorPages(pCur);
|
|
pCur->eState = 3;
|
|
}
|
|
if( rc==16 ) rc = 0;
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
# 9003 "src/btree.c"
|
|
static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
|
|
BtShared *pBt = p->pBt;
|
|
MemPage *pRoot;
|
|
Pgno pgnoRoot;
|
|
int rc;
|
|
int ptfFlags;
|
|
|
|
assert( sqlite3BtreeHoldsMutex(p) );
|
|
assert( pBt->inTransaction==2 );
|
|
assert( (pBt->btsFlags & 0x0001)==0 );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if( pBt->autoVacuum ){
|
|
Pgno pgnoMove;
|
|
MemPage *pPageMove;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
invalidateAllOverflowCache(pBt);
|
|
|
|
|
|
|
|
|
|
|
|
sqlite3BtreeGetMeta(p, 4, &pgnoRoot);
|
|
pgnoRoot++;
|
|
|
|
|
|
|
|
|
|
while( pgnoRoot==ptrmapPageno(pBt, pgnoRoot) ||
|
|
pgnoRoot==((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) ){
|
|
pgnoRoot++;
|
|
}
|
|
assert( pgnoRoot>=3 || (sqlite3Config.neverCorrupt==0) );
|
|
;
|
|
|
|
|
|
|
|
|
|
|
|
rc = allocateBtreePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, 1);
|
|
if( rc!=0 ){
|
|
return rc;
|
|
}
|
|
|
|
if( pgnoMove!=pgnoRoot ){
|
|
|
|
|
|
|
|
|
|
|
|
|
|
u8 eType = 0;
|
|
Pgno iPtrPage = 0;
|
|
|
|
|
|
|
|
|
|
rc = saveAllCursors(pBt, 0, 0);
|
|
releasePage(pPageMove);
|
|
if( rc!=0 ){
|
|
return rc;
|
|
}
|
|
|
|
|
|
rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0);
|
|
if( rc!=0 ){
|
|
return rc;
|
|
}
|
|
rc = ptrmapGet(pBt, pgnoRoot, &eType, &iPtrPage);
|
|
if( eType==1 || eType==2 ){
|
|
rc = sqlite3CorruptError(9083);
|
|
}
|
|
if( rc!=0 ){
|
|
releasePage(pRoot);
|
|
return rc;
|
|
}
|
|
assert( eType!=1 );
|
|
assert( eType!=2 );
|
|
rc = relocatePage(pBt, pRoot, eType, iPtrPage, pgnoMove, 0);
|
|
releasePage(pRoot);
|
|
|
|
|
|
if( rc!=0 ){
|
|
return rc;
|
|
}
|
|
rc = btreeGetPage(pBt, pgnoRoot, &pRoot, 0);
|
|
if( rc!=0 ){
|
|
return rc;
|
|
}
|
|
rc = sqlite3PagerWrite(pRoot->pDbPage);
|
|
if( rc!=0 ){
|
|
releasePage(pRoot);
|
|
return rc;
|
|
}
|
|
}else{
|
|
pRoot = pPageMove;
|
|
}
|
|
|
|
|
|
ptrmapPut(pBt, pgnoRoot, 1, 0, &rc);
|
|
if( rc ){
|
|
releasePage(pRoot);
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
assert( sqlite3PagerIswriteable(pBt->pPage1->pDbPage) );
|
|
rc = sqlite3BtreeUpdateMeta(p, 4, pgnoRoot);
|
|
if( (rc) ){
|
|
releasePage(pRoot);
|
|
return rc;
|
|
}
|
|
|
|
}else{
|
|
rc = allocateBtreePage(pBt, &pRoot, &pgnoRoot, 1, 0);
|
|
if( rc ) return rc;
|
|
}
|
|
|
|
assert( sqlite3PagerIswriteable(pRoot->pDbPage) );
|
|
if( createTabFlags & 1 ){
|
|
ptfFlags = 0x01 | 0x04 | 0x08;
|
|
}else{
|
|
ptfFlags = 0x02 | 0x08;
|
|
}
|
|
zeroPage(pRoot, ptfFlags);
|
|
sqlite3PagerUnref(pRoot->pDbPage);
|
|
assert( (pBt->openFlags & 4)==0 || pgnoRoot==2 );
|
|
*piTable = (int)pgnoRoot;
|
|
return 0;
|
|
}
|
|
int sqlite3BtreeCreateTable(Btree *p, int *piTable, int flags){
|
|
int rc;
|
|
sqlite3BtreeEnter(p);
|
|
rc = btreeCreateTable(p, piTable, flags);
|
|
sqlite3BtreeLeave(p);
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int clearDatabasePage(
|
|
BtShared *pBt,
|
|
Pgno pgno,
|
|
int freePageFlag,
|
|
int *pnChange
|
|
){
|
|
MemPage *pPage;
|
|
int rc;
|
|
unsigned char *pCell;
|
|
int i;
|
|
int hdr;
|
|
CellInfo info;
|
|
|
|
assert( sqlite3_mutex_held(pBt->mutex) );
|
|
if( pgno>btreePagecount(pBt) ){
|
|
return sqlite3CorruptError(9173);
|
|
}
|
|
rc = getAndInitPage(pBt, pgno, &pPage, 0, 0);
|
|
if( rc ) return rc;
|
|
if( pPage->bBusy ){
|
|
rc = sqlite3CorruptError(9178);
|
|
goto cleardatabasepage_out;
|
|
}
|
|
pPage->bBusy = 1;
|
|
hdr = pPage->hdrOffset;
|
|
for(i=0; i<pPage->nCell; i++){
|
|
pCell = ((pPage)->aData + ((pPage)->maskPage & __builtin_bswap16(*(u16*)(&(pPage)->aCellIdx[2*(i)]))));
|
|
if( !pPage->leaf ){
|
|
rc = clearDatabasePage(pBt, sqlite3Get4byte(pCell), 1, pnChange);
|
|
if( rc ) goto cleardatabasepage_out;
|
|
}
|
|
rc = clearCell(pPage, pCell, &info);
|
|
if( rc ) goto cleardatabasepage_out;
|
|
}
|
|
if( !pPage->leaf ){
|
|
rc = clearDatabasePage(pBt, sqlite3Get4byte(&pPage->aData[hdr+8]), 1, pnChange);
|
|
if( rc ) goto cleardatabasepage_out;
|
|
}else if( pnChange ){
|
|
assert( pPage->intKey || (sqlite3Config.neverCorrupt==0) );
|
|
;
|
|
*pnChange += pPage->nCell;
|
|
}
|
|
if( freePageFlag ){
|
|
freePage(pPage, &rc);
|
|
}else if( (rc = sqlite3PagerWrite(pPage->pDbPage))==0 ){
|
|
zeroPage(pPage, pPage->aData[hdr] | 0x08);
|
|
}
|
|
|
|
cleardatabasepage_out:
|
|
pPage->bBusy = 0;
|
|
releasePage(pPage);
|
|
return rc;
|
|
}
|
|
# 9225 "src/btree.c"
|
|
int sqlite3BtreeClearTable(Btree *p, int iTable, int *pnChange){
|
|
int rc;
|
|
BtShared *pBt = p->pBt;
|
|
sqlite3BtreeEnter(p);
|
|
assert( p->inTrans==2 );
|
|
|
|
rc = saveAllCursors(pBt, (Pgno)iTable, 0);
|
|
|
|
if( 0==rc ){
|
|
|
|
|
|
|
|
invalidateIncrblobCursors(p, (Pgno)iTable, 0, 1);
|
|
rc = clearDatabasePage(pBt, (Pgno)iTable, 0, pnChange);
|
|
}
|
|
sqlite3BtreeLeave(p);
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int sqlite3BtreeClearTableOfCursor(BtCursor *pCur){
|
|
return sqlite3BtreeClearTable(pCur->pBtree, pCur->pgnoRoot, 0);
|
|
}
|
|
# 9273 "src/btree.c"
|
|
static int btreeDropTable(Btree *p, Pgno iTable, int *piMoved){
|
|
int rc;
|
|
MemPage *pPage = 0;
|
|
BtShared *pBt = p->pBt;
|
|
|
|
assert( sqlite3BtreeHoldsMutex(p) );
|
|
assert( p->inTrans==2 );
|
|
assert( iTable>=2 );
|
|
if( iTable>btreePagecount(pBt) ){
|
|
return sqlite3CorruptError(9282);
|
|
}
|
|
|
|
rc = btreeGetPage(pBt, (Pgno)iTable, &pPage, 0);
|
|
if( rc ) return rc;
|
|
rc = sqlite3BtreeClearTable(p, iTable, 0);
|
|
if( rc ){
|
|
releasePage(pPage);
|
|
return rc;
|
|
}
|
|
|
|
*piMoved = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if( pBt->autoVacuum ){
|
|
Pgno maxRootPgno;
|
|
sqlite3BtreeGetMeta(p, 4, &maxRootPgno);
|
|
|
|
if( iTable==maxRootPgno ){
|
|
|
|
|
|
|
|
freePage(pPage, &rc);
|
|
releasePage(pPage);
|
|
if( rc!=0 ){
|
|
return rc;
|
|
}
|
|
}else{
|
|
|
|
|
|
|
|
|
|
MemPage *pMove;
|
|
releasePage(pPage);
|
|
rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
|
|
if( rc!=0 ){
|
|
return rc;
|
|
}
|
|
rc = relocatePage(pBt, pMove, 1, 0, iTable, 0);
|
|
releasePage(pMove);
|
|
if( rc!=0 ){
|
|
return rc;
|
|
}
|
|
pMove = 0;
|
|
rc = btreeGetPage(pBt, maxRootPgno, &pMove, 0);
|
|
freePage(pMove, &rc);
|
|
releasePage(pMove);
|
|
if( rc!=0 ){
|
|
return rc;
|
|
}
|
|
*piMoved = maxRootPgno;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
maxRootPgno--;
|
|
while( maxRootPgno==((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1))
|
|
|| (ptrmapPageno((pBt), (maxRootPgno))==(maxRootPgno)) ){
|
|
maxRootPgno--;
|
|
}
|
|
assert( maxRootPgno!=((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1)) );
|
|
|
|
rc = sqlite3BtreeUpdateMeta(p, 4, maxRootPgno);
|
|
}else{
|
|
freePage(pPage, &rc);
|
|
releasePage(pPage);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
int sqlite3BtreeDropTable(Btree *p, int iTable, int *piMoved){
|
|
int rc;
|
|
sqlite3BtreeEnter(p);
|
|
rc = btreeDropTable(p, iTable, piMoved);
|
|
sqlite3BtreeLeave(p);
|
|
return rc;
|
|
}
|
|
# 9387 "src/btree.c"
|
|
void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){
|
|
BtShared *pBt = p->pBt;
|
|
|
|
sqlite3BtreeEnter(p);
|
|
assert( p->inTrans>0 );
|
|
assert( 0==querySharedCacheTableLock(p, 1, 1) );
|
|
assert( pBt->pPage1 );
|
|
assert( idx>=0 && idx<=15 );
|
|
|
|
if( idx==15 ){
|
|
*pMeta = sqlite3PagerDataVersion(pBt->pPager) + p->iDataVersion;
|
|
}else{
|
|
*pMeta = sqlite3Get4byte(&pBt->pPage1->aData[36 + idx*4]);
|
|
}
|
|
# 9410 "src/btree.c"
|
|
sqlite3BtreeLeave(p);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int sqlite3BtreeUpdateMeta(Btree *p, int idx, u32 iMeta){
|
|
BtShared *pBt = p->pBt;
|
|
unsigned char *pP1;
|
|
int rc;
|
|
assert( idx>=1 && idx<=15 );
|
|
sqlite3BtreeEnter(p);
|
|
assert( p->inTrans==2 );
|
|
assert( pBt->pPage1!=0 );
|
|
pP1 = pBt->pPage1->aData;
|
|
rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
|
|
if( rc==0 ){
|
|
sqlite3Put4byte(&pP1[36 + idx*4], iMeta);
|
|
|
|
if( idx==7 ){
|
|
assert( pBt->autoVacuum || iMeta==0 );
|
|
assert( iMeta==0 || iMeta==1 );
|
|
pBt->incrVacuum = (u8)iMeta;
|
|
}
|
|
|
|
}
|
|
sqlite3BtreeLeave(p);
|
|
return rc;
|
|
}
|
|
# 9450 "src/btree.c"
|
|
int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
|
|
i64 nEntry = 0;
|
|
int rc;
|
|
|
|
rc = moveToRoot(pCur);
|
|
if( rc==16 ){
|
|
*pnEntry = 0;
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
while( rc==0 ){
|
|
int iIdx;
|
|
MemPage *pPage;
|
|
|
|
|
|
|
|
|
|
|
|
pPage = pCur->pPage;
|
|
if( pPage->leaf || !pPage->intKey ){
|
|
nEntry += pPage->nCell;
|
|
}
|
|
# 9486 "src/btree.c"
|
|
if( pPage->leaf ){
|
|
do {
|
|
if( pCur->iPage==0 ){
|
|
|
|
*pnEntry = nEntry;
|
|
return moveToRoot(pCur);
|
|
}
|
|
moveToParent(pCur);
|
|
}while ( pCur->ix>=pCur->pPage->nCell );
|
|
|
|
pCur->ix++;
|
|
pPage = pCur->pPage;
|
|
}
|
|
|
|
|
|
|
|
|
|
iIdx = pCur->ix;
|
|
if( iIdx==pPage->nCell ){
|
|
rc = moveToChild(pCur, sqlite3Get4byte(&pPage->aData[pPage->hdrOffset+8]));
|
|
}else{
|
|
rc = moveToChild(pCur, sqlite3Get4byte(((pPage)->aData + ((pPage)->maskPage & __builtin_bswap16(*(u16*)(&(pPage)->aCellIdx[2*(iIdx)]))))));
|
|
}
|
|
}
|
|
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Pager *sqlite3BtreePager(Btree *p){
|
|
return p->pBt->pPager;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void checkAppendMsg(
|
|
IntegrityCk *pCheck,
|
|
const char *zFormat,
|
|
...
|
|
){
|
|
va_list ap;
|
|
if( !pCheck->mxErr ) return;
|
|
pCheck->mxErr--;
|
|
pCheck->nErr++;
|
|
__builtin_va_start((ap));
|
|
if( pCheck->errMsg.nChar ){
|
|
sqlite3_str_append(&pCheck->errMsg, "\n", 1);
|
|
}
|
|
if( pCheck->zPfx ){
|
|
sqlite3_str_appendf(&pCheck->errMsg, pCheck->zPfx, pCheck->v1, pCheck->v2);
|
|
}
|
|
sqlite3_str_vappendf(&pCheck->errMsg, zFormat, ap);
|
|
;
|
|
if( pCheck->errMsg.accError==7 ){
|
|
pCheck->mallocFailed = 1;
|
|
}
|
|
}
|
|
# 9558 "src/btree.c"
|
|
static int getPageReferenced(IntegrityCk *pCheck, Pgno iPg){
|
|
assert( iPg<=pCheck->nPage && sizeof(pCheck->aPgRef[0])==1 );
|
|
return (pCheck->aPgRef[iPg/8] & (1 << (iPg & 0x07)));
|
|
}
|
|
|
|
|
|
|
|
|
|
static void setPageReferenced(IntegrityCk *pCheck, Pgno iPg){
|
|
assert( iPg<=pCheck->nPage && sizeof(pCheck->aPgRef[0])==1 );
|
|
pCheck->aPgRef[iPg/8] |= (1 << (iPg & 0x07));
|
|
}
|
|
# 9580 "src/btree.c"
|
|
static int checkRef(IntegrityCk *pCheck, Pgno iPage){
|
|
if( iPage>pCheck->nPage || iPage==0 ){
|
|
checkAppendMsg(pCheck, "invalid page number %d", iPage);
|
|
return 1;
|
|
}
|
|
if( getPageReferenced(pCheck, iPage) ){
|
|
checkAppendMsg(pCheck, "2nd reference to page %d", iPage);
|
|
return 1;
|
|
}
|
|
setPageReferenced(pCheck, iPage);
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void checkPtrmap(
|
|
IntegrityCk *pCheck,
|
|
Pgno iChild,
|
|
u8 eType,
|
|
Pgno iParent
|
|
){
|
|
int rc;
|
|
u8 ePtrmapType;
|
|
Pgno iPtrmapParent;
|
|
|
|
rc = ptrmapGet(pCheck->pBt, iChild, &ePtrmapType, &iPtrmapParent);
|
|
if( rc!=0 ){
|
|
if( rc==7 || rc==(10 | (12<<8)) ) pCheck->mallocFailed = 1;
|
|
checkAppendMsg(pCheck, "Failed to read ptrmap key=%d", iChild);
|
|
return;
|
|
}
|
|
|
|
if( ePtrmapType!=eType || iPtrmapParent!=iParent ){
|
|
checkAppendMsg(pCheck,
|
|
"Bad ptr map entry key=%d expected=(%d,%d) got=(%d,%d)",
|
|
iChild, eType, iParent, ePtrmapType, iPtrmapParent);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void checkList(
|
|
IntegrityCk *pCheck,
|
|
int isFreeList,
|
|
int iPage,
|
|
u32 N
|
|
){
|
|
int i;
|
|
u32 expected = N;
|
|
int nErrAtStart = pCheck->nErr;
|
|
while( iPage!=0 && pCheck->mxErr ){
|
|
DbPage *pOvflPage;
|
|
unsigned char *pOvflData;
|
|
if( checkRef(pCheck, iPage) ) break;
|
|
N--;
|
|
if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage, 0) ){
|
|
checkAppendMsg(pCheck, "failed to get page %d", iPage);
|
|
break;
|
|
}
|
|
pOvflData = (unsigned char *)sqlite3PagerGetData(pOvflPage);
|
|
if( isFreeList ){
|
|
u32 n = (u32)sqlite3Get4byte(&pOvflData[4]);
|
|
|
|
if( pCheck->pBt->autoVacuum ){
|
|
checkPtrmap(pCheck, iPage, 2, 0);
|
|
}
|
|
|
|
if( n>pCheck->pBt->usableSize/4-2 ){
|
|
checkAppendMsg(pCheck,
|
|
"freelist leaf count too big on page %d", iPage);
|
|
N--;
|
|
}else{
|
|
for(i=0; i<(int)n; i++){
|
|
Pgno iFreePage = sqlite3Get4byte(&pOvflData[8+i*4]);
|
|
|
|
if( pCheck->pBt->autoVacuum ){
|
|
checkPtrmap(pCheck, iFreePage, 2, 0);
|
|
}
|
|
|
|
checkRef(pCheck, iFreePage);
|
|
}
|
|
N -= n;
|
|
}
|
|
}
|
|
|
|
else{
|
|
|
|
|
|
|
|
|
|
if( pCheck->pBt->autoVacuum && N>0 ){
|
|
i = sqlite3Get4byte(pOvflData);
|
|
checkPtrmap(pCheck, i, 4, iPage);
|
|
}
|
|
}
|
|
|
|
iPage = sqlite3Get4byte(pOvflData);
|
|
sqlite3PagerUnref(pOvflPage);
|
|
}
|
|
if( N && nErrAtStart==pCheck->nErr ){
|
|
checkAppendMsg(pCheck,
|
|
"%s is %d but should be %d",
|
|
isFreeList ? "size" : "overflow list length",
|
|
expected-N, expected);
|
|
}
|
|
}
|
|
# 9717 "src/btree.c"
|
|
static void btreeHeapInsert(u32 *aHeap, u32 x){
|
|
u32 j, i = ++aHeap[0];
|
|
aHeap[i] = x;
|
|
while( (j = i/2)>0 && aHeap[j]>aHeap[i] ){
|
|
x = aHeap[j];
|
|
aHeap[j] = aHeap[i];
|
|
aHeap[i] = x;
|
|
i = j;
|
|
}
|
|
}
|
|
static int btreeHeapPull(u32 *aHeap, u32 *pOut){
|
|
u32 j, i, x;
|
|
if( (x = aHeap[0])==0 ) return 0;
|
|
*pOut = aHeap[1];
|
|
aHeap[1] = aHeap[x];
|
|
aHeap[x] = 0xffffffff;
|
|
aHeap[0]--;
|
|
i = 1;
|
|
while( (j = i*2)<=aHeap[0] ){
|
|
if( aHeap[j]>aHeap[j+1] ) j++;
|
|
if( aHeap[i]<aHeap[j] ) break;
|
|
x = aHeap[i];
|
|
aHeap[i] = aHeap[j];
|
|
aHeap[j] = x;
|
|
i = j;
|
|
}
|
|
return 1;
|
|
}
|
|
# 9761 "src/btree.c"
|
|
static int checkTreePage(
|
|
IntegrityCk *pCheck,
|
|
int iPage,
|
|
i64 *piMinKey,
|
|
i64 maxKey
|
|
){
|
|
MemPage *pPage = 0;
|
|
int i;
|
|
int rc;
|
|
int depth = -1, d2;
|
|
int pgno;
|
|
int nFrag;
|
|
int hdr;
|
|
int cellStart;
|
|
int nCell;
|
|
int doCoverageCheck = 1;
|
|
int keyCanBeEqual = 1;
|
|
|
|
u8 *data;
|
|
u8 *pCell;
|
|
u8 *pCellIdx;
|
|
BtShared *pBt;
|
|
u32 pc;
|
|
u32 usableSize;
|
|
u32 contentOffset;
|
|
u32 *heap = 0;
|
|
u32 x, prev = 0;
|
|
const char *saved_zPfx = pCheck->zPfx;
|
|
int saved_v1 = pCheck->v1;
|
|
int saved_v2 = pCheck->v2;
|
|
u8 savedIsInit = 0;
|
|
|
|
|
|
|
|
pBt = pCheck->pBt;
|
|
usableSize = pBt->usableSize;
|
|
if( iPage==0 ) return 0;
|
|
if( checkRef(pCheck, iPage) ) return 0;
|
|
pCheck->zPfx = "Page %d: ";
|
|
pCheck->v1 = iPage;
|
|
if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){
|
|
checkAppendMsg(pCheck,
|
|
"unable to get the page. error code=%d", rc);
|
|
goto end_of_check;
|
|
}
|
|
|
|
|
|
|
|
savedIsInit = pPage->isInit;
|
|
pPage->isInit = 0;
|
|
if( (rc = btreeInitPage(pPage))!=0 ){
|
|
assert( rc==11 );
|
|
checkAppendMsg(pCheck,
|
|
"btreeInitPage() returns error code %d", rc);
|
|
goto end_of_check;
|
|
}
|
|
if( (rc = btreeComputeFreeSpace(pPage))!=0 ){
|
|
assert( rc==11 );
|
|
checkAppendMsg(pCheck, "free space corruption", rc);
|
|
goto end_of_check;
|
|
}
|
|
data = pPage->aData;
|
|
hdr = pPage->hdrOffset;
|
|
|
|
|
|
pCheck->zPfx = "On tree page %d cell %d: ";
|
|
contentOffset = (((((int)((&data[hdr+5])[0]<<8 | (&data[hdr+5])[1]))-1)&0xffff)+1);
|
|
assert( contentOffset<=usableSize );
|
|
|
|
|
|
|
|
nCell = ((&data[hdr+3])[0]<<8 | (&data[hdr+3])[1]);
|
|
assert( pPage->nCell==nCell );
|
|
|
|
|
|
|
|
cellStart = hdr + 12 - 4*pPage->leaf;
|
|
assert( pPage->aCellIdx==&data[cellStart] );
|
|
pCellIdx = &data[cellStart + 2*(nCell-1)];
|
|
|
|
if( !pPage->leaf ){
|
|
|
|
pgno = sqlite3Get4byte(&data[hdr+8]);
|
|
|
|
if( pBt->autoVacuum ){
|
|
pCheck->zPfx = "On page %d at right child: ";
|
|
checkPtrmap(pCheck, pgno, 5, iPage);
|
|
}
|
|
|
|
depth = checkTreePage(pCheck, pgno, &maxKey, maxKey);
|
|
keyCanBeEqual = 0;
|
|
}else{
|
|
|
|
|
|
heap = pCheck->heap;
|
|
heap[0] = 0;
|
|
}
|
|
|
|
|
|
|
|
for(i=nCell-1; i>=0 && pCheck->mxErr; i--){
|
|
CellInfo info;
|
|
|
|
|
|
pCheck->v2 = i;
|
|
assert( pCellIdx==&data[cellStart + i*2] );
|
|
pc = __builtin_bswap16(*(u16*)(pCellIdx));
|
|
pCellIdx -= 2;
|
|
if( pc<contentOffset || pc>usableSize-4 ){
|
|
checkAppendMsg(pCheck, "Offset %d out of range %d..%d",
|
|
pc, contentOffset, usableSize-4);
|
|
doCoverageCheck = 0;
|
|
continue;
|
|
}
|
|
pCell = &data[pc];
|
|
pPage->xParseCell(pPage, pCell, &info);
|
|
if( pc+info.nSize>usableSize ){
|
|
checkAppendMsg(pCheck, "Extends off end of page");
|
|
doCoverageCheck = 0;
|
|
continue;
|
|
}
|
|
|
|
|
|
if( pPage->intKey ){
|
|
if( keyCanBeEqual ? (info.nKey > maxKey) : (info.nKey >= maxKey) ){
|
|
checkAppendMsg(pCheck, "Rowid %lld out of order", info.nKey);
|
|
}
|
|
maxKey = info.nKey;
|
|
keyCanBeEqual = 0;
|
|
}
|
|
|
|
|
|
if( info.nPayload>info.nLocal ){
|
|
u32 nPage;
|
|
Pgno pgnoOvfl;
|
|
assert( pc + info.nSize - 4 <= usableSize );
|
|
nPage = (info.nPayload - info.nLocal + usableSize - 5)/(usableSize - 4);
|
|
pgnoOvfl = sqlite3Get4byte(&pCell[info.nSize - 4]);
|
|
|
|
if( pBt->autoVacuum ){
|
|
checkPtrmap(pCheck, pgnoOvfl, 3, iPage);
|
|
}
|
|
|
|
checkList(pCheck, 0, pgnoOvfl, nPage);
|
|
}
|
|
|
|
if( !pPage->leaf ){
|
|
|
|
pgno = sqlite3Get4byte(pCell);
|
|
|
|
if( pBt->autoVacuum ){
|
|
checkPtrmap(pCheck, pgno, 5, iPage);
|
|
}
|
|
|
|
d2 = checkTreePage(pCheck, pgno, &maxKey, maxKey);
|
|
keyCanBeEqual = 0;
|
|
if( d2!=depth ){
|
|
checkAppendMsg(pCheck, "Child page depth differs");
|
|
depth = d2;
|
|
}
|
|
}else{
|
|
|
|
btreeHeapInsert(heap, (pc<<16)|(pc+info.nSize-1));
|
|
}
|
|
}
|
|
*piMinKey = maxKey;
|
|
|
|
|
|
|
|
pCheck->zPfx = 0;
|
|
if( doCoverageCheck && pCheck->mxErr>0 ){
|
|
|
|
|
|
|
|
if( !pPage->leaf ){
|
|
heap = pCheck->heap;
|
|
heap[0] = 0;
|
|
for(i=nCell-1; i>=0; i--){
|
|
u32 size;
|
|
pc = __builtin_bswap16(*(u16*)(&data[cellStart+i*2]));
|
|
size = pPage->xCellSize(pPage, &data[pc]);
|
|
btreeHeapInsert(heap, (pc<<16)|(pc+size-1));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
i = ((&data[hdr+1])[0]<<8 | (&data[hdr+1])[1]);
|
|
while( i>0 ){
|
|
int size, j;
|
|
assert( (u32)i<=usableSize-4 );
|
|
size = ((&data[i+2])[0]<<8 | (&data[i+2])[1]);
|
|
assert( (u32)(i+size)<=usableSize );
|
|
btreeHeapInsert(heap, (((u32)i)<<16)|(i+size-1));
|
|
|
|
|
|
|
|
|
|
j = ((&data[i])[0]<<8 | (&data[i])[1]);
|
|
|
|
|
|
assert( j==0 || j>i+size );
|
|
assert( (u32)j<=usableSize-4 );
|
|
i = j;
|
|
}
|
|
# 9982 "src/btree.c"
|
|
nFrag = 0;
|
|
prev = contentOffset - 1;
|
|
while( btreeHeapPull(heap,&x) ){
|
|
if( (prev&0xffff)>=(x>>16) ){
|
|
checkAppendMsg(pCheck,
|
|
"Multiple uses for byte %u of page %d", x>>16, iPage);
|
|
break;
|
|
}else{
|
|
nFrag += (x>>16) - (prev&0xffff) - 1;
|
|
prev = x;
|
|
}
|
|
}
|
|
nFrag += usableSize - (prev&0xffff) - 1;
|
|
|
|
|
|
|
|
|
|
|
|
if( heap[0]==0 && nFrag!=data[hdr+7] ){
|
|
checkAppendMsg(pCheck,
|
|
"Fragmentation of %d bytes reported as %d on page %d",
|
|
nFrag, data[hdr+7], iPage);
|
|
}
|
|
}
|
|
|
|
end_of_check:
|
|
if( !doCoverageCheck ) pPage->isInit = savedIsInit;
|
|
releasePage(pPage);
|
|
pCheck->zPfx = saved_zPfx;
|
|
pCheck->v1 = saved_v1;
|
|
pCheck->v2 = saved_v2;
|
|
return depth+1;
|
|
}
|
|
# 10031 "src/btree.c"
|
|
char *sqlite3BtreeIntegrityCheck(
|
|
Btree *p,
|
|
int *aRoot,
|
|
int nRoot,
|
|
int mxErr,
|
|
int *pnErr
|
|
){
|
|
Pgno i;
|
|
IntegrityCk sCheck;
|
|
BtShared *pBt = p->pBt;
|
|
u64 savedDbFlags = pBt->db->flags;
|
|
char zErr[100];
|
|
;
|
|
|
|
sqlite3BtreeEnter(p);
|
|
assert( p->inTrans>0 && pBt->inTransaction>0 );
|
|
;
|
|
assert( nRef>=0 );
|
|
sCheck.pBt = pBt;
|
|
sCheck.pPager = pBt->pPager;
|
|
sCheck.nPage = btreePagecount(sCheck.pBt);
|
|
sCheck.mxErr = mxErr;
|
|
sCheck.nErr = 0;
|
|
sCheck.mallocFailed = 0;
|
|
sCheck.zPfx = 0;
|
|
sCheck.v1 = 0;
|
|
sCheck.v2 = 0;
|
|
sCheck.aPgRef = 0;
|
|
sCheck.heap = 0;
|
|
sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), 1000000000);
|
|
sCheck.errMsg.printfFlags = 0x01;
|
|
if( sCheck.nPage==0 ){
|
|
goto integrity_ck_cleanup;
|
|
}
|
|
|
|
sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1);
|
|
if( !sCheck.aPgRef ){
|
|
sCheck.mallocFailed = 1;
|
|
goto integrity_ck_cleanup;
|
|
}
|
|
sCheck.heap = (u32*)sqlite3PageMalloc( pBt->pageSize );
|
|
if( sCheck.heap==0 ){
|
|
sCheck.mallocFailed = 1;
|
|
goto integrity_ck_cleanup;
|
|
}
|
|
|
|
i = ((Pgno)((sqlite3PendingByte/((pBt)->pageSize))+1));
|
|
if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i);
|
|
|
|
|
|
|
|
sCheck.zPfx = "Main freelist: ";
|
|
checkList(&sCheck, 1, sqlite3Get4byte(&pBt->pPage1->aData[32]),
|
|
sqlite3Get4byte(&pBt->pPage1->aData[36]));
|
|
sCheck.zPfx = 0;
|
|
|
|
|
|
|
|
|
|
if( pBt->autoVacuum ){
|
|
int mx = 0;
|
|
int mxInHdr;
|
|
for(i=0; (int)i<nRoot; i++) if( mx<aRoot[i] ) mx = aRoot[i];
|
|
mxInHdr = sqlite3Get4byte(&pBt->pPage1->aData[52]);
|
|
if( mx!=mxInHdr ){
|
|
checkAppendMsg(&sCheck,
|
|
"max rootpage (%d) disagrees with header (%d)",
|
|
mx, mxInHdr
|
|
);
|
|
}
|
|
}else if( sqlite3Get4byte(&pBt->pPage1->aData[64])!=0 ){
|
|
checkAppendMsg(&sCheck,
|
|
"incremental_vacuum enabled with a max rootpage of zero"
|
|
);
|
|
}
|
|
|
|
;
|
|
pBt->db->flags &= ~(u64)0x00200000;
|
|
for(i=0; (int)i<nRoot && sCheck.mxErr; i++){
|
|
i64 notUsed;
|
|
if( aRoot[i]==0 ) continue;
|
|
|
|
if( pBt->autoVacuum && aRoot[i]>1 ){
|
|
checkPtrmap(&sCheck, aRoot[i], 1, 0);
|
|
}
|
|
|
|
checkTreePage(&sCheck, aRoot[i], ¬Used, (0xffffffff|(((i64)0x7fffffff)<<32)));
|
|
}
|
|
pBt->db->flags = savedDbFlags;
|
|
|
|
|
|
|
|
for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){
|
|
# 10132 "src/btree.c"
|
|
if( getPageReferenced(&sCheck, i)==0 &&
|
|
(ptrmapPageno(pBt, i)!=i || !pBt->autoVacuum) ){
|
|
checkAppendMsg(&sCheck, "Page %d is never used", i);
|
|
}
|
|
if( getPageReferenced(&sCheck, i)!=0 &&
|
|
(ptrmapPageno(pBt, i)==i && pBt->autoVacuum) ){
|
|
checkAppendMsg(&sCheck, "Pointer map page %d is referenced", i);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
integrity_ck_cleanup:
|
|
sqlite3PageFree(sCheck.heap);
|
|
sqlite3_free(sCheck.aPgRef);
|
|
if( sCheck.mallocFailed ){
|
|
sqlite3_str_reset(&sCheck.errMsg);
|
|
sCheck.nErr++;
|
|
}
|
|
*pnErr = sCheck.nErr;
|
|
if( sCheck.nErr==0 ) sqlite3_str_reset(&sCheck.errMsg);
|
|
|
|
assert( nRef==sqlite3PagerRefcount(pBt->pPager) );
|
|
sqlite3BtreeLeave(p);
|
|
return sqlite3StrAccumFinish(&sCheck.errMsg);
|
|
}
|
|
# 10168 "src/btree.c"
|
|
const char *sqlite3BtreeGetFilename(Btree *p){
|
|
assert( p->pBt->pPager!=0 );
|
|
return sqlite3PagerFilename(p->pBt->pPager, 1);
|
|
}
|
|
# 10181 "src/btree.c"
|
|
const char *sqlite3BtreeGetJournalname(Btree *p){
|
|
assert( p->pBt->pPager!=0 );
|
|
return sqlite3PagerJournalname(p->pBt->pPager);
|
|
}
|
|
|
|
|
|
|
|
|
|
int sqlite3BtreeIsInTrans(Btree *p){
|
|
assert( p==0 || sqlite3_mutex_held(p->db->mutex) );
|
|
return (p && (p->inTrans==2));
|
|
}
|
|
# 10203 "src/btree.c"
|
|
int sqlite3BtreeCheckpoint(Btree *p, int eMode, int *pnLog, int *pnCkpt){
|
|
int rc = 0;
|
|
if( p ){
|
|
BtShared *pBt = p->pBt;
|
|
sqlite3BtreeEnter(p);
|
|
if( pBt->inTransaction!=0 ){
|
|
rc = 6;
|
|
}else{
|
|
rc = sqlite3PagerCheckpoint(pBt->pPager, p->db, eMode, pnLog, pnCkpt);
|
|
}
|
|
sqlite3BtreeLeave(p);
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int sqlite3BtreeIsInReadTrans(Btree *p){
|
|
assert( p );
|
|
assert( sqlite3_mutex_held(p->db->mutex) );
|
|
return p->inTrans!=0;
|
|
}
|
|
|
|
int sqlite3BtreeIsInBackup(Btree *p){
|
|
assert( p );
|
|
assert( sqlite3_mutex_held(p->db->mutex) );
|
|
return p->nBackup!=0;
|
|
}
|
|
# 10254 "src/btree.c"
|
|
void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){
|
|
BtShared *pBt = p->pBt;
|
|
sqlite3BtreeEnter(p);
|
|
if( !pBt->pSchema && nBytes ){
|
|
pBt->pSchema = sqlite3DbMallocZero(0, nBytes);
|
|
pBt->xFreeSchema = xFree;
|
|
}
|
|
sqlite3BtreeLeave(p);
|
|
return pBt->pSchema;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int sqlite3BtreeSchemaLocked(Btree *p){
|
|
int rc;
|
|
assert( sqlite3_mutex_held(p->db->mutex) );
|
|
sqlite3BtreeEnter(p);
|
|
rc = querySharedCacheTableLock(p, 1, 1);
|
|
assert( rc==0 || rc==(6 | (1<<8)) );
|
|
sqlite3BtreeLeave(p);
|
|
return rc;
|
|
}
|
|
# 10287 "src/btree.c"
|
|
int sqlite3BtreeLockTable(Btree *p, int iTab, u8 isWriteLock){
|
|
int rc = 0;
|
|
assert( p->inTrans!=0 );
|
|
if( p->sharable ){
|
|
u8 lockType = 1 + isWriteLock;
|
|
assert( 1 +1==2 );
|
|
assert( isWriteLock==0 || isWriteLock==1 );
|
|
|
|
sqlite3BtreeEnter(p);
|
|
rc = querySharedCacheTableLock(p, iTab, lockType);
|
|
if( rc==0 ){
|
|
rc = setSharedCacheTableLock(p, iTab, lockType);
|
|
}
|
|
sqlite3BtreeLeave(p);
|
|
}
|
|
return rc;
|
|
}
|
|
# 10317 "src/btree.c"
|
|
int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){
|
|
int rc;
|
|
assert( cursorOwnsBtShared(pCsr) );
|
|
assert( sqlite3_mutex_held(pCsr->pBtree->db->mutex) );
|
|
assert( pCsr->curFlags & 0x10 );
|
|
|
|
rc = (pCsr->eState>=3 ? btreeRestoreCursorPosition(pCsr) : 0);
|
|
if( rc!=0 ){
|
|
return rc;
|
|
}
|
|
assert( pCsr->eState!=3 );
|
|
if( pCsr->eState!=0 ){
|
|
return 4;
|
|
}
|
|
# 10340 "src/btree.c"
|
|
saveAllCursors(pCsr->pBt, pCsr->pgnoRoot, pCsr);
|
|
assert( rc==0 );
|
|
# 10350 "src/btree.c"
|
|
if( (pCsr->curFlags & 0x01)==0 ){
|
|
return 8;
|
|
}
|
|
assert( (pCsr->pBt->btsFlags & 0x0001)==0
|
|
&& pCsr->pBt->inTransaction==2 );
|
|
assert( hasSharedCacheTableLock(pCsr->pBtree, pCsr->pgnoRoot, 0, 2) );
|
|
assert( !hasReadConflicts(pCsr->pBtree, pCsr->pgnoRoot) );
|
|
assert( pCsr->pPage->intKey );
|
|
|
|
return accessPayload(pCsr, offset, amt, (unsigned char *)z, 1);
|
|
}
|
|
|
|
|
|
|
|
|
|
void sqlite3BtreeIncrblobCursor(BtCursor *pCur){
|
|
pCur->curFlags |= 0x10;
|
|
pCur->pBtree->hasIncrblobCur = 1;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
|
|
BtShared *pBt = pBtree->pBt;
|
|
int rc;
|
|
|
|
assert( iVersion==1 || iVersion==2 );
|
|
|
|
|
|
|
|
|
|
pBt->btsFlags &= ~0x0020;
|
|
if( iVersion==1 ) pBt->btsFlags |= 0x0020;
|
|
|
|
rc = sqlite3BtreeBeginTrans(pBtree, 0, 0);
|
|
if( rc==0 ){
|
|
u8 *aData = pBt->pPage1->aData;
|
|
if( aData[18]!=(u8)iVersion || aData[19]!=(u8)iVersion ){
|
|
rc = sqlite3BtreeBeginTrans(pBtree, 2, 0);
|
|
if( rc==0 ){
|
|
rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
|
|
if( rc==0 ){
|
|
aData[18] = (u8)iVersion;
|
|
aData[19] = (u8)iVersion;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pBt->btsFlags &= ~0x0020;
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int sqlite3BtreeCursorHasHint(BtCursor *pCsr, unsigned int mask){
|
|
return (pCsr->hints & mask)!=0;
|
|
}
|
|
|
|
|
|
|
|
|
|
int sqlite3BtreeIsReadonly(Btree *p){
|
|
return (p->pBt->btsFlags & 0x0001)!=0;
|
|
}
|
|
|
|
|
|
|
|
|
|
int sqlite3HeaderSizeBtree(void){ return (((sizeof(MemPage))+7)&~7); }
|
|
|
|
|
|
|
|
|
|
|
|
int sqlite3BtreeSharable(Btree *p){
|
|
return p->sharable;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int sqlite3BtreeConnectionCount(Btree *p){
|
|
;
|
|
return p->pBt->nRef;
|
|
}
|