| # 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; |
| } |