// Code generated by modernc.org/undup from the per-target sqlite_*.go files; DO NOT EDIT. //go:build (darwin && amd64) || (darwin && arm64) || (freebsd && 386) || (freebsd && amd64) || (freebsd && arm) || (freebsd && arm64) || (linux && 386) || (linux && amd64) || (linux && arm) || (linux && arm64) || (linux && loong64) || (linux && ppc64le) || (linux && riscv64) || (linux && s390x) || (netbsd && amd64) || (openbsd && amd64) || (openbsd && arm64) package sqlite3 import ( "unsafe" "modernc.org/libc" ) const BIG_ENDIAN = 4321 const BUFSIZ = 1024 const DOTLOCK_SUFFIX = ".lock" type DbPath = TDbPath type Dl_info = TDl_info const ENOTBLK = 15 const ETXTBSY = 26 const FD_CLOEXEC = 1 const F_DUPFD = 0 const F_GETFD = 1 const F_GETFL = 3 const F_LOCK = 1 const F_OK = 0 const F_SETFD = 2 const F_SETFL = 4 const F_TEST = 3 const F_TLOCK = 2 const F_ULOCK = 0 const F_UNLCK = 2 const HAVE_FCHMOD = 1 const HAVE_GETHOSTUUID = 0 const INTERFACE = 1 const ITIMER_PROF = 2 const ITIMER_REAL = 0 const ITIMER_VIRTUAL = 1 const LITTLE_ENDIAN = 1234 const L_INCR = 1 const L_SET = 0 const L_XTND = 2 const MADV_DONTNEED = 4 const MADV_NORMAL = 0 const MADV_RANDOM = 1 const MADV_SEQUENTIAL = 2 const MADV_WILLNEED = 3 const MAP_FAILED = -1 const MAP_FILE = 0 const MAP_FIXED = 16 const MAP_PRIVATE = 2 const MAP_SHARED = 1 const MATH_ERREXCEPT = 2 const MATH_ERRNO = 1 const MAX_PATHNAME = 512 const MS_ASYNC = 1 const O_BINARY = 0 const O_RDONLY = 0 const O_RDWR = 2 const O_WRONLY = 1 const PDP_ENDIAN = 3412 const POSIX_MADV_DONTNEED = 4 const POSIX_MADV_NORMAL = 0 const POSIX_MADV_RANDOM = 1 const POSIX_MADV_SEQUENTIAL = 2 const POSIX_MADV_WILLNEED = 3 const PROT_EXEC = 4 const PROT_NONE = 0 const PROT_READ = 1 const PROT_WRITE = 2 const RAND_MAX = 2147483647 const RTLD_LAZY = 1 const RTLD_NEXT = -1 const RTLD_NOW = 2 const R_OK = 4 const SQLITE_DEFAULT_FILE_PERMISSIONS = 420 const SQLITE_DEFAULT_PROXYDIR_PERMISSIONS = 493 const SQLITE_FSFLAGS_IS_MSDOS = 1 const SQLITE_MAX_SYMLINKS = 100 const SQLITE_MINIMUM_FILE_DESCRIPTOR = 3 const SQLITE_OS_UNIX = 1 const S_IEXEC = 64 const S_IFBLK = 24576 const S_IFCHR = 8192 const S_IFDIR = 16384 const S_IFIFO = 4096 const S_IFLNK = 40960 const S_IFMT = 61440 const S_IFREG = 32768 const S_IFSOCK = 49152 const S_IREAD = 256 const S_IRGRP = 32 const S_IROTH = 4 const S_IRUSR = 256 const S_IRWXG = 56 const S_IRWXO = 7 const S_IRWXU = 448 const S_ISGID = 1024 const S_ISUID = 2048 const S_ISVTX = 512 const S_IWGRP = 16 const S_IWOTH = 2 const S_IWRITE = 128 const S_IWUSR = 128 const S_IXGRP = 8 const S_IXOTH = 1 const S_IXUSR = 64 // C documentation // // /* // ** A pathname under construction // */ type TDbPath = struct { Frc int32 FnSymlink int32 FzOut uintptr FnOut int32 FnUsed int32 } type TDl_info = struct { Fdli_fname uintptr Fdli_fbase uintptr Fdli_sname uintptr Fdli_saddr uintptr } const TIME_UTC = 1 const TIOCM_CAR = 64 const TIOCM_CD = 64 const TIOCM_CTS = 32 const TIOCM_DSR = 256 const TIOCM_DTR = 2 const TIOCM_LE = 1 const TIOCM_RI = 128 const TIOCM_RNG = 128 const TIOCM_RTS = 4 const TIOCM_SR = 16 const TIOCM_ST = 8 const TIOCPKT_DATA = 0 const TIOCPKT_DOSTOP = 32 const TIOCPKT_FLUSHREAD = 1 const TIOCPKT_FLUSHWRITE = 2 const TIOCPKT_IOCTL = 64 const TIOCPKT_NOSTOP = 16 const TIOCPKT_START = 8 const TIOCPKT_STOP = 4 /* An i-node */ type TUnixUnusedFd = struct { Ffd int32 Fflags int32 FpNext uintptr } type Tblkcnt_t = int64 type Tcaddr_t = uintptr // C documentation // // /* // ** An abstract type for a pointer to an IO method finder function: // */ type Tfinder_type = uintptr type Tgid_t = uint32 type Tino_t = uint64 type Tquad_t = int64 type Tu_int16_t = uint16 type Tu_int32_t = uint32 type Tu_int64_t = uint64 type Tu_int8_t = uint8 type Tu_quad_t = uint64 type Tuid_t = uint32 type Tuint = uint32 // C documentation // // /* Forward references */ type TunixShm = struct { FpShmNode uintptr FpNext uintptr FhasMutex Tu8 Fid Tu8 FsharedMask Tu16 FexclMask Tu16 } /* Connection shared memory */ type TunixShmNode = struct { FpInode uintptr FpShmMutex uintptr FzFilename uintptr FhShm int32 FszRegion int32 FnRegion Tu16 FisReadonly Tu8 FisUnlocked Tu8 FapRegion uintptr FnRef int32 FpFirst uintptr FaLock [8]int32 } // C documentation // // /* // ** Many system calls are accessed through pointer-to-functions so that // ** they may be overridden at runtime to facilitate fault injection during // ** testing and sandboxing. The following array holds the names and pointers // ** to all overrideable system calls. // */ type Tunix_syscall = struct { FzName uintptr FpCurrent Tsqlite3_syscall_ptr FpDefault Tsqlite3_syscall_ptr } type Tushort = uint16 /****************************************************************************** ****************** Begin Unique File ID Utility Used By VxWorks *************** ** ** On most versions of unix, we can get a unique ID for a file by concatenating ** the device number and the inode number. But this does not work on VxWorks. ** On VxWorks, a unique file id must be based on the canonical filename. ** ** A pointer to an instance of the following structure can be used as a ** unique file ID in VxWorks. Each instance of this structure contains ** a copy of the canonical filename. There is also a reference count. ** The structure is reclaimed when the number of pointers to it drops to ** zero. ** ** There are never very many files open at one time and lookups are not ** a performance-critical path, so it is sufficient to put these ** structures on a linked list. */ type TvxworksFileId = struct { FpNext uintptr FnRef int32 FnName int32 FzCanonicalName uintptr } type Twinsize = struct { Fws_row uint16 Fws_col uint16 Fws_xpixel uint16 Fws_ypixel uint16 } const UNIXFILE_DELETE = 32 const UNIXFILE_DIRSYNC = 8 const UNIXFILE_EXCL = 1 const UNIXFILE_NOLOCK = 128 const UNIXFILE_PERSIST_WAL = 4 const UNIXFILE_PSOW = 16 const UNIXFILE_RDONLY = 2 const UNIXFILE_URI = 64 const UNIX_SHM_BASE = 120 const UNIX_SHM_DMS = 128 type UnixUnusedFd = TUnixUnusedFd const W_OK = 2 const X_OK = 1 // C documentation // // /* // ** Allocate or return the aggregate context for a user function. A new // ** context is allocated on the first call. Subsequent calls return the // ** same context that was returned on prior calls. // */ func Xsqlite3_aggregate_context(tls *libc.TLS, p uintptr, nByte int32) (r uintptr) { if libc.Int32FromUint16((*TMem)(unsafe.Pointer((*Tsqlite3_context)(unsafe.Pointer(p)).FpMem)).Fflags)&int32(MEM_Agg) == 0 { return _createAggContext(tls, p, nByte) } else { return (*TMem)(unsafe.Pointer((*Tsqlite3_context)(unsafe.Pointer(p)).FpMem)).Fz } return r } // C documentation // // /* // ** Return the total number of pages in the source database as of the most // ** recent call to sqlite3_backup_step(). // */ func Xsqlite3_backup_pagecount(tls *libc.TLS, p uintptr) (r int32) { return libc.Int32FromUint32((*Tsqlite3_backup)(unsafe.Pointer(p)).FnPagecount) } // C documentation // // /* // ** Return the number of pages still to be backed up as of the most recent // ** call to sqlite3_backup_step(). // */ func Xsqlite3_backup_remaining(tls *libc.TLS, p uintptr) (r int32) { return libc.Int32FromUint32((*Tsqlite3_backup)(unsafe.Pointer(p)).FnRemaining) } func Xsqlite3_bind_blob64(tls *libc.TLS, pStmt uintptr, i int32, zData uintptr, nData Tsqlite3_uint64, __ccgo_fp_xDel uintptr) (r int32) { return _bindText(tls, pStmt, i, zData, libc.Int64FromUint64(nData), __ccgo_fp_xDel, uint8(0)) } func Xsqlite3_bind_null(tls *libc.TLS, pStmt uintptr, i int32) (r int32) { var p uintptr var rc int32 _, _ = p, rc p = pStmt rc = _vdbeUnbind(tls, p, libc.Uint32FromInt32(i-libc.Int32FromInt32(1))) if rc == SQLITE_OK { /* tag-20240917-01 */ Xsqlite3_mutex_leave(tls, (*Tsqlite3)(unsafe.Pointer((*TVdbe)(unsafe.Pointer(p)).Fdb)).Fmutex) } return rc } func Xsqlite3_bind_value(tls *libc.TLS, pStmt uintptr, i int32, pValue uintptr) (r int32) { var rc int32 var v1 float64 _, _ = rc, v1 switch Xsqlite3_value_type(tls, pValue) { case int32(SQLITE_INTEGER): rc = Xsqlite3_bind_int64(tls, pStmt, i, *(*Ti64)(unsafe.Pointer(pValue))) case int32(SQLITE_FLOAT): if libc.Int32FromUint16((*Tsqlite3_value)(unsafe.Pointer(pValue)).Fflags)&int32(MEM_Real) != 0 { v1 = *(*float64)(unsafe.Pointer(pValue)) } else { v1 = float64(*(*Ti64)(unsafe.Pointer(pValue))) } rc = Xsqlite3_bind_double(tls, pStmt, i, v1) case int32(SQLITE_BLOB): if libc.Int32FromUint16((*Tsqlite3_value)(unsafe.Pointer(pValue)).Fflags)&int32(MEM_Zero) != 0 { rc = Xsqlite3_bind_zeroblob(tls, pStmt, i, *(*int32)(unsafe.Pointer(&(*Tsqlite3_value)(unsafe.Pointer(pValue)).Fu))) } else { rc = Xsqlite3_bind_blob(tls, pStmt, i, (*Tsqlite3_value)(unsafe.Pointer(pValue)).Fz, (*Tsqlite3_value)(unsafe.Pointer(pValue)).Fn, uintptr(-libc.Int32FromInt32(1))) } case int32(SQLITE_TEXT): rc = _bindText(tls, pStmt, i, (*Tsqlite3_value)(unsafe.Pointer(pValue)).Fz, int64((*Tsqlite3_value)(unsafe.Pointer(pValue)).Fn), uintptr(-libc.Int32FromInt32(1)), (*Tsqlite3_value)(unsafe.Pointer(pValue)).Fenc) default: rc = Xsqlite3_bind_null(tls, pStmt, i) break } return rc } // C documentation // // /* // ** Return the number of columns in the result set for the statement pStmt. // */ func Xsqlite3_column_count(tls *libc.TLS, pStmt uintptr) (r int32) { var pVm uintptr _ = pVm pVm = pStmt if pVm == uintptr(0) { return 0 } return libc.Int32FromUint16((*TVdbe)(unsafe.Pointer(pVm)).FnResColumn) } // C documentation // // /* // ** Register a new collation sequence with the database handle db. // */ func Xsqlite3_create_collation_v2(tls *libc.TLS, db uintptr, zName uintptr, enc int32, pCtx uintptr, __ccgo_fp_xCompare uintptr, __ccgo_fp_xDel uintptr) (r int32) { var rc int32 _ = rc Xsqlite3_mutex_enter(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex) rc = _createCollation(tls, db, zName, libc.Uint8FromInt32(enc), pCtx, __ccgo_fp_xCompare, __ccgo_fp_xDel) rc = _sqlite3ApiExit(tls, db, rc) Xsqlite3_mutex_leave(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex) return rc } // C documentation // // /* // ** Return the number of values available from the current row of the // ** currently executing statement pStmt. // */ func Xsqlite3_data_count(tls *libc.TLS, pStmt uintptr) (r int32) { var pVm uintptr _ = pVm pVm = pStmt if pVm == uintptr(0) || (*TVdbe)(unsafe.Pointer(pVm)).FpResultRow == uintptr(0) { return 0 } return libc.Int32FromUint16((*TVdbe)(unsafe.Pointer(pVm)).FnResColumn) } // C documentation // // /* // ** Enable or disable the extended result codes. // */ func Xsqlite3_extended_result_codes(tls *libc.TLS, db uintptr, onoff int32) (r int32) { var v1 uint32 _ = v1 Xsqlite3_mutex_enter(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex) if onoff != 0 { v1 = uint32(0xffffffff) } else { v1 = uint32(0xff) } (*Tsqlite3)(unsafe.Pointer(db)).FerrMask = libc.Int32FromUint32(v1) Xsqlite3_mutex_leave(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex) return SQLITE_OK } // C documentation // // /* // ** Test to see whether or not the database connection is in autocommit // ** mode. Return TRUE if it is and FALSE if not. Autocommit mode is on // ** by default. Autocommit is disabled by a BEGIN statement and reenabled // ** by the next COMMIT or ROLLBACK. // */ func Xsqlite3_get_autocommit(tls *libc.TLS, db uintptr) (r int32) { var iRet int32 _ = iRet Xsqlite3_mutex_enter(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex) iRet = libc.Int32FromUint8((*Tsqlite3)(unsafe.Pointer(db)).FautoCommit) Xsqlite3_mutex_leave(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex) return iRet } func Xsqlite3_keyword_name(tls *libc.TLS, i int32, pzName uintptr, pnName uintptr) (r int32) { if i < 0 || i >= int32(SQLITE_N_KEYWORD) { return int32(SQLITE_ERROR) } i = i + 1 **(**uintptr)(__ccgo_up(pzName)) = uintptr(unsafe.Pointer(&_zKWText)) + uintptr(_aKWOffset[i]) **(**int32)(__ccgo_up(pnName)) = libc.Int32FromUint8(_aKWLen[i]) return SQLITE_OK } // C documentation // // /* // ** This version of the memory allocation is for use by the application. // ** First make sure the memory subsystem is initialized, then do the // ** allocation. // */ func Xsqlite3_malloc(tls *libc.TLS, n int32) (r uintptr) { var v1 uintptr _ = v1 if Xsqlite3_initialize(tls) != 0 { return uintptr(0) } if n <= 0 { v1 = uintptr(0) } else { v1 = _sqlite3Malloc(tls, libc.Uint64FromInt32(n)) } return v1 } func Xsqlite3_msize(tls *libc.TLS, p uintptr) (r Tsqlite3_uint64) { var v1 int32 _ = v1 if p != 0 { v1 = (*(*func(*libc.TLS, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{_sqlite3Config.Fm.FxSize})))(tls, p) } else { v1 = 0 } return libc.Uint64FromInt32(v1) } // C documentation // // /* // ** Open a new database handle. // */ func Xsqlite3_open(tls *libc.TLS, zFilename uintptr, ppDb uintptr) (r int32) { return _openDatabase(tls, zFilename, ppDb, libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_OPEN_READWRITE)|libc.Int32FromInt32(SQLITE_OPEN_CREATE)), uintptr(0)) } func Xsqlite3_open_v2(tls *libc.TLS, filename uintptr, ppDb uintptr, flags int32, zVfs uintptr) (r int32) { return _openDatabase(tls, filename, ppDb, libc.Uint32FromInt32(flags), zVfs) } // C documentation // // /* // ** Shutdown the operating system interface. // ** // ** Some operating systems might need to do some cleanup in this routine, // ** to release dynamically allocated objects. But not on unix. // ** This routine is a no-op for unix. // */ func Xsqlite3_os_end(tls *libc.TLS) (r int32) { _unixBigLock = uintptr(0) return SQLITE_OK } /************** End of os_unix.c *********************************************/ /************** Begin file os_win.c ******************************************/ /* ** 2004 May 22 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ****************************************************************************** ** ** This file contains code that is specific to Windows. */ /* #include "sqliteInt.h" */ /************** End of os_win.c **********************************************/ /************** Begin file memdb.c *******************************************/ /* ** 2016-09-07 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ****************************************************************************** ** ** This file implements an in-memory VFS. A database is held as a contiguous ** block of memory. ** ** This file also implements interface sqlite3_serialize() and ** sqlite3_deserialize(). */ /* #include "sqliteInt.h" */ // C documentation // // /* // ** This function is called from within a pre-update callback to retrieve // ** the number of columns in the row being updated, deleted or inserted. // */ func Xsqlite3_preupdate_count(tls *libc.TLS, db uintptr) (r int32) { var p uintptr var v1 int32 _, _ = p, v1 p = (*Tsqlite3)(unsafe.Pointer(db)).FpPreUpdate if p != 0 { v1 = libc.Int32FromUint16((*TKeyInfo)(unsafe.Pointer((*TPreUpdate)(unsafe.Pointer(p)).FpKeyinfo)).FnKeyField) } else { v1 = 0 } return v1 } // C documentation // // /* // ** This routine sets the progress callback for an Sqlite database to the // ** given callback function with the given argument. The progress callback will // ** be invoked every nOps opcodes. // */ func Xsqlite3_progress_handler(tls *libc.TLS, db uintptr, nOps int32, __ccgo_fp_xProgress uintptr, pArg uintptr) { Xsqlite3_mutex_enter(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex) if nOps > 0 { (*Tsqlite3)(unsafe.Pointer(db)).FxProgress = __ccgo_fp_xProgress (*Tsqlite3)(unsafe.Pointer(db)).FnProgressOps = libc.Uint32FromInt32(nOps) (*Tsqlite3)(unsafe.Pointer(db)).FpProgressArg = pArg } else { (*Tsqlite3)(unsafe.Pointer(db)).FxProgress = uintptr(0) (*Tsqlite3)(unsafe.Pointer(db)).FnProgressOps = uint32(0) (*Tsqlite3)(unsafe.Pointer(db)).FpProgressArg = uintptr(0) } Xsqlite3_mutex_leave(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex) } // C documentation // // /* // ** The public interface to sqlite3Realloc. Make sure that the memory // ** subsystem is initialized prior to invoking sqliteRealloc. // */ func Xsqlite3_realloc(tls *libc.TLS, pOld uintptr, n int32) (r uintptr) { if Xsqlite3_initialize(tls) != 0 { return uintptr(0) } if n < 0 { n = 0 } /* IMP: R-26507-47431 */ return _sqlite3Realloc(tls, pOld, libc.Uint64FromInt32(n)) } func Xsqlite3_result_blob64(tls *libc.TLS, pCtx uintptr, z uintptr, n Tsqlite3_uint64, __ccgo_fp_xDel uintptr) { if n > uint64(0x7fffffff) { _invokeValueDestructor(tls, z, __ccgo_fp_xDel, pCtx) } else { _setResultStrOrError(tls, pCtx, z, libc.Int32FromUint64(n), uint8(0), __ccgo_fp_xDel) } } func Xsqlite3_result_error_code(tls *libc.TLS, pCtx uintptr, errCode int32) { var v1 int32 _ = v1 if errCode != 0 { v1 = errCode } else { v1 = -int32(1) } (*Tsqlite3_context)(unsafe.Pointer(pCtx)).FisError = v1 if libc.Int32FromUint16((*TMem)(unsafe.Pointer((*Tsqlite3_context)(unsafe.Pointer(pCtx)).FpOut)).Fflags)&int32(MEM_Null) != 0 { _setResultStrOrError(tls, pCtx, _sqlite3ErrStr(tls, errCode), -int32(1), uint8(SQLITE_UTF8), libc.UintptrFromInt32(0)) } } func Xsqlite3_result_text16be(tls *libc.TLS, pCtx uintptr, z uintptr, n int32, __ccgo_fp_xDel uintptr) { _setResultStrOrError(tls, pCtx, z, libc.Int32FromUint64(libc.Uint64FromInt32(n) & ^libc.Uint64FromInt32(1)), uint8(SQLITE_UTF16BE), __ccgo_fp_xDel) } func Xsqlite3_result_text16le(tls *libc.TLS, pCtx uintptr, z uintptr, n int32, __ccgo_fp_xDel uintptr) { _setResultStrOrError(tls, pCtx, z, libc.Int32FromUint64(libc.Uint64FromInt32(n) & ^libc.Uint64FromInt32(1)), uint8(SQLITE_UTF16LE), __ccgo_fp_xDel) } func Xsqlite3_result_value(tls *libc.TLS, pCtx uintptr, pValue uintptr) { var pOut uintptr _ = pOut pOut = (*Tsqlite3_context)(unsafe.Pointer(pCtx)).FpOut _sqlite3VdbeMemCopy(tls, pOut, pValue) _sqlite3VdbeChangeEncoding(tls, pOut, libc.Int32FromUint8((*Tsqlite3_context)(unsafe.Pointer(pCtx)).Fenc)) if _sqlite3VdbeMemTooBig(tls, pOut) != 0 { Xsqlite3_result_error_toobig(tls, pCtx) } } func Xsqlite3_result_zeroblob(tls *libc.TLS, pCtx uintptr, n int32) { var v1 int32 _ = v1 if n > 0 { v1 = n } else { v1 = 0 } Xsqlite3_result_zeroblob64(tls, pCtx, libc.Uint64FromInt32(v1)) } // C documentation // // /* // ** Return true if the prepared statement is in need of being reset. // */ func Xsqlite3_stmt_busy(tls *libc.TLS, pStmt uintptr) (r int32) { var v uintptr _ = v v = pStmt return libc.BoolInt32(v != uintptr(0) && libc.Int32FromUint8((*TVdbe)(unsafe.Pointer(v)).FeVdbeState) == int32(VDBE_RUN_STATE)) } // C documentation // // /* Return any error code associated with p */ func Xsqlite3_str_errcode(tls *libc.TLS, p uintptr) (r int32) { var v1 int32 _ = v1 if p != 0 { v1 = libc.Int32FromUint8((*Tsqlite3_str)(unsafe.Pointer(p)).FaccError) } else { v1 = int32(SQLITE_NOMEM) } return v1 } // C documentation // // /* Return the current length of p in bytes */ func Xsqlite3_str_length(tls *libc.TLS, p uintptr) (r int32) { var v1 uint32 _ = v1 if p != 0 { v1 = (*Tsqlite3_str)(unsafe.Pointer(p)).FnChar } else { v1 = uint32(0) } return libc.Int32FromUint32(v1) } func Xsqlite3_strnicmp(tls *libc.TLS, zLeft uintptr, zRight uintptr, N int32) (r int32) { var a, b uintptr var v1 int32 _, _, _ = a, b, v1 if zLeft == uintptr(0) { if zRight != 0 { v1 = -int32(1) } else { v1 = 0 } return v1 } else { if zRight == uintptr(0) { return int32(1) } } a = zLeft b = zRight for { v1 = N N = N - 1 if !(v1 > 0 && libc.Int32FromUint8(**(**uint8)(__ccgo_up(a))) != 0 && libc.Int32FromUint8(_sqlite3UpperToLower[**(**uint8)(__ccgo_up(a))]) == libc.Int32FromUint8(_sqlite3UpperToLower[**(**uint8)(__ccgo_up(b))])) { break } a = a + 1 b = b + 1 } if N < 0 { v1 = 0 } else { v1 = libc.Int32FromUint8(_sqlite3UpperToLower[**(**uint8)(__ccgo_up(a))]) - libc.Int32FromUint8(_sqlite3UpperToLower[**(**uint8)(__ccgo_up(b))]) } return v1 } // C documentation // // /* // ** Return a boolean value for a query parameter. // */ func Xsqlite3_uri_boolean(tls *libc.TLS, zFilename uintptr, zParam uintptr, bDflt int32) (r int32) { var z uintptr var v1 int32 _, _ = z, v1 z = Xsqlite3_uri_parameter(tls, zFilename, zParam) bDflt = libc.BoolInt32(bDflt != 0) if z != 0 { v1 = libc.Int32FromUint8(_sqlite3GetBoolean(tls, z, libc.Uint8FromInt32(bDflt))) } else { v1 = bDflt } return v1 } func Xsqlite3_value_encoding(tls *libc.TLS, pVal uintptr) (r int32) { return libc.Int32FromUint8((*Tsqlite3_value)(unsafe.Pointer(pVal)).Fenc) } // C documentation // // /* Return true if a parameter value originated from an sqlite3_bind() */ func Xsqlite3_value_frombind(tls *libc.TLS, pVal uintptr) (r int32) { return libc.BoolInt32(libc.Int32FromUint16((*Tsqlite3_value)(unsafe.Pointer(pVal)).Fflags)&int32(MEM_FromBind) != 0) } // C documentation // // /* Return true if a parameter to xUpdate represents an unchanged column */ func Xsqlite3_value_nochange(tls *libc.TLS, pVal uintptr) (r int32) { return libc.BoolInt32(libc.Int32FromUint16((*Tsqlite3_value)(unsafe.Pointer(pVal)).Fflags)&(libc.Int32FromInt32(MEM_Null)|libc.Int32FromInt32(MEM_Zero)) == libc.Int32FromInt32(MEM_Null)|libc.Int32FromInt32(MEM_Zero)) } func Xsqlite3_value_subtype(tls *libc.TLS, pVal uintptr) (r uint32) { var pMem uintptr var v1 int32 _, _ = pMem, v1 pMem = pVal if libc.Int32FromUint16((*TMem)(unsafe.Pointer(pMem)).Fflags)&int32(MEM_Subtype) != 0 { v1 = libc.Int32FromUint8((*TMem)(unsafe.Pointer(pMem)).FeSubtype) } else { v1 = 0 } return libc.Uint32FromInt32(v1) } // C documentation // // /* EVIDENCE-OF: R-12793-43283 Every value in SQLite has one of five // ** fundamental datatypes: 64-bit signed integer 64-bit IEEE floating // ** point number string BLOB NULL // */ func Xsqlite3_value_type(tls *libc.TLS, pVal uintptr) (r int32) { return libc.Int32FromUint8(_aType[libc.Int32FromUint16((*Tsqlite3_value)(unsafe.Pointer(pVal)).Fflags)&int32(MEM_AffMask)]) } // C documentation // // /* // ** Call from within the xCreate() or xConnect() methods to provide // ** the SQLite core with additional information about the behavior // ** of the virtual table being implemented. // */ func Xsqlite3_vtab_config(tls *libc.TLS, db uintptr, op int32, va uintptr) (r int32) { var ap Tva_list var p uintptr var rc int32 _, _, _ = ap, p, rc rc = SQLITE_OK Xsqlite3_mutex_enter(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex) p = (*Tsqlite3)(unsafe.Pointer(db)).FpVtabCtx if !(p != 0) { rc = _sqlite3MisuseError(tls, int32(163230)) } else { ap = va switch op { case int32(SQLITE_VTAB_CONSTRAINT_SUPPORT): (*TVTable)(unsafe.Pointer((*TVtabCtx)(unsafe.Pointer(p)).FpVTable)).FbConstraint = libc.Uint8FromInt32(libc.VaInt32(&ap)) case int32(SQLITE_VTAB_INNOCUOUS): (*TVTable)(unsafe.Pointer((*TVtabCtx)(unsafe.Pointer(p)).FpVTable)).FeVtabRisk = uint8(SQLITE_VTABRISK_Low) case int32(SQLITE_VTAB_DIRECTONLY): (*TVTable)(unsafe.Pointer((*TVtabCtx)(unsafe.Pointer(p)).FpVTable)).FeVtabRisk = uint8(SQLITE_VTABRISK_High) case int32(SQLITE_VTAB_USES_ALL_SCHEMAS): (*TVTable)(unsafe.Pointer((*TVtabCtx)(unsafe.Pointer(p)).FpVTable)).FbAllSchemas = uint8(1) default: rc = _sqlite3MisuseError(tls, int32(163252)) break } _ = ap } if rc != SQLITE_OK { _sqlite3Error(tls, db, rc) } Xsqlite3_mutex_leave(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex) return rc } /************** End of vtab.c ************************************************/ /************** Begin file wherecode.c ***************************************/ /* ** 2015-06-06 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. ** ** This file was split off from where.c on 2015-06-06 in order to reduce the ** size of where.c and make it easier to edit. This file contains the routines ** that actually generate the bulk of the WHERE loop code. The original where.c ** file retains the code that does query planning and analysis. */ /* #include "sqliteInt.h" */ /************** Include whereInt.h in the middle of wherecode.c **************/ /************** Begin file whereInt.h ****************************************/ /* ** 2013-11-12 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file contains structure and macro definitions for the query ** planner logic in "where.c". These definitions are broken out into ** a separate source file for easier editing. */ const _IOLBF = 1 const _IONBF = 2 const __SIZEOF_WCHAR_T__ = 4 const __SIZEOF_WINT_T__ = 4 const __WCHAR_WIDTH__ = 32 const __WINT_WIDTH__ = 32 const __restrict_arr = 0 /* EVIDENCE-OF: R-14606-31564 Value is a BLOB that is (N-12)/2 bytes in ** length. ** EVIDENCE-OF: R-28401-00140 Value is a string in the text encoding and ** (N-13)/2 bytes in length. */ var _aFlag = [2]Tu16{ 0: libc.Uint16FromInt32(libc.Int32FromInt32(MEM_Blob) | libc.Int32FromInt32(MEM_Ephem)), 1: libc.Uint16FromInt32(libc.Int32FromInt32(MEM_Str) | libc.Int32FromInt32(MEM_Ephem)), } /* If the column value is a string, we need a persistent value, not ** a MEM_Ephem value. This branch is a fast short-cut that is equivalent ** to calling sqlite3VdbeSerialGet() and sqlite3VdbeDeephemeralize(). */ var _aFlag1 = [2]Tu16{ 0: uint16(MEM_Blob), 1: libc.Uint16FromInt32(libc.Int32FromInt32(MEM_Str) | libc.Int32FromInt32(MEM_Term)), } var _aKeyword = [7]struct { Fi Tu8 FnChar Tu8 Fcode Tu8 }{ 0: { FnChar: uint8(7), Fcode: uint8(JT_NATURAL), }, 1: { Fi: uint8(6), FnChar: uint8(4), Fcode: libc.Uint8FromInt32(libc.Int32FromInt32(JT_LEFT) | libc.Int32FromInt32(JT_OUTER)), }, 2: { Fi: uint8(10), FnChar: uint8(5), Fcode: uint8(JT_OUTER), }, 3: { Fi: uint8(14), FnChar: uint8(5), Fcode: libc.Uint8FromInt32(libc.Int32FromInt32(JT_RIGHT) | libc.Int32FromInt32(JT_OUTER)), }, 4: { Fi: uint8(19), FnChar: uint8(4), Fcode: libc.Uint8FromInt32(libc.Int32FromInt32(JT_LEFT) | libc.Int32FromInt32(JT_RIGHT) | libc.Int32FromInt32(JT_OUTER)), }, 5: { Fi: uint8(23), FnChar: uint8(5), Fcode: uint8(JT_INNER), }, 6: { Fi: uint8(28), FnChar: uint8(5), Fcode: libc.Uint8FromInt32(libc.Int32FromInt32(JT_INNER) | libc.Int32FromInt32(JT_CROSS)), }, } var _aWindowFuncs = [15]TFuncDef{ 0: { FfuncFlags: libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_FUNC_BUILTIN) | libc.Int32FromInt32(SQLITE_UTF8) | libc.Int32FromInt32(SQLITE_FUNC_WINDOW) | libc.Int32FromInt32(0)), FzName: uintptr(unsafe.Pointer(&_row_numberName)), }, 1: { FfuncFlags: libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_FUNC_BUILTIN) | libc.Int32FromInt32(SQLITE_UTF8) | libc.Int32FromInt32(SQLITE_FUNC_WINDOW) | libc.Int32FromInt32(0)), FzName: uintptr(unsafe.Pointer(&_dense_rankName)), }, 2: { FfuncFlags: libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_FUNC_BUILTIN) | libc.Int32FromInt32(SQLITE_UTF8) | libc.Int32FromInt32(SQLITE_FUNC_WINDOW) | libc.Int32FromInt32(0)), FzName: uintptr(unsafe.Pointer(&_rankName)), }, 3: { FfuncFlags: libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_FUNC_BUILTIN) | libc.Int32FromInt32(SQLITE_UTF8) | libc.Int32FromInt32(SQLITE_FUNC_WINDOW) | libc.Int32FromInt32(0)), FzName: uintptr(unsafe.Pointer(&_percent_rankName)), }, 4: { FfuncFlags: libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_FUNC_BUILTIN) | libc.Int32FromInt32(SQLITE_UTF8) | libc.Int32FromInt32(SQLITE_FUNC_WINDOW) | libc.Int32FromInt32(0)), FzName: uintptr(unsafe.Pointer(&_cume_distName)), }, 5: { FnArg: int16(1), FfuncFlags: libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_FUNC_BUILTIN) | libc.Int32FromInt32(SQLITE_UTF8) | libc.Int32FromInt32(SQLITE_FUNC_WINDOW) | libc.Int32FromInt32(0)), FzName: uintptr(unsafe.Pointer(&_ntileName)), }, 6: { FnArg: int16(1), FfuncFlags: libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_FUNC_BUILTIN) | libc.Int32FromInt32(SQLITE_UTF8) | libc.Int32FromInt32(SQLITE_FUNC_WINDOW) | libc.Int32FromInt32(0)), FzName: uintptr(unsafe.Pointer(&_last_valueName)), }, 7: { FnArg: int16(2), FfuncFlags: libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_FUNC_BUILTIN) | libc.Int32FromInt32(SQLITE_UTF8) | libc.Int32FromInt32(SQLITE_FUNC_WINDOW) | libc.Int32FromInt32(0)), FzName: uintptr(unsafe.Pointer(&_nth_valueName)), }, 8: { FnArg: int16(1), FfuncFlags: libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_FUNC_BUILTIN) | libc.Int32FromInt32(SQLITE_UTF8) | libc.Int32FromInt32(SQLITE_FUNC_WINDOW) | libc.Int32FromInt32(0)), FzName: uintptr(unsafe.Pointer(&_first_valueName)), }, 9: { FnArg: int16(1), FfuncFlags: libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_FUNC_BUILTIN) | libc.Int32FromInt32(SQLITE_UTF8) | libc.Int32FromInt32(SQLITE_FUNC_WINDOW) | libc.Int32FromInt32(0)), FzName: uintptr(unsafe.Pointer(&_leadName)), }, 10: { FnArg: int16(2), FfuncFlags: libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_FUNC_BUILTIN) | libc.Int32FromInt32(SQLITE_UTF8) | libc.Int32FromInt32(SQLITE_FUNC_WINDOW) | libc.Int32FromInt32(0)), FzName: uintptr(unsafe.Pointer(&_leadName)), }, 11: { FnArg: int16(3), FfuncFlags: libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_FUNC_BUILTIN) | libc.Int32FromInt32(SQLITE_UTF8) | libc.Int32FromInt32(SQLITE_FUNC_WINDOW) | libc.Int32FromInt32(0)), FzName: uintptr(unsafe.Pointer(&_leadName)), }, 12: { FnArg: int16(1), FfuncFlags: libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_FUNC_BUILTIN) | libc.Int32FromInt32(SQLITE_UTF8) | libc.Int32FromInt32(SQLITE_FUNC_WINDOW) | libc.Int32FromInt32(0)), FzName: uintptr(unsafe.Pointer(&_lagName)), }, 13: { FnArg: int16(2), FfuncFlags: libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_FUNC_BUILTIN) | libc.Int32FromInt32(SQLITE_UTF8) | libc.Int32FromInt32(SQLITE_FUNC_WINDOW) | libc.Int32FromInt32(0)), FzName: uintptr(unsafe.Pointer(&_lagName)), }, 14: { FnArg: int16(3), FfuncFlags: libc.Uint32FromInt32(libc.Int32FromInt32(SQLITE_FUNC_BUILTIN) | libc.Int32FromInt32(SQLITE_UTF8) | libc.Int32FromInt32(SQLITE_FUNC_WINDOW) | libc.Int32FromInt32(0)), FzName: uintptr(unsafe.Pointer(&_lagName)), }, } // C documentation // // /* // ** This variant of sqlite3BtreePayload() works even if the cursor has not // ** in the CURSOR_VALID state. It is only used by the sqlite3_blob_read() // ** interface. // */ func _accessPayloadChecked(tls *libc.TLS, pCur uintptr, offset Tu32, amt Tu32, pBuf uintptr) (r int32) { var rc, v1 int32 _, _ = rc, v1 if libc.Int32FromUint8((*TBtCursor)(unsafe.Pointer(pCur)).FeState) == int32(CURSOR_INVALID) { return int32(SQLITE_ABORT) } rc = _btreeRestoreCursorPosition(tls, pCur) if rc != 0 { v1 = rc } else { v1 = _accessPayload(tls, pCur, offset, amt, pBuf, 0) } return v1 } // C documentation // // /* // ** This routine takes the module argument that has been accumulating // ** in pParse->zArg[] and appends it to the list of arguments on the // ** virtual table currently under construction in pParse->pTable. // */ func _addArgumentToVtab(tls *libc.TLS, pParse uintptr) { var db, z uintptr var n int32 _, _, _ = db, n, z if (*TParse)(unsafe.Pointer(pParse)).FsArg.Fz != 0 && (*TParse)(unsafe.Pointer(pParse)).FpNewTable != 0 { z = (*TParse)(unsafe.Pointer(pParse)).FsArg.Fz n = libc.Int32FromUint32((*TParse)(unsafe.Pointer(pParse)).FsArg.Fn) db = (*TParse)(unsafe.Pointer(pParse)).Fdb _addModuleArgument(tls, pParse, (*TParse)(unsafe.Pointer(pParse)).FpNewTable, _sqlite3DbStrNDup(tls, db, z, libc.Uint64FromInt32(n))) } } // C documentation // // /* // ** Return SQLITE_CORRUPT if any cursor other than pCur is currently valid // ** on the same B-tree as pCur. // ** // ** This can occur if a database is corrupt with two or more SQL tables // ** pointing to the same b-tree. If an insert occurs on one SQL table // ** and causes a BEFORE TRIGGER to do a secondary insert on the other SQL // ** table linked to the same b-tree. If the secondary insert causes a // ** rebalance, that can change content out from under the cursor on the // ** first SQL table, violating invariants on the first insert. // */ func _anotherValidCursor(tls *libc.TLS, pCur uintptr) (r int32) { var pOther uintptr _ = pOther pOther = (*TBtShared)(unsafe.Pointer((*TBtCursor)(unsafe.Pointer(pCur)).FpBt)).FpCursor for { if !(pOther != 0) { break } if pOther != pCur && libc.Int32FromUint8((*TBtCursor)(unsafe.Pointer(pOther)).FeState) == CURSOR_VALID && (*TBtCursor)(unsafe.Pointer(pOther)).FpPage == (*TBtCursor)(unsafe.Pointer(pCur)).FpPage { return _sqlite3CorruptError(tls, int32(82340)) } goto _1 _1: ; pOther = (*TBtCursor)(unsafe.Pointer(pOther)).FpNext } return SQLITE_OK } // C documentation // // /* // ** Perform a read or write operation on a blob // */ func _blobReadWrite(tls *libc.TLS, pBlob uintptr, z uintptr, n int32, iOffset int32, __ccgo_fp_xCall uintptr) (r int32) { bp := tls.Alloc(16) defer tls.Free(16) var db, p, v uintptr var iKey Tsqlite3_int64 var rc int32 var _ /* bDiff at bp+0 */ int32 _, _, _, _, _ = db, iKey, p, rc, v rc = SQLITE_OK p = pBlob if p == uintptr(0) { return _sqlite3MisuseError(tls, int32(106385)) } db = (*TIncrblob)(unsafe.Pointer(p)).Fdb Xsqlite3_mutex_enter(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex) v = (*TIncrblob)(unsafe.Pointer(p)).FpStmt if n < 0 || iOffset < 0 || int64(iOffset)+int64(n) > int64((*TIncrblob)(unsafe.Pointer(p)).FnByte) { /* Request is out of range. Return a transient error. */ rc = int32(SQLITE_ERROR) } else { if v == uintptr(0) { /* If there is no statement handle, then the blob-handle has ** already been invalidated. Return SQLITE_ABORT in this case. */ rc = int32(SQLITE_ABORT) } else { /* Call either BtreeData() or BtreePutData(). If SQLITE_ABORT is ** returned, clean-up the statement handle. */ _sqlite3BtreeEnterCursor(tls, (*TIncrblob)(unsafe.Pointer(p)).FpCsr) if __ccgo_fp_xCall == __ccgo_fp(_sqlite3BtreePutData) && (*Tsqlite3)(unsafe.Pointer(db)).FxPreUpdateCallback != 0 { /* If a pre-update hook is registered and this is a write cursor, ** invoke it here. ** ** TODO: The preupdate-hook is passed SQLITE_DELETE, even though this ** operation should really be an SQLITE_UPDATE. This is probably ** incorrect, but is convenient because at this point the new.* values ** are not easily obtainable. And for the sessions module, an ** SQLITE_UPDATE where the PK columns do not change is handled in the ** same way as an SQLITE_DELETE (the SQLITE_DELETE code is actually ** slightly more efficient). Since you cannot write to a PK column ** using the incremental-blob API, this works. For the sessions module ** anyhow. */ if _sqlite3BtreeCursorIsValidNN(tls, (*TIncrblob)(unsafe.Pointer(p)).FpCsr) == 0 { /* If the cursor is not currently valid, try to reseek it. This ** always either fails or finds the correct row - the cursor will ** have been marked permanently CURSOR_INVALID if the open row has ** been deleted. */ **(**int32)(__ccgo_up(bp)) = 0 rc = _sqlite3BtreeCursorRestore(tls, (*TIncrblob)(unsafe.Pointer(p)).FpCsr, bp) } if _sqlite3BtreeCursorIsValidNN(tls, (*TIncrblob)(unsafe.Pointer(p)).FpCsr) != 0 { iKey = _sqlite3BtreeIntegerKey(tls, (*TIncrblob)(unsafe.Pointer(p)).FpCsr) _sqlite3VdbePreUpdateHook(tls, v, **(**uintptr)(__ccgo_up((*TVdbe)(unsafe.Pointer(v)).FapCsr)), int32(SQLITE_DELETE), (*TIncrblob)(unsafe.Pointer(p)).FzDb, (*TIncrblob)(unsafe.Pointer(p)).FpTab, iKey, -int32(1), libc.Int32FromUint16((*TIncrblob)(unsafe.Pointer(p)).FiCol)) } } if rc == SQLITE_OK { rc = (*(*func(*libc.TLS, uintptr, Tu32, Tu32, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{__ccgo_fp_xCall})))(tls, (*TIncrblob)(unsafe.Pointer(p)).FpCsr, libc.Uint32FromInt32(iOffset+(*TIncrblob)(unsafe.Pointer(p)).FiOffset), libc.Uint32FromInt32(n), z) } _sqlite3BtreeLeaveCursor(tls, (*TIncrblob)(unsafe.Pointer(p)).FpCsr) if rc == int32(SQLITE_ABORT) { _sqlite3VdbeFinalize(tls, v) (*TIncrblob)(unsafe.Pointer(p)).FpStmt = uintptr(0) } else { (*TVdbe)(unsafe.Pointer(v)).Frc = rc } } } _sqlite3Error(tls, db, rc) rc = _sqlite3ApiExit(tls, db, rc) Xsqlite3_mutex_leave(tls, (*Tsqlite3)(unsafe.Pointer(db)).Fmutex) return rc } // C documentation // // /* This is a helper function to impliesNotNullRow(). In this routine, // ** set pWalker->eCode to one only if *both* of the input expressions // ** separately have the implies-not-null-row property. // */ func _bothImplyNotNullRow(tls *libc.TLS, pWalker uintptr, pE1 uintptr, pE2 uintptr) { if libc.Int32FromUint16((*TWalker)(unsafe.Pointer(pWalker)).FeCode) == 0 { _sqlite3WalkExpr(tls, pWalker, pE1) if (*TWalker)(unsafe.Pointer(pWalker)).FeCode != 0 { (*TWalker)(unsafe.Pointer(pWalker)).FeCode = uint16(0) _sqlite3WalkExpr(tls, pWalker, pE2) } } } // C documentation // // /* // ** Compute the amount of freespace on the page. In other words, fill // ** in the pPage->nFree field. // */ func _btreeComputeFreeSpace(tls *libc.TLS, pPage uintptr) (r int32) { var data uintptr var hdr Tu8 var iCellFirst, iCellLast, nFree, pc, top, usableSize int32 var next, size Tu32 _, _, _, _, _, _, _, _, _, _ = data, hdr, iCellFirst, iCellLast, nFree, next, pc, size, top, usableSize /* Last possible cell or freeblock offset */ usableSize = libc.Int32FromUint32((*TBtShared)(unsafe.Pointer((*TMemPage)(unsafe.Pointer(pPage)).FpBt)).FusableSize) hdr = (*TMemPage)(unsafe.Pointer(pPage)).FhdrOffset data = (*TMemPage)(unsafe.Pointer(pPage)).FaData /* EVIDENCE-OF: R-58015-48175 The two-byte integer at offset 5 designates ** the start of the cell content area. A zero value for this integer is ** interpreted as 65536. */ top = (libc.Int32FromUint8(**(**Tu8)(__ccgo_up(data + uintptr(libc.Int32FromUint8(hdr)+int32(5)))))< 0 { if pc < top { /* EVIDENCE-OF: R-55530-52930 In a well-formed b-tree page, there will ** always be at least one cell before the first freeblock. */ return _sqlite3CorruptError(tls, int32(75358)) } for int32(1) != 0 { if pc > iCellLast { /* Freeblock off the end of the page */ return _sqlite3CorruptError(tls, int32(75363)) } next = libc.Uint32FromInt32(libc.Int32FromUint8(**(**Tu8)(__ccgo_up(data + uintptr(pc))))< uint32(0) { /* Freeblock not in ascending order */ return _sqlite3CorruptError(tls, int32(75377)) } if libc.Uint32FromInt32(pc)+size > libc.Uint32FromInt32(usableSize) { /* Last freeblock extends past page end */ return _sqlite3CorruptError(tls, int32(75381)) } } /* At this point, nFree contains the sum of the offset to the start ** of the cell-content area plus the number of free bytes within ** the cell-content area. If this is greater than the usable-size ** of the page, then the page must be corrupted. This check also ** serves to verify that the offset to the start of the cell-content ** area, according to the page header, lies within the page. */ if nFree > usableSize || nFree < iCellFirst { return _sqlite3CorruptError(tls, int32(75393)) } (*TMemPage)(unsafe.Pointer(pPage)).FnFree = libc.Int32FromUint16(libc.Uint16FromInt32(nFree - iCellFirst)) return SQLITE_OK } // C documentation // // /* // ** This function is called from both BtreeCommitPhaseTwo() and BtreeRollback() // ** at the conclusion of a transaction. // */ func _btreeEndTransaction(tls *libc.TLS, p uintptr) { var db, pBt uintptr _, _ = db, pBt pBt = (*TBtree)(unsafe.Pointer(p)).FpBt db = (*TBtree)(unsafe.Pointer(p)).Fdb (*TBtShared)(unsafe.Pointer(pBt)).FbDoTruncate = uint8(0) if libc.Int32FromUint8((*TBtree)(unsafe.Pointer(p)).FinTrans) > TRANS_NONE && (*Tsqlite3)(unsafe.Pointer(db)).FnVdbeRead > int32(1) { /* If there are other active statements that belong to this database ** handle, downgrade to a read-only transaction. The other statements ** may still be reading from the database. */ _downgradeAllSharedCacheTableLocks(tls, p) (*TBtree)(unsafe.Pointer(p)).FinTrans = uint8(TRANS_READ) } else { /* If the handle had any kind of transaction open, decrement the ** transaction count of the shared btree. If the transaction count ** reaches 0, set the shared state to TRANS_NONE. The unlockBtreeIfUnused() ** call below will unlock the pager. */ if libc.Int32FromUint8((*TBtree)(unsafe.Pointer(p)).FinTrans) != TRANS_NONE { _clearAllSharedCacheTableLocks(tls, p) (*TBtShared)(unsafe.Pointer(pBt)).FnTransaction = (*TBtShared)(unsafe.Pointer(pBt)).FnTransaction - 1 if 0 == (*TBtShared)(unsafe.Pointer(pBt)).FnTransaction { (*TBtShared)(unsafe.Pointer(pBt)).FinTransaction = uint8(TRANS_NONE) } } /* Set the current transaction state to TRANS_NONE and unlock the ** pager if this call closed the only read or write transaction. */ (*TBtree)(unsafe.Pointer(p)).FinTrans = uint8(TRANS_NONE) _unlockBtreeIfUnused(tls, pBt) } } // C documentation // // /* // ** Initialize the auxiliary information for a disk block. // ** // ** Return SQLITE_OK on success. If we see that the page does // ** not contain a well-formed database page, then return // ** SQLITE_CORRUPT. Note that a return of SQLITE_OK does not // ** guarantee that the page is well-formed. It only shows that // ** we failed to detect any corruption. // */ func _btreeInitPage(tls *libc.TLS, pPage uintptr) (r int32) { var data, pBt uintptr _, _ = data, pBt /* The main btree structure */ pBt = (*TMemPage)(unsafe.Pointer(pPage)).FpBt data = (*TMemPage)(unsafe.Pointer(pPage)).FaData + uintptr((*TMemPage)(unsafe.Pointer(pPage)).FhdrOffset) /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating ** the b-tree page type. */ if _decodeFlags(tls, pPage, libc.Int32FromUint8(**(**Tu8)(__ccgo_up(data)))) != 0 { return _sqlite3CorruptError(tls, int32(75461)) } (*TMemPage)(unsafe.Pointer(pPage)).FmaskPage = uint16((*TBtShared)(unsafe.Pointer(pBt)).FpageSize - libc.Uint32FromInt32(1)) (*TMemPage)(unsafe.Pointer(pPage)).FnOverflow = uint8(0) (*TMemPage)(unsafe.Pointer(pPage)).FcellOffset = libc.Uint16FromInt32(libc.Int32FromUint8((*TMemPage)(unsafe.Pointer(pPage)).FhdrOffset) + libc.Int32FromInt32(8) + libc.Int32FromUint8((*TMemPage)(unsafe.Pointer(pPage)).FchildPtrSize)) (*TMemPage)(unsafe.Pointer(pPage)).FaCellIdx = data + uintptr((*TMemPage)(unsafe.Pointer(pPage)).FchildPtrSize) + uintptr(8) (*TMemPage)(unsafe.Pointer(pPage)).FaDataEnd = (*TMemPage)(unsafe.Pointer(pPage)).FaData + uintptr((*TBtShared)(unsafe.Pointer(pBt)).FpageSize) (*TMemPage)(unsafe.Pointer(pPage)).FaDataOfst = (*TMemPage)(unsafe.Pointer(pPage)).FaData + uintptr((*TMemPage)(unsafe.Pointer(pPage)).FchildPtrSize) /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the ** number of cells on the page. */ (*TMemPage)(unsafe.Pointer(pPage)).FnCell = libc.Uint16FromInt32(libc.Int32FromUint8(**(**Tu8)(__ccgo_up(data + 3)))< ((*TBtShared)(unsafe.Pointer(pBt)).FpageSize-uint32(8))/uint32(6) { /* To many cells for a single page. The page must be corrupt */ return _sqlite3CorruptError(tls, int32(75475)) } /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only ** possible for a root page of a table that contains no rows) then the ** offset to the cell content area will equal the page size minus the ** bytes of reserved space. */ (*TMemPage)(unsafe.Pointer(pPage)).FnFree = -int32(1) /* Indicate that this value is yet uncomputed */ (*TMemPage)(unsafe.Pointer(pPage)).FisInit = uint8(1) if (*Tsqlite3)(unsafe.Pointer((*TBtShared)(unsafe.Pointer(pBt)).Fdb)).Fflags&uint64(SQLITE_CellSizeCk) != 0 { return _btreeCellSizeCheck(tls, pPage) } return SQLITE_OK } // C documentation // // /* // ** In this version of BtreeMoveto, pKey is a packed index record // ** such as is generated by the OP_MakeRecord opcode. Unpack the // ** record and then call sqlite3BtreeIndexMoveto() to do the work. // */ func _btreeMoveto(tls *libc.TLS, pCur uintptr, pKey uintptr, nKey Ti64, bias int32, pRes uintptr) (r int32) { var pIdxKey, pKeyInfo uintptr var rc int32 _, _, _ = pIdxKey, pKeyInfo, rc /* Unpacked index key */ if pKey != 0 { pKeyInfo = (*TBtCursor)(unsafe.Pointer(pCur)).FpKeyInfo pIdxKey = _sqlite3VdbeAllocUnpackedRecord(tls, pKeyInfo) if pIdxKey == uintptr(0) { return int32(SQLITE_NOMEM) } _sqlite3VdbeRecordUnpack(tls, int32(nKey), pKey, pIdxKey) if libc.Int32FromUint16((*TUnpackedRecord)(unsafe.Pointer(pIdxKey)).FnField) == 0 || libc.Int32FromUint16((*TUnpackedRecord)(unsafe.Pointer(pIdxKey)).FnField) > libc.Int32FromUint16((*TKeyInfo)(unsafe.Pointer(pKeyInfo)).FnAllField) { rc = _sqlite3CorruptError(tls, int32(74103)) } else { rc = _sqlite3BtreeIndexMoveto(tls, pCur, pIdxKey, pRes) } _sqlite3DbFree(tls, (*TKeyInfo)(unsafe.Pointer((*TBtCursor)(unsafe.Pointer(pCur)).FpKeyInfo)).Fdb, pIdxKey) } else { pIdxKey = uintptr(0) rc = _sqlite3BtreeTableMoveto(tls, pCur, nKey, bias, pRes) } return rc } // C documentation // // /* // ** Overwrite the cell that cursor pCur is pointing to with fresh content // ** contained in pX. // */ func _btreeOverwriteCell(tls *libc.TLS, pCur uintptr, pX uintptr) (r int32) { var nTotal int32 var pPage uintptr _, _ = nTotal, pPage nTotal = (*TBtreePayload)(unsafe.Pointer(pX)).FnData + (*TBtreePayload)(unsafe.Pointer(pX)).FnZero /* Total bytes of to write */ pPage = (*TBtCursor)(unsafe.Pointer(pCur)).FpPage /* Page being written */ if (*TBtCursor)(unsafe.Pointer(pCur)).Finfo.FpPayload+uintptr((*TBtCursor)(unsafe.Pointer(pCur)).Finfo.FnLocal) > (*TMemPage)(unsafe.Pointer(pPage)).FaDataEnd || (*TBtCursor)(unsafe.Pointer(pCur)).Finfo.FpPayload < (*TMemPage)(unsafe.Pointer(pPage)).FaData+uintptr((*TMemPage)(unsafe.Pointer(pPage)).FcellOffset) { return _sqlite3CorruptError(tls, int32(82592)) } if libc.Int32FromUint16((*TBtCursor)(unsafe.Pointer(pCur)).Finfo.FnLocal) == nTotal { /* The entire cell is local */ return _btreeOverwriteContent(tls, pPage, (*TBtCursor)(unsafe.Pointer(pCur)).Finfo.FpPayload, pX, 0, libc.Int32FromUint16((*TBtCursor)(unsafe.Pointer(pCur)).Finfo.FnLocal)) } else { /* The cell contains overflow content */ return _btreeOverwriteOverflowCell(tls, pCur, pX) } return r } // C documentation // // /* // ** Overwrite the cell that cursor pCur is pointing to with fresh content // ** contained in pX. In this variant, pCur is pointing to an overflow // ** cell. // */ func _btreeOverwriteOverflowCell(tls *libc.TLS, pCur uintptr, pX uintptr) (r int32) { bp := tls.Alloc(16) defer tls.Free(16) var iOffset, nTotal, rc int32 var ovflPageSize Tu32 var ovflPgno TPgno var pBt uintptr var _ /* pPage at bp+0 */ uintptr _, _, _, _, _, _ = iOffset, nTotal, ovflPageSize, ovflPgno, pBt, rc /* Next byte of pX->pData to write */ nTotal = (*TBtreePayload)(unsafe.Pointer(pX)).FnData + (*TBtreePayload)(unsafe.Pointer(pX)).FnZero /* Return code */ **(**uintptr)(__ccgo_up(bp)) = (*TBtCursor)(unsafe.Pointer(pCur)).FpPage /* Size to write on overflow page */ /* pCur is an overflow cell */ /* Overwrite the local portion first */ rc = _btreeOverwriteContent(tls, **(**uintptr)(__ccgo_up(bp)), (*TBtCursor)(unsafe.Pointer(pCur)).Finfo.FpPayload, pX, 0, libc.Int32FromUint16((*TBtCursor)(unsafe.Pointer(pCur)).Finfo.FnLocal)) if rc != 0 { return rc } /* Now overwrite the overflow pages */ iOffset = libc.Int32FromUint16((*TBtCursor)(unsafe.Pointer(pCur)).Finfo.FnLocal) ovflPgno = _sqlite3Get4byte(tls, (*TBtCursor)(unsafe.Pointer(pCur)).Finfo.FpPayload+uintptr(iOffset)) pBt = (*TMemPage)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FpBt ovflPageSize = (*TBtShared)(unsafe.Pointer(pBt)).FusableSize - uint32(4) for cond := true; cond; cond = iOffset < nTotal { rc = _btreeGetPage(tls, pBt, ovflPgno, bp, 0) if rc != 0 { return rc } if _sqlite3PagerPageRefcount(tls, (*TMemPage)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FpDbPage) != int32(1) || (*TMemPage)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FisInit != 0 { rc = _sqlite3CorruptError(tls, int32(82564)) } else { if libc.Uint32FromInt32(iOffset)+ovflPageSize < libc.Uint32FromInt32(nTotal) { ovflPgno = _sqlite3Get4byte(tls, (*TMemPage)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FaData) } else { ovflPageSize = libc.Uint32FromInt32(nTotal - iOffset) } rc = _btreeOverwriteContent(tls, **(**uintptr)(__ccgo_up(bp)), (*TMemPage)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FaData+uintptr(4), pX, iOffset, libc.Int32FromUint32(ovflPageSize)) } _sqlite3PagerUnref(tls, (*TMemPage)(unsafe.Pointer(**(**uintptr)(__ccgo_up(bp)))).FpDbPage) if rc != 0 { return rc } iOffset = libc.Int32FromUint32(uint32(iOffset) + ovflPageSize) } return SQLITE_OK } // C documentation // // /* // ** Convert a DbPage obtained from the pager into a MemPage used by // ** the btree layer. // */ func _btreePageFromDbPage(tls *libc.TLS, pDbPage uintptr, pgno TPgno, pBt uintptr) (r uintptr) { var pPage uintptr var v1 int32 _, _ = pPage, v1 pPage = _sqlite3PagerGetExtra(tls, pDbPage) if pgno != (*TMemPage)(unsafe.Pointer(pPage)).Fpgno { (*TMemPage)(unsafe.Pointer(pPage)).FaData = _sqlite3PagerGetData(tls, pDbPage) (*TMemPage)(unsafe.Pointer(pPage)).FpDbPage = pDbPage (*TMemPage)(unsafe.Pointer(pPage)).FpBt = pBt (*TMemPage)(unsafe.Pointer(pPage)).Fpgno = pgno if pgno == uint32(1) { v1 = int32(100) } else { v1 = 0 } (*TMemPage)(unsafe.Pointer(pPage)).FhdrOffset = libc.Uint8FromInt32(v1) } return pPage } // C documentation // // /* // ** The following routines are implementations of the MemPage.xParseCell() // ** method. // ** // ** Parse a cell content block and fill in the CellInfo structure. // ** // ** btreeParseCellPtr() => table btree leaf nodes // ** btreeParseCellNoPayload() => table btree internal nodes // ** btreeParseCellPtrIndex() => index btree nodes // ** // ** There is also a wrapper function btreeParseCell() that works for // ** all MemPage types and that references the cell by index rather than // ** by pointer. // */ func _btreeParseCellPtrNoPayload(tls *libc.TLS, pPage uintptr, pCell uintptr, pInfo uintptr) { _ = pPage (*TCellInfo)(unsafe.Pointer(pInfo)).FnSize = libc.Uint16FromInt32(int32(4) + libc.Int32FromUint8(_sqlite3GetVarint(tls, pCell+4, pInfo))) (*TCellInfo)(unsafe.Pointer(pInfo)).FnPayload = uint32(0) (*TCellInfo)(unsafe.Pointer(pInfo)).FnLocal = uint16(0) (*TCellInfo)(unsafe.Pointer(pInfo)).FpPayload = uintptr(0) return } // C documentation // // /* // ** Given a record with nPayload bytes of payload stored within btree // ** page pPage, return the number of bytes of payload stored locally. // */ func _btreePayloadToLocal(tls *libc.TLS, pPage uintptr, nPayload Ti64) (r int32) { var maxLocal, minLocal, surplus, v1 int32 _, _, _, _ = maxLocal, minLocal, surplus, v1 /* Maximum amount of payload held locally */ maxLocal = libc.Int32FromUint16((*TMemPage)(unsafe.Pointer(pPage)).FmaxLocal) if nPayload <= int64(maxLocal) { return int32(nPayload) } else { /* Overflow payload available for local storage */ minLocal = libc.Int32FromUint16((*TMemPage)(unsafe.Pointer(pPage)).FminLocal) surplus = int32(int64(minLocal) + (nPayload-int64(minLocal))%libc.Int64FromUint32((*TBtShared)(unsafe.Pointer((*TMemPage)(unsafe.Pointer(pPage)).FpBt)).FusableSize-libc.Uint32FromInt32(4))) if surplus <= maxLocal { v1 = surplus } else { v1 = minLocal } return v1 } return r } // C documentation // // /* // ** Restore the cursor to the position it was in (or as close to as possible) // ** when saveCursorPosition() was called. Note that this call deletes the // ** saved position info stored by saveCursorPosition(), so there can be // ** at most one effective restoreCursorPosition() call after each // ** saveCursorPosition(). // */ func _btreeRestoreCursorPosition(tls *libc.TLS, pCur uintptr) (r int32) { bp := tls.Alloc(16) defer tls.Free(16) var rc int32 var _ /* skipNext at bp+0 */ int32 _ = rc **(**int32)(__ccgo_up(bp)) = 0 if libc.Int32FromUint8((*TBtCursor)(unsafe.Pointer(pCur)).FeState) == int32(CURSOR_FAULT) { return (*TBtCursor)(unsafe.Pointer(pCur)).FskipNext } (*TBtCursor)(unsafe.Pointer(pCur)).FeState = uint8(CURSOR_INVALID) if _sqlite3FaultSim(tls, int32(410)) != 0 { rc = int32(SQLITE_IOERR) } else { rc = _btreeMoveto(tls, pCur, (*TBtCursor)(unsafe.Pointer(pCur)).FpKey, (*TBtCursor)(unsafe.Pointer(pCur)).FnKey, 0, bp) } if rc == SQLITE_OK { Xsqlite3_free(tls, (*TBtCursor)(unsafe.Pointer(pCur)).FpKey) (*TBtCursor)(unsafe.Pointer(pCur)).FpKey = uintptr(0) if **(**int32)(__ccgo_up(bp)) != 0 { (*TBtCursor)(unsafe.Pointer(pCur)).FskipNext = **(**int32)(__ccgo_up(bp)) } if (*TBtCursor)(unsafe.Pointer(pCur)).FskipNext != 0 && libc.Int32FromUint8((*TBtCursor)(unsafe.Pointer(pCur)).FeState) == CURSOR_VALID { (*TBtCursor)(unsafe.Pointer(pCur)).FeState = uint8(CURSOR_SKIPNEXT) } } return rc } // C documentation // // /* // ** Set the pBt->nPage field correctly, according to the current // ** state of the database. Assume pBt->pPage1 is valid. // */ func _btreeSetNPage(tls *libc.TLS, pBt uintptr, pPage1 uintptr) { bp := tls.Alloc(16) defer tls.Free(16) var _ /* nPage at bp+0 */ int32 **(**int32)(__ccgo_up(bp)) = libc.Int32FromUint32(_sqlite3Get4byte(tls, (*TMemPage)(unsafe.Pointer(pPage1)).FaData+28)) if **(**int32)(__ccgo_up(bp)) == 0 { _sqlite3PagerPagecount(tls, (*TBtShared)(unsafe.Pointer(pBt)).FpPager, bp) } (*TBtShared)(unsafe.Pointer(pBt)).FnPage = libc.Uint32FromInt32(**(**int32)(__ccgo_up(bp))) } // C documentation // // /* // ** Implementation of the octet_length() function // */ func _bytelengthFunc(tls *libc.TLS, context uintptr, argc int32, argv uintptr) { var m Ti64 var v1 int32 _, _ = m, v1 _ = argc switch Xsqlite3_value_type(tls, **(**uintptr)(__ccgo_up(argv))) { case int32(SQLITE_BLOB): Xsqlite3_result_int(tls, context, Xsqlite3_value_bytes(tls, **(**uintptr)(__ccgo_up(argv)))) case int32(SQLITE_INTEGER): fallthrough case int32(SQLITE_FLOAT): if libc.Int32FromUint8((*Tsqlite3)(unsafe.Pointer(Xsqlite3_context_db_handle(tls, context))).Fenc) <= int32(SQLITE_UTF8) { v1 = int32(1) } else { v1 = int32(2) } m = int64(v1) Xsqlite3_result_int64(tls, context, int64(Xsqlite3_value_bytes(tls, **(**uintptr)(__ccgo_up(argv))))*m) case int32(SQLITE_TEXT): if Xsqlite3_value_encoding(tls, **(**uintptr)(__ccgo_up(argv))) <= int32(SQLITE_UTF8) { Xsqlite3_result_int(tls, context, Xsqlite3_value_bytes(tls, **(**uintptr)(__ccgo_up(argv)))) } else { Xsqlite3_result_int(tls, context, Xsqlite3_value_bytes16(tls, **(**uintptr)(__ccgo_up(argv)))) } default: Xsqlite3_result_null(tls, context) break } } // C documentation // // /* // ** Return the N-dimensional volume of the cell stored in *p. // */ func _cellArea(tls *libc.TLS, pRtree uintptr, p uintptr) (r TRtreeDValue) { var area TRtreeDValue _ = area area = libc.Float64FromInt32(1) if libc.Int32FromUint8((*TRtree)(unsafe.Pointer(pRtree)).FeCoordType) == RTREE_COORD_REAL32 { switch libc.Int32FromUint8((*TRtree)(unsafe.Pointer(pRtree)).FnDim) { case int32(5): area = float64(*(*TRtreeValue)(unsafe.Pointer(p + 8 + 9*4)) - *(*TRtreeValue)(unsafe.Pointer(p + 8 + 8*4))) fallthrough case int32(4): area = area * float64(*(*TRtreeValue)(unsafe.Pointer(p + 8 + 7*4))-*(*TRtreeValue)(unsafe.Pointer(p + 8 + 6*4))) fallthrough case int32(3): area = area * float64(*(*TRtreeValue)(unsafe.Pointer(p + 8 + 5*4))-*(*TRtreeValue)(unsafe.Pointer(p + 8 + 4*4))) fallthrough case int32(2): area = area * float64(*(*TRtreeValue)(unsafe.Pointer(p + 8 + 3*4))-*(*TRtreeValue)(unsafe.Pointer(p + 8 + 2*4))) fallthrough default: area = area * float64(*(*TRtreeValue)(unsafe.Pointer(p + 8 + 1*4))-*(*TRtreeValue)(unsafe.Pointer(p + 8))) } } else { switch libc.Int32FromUint8((*TRtree)(unsafe.Pointer(pRtree)).FnDim) { case int32(5): area = float64(int64(*(*int32)(unsafe.Pointer(p + 8 + 9*4))) - int64(*(*int32)(unsafe.Pointer(p + 8 + 8*4)))) fallthrough case int32(4): area = area * float64(int64(*(*int32)(unsafe.Pointer(p + 8 + 7*4)))-int64(*(*int32)(unsafe.Pointer(p + 8 + 6*4)))) fallthrough case int32(3): area = area * float64(int64(*(*int32)(unsafe.Pointer(p + 8 + 5*4)))-int64(*(*int32)(unsafe.Pointer(p + 8 + 4*4)))) fallthrough case int32(2): area = area * float64(int64(*(*int32)(unsafe.Pointer(p + 8 + 3*4)))-int64(*(*int32)(unsafe.Pointer(p + 8 + 2*4)))) fallthrough default: area = area * float64(int64(*(*int32)(unsafe.Pointer(p + 8 + 1*4)))-int64(*(*int32)(unsafe.Pointer(p + 8)))) } } return area } // C documentation // // /* // ** Return true if the area covered by p2 is a subset of the area covered // ** by p1. False otherwise. // */ func _cellContains(tls *libc.TLS, pRtree uintptr, p1 uintptr, p2 uintptr) (r int32) { var a1, a11, a2, a21 uintptr var ii int32 _, _, _, _, _ = a1, a11, a2, a21, ii if libc.Int32FromUint8((*TRtree)(unsafe.Pointer(pRtree)).FeCoordType) == int32(RTREE_COORD_INT32) { ii = 0 for { if !(ii < libc.Int32FromUint8((*TRtree)(unsafe.Pointer(pRtree)).FnDim2)) { break } a1 = p1 + 8 + uintptr(ii)*4 a2 = p2 + 8 + uintptr(ii)*4 if *(*int32)(unsafe.Pointer(a2)) < *(*int32)(unsafe.Pointer(a1)) || *(*int32)(unsafe.Pointer(a2 + 1*4)) > *(*int32)(unsafe.Pointer(a1 + 1*4)) { return 0 } goto _1 _1: ; ii = ii + int32(2) } } else { ii = 0 for { if !(ii < libc.Int32FromUint8((*TRtree)(unsafe.Pointer(pRtree)).FnDim2)) { break } a11 = p1 + 8 + uintptr(ii)*4 a21 = p2 + 8 + uintptr(ii)*4 if *(*TRtreeValue)(unsafe.Pointer(a21)) < *(*TRtreeValue)(unsafe.Pointer(a11)) || *(*TRtreeValue)(unsafe.Pointer(a21 + 1*4)) > *(*TRtreeValue)(unsafe.Pointer(a11 + 1*4)) { return 0 } goto _2 _2: ; ii = ii + int32(2) } } return int32(1) } // C documentation // // /* // ** Return the margin length of cell p. The margin length is the sum // ** of the objects size in each dimension. // */ func _cellMargin(tls *libc.TLS, pRtree uintptr, p uintptr) (r TRtreeDValue) { var ii int32 var margin TRtreeDValue var v1, v2 float64 _, _, _, _ = ii, margin, v1, v2 margin = libc.Float64FromInt32(0) ii = libc.Int32FromUint8((*TRtree)(unsafe.Pointer(pRtree)).FnDim2) - int32(2) for cond := true; cond; cond = ii >= 0 { if libc.Int32FromUint8((*TRtree)(unsafe.Pointer(pRtree)).FeCoordType) == RTREE_COORD_REAL32 { v1 = float64(*(*TRtreeValue)(unsafe.Pointer(p + 8 + uintptr(ii+int32(1))*4))) } else { v1 = float64(*(*int32)(unsafe.Pointer(p + 8 + uintptr(ii+int32(1))*4))) } if libc.Int32FromUint8((*TRtree)(unsafe.Pointer(pRtree)).FeCoordType) == RTREE_COORD_REAL32 { v2 = float64(*(*TRtreeValue)(unsafe.Pointer(p + 8 + uintptr(ii)*4))) } else { v2 = float64(*(*int32)(unsafe.Pointer(p + 8 + uintptr(ii)*4))) } margin = margin + (v1 - v2) ii = ii - int32(2) } return margin } // C documentation // // /* // ** Store the union of cells p1 and p2 in p1. // */ func _cellUnion(tls *libc.TLS, pRtree uintptr, p1 uintptr, p2 uintptr) { var ii, v3 int32 var v1 TRtreeValue _, _, _ = ii, v1, v3 ii = 0 if libc.Int32FromUint8((*TRtree)(unsafe.Pointer(pRtree)).FeCoordType) == RTREE_COORD_REAL32 { for cond := true; cond; cond = ii < libc.Int32FromUint8((*TRtree)(unsafe.Pointer(pRtree)).FnDim2) { if *(*TRtreeValue)(unsafe.Pointer(p1 + 8 + uintptr(ii)*4)) < *(*TRtreeValue)(unsafe.Pointer(p2 + 8 + uintptr(ii)*4)) { v1 = *(*TRtreeValue)(unsafe.Pointer(p1 + 8 + uintptr(ii)*4)) } else { v1 = *(*TRtreeValue)(unsafe.Pointer(p2 + 8 + uintptr(ii)*4)) } *(*TRtreeValue)(unsafe.Pointer(p1 + 8 + uintptr(ii)*4)) = v1 if *(*TRtreeValue)(unsafe.Pointer(p1 + 8 + uintptr(ii+int32(1))*4)) > *(*TRtreeValue)(unsafe.Pointer(p2 + 8 + uintptr(ii+int32(1))*4)) { v1 = *(*TRtreeValue)(unsafe.Pointer(p1 + 8 + uintptr(ii+int32(1))*4)) } else { v1 = *(*TRtreeValue)(unsafe.Pointer(p2 + 8 + uintptr(ii+int32(1))*4)) } *(*TRtreeValue)(unsafe.Pointer(p1 + 8 + uintptr(ii+int32(1))*4)) = v1 ii = ii + int32(2) } } else { for cond := true; cond; cond = ii < libc.Int32FromUint8((*TRtree)(unsafe.Pointer(pRtree)).FnDim2) { if *(*int32)(unsafe.Pointer(p1 + 8 + uintptr(ii)*4)) < *(*int32)(unsafe.Pointer(p2 + 8 + uintptr(ii)*4)) { v3 = *(*int32)(unsafe.Pointer(p1 + 8 + uintptr(ii)*4)) } else { v3 = *(*int32)(unsafe.Pointer(p2 + 8 + uintptr(ii)*4)) } *(*int32)(unsafe.Pointer(p1 + 8 + uintptr(ii)*4)) = v3 if *(*int32)(unsafe.Pointer(p1 + 8 + uintptr(ii+int32(1))*4)) > *(*int32)(unsafe.Pointer(p2 + 8 + uintptr(ii+int32(1))*4)) { v3 = *(*int32)(unsafe.Pointer(p1 + 8 + uintptr(ii+int32(1))*4)) } else { v3 = *(*int32)(unsafe.Pointer(p2 + 8 + uintptr(ii+int32(1))*4)) } *(*int32)(unsafe.Pointer(p1 + 8 + uintptr(ii+int32(1))*4)) = v3 ii = ii + int32(2) } } } // C documentation // // /* // ** If the TEMP database is open, close it and mark the database schema // ** as needing reloading. This must be done when using the SQLITE_TEMP_STORE // ** or DEFAULT_TEMP_STORE pragmas. // */ func _changeTempStorage(tls *libc.TLS, pParse uintptr, zStorageType uintptr) (r int32) { var db uintptr var ts int32 _, _ = db, ts ts = _getTempStore(tls, zStorageType) db = (*TParse)(unsafe.Pointer(pParse)).Fdb if libc.Int32FromUint8((*Tsqlite3)(unsafe.Pointer(db)).Ftemp_store) == ts { return SQLITE_OK } if _invalidateTempStorage(tls, pParse) != SQLITE_OK { return int32(SQLITE_ERROR) } (*Tsqlite3)(unsafe.Pointer(db)).Ftemp_store = libc.Uint8FromInt32(ts) return SQLITE_OK } // C documentation // // /* // ** Close all file descriptors accumulated in the unixInodeInfo->pUnused list. // */ func _closePendingFds(tls *libc.TLS, pFile uintptr) { var p, pInode, pNext uintptr _, _, _ = p, pInode, pNext pInode = (*TunixFile)(unsafe.Pointer(pFile)).FpInode p = (*TunixInodeInfo)(unsafe.Pointer(pInode)).FpUnused for { if !(p != 0) { break } pNext = (*TUnixUnusedFd)(unsafe.Pointer(p)).FpNext _robust_close(tls, pFile, (*TUnixUnusedFd)(unsafe.Pointer(p)).Ffd, int32(41675)) Xsqlite3_free(tls, p) goto _1 _1: ; p = pNext } (*TunixInodeInfo)(unsafe.Pointer(pInode)).FpUnused = uintptr(0) } // C documentation // // /* // ** Generate code for a comparison operator. // */ func _codeCompare(tls *libc.TLS, pParse uintptr, pLeft uintptr, pRight uintptr, opcode int32, in1 int32, in2 int32, dest int32, jumpIfNull int32, isCommuted int32) (r int32) { var addr, p5 int32 var p4 uintptr _, _, _ = addr, p4, p5 if (*TParse)(unsafe.Pointer(pParse)).FnErr != 0 { return 0 } if isCommuted != 0 { p4 = _sqlite3BinaryCompareCollSeq(tls, pParse, pRight, pLeft) } else { p4 = _sqlite3BinaryCompareCollSeq(tls, pParse, pLeft, pRight) } p5 = libc.Int32FromUint8(_binaryCompareP5(tls, pLeft, pRight, jumpIfNull)) addr = _sqlite3VdbeAddOp4(tls, (*TParse)(unsafe.Pointer(pParse)).FpVdbe, opcode, in2, dest, in1, p4, -int32(2)) _sqlite3VdbeChangeP5(tls, (*TParse)(unsafe.Pointer(pParse)).FpVdbe, libc.Uint16FromInt32(p5)) return addr } // C documentation // // /* // ** Generate code for a single equality term of the WHERE clause. An equality // ** term can be either X=expr or X IN (...). pTerm is the term to be // ** coded. // ** // ** The current value for the constraint is left in a register, the index // ** of which is returned. An attempt is made store the result in iTarget but // ** this is only guaranteed for TK_ISNULL and TK_IN constraints. If the // ** constraint is a TK_EQ or TK_IS, then the current value might be left in // ** some other register and it is the caller's responsibility to compensate. // ** // ** For a constraint of the form X=expr, the expression is evaluated in // ** straight-line code. For constraints of the form X IN (...) // ** this routine sets up a loop that will iterate over all values of X. // */ func _codeEqualityTerm(tls *libc.TLS, pParse uintptr, pTerm uintptr, pLevel uintptr, iEq int32, bRev int32, iTarget int32) (r int32) { var iReg int32 var pX uintptr _, _ = iReg, pX pX = (*TWhereTerm)(unsafe.Pointer(pTerm)).FpExpr /* Register holding results */ if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pX)).Fop) == int32(TK_EQ) || libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pX)).Fop) == int32(TK_IS) { iReg = _sqlite3ExprCodeTarget(tls, pParse, (*TExpr)(unsafe.Pointer(pX)).FpRight, iTarget) } else { if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pX)).Fop) == int32(TK_ISNULL) { iReg = iTarget _sqlite3VdbeAddOp2(tls, (*TParse)(unsafe.Pointer(pParse)).FpVdbe, int32(OP_Null), 0, iReg) } else { iReg = iTarget _codeINTerm(tls, pParse, pTerm, pLevel, iEq, bRev, iTarget) } } /* As an optimization, try to disable the WHERE clause term that is ** driving the index as it will always be true. The correct answer is ** obtained regardless, but we might get the answer with fewer CPU cycles ** by omitting the term. ** ** But do not disable the term unless we are certain that the term is ** not a transitive constraint. For an example of where that does not ** work, see https://sqlite.org/forum/forumpost/eb8613976a (2021-05-04) */ if (*TWhereLoop)(unsafe.Pointer((*TWhereLevel)(unsafe.Pointer(pLevel)).FpWLoop)).FwsFlags&uint32(WHERE_TRANSCONS) == uint32(0) || libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pTerm)).FeOperator)&int32(WO_EQUIV) == 0 { _disableTerm(tls, pLevel, pTerm) } return iReg } // C documentation // // /* // ** pMem currently only holds a string type (or maybe a BLOB that we can // ** interpret as a string if we want to). Compute its corresponding // ** numeric type, if has one. Set the pMem->u.r and pMem->u.i fields // ** accordingly. // */ func _computeNumericType(tls *libc.TLS, pMem uintptr) (r Tu16) { bp := tls.Alloc(16) defer tls.Free(16) var rc, v1 int32 var _ /* ix at bp+0 */ Tsqlite3_int64 _, _ = rc, v1 if libc.Int32FromUint16((*TMem)(unsafe.Pointer(pMem)).Fflags)&int32(MEM_Zero) != 0 { v1 = _sqlite3VdbeMemExpandBlob(tls, pMem) } else { v1 = 0 } if v1 != 0 { *(*Ti64)(unsafe.Pointer(pMem)) = 0 return uint16(MEM_Int) } rc = _sqlite3MemRealValueRC(tls, pMem, pMem) if rc <= 0 { if rc&int32(2) == 0 && _sqlite3Atoi64(tls, (*TMem)(unsafe.Pointer(pMem)).Fz, bp, (*TMem)(unsafe.Pointer(pMem)).Fn, (*TMem)(unsafe.Pointer(pMem)).Fenc) <= int32(1) { *(*Ti64)(unsafe.Pointer(pMem)) = **(**Tsqlite3_int64)(__ccgo_up(bp)) return uint16(MEM_Int) } else { return uint16(MEM_Real) } } else { if rc&int32(2) == 0 && _sqlite3Atoi64(tls, (*TMem)(unsafe.Pointer(pMem)).Fz, bp, (*TMem)(unsafe.Pointer(pMem)).Fn, (*TMem)(unsafe.Pointer(pMem)).Fenc) == 0 { *(*Ti64)(unsafe.Pointer(pMem)) = **(**Tsqlite3_int64)(__ccgo_up(bp)) return uint16(MEM_Int) } } return uint16(MEM_Real) } // C documentation // // /* // ** idxNum: // ** // ** 0 schema=main, full table scan // ** 1 schema=main, pgno=?1 // ** 2 schema=?1, full table scan // ** 3 schema=?1, pgno=?2 // */ func _dbpageBestIndex(tls *libc.TLS, tab uintptr, pIdxInfo uintptr) (r int32) { var i, iPlan, v3 int32 var p, p1 uintptr _, _, _, _, _ = i, iPlan, p, p1, v3 iPlan = 0 _ = tab /* If there is a schema= constraint, it must be honored. Report a ** ridiculously large estimated cost if the schema= constraint is ** unavailable */ i = 0 for { if !(i < (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FnConstraint) { break } p = (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaConstraint + uintptr(i)*12 if (*Tsqlite3_index_constraint)(unsafe.Pointer(p)).FiColumn != int32(DBPAGE_COLUMN_SCHEMA) { goto _1 } if libc.Int32FromUint8((*Tsqlite3_index_constraint)(unsafe.Pointer(p)).Fop) != int32(SQLITE_INDEX_CONSTRAINT_EQ) { goto _1 } if !((*Tsqlite3_index_constraint)(unsafe.Pointer(p)).Fusable != 0) { /* No solution. */ return int32(SQLITE_CONSTRAINT) } iPlan = int32(2) (**(**Tsqlite3_index_constraint_usage)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaConstraintUsage + uintptr(i)*8))).FargvIndex = int32(1) (**(**Tsqlite3_index_constraint_usage)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaConstraintUsage + uintptr(i)*8))).Fomit = uint8(1) break goto _1 _1: ; i = i + 1 } /* If we reach this point, it means that either there is no schema= ** constraint (in which case we use the "main" schema) or else the ** schema constraint was accepted. Lower the estimated cost accordingly */ (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FestimatedCost = float64(1e+06) /* Check for constraints against pgno */ i = 0 for { if !(i < (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FnConstraint) { break } p1 = (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaConstraint + uintptr(i)*12 if (*Tsqlite3_index_constraint)(unsafe.Pointer(p1)).Fusable != 0 && (*Tsqlite3_index_constraint)(unsafe.Pointer(p1)).FiColumn <= 0 && libc.Int32FromUint8((*Tsqlite3_index_constraint)(unsafe.Pointer(p1)).Fop) == int32(SQLITE_INDEX_CONSTRAINT_EQ) { (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FestimatedRows = int64(1) (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FidxFlags = int32(SQLITE_INDEX_SCAN_UNIQUE) (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FestimatedCost = float64(1) if iPlan != 0 { v3 = int32(2) } else { v3 = int32(1) } (**(**Tsqlite3_index_constraint_usage)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaConstraintUsage + uintptr(i)*8))).FargvIndex = v3 (**(**Tsqlite3_index_constraint_usage)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaConstraintUsage + uintptr(i)*8))).Fomit = uint8(1) iPlan = iPlan | int32(1) break } goto _2 _2: ; i = i + 1 } (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FidxNum = iPlan if (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FnOrderBy >= int32(1) && (**(**Tsqlite3_index_orderby)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaOrderBy))).FiColumn <= 0 && libc.Int32FromUint8((**(**Tsqlite3_index_orderby)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaOrderBy))).Fdesc) == 0 { (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).ForderByConsumed = int32(1) } return SQLITE_OK } func _dbpageRowid(tls *libc.TLS, pCursor uintptr, pRowid uintptr) (r int32) { var pCsr uintptr _ = pCsr pCsr = pCursor **(**Tsqlite_int64)(__ccgo_up(pRowid)) = libc.Int64FromUint32((*TDbpageCursor)(unsafe.Pointer(pCsr)).Fpgno) return SQLITE_OK } // C documentation // // /* // ** Delete the cell at index iCell of node pNode. After removing the // ** cell, adjust the r-tree data structure if required. // */ func _deleteCell(tls *libc.TLS, pRtree uintptr, pNode uintptr, iCell int32, iHeight int32) (r int32) { var pParent uintptr var rc, v1 int32 _, _, _ = pParent, rc, v1 v1 = _fixLeafParent(tls, pRtree, pNode) rc = v1 if SQLITE_OK != v1 { return rc } /* Remove the cell from the node. This call just moves bytes around ** the in-memory node image, so it cannot fail. */ _nodeDeleteCell(tls, pRtree, pNode, iCell) /* If the node is not the tree root and now has less than the minimum ** number of cells, remove it from the tree. Otherwise, update the ** cell in the parent node so that it tightly contains the updated ** node. */ pParent = (*TRtreeNode)(unsafe.Pointer(pNode)).FpParent if pParent != 0 { if _readInt16(tls, (*TRtreeNode)(unsafe.Pointer(pNode)).FzData+2) < ((*TRtree)(unsafe.Pointer(pRtree)).FiNodeSize-int32(4))/libc.Int32FromUint8((*TRtree)(unsafe.Pointer(pRtree)).FnBytesPerCell)/int32(3) { rc = _removeNode(tls, pRtree, pNode, iHeight) } else { rc = _fixBoundingBox(tls, pRtree, pNode) } } return rc } // C documentation // // /* // ** Write VDBE code to erase table pTab and all associated indices on disk. // ** Code to update the sqlite_schema tables and internal schema definitions // ** in case a root-page belonging to another table is moved by the btree layer // ** is also added (this can happen with an auto-vacuum database). // */ func _destroyTable(tls *libc.TLS, pParse uintptr, pTab uintptr) { var iDb int32 var iDestroyed, iIdx, iLargest, iTab TPgno var pIdx uintptr _, _, _, _, _, _ = iDb, iDestroyed, iIdx, iLargest, iTab, pIdx /* If the database may be auto-vacuum capable (if SQLITE_OMIT_AUTOVACUUM ** is not defined), then it is important to call OP_Destroy on the ** table and index root-pages in order, starting with the numerically ** largest root-page number. This guarantees that none of the root-pages ** to be destroyed is relocated by an earlier OP_Destroy. i.e. if the ** following were coded: ** ** OP_Destroy 4 0 ** ... ** OP_Destroy 5 0 ** ** and root page 5 happened to be the largest root-page number in the ** database, then root page 5 would be moved to page 4 by the ** "OP_Destroy 4 0" opcode. The subsequent "OP_Destroy 5 0" would hit ** a free-list page. */ iTab = (*TTable)(unsafe.Pointer(pTab)).Ftnum iDestroyed = uint32(0) for int32(1) != 0 { iLargest = uint32(0) if iDestroyed == uint32(0) || iTab < iDestroyed { iLargest = iTab } pIdx = (*TTable)(unsafe.Pointer(pTab)).FpIndex for { if !(pIdx != 0) { break } iIdx = (*TIndex)(unsafe.Pointer(pIdx)).Ftnum if (iDestroyed == uint32(0) || iIdx < iDestroyed) && iIdx > iLargest { iLargest = iIdx } goto _1 _1: ; pIdx = (*TIndex)(unsafe.Pointer(pIdx)).FpNext } if iLargest == uint32(0) { return } else { iDb = _sqlite3SchemaToIndex(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, (*TTable)(unsafe.Pointer(pTab)).FpSchema) _destroyRootPage(tls, pParse, libc.Int32FromUint32(iLargest), iDb) iDestroyed = iLargest } } } // C documentation // // /* // ** This routine checks if there is a RESERVED lock held on the specified // ** file by this or any other process. If the caller holds a SHARED // ** or greater lock when it is called, then it is assumed that no other // ** client may hold RESERVED. Or, if the caller holds no lock, then it // ** is assumed another client holds RESERVED if the lock-file exists. // */ func _dotlockCheckReservedLock(tls *libc.TLS, id uintptr, pResOut uintptr) (r int32) { var pFile uintptr _ = pFile pFile = id if libc.Int32FromUint8((*TunixFile)(unsafe.Pointer(pFile)).FeFileLock) >= int32(SHARED_LOCK) { **(**int32)(__ccgo_up(pResOut)) = 0 } else { **(**int32)(__ccgo_up(pResOut)) = libc.BoolInt32((*(*func(*libc.TLS, uintptr, int32) int32)(unsafe.Pointer(&struct{ uintptr }{_aSyscall[int32(2)].FpCurrent})))(tls, (*TunixFile)(unsafe.Pointer(pFile)).FlockingContext, 0) == 0) } return SQLITE_OK } var _dotlockIoFinder = uintptr(0) func _dotlockIoFinderImpl(tls *libc.TLS, z uintptr, p uintptr) (r uintptr) { _ = z _ = p return uintptr(unsafe.Pointer(&_dotlockIoMethods)) } var _dotlockIoMethods = Tsqlite3_io_methods{ FiVersion: int32(1), } // C documentation // // /* // ** Estimate the logarithm of the input value to base 2. // */ func _estLog(tls *libc.TLS, N TLogEst) (r TLogEst) { var v1 int32 _ = v1 if int32(N) <= int32(10) { v1 = 0 } else { v1 = int32(_sqlite3LogEst(tls, libc.Uint64FromInt16(N))) - int32(33) } return int16(v1) } // C documentation // // /* // ** If expression pExpr is of type TK_SELECT, generate code to evaluate // ** it. Return the register in which the result is stored (or, if the // ** sub-select returns more than one column, the first in an array // ** of registers in which the result is stored). // ** // ** If pExpr is not a TK_SELECT expression, return 0. // */ func _exprCodeSubselect(tls *libc.TLS, pParse uintptr, pExpr uintptr) (r int32) { var reg int32 _ = reg reg = 0 if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) == int32(TK_SELECT) { reg = _sqlite3CodeSubselect(tls, pParse, pExpr) } return reg } // C documentation // // /* // ** Generate code that evaluates an AND or OR operator leaving a // ** boolean result in a register. pExpr is the AND/OR expression. // ** Store the result in the "target" register. Use short-circuit // ** evaluation to avoid computing both operands, if possible. // ** // ** The code generated might require the use of a temporary register. // ** If it does, then write the number of that temporary register // ** into *pTmpReg. If not, leave *pTmpReg unchanged. // */ func _exprCodeTargetAndOr(tls *libc.TLS, pParse uintptr, pExpr uintptr, target int32, pTmpReg uintptr) (r int32) { var addrSkip, op, r1, r2, regSS, skipOp, v1 int32 var pAlt, v uintptr _, _, _, _, _, _, _, _, _ = addrSkip, op, pAlt, r1, r2, regSS, skipOp, v, v1 /* Branch instruction that skips one of the operands */ regSS = 0 /* statement being coded */ op = libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe pAlt = _sqlite3ExprSimplifiedAndOr(tls, pExpr) if pAlt != pExpr { r1 = _sqlite3ExprCodeTarget(tls, pParse, pAlt, target) _sqlite3VdbeAddOp3(tls, v, int32(OP_And), r1, r1, target) return target } if op == int32(TK_AND) { v1 = int32(OP_IfNot) } else { v1 = int32(OP_If) } skipOp = v1 if _exprEvalRhsFirst(tls, pExpr) != 0 { /* Compute the right operand first. Skip the computation of the left ** operand if the right operand fully determines the result */ v1 = _sqlite3ExprCodeTarget(tls, pParse, (*TExpr)(unsafe.Pointer(pExpr)).FpRight, target) regSS = v1 r2 = v1 addrSkip = _sqlite3VdbeAddOp1(tls, v, skipOp, r2) r1 = _sqlite3ExprCodeTemp(tls, pParse, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft, pTmpReg) } else { /* Compute the left operand first */ r1 = _sqlite3ExprCodeTarget(tls, pParse, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft, target) if (*TExpr)(unsafe.Pointer((*TExpr)(unsafe.Pointer(pExpr)).FpRight)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_Subquery)) != uint32(0) { /* Skip over the computation of the right operand if the right ** operand is a subquery and the left operand completely determines ** the result */ regSS = r1 addrSkip = _sqlite3VdbeAddOp1(tls, v, skipOp, r1) } else { v1 = libc.Int32FromInt32(0) regSS = v1 addrSkip = v1 } r2 = _sqlite3ExprCodeTemp(tls, pParse, (*TExpr)(unsafe.Pointer(pExpr)).FpRight, pTmpReg) } _sqlite3VdbeAddOp3(tls, v, op, r2, r1, target) if addrSkip != 0 { _sqlite3VdbeAddOp2(tls, v, int32(OP_Goto), 0, _sqlite3VdbeCurrentAddr(tls, v)+int32(2)) _sqlite3VdbeJumpHere(tls, v, addrSkip) _sqlite3VdbeAddOp3(tls, v, int32(OP_Or), regSS, regSS, target) } return target } // C documentation // // /* // ** Commute a comparison operator. Expressions of the form "X op Y" // ** are converted into "Y op X". // */ func _exprCommute(tls *libc.TLS, pParse uintptr, pExpr uintptr) (r Tu16) { var t uintptr _ = t if libc.Int32FromUint8((*TExpr)(unsafe.Pointer((*TExpr)(unsafe.Pointer(pExpr)).FpLeft)).Fop) == int32(TK_VECTOR) || libc.Int32FromUint8((*TExpr)(unsafe.Pointer((*TExpr)(unsafe.Pointer(pExpr)).FpRight)).Fop) == int32(TK_VECTOR) || _sqlite3BinaryCompareCollSeq(tls, pParse, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft, (*TExpr)(unsafe.Pointer(pExpr)).FpRight) != _sqlite3BinaryCompareCollSeq(tls, pParse, (*TExpr)(unsafe.Pointer(pExpr)).FpRight, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft) { **(**Tu32)(__ccgo_up(pExpr + 4)) ^= uint32(EP_Commuted) } t = (*TExpr)(unsafe.Pointer(pExpr)).FpRight (*TExpr)(unsafe.Pointer(pExpr)).FpRight = (*TExpr)(unsafe.Pointer(pExpr)).FpLeft (*TExpr)(unsafe.Pointer(pExpr)).FpLeft = t if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) >= int32(TK_GT) { (*TExpr)(unsafe.Pointer(pExpr)).Fop = libc.Uint8FromInt32(libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) - int32(TK_GT) ^ int32(2) + int32(TK_GT)) } return uint16(0) } // C documentation // // /* // ** Expression pVar is guaranteed to be an SQL variable. pExpr may be any // ** type of expression. // ** // ** If pExpr is a simple SQL value - an integer, real, string, blob // ** or NULL value - then the VDBE currently being prepared is configured // ** to re-prepare each time a new value is bound to variable pVar. // ** // ** Additionally, if pExpr is a simple SQL value and the value is the // ** same as that currently bound to variable pVar, non-zero is returned. // ** Otherwise, if the values are not the same or if pExpr is not a simple // ** SQL value, zero is returned. // ** // ** If the SQLITE_EnableQPSG flag is set on the database connection, then // ** this routine always returns false. // */ func _exprCompareVariable(tls *libc.TLS, pParse uintptr, pVar uintptr, pExpr uintptr) (r int32) { bp := tls.Alloc(16) defer tls.Free(16) var iVar, res, v1 int32 var pL uintptr var _ /* pR at bp+0 */ uintptr _, _, _, _ = iVar, pL, res, v1 res = int32(2) **(**uintptr)(__ccgo_up(bp)) = uintptr(0) if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) == int32(TK_VARIABLE) && int32((*TExpr)(unsafe.Pointer(pVar)).FiColumn) == int32((*TExpr)(unsafe.Pointer(pExpr)).FiColumn) { return 0 } if (*Tsqlite3)(unsafe.Pointer((*TParse)(unsafe.Pointer(pParse)).Fdb)).Fflags&uint64(SQLITE_EnableQPSG) != uint64(0) { return int32(2) } _sqlite3ValueFromExpr(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, pExpr, uint8(SQLITE_UTF8), uint8(SQLITE_AFF_BLOB), bp) if **(**uintptr)(__ccgo_up(bp)) != 0 { iVar = int32((*TExpr)(unsafe.Pointer(pVar)).FiColumn) _sqlite3VdbeSetVarmask(tls, (*TParse)(unsafe.Pointer(pParse)).FpVdbe, iVar) pL = _sqlite3VdbeGetBoundValue(tls, (*TParse)(unsafe.Pointer(pParse)).FpReprepare, iVar, uint8(SQLITE_AFF_BLOB)) if pL != 0 { if Xsqlite3_value_type(tls, pL) == int32(SQLITE_TEXT) { Xsqlite3_value_text(tls, pL) /* Make sure the encoding is UTF-8 */ } if _sqlite3MemCompare(tls, pL, **(**uintptr)(__ccgo_up(bp)), uintptr(0)) != 0 { v1 = int32(2) } else { v1 = 0 } res = v1 } _sqlite3ValueFree(tls, **(**uintptr)(__ccgo_up(bp))) _sqlite3ValueFree(tls, pL) } return res } // C documentation // // /* // ** Compute the two operands of a binary operator. // ** // ** If either operand contains a subquery, then the code strives to // ** compute the operand containing the subquery second. If the other // ** operand evalutes to NULL, then a jump is made. The address of the // ** IsNull operand that does this jump is returned. The caller can use // ** this to optimize the computation so as to avoid doing the potentially // ** expensive subquery. // ** // ** If no optimization opportunities exist, return 0. // */ func _exprComputeOperands(tls *libc.TLS, pParse uintptr, pExpr uintptr, pR1 uintptr, pR2 uintptr, pFree1 uintptr, pFree2 uintptr) (r int32) { var addrIsNull, r1, r2 int32 var v uintptr _, _, _, _ = addrIsNull, r1, r2, v v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe /* ** If the left operand contains a (possibly expensive) subquery and the ** right operand does not and the right operation might be NULL, ** then compute the right operand first and do an IsNull jump if the ** right operand evalutes to NULL. */ if _exprEvalRhsFirst(tls, pExpr) != 0 && _sqlite3ExprCanBeNull(tls, (*TExpr)(unsafe.Pointer(pExpr)).FpRight) != 0 { r2 = _sqlite3ExprCodeTemp(tls, pParse, (*TExpr)(unsafe.Pointer(pExpr)).FpRight, pFree2) addrIsNull = _sqlite3VdbeAddOp1(tls, v, int32(OP_IsNull), r2) } else { r2 = 0 /* Silence a false-positive uninit-var warning in MSVC */ addrIsNull = 0 } r1 = _sqlite3ExprCodeTemp(tls, pParse, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft, pFree1) if addrIsNull == 0 { /* ** If the right operand contains a subquery and the left operand does not ** and the left operand might be NULL, then do an IsNull check ** check on the left operand before computing the right operand. */ if (*TExpr)(unsafe.Pointer((*TExpr)(unsafe.Pointer(pExpr)).FpRight)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_Subquery)) != uint32(0) && _sqlite3ExprCanBeNull(tls, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft) != 0 { addrIsNull = _sqlite3VdbeAddOp1(tls, v, int32(OP_IsNull), r1) } r2 = _sqlite3ExprCodeTemp(tls, pParse, (*TExpr)(unsafe.Pointer(pExpr)).FpRight, pFree2) } **(**int32)(__ccgo_up(pR1)) = r1 **(**int32)(__ccgo_up(pR2)) = r2 return addrIsNull } // C documentation // // /* // ** Return true if it might be advantageous to compute the right operand // ** of expression pExpr first, before the left operand. // ** // ** Normally the left operand is computed before the right operand. But if // ** the left operand contains a subquery and the right does not, then it // ** might be more efficient to compute the right operand first. // */ func _exprEvalRhsFirst(tls *libc.TLS, pExpr uintptr) (r int32) { if (*TExpr)(unsafe.Pointer((*TExpr)(unsafe.Pointer(pExpr)).FpLeft)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_Subquery)) != uint32(0) && !((*TExpr)(unsafe.Pointer((*TExpr)(unsafe.Pointer(pExpr)).FpRight)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_Subquery)) != libc.Uint32FromInt32(0)) { return int32(1) } else { return 0 } return r } // C documentation // // /* // ** Helper function for exprIsDeterministic(). // */ func _exprNodeIsDeterministic(tls *libc.TLS, pWalker uintptr, pExpr uintptr) (r int32) { if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) == int32(TK_FUNCTION) && libc.BoolInt32((*TExpr)(unsafe.Pointer(pExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_ConstFunc)) != uint32(0)) == 0 { (*TWalker)(unsafe.Pointer(pWalker)).FeCode = uint16(0) return int32(WRC_Abort) } return WRC_Continue } // C documentation // // /* // ** The database opened by the first argument is an auto-vacuum database // ** nOrig pages in size containing nFree free pages. Return the expected // ** size of the database in pages following an auto-vacuum operation. // */ func _finalDbSize(tls *libc.TLS, pBt uintptr, nOrig TPgno, nFree TPgno) (r TPgno) { var nEntry int32 var nFin, nPtrmap TPgno _, _, _ = nEntry, nFin, nPtrmap /* Return value */ nEntry = libc.Int32FromUint32((*TBtShared)(unsafe.Pointer(pBt)).FusableSize / uint32(5)) nPtrmap = (nFree - nOrig + _ptrmapPageno(tls, pBt, nOrig) + libc.Uint32FromInt32(nEntry)) / libc.Uint32FromInt32(nEntry) nFin = nOrig - nFree - nPtrmap if nOrig > libc.Uint32FromInt32(_sqlite3PendingByte)/(*TBtShared)(unsafe.Pointer(pBt)).FpageSize+libc.Uint32FromInt32(1) && nFin < libc.Uint32FromInt32(_sqlite3PendingByte)/(*TBtShared)(unsafe.Pointer(pBt)).FpageSize+libc.Uint32FromInt32(1) { nFin = nFin - 1 } for _ptrmapPageno(tls, pBt, nFin) == nFin || nFin == libc.Uint32FromInt32(_sqlite3PendingByte)/(*TBtShared)(unsafe.Pointer(pBt)).FpageSize+libc.Uint32FromInt32(1) { nFin = nFin - 1 } return nFin } // C documentation // // /* // ** Find all terms of COLUMN=VALUE or VALUE=COLUMN in pExpr where VALUE // ** is a constant expression and where the term must be true because it // ** is part of the AND-connected terms of the expression. For each term // ** found, add it to the pConst structure. // */ func _findConstInWhere(tls *libc.TLS, pConst uintptr, pExpr uintptr) { var pLeft, pRight uintptr _, _ = pLeft, pRight if pExpr == uintptr(0) { return } if (*TExpr)(unsafe.Pointer(pExpr)).Fflags&(*TWhereConst)(unsafe.Pointer(pConst)).FmExcludeOn != uint32(0) { return } if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) == int32(TK_AND) { _findConstInWhere(tls, pConst, (*TExpr)(unsafe.Pointer(pExpr)).FpRight) _findConstInWhere(tls, pConst, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft) return } if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) != int32(TK_EQ) { return } pRight = (*TExpr)(unsafe.Pointer(pExpr)).FpRight pLeft = (*TExpr)(unsafe.Pointer(pExpr)).FpLeft if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pRight)).Fop) == int32(TK_COLUMN) && _sqlite3ExprIsConstant(tls, (*TWhereConst)(unsafe.Pointer(pConst)).FpParse, pLeft) != 0 { _constInsert(tls, pConst, pRight, pLeft, pExpr) } if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pLeft)).Fop) == int32(TK_COLUMN) && _sqlite3ExprIsConstant(tls, (*TWhereConst)(unsafe.Pointer(pConst)).FpParse, pRight) != 0 { _constInsert(tls, pConst, pLeft, pRight, pExpr) } } // C documentation // // /* // ** This routine runs after codeDistinct(). It makes necessary // ** adjustments to the OP_OpenEphemeral opcode that the codeDistinct() // ** routine made use of. This processing must be done separately since // ** sometimes codeDistinct is called before the OP_OpenEphemeral is actually // ** laid down. // ** // ** WHERE_DISTINCT_NOOP: // ** WHERE_DISTINCT_UNORDERED: // ** // ** No adjustments necessary. This function is a no-op. // ** // ** WHERE_DISTINCT_UNIQUE: // ** // ** The ephemeral table is not needed. So change the // ** OP_OpenEphemeral opcode into an OP_Noop. // ** // ** WHERE_DISTINCT_ORDERED: // ** // ** The ephemeral table is not needed. But we do need register // ** iVal to be initialized to NULL. So change the OP_OpenEphemeral // ** into an OP_Null on the iVal register. // */ func _fixDistinctOpenEph(tls *libc.TLS, pParse uintptr, eTnctType int32, iVal int32, iOpenEphAddr int32) { var pOp, v uintptr _, _ = pOp, v if (*TParse)(unsafe.Pointer(pParse)).FnErr == 0 && (eTnctType == int32(WHERE_DISTINCT_UNIQUE) || eTnctType == int32(WHERE_DISTINCT_ORDERED)) { v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe _sqlite3VdbeChangeToNoop(tls, v, iOpenEphAddr) if libc.Int32FromUint8((*TVdbeOp)(unsafe.Pointer(_sqlite3VdbeGetOp(tls, v, iOpenEphAddr+int32(1)))).Fopcode) == int32(OP_Explain) { _sqlite3VdbeChangeToNoop(tls, v, iOpenEphAddr+int32(1)) } if eTnctType == int32(WHERE_DISTINCT_ORDERED) { /* Change the OP_OpenEphemeral to an OP_Null that sets the MEM_Cleared ** bit on the first register of the previous value. This will cause the ** OP_Ne added in codeDistinct() to always fail on the first iteration of ** the loop even if the first row is all NULLs. */ pOp = _sqlite3VdbeGetOp(tls, v, iOpenEphAddr) (*TVdbeOp)(unsafe.Pointer(pOp)).Fopcode = uint8(OP_Null) (*TVdbeOp)(unsafe.Pointer(pOp)).Fp1 = int32(1) (*TVdbeOp)(unsafe.Pointer(pOp)).Fp2 = iVal } } } // C documentation // // /* // ** This function is called when a row is inserted into or deleted from the // ** child table of foreign key constraint pFKey. If an SQL UPDATE is executed // ** on the child table of pFKey, this function is invoked twice for each row // ** affected - once to "delete" the old row, and then again to "insert" the // ** new row. // ** // ** Each time it is called, this function generates VDBE code to locate the // ** row in the parent table that corresponds to the row being inserted into // ** or deleted from the child table. If the parent row can be found, no // ** special action is taken. Otherwise, if the parent row can *not* be // ** found in the parent table: // ** // ** Operation | FK type | Action taken // ** -------------------------------------------------------------------------- // ** INSERT immediate Increment the "immediate constraint counter". // ** // ** DELETE immediate Decrement the "immediate constraint counter". // ** // ** INSERT deferred Increment the "deferred constraint counter". // ** // ** DELETE deferred Decrement the "deferred constraint counter". // ** // ** These operations are identified in the comment at the top of this file // ** (fkey.c) as "I.1" and "D.1". // */ func _fkLookupParent(tls *libc.TLS, pParse uintptr, iDb int32, pTab uintptr, pIdx uintptr, pFKey uintptr, aiCol uintptr, regData int32, nIncr int32, isIgnore int32) { var i, iChild, iCur, iJump, iMustBeInt, iOk, iParent, iReg, nCol, regTemp, regTemp1 int32 var v uintptr _, _, _, _, _, _, _, _, _, _, _, _ = i, iChild, iCur, iJump, iMustBeInt, iOk, iParent, iReg, nCol, regTemp, regTemp1, v /* Iterator variable */ v = _sqlite3GetVdbe(tls, pParse) /* Vdbe to add code to */ iCur = (*TParse)(unsafe.Pointer(pParse)).FnTab - int32(1) /* Cursor number to use */ iOk = _sqlite3VdbeMakeLabel(tls, pParse) /* jump here if parent key found */ /* If nIncr is less than zero, then check at runtime if there are any ** outstanding constraints to resolve. If there are not, there is no need ** to check if deleting this row resolves any outstanding violations. ** ** Check if any of the key columns in the child table row are NULL. If ** any are, then the constraint is considered satisfied. No need to ** search for a matching row in the parent table. */ if nIncr < 0 { _sqlite3VdbeAddOp2(tls, v, int32(OP_FkIfZero), libc.Int32FromUint8((*TFKey)(unsafe.Pointer(pFKey)).FisDeferred), iOk) } i = 0 for { if !(i < (*TFKey)(unsafe.Pointer(pFKey)).FnCol) { break } iReg = int32(_sqlite3TableColumnToStorage(tls, (*TFKey)(unsafe.Pointer(pFKey)).FpFrom, int16(**(**int32)(__ccgo_up(aiCol + uintptr(i)*4))))) + regData + int32(1) _sqlite3VdbeAddOp2(tls, v, int32(OP_IsNull), iReg, iOk) goto _1 _1: ; i = i + 1 } if isIgnore == 0 { if pIdx == uintptr(0) { /* Address of MustBeInt instruction */ regTemp = _sqlite3GetTempReg(tls, pParse) /* Invoke MustBeInt to coerce the child key value to an integer (i.e. ** apply the affinity of the parent key). If this fails, then there ** is no matching parent key. Before using MustBeInt, make a copy of ** the value. Otherwise, the value inserted into the child key column ** will have INTEGER affinity applied to it, which may not be correct. */ _sqlite3VdbeAddOp2(tls, v, int32(OP_SCopy), int32(_sqlite3TableColumnToStorage(tls, (*TFKey)(unsafe.Pointer(pFKey)).FpFrom, int16(**(**int32)(__ccgo_up(aiCol)))))+int32(1)+regData, regTemp) iMustBeInt = _sqlite3VdbeAddOp2(tls, v, int32(OP_MustBeInt), regTemp, 0) /* If the parent table is the same as the child table, and we are about ** to increment the constraint-counter (i.e. this is an INSERT operation), ** then check if the row being inserted matches itself. If so, do not ** increment the constraint-counter. */ if pTab == (*TFKey)(unsafe.Pointer(pFKey)).FpFrom && nIncr == int32(1) { _sqlite3VdbeAddOp3(tls, v, int32(OP_Eq), regData, iOk, regTemp) _sqlite3VdbeChangeP5(tls, v, uint16(SQLITE_NOTNULL)) } _sqlite3OpenTable(tls, pParse, iCur, iDb, pTab, int32(OP_OpenRead)) _sqlite3VdbeAddOp3(tls, v, int32(OP_NotExists), iCur, 0, regTemp) _sqlite3VdbeGoto(tls, v, iOk) _sqlite3VdbeJumpHere(tls, v, _sqlite3VdbeCurrentAddr(tls, v)-int32(2)) _sqlite3VdbeJumpHere(tls, v, iMustBeInt) _sqlite3ReleaseTempReg(tls, pParse, regTemp) } else { nCol = (*TFKey)(unsafe.Pointer(pFKey)).FnCol regTemp1 = _sqlite3GetTempRange(tls, pParse, nCol) _sqlite3VdbeAddOp3(tls, v, int32(OP_OpenRead), iCur, libc.Int32FromUint32((*TIndex)(unsafe.Pointer(pIdx)).Ftnum), iDb) _sqlite3VdbeSetP4KeyInfo(tls, pParse, pIdx) i = 0 for { if !(i < nCol) { break } _sqlite3VdbeAddOp2(tls, v, int32(OP_Copy), int32(_sqlite3TableColumnToStorage(tls, (*TFKey)(unsafe.Pointer(pFKey)).FpFrom, int16(**(**int32)(__ccgo_up(aiCol + uintptr(i)*4)))))+int32(1)+regData, regTemp1+i) goto _2 _2: ; i = i + 1 } /* If the parent table is the same as the child table, and we are about ** to increment the constraint-counter (i.e. this is an INSERT operation), ** then check if the row being inserted matches itself. If so, do not ** increment the constraint-counter. ** ** If any of the parent-key values are NULL, then the row cannot match ** itself. So set JUMPIFNULL to make sure we do the OP_Found if any ** of the parent-key values are NULL (at this point it is known that ** none of the child key values are). */ if pTab == (*TFKey)(unsafe.Pointer(pFKey)).FpFrom && nIncr == int32(1) { iJump = _sqlite3VdbeCurrentAddr(tls, v) + nCol + int32(1) i = 0 for { if !(i < nCol) { break } iChild = int32(_sqlite3TableColumnToStorage(tls, (*TFKey)(unsafe.Pointer(pFKey)).FpFrom, int16(**(**int32)(__ccgo_up(aiCol + uintptr(i)*4))))) + int32(1) + regData iParent = int32(1) + regData iParent = iParent + int32(_sqlite3TableColumnToStorage(tls, (*TIndex)(unsafe.Pointer(pIdx)).FpTable, **(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FaiColumn + uintptr(i)*2)))) if int32(**(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FaiColumn + uintptr(i)*2))) == int32((*TTable)(unsafe.Pointer(pTab)).FiPKey) { /* The parent key is a composite key that includes the IPK column */ iParent = regData } _sqlite3VdbeAddOp3(tls, v, int32(OP_Ne), iChild, iJump, iParent) _sqlite3VdbeChangeP5(tls, v, uint16(SQLITE_JUMPIFNULL)) goto _3 _3: ; i = i + 1 } _sqlite3VdbeGoto(tls, v, iOk) } _sqlite3VdbeAddOp4(tls, v, int32(OP_Affinity), regTemp1, nCol, 0, _sqlite3IndexAffinityStr(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, pIdx), nCol) _sqlite3VdbeAddOp4Int(tls, v, int32(OP_Found), iCur, iOk, regTemp1, nCol) _sqlite3ReleaseTempRange(tls, pParse, regTemp1, nCol) } } if !((*TFKey)(unsafe.Pointer(pFKey)).FisDeferred != 0) && !((*Tsqlite3)(unsafe.Pointer((*TParse)(unsafe.Pointer(pParse)).Fdb)).Fflags&libc.Uint64FromInt32(SQLITE_DeferFKs) != 0) && !((*TParse)(unsafe.Pointer(pParse)).FpToplevel != 0) && !((*TParse)(unsafe.Pointer(pParse)).FisMultiWrite != 0) { /* Special case: If this is an INSERT statement that will insert exactly ** one row into the table, raise a constraint immediately instead of ** incrementing a counter. This is necessary as the VM code is being ** generated for will not open a statement transaction. */ _sqlite3HaltConstraint(tls, pParse, libc.Int32FromInt32(SQLITE_CONSTRAINT)|libc.Int32FromInt32(3)< 0 && libc.Int32FromUint8((*TFKey)(unsafe.Pointer(pFKey)).FisDeferred) == 0 { _sqlite3MayAbort(tls, pParse) } _sqlite3VdbeAddOp2(tls, v, int32(OP_FkCounter), libc.Int32FromUint8((*TFKey)(unsafe.Pointer(pFKey)).FisDeferred), nIncr) } _sqlite3VdbeResolveLabel(tls, v, iOk) _sqlite3VdbeAddOp1(tls, v, int32(OP_Close), iCur) } func _fts5ApiPhraseNextColumn(tls *libc.TLS, pCtx uintptr, pIter uintptr, piCol uintptr) { bp := tls.Alloc(16) defer tls.Free(16) var pConfig, pCsr uintptr var _ /* dummy at bp+4 */ int32 var _ /* iIncr at bp+0 */ int32 _, _ = pConfig, pCsr pCsr = pCtx pConfig = (*TFts5Table)(unsafe.Pointer((*TFts5Cursor)(unsafe.Pointer(pCsr)).Fbase.FpVtab)).FpConfig if (*TFts5Config)(unsafe.Pointer(pConfig)).FeDetail == int32(FTS5_DETAIL_COLUMNS) { if (*TFts5PhraseIter)(unsafe.Pointer(pIter)).Fa >= (*TFts5PhraseIter)(unsafe.Pointer(pIter)).Fb { **(**int32)(__ccgo_up(piCol)) = -int32(1) } else { **(**uintptr)(__ccgo_up(pIter)) += uintptr(_sqlite3Fts5GetVarint32(tls, (*TFts5PhraseIter)(unsafe.Pointer(pIter)).Fa, bp)) **(**int32)(__ccgo_up(piCol)) += **(**int32)(__ccgo_up(bp)) - int32(2) } } else { for int32(1) != 0 { if (*TFts5PhraseIter)(unsafe.Pointer(pIter)).Fa >= (*TFts5PhraseIter)(unsafe.Pointer(pIter)).Fb { **(**int32)(__ccgo_up(piCol)) = -int32(1) return } if libc.Int32FromUint8(**(**uint8)(__ccgo_up((*TFts5PhraseIter)(unsafe.Pointer(pIter)).Fa))) == int32(0x01) { break } **(**uintptr)(__ccgo_up(pIter)) += uintptr(_sqlite3Fts5GetVarint32(tls, (*TFts5PhraseIter)(unsafe.Pointer(pIter)).Fa, bp+4)) } **(**uintptr)(__ccgo_up(pIter)) += uintptr(int32(1) + _sqlite3Fts5GetVarint32(tls, (*TFts5PhraseIter)(unsafe.Pointer(pIter)).Fa+1, piCol)) } } func _fts5DlidxExtractFirstRowid(tls *libc.TLS, pBuf uintptr) (r Ti64) { bp := tls.Alloc(16) defer tls.Free(16) var iOff int32 var _ /* iRowid at bp+0 */ Ti64 _ = iOff iOff = int32(1) + libc.Int32FromUint8(_sqlite3Fts5GetVarint(tls, (*TFts5Buffer)(unsafe.Pointer(pBuf)).Fp+1, bp)) _sqlite3Fts5GetVarint(tls, (*TFts5Buffer)(unsafe.Pointer(pBuf)).Fp+uintptr(iOff), bp) return **(**Ti64)(__ccgo_up(bp)) } func _fts5ExprSynonymAdvanceto(tls *libc.TLS, pTerm uintptr, bDesc int32, piLast uintptr, pRc uintptr) (r int32) { bp := tls.Alloc(16) defer tls.Free(16) var iLast, iRowid Ti64 var p uintptr var rc int32 var _ /* bEof at bp+0 */ int32 _, _, _, _ = iLast, iRowid, p, rc rc = SQLITE_OK iLast = **(**Ti64)(__ccgo_up(piLast)) **(**int32)(__ccgo_up(bp)) = 0 p = pTerm for { if !(rc == SQLITE_OK && p != 0) { break } if libc.Int32FromUint8((*TFts5IndexIter)(unsafe.Pointer((*TFts5ExprTerm)(unsafe.Pointer(p)).FpIter)).FbEof) == 0 { iRowid = (*TFts5IndexIter)(unsafe.Pointer((*TFts5ExprTerm)(unsafe.Pointer(p)).FpIter)).FiRowid if bDesc == 0 && iLast > iRowid || bDesc != 0 && iLast < iRowid { rc = _sqlite3Fts5IterNextFrom(tls, (*TFts5ExprTerm)(unsafe.Pointer(p)).FpIter, iLast) } } goto _1 _1: ; p = (*TFts5ExprTerm)(unsafe.Pointer(p)).FpSynonym } if rc != SQLITE_OK { **(**int32)(__ccgo_up(pRc)) = rc **(**int32)(__ccgo_up(bp)) = int32(1) } else { **(**Ti64)(__ccgo_up(piLast)) = _fts5ExprSynonymRowid(tls, pTerm, bDesc, bp) } return **(**int32)(__ccgo_up(bp)) } // C documentation // // /* // ** Argument pTerm must be a synonym iterator. Return the current rowid // ** that it points to. // */ func _fts5ExprSynonymRowid(tls *libc.TLS, pTerm uintptr, bDesc int32, pbEof uintptr) (r Ti64) { var bRetValid int32 var iRet, iRowid Ti64 var p uintptr _, _, _, _ = bRetValid, iRet, iRowid, p iRet = 0 bRetValid = 0 p = pTerm for { if !(p != 0) { break } if 0 == libc.Int32FromUint8((*TFts5IndexIter)(unsafe.Pointer((*TFts5ExprTerm)(unsafe.Pointer(p)).FpIter)).FbEof) { iRowid = (*TFts5IndexIter)(unsafe.Pointer((*TFts5ExprTerm)(unsafe.Pointer(p)).FpIter)).FiRowid if bRetValid == 0 || bDesc != libc.BoolInt32(iRowid < iRet) { iRet = iRowid bRetValid = int32(1) } } goto _1 _1: ; p = (*TFts5ExprTerm)(unsafe.Pointer(p)).FpSynonym } if pbEof != 0 && bRetValid == 0 { **(**int32)(__ccgo_up(pbEof)) = int32(1) } return iRet } // C documentation // // /* // ** Argument p points to a buffer containing a varint to be interpreted as a // ** position list size field. Read the varint and return the number of bytes // ** read. Before returning, set *pnSz to the number of bytes in the position // ** list, and *pbDel to true if the delete flag is set, or false otherwise. // */ func _fts5GetPoslistSize(tls *libc.TLS, p uintptr, pnSz uintptr, pbDel uintptr) (r int32) { bp := tls.Alloc(16) defer tls.Free(16) var n, v1 int32 var _ /* nSz at bp+0 */ int32 _, _ = n, v1 n = 0 v1 = n n = n + 1 **(**int32)(__ccgo_up(bp)) = libc.Int32FromUint8(**(**Tu8)(__ccgo_up(p + uintptr(v1)))) if **(**int32)(__ccgo_up(bp))&int32(0x80) != 0 { n = n - 1 n = n + _sqlite3Fts5GetVarint32(tls, p+uintptr(n), bp) } **(**int32)(__ccgo_up(pnSz)) = **(**int32)(__ccgo_up(bp)) / int32(2) **(**int32)(__ccgo_up(pbDel)) = **(**int32)(__ccgo_up(bp)) & int32(0x0001) return n } func _fts5GetU16(tls *libc.TLS, aIn uintptr) (r Tu16) { return libc.Uint16FromInt32(libc.Int32FromUint16(uint16(**(**Tu8)(__ccgo_up(aIn))))<= 0) { break } h = h<= 0) { break } h = h<= (*TFts5Data)(unsafe.Pointer(pLeaf)).Fnn) || i >= iNoRowid && 0 != libc.Int32FromUint16(_fts5GetU16(tls, (*TFts5Data)(unsafe.Pointer(pLeaf)).Fp)) { _fts5IndexCorruptRowid(tls, p, int64((*TFts5StructureSegment)(unsafe.Pointer(pSeg)).FiSegid)<<(libc.Int32FromInt32(FTS5_DATA_PAGE_B)+libc.Int32FromInt32(FTS5_DATA_HEIGHT_B)+libc.Int32FromInt32(FTS5_DATA_DLI_B))+int64(libc.Int32FromInt32(0))<<(libc.Int32FromInt32(FTS5_DATA_PAGE_B)+libc.Int32FromInt32(FTS5_DATA_HEIGHT_B))+int64(libc.Int32FromInt32(0))< int32(16) { if libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TFts5Data)(unsafe.Pointer(pPg)).Fp))) == int32(4) { v3 = int32(4) } else { v3 = int32(8) } v2 = ((*TFts5Data)(unsafe.Pointer(pPg)).Fnn - int32(8)) / v3 } else { v2 = int32(1) } nSlot = v2 nElem = libc.Int32FromUint32(_fts5GetU32(tls, (*TFts5Data)(unsafe.Pointer(pPg)).Fp+4)) iSlot = libc.Int32FromUint64(iRowid / libc.Uint64FromInt32(nPg) % libc.Uint64FromInt32(nSlot)) nCollide = nSlot if szKey == int32(4) && iRowid > uint64(0xFFFFFFFF) { return int32(2) } if iRowid == uint64(0) { **(**Tu8)(__ccgo_up((*TFts5Data)(unsafe.Pointer(pPg)).Fp + 1)) = uint8(0x01) return 0 } if bForce == 0 && nElem >= nSlot/int32(2) { return int32(1) } _fts5PutU32(tls, (*TFts5Data)(unsafe.Pointer(pPg)).Fp+4, libc.Uint32FromInt32(nElem+int32(1))) if szKey == int32(4) { aSlot = (*TFts5Data)(unsafe.Pointer(pPg)).Fp + 8 for **(**Tu32)(__ccgo_up(aSlot + uintptr(iSlot)*4)) != 0 { iSlot = (iSlot + int32(1)) % nSlot v1 = nCollide nCollide = nCollide - 1 if v1 == 0 { return 0 } } _fts5PutU32(tls, aSlot+uintptr(iSlot)*4, uint32(iRowid)) } else { aSlot1 = (*TFts5Data)(unsafe.Pointer(pPg)).Fp + 8 for **(**Tu64)(__ccgo_up(aSlot1 + uintptr(iSlot)*8)) != 0 { iSlot = (iSlot + int32(1)) % nSlot v1 = nCollide nCollide = nCollide - 1 if v1 == 0 { return 0 } } _fts5PutU64(tls, aSlot1+uintptr(iSlot)*8, iRowid) } return 0 } // C documentation // // /* // ** Query a single tombstone hash table for rowid iRowid. Return true if // ** it is found or false otherwise. The tombstone hash table is one of // ** nHashTable tables. // */ func _fts5IndexTombstoneQuery(tls *libc.TLS, pHash uintptr, nHashTable int32, iRowid Tu64) (r int32) { var aSlot, aSlot1 uintptr var iSlot, nCollide, nSlot, szKey, v1, v2, v3 int32 _, _, _, _, _, _, _, _, _ = aSlot, aSlot1, iSlot, nCollide, nSlot, szKey, v1, v2, v3 if libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TFts5Data)(unsafe.Pointer(pHash)).Fp))) == int32(4) { v1 = int32(4) } else { v1 = int32(8) } szKey = v1 if (*TFts5Data)(unsafe.Pointer(pHash)).Fnn > int32(16) { if libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TFts5Data)(unsafe.Pointer(pHash)).Fp))) == int32(4) { v3 = int32(4) } else { v3 = int32(8) } v2 = ((*TFts5Data)(unsafe.Pointer(pHash)).Fnn - int32(8)) / v3 } else { v2 = int32(1) } nSlot = v2 iSlot = libc.Int32FromUint64(iRowid / libc.Uint64FromInt32(nHashTable) % libc.Uint64FromInt32(nSlot)) nCollide = nSlot if iRowid == uint64(0) { return libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TFts5Data)(unsafe.Pointer(pHash)).Fp + 1))) } else { if szKey == int32(4) { aSlot = (*TFts5Data)(unsafe.Pointer(pHash)).Fp + 8 for **(**Tu32)(__ccgo_up(aSlot + uintptr(iSlot)*4)) != 0 { if uint64(_fts5GetU32(tls, aSlot+uintptr(iSlot)*4)) == iRowid { return int32(1) } v1 = nCollide nCollide = nCollide - 1 if v1 == 0 { break } iSlot = (iSlot + int32(1)) % nSlot } } else { aSlot1 = (*TFts5Data)(unsafe.Pointer(pHash)).Fp + 8 for **(**Tu64)(__ccgo_up(aSlot1 + uintptr(iSlot)*8)) != 0 { if _fts5GetU64(tls, aSlot1+uintptr(iSlot)*8) == iRowid { return int32(1) } v1 = nCollide nCollide = nCollide - 1 if v1 == 0 { break } iSlot = (iSlot + int32(1)) % nSlot } } } return 0 } func _fts5NextRowid(tls *libc.TLS, pBuf uintptr, piOff uintptr, piRowid uintptr) { bp := tls.Alloc(16) defer tls.Free(16) var i int32 var v1 uintptr var _ /* iVal at bp+0 */ Tu64 _, _ = i, v1 i = **(**int32)(__ccgo_up(piOff)) if i >= (*TFts5Buffer)(unsafe.Pointer(pBuf)).Fn { **(**int32)(__ccgo_up(piOff)) = -int32(1) } else { **(**int32)(__ccgo_up(piOff)) = i + libc.Int32FromUint8(_sqlite3Fts5GetVarint(tls, (*TFts5Buffer)(unsafe.Pointer(pBuf)).Fp+uintptr(i), bp)) v1 = piRowid *(*Ti64)(unsafe.Pointer(v1)) = Ti64(uint64(*(*Ti64)(unsafe.Pointer(v1))) + **(**Tu64)(__ccgo_up(bp))) } } func _fts5ParseAlloc(tls *libc.TLS, t Tu64) (r uintptr) { return Xsqlite3_malloc64(tls, libc.Uint64FromInt64(libc.Int64FromUint64(t))) } // C documentation // // /* // ** Return the size of the prefix, in bytes, that buffer // ** (pNew/) shares with buffer (pOld/nOld). // ** // ** Buffer (pNew/) is guaranteed to be greater // ** than buffer (pOld/nOld). // */ func _fts5PrefixCompress(tls *libc.TLS, nOld int32, pOld uintptr, pNew uintptr) (r int32) { var i int32 _ = i i = 0 for { if !(i < nOld) { break } if libc.Int32FromUint8(**(**Tu8)(__ccgo_up(pOld + uintptr(i)))) != libc.Int32FromUint8(**(**Tu8)(__ccgo_up(pNew + uintptr(i)))) { break } goto _1 _1: ; i = i + 1 } return i } func _fts5PutU16(tls *libc.TLS, aOut uintptr, iVal Tu16) { **(**Tu8)(__ccgo_up(aOut)) = libc.Uint8FromInt32(libc.Int32FromUint16(iVal) >> libc.Int32FromInt32(8)) **(**Tu8)(__ccgo_up(aOut + 1)) = libc.Uint8FromInt32(libc.Int32FromUint16(iVal) & libc.Int32FromInt32(0xFF)) } // C documentation // // /* // ** Fts5SegIter.iLeafOffset currently points to the first byte of a // ** position-list size field. Read the value of the field and store it // ** in the following variables: // ** // ** Fts5SegIter.nPos // ** Fts5SegIter.bDel // ** // ** Leave Fts5SegIter.iLeafOffset pointing to the first byte of the // ** position list content (if any). // */ func _fts5SegIterLoadNPos(tls *libc.TLS, p uintptr, pIter uintptr) { bp := tls.Alloc(16) defer tls.Free(16) var iEod, iOff, v1 int32 var _ /* nSz at bp+0 */ int32 _, _, _ = iEod, iOff, v1 if (*TFts5Index)(unsafe.Pointer(p)).Frc == SQLITE_OK { iOff = int32((*TFts5SegIter)(unsafe.Pointer(pIter)).FiLeafOffset) /* Offset to read at */ if (*TFts5Config)(unsafe.Pointer((*TFts5Index)(unsafe.Pointer(p)).FpConfig)).FeDetail == int32(FTS5_DETAIL_NONE) { if (*TFts5SegIter)(unsafe.Pointer(pIter)).FiEndofDoclist < (*TFts5Data)(unsafe.Pointer((*TFts5SegIter)(unsafe.Pointer(pIter)).FpLeaf)).FszLeaf { v1 = (*TFts5SegIter)(unsafe.Pointer(pIter)).FiEndofDoclist } else { v1 = (*TFts5Data)(unsafe.Pointer((*TFts5SegIter)(unsafe.Pointer(pIter)).FpLeaf)).FszLeaf } iEod = v1 (*TFts5SegIter)(unsafe.Pointer(pIter)).FbDel = uint8(0) (*TFts5SegIter)(unsafe.Pointer(pIter)).FnPos = int32(1) if iOff < iEod && libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TFts5Data)(unsafe.Pointer((*TFts5SegIter)(unsafe.Pointer(pIter)).FpLeaf)).Fp + uintptr(iOff)))) == 0 { (*TFts5SegIter)(unsafe.Pointer(pIter)).FbDel = uint8(1) iOff = iOff + 1 if iOff < iEod && libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TFts5Data)(unsafe.Pointer((*TFts5SegIter)(unsafe.Pointer(pIter)).FpLeaf)).Fp + uintptr(iOff)))) == 0 { (*TFts5SegIter)(unsafe.Pointer(pIter)).FnPos = int32(1) iOff = iOff + 1 } else { (*TFts5SegIter)(unsafe.Pointer(pIter)).FnPos = 0 } } } else { v1 = iOff iOff = iOff + 1 **(**int32)(__ccgo_up(bp)) = libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TFts5Data)(unsafe.Pointer((*TFts5SegIter)(unsafe.Pointer(pIter)).FpLeaf)).Fp + uintptr(v1)))) if **(**int32)(__ccgo_up(bp))&int32(0x80) != 0 { iOff = iOff - 1 iOff = iOff + _sqlite3Fts5GetVarint32(tls, (*TFts5Data)(unsafe.Pointer((*TFts5SegIter)(unsafe.Pointer(pIter)).FpLeaf)).Fp+uintptr(iOff), bp) } (*TFts5SegIter)(unsafe.Pointer(pIter)).FbDel = libc.Uint8FromInt32(**(**int32)(__ccgo_up(bp)) & libc.Int32FromInt32(0x0001)) (*TFts5SegIter)(unsafe.Pointer(pIter)).FnPos = **(**int32)(__ccgo_up(bp)) >> int32(1) } (*TFts5SegIter)(unsafe.Pointer(pIter)).FiLeafOffset = int64(iOff) } } func _fts5UsePatternMatch(tls *libc.TLS, pConfig uintptr, p uintptr) (r int32) { if (*TFts5Config)(unsafe.Pointer(pConfig)).Ft.FePattern == int32(FTS5_PATTERN_GLOB) && libc.Int32FromUint8((*Tsqlite3_index_constraint)(unsafe.Pointer(p)).Fop) == int32(FTS5_PATTERN_GLOB) { return int32(1) } if (*TFts5Config)(unsafe.Pointer(pConfig)).Ft.FePattern == int32(FTS5_PATTERN_LIKE) && (libc.Int32FromUint8((*Tsqlite3_index_constraint)(unsafe.Pointer(p)).Fop) == int32(FTS5_PATTERN_LIKE) || libc.Int32FromUint8((*Tsqlite3_index_constraint)(unsafe.Pointer(p)).Fop) == int32(FTS5_PATTERN_GLOB)) { return int32(1) } return 0 } // C documentation // // /* // ** Implementation of the xBestIndex method. // ** // ** Only constraints of the form: // ** // ** term <= ? // ** term == ? // ** term >= ? // ** // ** are interpreted. Less-than and less-than-or-equal are treated // ** identically, as are greater-than and greater-than-or-equal. // */ func _fts5VocabBestIndexMethod(tls *libc.TLS, pUnused uintptr, pInfo uintptr) (r int32) { var i, iTermEq, iTermGe, iTermLe, idxNum, nArg, v2 int32 var p uintptr _, _, _, _, _, _, _, _ = i, iTermEq, iTermGe, iTermLe, idxNum, nArg, p, v2 iTermEq = -int32(1) iTermGe = -int32(1) iTermLe = -int32(1) idxNum = libc.Int32FromUint64((*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FcolUsed) nArg = 0 _ = pUnused i = 0 for { if !(i < (*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FnConstraint) { break } p = (*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FaConstraint + uintptr(i)*12 if libc.Int32FromUint8((*Tsqlite3_index_constraint)(unsafe.Pointer(p)).Fusable) == 0 { goto _1 } if (*Tsqlite3_index_constraint)(unsafe.Pointer(p)).FiColumn == 0 { /* term column */ if libc.Int32FromUint8((*Tsqlite3_index_constraint)(unsafe.Pointer(p)).Fop) == int32(SQLITE_INDEX_CONSTRAINT_EQ) { iTermEq = i } if libc.Int32FromUint8((*Tsqlite3_index_constraint)(unsafe.Pointer(p)).Fop) == int32(SQLITE_INDEX_CONSTRAINT_LE) { iTermLe = i } if libc.Int32FromUint8((*Tsqlite3_index_constraint)(unsafe.Pointer(p)).Fop) == int32(SQLITE_INDEX_CONSTRAINT_LT) { iTermLe = i } if libc.Int32FromUint8((*Tsqlite3_index_constraint)(unsafe.Pointer(p)).Fop) == int32(SQLITE_INDEX_CONSTRAINT_GE) { iTermGe = i } if libc.Int32FromUint8((*Tsqlite3_index_constraint)(unsafe.Pointer(p)).Fop) == int32(SQLITE_INDEX_CONSTRAINT_GT) { iTermGe = i } } goto _1 _1: ; i = i + 1 } if iTermEq >= 0 { idxNum = idxNum | int32(FTS5_VOCAB_TERM_EQ) nArg = nArg + 1 v2 = nArg (**(**Tsqlite3_index_constraint_usage)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FaConstraintUsage + uintptr(iTermEq)*8))).FargvIndex = v2 (*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FestimatedCost = libc.Float64FromInt32(100) } else { (*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FestimatedCost = libc.Float64FromInt32(1000000) if iTermGe >= 0 { idxNum = idxNum | int32(FTS5_VOCAB_TERM_GE) nArg = nArg + 1 v2 = nArg (**(**Tsqlite3_index_constraint_usage)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FaConstraintUsage + uintptr(iTermGe)*8))).FargvIndex = v2 (*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FestimatedCost = (*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FestimatedCost / libc.Float64FromInt32(2) } if iTermLe >= 0 { idxNum = idxNum | int32(FTS5_VOCAB_TERM_LE) nArg = nArg + 1 v2 = nArg (**(**Tsqlite3_index_constraint_usage)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FaConstraintUsage + uintptr(iTermLe)*8))).FargvIndex = v2 (*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FestimatedCost = (*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FestimatedCost / libc.Float64FromInt32(2) } } /* This virtual table always delivers results in ascending order of ** the "term" column (column 0). So if the user has requested this ** specifically - "ORDER BY term" or "ORDER BY term ASC" - set the ** sqlite3_index_info.orderByConsumed flag to tell the core the results ** are already in sorted order. */ if (*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FnOrderBy == int32(1) && (**(**Tsqlite3_index_orderby)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FaOrderBy))).FiColumn == 0 && libc.Int32FromUint8((**(**Tsqlite3_index_orderby)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FaOrderBy))).Fdesc) == 0 { (*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).ForderByConsumed = int32(1) } (*Tsqlite3_index_info)(unsafe.Pointer(pInfo)).FidxNum = idxNum return SQLITE_OK } // C documentation // // /* The following function deletes the "minor type" or semantic value // ** associated with a symbol. The symbol can be either a terminal // ** or nonterminal. "fts5yymajor" is the symbol code, and "fts5yypminor" is // ** a pointer to the value to be deleted. The code used to do the // ** deletions is derived from the %destructor and/or %token_destructor // ** directives of the input grammar. // */ func _fts5yy_destructor(tls *libc.TLS, fts5yypParser uintptr, fts5yymajor uint8, fts5yypminor uintptr) { var pParse uintptr _ = pParse pParse = (*Tfts5yyParser)(unsafe.Pointer(fts5yypParser)).FpParse switch libc.Int32FromUint8(fts5yymajor) { /* Here is inserted the actions which take place when a ** terminal or non-terminal is destroyed. This can happen ** when the symbol is popped from the stack during a ** reduce or during error processing or when a parser is ** being destroyed before it is finished parsing. ** ** Note: during a reduce, the only symbols destroyed are those ** which appear on the RHS of the rule, but which are *not* used ** inside the C code. */ /********* Begin destructor definitions ***************************************/ case int32(16): /* input */ _ = pParse case int32(17): /* expr */ fallthrough case int32(18): /* cnearset */ fallthrough case int32(19): /* exprlist */ _sqlite3Fts5ParseNodeFree(tls, *(*uintptr)(unsafe.Pointer(fts5yypminor))) case int32(20): /* colset */ fallthrough case int32(21): /* colsetlist */ Xsqlite3_free(tls, *(*uintptr)(unsafe.Pointer(fts5yypminor))) case int32(22): /* nearset */ fallthrough case int32(23): /* nearphrases */ _sqlite3Fts5ParseNearsetFree(tls, *(*uintptr)(unsafe.Pointer(fts5yypminor))) case int32(24): /* phrase */ _sqlite3Fts5ParsePhraseFree(tls, *(*uintptr)(unsafe.Pointer(fts5yypminor))) break /********* End destructor definitions *****************************************/ fallthrough default: break /* If no destructor action specified: do nothing */ } } // C documentation // // /* // ** Find the appropriate action for a parser given the non-terminal // ** look-ahead token iLookAhead. // */ func _fts5yy_find_reduce_action(tls *libc.TLS, stateno uint8, iLookAhead uint8) (r uint8) { var i int32 _ = i i = int32(_fts5yy_reduce_ofst[stateno]) i = i + libc.Int32FromUint8(iLookAhead) return _fts5yy_action[i] } // C documentation // // /* // ** Find the appropriate action for a parser given the terminal // ** look-ahead token iLookAhead. // */ func _fts5yy_find_shift_action(tls *libc.TLS, iLookAhead uint8, stateno uint8) (r uint8) { var i int32 _ = i if libc.Int32FromUint8(stateno) > int32(fts5YY_MAX_SHIFT) { return stateno } for cond := true; cond; cond = int32(1) != 0 { i = libc.Int32FromUint8(_fts5yy_shift_ofst[stateno]) i = i + libc.Int32FromUint8(iLookAhead) if libc.Int32FromUint8(_fts5yy_lookahead[i]) != libc.Int32FromUint8(iLookAhead) { return _fts5yy_default[stateno] } else { return _fts5yy_action[i] } } return r } // C documentation // // /* // ** Insert all segments and events for polygon pPoly. // */ func _geopolyAddSegments(tls *libc.TLS, p uintptr, pPoly uintptr, side uint8) { var i uint32 var x uintptr _, _ = i, x i = uint32(0) for { if !(i < libc.Uint32FromInt32((*TGeoPoly)(unsafe.Pointer(pPoly)).FnVertex)-uint32(1)) { break } x = pPoly + 8 + uintptr(i*uint32(2))*4 _geopolyAddOneSegment(tls, p, **(**TGeoCoord)(__ccgo_up(x)), **(**TGeoCoord)(__ccgo_up(x + 1*4)), **(**TGeoCoord)(__ccgo_up(x + 2*4)), **(**TGeoCoord)(__ccgo_up(x + 3*4)), side, i) goto _1 _1: ; i = i + 1 } x = pPoly + 8 + uintptr(i*uint32(2))*4 _geopolyAddOneSegment(tls, p, **(**TGeoCoord)(__ccgo_up(x)), **(**TGeoCoord)(__ccgo_up(x + 1*4)), **(**TGeoCoord)(__ccgo_up(pPoly + 8)), **(**TGeoCoord)(__ccgo_up(pPoly + 8 + 1*4)), side, i) } // C documentation // // /* // ** Get a page from the pager and initialize it. // */ func _getAndInitPage(tls *libc.TLS, pBt uintptr, pgno TPgno, ppPage uintptr, bReadOnly int32) (r int32) { bp := tls.Alloc(16) defer tls.Free(16) var pPage uintptr var rc int32 var _ /* pDbPage at bp+0 */ uintptr _, _ = pPage, rc if pgno > _btreePagecount(tls, pBt) { **(**uintptr)(__ccgo_up(ppPage)) = uintptr(0) return _sqlite3CorruptError(tls, int32(75618)) } rc = _sqlite3PagerGet(tls, (*TBtShared)(unsafe.Pointer(pBt)).FpPager, pgno, bp, bReadOnly) if rc != 0 { **(**uintptr)(__ccgo_up(ppPage)) = uintptr(0) return rc } pPage = _sqlite3PagerGetExtra(tls, **(**uintptr)(__ccgo_up(bp))) if libc.Int32FromUint8((*TMemPage)(unsafe.Pointer(pPage)).FisInit) == 0 { _btreePageFromDbPage(tls, **(**uintptr)(__ccgo_up(bp)), pgno, pBt) rc = _btreeInitPage(tls, pPage) if rc != SQLITE_OK { _releasePage(tls, pPage) **(**uintptr)(__ccgo_up(ppPage)) = uintptr(0) return rc } } **(**uintptr)(__ccgo_up(ppPage)) = pPage return SQLITE_OK } // C documentation // // /* // ** For a single cell on a btree page, compute the number of bytes of // ** content (payload) stored on that page. That is to say, compute the // ** number of bytes of content not found on overflow pages. // */ func _getLocalPayload(tls *libc.TLS, nUsable int32, flags Tu8, nTotal int32) (r int32) { var nLocal, nMaxLocal, nMinLocal int32 _, _, _ = nLocal, nMaxLocal, nMinLocal if libc.Int32FromUint8(flags) == int32(0x0D) { /* Table leaf node */ nMinLocal = (nUsable-int32(12))*int32(32)/int32(255) - int32(23) nMaxLocal = nUsable - int32(35) } else { /* Index interior and leaf nodes */ nMinLocal = (nUsable-int32(12))*int32(32)/int32(255) - int32(23) nMaxLocal = (nUsable-int32(12))*int32(64)/int32(255) - int32(23) } nLocal = nMinLocal + (nTotal-nMinLocal)%(nUsable-int32(4)) if nLocal > nMaxLocal { nLocal = nMinLocal } return nLocal } // C documentation // // /* // ** Return non-zero if the bit in the IntegrityCk.aPgRef[] array that // ** corresponds to page iPg is already set. // */ func _getPageReferenced(tls *libc.TLS, pCheck uintptr, iPg TPgno) (r int32) { return libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TIntegrityCk)(unsafe.Pointer(pCheck)).FaPgRef + uintptr(iPg/uint32(8))))) & (int32(1) << (iPg & uint32(0x07))) } // C documentation // // /* // ** This function is called after transitioning from PAGER_UNLOCK to // ** PAGER_SHARED state. It tests if there is a hot journal present in // ** the file-system for the given pager. A hot journal is one that // ** needs to be played back. According to this function, a hot-journal // ** file exists if the following criteria are met: // ** // ** * The journal file exists in the file system, and // ** * No process holds a RESERVED or greater lock on the database file, and // ** * The database file itself is greater than 0 bytes in size, and // ** * The first byte of the journal file exists and is not 0x00. // ** // ** If the current size of the database file is 0 but a journal file // ** exists, that is probably an old journal left over from a prior // ** database with the same name. In this case the journal file is // ** just deleted using OsDelete, *pExists is set to 0 and SQLITE_OK // ** is returned. // ** // ** This routine does not check if there is a super-journal filename // ** at the end of the file. If there is, and that super-journal file // ** does not exist, then the journal file is not really hot. In this // ** case this routine will return a false-positive. The pager_playback() // ** routine will discover that the journal file is not really hot and // ** will not roll it back. // ** // ** If a hot-journal file is found to exist, *pExists is set to 1 and // ** SQLITE_OK returned. If no hot-journal file is present, *pExists is // ** set to 0 and SQLITE_OK returned. If an IO error occurs while trying // ** to determine whether or not a hot-journal file exists, the IO error // ** code is returned and the value of *pExists is undefined. // */ func _hasHotJournal(tls *libc.TLS, pPager uintptr, pExists uintptr) (r int32) { bp := tls.Alloc(32) defer tls.Free(32) var jrnlOpen, rc int32 var pVfs uintptr var _ /* exists at bp+0 */ int32 var _ /* f at bp+12 */ int32 var _ /* first at bp+16 */ Tu8 var _ /* locked at bp+4 */ int32 var _ /* nPage at bp+8 */ TPgno _, _, _ = jrnlOpen, pVfs, rc pVfs = (*TPager)(unsafe.Pointer(pPager)).FpVfs rc = SQLITE_OK /* Return code */ **(**int32)(__ccgo_up(bp)) = int32(1) /* True if a journal file is present */ jrnlOpen = libc.BoolInt32(!!((*Tsqlite3_file)(unsafe.Pointer((*TPager)(unsafe.Pointer(pPager)).Fjfd)).FpMethods != libc.UintptrFromInt32(0))) **(**int32)(__ccgo_up(pExists)) = 0 if !(jrnlOpen != 0) { rc = _sqlite3OsAccess(tls, pVfs, (*TPager)(unsafe.Pointer(pPager)).FzJournal, SQLITE_ACCESS_EXISTS, bp) } if rc == SQLITE_OK && **(**int32)(__ccgo_up(bp)) != 0 { **(**int32)(__ccgo_up(bp + 4)) = 0 /* True if some process holds a RESERVED lock */ /* Race condition here: Another process might have been holding the ** the RESERVED lock and have a journal open at the sqlite3OsAccess() ** call above, but then delete the journal and drop the lock before ** we get to the following sqlite3OsCheckReservedLock() call. If that ** is the case, this routine might think there is a hot journal when ** in fact there is none. This results in a false-positive which will ** be dealt with by the playback routine. Ticket #3883. */ rc = _sqlite3OsCheckReservedLock(tls, (*TPager)(unsafe.Pointer(pPager)).Ffd, bp+4) if rc == SQLITE_OK && !(**(**int32)(__ccgo_up(bp + 4)) != 0) { /* Number of pages in database file */ rc = _pagerPagecount(tls, pPager, bp+8) if rc == SQLITE_OK { /* If the database is zero pages in size, that means that either (1) the ** journal is a remnant from a prior database with the same name where ** the database file but not the journal was deleted, or (2) the initial ** transaction that populates a new database is being rolled back. ** In either case, the journal file can be deleted. However, take care ** not to delete the journal file if it is already open due to ** journal_mode=PERSIST. */ if **(**TPgno)(__ccgo_up(bp + 8)) == uint32(0) && !(jrnlOpen != 0) { _sqlite3BeginBenignMalloc(tls) if _pagerLockDb(tls, pPager, int32(RESERVED_LOCK)) == SQLITE_OK { _sqlite3OsDelete(tls, pVfs, (*TPager)(unsafe.Pointer(pPager)).FzJournal, 0) if !((*TPager)(unsafe.Pointer(pPager)).FexclusiveMode != 0) { _pagerUnlockDb(tls, pPager, int32(SHARED_LOCK)) } } _sqlite3EndBenignMalloc(tls) } else { /* The journal file exists and no other connection has a reserved ** or greater lock on the database file. Now check that there is ** at least one non-zero bytes at the start of the journal file. ** If there is, then we consider this journal to be hot. If not, ** it can be ignored. */ if !(jrnlOpen != 0) { **(**int32)(__ccgo_up(bp + 12)) = libc.Int32FromInt32(SQLITE_OPEN_READONLY) | libc.Int32FromInt32(SQLITE_OPEN_MAIN_JOURNAL) rc = _sqlite3OsOpen(tls, pVfs, (*TPager)(unsafe.Pointer(pPager)).FzJournal, (*TPager)(unsafe.Pointer(pPager)).Fjfd, **(**int32)(__ccgo_up(bp + 12)), bp+12) } if rc == SQLITE_OK { **(**Tu8)(__ccgo_up(bp + 16)) = uint8(0) rc = _sqlite3OsRead(tls, (*TPager)(unsafe.Pointer(pPager)).Fjfd, bp+16, int32(1), 0) if rc == libc.Int32FromInt32(SQLITE_IOERR)|libc.Int32FromInt32(2)<= int32(SQLITE_INDEX_CONSTRAINT_LIMIT) && libc.Int32FromUint8((*TWhereTerm)(unsafe.Pointer(pTerm)).FeMatchOp) <= int32(SQLITE_INDEX_CONSTRAINT_OFFSET)) } // C documentation // // /* // ** Return the offset of the sector boundary at or immediately // ** following the value in pPager->journalOff, assuming a sector // ** size of pPager->sectorSize bytes. // ** // ** i.e for a sector size of 512: // ** // ** Pager.journalOff Return value // ** --------------------------------------- // ** 0 0 // ** 512 512 // ** 100 512 // ** 2000 2048 // ** // */ func _journalHdrOffset(tls *libc.TLS, pPager uintptr) (r Ti64) { var c, offset Ti64 _, _ = c, offset offset = 0 c = (*TPager)(unsafe.Pointer(pPager)).FjournalOff if c != 0 { offset = ((c-int64(1))/libc.Int64FromUint32((*TPager)(unsafe.Pointer(pPager)).FsectorSize) + int64(1)) * libc.Int64FromUint32((*TPager)(unsafe.Pointer(pPager)).FsectorSize) } return offset } // C documentation // // /* // ** If pArg is a blob that seems like a JSONB blob, then initialize // ** p to point to that JSONB and return TRUE. If pArg does not seem like // ** a JSONB blob, then return FALSE. // ** // ** For small BLOBs (having no more than 7 bytes of payload) a full // ** validity check is done. So for small BLOBs this routine only returns // ** true if the value is guaranteed to be a valid JSONB. For larger BLOBs // ** (8 byte or more of payload) only the size of the outermost element is // ** checked to verify that the BLOB is superficially valid JSONB. // ** // ** A full JSONB validation is done on smaller BLOBs because those BLOBs might // ** also be text JSON that has been incorrectly cast into a BLOB. // ** (See tag-20240123-a and https://sqlite.org/forum/forumpost/012136abd5) // ** If the BLOB is 9 bytes are larger, then it is not possible for the // ** superficial size check done here to pass if the input is really text // ** JSON so we do not need to look deeper in that case. // ** // ** Why we only need to do full JSONB validation for smaller BLOBs: // ** // ** The first byte of valid JSON text must be one of: '{', '[', '"', ' ', '\n', // ** '\r', '\t', '-', or a digit '0' through '9'. Of these, only a subset // ** can also be the first byte of JSONB: '{', '[', and digits '3' // ** through '9'. In every one of those cases, the payload size is 7 bytes // ** or less. So if we do full JSONB validation for every BLOB where the // ** payload is less than 7 bytes, we will never get a false positive for // ** JSONB on an input that is really text JSON. // */ func _jsonArgIsJsonb(tls *libc.TLS, pArg uintptr, p uintptr) (r int32) { bp := tls.Alloc(16) defer tls.Free(16) var c, v1 Tu8 var n, v3 Tu32 var v2, v4 bool var _ /* sz at bp+0 */ Tu32 _, _, _, _, _, _ = c, n, v1, v2, v3, v4 **(**Tu32)(__ccgo_up(bp)) = uint32(0) if Xsqlite3_value_type(tls, pArg) != int32(SQLITE_BLOB) { return 0 } (*TJsonParse)(unsafe.Pointer(p)).FaBlob = Xsqlite3_value_blob(tls, pArg) (*TJsonParse)(unsafe.Pointer(p)).FnBlob = libc.Uint32FromInt32(Xsqlite3_value_bytes(tls, pArg)) if v2 = (*TJsonParse)(unsafe.Pointer(p)).FnBlob > uint32(0) && (*TJsonParse)(unsafe.Pointer(p)).FaBlob != uintptr(0); v2 { v1 = **(**Tu8)(__ccgo_up((*TJsonParse)(unsafe.Pointer(p)).FaBlob)) c = v1 } if v4 = v2 && libc.Int32FromUint8(v1)&int32(0x0f) <= int32(JSONB_OBJECT); v4 { v3 = _jsonbPayloadSize(tls, p, uint32(0), bp) n = v3 } if v4 && v3 > uint32(0) && **(**Tu32)(__ccgo_up(bp))+n == (*TJsonParse)(unsafe.Pointer(p)).FnBlob && (libc.Int32FromUint8(c)&int32(0x0f) > int32(JSONB_FALSE) || **(**Tu32)(__ccgo_up(bp)) == uint32(0)) && (**(**Tu32)(__ccgo_up(bp)) > uint32(7) || libc.Int32FromUint8(c) != int32(0x7b) && libc.Int32FromUint8(c) != int32(0x5b) && !(libc.Int32FromUint8(_sqlite3CtypeMap[c])&libc.Int32FromInt32(0x04) != 0) || _jsonbValidityCheck(tls, p, uint32(0), (*TJsonParse)(unsafe.Pointer(p)).FnBlob, uint32(1)) == uint32(0)) { return int32(1) } (*TJsonParse)(unsafe.Pointer(p)).FaBlob = uintptr(0) (*TJsonParse)(unsafe.Pointer(p)).FnBlob = uint32(0) return 0 } // C documentation // // /* The query strategy is to look for an equality constraint on the json // ** column. Without such a constraint, the table cannot operate. idxNum is // ** 1 if the constraint is found, 3 if the constraint and zRoot are found, // ** and 0 otherwise. // */ func _jsonEachBestIndex(tls *libc.TLS, tab uintptr, pIdxInfo uintptr) (r int32) { var aIdx [2]int32 var i, iCol, iMask, idxMask, unusableMask, v1 int32 var pConstraint uintptr _, _, _, _, _, _, _, _ = aIdx, i, iCol, iMask, idxMask, pConstraint, unusableMask, v1 /* Index of constraints for JSON and ROOT */ unusableMask = 0 /* Mask of unusable JSON and ROOT constraints */ idxMask = 0 /* This implementation assumes that JSON and ROOT are the last two ** columns in the table */ _ = tab v1 = -libc.Int32FromInt32(1) aIdx[int32(1)] = v1 aIdx[0] = v1 pConstraint = (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaConstraint i = 0 for { if !(i < (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FnConstraint) { break } if (*Tsqlite3_index_constraint)(unsafe.Pointer(pConstraint)).FiColumn < int32(JEACH_JSON) { goto _2 } iCol = (*Tsqlite3_index_constraint)(unsafe.Pointer(pConstraint)).FiColumn - int32(JEACH_JSON) iMask = int32(1) << iCol if libc.Int32FromUint8((*Tsqlite3_index_constraint)(unsafe.Pointer(pConstraint)).Fusable) == 0 { unusableMask = unusableMask | iMask } else { if libc.Int32FromUint8((*Tsqlite3_index_constraint)(unsafe.Pointer(pConstraint)).Fop) == int32(SQLITE_INDEX_CONSTRAINT_EQ) { aIdx[iCol] = i idxMask = idxMask | iMask } } goto _2 _2: ; i = i + 1 pConstraint += 12 } if (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FnOrderBy > 0 && (**(**Tsqlite3_index_orderby)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaOrderBy))).FiColumn < 0 && libc.Int32FromUint8((**(**Tsqlite3_index_orderby)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaOrderBy))).Fdesc) == 0 { (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).ForderByConsumed = int32(1) } if unusableMask & ^idxMask != 0 { /* If there are any unusable constraints on JSON or ROOT, then reject ** this entire plan */ return int32(SQLITE_CONSTRAINT) } if aIdx[0] < 0 { /* No JSON input. Leave estimatedCost at the huge value that it was ** initialized to to discourage the query planner from selecting this ** plan. */ (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FidxNum = 0 } else { (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FestimatedCost = float64(1) i = aIdx[0] (**(**Tsqlite3_index_constraint_usage)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaConstraintUsage + uintptr(i)*8))).FargvIndex = int32(1) (**(**Tsqlite3_index_constraint_usage)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaConstraintUsage + uintptr(i)*8))).Fomit = uint8(1) if aIdx[int32(1)] < 0 { (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FidxNum = int32(1) /* Only JSON supplied. Plan 1 */ } else { i = aIdx[int32(1)] (**(**Tsqlite3_index_constraint_usage)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaConstraintUsage + uintptr(i)*8))).FargvIndex = int32(2) (**(**Tsqlite3_index_constraint_usage)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaConstraintUsage + uintptr(i)*8))).Fomit = uint8(1) (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FidxNum = int32(3) /* Both JSON and ROOT are supplied. Plan 3 */ } } return SQLITE_OK } // C documentation // // /* Return the current rowid value */ func _jsonEachRowid(tls *libc.TLS, cur uintptr, pRowid uintptr) (r int32) { var p uintptr _ = p p = cur **(**Tsqlite_int64)(__ccgo_up(pRowid)) = libc.Int64FromUint32((*TJsonEachCursor)(unsafe.Pointer(p)).FiRowid) return SQLITE_OK } // C documentation // // /* // ** Translate a single byte of Hex into an integer. // ** This routine only gives a correct answer if h really is a valid hexadecimal // ** character: 0..9a..fA..F. But unlike sqlite3HexToInt(), it does not // ** assert() if the digit is not hex. // */ func _jsonHexToInt(tls *libc.TLS, h int32) (r Tu8) { h = h + int32(9)*(int32(1)&(h>>int32(6))) return libc.Uint8FromInt32(h & libc.Int32FromInt32(0xf)) } // C documentation // // /* Remove a single character from the end of the string // */ func _jsonStringTrimOneChar(tls *libc.TLS, p uintptr) { if libc.Int32FromUint8((*TJsonString)(unsafe.Pointer(p)).FeErr) == 0 { (*TJsonString)(unsafe.Pointer(p)).FnUsed = (*TJsonString)(unsafe.Pointer(p)).FnUsed - 1 } } // C documentation // // /* The byte at index i is a node type-code. This routine // ** determines the payload size for that node and writes that // ** payload size in to *pSz. It returns the offset from i to the // ** beginning of the payload. Return 0 on error. // */ func _jsonbPayloadSize(tls *libc.TLS, pParse uintptr, i Tu32, pSz uintptr) (r Tu32) { var n, sz Tu32 var x, v1 Tu8 _, _, _, _ = n, sz, x, v1 if i >= (*TJsonParse)(unsafe.Pointer(pParse)).FnBlob { **(**Tu32)(__ccgo_up(pSz)) = uint32(0) return uint32(0) } else { v1 = libc.Uint8FromInt32(libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TJsonParse)(unsafe.Pointer(pParse)).FaBlob + uintptr(i)))) >> libc.Int32FromInt32(4)) x = v1 if libc.Int32FromUint8(v1) <= int32(11) { sz = uint32(x) n = uint32(1) } else { if libc.Int32FromUint8(x) == int32(12) { if i+uint32(1) >= (*TJsonParse)(unsafe.Pointer(pParse)).FnBlob { **(**Tu32)(__ccgo_up(pSz)) = uint32(0) return uint32(0) } sz = uint32(**(**Tu8)(__ccgo_up((*TJsonParse)(unsafe.Pointer(pParse)).FaBlob + uintptr(i+uint32(1))))) n = uint32(2) } else { if libc.Int32FromUint8(x) == int32(13) { if i+uint32(2) >= (*TJsonParse)(unsafe.Pointer(pParse)).FnBlob { **(**Tu32)(__ccgo_up(pSz)) = uint32(0) return uint32(0) } sz = libc.Uint32FromInt32(libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TJsonParse)(unsafe.Pointer(pParse)).FaBlob + uintptr(i+uint32(1)))))<= (*TJsonParse)(unsafe.Pointer(pParse)).FnBlob { **(**Tu32)(__ccgo_up(pSz)) = uint32(0) return uint32(0) } sz = uint32(**(**Tu8)(__ccgo_up((*TJsonParse)(unsafe.Pointer(pParse)).FaBlob + uintptr(i+uint32(1)))))<= (*TJsonParse)(unsafe.Pointer(pParse)).FnBlob || libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TJsonParse)(unsafe.Pointer(pParse)).FaBlob + uintptr(i+uint32(1))))) != 0 || libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TJsonParse)(unsafe.Pointer(pParse)).FaBlob + uintptr(i+uint32(2))))) != 0 || libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TJsonParse)(unsafe.Pointer(pParse)).FaBlob + uintptr(i+uint32(3))))) != 0 || libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TJsonParse)(unsafe.Pointer(pParse)).FaBlob + uintptr(i+uint32(4))))) != 0 { **(**Tu32)(__ccgo_up(pSz)) = uint32(0) return uint32(0) } sz = uint32(**(**Tu8)(__ccgo_up((*TJsonParse)(unsafe.Pointer(pParse)).FaBlob + uintptr(i+uint32(5)))))< libc.Int64FromUint32((*TJsonParse)(unsafe.Pointer(pParse)).FnBlob) && libc.Int64FromUint32(i)+libc.Int64FromUint32(sz)+libc.Int64FromUint32(n) > libc.Int64FromUint32((*TJsonParse)(unsafe.Pointer(pParse)).FnBlob-libc.Uint32FromInt32((*TJsonParse)(unsafe.Pointer(pParse)).Fdelta)) { **(**Tu32)(__ccgo_up(pSz)) = uint32(0) return uint32(0) } **(**Tu32)(__ccgo_up(pSz)) = sz return n } func _lookasideMallocSize(tls *libc.TLS, db uintptr, p uintptr) (r int32) { var v1 int32 _ = v1 if p < (*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpMiddle { v1 = libc.Int32FromUint16((*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FszTrue) } else { v1 = int32(LOOKASIDE_SMALL) } return v1 } // C documentation // // /* // ** Try to enlarge the memory allocation to hold at least sz bytes // */ func _memdbEnlarge(tls *libc.TLS, p uintptr, newSz Tsqlite3_int64) (r int32) { var pNew uintptr _ = pNew if (*TMemStore)(unsafe.Pointer(p)).FmFlags&uint32(SQLITE_DESERIALIZE_RESIZEABLE) == uint32(0) || (*TMemStore)(unsafe.Pointer(p)).FnMmap > 0 { return int32(SQLITE_FULL) } if newSz > (*TMemStore)(unsafe.Pointer(p)).FszMax { return int32(SQLITE_FULL) } newSz = newSz * int64(2) if newSz > (*TMemStore)(unsafe.Pointer(p)).FszMax { newSz = (*TMemStore)(unsafe.Pointer(p)).FszMax } pNew = _sqlite3Realloc(tls, (*TMemStore)(unsafe.Pointer(p)).FaData, libc.Uint64FromInt64(newSz)) if pNew == uintptr(0) { return libc.Int32FromInt32(SQLITE_IOERR) | libc.Int32FromInt32(12)<flags. // ** But it does set pMem->u.r and pMem->u.i appropriately. // */ func _numericType(tls *libc.TLS, pMem uintptr) (r Tu16) { if libc.Int32FromUint16((*TMem)(unsafe.Pointer(pMem)).Fflags)&(libc.Int32FromInt32(MEM_Int)|libc.Int32FromInt32(MEM_Real)|libc.Int32FromInt32(MEM_IntReal)|libc.Int32FromInt32(MEM_Null)) != 0 { return libc.Uint16FromInt32(libc.Int32FromUint16((*TMem)(unsafe.Pointer(pMem)).Fflags) & (libc.Int32FromInt32(MEM_Int) | libc.Int32FromInt32(MEM_Real) | libc.Int32FromInt32(MEM_IntReal) | libc.Int32FromInt32(MEM_Null))) } return _computeNumericType(tls, pMem) return uint16(0) } // C documentation // // /* // ** Ensure that the sub-journal file is open. If it is already open, this // ** function is a no-op. // ** // ** SQLITE_OK is returned if everything goes according to plan. An // ** SQLITE_IOERR_XXX error code is returned if a call to sqlite3OsOpen() // ** fails. // */ func _openSubJournal(tls *libc.TLS, pPager uintptr) (r int32) { var flags, nStmtSpill, rc int32 _, _, _ = flags, nStmtSpill, rc rc = SQLITE_OK if !((*Tsqlite3_file)(unsafe.Pointer((*TPager)(unsafe.Pointer(pPager)).Fsjfd)).FpMethods != libc.UintptrFromInt32(0)) { flags = libc.Int32FromInt32(SQLITE_OPEN_SUBJOURNAL) | libc.Int32FromInt32(SQLITE_OPEN_READWRITE) | libc.Int32FromInt32(SQLITE_OPEN_CREATE) | libc.Int32FromInt32(SQLITE_OPEN_EXCLUSIVE) | libc.Int32FromInt32(SQLITE_OPEN_DELETEONCLOSE) nStmtSpill = _sqlite3Config.FnStmtSpill if libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FjournalMode) == int32(PAGER_JOURNALMODE_MEMORY) || (*TPager)(unsafe.Pointer(pPager)).FsubjInMemory != 0 { nStmtSpill = -int32(1) } rc = _sqlite3JournalOpen(tls, (*TPager)(unsafe.Pointer(pPager)).FpVfs, uintptr(0), (*TPager)(unsafe.Pointer(pPager)).Fsjfd, flags, nStmtSpill) } return rc } // C documentation // // /* // ** Translate from TK_xx operator to WO_xx bitmask. // */ func _operatorMask(tls *libc.TLS, op int32) (r Tu16) { var c Tu16 _ = c if op >= int32(TK_EQ) { c = libc.Uint16FromInt32(libc.Int32FromInt32(WO_EQ) << (op - libc.Int32FromInt32(TK_EQ))) } else { if op == int32(TK_IN) { c = uint16(WO_IN) } else { if op == int32(TK_ISNULL) { c = uint16(WO_ISNULL) } else { c = uint16(WO_IS) } } } return c } // C documentation // // /* // ** The following routine implements the rough equivalent of localtime_r() // ** using whatever operating-system specific localtime facility that // ** is available. This routine returns 0 on success and // ** non-zero on any kind of error. // ** // ** If the sqlite3GlobalConfig.bLocaltimeFault variable is non-zero then this // ** routine will always fail. If bLocaltimeFault is nonzero and // ** sqlite3GlobalConfig.xAltLocaltime is not NULL, then xAltLocaltime() is // ** invoked in place of the OS-defined localtime() function. // ** // ** EVIDENCE-OF: R-62172-00036 In this implementation, the standard C // ** library function localtime_r() is used to assist in the calculation of // ** local time. // */ func _osLocaltime(tls *libc.TLS, t uintptr, pTm uintptr) (r int32) { var mutex, pX uintptr var rc int32 _, _, _ = mutex, pX, rc mutex = _sqlite3MutexAlloc(tls, int32(SQLITE_MUTEX_STATIC_MAIN)) Xsqlite3_mutex_enter(tls, mutex) pX = libc.Xlocaltime(tls, t) if _sqlite3Config.FbLocaltimeFault != 0 { if _sqlite3Config.FxAltLocaltime != uintptr(0) && 0 == (*(*func(*libc.TLS, uintptr, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{_sqlite3Config.FxAltLocaltime})))(tls, t, pTm) { pX = pTm } else { pX = uintptr(0) } } if pX != 0 { **(**Ttm)(__ccgo_up(pTm)) = **(**Ttm)(__ccgo_up(pX)) } Xsqlite3_mutex_leave(tls, mutex) rc = libc.BoolInt32(pX == uintptr(0)) return rc } // C documentation // // /* // ** Attempt to take an exclusive lock on the database file. If a PENDING lock // ** is obtained instead, immediately release it. // */ func _pagerExclusiveLock(tls *libc.TLS, pPager uintptr) (r int32) { var eOrigLock Tu8 var rc int32 _, _ = eOrigLock, rc /* Original lock */ eOrigLock = (*TPager)(unsafe.Pointer(pPager)).FeLock rc = _pagerLockDb(tls, pPager, int32(EXCLUSIVE_LOCK)) if rc != SQLITE_OK { /* If the attempt to grab the exclusive lock failed, release the ** pending lock that may have been obtained instead. */ _pagerUnlockDb(tls, pPager, libc.Int32FromUint8(eOrigLock)) } return rc } // C documentation // // /* // ** The write transaction open on pPager is being committed (bCommit==1) // ** or rolled back (bCommit==0). // ** // ** Return TRUE if and only if all dirty pages should be flushed to disk. // ** // ** Rules: // ** // ** * For non-TEMP databases, always sync to disk. This is necessary // ** for transactions to be durable. // ** // ** * Sync TEMP database only on a COMMIT (not a ROLLBACK) when the backing // ** file has been created already (via a spill on pagerStress()) and // ** when the number of dirty pages in memory exceeds 25% of the total // ** cache size. // */ func _pagerFlushOnCommit(tls *libc.TLS, pPager uintptr, bCommit int32) (r int32) { if libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FtempFile) == 0 { return int32(1) } if !(bCommit != 0) { return 0 } if !((*Tsqlite3_file)(unsafe.Pointer((*TPager)(unsafe.Pointer(pPager)).Ffd)).FpMethods != libc.UintptrFromInt32(0)) { return 0 } return libc.BoolInt32(_sqlite3PCachePercentDirty(tls, (*TPager)(unsafe.Pointer(pPager)).FpPCache) >= int32(25)) } // C documentation // // /* // ** Lock the database file to level eLock, which must be either SHARED_LOCK, // ** RESERVED_LOCK or EXCLUSIVE_LOCK. If the caller is successful, set the // ** Pager.eLock variable to the new locking state. // ** // ** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is // ** called, do not modify it unless the new locking state is EXCLUSIVE_LOCK. // ** See the comment above the #define of UNKNOWN_LOCK for an explanation // ** of this. // */ func _pagerLockDb(tls *libc.TLS, pPager uintptr, eLock int32) (r int32) { var rc, v1 int32 _, _ = rc, v1 rc = SQLITE_OK if libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FeLock) < eLock || libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FeLock) == libc.Int32FromInt32(EXCLUSIVE_LOCK)+libc.Int32FromInt32(1) { if (*TPager)(unsafe.Pointer(pPager)).FnoLock != 0 { v1 = SQLITE_OK } else { v1 = _sqlite3OsLock(tls, (*TPager)(unsafe.Pointer(pPager)).Ffd, eLock) } rc = v1 if rc == SQLITE_OK && (libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FeLock) != libc.Int32FromInt32(EXCLUSIVE_LOCK)+libc.Int32FromInt32(1) || eLock == int32(EXCLUSIVE_LOCK)) { (*TPager)(unsafe.Pointer(pPager)).FeLock = libc.Uint8FromInt32(eLock) } } return rc } // C documentation // // /* // ** Check if the *-wal file that corresponds to the database opened by pPager // ** exists if the database is not empty, or verify that the *-wal file does // ** not exist (by deleting it) if the database file is empty. // ** // ** If the database is not empty and the *-wal file exists, open the pager // ** in WAL mode. If the database is empty or if no *-wal file exists and // ** if no error occurs, make sure Pager.journalMode is not set to // ** PAGER_JOURNALMODE_WAL. // ** // ** Return SQLITE_OK or an error code. // ** // ** The caller must hold a SHARED lock on the database file to call this // ** function. Because an EXCLUSIVE lock on the db file is required to delete // ** a WAL on a none-empty database, this ensures there is no race condition // ** between the xAccess() below and an xDelete() being executed by some // ** other connection. // */ func _pagerOpenWalIfPresent(tls *libc.TLS, pPager uintptr) (r int32) { bp := tls.Alloc(16) defer tls.Free(16) var rc int32 var _ /* isWal at bp+0 */ int32 var _ /* nPage at bp+4 */ TPgno _ = rc rc = SQLITE_OK if !((*TPager)(unsafe.Pointer(pPager)).FtempFile != 0) { /* True if WAL file exists */ rc = _sqlite3OsAccess(tls, (*TPager)(unsafe.Pointer(pPager)).FpVfs, (*TPager)(unsafe.Pointer(pPager)).FzWal, SQLITE_ACCESS_EXISTS, bp) if rc == SQLITE_OK { if **(**int32)(__ccgo_up(bp)) != 0 { /* Size of the database file */ rc = _pagerPagecount(tls, pPager, bp+4) if rc != 0 { return rc } if **(**TPgno)(__ccgo_up(bp + 4)) == uint32(0) { rc = _sqlite3OsDelete(tls, (*TPager)(unsafe.Pointer(pPager)).FpVfs, (*TPager)(unsafe.Pointer(pPager)).FzWal, 0) } else { rc = _sqlite3PagerOpenWal(tls, pPager, uintptr(0)) } } else { if libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FjournalMode) == int32(PAGER_JOURNALMODE_WAL) { (*TPager)(unsafe.Pointer(pPager)).FjournalMode = uint8(PAGER_JOURNALMODE_DELETE) } } } } return rc } // C documentation // // /* // ** This function is called as part of the transition from PAGER_OPEN // ** to PAGER_READER state to determine the size of the database file // ** in pages (assuming the page size currently stored in Pager.pageSize). // ** // ** If no error occurs, SQLITE_OK is returned and the size of the database // ** in pages is stored in *pnPage. Otherwise, an error code (perhaps // ** SQLITE_IOERR_FSTAT) is returned and *pnPage is left unmodified. // */ func _pagerPagecount(tls *libc.TLS, pPager uintptr, pnPage uintptr) (r int32) { bp := tls.Alloc(16) defer tls.Free(16) var nPage TPgno var rc int32 var _ /* n at bp+0 */ Ti64 _, _ = nPage, rc /* Value to return via *pnPage */ /* Query the WAL sub-system for the database size. The WalDbsize() ** function returns zero if the WAL is not open (i.e. Pager.pWal==0), or ** if the database size is not available. The database size is not ** available from the WAL sub-system if the log file is empty or ** contains no valid committed transactions. */ nPage = _sqlite3WalDbsize(tls, (*TPager)(unsafe.Pointer(pPager)).FpWal) /* If the number of pages in the database is not available from the ** WAL sub-system, determine the page count based on the size of ** the database file. If the size of the database file is not an ** integer multiple of the page-size, round up the result. */ if nPage == uint32(0) && (*Tsqlite3_file)(unsafe.Pointer((*TPager)(unsafe.Pointer(pPager)).Ffd)).FpMethods != uintptr(0) { **(**Ti64)(__ccgo_up(bp)) = 0 /* Size of db file in bytes */ rc = _sqlite3OsFileSize(tls, (*TPager)(unsafe.Pointer(pPager)).Ffd, bp) if rc != SQLITE_OK { return rc } nPage = libc.Uint32FromInt64((**(**Ti64)(__ccgo_up(bp)) + (*TPager)(unsafe.Pointer(pPager)).FpageSize - libc.Int64FromInt32(1)) / (*TPager)(unsafe.Pointer(pPager)).FpageSize) } /* If the current number of pages in the file is greater than the ** configured maximum pager number, increase the allowed limit so ** that the file can be read. */ if nPage > (*TPager)(unsafe.Pointer(pPager)).FmxPgno { (*TPager)(unsafe.Pointer(pPager)).FmxPgno = nPage } **(**TPgno)(__ccgo_up(pnPage)) = nPage return SQLITE_OK } // C documentation // // /* // ** Release a reference to page pPg. pPg must have been returned by an // ** earlier call to pagerAcquireMapPage(). // */ func _pagerReleaseMapPage(tls *libc.TLS, pPg uintptr) { var pPager uintptr _ = pPager pPager = (*TPgHdr)(unsafe.Pointer(pPg)).FpPager (*TPager)(unsafe.Pointer(pPager)).FnMmapOut = (*TPager)(unsafe.Pointer(pPager)).FnMmapOut - 1 (*TPgHdr)(unsafe.Pointer(pPg)).FpDirty = (*TPager)(unsafe.Pointer(pPager)).FpMmapFreelist (*TPager)(unsafe.Pointer(pPager)).FpMmapFreelist = pPg _sqlite3OsUnfetch(tls, (*TPager)(unsafe.Pointer(pPager)).Ffd, libc.Int64FromUint32((*TPgHdr)(unsafe.Pointer(pPg)).Fpgno-libc.Uint32FromInt32(1))*(*TPager)(unsafe.Pointer(pPager)).FpageSize, (*TPgHdr)(unsafe.Pointer(pPg)).FpData) } // C documentation // // /* // ** Execute a rollback if a transaction is active and unlock the // ** database file. // ** // ** If the pager has already entered the ERROR state, do not attempt // ** the rollback at this time. Instead, pager_unlock() is called. The // ** call to pager_unlock() will discard all in-memory pages, unlock // ** the database file and move the pager back to OPEN state. If this // ** means that there is a hot-journal left in the file-system, the next // ** connection to obtain a shared lock on the pager (which may be this one) // ** will roll it back. // ** // ** If the pager has not already entered the ERROR state, but an IO or // ** malloc error occurs during a rollback, then this will itself cause // ** the pager to enter the ERROR state. Which will be cleared by the // ** call to pager_unlock(), as described above. // */ func _pagerUnlockAndRollback(tls *libc.TLS, pPager uintptr) { var eLock Tu8 var errCode int32 _, _ = eLock, errCode if libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FeState) != int32(PAGER_ERROR) && libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FeState) != PAGER_OPEN { if libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FeState) >= int32(PAGER_WRITER_LOCKED) { _sqlite3BeginBenignMalloc(tls) _sqlite3PagerRollback(tls, pPager) _sqlite3EndBenignMalloc(tls) } else { if !((*TPager)(unsafe.Pointer(pPager)).FexclusiveMode != 0) { _pager_end_transaction(tls, pPager, 0, 0) } } } else { if libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FeState) == int32(PAGER_ERROR) && libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FjournalMode) == int32(PAGER_JOURNALMODE_MEMORY) && (*Tsqlite3_file)(unsafe.Pointer((*TPager)(unsafe.Pointer(pPager)).Fjfd)).FpMethods != uintptr(0) { /* Special case for a ROLLBACK due to I/O error with an in-memory ** journal: We have to rollback immediately, before the journal is ** closed, because once it is closed, all content is forgotten. */ errCode = (*TPager)(unsafe.Pointer(pPager)).FerrCode eLock = (*TPager)(unsafe.Pointer(pPager)).FeLock (*TPager)(unsafe.Pointer(pPager)).FeState = uint8(PAGER_OPEN) (*TPager)(unsafe.Pointer(pPager)).FerrCode = SQLITE_OK (*TPager)(unsafe.Pointer(pPager)).FeLock = uint8(EXCLUSIVE_LOCK) _pager_playback(tls, pPager, int32(1)) (*TPager)(unsafe.Pointer(pPager)).FerrCode = errCode (*TPager)(unsafe.Pointer(pPager)).FeLock = eLock } } _pager_unlock(tls, pPager) } // C documentation // // /* // ** Unlock the database file to level eLock, which must be either NO_LOCK // ** or SHARED_LOCK. Regardless of whether or not the call to xUnlock() // ** succeeds, set the Pager.eLock variable to match the (attempted) new lock. // ** // ** Except, if Pager.eLock is set to UNKNOWN_LOCK when this function is // ** called, do not modify it. See the comment above the #define of // ** UNKNOWN_LOCK for an explanation of this. // */ func _pagerUnlockDb(tls *libc.TLS, pPager uintptr, eLock int32) (r int32) { var rc, v1 int32 _, _ = rc, v1 rc = SQLITE_OK if (*Tsqlite3_file)(unsafe.Pointer((*TPager)(unsafe.Pointer(pPager)).Ffd)).FpMethods != uintptr(0) { if (*TPager)(unsafe.Pointer(pPager)).FnoLock != 0 { v1 = SQLITE_OK } else { v1 = _sqlite3OsUnlock(tls, (*TPager)(unsafe.Pointer(pPager)).Ffd, eLock) } rc = v1 if libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FeLock) != libc.Int32FromInt32(EXCLUSIVE_LOCK)+libc.Int32FromInt32(1) { (*TPager)(unsafe.Pointer(pPager)).FeLock = libc.Uint8FromInt32(eLock) } } (*TPager)(unsafe.Pointer(pPager)).FchangeCountDone = (*TPager)(unsafe.Pointer(pPager)).FtempFile /* ticket fb3b3024ea238d5c */ return rc } // C documentation // // /* // ** This routine ends a transaction. A transaction is usually ended by // ** either a COMMIT or a ROLLBACK operation. This routine may be called // ** after rollback of a hot-journal, or if an error occurs while opening // ** the journal file or writing the very first journal-header of a // ** database transaction. // ** // ** This routine is never called in PAGER_ERROR state. If it is called // ** in PAGER_NONE or PAGER_SHARED state and the lock held is less // ** exclusive than a RESERVED lock, it is a no-op. // ** // ** Otherwise, any active savepoints are released. // ** // ** If the journal file is open, then it is "finalized". Once a journal // ** file has been finalized it is not possible to use it to roll back a // ** transaction. Nor will it be considered to be a hot-journal by this // ** or any other database connection. Exactly how a journal is finalized // ** depends on whether or not the pager is running in exclusive mode and // ** the current journal-mode (Pager.journalMode value), as follows: // ** // ** journalMode==MEMORY // ** Journal file descriptor is simply closed. This destroys an // ** in-memory journal. // ** // ** journalMode==TRUNCATE // ** Journal file is truncated to zero bytes in size. // ** // ** journalMode==PERSIST // ** The first 28 bytes of the journal file are zeroed. This invalidates // ** the first journal header in the file, and hence the entire journal // ** file. An invalid journal file cannot be rolled back. // ** // ** journalMode==DELETE // ** The journal file is closed and deleted using sqlite3OsDelete(). // ** // ** If the pager is running in exclusive mode, this method of finalizing // ** the journal file is never used. Instead, if the journalMode is // ** DELETE and the pager is in exclusive mode, the method described under // ** journalMode==PERSIST is used instead. // ** // ** After the journal is finalized, the pager moves to PAGER_READER state. // ** If running in non-exclusive rollback mode, the lock on the file is // ** downgraded to a SHARED_LOCK. // ** // ** SQLITE_OK is returned if no error occurs. If an error occurs during // ** any of the IO operations to finalize the journal file or unlock the // ** database then the IO error code is returned to the user. If the // ** operation to finalize the journal file fails, then the code still // ** tries to unlock the database file if not in exclusive mode. If the // ** unlock operation fails as well, then the first error code related // ** to the first error encountered (the journal finalization one) is // ** returned. // */ func _pager_end_transaction(tls *libc.TLS, pPager uintptr, hasSuper int32, bCommit int32) (r int32) { var bDelete, rc, rc2, v1 int32 _, _, _, _ = bDelete, rc, rc2, v1 rc = SQLITE_OK /* Error code from journal finalization operation */ rc2 = SQLITE_OK /* Error code from db file unlock operation */ /* Do nothing if the pager does not have an open write transaction ** or at least a RESERVED lock. This function may be called when there ** is no write-transaction active but a RESERVED or greater lock is ** held under two circumstances: ** ** 1. After a successful hot-journal rollback, it is called with ** eState==PAGER_NONE and eLock==EXCLUSIVE_LOCK. ** ** 2. If a connection with locking_mode=exclusive holding an EXCLUSIVE ** lock switches back to locking_mode=normal and then executes a ** read-transaction, this function is called with eState==PAGER_READER ** and eLock==EXCLUSIVE_LOCK when the read-transaction is closed. */ if libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FeState) < int32(PAGER_WRITER_LOCKED) && libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FeLock) < int32(RESERVED_LOCK) { return SQLITE_OK } _releaseAllSavepoints(tls, pPager) if (*Tsqlite3_file)(unsafe.Pointer((*TPager)(unsafe.Pointer(pPager)).Fjfd)).FpMethods != uintptr(0) { /* Finalize the journal file. */ if _sqlite3JournalIsInMemory(tls, (*TPager)(unsafe.Pointer(pPager)).Fjfd) != 0 { /* assert( pPager->journalMode==PAGER_JOURNALMODE_MEMORY ); */ _sqlite3OsClose(tls, (*TPager)(unsafe.Pointer(pPager)).Fjfd) } else { if libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FjournalMode) == int32(PAGER_JOURNALMODE_TRUNCATE) { if (*TPager)(unsafe.Pointer(pPager)).FjournalOff == 0 { rc = SQLITE_OK } else { rc = _sqlite3OsTruncate(tls, (*TPager)(unsafe.Pointer(pPager)).Fjfd, 0) if rc == SQLITE_OK && (*TPager)(unsafe.Pointer(pPager)).FfullSync != 0 { /* Make sure the new file size is written into the inode right away. ** Otherwise the journal might resurrect following a power loss and ** cause the last transaction to roll back. See ** https://bugzilla.mozilla.org/show_bug.cgi?id=1072773 */ rc = _sqlite3OsSync(tls, (*TPager)(unsafe.Pointer(pPager)).Fjfd, libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FsyncFlags)) } } (*TPager)(unsafe.Pointer(pPager)).FjournalOff = 0 } else { if libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FjournalMode) == int32(PAGER_JOURNALMODE_PERSIST) || (*TPager)(unsafe.Pointer(pPager)).FexclusiveMode != 0 && libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FjournalMode) < int32(PAGER_JOURNALMODE_WAL) { rc = _zeroJournalHdr(tls, pPager, libc.BoolInt32(hasSuper != 0 || (*TPager)(unsafe.Pointer(pPager)).FtempFile != 0)) (*TPager)(unsafe.Pointer(pPager)).FjournalOff = 0 } else { /* This branch may be executed with Pager.journalMode==MEMORY if ** a hot-journal was just rolled back. In this case the journal ** file should be closed and deleted. If this connection writes to ** the database file, it will do so using an in-memory journal. */ bDelete = libc.BoolInt32(!((*TPager)(unsafe.Pointer(pPager)).FtempFile != 0)) _sqlite3OsClose(tls, (*TPager)(unsafe.Pointer(pPager)).Fjfd) if bDelete != 0 { rc = _sqlite3OsDelete(tls, (*TPager)(unsafe.Pointer(pPager)).FpVfs, (*TPager)(unsafe.Pointer(pPager)).FzJournal, libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FextraSync)) } } } } } _sqlite3BitvecDestroy(tls, (*TPager)(unsafe.Pointer(pPager)).FpInJournal) (*TPager)(unsafe.Pointer(pPager)).FpInJournal = uintptr(0) (*TPager)(unsafe.Pointer(pPager)).FnRec = 0 if rc == SQLITE_OK { if (*TPager)(unsafe.Pointer(pPager)).FmemDb != 0 || _pagerFlushOnCommit(tls, pPager, bCommit) != 0 { _sqlite3PcacheCleanAll(tls, (*TPager)(unsafe.Pointer(pPager)).FpPCache) } else { _sqlite3PcacheClearWritable(tls, (*TPager)(unsafe.Pointer(pPager)).FpPCache) } _sqlite3PcacheTruncate(tls, (*TPager)(unsafe.Pointer(pPager)).FpPCache, (*TPager)(unsafe.Pointer(pPager)).FdbSize) } if (*TPager)(unsafe.Pointer(pPager)).FpWal != uintptr(0) { /* Drop the WAL write-lock, if any. Also, if the connection was in ** locking_mode=exclusive mode but is no longer, drop the EXCLUSIVE ** lock held on the database file. */ rc2 = _sqlite3WalEndWriteTransaction(tls, (*TPager)(unsafe.Pointer(pPager)).FpWal) } else { if rc == SQLITE_OK && bCommit != 0 && (*TPager)(unsafe.Pointer(pPager)).FdbFileSize > (*TPager)(unsafe.Pointer(pPager)).FdbSize { /* This branch is taken when committing a transaction in rollback-journal ** mode if the database file on disk is larger than the database image. ** At this point the journal has been finalized and the transaction ** successfully committed, but the EXCLUSIVE lock is still held on the ** file. So it is safe to truncate the database file to its minimum ** required size. */ rc = _pager_truncate(tls, pPager, (*TPager)(unsafe.Pointer(pPager)).FdbSize) } } if rc == SQLITE_OK && bCommit != 0 { rc = _sqlite3OsFileControl(tls, (*TPager)(unsafe.Pointer(pPager)).Ffd, int32(SQLITE_FCNTL_COMMIT_PHASETWO), uintptr(0)) if rc == int32(SQLITE_NOTFOUND) { rc = SQLITE_OK } } if !((*TPager)(unsafe.Pointer(pPager)).FexclusiveMode != 0) && (!((*TPager)(unsafe.Pointer(pPager)).FpWal != libc.UintptrFromInt32(0)) || _sqlite3WalExclusiveMode(tls, (*TPager)(unsafe.Pointer(pPager)).FpWal, 0) != 0) { rc2 = _pagerUnlockDb(tls, pPager, int32(SHARED_LOCK)) } (*TPager)(unsafe.Pointer(pPager)).FeState = uint8(PAGER_READER) (*TPager)(unsafe.Pointer(pPager)).FsetSuper = uint8(0) if rc == SQLITE_OK { v1 = rc2 } else { v1 = rc } return v1 } // C documentation // // /* // ** This function is called at the start of every write transaction. // ** There must already be a RESERVED or EXCLUSIVE lock on the database // ** file when this routine is called. // ** // ** Open the journal file for pager pPager and write a journal header // ** to the start of it. If there are active savepoints, open the sub-journal // ** as well. This function is only used when the journal file is being // ** opened to write a rollback log for a transaction. It is not used // ** when opening a hot journal file to roll it back. // ** // ** If the journal file is already open (as it may be in exclusive mode), // ** then this function just writes a journal header to the start of the // ** already open file. // ** // ** Whether or not the journal file is opened by this function, the // ** Pager.pInJournal bitvec structure is allocated. // ** // ** Return SQLITE_OK if everything is successful. Otherwise, return // ** SQLITE_NOMEM if the attempt to allocate Pager.pInJournal fails, or // ** an IO error code if opening or writing the journal file fails. // */ func _pager_open_journal(tls *libc.TLS, pPager uintptr) (r int32) { var flags, nSpill, rc int32 var pVfs uintptr _, _, _, _ = flags, nSpill, pVfs, rc rc = SQLITE_OK /* Return code */ pVfs = (*TPager)(unsafe.Pointer(pPager)).FpVfs /* Local cache of vfs pointer */ /* If already in the error state, this function is a no-op. But on ** the other hand, this routine is never called if we are already in ** an error state. */ if (*TPager)(unsafe.Pointer(pPager)).FerrCode != 0 { return (*TPager)(unsafe.Pointer(pPager)).FerrCode } if !((*TPager)(unsafe.Pointer(pPager)).FpWal != libc.UintptrFromInt32(0)) && libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FjournalMode) != int32(PAGER_JOURNALMODE_OFF) { (*TPager)(unsafe.Pointer(pPager)).FpInJournal = _sqlite3BitvecCreate(tls, (*TPager)(unsafe.Pointer(pPager)).FdbSize) if (*TPager)(unsafe.Pointer(pPager)).FpInJournal == uintptr(0) { return int32(SQLITE_NOMEM) } /* Open the journal file if it is not already open. */ if !((*Tsqlite3_file)(unsafe.Pointer((*TPager)(unsafe.Pointer(pPager)).Fjfd)).FpMethods != libc.UintptrFromInt32(0)) { if libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FjournalMode) == int32(PAGER_JOURNALMODE_MEMORY) { _sqlite3MemJournalOpen(tls, (*TPager)(unsafe.Pointer(pPager)).Fjfd) } else { flags = libc.Int32FromInt32(SQLITE_OPEN_READWRITE) | libc.Int32FromInt32(SQLITE_OPEN_CREATE) if (*TPager)(unsafe.Pointer(pPager)).FtempFile != 0 { flags = flags | (libc.Int32FromInt32(SQLITE_OPEN_DELETEONCLOSE) | libc.Int32FromInt32(SQLITE_OPEN_TEMP_JOURNAL)) flags = flags | int32(SQLITE_OPEN_EXCLUSIVE) nSpill = _sqlite3Config.FnStmtSpill } else { flags = flags | int32(SQLITE_OPEN_MAIN_JOURNAL) nSpill = _jrnlBufferSize(tls, pPager) } /* Verify that the database still has the same name as it did when ** it was originally opened. */ rc = _databaseIsUnmoved(tls, pPager) if rc == SQLITE_OK { rc = _sqlite3JournalOpen(tls, pVfs, (*TPager)(unsafe.Pointer(pPager)).FzJournal, (*TPager)(unsafe.Pointer(pPager)).Fjfd, flags, nSpill) } } } /* Write the first journal header to the journal file and open ** the sub-journal if necessary. */ if rc == SQLITE_OK { /* TODO: Check if all of these are really required. */ (*TPager)(unsafe.Pointer(pPager)).FnRec = 0 (*TPager)(unsafe.Pointer(pPager)).FjournalOff = 0 (*TPager)(unsafe.Pointer(pPager)).FsetSuper = uint8(0) (*TPager)(unsafe.Pointer(pPager)).FjournalHdr = 0 rc = _writeJournalHdr(tls, pPager) } } if rc != SQLITE_OK { _sqlite3BitvecDestroy(tls, (*TPager)(unsafe.Pointer(pPager)).FpInJournal) (*TPager)(unsafe.Pointer(pPager)).FpInJournal = uintptr(0) (*TPager)(unsafe.Pointer(pPager)).FjournalOff = 0 } else { (*TPager)(unsafe.Pointer(pPager)).FeState = uint8(PAGER_WRITER_CACHEMOD) } return rc } // C documentation // // /* Memory allocator for parser stack resizing. This is a thin wrapper around // ** sqlite3_realloc() that includes a call to sqlite3FaultSim() to facilitate // ** testing. // */ func _parserStackRealloc(tls *libc.TLS, pOld uintptr, newSize Tsqlite3_uint64, pParse uintptr) (r uintptr) { var p, v1 uintptr _, _ = p, v1 if _sqlite3FaultSim(tls, int32(700)) != 0 { v1 = uintptr(0) } else { v1 = Xsqlite3_realloc(tls, pOld, libc.Int32FromUint64(newSize)) } p = v1 if p == uintptr(0) { _sqlite3OomFault(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb) } return p } // C documentation // // /* // ** If there are currently more than nMaxPage pages allocated, try // ** to recycle pages to reduce the number allocated to nMaxPage. // */ func _pcache1EnforceMaxPage(tls *libc.TLS, pCache uintptr) { var p, pGroup, v1 uintptr var v2 bool _, _, _, _ = p, pGroup, v1, v2 pGroup = (*TPCache1)(unsafe.Pointer(pCache)).FpGroup for { if v2 = (*TPGroup)(unsafe.Pointer(pGroup)).FnPurgeable > (*TPGroup)(unsafe.Pointer(pGroup)).FnMaxPage; v2 { v1 = (*TPGroup)(unsafe.Pointer(pGroup)).Flru.FpLruPrev p = v1 } if !(v2 && libc.Int32FromUint16((*TPgHdr1)(unsafe.Pointer(v1)).FisAnchor) == 0) { break } _pcache1PinPage(tls, p) _pcache1RemoveFromHash(tls, p, int32(1)) } if (*TPCache1)(unsafe.Pointer(pCache)).FnPage == uint32(0) && (*TPCache1)(unsafe.Pointer(pCache)).FpBulk != 0 { Xsqlite3_free(tls, (*TPCache1)(unsafe.Pointer(pCache)).FpBulk) v1 = libc.UintptrFromInt32(0) (*TPCache1)(unsafe.Pointer(pCache)).FpFree = v1 (*TPCache1)(unsafe.Pointer(pCache)).FpBulk = v1 } } // C documentation // // /* // ** Implementation of the sqlite3_pcache.xPagecount method. // */ func _pcache1Pagecount(tls *libc.TLS, p uintptr) (r int32) { var n int32 var pCache uintptr _, _ = n, pCache pCache = p Xsqlite3_mutex_enter(tls, (*TPGroup)(unsafe.Pointer((*TPCache1)(unsafe.Pointer(pCache)).FpGroup)).Fmutex) n = libc.Int32FromUint32((*TPCache1)(unsafe.Pointer(pCache)).FnPage) Xsqlite3_mutex_leave(tls, (*TPGroup)(unsafe.Pointer((*TPCache1)(unsafe.Pointer(pCache)).FpGroup)).Fmutex) return n } // C documentation // // /* // ** Manage pPage's participation on the dirty list. Bits of the addRemove // ** argument determines what operation to do. The 0x01 bit means first // ** remove pPage from the dirty list. The 0x02 means add pPage back to // ** the dirty list. Doing both moves pPage to the front of the dirty list. // */ func _pcacheManageDirtyList(tls *libc.TLS, pPage uintptr, addRemove Tu8) { var p uintptr _ = p p = (*TPgHdr)(unsafe.Pointer(pPage)).FpCache if libc.Int32FromUint8(addRemove)&int32(PCACHE_DIRTYLIST_REMOVE) != 0 { /* Update the PCache1.pSynced variable if necessary. */ if (*TPCache)(unsafe.Pointer(p)).FpSynced == pPage { (*TPCache)(unsafe.Pointer(p)).FpSynced = (*TPgHdr)(unsafe.Pointer(pPage)).FpDirtyPrev } if (*TPgHdr)(unsafe.Pointer(pPage)).FpDirtyNext != 0 { (*TPgHdr)(unsafe.Pointer((*TPgHdr)(unsafe.Pointer(pPage)).FpDirtyNext)).FpDirtyPrev = (*TPgHdr)(unsafe.Pointer(pPage)).FpDirtyPrev } else { (*TPCache)(unsafe.Pointer(p)).FpDirtyTail = (*TPgHdr)(unsafe.Pointer(pPage)).FpDirtyPrev } if (*TPgHdr)(unsafe.Pointer(pPage)).FpDirtyPrev != 0 { (*TPgHdr)(unsafe.Pointer((*TPgHdr)(unsafe.Pointer(pPage)).FpDirtyPrev)).FpDirtyNext = (*TPgHdr)(unsafe.Pointer(pPage)).FpDirtyNext } else { /* If there are now no dirty pages in the cache, set eCreate to 2. ** This is an optimization that allows sqlite3PcacheFetch() to skip ** searching for a dirty page to eject from the cache when it might ** otherwise have to. */ (*TPCache)(unsafe.Pointer(p)).FpDirty = (*TPgHdr)(unsafe.Pointer(pPage)).FpDirtyNext if (*TPCache)(unsafe.Pointer(p)).FpDirty == uintptr(0) { /*OPTIMIZATION-IF-TRUE*/ (*TPCache)(unsafe.Pointer(p)).FeCreate = uint8(2) } } } if libc.Int32FromUint8(addRemove)&int32(PCACHE_DIRTYLIST_ADD) != 0 { (*TPgHdr)(unsafe.Pointer(pPage)).FpDirtyPrev = uintptr(0) (*TPgHdr)(unsafe.Pointer(pPage)).FpDirtyNext = (*TPCache)(unsafe.Pointer(p)).FpDirty if (*TPgHdr)(unsafe.Pointer(pPage)).FpDirtyNext != 0 { (*TPgHdr)(unsafe.Pointer((*TPgHdr)(unsafe.Pointer(pPage)).FpDirtyNext)).FpDirtyPrev = pPage } else { (*TPCache)(unsafe.Pointer(p)).FpDirtyTail = pPage if (*TPCache)(unsafe.Pointer(p)).FbPurgeable != 0 { (*TPCache)(unsafe.Pointer(p)).FeCreate = uint8(1) } } (*TPCache)(unsafe.Pointer(p)).FpDirty = pPage /* If pSynced is NULL and this page has a clear NEED_SYNC flag, set ** pSynced to point to it. Checking the NEED_SYNC flag is an ** optimization, as if pSynced points to a page with the NEED_SYNC ** flag set sqlite3PcacheFetchStress() searches through all newer ** entries of the dirty-list for a page with NEED_SYNC clear anyway. */ if !((*TPCache)(unsafe.Pointer(p)).FpSynced != 0) && 0 == libc.Int32FromUint16((*TPgHdr)(unsafe.Pointer(pPage)).Fflags)&int32(PGHDR_NEED_SYNC) { (*TPCache)(unsafe.Pointer(p)).FpSynced = pPage } } } var _pgsz = int32(4096) /* ** Check that the pShmNode->aLock[] array comports with the locking bitmasks ** held by each client. Return true if it does, or false otherwise. This ** is to be used in an assert(). e.g. ** ** assert( assertLockingArrayOk(pShmNode) ); */ var _posixIoFinder = uintptr(0) func _posixIoFinderImpl(tls *libc.TLS, z uintptr, p uintptr) (r uintptr) { _ = z _ = p return uintptr(unsafe.Pointer(&_posixIoMethods)) } // C documentation // // /* // ** Here are all of the sqlite3_io_methods objects for each of the // ** locking strategies. Functions that return pointers to these methods // ** are also created. // */ var _posixIoMethods = Tsqlite3_io_methods{ FiVersion: int32(3), } // C documentation // // /* // ** Different Unix systems declare open() in different ways. Same use // ** open(const char*,int,mode_t). Others use open(const char*,int,...). // ** The difference is important when using a pointer to the function. // ** // ** The safest way to deal with the problem is to always use this wrapper // ** which always has the same well-defined interface. // */ func _posixOpen(tls *libc.TLS, zFile uintptr, flags int32, mode int32) (r int32) { bp := tls.Alloc(16) defer tls.Free(16) return libc.Xopen(tls, zFile, flags, libc.VaList(bp+8, mode)) } // C documentation // // /* Figure out the best index to use to search a pragma virtual table. // ** // ** There are not really any index choices. But we want to encourage the // ** query planner to give == constraints on as many hidden parameters as // ** possible, and especially on the first hidden parameter. So return a // ** high cost if hidden parameters are unconstrained. // */ func _pragmaVtabBestIndex(tls *libc.TLS, tab uintptr, pIdxInfo uintptr) (r int32) { var i, j int32 var pConstraint, pTab uintptr var seen [2]int32 _, _, _, _, _ = i, j, pConstraint, pTab, seen pTab = tab (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FestimatedCost = libc.Float64FromInt32(1) if libc.Int32FromUint8((*TPragmaVtab)(unsafe.Pointer(pTab)).FnHidden) == 0 { return SQLITE_OK } pConstraint = (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaConstraint seen[0] = 0 seen[int32(1)] = 0 i = 0 for { if !(i < (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FnConstraint) { break } if (*Tsqlite3_index_constraint)(unsafe.Pointer(pConstraint)).FiColumn < libc.Int32FromUint8((*TPragmaVtab)(unsafe.Pointer(pTab)).FiHidden) { goto _1 } if libc.Int32FromUint8((*Tsqlite3_index_constraint)(unsafe.Pointer(pConstraint)).Fop) != int32(SQLITE_INDEX_CONSTRAINT_EQ) { goto _1 } if libc.Int32FromUint8((*Tsqlite3_index_constraint)(unsafe.Pointer(pConstraint)).Fusable) == 0 { return int32(SQLITE_CONSTRAINT) } j = (*Tsqlite3_index_constraint)(unsafe.Pointer(pConstraint)).FiColumn - libc.Int32FromUint8((*TPragmaVtab)(unsafe.Pointer(pTab)).FiHidden) seen[j] = i + int32(1) goto _1 _1: ; i = i + 1 pConstraint += 12 } if seen[0] == 0 { (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FestimatedCost = libc.Float64FromInt32(2147483647) (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FestimatedRows = int64(2147483647) return SQLITE_OK } j = seen[0] - int32(1) (**(**Tsqlite3_index_constraint_usage)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaConstraintUsage + uintptr(j)*8))).FargvIndex = int32(1) (**(**Tsqlite3_index_constraint_usage)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaConstraintUsage + uintptr(j)*8))).Fomit = uint8(1) (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FestimatedCost = libc.Float64FromInt32(20) (*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FestimatedRows = int64(20) if seen[int32(1)] != 0 { j = seen[int32(1)] - int32(1) (**(**Tsqlite3_index_constraint_usage)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaConstraintUsage + uintptr(j)*8))).FargvIndex = int32(2) (**(**Tsqlite3_index_constraint_usage)(__ccgo_up((*Tsqlite3_index_info)(unsafe.Pointer(pIdxInfo)).FaConstraintUsage + uintptr(j)*8))).Fomit = uint8(1) } return SQLITE_OK } // C documentation // // /* // ** Allocate memory for a temporary buffer needed for printf rendering. // ** // ** If the requested size of the temp buffer is larger than the size // ** of the output buffer in pAccum, then cause an SQLITE_TOOBIG error. // ** Do the size check before the memory allocation to prevent rogue // ** SQL from requesting large allocations using the precision or width // ** field of the printf() function. // */ func _printfTempBuf(tls *libc.TLS, pAccum uintptr, n Tsqlite3_int64) (r uintptr) { var z uintptr _ = z if (*Tsqlite3_str)(unsafe.Pointer(pAccum)).FaccError != 0 { return uintptr(0) } if n > libc.Int64FromUint32((*Tsqlite3_str)(unsafe.Pointer(pAccum)).FnAlloc) && n > libc.Int64FromUint32((*Tsqlite3_str)(unsafe.Pointer(pAccum)).FmxAlloc) { _sqlite3StrAccumSetError(tls, pAccum, uint8(SQLITE_TOOBIG)) return uintptr(0) } z = Xsqlite3_malloc(tls, int32(n)) if z == uintptr(0) { _sqlite3StrAccumSetError(tls, pAccum, uint8(SQLITE_NOMEM)) } return z } /* ** On machines with a small stack size, you can redefine the ** SQLITE_PRINT_BUF_SIZE to be something smaller, if desired. */ /* ** Hard limit on the precision of floating-point conversions. */ // C documentation // // /* // ** Read an entry from the pointer map. // ** // ** This routine retrieves the pointer map entry for page 'key', writing // ** the type and parent page number to *pEType and *pPgno respectively. // ** An error code is returned if something goes wrong, otherwise SQLITE_OK. // */ func _ptrmapGet(tls *libc.TLS, pBt uintptr, key TPgno, pEType uintptr, pPgno uintptr) (r int32) { bp := tls.Alloc(16) defer tls.Free(16) var iPtrmap, offset, rc int32 var pPtrmap uintptr var _ /* pDbPage at bp+0 */ uintptr _, _, _, _ = iPtrmap, offset, pPtrmap, rc iPtrmap = libc.Int32FromUint32(_ptrmapPageno(tls, pBt, key)) rc = _sqlite3PagerGet(tls, (*TBtShared)(unsafe.Pointer(pBt)).FpPager, libc.Uint32FromInt32(iPtrmap), bp, 0) if rc != 0 { return rc } pPtrmap = _sqlite3PagerGetData(tls, **(**uintptr)(__ccgo_up(bp))) offset = libc.Int32FromUint32(libc.Uint32FromInt32(5) * (key - libc.Uint32FromInt32(iPtrmap) - libc.Uint32FromInt32(1))) if offset < 0 { _sqlite3PagerUnref(tls, **(**uintptr)(__ccgo_up(bp))) return _sqlite3CorruptError(tls, int32(74364)) } **(**Tu8)(__ccgo_up(pEType)) = **(**Tu8)(__ccgo_up(pPtrmap + uintptr(offset))) if pPgno != 0 { **(**TPgno)(__ccgo_up(pPgno)) = _sqlite3Get4byte(tls, pPtrmap+uintptr(offset+int32(1))) } _sqlite3PagerUnref(tls, **(**uintptr)(__ccgo_up(bp))) if libc.Int32FromUint8(**(**Tu8)(__ccgo_up(pEType))) < int32(1) || libc.Int32FromUint8(**(**Tu8)(__ccgo_up(pEType))) > int32(5) { return _sqlite3CorruptError(tls, int32(74372)) } return SQLITE_OK } /* ** Given a btree page and a cell index (0 means the first cell on ** the page, 1 means the second cell, and so forth) return a pointer ** to the cell content. ** ** findCellPastPtr() does the same except it skips past the initial ** 4-byte child pointer found on interior pages, if there is one. ** ** This routine works only for pages that do not contain overflow cells. */ // C documentation // // /* // ** Given a page number of a regular database page, return the page // ** number for the pointer-map page that contains the entry for the // ** input page number. // ** // ** Return 0 (not a valid page) for pgno==1 since there is // ** no pointer map associated with page 1. The integrity_check logic // ** requires that ptrmapPageno(*,1)!=1. // */ func _ptrmapPageno(tls *libc.TLS, pBt uintptr, pgno TPgno) (r TPgno) { var iPtrMap, ret TPgno var nPagesPerMapPage int32 _, _, _ = iPtrMap, nPagesPerMapPage, ret if pgno < uint32(2) { return uint32(0) } nPagesPerMapPage = libc.Int32FromUint32((*TBtShared)(unsafe.Pointer(pBt)).FusableSize/uint32(5) + uint32(1)) iPtrMap = (pgno - uint32(2)) / libc.Uint32FromInt32(nPagesPerMapPage) ret = iPtrMap*libc.Uint32FromInt32(nPagesPerMapPage) + uint32(2) if ret == libc.Uint32FromInt32(_sqlite3PendingByte)/(*TBtShared)(unsafe.Pointer(pBt)).FpageSize+libc.Uint32FromInt32(1) { ret = ret + 1 } return ret } // C documentation // // /* // ** Called when a page of data is written to offset iOff of the database // ** file while the rbu handle is in capture mode. Record the page number // ** of the page being written in the aFrame[] array. // */ func _rbuCaptureDbWrite(tls *libc.TLS, pRbu uintptr, iOff Ti64) (r int32) { (**(**TRbuFrame)(__ccgo_up((*Tsqlite3rbu)(unsafe.Pointer(pRbu)).FaFrame + uintptr((*Tsqlite3rbu)(unsafe.Pointer(pRbu)).FnFrame-int32(1))*8))).FiDbPage = libc.Uint32FromInt64(iOff/int64((*Tsqlite3rbu)(unsafe.Pointer(pRbu)).Fpgsz)) + uint32(1) return SQLITE_OK } // C documentation // // /* // ** This is called as part of an incremental checkpoint operation. Copy // ** a single frame of data from the wal file into the database file, as // ** indicated by the RbuFrame object. // */ func _rbuCheckpointFrame(tls *libc.TLS, p uintptr, pFrame uintptr) { var iOff Ti64 var pDb, pWal uintptr _, _, _ = iOff, pDb, pWal pWal = (*Trbu_file)(unsafe.Pointer((*Trbu_file)(unsafe.Pointer((*Tsqlite3rbu)(unsafe.Pointer(p)).FpTargetFd)).FpWalFd)).FpReal pDb = (*Trbu_file)(unsafe.Pointer((*Tsqlite3rbu)(unsafe.Pointer(p)).FpTargetFd)).FpReal iOff = libc.Int64FromUint32((*TRbuFrame)(unsafe.Pointer(pFrame)).FiWalFrame-libc.Uint32FromInt32(1))*int64((*Tsqlite3rbu)(unsafe.Pointer(p)).Fpgsz+libc.Int32FromInt32(24)) + int64(32) + int64(24) (*Tsqlite3rbu)(unsafe.Pointer(p)).Frc = (*(*func(*libc.TLS, uintptr, uintptr, int32, Tsqlite3_int64) int32)(unsafe.Pointer(&struct{ uintptr }{(*Tsqlite3_io_methods)(unsafe.Pointer((*Tsqlite3_file)(unsafe.Pointer(pWal)).FpMethods)).FxRead})))(tls, pWal, (*Tsqlite3rbu)(unsafe.Pointer(p)).FaBuf, (*Tsqlite3rbu)(unsafe.Pointer(p)).Fpgsz, iOff) if (*Tsqlite3rbu)(unsafe.Pointer(p)).Frc != 0 { return } iOff = libc.Int64FromUint32((*TRbuFrame)(unsafe.Pointer(pFrame)).FiDbPage-libc.Uint32FromInt32(1)) * int64((*Tsqlite3rbu)(unsafe.Pointer(p)).Fpgsz) (*Tsqlite3rbu)(unsafe.Pointer(p)).Frc = (*(*func(*libc.TLS, uintptr, uintptr, int32, Tsqlite3_int64) int32)(unsafe.Pointer(&struct{ uintptr }{(*Tsqlite3_io_methods)(unsafe.Pointer((*Tsqlite3_file)(unsafe.Pointer(pDb)).FpMethods)).FxWrite})))(tls, pDb, (*Tsqlite3rbu)(unsafe.Pointer(p)).FaBuf, (*Tsqlite3rbu)(unsafe.Pointer(p)).Fpgsz, iOff) } /* ** This value is copied from the definition of ZIPVFS_CTRL_FILE_POINTER ** in zipvfs.h. */ func _rbuPutU16(tls *libc.TLS, aBuf uintptr, iVal Tu16) { **(**Tu8)(__ccgo_up(aBuf)) = libc.Uint8FromInt32(libc.Int32FromUint16(iVal) >> int32(8) & int32(0xFF)) **(**Tu8)(__ccgo_up(aBuf + 1)) = libc.Uint8FromInt32(libc.Int32FromUint16(iVal) >> 0 & int32(0xFF)) } // C documentation // // /* // ** Return the current wal-index header checksum for the target database // ** as a 64-bit integer. // ** // ** The checksum is store in the first page of xShmMap memory as an 8-byte // ** blob starting at byte offset 40. // */ func _rbuShmChecksum(tls *libc.TLS, p uintptr) (r Ti64) { bp := tls.Alloc(16) defer tls.Free(16) var iRet Ti64 var pDb uintptr var _ /* ptr at bp+0 */ uintptr _, _ = iRet, pDb iRet = 0 if (*Tsqlite3rbu)(unsafe.Pointer(p)).Frc == SQLITE_OK { pDb = (*Trbu_file)(unsafe.Pointer((*Tsqlite3rbu)(unsafe.Pointer(p)).FpTargetFd)).FpReal (*Tsqlite3rbu)(unsafe.Pointer(p)).Frc = (*(*func(*libc.TLS, uintptr, int32, int32, int32, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{(*Tsqlite3_io_methods)(unsafe.Pointer((*Tsqlite3_file)(unsafe.Pointer(pDb)).FpMethods)).FxShmMap})))(tls, pDb, 0, libc.Int32FromInt32(32)*libc.Int32FromInt32(1024), 0, bp) if (*Tsqlite3rbu)(unsafe.Pointer(p)).Frc == SQLITE_OK { iRet = libc.Int64FromUint64(uint64(libc.AtomicLoadPUint32(**(**uintptr)(__ccgo_up(bp))+libc.UintptrFromInt32(10)*4))< SELECT ..." can // ** run without using a temporary table for the results of the SELECT. // */ func _readsTable(tls *libc.TLS, p uintptr, iDb int32, pTab uintptr) (r int32) { var i, iEnd int32 var pIndex, pOp, pVTab, v, v1 uintptr var tnum TPgno _, _, _, _, _, _, _, _ = i, iEnd, pIndex, pOp, pVTab, tnum, v, v1 v = _sqlite3GetVdbe(tls, p) iEnd = _sqlite3VdbeCurrentAddr(tls, v) if libc.Int32FromUint8((*TTable)(unsafe.Pointer(pTab)).FeTabType) == int32(TABTYP_VTAB) { v1 = _sqlite3GetVTable(tls, (*TParse)(unsafe.Pointer(p)).Fdb, pTab) } else { v1 = uintptr(0) } pVTab = v1 i = int32(1) for { if !(i < iEnd) { break } pOp = _sqlite3VdbeGetOp(tls, v, i) if libc.Int32FromUint8((*TVdbeOp)(unsafe.Pointer(pOp)).Fopcode) == int32(OP_OpenRead) && (*TVdbeOp)(unsafe.Pointer(pOp)).Fp3 == iDb { tnum = libc.Uint32FromInt32((*TVdbeOp)(unsafe.Pointer(pOp)).Fp2) if tnum == (*TTable)(unsafe.Pointer(pTab)).Ftnum { return int32(1) } pIndex = (*TTable)(unsafe.Pointer(pTab)).FpIndex for { if !(pIndex != 0) { break } if tnum == (*TIndex)(unsafe.Pointer(pIndex)).Ftnum { return int32(1) } goto _3 _3: ; pIndex = (*TIndex)(unsafe.Pointer(pIndex)).FpNext } } if libc.Int32FromUint8((*TVdbeOp)(unsafe.Pointer(pOp)).Fopcode) == int32(OP_VOpen) && *(*uintptr)(unsafe.Pointer(pOp + 16)) == pVTab { return int32(1) } goto _2 _2: ; i = i + 1 } return 0 } // C documentation // // /* // ** Release a unixInodeInfo structure previously allocated by findInodeInfo(). // ** // ** The global mutex must be held when this routine is called, but the mutex // ** on the inode being deleted must NOT be held. // */ func _releaseInodeInfo(tls *libc.TLS, pFile uintptr) { var pInode uintptr _ = pInode pInode = (*TunixFile)(unsafe.Pointer(pFile)).FpInode if pInode != 0 { (*TunixInodeInfo)(unsafe.Pointer(pInode)).FnRef = (*TunixInodeInfo)(unsafe.Pointer(pInode)).FnRef - 1 if (*TunixInodeInfo)(unsafe.Pointer(pInode)).FnRef == 0 { Xsqlite3_mutex_enter(tls, (*TunixInodeInfo)(unsafe.Pointer(pInode)).FpLockMutex) _closePendingFds(tls, pFile) Xsqlite3_mutex_leave(tls, (*TunixInodeInfo)(unsafe.Pointer(pInode)).FpLockMutex) if (*TunixInodeInfo)(unsafe.Pointer(pInode)).FpPrev != 0 { (*TunixInodeInfo)(unsafe.Pointer((*TunixInodeInfo)(unsafe.Pointer(pInode)).FpPrev)).FpNext = (*TunixInodeInfo)(unsafe.Pointer(pInode)).FpNext } else { _inodeList = (*TunixInodeInfo)(unsafe.Pointer(pInode)).FpNext } if (*TunixInodeInfo)(unsafe.Pointer(pInode)).FpNext != 0 { (*TunixInodeInfo)(unsafe.Pointer((*TunixInodeInfo)(unsafe.Pointer(pInode)).FpNext)).FpPrev = (*TunixInodeInfo)(unsafe.Pointer(pInode)).FpPrev } Xsqlite3_mutex_free(tls, (*TunixInodeInfo)(unsafe.Pointer(pInode)).FpLockMutex) Xsqlite3_free(tls, pInode) } } } // C documentation // // /* // ** This is a Walker select callback. It does nothing. It is only required // ** because without a dummy callback, sqlite3WalkExpr() and similar do not // ** descend into sub-select statements. // */ func _renameColumnSelectCb(tls *libc.TLS, pWalker uintptr, p uintptr) (r int32) { if (*TSelect)(unsafe.Pointer(p)).FselFlags&libc.Uint32FromInt32(libc.Int32FromInt32(SF_View)|libc.Int32FromInt32(SF_CopyCte)) != 0 { return int32(WRC_Prune) } _renameWalkWith(tls, pWalker, p) return WRC_Continue } // C documentation // // /* // ** Resolve an expression that was part of an ATTACH or DETACH statement. This // ** is slightly different from resolving a normal SQL expression, because simple // ** identifiers are treated as strings, not possible column names or aliases. // ** // ** i.e. if the parser sees: // ** // ** ATTACH DATABASE abc AS def // ** // ** it treats the two expressions as literal strings 'abc' and 'def' instead of // ** looking for columns of the same name. // ** // ** This only applies to the root node of pExpr, so the statement: // ** // ** ATTACH DATABASE abc||def AS 'db2' // ** // ** will fail because neither abc or def can be resolved. // */ func _resolveAttachExpr(tls *libc.TLS, pName uintptr, pExpr uintptr) (r int32) { var rc int32 _ = rc rc = SQLITE_OK if pExpr != 0 { if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) != int32(TK_ID) { rc = _sqlite3ResolveExprNames(tls, pName, pExpr) } else { (*TExpr)(unsafe.Pointer(pExpr)).Fop = uint8(TK_STRING) } } return rc } // C documentation // // /* // ** Rtree virtual table module xClose method. // */ func _rtreeClose(tls *libc.TLS, cur uintptr) (r int32) { var pCsr, pRtree uintptr _, _ = pCsr, pRtree pRtree = (*Tsqlite3_vtab_cursor)(unsafe.Pointer(cur)).FpVtab pCsr = cur _resetCursor(tls, pCsr) Xsqlite3_finalize(tls, (*TRtreeCursor)(unsafe.Pointer(pCsr)).FpReadAux) Xsqlite3_free(tls, pCsr) (*TRtree)(unsafe.Pointer(pRtree)).FnCursor = (*TRtree)(unsafe.Pointer(pRtree)).FnCursor - 1 if (*TRtree)(unsafe.Pointer(pRtree)).FnCursor == uint32(0) && libc.Int32FromUint8((*TRtree)(unsafe.Pointer(pRtree)).FinWrTrans) == 0 { _nodeBlobReset(tls, pRtree) } return SQLITE_OK } // C documentation // // /* // ** Rtree virtual table module xEof method. // ** // ** Return non-zero if the cursor does not currently point to a valid // ** record (i.e if the scan has finished), or zero otherwise. // */ func _rtreeEof(tls *libc.TLS, cur uintptr) (r int32) { var pCsr uintptr _ = pCsr pCsr = cur return libc.Int32FromUint8((*TRtreeCursor)(unsafe.Pointer(pCsr)).FatEOF) } /* ** Convert raw bits from the on-disk RTree record into a coordinate value. ** The on-disk format is big-endian and needs to be converted for little- ** endian platforms. The on-disk record stores integer coordinates if ** eInt is true and it stores 32-bit floating point records if eInt is ** false. a[] is the four bytes of the on-disk record to be decoded. ** Store the results in "r". ** ** There are five versions of this macro. The last one is generic. The ** other four are various architectures-specific optimizations. */ // C documentation // // /* // ** Rtree virtual table module xRowid method. // */ func _rtreeRowid(tls *libc.TLS, pVtabCursor uintptr, pRowid uintptr) (r int32) { bp := tls.Alloc(16) defer tls.Free(16) var p, pCsr, pNode uintptr var _ /* rc at bp+0 */ int32 _, _, _ = p, pCsr, pNode pCsr = pVtabCursor p = _rtreeSearchPointFirst(tls, pCsr) **(**int32)(__ccgo_up(bp)) = SQLITE_OK pNode = _rtreeNodeOfFirstSearchPoint(tls, pCsr, bp) if **(**int32)(__ccgo_up(bp)) == SQLITE_OK && p != 0 { if libc.Int32FromUint8((*TRtreeSearchPoint)(unsafe.Pointer(p)).FiCell) >= _readInt16(tls, (*TRtreeNode)(unsafe.Pointer(pNode)).FzData+2) { **(**int32)(__ccgo_up(bp)) = int32(SQLITE_ABORT) } else { **(**Tsqlite_int64)(__ccgo_up(pRowid)) = _nodeGetRowid(tls, (*TRtreeCursor)(unsafe.Pointer(pCsr)).Fbase.FpVtab, pNode, libc.Int32FromUint8((*TRtreeSearchPoint)(unsafe.Pointer(p)).FiCell)) } } return **(**int32)(__ccgo_up(bp)) } // C documentation // // /* // ** Compare two search points. Return negative, zero, or positive if the first // ** is less than, equal to, or greater than the second. // ** // ** The rScore is the primary key. Smaller rScore values come first. // ** If the rScore is a tie, then use iLevel as the tie breaker with smaller // ** iLevel values coming first. In this way, if rScore is the same for all // ** SearchPoints, then iLevel becomes the deciding factor and the result // ** is a depth-first search, which is the desired default behavior. // */ func _rtreeSearchPointCompare(tls *libc.TLS, pA uintptr, pB uintptr) (r int32) { if (*TRtreeSearchPoint)(unsafe.Pointer(pA)).FrScore < (*TRtreeSearchPoint)(unsafe.Pointer(pB)).FrScore { return -int32(1) } if (*TRtreeSearchPoint)(unsafe.Pointer(pA)).FrScore > (*TRtreeSearchPoint)(unsafe.Pointer(pB)).FrScore { return +libc.Int32FromInt32(1) } if libc.Int32FromUint8((*TRtreeSearchPoint)(unsafe.Pointer(pA)).FiLevel) < libc.Int32FromUint8((*TRtreeSearchPoint)(unsafe.Pointer(pB)).FiLevel) { return -int32(1) } if libc.Int32FromUint8((*TRtreeSearchPoint)(unsafe.Pointer(pA)).FiLevel) > libc.Int32FromUint8((*TRtreeSearchPoint)(unsafe.Pointer(pB)).FiLevel) { return +libc.Int32FromInt32(1) } return 0 } // C documentation // // /* // ** This is the collating function named "RTRIM" which is always // ** available. Ignore trailing spaces. // */ func _rtrimCollFunc(tls *libc.TLS, pUser uintptr, nKey1 int32, pKey1 uintptr, nKey2 int32, pKey2 uintptr) (r int32) { var pK1, pK2 uintptr _, _ = pK1, pK2 pK1 = pKey1 pK2 = pKey2 for nKey1 != 0 && libc.Int32FromUint8(**(**Tu8)(__ccgo_up(pK1 + uintptr(nKey1-int32(1))))) == int32(' ') { nKey1 = nKey1 - 1 } for nKey2 != 0 && libc.Int32FromUint8(**(**Tu8)(__ccgo_up(pK2 + uintptr(nKey2-int32(1))))) == int32(' ') { nKey2 = nKey2 - 1 } return _binCollFunc(tls, pUser, nKey1, pKey1, nKey2, pKey2) } // C documentation // // /* // ** Save the current cursor position in the variables BtCursor.nKey // ** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK. // ** // ** The caller must ensure that the cursor is valid (has eState==CURSOR_VALID) // ** prior to calling this routine. // */ func _saveCursorPosition(tls *libc.TLS, pCur uintptr) (r int32) { var rc int32 var v1 uintptr _, _ = rc, v1 if libc.Int32FromUint8((*TBtCursor)(unsafe.Pointer(pCur)).FcurFlags)&int32(BTCF_Pinned) != 0 { return libc.Int32FromInt32(SQLITE_CONSTRAINT) | libc.Int32FromInt32(11)< int64((*TSessionBuffer)(unsafe.Pointer(p)).FnAlloc) { if (*TSessionBuffer)(unsafe.Pointer(p)).FnAlloc != 0 { v1 = (*TSessionBuffer)(unsafe.Pointer(p)).FnAlloc } else { v1 = int32(128) } nNew = int64(v1) for cond := true; cond; cond = nNew < nReq { nNew = nNew * int64(2) } /* The value of SESSION_MAX_BUFFER_SZ is copied from the implementation ** of sqlite3_realloc64(). Allocations greater than this size in bytes ** always fail. It is used here to ensure that this routine can always ** allocate up to this limit - instead of up to the largest power of ** two smaller than the limit. */ if nNew > int64(libc.Int32FromInt32(0x7FFFFF00)-libc.Int32FromInt32(1)) { nNew = int64(libc.Int32FromInt32(0x7FFFFF00) - libc.Int32FromInt32(1)) if nNew < nReq { **(**int32)(__ccgo_up(pRc)) = int32(SQLITE_NOMEM) return int32(1) } } aNew = Xsqlite3_realloc64(tls, (*TSessionBuffer)(unsafe.Pointer(p)).FaBuf, libc.Uint64FromInt64(nNew)) if uintptr(0) == aNew { **(**int32)(__ccgo_up(pRc)) = int32(SQLITE_NOMEM) } else { (*TSessionBuffer)(unsafe.Pointer(p)).FaBuf = aNew (*TSessionBuffer)(unsafe.Pointer(p)).FnAlloc = int32(nNew) } } return libc.BoolInt32(**(**int32)(__ccgo_up(pRc)) != SQLITE_OK) } // C documentation // // /* // ** Based on the primary key values stored in change aRecord, calculate a // ** hash key. Assume the has table has nBucket buckets. The hash keys // ** calculated by this function are compatible with those calculated by // ** sessionPreupdateHash(). // ** // ** The bPkOnly argument is non-zero if the record at aRecord[] is from // ** a patchset DELETE. In this case the non-PK fields are omitted entirely. // */ func _sessionChangeHash(tls *libc.TLS, pTab uintptr, bPkOnly int32, aRecord uintptr, nBucket int32) (r uint32) { bp := tls.Alloc(16) defer tls.Free(16) var a, v2 uintptr var eType, i, isPK int32 var h uint32 var _ /* n at bp+0 */ int32 _, _, _, _, _, _ = a, eType, h, i, isPK, v2 h = uint32(0) /* Used to iterate through columns */ a = aRecord /* Used to iterate through change record */ i = 0 for { if !(i < (*TSessionTable)(unsafe.Pointer(pTab)).FnCol) { break } isPK = libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TSessionTable)(unsafe.Pointer(pTab)).FabPK + uintptr(i)))) if bPkOnly != 0 && isPK == 0 { goto _1 } if isPK != 0 { v2 = a a = a + 1 eType = libc.Int32FromUint8(**(**Tu8)(__ccgo_up(v2))) h = _sessionHashAppendType(tls, h, eType) if eType == int32(SQLITE_INTEGER) || eType == int32(SQLITE_FLOAT) { h = _sessionHashAppendI64(tls, h, _sessionGetI64(tls, a)) a = a + uintptr(8) } else { if eType == int32(SQLITE_TEXT) || eType == int32(SQLITE_BLOB) { a = a + uintptr(_sessionVarintGet(tls, a, bp)) h = _sessionHashAppendBlob(tls, h, **(**int32)(__ccgo_up(bp)), a) a = a + uintptr(**(**int32)(__ccgo_up(bp))) } } /* It should not be possible for eType to be SQLITE_NULL or 0x00 here, ** as the session module does not record changes for rows with NULL ** values stored in primary key columns. But a corrupt changesets ** may contain such a value. */ } else { a = a + uintptr(_sessionSerialLen(tls, a)) } goto _1 _1: ; i = i + 1 } return h % libc.Uint32FromInt32(nBucket) } // C documentation // // /* // ** The input pointer currently points to the first byte of the first field // ** of a record consisting of nCol columns. This function ensures the entire // ** record is buffered. It does not move the input pointer. // ** // ** If successful, SQLITE_OK is returned and *pnByte is set to the size of // ** the record in bytes. Otherwise, an SQLite error code is returned. The // ** final value of *pnByte is undefined in this case. // */ func _sessionChangesetBufferRecord(tls *libc.TLS, pIn uintptr, nCol int32, pnByte uintptr) (r int32) { bp := tls.Alloc(16) defer tls.Free(16) var eType, i, nRem, rc int32 var nByte, v2 Ti64 var _ /* n at bp+0 */ int32 _, _, _, _, _, _ = eType, i, nByte, nRem, rc, v2 rc = SQLITE_OK nByte = 0 i = 0 for { if !(rc == SQLITE_OK && i < nCol) { break } rc = _sessionInputBuffer(tls, pIn, int32(nByte+int64(10))) if rc == SQLITE_OK { v2 = nByte nByte = nByte + 1 eType = libc.Int32FromUint8(**(**Tu8)(__ccgo_up((*TSessionInput)(unsafe.Pointer(pIn)).FaData + uintptr(int64((*TSessionInput)(unsafe.Pointer(pIn)).FiNext)+v2)))) if eType == int32(SQLITE_TEXT) || eType == int32(SQLITE_BLOB) { nRem = int32(int64((*TSessionInput)(unsafe.Pointer(pIn)).FnData) - (int64((*TSessionInput)(unsafe.Pointer(pIn)).FiNext) + nByte)) nByte = nByte + int64(_sessionVarintGetSafe(tls, (*TSessionInput)(unsafe.Pointer(pIn)).FaData+uintptr(int64((*TSessionInput)(unsafe.Pointer(pIn)).FiNext)+nByte), nRem, bp)) nByte = nByte + int64(**(**int32)(__ccgo_up(bp))) rc = _sessionInputBuffer(tls, pIn, int32(nByte)) } else { if eType == int32(SQLITE_INTEGER) || eType == int32(SQLITE_FLOAT) { nByte = nByte + int64(8) } else { if eType != 0 && eType != int32(SQLITE_NULL) { rc = _sqlite3CorruptError(tls, int32(237456)) } } } } if rc == SQLITE_OK && int64((*TSessionInput)(unsafe.Pointer(pIn)).FiNext)+nByte > int64((*TSessionInput)(unsafe.Pointer(pIn)).FnData) { rc = _sqlite3CorruptError(tls, int32(237460)) } goto _1 _1: ; i = i + 1 } **(**int32)(__ccgo_up(pnByte)) = int32(nByte) return rc } // C documentation // // /* // ** Read a 64-bit big-endian integer value from buffer aRec[]. Return // ** the value read. // */ func _sessionGetI64(tls *libc.TLS, aRec uintptr) (r Tsqlite3_int64) { var x Tu64 var y Tu32 _, _ = x, y x = uint64(uint32(**(**Tu8)(__ccgo_up(aRec)))<>libc.Int32FromInt32(32)&libc.Int64FromUint32(0xFFFFFFFF)) } // C documentation // // /* // ** Append the hash of the data type passed as the second argument to the // ** hash-key value passed as the first. Return the new hash-key value. // */ func _sessionHashAppendType(tls *libc.TLS, h uint32, eType int32) (r uint32) { return h<> libc.Int32FromInt32(56) & int64(0xFF)) **(**Tu8)(__ccgo_up(aBuf + 1)) = libc.Uint8FromInt64(i >> libc.Int32FromInt32(48) & int64(0xFF)) **(**Tu8)(__ccgo_up(aBuf + 2)) = libc.Uint8FromInt64(i >> libc.Int32FromInt32(40) & int64(0xFF)) **(**Tu8)(__ccgo_up(aBuf + 3)) = libc.Uint8FromInt64(i >> libc.Int32FromInt32(32) & int64(0xFF)) **(**Tu8)(__ccgo_up(aBuf + 4)) = libc.Uint8FromInt64(i >> libc.Int32FromInt32(24) & int64(0xFF)) **(**Tu8)(__ccgo_up(aBuf + 5)) = libc.Uint8FromInt64(i >> libc.Int32FromInt32(16) & int64(0xFF)) **(**Tu8)(__ccgo_up(aBuf + 6)) = libc.Uint8FromInt64(i >> libc.Int32FromInt32(8) & int64(0xFF)) **(**Tu8)(__ccgo_up(aBuf + 7)) = libc.Uint8FromInt64(i >> libc.Int32FromInt32(0) & int64(0xFF)) } // C documentation // // /* // ** The buffer that the argument points to contains a serialized SQL value. // ** Return the number of bytes of space occupied by the value (including // ** the type byte). // */ func _sessionSerialLen(tls *libc.TLS, a uintptr) (r int32) { bp := tls.Alloc(16) defer tls.Free(16) var e int32 var _ /* n at bp+0 */ int32 _ = e e = libc.Int32FromUint8(**(**Tu8)(__ccgo_up(a))) if e == int32(SQLITE_INTEGER) || e == int32(SQLITE_FLOAT) { return int32(9) } if e == int32(SQLITE_TEXT) || e == int32(SQLITE_BLOB) { return _sessionVarintGet(tls, a+1, bp) + int32(1) + **(**int32)(__ccgo_up(bp)) } return int32(1) } // C documentation // // /* // ** When this function is called, *ppRec points to the start of a record // ** that contains nCol values. This function advances the pointer *ppRec // ** until it points to the byte immediately following that record. // */ func _sessionSkipRecord(tls *libc.TLS, ppRec uintptr, nCol int32) { bp := tls.Alloc(16) defer tls.Free(16) var aRec, v2 uintptr var eType, i int32 var _ /* nByte at bp+0 */ int32 _, _, _, _ = aRec, eType, i, v2 aRec = **(**uintptr)(__ccgo_up(ppRec)) i = 0 for { if !(i < nCol) { break } v2 = aRec aRec = aRec + 1 eType = libc.Int32FromUint8(**(**Tu8)(__ccgo_up(v2))) if eType == int32(SQLITE_TEXT) || eType == int32(SQLITE_BLOB) { aRec = aRec + uintptr(_sessionVarintGet(tls, aRec, bp)) aRec = aRec + uintptr(**(**int32)(__ccgo_up(bp))) } else { if eType == int32(SQLITE_INTEGER) || eType == int32(SQLITE_FLOAT) { aRec = aRec + uintptr(8) } } goto _1 _1: ; i = i + 1 } **(**uintptr)(__ccgo_up(ppRec)) = aRec } // C documentation // // /* // ** Read a varint value from aBuf[] into *piVal. Return the number of // ** bytes read. // */ func _sessionVarintGet(tls *libc.TLS, aBuf uintptr, piVal uintptr) (r int32) { var v1 int32 _ = v1 if libc.Int32FromUint8(**(**Tu8)(__ccgo_up(aBuf))) < libc.Int32FromUint8(libc.Uint8FromInt32(0x80)) { **(**int32)(__ccgo_up(piVal)) = libc.Int32FromUint32(uint32(**(**Tu8)(__ccgo_up(aBuf)))) v1 = libc.Int32FromInt32(1) } else { v1 = libc.Int32FromUint8(_sqlite3GetVarint32(tls, aBuf, piVal)) } return libc.Int32FromUint8(libc.Uint8FromInt32(v1)) } // C documentation // // /* // ** Return the number of bytes required to store value iVal as a varint. // */ func _sessionVarintLen(tls *libc.TLS, iVal int32) (r int32) { return _sqlite3VarintLen(tls, libc.Uint64FromInt32(iVal)) } // C documentation // // /* // ** Write a varint with value iVal into the buffer at aBuf. Return the // ** number of bytes written. // */ func _sessionVarintPut(tls *libc.TLS, aBuf uintptr, iVal int32) (r int32) { var v1 int32 _ = v1 if libc.Uint32FromInt32(iVal) < libc.Uint32FromInt32(0x80) { **(**Tu8)(__ccgo_up(aBuf)) = libc.Uint8FromInt32(iVal) v1 = libc.Int32FromInt32(1) } else { v1 = _sqlite3PutVarint(tls, aBuf, libc.Uint64FromInt32(iVal)) } return libc.Int32FromUint8(libc.Uint8FromInt32(v1)) } // C documentation // // /* // ** If the last opcode is a OP_Copy, then set the do-not-merge flag (p5) // ** so that a subsequent copy will not be merged into this one. // */ func _setDoNotMergeFlagOnCopy(tls *libc.TLS, v uintptr) { if libc.Int32FromUint8((*TVdbeOp)(unsafe.Pointer(_sqlite3VdbeGetLastOp(tls, v))).Fopcode) == int32(OP_Copy) { _sqlite3VdbeChangeP5(tls, v, uint16(1)) /* Tag trailing OP_Copy as not mergeable */ } } // C documentation // // /* // ** Add the file descriptor used by file handle pFile to the corresponding // ** pUnused list. // */ func _setPendingFd(tls *libc.TLS, pFile uintptr) { var p, pInode uintptr _, _ = p, pInode pInode = (*TunixFile)(unsafe.Pointer(pFile)).FpInode p = (*TunixFile)(unsafe.Pointer(pFile)).FpPreallocatedUnused (*TUnixUnusedFd)(unsafe.Pointer(p)).FpNext = (*TunixInodeInfo)(unsafe.Pointer(pInode)).FpUnused (*TunixInodeInfo)(unsafe.Pointer(pInode)).FpUnused = p (*TunixFile)(unsafe.Pointer(pFile)).Fh = -int32(1) (*TunixFile)(unsafe.Pointer(pFile)).FpPreallocatedUnused = uintptr(0) } // C documentation // // /* // ** Set result column names for a pragma. // */ func _setPragmaResultColumnNames(tls *libc.TLS, v uintptr, pPragma uintptr) { var i, j, v1 int32 var n Tu8 _, _, _, _ = i, j, n, v1 n = (*TPragmaName)(unsafe.Pointer(pPragma)).FnPragCName if libc.Int32FromUint8(n) == 0 { v1 = int32(1) } else { v1 = libc.Int32FromUint8(n) } _sqlite3VdbeSetNumCols(tls, v, v1) if libc.Int32FromUint8(n) == 0 { _sqlite3VdbeSetColName(tls, v, 0, COLNAME_NAME, (*TPragmaName)(unsafe.Pointer(pPragma)).FzName, libc.UintptrFromInt32(0)) } else { i = 0 j = libc.Int32FromUint8((*TPragmaName)(unsafe.Pointer(pPragma)).FiPragCName) for { if !(i < libc.Int32FromUint8(n)) { break } _sqlite3VdbeSetColName(tls, v, i, COLNAME_NAME, _pragCName[j], libc.UintptrFromInt32(0)) goto _2 _2: ; i = i + 1 j = j + 1 } } } // C documentation // // /* // ** Set the value of the Pager.sectorSize variable for the given // ** pager based on the value returned by the xSectorSize method // ** of the open database file. The sector size will be used // ** to determine the size and alignment of journal header and // ** super-journal pointers within created journal files. // ** // ** For temporary files the effective sector size is always 512 bytes. // ** // ** Otherwise, for non-temporary files, the effective sector size is // ** the value returned by the xSectorSize() method rounded up to 32 if // ** it is less than 32, or rounded down to MAX_SECTOR_SIZE if it // ** is greater than MAX_SECTOR_SIZE. // ** // ** If the file has the SQLITE_IOCAP_POWERSAFE_OVERWRITE property, then set // ** the effective sector size to its minimum value (512). The purpose of // ** pPager->sectorSize is to define the "blast radius" of bytes that // ** might change if a crash occurs while writing to a single byte in // ** that range. But with POWERSAFE_OVERWRITE, the blast radius is zero // ** (that is what POWERSAFE_OVERWRITE means), so we minimize the sector // ** size. For backwards compatibility of the rollback journal file format, // ** we cannot reduce the effective sector size below 512. // */ func _setSectorSize(tls *libc.TLS, pPager uintptr) { if (*TPager)(unsafe.Pointer(pPager)).FtempFile != 0 || _sqlite3OsDeviceCharacteristics(tls, (*TPager)(unsafe.Pointer(pPager)).Ffd)&int32(SQLITE_IOCAP_POWERSAFE_OVERWRITE) != 0 { /* Sector size doesn't matter for temporary files. Also, the file ** may not have been opened yet, in which case the OsSectorSize() ** call will segfault. */ (*TPager)(unsafe.Pointer(pPager)).FsectorSize = uint32(512) } else { (*TPager)(unsafe.Pointer(pPager)).FsectorSize = libc.Uint32FromInt32(_sqlite3SectorSize(tls, (*TPager)(unsafe.Pointer(pPager)).Ffd)) } } // C documentation // // /* // ** The string z[] is an text representation of a real number. // ** Convert this string to a double and write it into *pResult. // ** // ** z[] must be UTF-8 and zero-terminated. // ** // ** Return positive if the result is a valid real number (or integer) and // ** zero or negative if the string is empty or contains extraneous text. // ** Lower bits of the return value contain addition information about the // ** parse: // ** // ** bit 0 => Set if any prefix of the input is valid. Clear if // ** there is no prefix of the input that can be seen as // ** a valid floating point number. // ** bit 1 => Set if the input contains a decimal point or eNNN // ** clause. Zero if the input is an integer. // ** bit 2 => The input is exactly 0.0, not an underflow from // ** some value near zero. // ** bit 3 => Set if there are more than about 19 significant // ** digits in the input. // ** // ** If the input contains a syntax error but begins with text that might // ** be a valid number of some kind, then the result is negative. The // ** result is only zero if no prefix of the input could be interpreted as // ** a number. // ** // ** Leading and trailing whitespace is ignored. Valid numbers are in // ** one of the formats below: // ** // ** [+-]digits[E[+-]digits] // ** [+-]digits.[digits][E[+-]digits] // ** [+-].digits[E[+-]digits] // ** // ** Algorithm sketch: Compute an unsigned 64-bit integer s and a base-10 // ** exponent d such that the value encoding by the input is s*pow(10,d). // ** Then invoke sqlite3Fp10Convert2() to calculated the closest possible // ** IEEE754 double. The sign is added back afterwards, if the input string // ** starts with a "-". The use of an unsigned 64-bit s mantissa means that // ** only about the first 19 significant digits of the input can contribute // ** to the result. This can result in suboptimal rounding decisions when // ** correct rounding requires more than 19 input digits. For example, // ** this routine renders "3500000000000000.2500001" as // ** 3500000000000000.0 instead of 3500000000000000.5 because the decision // ** to round up instead of using banker's rounding to round down is determined // ** by the 23rd significant digit, which this routine ignores. It is not // ** possible to do better without some kind of BigNum. // */ func _sqlite3AtoF(tls *libc.TLS, zIn uintptr, pResult uintptr) (r int32) { var d, esign, exp, mState, neg int32 var s Tu64 var v, v3, v4 uint32 var z, v7 uintptr _, _, _, _, _, _, _, _, _, _, _ = d, esign, exp, mState, neg, s, v, z, v3, v4, v7 z = zIn neg = 0 /* True for a negative value */ s = uint64(0) /* mantissa */ d = 0 /* Value is s * pow(10,d) */ mState = 0 /* Value of a single digit */ goto start_of_text start_of_text: ; v3 = uint32(**(**uint8)(__ccgo_up(z))) - libc.Uint32FromUint8('0') v = v3 if !(v3 < uint32(10)) { goto _1 } goto parse_integer_part parse_integer_part: ; mState = int32(1) s = uint64(v) z = z + 1 for { v3 = uint32(**(**uint8)(__ccgo_up(z))) - libc.Uint32FromUint8('0') v = v3 if !(v3 < uint32(10)) { break } s = s*uint64(10) + uint64(v) z = z + 1 if s >= (libc.Uint64FromUint32(0xffffffff)|libc.Uint64FromUint32(0xffffffff)< 0 { goto bitvec_end } /* NULL pBitvec tests */ _sqlite3BitvecSet(tls, uintptr(0), uint32(1)) _sqlite3BitvecClear(tls, uintptr(0), uint32(1), pTmpSpace) /* Run the program */ v1 = libc.Int32FromInt32(0) **(**int32)(__ccgo_up(bp)) = v1 pc = v1 for { v1 = **(**int32)(__ccgo_up(aOp + uintptr(pc)*4)) op = v1 if !(v1 != 0) { break } if op >= int32(6) { pc = pc + 1 continue } switch op { case int32(1): fallthrough case int32(2): fallthrough case int32(5): nx = int32(4) **(**int32)(__ccgo_up(bp)) = **(**int32)(__ccgo_up(aOp + uintptr(pc+int32(2))*4)) - int32(1) **(**int32)(__ccgo_up(aOp + uintptr(pc+int32(2))*4)) += **(**int32)(__ccgo_up(aOp + uintptr(pc+int32(3))*4)) case int32(3): fallthrough case int32(4): fallthrough default: nx = int32(2) Xsqlite3_randomness(tls, int32(4), bp) break } v4 = aOp + uintptr(pc+int32(1))*4 *(*int32)(unsafe.Pointer(v4)) = *(*int32)(unsafe.Pointer(v4)) - 1 v1 = *(*int32)(unsafe.Pointer(v4)) if v1 > 0 { nx = 0 } pc = pc + nx **(**int32)(__ccgo_up(bp)) = **(**int32)(__ccgo_up(bp)) & int32(0x7fffffff) % sz if op&int32(1) != 0 { if pV != 0 { v4 = pV + uintptr((**(**int32)(__ccgo_up(bp))+int32(1))>>int32(3)) *(*uint8)(unsafe.Pointer(v4)) = uint8(int32(*(*uint8)(unsafe.Pointer(v4))) | libc.Int32FromInt32(1)<<((**(**int32)(__ccgo_up(bp))+libc.Int32FromInt32(1))&libc.Int32FromInt32(7))) } if op != int32(5) { if _sqlite3BitvecSet(tls, pBitvec, libc.Uint32FromInt32(**(**int32)(__ccgo_up(bp))+int32(1))) != 0 { goto bitvec_end } } } else { if pV != 0 { v4 = pV + uintptr((**(**int32)(__ccgo_up(bp))+int32(1))>>int32(3)) *(*uint8)(unsafe.Pointer(v4)) = uint8(int32(*(*uint8)(unsafe.Pointer(v4))) & ^libc.Int32FromUint8(libc.Uint8FromInt32(libc.Int32FromInt32(1)<<((**(**int32)(__ccgo_up(bp))+libc.Int32FromInt32(1))&libc.Int32FromInt32(7))))) } _sqlite3BitvecClear(tls, pBitvec, libc.Uint32FromInt32(**(**int32)(__ccgo_up(bp))+int32(1)), pTmpSpace) } } /* Test to make sure the linear array exactly matches the ** Bitvec object. Start with the assumption that they do ** match (rc==0). Change rc to non-zero if a discrepancy ** is found. */ if pV != 0 { rc = libc.Int32FromUint32(libc.Uint32FromInt32(_sqlite3BitvecTest(tls, uintptr(0), uint32(0))+_sqlite3BitvecTest(tls, pBitvec, libc.Uint32FromInt32(sz+int32(1)))+_sqlite3BitvecTest(tls, pBitvec, uint32(0))) + (_sqlite3BitvecSize(tls, pBitvec) - libc.Uint32FromInt32(sz))) **(**int32)(__ccgo_up(bp)) = int32(1) for { if !(**(**int32)(__ccgo_up(bp)) <= sz) { break } if libc.BoolInt32(libc.Int32FromUint8(**(**uint8)(__ccgo_up(pV + uintptr(**(**int32)(__ccgo_up(bp))>>int32(3)))))&(int32(1)<<(**(**int32)(__ccgo_up(bp))&int32(7))) != 0) != _sqlite3BitvecTest(tls, pBitvec, libc.Uint32FromInt32(**(**int32)(__ccgo_up(bp)))) { rc = **(**int32)(__ccgo_up(bp)) break } goto _7 _7: ; **(**int32)(__ccgo_up(bp)) = **(**int32)(__ccgo_up(bp)) + 1 } } else { rc = 0 } /* Free allocated structure */ goto bitvec_end bitvec_end: ; Xsqlite3_free(tls, pTmpSpace) Xsqlite3_free(tls, pV) _sqlite3BitvecDestroy(tls, pBitvec) return rc } /********************************** Test and Debug Logic **********************/ /* ** Debug tracing macros. Enable by by changing the "0" to "1" and ** recompiling. ** ** When sqlite3PcacheTrace is 1, single line trace messages are issued. ** When sqlite3PcacheTrace is 2, a dump of the pcache showing all cache entries ** is displayed for many operations, resulting in a lot of output. */ /* ** Return 1 if pPg is on the dirty list for pCache. Return 0 if not. ** This routine runs inside of assert() statements only. */ /* ** Check invariants on a PgHdr entry. Return true if everything is OK. ** Return false if any invariant is violated. ** ** This routine is for use inside of assert() statements only. For ** example: ** ** assert( sqlite3PcachePageSanity(pPg) ); */ /********************************** Linked List Management ********************/ /* Allowed values for second argument to pcacheManageDirtyList() */ func _sqlite3BtreeBeginTrans(tls *libc.TLS, p uintptr, wrflag int32, pSchemaVersion uintptr) (r int32) { var pBt uintptr _ = pBt if (*TBtree)(unsafe.Pointer(p)).Fsharable != 0 || libc.Int32FromUint8((*TBtree)(unsafe.Pointer(p)).FinTrans) == TRANS_NONE || libc.Int32FromUint8((*TBtree)(unsafe.Pointer(p)).FinTrans) == int32(TRANS_READ) && wrflag != 0 { return _btreeBeginTrans(tls, p, wrflag, pSchemaVersion) } pBt = (*TBtree)(unsafe.Pointer(p)).FpBt if pSchemaVersion != 0 { **(**int32)(__ccgo_up(pSchemaVersion)) = libc.Int32FromUint32(_sqlite3Get4byte(tls, (*TMemPage)(unsafe.Pointer((*TBtShared)(unsafe.Pointer(pBt)).FpPage1)).FaData+40)) } if wrflag != 0 { /* This call makes sure that the pager has the correct number of ** open savepoints. If the second parameter is greater than 0 and ** the sub-journal is not already open, then it will be opened here. */ return _sqlite3PagerOpenSavepoint(tls, (*TBtShared)(unsafe.Pointer(pBt)).FpPager, (*Tsqlite3)(unsafe.Pointer((*TBtree)(unsafe.Pointer(p)).Fdb)).FnSavepoint) } else { return SQLITE_OK } return r } // C documentation // // /* // ** Run a checkpoint on the Btree passed as the first argument. // ** // ** Return SQLITE_LOCKED if this or any other connection has an open // ** transaction on the shared-cache the argument Btree is connected to. // ** // ** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART. // */ func _sqlite3BtreeCheckpoint(tls *libc.TLS, p uintptr, eMode int32, pnLog uintptr, pnCkpt uintptr) (r int32) { var pBt uintptr var rc int32 _, _ = pBt, rc rc = SQLITE_OK if p != 0 { pBt = (*TBtree)(unsafe.Pointer(p)).FpBt _sqlite3BtreeEnter(tls, p) if libc.Int32FromUint8((*TBtShared)(unsafe.Pointer(pBt)).FinTransaction) != TRANS_NONE { rc = int32(SQLITE_LOCKED) } else { rc = _sqlite3PagerCheckpoint(tls, (*TBtShared)(unsafe.Pointer(pBt)).FpPager, (*TBtree)(unsafe.Pointer(p)).Fdb, eMode, pnLog, pnCkpt) } _sqlite3BtreeLeave(tls, p) } return rc } // C documentation // // /* // ** If no transaction is active and the database is not a temp-db, clear // ** the in-memory pager cache. // */ func _sqlite3BtreeClearCache(tls *libc.TLS, p uintptr) { var pBt uintptr _ = pBt pBt = (*TBtree)(unsafe.Pointer(p)).FpBt if libc.Int32FromUint8((*TBtShared)(unsafe.Pointer(pBt)).FinTransaction) == TRANS_NONE { _sqlite3PagerClearCache(tls, (*TBtShared)(unsafe.Pointer(pBt)).FpPager) } } // C documentation // // /* // ** Delete all information from a single table in the database. iTable is // ** the page number of the root of the table. After this routine returns, // ** the root page is empty, but still exists. // ** // ** This routine will fail with SQLITE_LOCKED if there are any open // ** read cursors on the table. Open write cursors are moved to the // ** root of the table. // ** // ** If pnChange is not NULL, then the integer value pointed to by pnChange // ** is incremented by the number of entries in the table. // */ func _sqlite3BtreeClearTable(tls *libc.TLS, p uintptr, iTable int32, pnChange uintptr) (r int32) { var pBt uintptr var rc int32 _, _ = pBt, rc pBt = (*TBtree)(unsafe.Pointer(p)).FpBt _sqlite3BtreeEnter(tls, p) rc = _saveAllCursors(tls, pBt, libc.Uint32FromInt32(iTable), uintptr(0)) if SQLITE_OK == rc { /* Invalidate all incrblob cursors open on table iTable (assuming iTable ** is the root of a table b-tree - if it is not, the following call is ** a no-op). */ if (*TBtree)(unsafe.Pointer(p)).FhasIncrblobCur != 0 { _invalidateIncrblobCursors(tls, p, libc.Uint32FromInt32(iTable), 0, int32(1)) } rc = _clearDatabasePage(tls, pBt, libc.Uint32FromInt32(iTable), 0, pnChange) } _sqlite3BtreeLeave(tls, p) return rc } // C documentation // // /* // ** Delete all information from the single table that pCur is open on. // ** // ** This routine only work for pCur on an ephemeral table. // */ func _sqlite3BtreeClearTableOfCursor(tls *libc.TLS, pCur uintptr) (r int32) { return _sqlite3BtreeClearTable(tls, (*TBtCursor)(unsafe.Pointer(pCur)).FpBtree, libc.Int32FromUint32((*TBtCursor)(unsafe.Pointer(pCur)).FpgnoRoot), uintptr(0)) } // C documentation // // /* // ** Close a cursor. The read lock on the database file is released // ** when the last cursor is closed. // */ func _sqlite3BtreeCloseCursor(tls *libc.TLS, pCur uintptr) (r int32) { var pBt, pBtree, pPrev uintptr _, _, _ = pBt, pBtree, pPrev pBtree = (*TBtCursor)(unsafe.Pointer(pCur)).FpBtree if pBtree != 0 { pBt = (*TBtCursor)(unsafe.Pointer(pCur)).FpBt _sqlite3BtreeEnter(tls, pBtree) if (*TBtShared)(unsafe.Pointer(pBt)).FpCursor == pCur { (*TBtShared)(unsafe.Pointer(pBt)).FpCursor = (*TBtCursor)(unsafe.Pointer(pCur)).FpNext } else { pPrev = (*TBtShared)(unsafe.Pointer(pBt)).FpCursor for cond := true; cond; cond = pPrev != 0 { if (*TBtCursor)(unsafe.Pointer(pPrev)).FpNext == pCur { (*TBtCursor)(unsafe.Pointer(pPrev)).FpNext = (*TBtCursor)(unsafe.Pointer(pCur)).FpNext break } pPrev = (*TBtCursor)(unsafe.Pointer(pPrev)).FpNext } } _btreeReleaseAllCursorPages(tls, pCur) _unlockBtreeIfUnused(tls, pBt) Xsqlite3_free(tls, (*TBtCursor)(unsafe.Pointer(pCur)).FaOverflow) Xsqlite3_free(tls, (*TBtCursor)(unsafe.Pointer(pCur)).FpKey) if libc.Int32FromUint8((*TBtShared)(unsafe.Pointer(pBt)).FopenFlags)&int32(BTREE_SINGLE) != 0 && (*TBtShared)(unsafe.Pointer(pBt)).FpCursor == uintptr(0) { /* Since the BtShared is not sharable, there is no need to ** worry about the missing sqlite3BtreeLeave() call here. */ _sqlite3BtreeClose(tls, pBtree) } else { _sqlite3BtreeLeave(tls, pBtree) } (*TBtCursor)(unsafe.Pointer(pCur)).FpBtree = uintptr(0) } return SQLITE_OK } // C documentation // // /* // ** This routine does the first phase of a two-phase commit. This routine // ** causes a rollback journal to be created (if it does not already exist) // ** and populated with enough information so that if a power loss occurs // ** the database can be restored to its original state by playing back // ** the journal. Then the contents of the journal are flushed out to // ** the disk. After the journal is safely on oxide, the changes to the // ** database are written into the database file and flushed to oxide. // ** At the end of this call, the rollback journal still exists on the // ** disk and we are still holding all locks, so the transaction has not // ** committed. See sqlite3BtreeCommitPhaseTwo() for the second phase of the // ** commit process. // ** // ** This call is a no-op if no write-transaction is currently active on pBt. // ** // ** Otherwise, sync the database file for the btree pBt. zSuperJrnl points to // ** the name of a super-journal file that should be written into the // ** individual journal file, or is NULL, indicating no super-journal file // ** (single database transaction). // ** // ** When this is called, the super-journal should already have been // ** created, populated with this journal pointer and synced to disk. // ** // ** Once this is routine has returned, the only thing required to commit // ** the write-transaction for this database file is to delete the journal. // */ func _sqlite3BtreeCommitPhaseOne(tls *libc.TLS, p uintptr, zSuperJrnl uintptr) (r int32) { var pBt uintptr var rc int32 _, _ = pBt, rc rc = SQLITE_OK if libc.Int32FromUint8((*TBtree)(unsafe.Pointer(p)).FinTrans) == int32(TRANS_WRITE) { pBt = (*TBtree)(unsafe.Pointer(p)).FpBt _sqlite3BtreeEnter(tls, p) if (*TBtShared)(unsafe.Pointer(pBt)).FautoVacuum != 0 { rc = _autoVacuumCommit(tls, p) if rc != SQLITE_OK { _sqlite3BtreeLeave(tls, p) return rc } } if (*TBtShared)(unsafe.Pointer(pBt)).FbDoTruncate != 0 { _sqlite3PagerTruncateImage(tls, (*TBtShared)(unsafe.Pointer(pBt)).FpPager, (*TBtShared)(unsafe.Pointer(pBt)).FnPage) } rc = _sqlite3PagerCommitPhaseOne(tls, (*TBtShared)(unsafe.Pointer(pBt)).FpPager, zSuperJrnl, 0) _sqlite3BtreeLeave(tls, p) } return rc } // C documentation // // /* // ** Commit the transaction currently in progress. // ** // ** This routine implements the second phase of a 2-phase commit. The // ** sqlite3BtreeCommitPhaseOne() routine does the first phase and should // ** be invoked prior to calling this routine. The sqlite3BtreeCommitPhaseOne() // ** routine did all the work of writing information out to disk and flushing the // ** contents so that they are written onto the disk platter. All this // ** routine has to do is delete or truncate or zero the header in the // ** the rollback journal (which causes the transaction to commit) and // ** drop locks. // ** // ** Normally, if an error occurs while the pager layer is attempting to // ** finalize the underlying journal file, this function returns an error and // ** the upper layer will attempt a rollback. However, if the second argument // ** is non-zero then this b-tree transaction is part of a multi-file // ** transaction. In this case, the transaction has already been committed // ** (by deleting a super-journal file) and the caller will ignore this // ** functions return code. So, even if an error occurs in the pager layer, // ** reset the b-tree objects internal state to indicate that the write // ** transaction has been closed. This is quite safe, as the pager will have // ** transitioned to the error state. // ** // ** This will release the write lock on the database file. If there // ** are no active cursors, it also releases the read lock. // */ func _sqlite3BtreeCommitPhaseTwo(tls *libc.TLS, p uintptr, bCleanup int32) (r int32) { var pBt uintptr var rc int32 _, _ = pBt, rc if libc.Int32FromUint8((*TBtree)(unsafe.Pointer(p)).FinTrans) == TRANS_NONE { return SQLITE_OK } _sqlite3BtreeEnter(tls, p) /* If the handle has a write-transaction open, commit the shared-btrees ** transaction and set the shared state to TRANS_READ. */ if libc.Int32FromUint8((*TBtree)(unsafe.Pointer(p)).FinTrans) == int32(TRANS_WRITE) { pBt = (*TBtree)(unsafe.Pointer(p)).FpBt rc = _sqlite3PagerCommitPhaseTwo(tls, (*TBtShared)(unsafe.Pointer(pBt)).FpPager) if rc != SQLITE_OK && bCleanup == 0 { _sqlite3BtreeLeave(tls, p) return rc } (*TBtree)(unsafe.Pointer(p)).FiBDataVersion = (*TBtree)(unsafe.Pointer(p)).FiBDataVersion - 1 /* Compensate for pPager->iDataVersion++; */ (*TBtShared)(unsafe.Pointer(pBt)).FinTransaction = uint8(TRANS_READ) _btreeClearHasContent(tls, pBt) } _btreeEndTransaction(tls, p) _sqlite3BtreeLeave(tls, p) return SQLITE_OK } // C documentation // // /* // ** Determine whether or not a cursor has moved from the position where // ** it was last placed, or has been invalidated for any other reason. // ** Cursors can move when the row they are pointing at is deleted out // ** from under them, for example. Cursor might also move if a btree // ** is rebalanced. // ** // ** Calling this routine with a NULL cursor pointer returns false. // ** // ** Use the separate sqlite3BtreeCursorRestore() routine to restore a cursor // ** back to where it ought to be if this routine returns true. // */ func _sqlite3BtreeCursorHasMoved(tls *libc.TLS, pCur uintptr) (r int32) { return libc.BoolInt32(CURSOR_VALID != libc.Int32FromUint8(**(**Tu8)(__ccgo_up(pCur)))) } func _sqlite3BtreeCursorIsValidNN(tls *libc.TLS, pCur uintptr) (r int32) { return libc.BoolInt32(libc.Int32FromUint8((*TBtCursor)(unsafe.Pointer(pCur)).FeState) == CURSOR_VALID) } // C documentation // // /* // ** This routine restores a cursor back to its original position after it // ** has been moved by some outside activity (such as a btree rebalance or // ** a row having been deleted out from under the cursor). // ** // ** On success, the *pDifferentRow parameter is false if the cursor is left // ** pointing at exactly the same row. *pDifferntRow is the row the cursor // ** was pointing to has been deleted, forcing the cursor to point to some // ** nearby row. // ** // ** This routine should only be called for a cursor that just returned // ** TRUE from sqlite3BtreeCursorHasMoved(). // */ func _sqlite3BtreeCursorRestore(tls *libc.TLS, pCur uintptr, pDifferentRow uintptr) (r int32) { var rc, v1 int32 _, _ = rc, v1 if libc.Int32FromUint8((*TBtCursor)(unsafe.Pointer(pCur)).FeState) >= int32(CURSOR_REQUIRESEEK) { v1 = _btreeRestoreCursorPosition(tls, pCur) } else { v1 = SQLITE_OK } rc = v1 if rc != 0 { **(**int32)(__ccgo_up(pDifferentRow)) = int32(1) return rc } if libc.Int32FromUint8((*TBtCursor)(unsafe.Pointer(pCur)).FeState) != CURSOR_VALID { **(**int32)(__ccgo_up(pDifferentRow)) = int32(1) } else { **(**int32)(__ccgo_up(pDifferentRow)) = 0 } return SQLITE_OK } func _sqlite3BtreeDropTable(tls *libc.TLS, p uintptr, iTable int32, piMoved uintptr) (r int32) { var rc int32 _ = rc _sqlite3BtreeEnter(tls, p) rc = _btreeDropTable(tls, p, libc.Uint32FromInt32(iTable), piMoved) _sqlite3BtreeLeave(tls, p) return rc } func _sqlite3BtreeEnterAll(tls *libc.TLS, db uintptr) { if libc.Int32FromUint8((*Tsqlite3)(unsafe.Pointer(db)).FnoSharedCache) == 0 { _btreeEnterAll(tls, db) } } // C documentation // // /* // ** Return TRUE if the cursor is not pointing at an entry of the table. // ** // ** TRUE will be returned after a call to sqlite3BtreeNext() moves // ** past the last entry in the table or sqlite3BtreePrev() moves past // ** the first entry. TRUE is also returned if the table is empty. // */ func _sqlite3BtreeEof(tls *libc.TLS, pCur uintptr) (r int32) { /* TODO: What if the cursor is in CURSOR_REQUIRESEEK but all table entries ** have been deleted? This API will need to change to return an error code ** as well as the boolean result value. */ return libc.BoolInt32(CURSOR_VALID != libc.Int32FromUint8((*TBtCursor)(unsafe.Pointer(pCur)).FeState)) } // C documentation // // /* // ** Return the currently defined page size // */ func _sqlite3BtreeGetPageSize(tls *libc.TLS, p uintptr) (r int32) { return libc.Int32FromUint32((*TBtShared)(unsafe.Pointer((*TBtree)(unsafe.Pointer(p)).FpBt)).FpageSize) } // C documentation // // /* // ** Return the number of bytes of space at the end of every page that // ** are intentionally left unused. This is the "reserved" space that is // ** sometimes used by extensions. // ** // ** The value returned is the larger of the current reserve size and // ** the latest reserve size requested by SQLITE_FILECTRL_RESERVE_BYTES. // ** The amount of reserve can only grow - never shrink. // */ func _sqlite3BtreeGetRequestedReserve(tls *libc.TLS, p uintptr) (r int32) { var n1, n2, v1 int32 _, _, _ = n1, n2, v1 _sqlite3BtreeEnter(tls, p) n1 = libc.Int32FromUint8((*TBtShared)(unsafe.Pointer((*TBtree)(unsafe.Pointer(p)).FpBt)).FnReserveWanted) n2 = _sqlite3BtreeGetReserveNoMutex(tls, p) _sqlite3BtreeLeave(tls, p) if n1 > n2 { v1 = n1 } else { v1 = n2 } return v1 } // C documentation // // /* // ** This function is similar to sqlite3BtreeGetReserve(), except that it // ** may only be called if it is guaranteed that the b-tree mutex is already // ** held. // ** // ** This is useful in one special case in the backup API code where it is // ** known that the shared b-tree mutex is held, but the mutex on the // ** database handle that owns *p is not. In this case if sqlite3BtreeEnter() // ** were to be called, it might collide with some other operation on the // ** database handle that owns *p, causing undefined behavior. // */ func _sqlite3BtreeGetReserveNoMutex(tls *libc.TLS, p uintptr) (r int32) { var n int32 _ = n n = libc.Int32FromUint32((*TBtShared)(unsafe.Pointer((*TBtree)(unsafe.Pointer(p)).FpBt)).FpageSize - (*TBtShared)(unsafe.Pointer((*TBtree)(unsafe.Pointer(p)).FpBt)).FusableSize) return n } // C documentation // // /* Set *pRes to 1 (true) if the BTree pointed to by cursor pCur contains zero // ** rows of content. Set *pRes to 0 (false) if the table contains content. // ** Return SQLITE_OK on success or some error code (ex: SQLITE_NOMEM) if // ** something goes wrong. // */ func _sqlite3BtreeIsEmpty(tls *libc.TLS, pCur uintptr, pRes uintptr) (r int32) { var rc int32 _ = rc if libc.Int32FromUint8((*TBtCursor)(unsafe.Pointer(pCur)).FeState) == CURSOR_VALID { **(**int32)(__ccgo_up(pRes)) = 0 return SQLITE_OK } rc = _moveToRoot(tls, pCur) if rc == int32(SQLITE_EMPTY) { **(**int32)(__ccgo_up(pRes)) = int32(1) rc = SQLITE_OK } else { **(**int32)(__ccgo_up(pRes)) = 0 } return rc } // C documentation // // /* // ** Return true if the given Btree is read-only. // */ func _sqlite3BtreeIsReadonly(tls *libc.TLS, p uintptr) (r int32) { return libc.BoolInt32(libc.Int32FromUint16((*TBtShared)(unsafe.Pointer((*TBtree)(unsafe.Pointer(p)).FpBt)).FbtsFlags)&int32(BTS_READ_ONLY) != 0) } func _sqlite3BtreeLast(tls *libc.TLS, pCur uintptr, pRes uintptr) (r int32) { /* If the cursor already points to the last entry, this is a no-op. */ if CURSOR_VALID == libc.Int32FromUint8((*TBtCursor)(unsafe.Pointer(pCur)).FeState) && libc.Int32FromUint8((*TBtCursor)(unsafe.Pointer(pCur)).FcurFlags)&int32(BTCF_AtLast) != 0 { **(**int32)(__ccgo_up(pRes)) = 0 return SQLITE_OK } return _btreeLast(tls, pCur, pRes) } func _sqlite3BtreeLeaveAll(tls *libc.TLS, db uintptr) { if libc.Int32FromUint8((*Tsqlite3)(unsafe.Pointer(db)).FnoSharedCache) == 0 { _btreeLeaveAll(tls, db) } } // C documentation // // /* // ** Obtain a lock on the table whose root page is iTab. The // ** lock is a write lock if isWritelock is true or a read lock // ** if it is false. // */ func _sqlite3BtreeLockTable(tls *libc.TLS, p uintptr, iTab int32, isWriteLock Tu8) (r int32) { var lockType Tu8 var rc int32 _, _ = lockType, rc rc = SQLITE_OK if (*TBtree)(unsafe.Pointer(p)).Fsharable != 0 { lockType = libc.Uint8FromInt32(int32(READ_LOCK) + libc.Int32FromUint8(isWriteLock)) _sqlite3BtreeEnter(tls, p) rc = _querySharedCacheTableLock(tls, p, libc.Uint32FromInt32(iTab), lockType) if rc == SQLITE_OK { rc = _setSharedCacheTableLock(tls, p, libc.Uint32FromInt32(iTab), lockType) } _sqlite3BtreeLeave(tls, p) } return rc } // C documentation // // /* // ** Return an upper bound on the size of any record for the table // ** that the cursor is pointing into. // ** // ** This is an optimization. Everything will still work if this // ** routine always returns 2147483647 (which is the largest record // ** that SQLite can handle) or more. But returning a smaller value might // ** prevent large memory allocations when trying to interpret a // ** corrupt database. // ** // ** The current implementation merely returns the size of the underlying // ** database file. // */ func _sqlite3BtreeMaxRecordSize(tls *libc.TLS, pCur uintptr) (r Tsqlite3_int64) { return libc.Int64FromUint32((*TBtShared)(unsafe.Pointer((*TBtCursor)(unsafe.Pointer(pCur)).FpBt)).FpageSize) * libc.Int64FromUint32((*TBtShared)(unsafe.Pointer((*TBtCursor)(unsafe.Pointer(pCur)).FpBt)).FnPage) } func _sqlite3BtreePayloadChecked(tls *libc.TLS, pCur uintptr, offset Tu32, amt Tu32, pBuf uintptr) (r int32) { if libc.Int32FromUint8((*TBtCursor)(unsafe.Pointer(pCur)).FeState) == CURSOR_VALID { return _accessPayload(tls, pCur, offset, amt, pBuf, 0) } else { return _accessPayloadChecked(tls, pCur, offset, amt, pBuf) } return r } func _sqlite3BtreePrevious(tls *libc.TLS, pCur uintptr, flags int32) (r int32) { var v1 uintptr _ = v1 _ = flags /* Used in COMDB2 but not native SQLite */ v1 = pCur + 1 *(*Tu8)(unsafe.Pointer(v1)) = Tu8(int32(*(*Tu8)(unsafe.Pointer(v1))) & ^(libc.Int32FromInt32(BTCF_AtLast) | libc.Int32FromInt32(BTCF_ValidOvfl) | libc.Int32FromInt32(BTCF_ValidNKey))) (*TBtCursor)(unsafe.Pointer(pCur)).Finfo.FnSize = uint16(0) if libc.Int32FromUint8((*TBtCursor)(unsafe.Pointer(pCur)).FeState) != CURSOR_VALID || libc.Int32FromUint16((*TBtCursor)(unsafe.Pointer(pCur)).Fix) == 0 || libc.Int32FromUint8((*TMemPage)(unsafe.Pointer((*TBtCursor)(unsafe.Pointer(pCur)).FpPage)).Fleaf) == 0 { return _btreePrevious(tls, pCur) } (*TBtCursor)(unsafe.Pointer(pCur)).Fix = (*TBtCursor)(unsafe.Pointer(pCur)).Fix - 1 return SQLITE_OK } // C documentation // // /* // ** Argument pCsr must be a cursor opened for writing on an // ** INTKEY table currently pointing at a valid table entry. // ** This function modifies the data stored as part of that entry. // ** // ** Only the data content may only be modified, it is not possible to // ** change the length of the data stored. If this function is called with // ** parameters that attempt to write past the end of the existing data, // ** no modifications are made and SQLITE_CORRUPT is returned. // */ func _sqlite3BtreePutData(tls *libc.TLS, pCsr uintptr, offset Tu32, amt Tu32, z uintptr) (r int32) { var rc, v1 int32 _, _ = rc, v1 if libc.Int32FromUint8((*TBtCursor)(unsafe.Pointer(pCsr)).FeState) >= int32(CURSOR_REQUIRESEEK) { v1 = _btreeRestoreCursorPosition(tls, pCsr) } else { v1 = SQLITE_OK } rc = v1 if rc != SQLITE_OK { return rc } if libc.Int32FromUint8((*TBtCursor)(unsafe.Pointer(pCsr)).FeState) != CURSOR_VALID { return int32(SQLITE_ABORT) } /* Save the positions of all other cursors open on this table. This is ** required in case any of them are holding references to an xFetch ** version of the b-tree page modified by the accessPayload call below. ** ** Note that pCsr must be open on a INTKEY table and saveCursorPosition() ** and hence saveAllCursors() cannot fail on a BTREE_INTKEY table, hence ** saveAllCursors can only return SQLITE_OK. */ _saveAllCursors(tls, (*TBtCursor)(unsafe.Pointer(pCsr)).FpBt, (*TBtCursor)(unsafe.Pointer(pCsr)).FpgnoRoot, pCsr) /* Check some assumptions: ** (a) the cursor is open for writing, ** (b) there is a read/write transaction open, ** (c) the connection holds a write-lock on the table (if required), ** (d) there are no conflicting read-locks, and ** (e) the cursor points at a valid row of an intKey table. */ if libc.Int32FromUint8((*TBtCursor)(unsafe.Pointer(pCsr)).FcurFlags)&int32(BTCF_WriteFlag) == 0 { return int32(SQLITE_READONLY) } return _accessPayload(tls, pCsr, offset, amt, z, int32(1)) } // C documentation // // /* // ** Rollback the transaction in progress. // ** // ** If tripCode is not SQLITE_OK then cursors will be invalidated (tripped). // ** Only write cursors are tripped if writeOnly is true but all cursors are // ** tripped if writeOnly is false. Any attempt to use // ** a tripped cursor will result in an error. // ** // ** This will release the write lock on the database file. If there // ** are no active cursors, it also releases the read lock. // */ func _sqlite3BtreeRollback(tls *libc.TLS, p uintptr, tripCode int32, writeOnly int32) (r int32) { bp := tls.Alloc(16) defer tls.Free(16) var pBt uintptr var rc, rc2, rc21, v1 int32 var _ /* pPage1 at bp+0 */ uintptr _, _, _, _, _ = pBt, rc, rc2, rc21, v1 pBt = (*TBtree)(unsafe.Pointer(p)).FpBt _sqlite3BtreeEnter(tls, p) if tripCode == SQLITE_OK { v1 = _saveAllCursors(tls, pBt, uint32(0), uintptr(0)) tripCode = v1 rc = v1 if rc != 0 { writeOnly = 0 } } else { rc = SQLITE_OK } if tripCode != 0 { rc2 = _sqlite3BtreeTripAllCursors(tls, p, tripCode, writeOnly) if rc2 != SQLITE_OK { rc = rc2 } } if libc.Int32FromUint8((*TBtree)(unsafe.Pointer(p)).FinTrans) == int32(TRANS_WRITE) { rc21 = _sqlite3PagerRollback(tls, (*TBtShared)(unsafe.Pointer(pBt)).FpPager) if rc21 != SQLITE_OK { rc = rc21 } /* The rollback may have destroyed the pPage1->aData value. So ** call btreeGetPage() on page 1 again to make ** sure pPage1->aData is set correctly. */ if _btreeGetPage(tls, pBt, uint32(1), bp, 0) == SQLITE_OK { _btreeSetNPage(tls, pBt, **(**uintptr)(__ccgo_up(bp))) _releasePageOne(tls, **(**uintptr)(__ccgo_up(bp))) } (*TBtShared)(unsafe.Pointer(pBt)).FinTransaction = uint8(TRANS_READ) _btreeClearHasContent(tls, pBt) } _btreeEndTransaction(tls, p) _sqlite3BtreeLeave(tls, p) return rc } // C documentation // // /* // ** The second argument to this function, op, is always SAVEPOINT_ROLLBACK // ** or SAVEPOINT_RELEASE. This function either releases or rolls back the // ** savepoint identified by parameter iSavepoint, depending on the value // ** of op. // ** // ** Normally, iSavepoint is greater than or equal to zero. However, if op is // ** SAVEPOINT_ROLLBACK, then iSavepoint may also be -1. In this case the // ** contents of the entire transaction are rolled back. This is different // ** from a normal transaction rollback, as no locks are released and the // ** transaction remains open. // */ func _sqlite3BtreeSavepoint(tls *libc.TLS, p uintptr, op int32, iSavepoint int32) (r int32) { var pBt uintptr var rc int32 _, _ = pBt, rc rc = SQLITE_OK if p != 0 && libc.Int32FromUint8((*TBtree)(unsafe.Pointer(p)).FinTrans) == int32(TRANS_WRITE) { pBt = (*TBtree)(unsafe.Pointer(p)).FpBt _sqlite3BtreeEnter(tls, p) if op == int32(SAVEPOINT_ROLLBACK) { rc = _saveAllCursors(tls, pBt, uint32(0), uintptr(0)) } if rc == SQLITE_OK { rc = _sqlite3PagerSavepoint(tls, (*TBtShared)(unsafe.Pointer(pBt)).FpPager, op, iSavepoint) } if rc == SQLITE_OK { if iSavepoint < 0 && libc.Int32FromUint16((*TBtShared)(unsafe.Pointer(pBt)).FbtsFlags)&int32(BTS_INITIALLY_EMPTY) != 0 { (*TBtShared)(unsafe.Pointer(pBt)).FnPage = uint32(0) } rc = _newDatabase(tls, pBt) _btreeSetNPage(tls, pBt, (*TBtShared)(unsafe.Pointer(pBt)).FpPage1) /* pBt->nPage might be zero if the database was corrupt when ** the transaction was started. Otherwise, it must be at least 1. */ } _sqlite3BtreeLeave(tls, p) } return rc } // C documentation // // /* // ** This function returns a pointer to a blob of memory associated with // ** a single shared-btree. The memory is used by client code for its own // ** purposes (for example, to store a high-level schema associated with // ** the shared-btree). The btree layer manages reference counting issues. // ** // ** The first time this is called on a shared-btree, nBytes bytes of memory // ** are allocated, zeroed, and returned to the caller. For each subsequent // ** call the nBytes parameter is ignored and a pointer to the same blob // ** of memory returned. // ** // ** If the nBytes parameter is 0 and the blob of memory has not yet been // ** allocated, a null pointer is returned. If the blob has already been // ** allocated, it is returned as normal. // ** // ** Just before the shared-btree is closed, the function passed as the // ** xFree argument when the memory allocation was made is invoked on the // ** blob of allocated memory. The xFree function should not call sqlite3_free() // ** on the memory, the btree layer does that. // */ func _sqlite3BtreeSchema(tls *libc.TLS, p uintptr, nBytes int32, __ccgo_fp_xFree uintptr) (r uintptr) { var pBt uintptr _ = pBt pBt = (*TBtree)(unsafe.Pointer(p)).FpBt _sqlite3BtreeEnter(tls, p) if !((*TBtShared)(unsafe.Pointer(pBt)).FpSchema != 0) && nBytes != 0 { (*TBtShared)(unsafe.Pointer(pBt)).FpSchema = _sqlite3DbMallocZero(tls, uintptr(0), libc.Uint64FromInt32(nBytes)) (*TBtShared)(unsafe.Pointer(pBt)).FxFreeSchema = __ccgo_fp_xFree } _sqlite3BtreeLeave(tls, p) return (*TBtShared)(unsafe.Pointer(pBt)).FpSchema } // C documentation // // /* // ** Change the 'auto-vacuum' property of the database. If the 'autoVacuum' // ** parameter is non-zero, then auto-vacuum mode is enabled. If zero, it // ** is disabled. The default value for the auto-vacuum property is // ** determined by the SQLITE_DEFAULT_AUTOVACUUM macro. // */ func _sqlite3BtreeSetAutoVacuum(tls *libc.TLS, p uintptr, autoVacuum int32) (r int32) { var av Tu8 var pBt uintptr var rc, v1 int32 var v2 bool _, _, _, _, _ = av, pBt, rc, v1, v2 pBt = (*TBtree)(unsafe.Pointer(p)).FpBt rc = SQLITE_OK av = libc.Uint8FromInt32(autoVacuum) _sqlite3BtreeEnter(tls, p) if v2 = libc.Int32FromUint16((*TBtShared)(unsafe.Pointer(pBt)).FbtsFlags)&int32(BTS_PAGESIZE_FIXED) != 0; v2 { if av != 0 { v1 = int32(1) } else { v1 = 0 } } if v2 && v1 != libc.Int32FromUint8((*TBtShared)(unsafe.Pointer(pBt)).FautoVacuum) { rc = int32(SQLITE_READONLY) } else { if av != 0 { v1 = int32(1) } else { v1 = 0 } (*TBtShared)(unsafe.Pointer(pBt)).FautoVacuum = libc.Uint8FromInt32(v1) if libc.Int32FromUint8(av) == int32(2) { v1 = int32(1) } else { v1 = 0 } (*TBtShared)(unsafe.Pointer(pBt)).FincrVacuum = libc.Uint8FromInt32(v1) } _sqlite3BtreeLeave(tls, p) return rc } // C documentation // // /* // ** Return true if the Btree passed as the only argument is sharable. // */ func _sqlite3BtreeSharable(tls *libc.TLS, p uintptr) (r int32) { return libc.Int32FromUint8((*TBtree)(unsafe.Pointer(p)).Fsharable) } // C documentation // // /* // ** This routine sets the state to CURSOR_FAULT and the error // ** code to errCode for every cursor on any BtShared that pBtree // ** references. Or if the writeOnly flag is set to 1, then only // ** trip write cursors and leave read cursors unchanged. // ** // ** Every cursor is a candidate to be tripped, including cursors // ** that belong to other database connections that happen to be // ** sharing the cache with pBtree. // ** // ** This routine gets called when a rollback occurs. If the writeOnly // ** flag is true, then only write-cursors need be tripped - read-only // ** cursors save their current positions so that they may continue // ** following the rollback. Or, if writeOnly is false, all cursors are // ** tripped. In general, writeOnly is false if the transaction being // ** rolled back modified the database schema. In this case b-tree root // ** pages may be moved or deleted from the database altogether, making // ** it unsafe for read cursors to continue. // ** // ** If the writeOnly flag is true and an error is encountered while // ** saving the current position of a read-only cursor, all cursors, // ** including all read-cursors are tripped. // ** // ** SQLITE_OK is returned if successful, or if an error occurs while // ** saving a cursor position, an SQLite error code. // */ func _sqlite3BtreeTripAllCursors(tls *libc.TLS, pBtree uintptr, errCode int32, writeOnly int32) (r int32) { var p uintptr var rc int32 _, _ = p, rc rc = SQLITE_OK if pBtree != 0 { _sqlite3BtreeEnter(tls, pBtree) p = (*TBtShared)(unsafe.Pointer((*TBtree)(unsafe.Pointer(pBtree)).FpBt)).FpCursor for { if !(p != 0) { break } if writeOnly != 0 && libc.Int32FromUint8((*TBtCursor)(unsafe.Pointer(p)).FcurFlags)&int32(BTCF_WriteFlag) == 0 { if libc.Int32FromUint8((*TBtCursor)(unsafe.Pointer(p)).FeState) == CURSOR_VALID || libc.Int32FromUint8((*TBtCursor)(unsafe.Pointer(p)).FeState) == int32(CURSOR_SKIPNEXT) { rc = _saveCursorPosition(tls, p) if rc != SQLITE_OK { _sqlite3BtreeTripAllCursors(tls, pBtree, rc, 0) break } } } else { _sqlite3BtreeClearCursor(tls, p) (*TBtCursor)(unsafe.Pointer(p)).FeState = uint8(CURSOR_FAULT) (*TBtCursor)(unsafe.Pointer(p)).FskipNext = errCode } _btreeReleaseAllCursorPages(tls, p) goto _1 _1: ; p = (*TBtCursor)(unsafe.Pointer(p)).FpNext } _sqlite3BtreeLeave(tls, pBtree) } return rc } // C documentation // // /* // ** Return one of SQLITE_TXN_NONE, SQLITE_TXN_READ, or SQLITE_TXN_WRITE // ** to describe the current transaction state of Btree p. // */ func _sqlite3BtreeTxnState(tls *libc.TLS, p uintptr) (r int32) { var v1 int32 _ = v1 if p != 0 { v1 = libc.Int32FromUint8((*TBtree)(unsafe.Pointer(p)).FinTrans) } else { v1 = 0 } return v1 } // C documentation // // /* // ** This is called to code the required FOR EACH ROW triggers for an operation // ** on table pTab. The operation to code triggers for (INSERT, UPDATE or DELETE) // ** is given by the op parameter. The tr_tm parameter determines whether the // ** BEFORE or AFTER triggers are coded. If the operation is an UPDATE, then // ** parameter pChanges is passed the list of columns being modified. // ** // ** If there are no triggers that fire at the specified time for the specified // ** operation on pTab, this function is a no-op. // ** // ** The reg argument is the address of the first in an array of registers // ** that contain the values substituted for the new.* and old.* references // ** in the trigger program. If N is the number of columns in table pTab // ** (a copy of pTab->nCol), then registers are populated as follows: // ** // ** Register Contains // ** ------------------------------------------------------ // ** reg+0 OLD.rowid // ** reg+1 OLD.* value of left-most column of pTab // ** ... ... // ** reg+N OLD.* value of right-most column of pTab // ** reg+N+1 NEW.rowid // ** reg+N+2 NEW.* value of left-most column of pTab // ** ... ... // ** reg+N+N+1 NEW.* value of right-most column of pTab // ** // ** For ON DELETE triggers, the registers containing the NEW.* values will // ** never be accessed by the trigger program, so they are not allocated or // ** populated by the caller (there is no data to populate them with anyway). // ** Similarly, for ON INSERT triggers the values stored in the OLD.* registers // ** are never accessed, and so are not allocated by the caller. So, for an // ** ON INSERT trigger, the value passed to this function as parameter reg // ** is not a readable register, although registers (reg+N) through // ** (reg+N+N+1) are. // ** // ** Parameter orconf is the default conflict resolution algorithm for the // ** trigger program to use (REPLACE, IGNORE etc.). Parameter ignoreJump // ** is the instruction that control should jump to if a trigger program // ** raises an IGNORE exception. // */ func _sqlite3CodeRowTrigger(tls *libc.TLS, pParse uintptr, pTrigger uintptr, op int32, pChanges uintptr, tr_tm int32, pTab uintptr, reg int32, orconf int32, ignoreJump int32) { var p uintptr _ = p /* Used to iterate through pTrigger list */ p = pTrigger for { if !(p != 0) { break } /* Sanity checking: The schema for the trigger and for the table are ** always defined. The trigger must be in the same schema as the table ** or else it must be a TEMP trigger. */ /* Determine whether we should code this trigger. One of two choices: ** 1. The trigger is an exact match to the current DML statement ** 2. This is a RETURNING trigger for INSERT but we are currently ** doing the UPDATE part of an UPSERT. */ if (libc.Int32FromUint8((*TTrigger)(unsafe.Pointer(p)).Fop) == op || (*TTrigger)(unsafe.Pointer(p)).FbReturning != 0 && libc.Int32FromUint8((*TTrigger)(unsafe.Pointer(p)).Fop) == int32(TK_INSERT) && op == int32(TK_UPDATE)) && libc.Int32FromUint8((*TTrigger)(unsafe.Pointer(p)).Ftr_tm) == tr_tm && _checkColumnOverlap(tls, (*TTrigger)(unsafe.Pointer(p)).FpColumns, pChanges) != 0 { if !((*TTrigger)(unsafe.Pointer(p)).FbReturning != 0) { _sqlite3CodeRowTriggerDirect(tls, pParse, p, pTab, reg, orconf, ignoreJump) } else { if (*TParse)(unsafe.Pointer(pParse)).FpToplevel == uintptr(0) { _codeReturningTrigger(tls, pParse, p, pTab, reg) } } } goto _1 _1: ; p = (*TTrigger)(unsafe.Pointer(p)).FpNext } } // C documentation // // /* // ** Allocate a new expression node from a zero-terminated token that has // ** already been dequoted. // */ func _sqlite3Expr(tls *libc.TLS, db uintptr, op int32, zToken uintptr) (r uintptr) { bp := tls.Alloc(16) defer tls.Free(16) var _ /* x at bp+0 */ TToken (**(**TToken)(__ccgo_up(bp))).Fz = zToken (**(**TToken)(__ccgo_up(bp))).Fn = libc.Uint32FromInt32(_sqlite3Strlen30(tls, zToken)) return _sqlite3ExprAlloc(tls, db, op, bp, 0) } // C documentation // // /* // ** Set the collating sequence for expression pExpr to be the collating // ** sequence named by pToken. Return a pointer to a new Expr node that // ** implements the COLLATE operator. // ** // ** If a memory allocation error occurs, that fact is recorded in pParse->db // ** and the pExpr parameter is returned unchanged. // */ func _sqlite3ExprAddCollateToken(tls *libc.TLS, pParse uintptr, pExpr uintptr, pCollName uintptr, dequote int32) (r uintptr) { var pNew uintptr _ = pNew if (*TToken)(unsafe.Pointer(pCollName)).Fn > uint32(0) { pNew = _sqlite3ExprAlloc(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, int32(TK_COLLATE), pCollName, dequote) if pNew != 0 { (*TExpr)(unsafe.Pointer(pNew)).FpLeft = pExpr **(**Tu32)(__ccgo_up(pNew + 4)) |= libc.Uint32FromInt32(libc.Int32FromInt32(EP_Collate) | libc.Int32FromInt32(EP_Skip)) pExpr = pNew } } return pExpr } // C documentation // // /* // ** Join two expressions using an AND operator. If either expression is // ** NULL, then just return the other expression. // ** // ** If one side or the other of the AND is known to be false, and neither side // ** is part of an ON clause, then instead of returning an AND expression, // ** just return a constant expression with a value of false. // */ func _sqlite3ExprAnd(tls *libc.TLS, pParse uintptr, pLeft uintptr, pRight uintptr) (r uintptr) { var db uintptr var f Tu32 _, _ = db, f db = (*TParse)(unsafe.Pointer(pParse)).Fdb if pLeft == uintptr(0) { return pRight } else { if pRight == uintptr(0) { return pLeft } else { f = (*TExpr)(unsafe.Pointer(pLeft)).Fflags | (*TExpr)(unsafe.Pointer(pRight)).Fflags if f&libc.Uint32FromInt32(libc.Int32FromInt32(EP_OuterON)|libc.Int32FromInt32(EP_InnerON)|libc.Int32FromInt32(EP_IsFalse)|libc.Int32FromInt32(EP_HasFunc)) == uint32(EP_IsFalse) && !(libc.Int32FromUint8((*TParse)(unsafe.Pointer(pParse)).FeParseMode) >= libc.Int32FromInt32(PARSE_MODE_RENAME)) { _sqlite3ExprDeferredDelete(tls, pParse, pLeft) _sqlite3ExprDeferredDelete(tls, pParse, pRight) return _sqlite3ExprInt32(tls, db, 0) } else { return _sqlite3PExpr(tls, pParse, int32(TK_AND), pLeft, pRight) } } } return r } // C documentation // // /* // ** Attach subtrees pLeft and pRight to the Expr node pRoot. // ** // ** If pRoot==NULL that means that a memory allocation error has occurred. // ** In that case, delete the subtrees pLeft and pRight. // */ func _sqlite3ExprAttachSubtrees(tls *libc.TLS, db uintptr, pRoot uintptr, pLeft uintptr, pRight uintptr) { if pRoot == uintptr(0) { _sqlite3ExprDelete(tls, db, pLeft) _sqlite3ExprDelete(tls, db, pRight) } else { if pRight != 0 { (*TExpr)(unsafe.Pointer(pRoot)).FpRight = pRight **(**Tu32)(__ccgo_up(pRoot + 4)) |= libc.Uint32FromInt32(libc.Int32FromInt32(EP_Collate)|libc.Int32FromInt32(EP_Subquery)|libc.Int32FromInt32(EP_HasFunc)) & (*TExpr)(unsafe.Pointer(pRight)).Fflags (*TExpr)(unsafe.Pointer(pRoot)).FnHeight = (*TExpr)(unsafe.Pointer(pRight)).FnHeight + int32(1) } else { (*TExpr)(unsafe.Pointer(pRoot)).FnHeight = int32(1) } if pLeft != 0 { (*TExpr)(unsafe.Pointer(pRoot)).FpLeft = pLeft **(**Tu32)(__ccgo_up(pRoot + 4)) |= libc.Uint32FromInt32(libc.Int32FromInt32(EP_Collate)|libc.Int32FromInt32(EP_Subquery)|libc.Int32FromInt32(EP_HasFunc)) & (*TExpr)(unsafe.Pointer(pLeft)).Fflags if (*TExpr)(unsafe.Pointer(pLeft)).FnHeight >= (*TExpr)(unsafe.Pointer(pRoot)).FnHeight { (*TExpr)(unsafe.Pointer(pRoot)).FnHeight = (*TExpr)(unsafe.Pointer(pLeft)).FnHeight + int32(1) } } } } // C documentation // // /* // ** Generate code that will evaluate expression pExpr and store the // ** results in register target. The results are guaranteed to appear // ** in register target. // */ func _sqlite3ExprCode(tls *libc.TLS, pParse uintptr, pExpr uintptr, target int32) { var inReg int32 var op Tu8 var pX uintptr _, _, _ = inReg, op, pX if (*TParse)(unsafe.Pointer(pParse)).FpVdbe == uintptr(0) { return } inReg = _sqlite3ExprCodeTarget(tls, pParse, pExpr, target) if inReg != target { pX = _sqlite3ExprSkipCollateAndLikely(tls, pExpr) if pX != 0 && ((*TExpr)(unsafe.Pointer(pX)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_Subquery)) != uint32(0) || libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pX)).Fop) == int32(TK_REGISTER)) { op = uint8(OP_Copy) } else { op = uint8(OP_SCopy) } _sqlite3VdbeAddOp2(tls, (*TParse)(unsafe.Pointer(pParse)).FpVdbe, libc.Int32FromUint8(op), inReg, target) } } // C documentation // // /* // ** Generate code that will extract the iColumn-th column from // ** table pTab and store the column value in register iReg. // ** // ** There must be an open cursor to pTab in iTable when this routine // ** is called. If iColumn<0 then code is generated that extracts the rowid. // */ func _sqlite3ExprCodeGetColumn(tls *libc.TLS, pParse uintptr, pTab uintptr, iColumn int32, iTable int32, iReg int32, p5 Tu8) (r int32) { var pOp uintptr _ = pOp _sqlite3ExprCodeGetColumnOfTable(tls, (*TParse)(unsafe.Pointer(pParse)).FpVdbe, pTab, iTable, iColumn, iReg) if p5 != 0 { pOp = _sqlite3VdbeGetLastOp(tls, (*TParse)(unsafe.Pointer(pParse)).FpVdbe) if libc.Int32FromUint8((*TVdbeOp)(unsafe.Pointer(pOp)).Fopcode) == int32(OP_Column) { (*TVdbeOp)(unsafe.Pointer(pOp)).Fp5 = uint16(p5) } if libc.Int32FromUint8((*TVdbeOp)(unsafe.Pointer(pOp)).Fopcode) == int32(OP_VColumn) { (*TVdbeOp)(unsafe.Pointer(pOp)).Fp5 = libc.Uint16FromInt32(libc.Int32FromUint8(p5) & libc.Int32FromInt32(OPFLAG_NOCHNG)) } } return iReg } // C documentation // // /* Expression p is a comparison operator. Return a collation sequence // ** appropriate for the comparison operator. // ** // ** This is normally just a wrapper around sqlite3BinaryCompareCollSeq(). // ** However, if the OP_Commuted flag is set, then the order of the operands // ** is reversed in the sqlite3BinaryCompareCollSeq() call so that the // ** correct collating sequence is found. // */ func _sqlite3ExprCompareCollSeq(tls *libc.TLS, pParse uintptr, p uintptr) (r uintptr) { if (*TExpr)(unsafe.Pointer(p)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_Commuted)) != uint32(0) { return _sqlite3BinaryCompareCollSeq(tls, pParse, (*TExpr)(unsafe.Pointer(p)).FpRight, (*TExpr)(unsafe.Pointer(p)).FpLeft) } else { return _sqlite3BinaryCompareCollSeq(tls, pParse, (*TExpr)(unsafe.Pointer(p)).FpLeft, (*TExpr)(unsafe.Pointer(p)).FpRight) } return r } // C documentation // // /* // ** If the input expression is an ID with the name "true" or "false" // ** then convert it into an TK_TRUEFALSE term. Return non-zero if // ** the conversion happened, and zero if the expression is unaltered. // */ func _sqlite3ExprIdToTrueFalse(tls *libc.TLS, pExpr uintptr) (r int32) { var v, v1 Tu32 var v2 bool _, _, _ = v, v1, v2 if v2 = !((*TExpr)(unsafe.Pointer(pExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_Quoted)|libc.Int32FromInt32(EP_IntValue)) != libc.Uint32FromInt32(0)); v2 { v1 = _sqlite3IsTrueOrFalse(tls, *(*uintptr)(unsafe.Pointer(pExpr + 8))) v = v1 } if v2 && v1 != uint32(0) { (*TExpr)(unsafe.Pointer(pExpr)).Fop = uint8(TK_TRUEFALSE) **(**Tu32)(__ccgo_up(pExpr + 4)) |= v return int32(1) } return 0 } // C documentation // // /* // ** Generate code for a boolean expression such that a jump is made // ** to the label "dest" if the expression is false but execution // ** continues straight thru if the expression is true. // ** // ** If the expression evaluates to NULL (neither true nor false) then // ** jump if jumpIfNull is SQLITE_JUMPIFNULL or fall through if jumpIfNull // ** is 0. // */ func _sqlite3ExprIfFalse(tls *libc.TLS, pParse uintptr, pExpr uintptr, dest int32, jumpIfNull int32) { bp := tls.Alloc(16) defer tls.Free(16) var addrIsNull, d2, destIfNull, isNot, isTrue, op, v19 int32 var pAlt, pFirst, pSecond, v uintptr var _ /* r1 at bp+8 */ int32 var _ /* r2 at bp+12 */ int32 var _ /* regFree1 at bp+0 */ int32 var _ /* regFree2 at bp+4 */ int32 _, _, _, _, _, _, _, _, _, _, _ = addrIsNull, d2, destIfNull, isNot, isTrue, op, pAlt, pFirst, pSecond, v, v19 v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe op = 0 **(**int32)(__ccgo_up(bp)) = 0 **(**int32)(__ccgo_up(bp + 4)) = 0 if v == uintptr(0) { return } /* Existence of VDBE checked by caller */ if pExpr == uintptr(0) { return } /* The value of pExpr->op and op are related as follows: ** ** pExpr->op op ** --------- ---------- ** TK_ISNULL OP_NotNull ** TK_NOTNULL OP_IsNull ** TK_NE OP_Eq ** TK_EQ OP_Ne ** TK_GT OP_Le ** TK_LE OP_Gt ** TK_GE OP_Lt ** TK_LT OP_Ge ** ** For other values of pExpr->op, op is undefined and unused. ** The value of TK_ and OP_ constants are arranged such that we ** can compute the mapping above using the following expression. ** Assert()s verify that the computation is correct. */ op = libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) + libc.Int32FromInt32(TK_ISNULL)&libc.Int32FromInt32(1) ^ int32(1) - libc.Int32FromInt32(TK_ISNULL)&libc.Int32FromInt32(1) /* Verify correct alignment of TK_ and OP_ constants */ switch libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) { case int32(TK_OR): goto _1 case int32(TK_AND): goto _2 case int32(TK_NOT): goto _3 case int32(TK_TRUTH): goto _4 case int32(TK_ISNOT): goto _5 case int32(TK_IS): goto _6 case int32(TK_EQ): goto _7 case int32(TK_NE): goto _8 case int32(TK_GE): goto _9 case int32(TK_GT): goto _10 case int32(TK_LE): goto _11 case int32(TK_LT): goto _12 case int32(TK_NOTNULL): goto _13 case int32(TK_ISNULL): goto _14 case int32(TK_BETWEEN): goto _15 case int32(TK_IN): goto _16 default: goto _17 } goto _18 _2: ; _1: ; pAlt = _sqlite3ExprSimplifiedAndOr(tls, pExpr) if pAlt != pExpr { _sqlite3ExprIfFalse(tls, pParse, pAlt, dest, jumpIfNull) } else { if _exprEvalRhsFirst(tls, pExpr) != 0 { pFirst = (*TExpr)(unsafe.Pointer(pExpr)).FpRight pSecond = (*TExpr)(unsafe.Pointer(pExpr)).FpLeft } else { pFirst = (*TExpr)(unsafe.Pointer(pExpr)).FpLeft pSecond = (*TExpr)(unsafe.Pointer(pExpr)).FpRight } if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) == int32(TK_AND) { _sqlite3ExprIfFalse(tls, pParse, pFirst, dest, jumpIfNull) _sqlite3ExprIfFalse(tls, pParse, pSecond, dest, jumpIfNull) } else { d2 = _sqlite3VdbeMakeLabel(tls, pParse) _sqlite3ExprIfTrue(tls, pParse, pFirst, d2, jumpIfNull^int32(SQLITE_JUMPIFNULL)) _sqlite3ExprIfFalse(tls, pParse, pSecond, dest, jumpIfNull) _sqlite3VdbeResolveLabel(tls, v, d2) } } goto _18 _3: ; _sqlite3ExprIfTrue(tls, pParse, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft, dest, jumpIfNull) goto _18 _4: ; /* IS TRUE or IS NOT TRUE */ isNot = libc.BoolInt32(libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop2) == int32(TK_ISNOT)) isTrue = _sqlite3ExprTruthValue(tls, (*TExpr)(unsafe.Pointer(pExpr)).FpRight) if isTrue^isNot != 0 { /* IS TRUE and IS NOT FALSE */ if isNot != 0 { v19 = 0 } else { v19 = int32(SQLITE_JUMPIFNULL) } _sqlite3ExprIfFalse(tls, pParse, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft, dest, v19) } else { /* IS FALSE and IS NOT TRUE */ if isNot != 0 { v19 = 0 } else { v19 = int32(SQLITE_JUMPIFNULL) } _sqlite3ExprIfTrue(tls, pParse, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft, dest, v19) } goto _18 _6: ; _5: ; if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) == int32(TK_IS) { v19 = int32(TK_NE) } else { v19 = int32(TK_EQ) } op = v19 jumpIfNull = int32(SQLITE_NULLEQ) _12: ; _11: ; _10: ; _9: ; _8: ; _7: ; if _sqlite3ExprIsVector(tls, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft) != 0 { goto default_expr } if (*TExpr)(unsafe.Pointer(pExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_Subquery)) != uint32(0) && jumpIfNull != int32(SQLITE_NULLEQ) { addrIsNull = _exprComputeOperands(tls, pParse, pExpr, bp+8, bp+12, bp, bp+4) } else { **(**int32)(__ccgo_up(bp + 8)) = _sqlite3ExprCodeTemp(tls, pParse, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft, bp) **(**int32)(__ccgo_up(bp + 12)) = _sqlite3ExprCodeTemp(tls, pParse, (*TExpr)(unsafe.Pointer(pExpr)).FpRight, bp+4) addrIsNull = 0 } _codeCompare(tls, pParse, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft, (*TExpr)(unsafe.Pointer(pExpr)).FpRight, op, **(**int32)(__ccgo_up(bp + 8)), **(**int32)(__ccgo_up(bp + 12)), dest, jumpIfNull, libc.BoolInt32((*TExpr)(unsafe.Pointer(pExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_Commuted)) != uint32(0))) if addrIsNull != 0 { if jumpIfNull != 0 { _sqlite3VdbeChangeP2(tls, v, addrIsNull, dest) } else { _sqlite3VdbeJumpHere(tls, v, addrIsNull) } } goto _18 _14: ; _13: ; **(**int32)(__ccgo_up(bp + 8)) = _sqlite3ExprCodeTemp(tls, pParse, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft, bp) if **(**int32)(__ccgo_up(bp)) != 0 { _sqlite3VdbeTypeofColumn(tls, v, **(**int32)(__ccgo_up(bp + 8))) } _sqlite3VdbeAddOp2(tls, v, op, **(**int32)(__ccgo_up(bp + 8)), dest) goto _18 _15: ; _exprCodeBetween(tls, pParse, pExpr, dest, __ccgo_fp(_sqlite3ExprIfFalse), jumpIfNull) goto _18 _16: ; if jumpIfNull != 0 { _sqlite3ExprCodeIN(tls, pParse, pExpr, dest, dest) } else { destIfNull = _sqlite3VdbeMakeLabel(tls, pParse) _sqlite3ExprCodeIN(tls, pParse, pExpr, dest, destIfNull) _sqlite3VdbeResolveLabel(tls, v, destIfNull) } goto _18 _17: ; goto default_expr default_expr: ; if (*TExpr)(unsafe.Pointer(pExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_OuterON)|libc.Int32FromInt32(EP_IsFalse)) == uint32(EP_IsFalse) { _sqlite3VdbeGoto(tls, v, dest) } else { if (*TExpr)(unsafe.Pointer(pExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_OuterON)|libc.Int32FromInt32(EP_IsTrue)) == uint32(EP_IsTrue) { /* no-op */ } else { **(**int32)(__ccgo_up(bp + 8)) = _sqlite3ExprCodeTemp(tls, pParse, pExpr, bp) _sqlite3VdbeAddOp3(tls, v, int32(OP_IfNot), **(**int32)(__ccgo_up(bp + 8)), dest, libc.BoolInt32(jumpIfNull != 0)) } } goto _18 _18: ; _sqlite3ReleaseTempReg(tls, pParse, **(**int32)(__ccgo_up(bp))) _sqlite3ReleaseTempReg(tls, pParse, **(**int32)(__ccgo_up(bp + 4))) } // C documentation // // /* // ** Like sqlite3ExprIfFalse() except that a copy is made of pExpr before // ** code generation, and that copy is deleted after code generation. This // ** ensures that the original pExpr is unchanged. // */ func _sqlite3ExprIfFalseDup(tls *libc.TLS, pParse uintptr, pExpr uintptr, dest int32, jumpIfNull int32) { var db, pCopy uintptr _, _ = db, pCopy db = (*TParse)(unsafe.Pointer(pParse)).Fdb pCopy = _sqlite3ExprDup(tls, db, pExpr, 0) if libc.Int32FromUint8((*Tsqlite3)(unsafe.Pointer(db)).FmallocFailed) == 0 { _sqlite3ExprIfFalse(tls, pParse, pCopy, dest, jumpIfNull) } _sqlite3ExprDelete(tls, db, pCopy) } // C documentation // // /* // ** Generate code for a boolean expression such that a jump is made // ** to the label "dest" if the expression is true but execution // ** continues straight thru if the expression is false. // ** // ** If the expression evaluates to NULL (neither true nor false), then // ** take the jump if the jumpIfNull flag is SQLITE_JUMPIFNULL. // ** // ** This code depends on the fact that certain token values (ex: TK_EQ) // ** are the same as opcode values (ex: OP_Eq) that implement the corresponding // ** operation. Special comments in vdbe.c and the mkopcodeh.awk script in // ** the make process cause these values to align. Assert()s in the code // ** below verify that the numbers are aligned correctly. // */ func _sqlite3ExprIfTrue(tls *libc.TLS, pParse uintptr, pExpr uintptr, dest int32, jumpIfNull int32) { bp := tls.Alloc(16) defer tls.Free(16) var addrIsNull, d2, destIfFalse, destIfNull, isNot, isTrue, op, v19 int32 var pAlt, pFirst, pSecond, v uintptr var _ /* r1 at bp+8 */ int32 var _ /* r2 at bp+12 */ int32 var _ /* regFree1 at bp+0 */ int32 var _ /* regFree2 at bp+4 */ int32 _, _, _, _, _, _, _, _, _, _, _, _ = addrIsNull, d2, destIfFalse, destIfNull, isNot, isTrue, op, pAlt, pFirst, pSecond, v, v19 v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe op = 0 **(**int32)(__ccgo_up(bp)) = 0 **(**int32)(__ccgo_up(bp + 4)) = 0 if v == uintptr(0) { return } /* Existence of VDBE checked by caller */ if pExpr == uintptr(0) { return } /* No way this can happen */ op = libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) switch op { case int32(TK_OR): goto _1 case int32(TK_AND): goto _2 case int32(TK_NOT): goto _3 case int32(TK_TRUTH): goto _4 case int32(TK_ISNOT): goto _5 case int32(TK_IS): goto _6 case int32(TK_EQ): goto _7 case int32(TK_NE): goto _8 case int32(TK_GE): goto _9 case int32(TK_GT): goto _10 case int32(TK_LE): goto _11 case int32(TK_LT): goto _12 case int32(TK_NOTNULL): goto _13 case int32(TK_ISNULL): goto _14 case int32(TK_BETWEEN): goto _15 case int32(TK_IN): goto _16 default: goto _17 } goto _18 _2: ; _1: ; pAlt = _sqlite3ExprSimplifiedAndOr(tls, pExpr) if pAlt != pExpr { _sqlite3ExprIfTrue(tls, pParse, pAlt, dest, jumpIfNull) } else { if _exprEvalRhsFirst(tls, pExpr) != 0 { pFirst = (*TExpr)(unsafe.Pointer(pExpr)).FpRight pSecond = (*TExpr)(unsafe.Pointer(pExpr)).FpLeft } else { pFirst = (*TExpr)(unsafe.Pointer(pExpr)).FpLeft pSecond = (*TExpr)(unsafe.Pointer(pExpr)).FpRight } if op == int32(TK_AND) { d2 = _sqlite3VdbeMakeLabel(tls, pParse) _sqlite3ExprIfFalse(tls, pParse, pFirst, d2, jumpIfNull^int32(SQLITE_JUMPIFNULL)) _sqlite3ExprIfTrue(tls, pParse, pSecond, dest, jumpIfNull) _sqlite3VdbeResolveLabel(tls, v, d2) } else { _sqlite3ExprIfTrue(tls, pParse, pFirst, dest, jumpIfNull) _sqlite3ExprIfTrue(tls, pParse, pSecond, dest, jumpIfNull) } } goto _18 _3: ; _sqlite3ExprIfFalse(tls, pParse, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft, dest, jumpIfNull) goto _18 _4: ; /* IS TRUE or IS NOT TRUE */ isNot = libc.BoolInt32(libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop2) == int32(TK_ISNOT)) isTrue = _sqlite3ExprTruthValue(tls, (*TExpr)(unsafe.Pointer(pExpr)).FpRight) if isTrue^isNot != 0 { if isNot != 0 { v19 = int32(SQLITE_JUMPIFNULL) } else { v19 = 0 } _sqlite3ExprIfTrue(tls, pParse, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft, dest, v19) } else { if isNot != 0 { v19 = int32(SQLITE_JUMPIFNULL) } else { v19 = 0 } _sqlite3ExprIfFalse(tls, pParse, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft, dest, v19) } goto _18 _6: ; _5: ; if op == int32(TK_IS) { v19 = int32(TK_EQ) } else { v19 = int32(TK_NE) } op = v19 jumpIfNull = int32(SQLITE_NULLEQ) _12: ; _11: ; _10: ; _9: ; _8: ; _7: ; if _sqlite3ExprIsVector(tls, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft) != 0 { goto default_expr } if (*TExpr)(unsafe.Pointer(pExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_Subquery)) != uint32(0) && jumpIfNull != int32(SQLITE_NULLEQ) { addrIsNull = _exprComputeOperands(tls, pParse, pExpr, bp+8, bp+12, bp, bp+4) } else { **(**int32)(__ccgo_up(bp + 8)) = _sqlite3ExprCodeTemp(tls, pParse, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft, bp) **(**int32)(__ccgo_up(bp + 12)) = _sqlite3ExprCodeTemp(tls, pParse, (*TExpr)(unsafe.Pointer(pExpr)).FpRight, bp+4) addrIsNull = 0 } _codeCompare(tls, pParse, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft, (*TExpr)(unsafe.Pointer(pExpr)).FpRight, op, **(**int32)(__ccgo_up(bp + 8)), **(**int32)(__ccgo_up(bp + 12)), dest, jumpIfNull, libc.BoolInt32((*TExpr)(unsafe.Pointer(pExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_Commuted)) != uint32(0))) if addrIsNull != 0 { if jumpIfNull != 0 { _sqlite3VdbeChangeP2(tls, v, addrIsNull, dest) } else { _sqlite3VdbeJumpHere(tls, v, addrIsNull) } } goto _18 _14: ; _13: ; **(**int32)(__ccgo_up(bp + 8)) = _sqlite3ExprCodeTemp(tls, pParse, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft, bp) if **(**int32)(__ccgo_up(bp)) != 0 { _sqlite3VdbeTypeofColumn(tls, v, **(**int32)(__ccgo_up(bp + 8))) } _sqlite3VdbeAddOp2(tls, v, op, **(**int32)(__ccgo_up(bp + 8)), dest) goto _18 _15: ; _exprCodeBetween(tls, pParse, pExpr, dest, __ccgo_fp(_sqlite3ExprIfTrue), jumpIfNull) goto _18 _16: ; destIfFalse = _sqlite3VdbeMakeLabel(tls, pParse) if jumpIfNull != 0 { v19 = dest } else { v19 = destIfFalse } destIfNull = v19 _sqlite3ExprCodeIN(tls, pParse, pExpr, destIfFalse, destIfNull) _sqlite3VdbeGoto(tls, v, dest) _sqlite3VdbeResolveLabel(tls, v, destIfFalse) goto _18 _17: ; goto default_expr default_expr: ; if (*TExpr)(unsafe.Pointer(pExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_OuterON)|libc.Int32FromInt32(EP_IsTrue)) == uint32(EP_IsTrue) { _sqlite3VdbeGoto(tls, v, dest) } else { if (*TExpr)(unsafe.Pointer(pExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_OuterON)|libc.Int32FromInt32(EP_IsFalse)) == uint32(EP_IsFalse) { /* No-op */ } else { **(**int32)(__ccgo_up(bp + 8)) = _sqlite3ExprCodeTemp(tls, pParse, pExpr, bp) _sqlite3VdbeAddOp3(tls, v, int32(OP_If), **(**int32)(__ccgo_up(bp + 8)), dest, libc.BoolInt32(jumpIfNull != 0)) } } goto _18 _18: ; _sqlite3ReleaseTempReg(tls, pParse, **(**int32)(__ccgo_up(bp))) _sqlite3ReleaseTempReg(tls, pParse, **(**int32)(__ccgo_up(bp + 4))) } // C documentation // // /* // ** Walk an expression tree for the DEFAULT field of a column definition // ** in a CREATE TABLE statement. Return non-zero if the expression is // ** acceptable for use as a DEFAULT. That is to say, return non-zero if // ** the expression is constant or a function call with constant arguments. // ** Return and 0 if there are any variables. // ** // ** isInit is true when parsing from sqlite_schema. isInit is false when // ** processing a new CREATE TABLE statement. When isInit is true, parameters // ** (such as ? or $abc) in the expression are converted into NULL. When // ** isInit is false, parameters raise an error. Parameters should not be // ** allowed in a CREATE TABLE statement, but some legacy versions of SQLite // ** allowed it, so we need to support it when reading sqlite_schema for // ** backwards compatibility. // ** // ** If isInit is true, set EP_FromDDL on every TK_FUNCTION node. // ** // ** For the purposes of this function, a double-quoted string (ex: "abc") // ** is considered a variable but a single-quoted string (ex: 'abc') is // ** a constant. // */ func _sqlite3ExprIsConstantOrFunction(tls *libc.TLS, p uintptr, isInit Tu8) (r int32) { return _exprIsConst(tls, uintptr(0), p, int32(4)+libc.Int32FromUint8(isInit)) } // C documentation // // /* // ** Return true if the boolean value of the expression is always either // ** FALSE or NULL. // */ func _sqlite3ExprIsNotTrue(tls *libc.TLS, pExpr uintptr) (r int32) { bp := tls.Alloc(16) defer tls.Free(16) var _ /* v at bp+0 */ int32 if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) == int32(TK_NULL) { return int32(1) } if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) == int32(TK_TRUEFALSE) && _sqlite3ExprTruthValue(tls, pExpr) == 0 { return int32(1) } **(**int32)(__ccgo_up(bp)) = int32(1) if _sqlite3ExprIsInteger(tls, pExpr, bp, uintptr(0)) != 0 && **(**int32)(__ccgo_up(bp)) == 0 { return int32(1) } return 0 } // C documentation // // /* // ** If pExpr is an AND or OR expression, try to simplify it by eliminating // ** terms that are always true or false. Return the simplified expression. // ** Or return the original expression if no simplification is possible. // ** // ** Examples: // ** // ** (x<10) AND true => (x<10) // ** (x<10) AND false => false // ** (x<10) AND (y=22 OR false) => (x<10) AND (y=22) // ** (x<10) AND (y=22 OR true) => (x<10) // ** (y=22) OR true => true // */ func _sqlite3ExprSimplifiedAndOr(tls *libc.TLS, pExpr uintptr) (r uintptr) { var pLeft, pRight, v1 uintptr _, _, _ = pLeft, pRight, v1 if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) == int32(TK_AND) || libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) == int32(TK_OR) { pRight = _sqlite3ExprSimplifiedAndOr(tls, (*TExpr)(unsafe.Pointer(pExpr)).FpRight) pLeft = _sqlite3ExprSimplifiedAndOr(tls, (*TExpr)(unsafe.Pointer(pExpr)).FpLeft) if (*TExpr)(unsafe.Pointer(pLeft)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_OuterON)|libc.Int32FromInt32(EP_IsTrue)) == uint32(EP_IsTrue) || (*TExpr)(unsafe.Pointer(pRight)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_OuterON)|libc.Int32FromInt32(EP_IsFalse)) == uint32(EP_IsFalse) { if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) == int32(TK_AND) { v1 = pRight } else { v1 = pLeft } pExpr = v1 } else { if (*TExpr)(unsafe.Pointer(pRight)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_OuterON)|libc.Int32FromInt32(EP_IsTrue)) == uint32(EP_IsTrue) || (*TExpr)(unsafe.Pointer(pLeft)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_OuterON)|libc.Int32FromInt32(EP_IsFalse)) == uint32(EP_IsFalse) { if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) == int32(TK_AND) { v1 = pLeft } else { v1 = pRight } pExpr = v1 } } } return pExpr } // C documentation // // /* // ** Skip over any TK_COLLATE operators. // */ func _sqlite3ExprSkipCollate(tls *libc.TLS, pExpr uintptr) (r uintptr) { for pExpr != 0 && (*TExpr)(unsafe.Pointer(pExpr)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_Skip)) != uint32(0) { pExpr = (*TExpr)(unsafe.Pointer(pExpr)).FpLeft } return pExpr } // C documentation // // /* // ** Convert a scalar expression node to a TK_REGISTER referencing // ** register iReg. The caller must ensure that iReg already contains // ** the correct value for the expression. // */ func _sqlite3ExprToRegister(tls *libc.TLS, pExpr uintptr, iReg int32) { var p uintptr _ = p p = _sqlite3ExprSkipCollateAndLikely(tls, pExpr) if p == uintptr(0) { return } if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(p)).Fop) == int32(TK_REGISTER) { } else { (*TExpr)(unsafe.Pointer(p)).Fop2 = (*TExpr)(unsafe.Pointer(p)).Fop (*TExpr)(unsafe.Pointer(p)).Fop = uint8(TK_REGISTER) (*TExpr)(unsafe.Pointer(p)).FiTable = iReg **(**Tu32)(__ccgo_up(p + 4)) &= ^libc.Uint32FromInt32(libc.Int32FromInt32(EP_Skip)) } } // C documentation // // /* Invoke sqlite3RenameExprUnmap() and sqlite3ExprDelete() on the // ** expression. // */ func _sqlite3ExprUnmapAndDelete(tls *libc.TLS, pParse uintptr, p uintptr) { if p != 0 { if libc.Int32FromUint8((*TParse)(unsafe.Pointer(pParse)).FeParseMode) >= int32(PARSE_MODE_RENAME) { _sqlite3RenameExprUnmap(tls, pParse, p) } _sqlite3ExprDeleteNN(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, p) } } // C documentation // // /* // ** Given m and e, which represent a quantity r == m*pow(2,e), // ** return values *pD and *pP such that r == (*pD)*pow(10,*pP), // ** approximately. *pD should contain at least n significant digits. // ** // ** The input m is required to have its highest bit set. In other words, // ** m should be left-shifted, and e decremented, to maximize the value of m. // */ func _sqlite3Fp2Convert10(tls *libc.TLS, m Tu64, e int32, n int32, pD uintptr, pP uintptr) { bp := tls.Alloc(16) defer tls.Free(16) var h Tu64 var p int32 var _ /* d1 at bp+0 */ Tu64 var _ /* d2 at bp+8 */ Tu32 _, _ = h, p p = n - int32(1) - _pwr2to10(tls, e+int32(63)) h = _sqlite3Multiply128(tls, m, _powerOfTen(tls, p, bp+8), bp) if n == int32(18) { h = h >> libc.Uint64FromInt32(-(e + _pwr10to2(tls, p) + libc.Int32FromInt32(2))) **(**Tu64)(__ccgo_up(pD)) = (h + h<> int32(1) } else { **(**Tu64)(__ccgo_up(pD)) = h >> -(e + _pwr10to2(tls, p) + int32(1)) } **(**int32)(__ccgo_up(pP)) = -p } // C documentation // // /* // ** Set the buffer to contain nData/pData. If an OOM error occurs, leave an // ** the error code in p. If an error has already occurred when this function // ** is called, it is a no-op. // */ func _sqlite3Fts5BufferSet(tls *libc.TLS, pRc uintptr, pBuf uintptr, nData int32, pData uintptr) { (*TFts5Buffer)(unsafe.Pointer(pBuf)).Fn = 0 _sqlite3Fts5BufferAppendBlob(tls, pRc, pBuf, libc.Uint32FromInt32(nData), pData) } func _sqlite3Fts5BufferSize(tls *libc.TLS, pRc uintptr, pBuf uintptr, nByte Tu32) (r int32) { var nNew Tu64 var pNew uintptr var v1 int32 _, _, _ = nNew, pNew, v1 if libc.Uint32FromInt32((*TFts5Buffer)(unsafe.Pointer(pBuf)).FnSpace) < nByte { if (*TFts5Buffer)(unsafe.Pointer(pBuf)).FnSpace != 0 { v1 = (*TFts5Buffer)(unsafe.Pointer(pBuf)).FnSpace } else { v1 = int32(64) } nNew = libc.Uint64FromInt32(v1) for nNew < uint64(nByte) { nNew = nNew * uint64(2) } pNew = Xsqlite3_realloc64(tls, (*TFts5Buffer)(unsafe.Pointer(pBuf)).Fp, nNew) if pNew == uintptr(0) { **(**int32)(__ccgo_up(pRc)) = int32(SQLITE_NOMEM) return int32(1) } else { (*TFts5Buffer)(unsafe.Pointer(pBuf)).FnSpace = libc.Int32FromUint64(nNew) (*TFts5Buffer)(unsafe.Pointer(pBuf)).Fp = pNew } } return 0 } func _sqlite3Fts5Get32(tls *libc.TLS, aBuf uintptr) (r int32) { return libc.Int32FromUint32(uint32(**(**Tu8)(__ccgo_up(aBuf)))<)); ** ** One row for each term instance in the database. */ /* #include "fts5Int.h" */ // C documentation // // /* // ** Retrieve the origin value that will be used for the segment currently // ** being accumulated in the in-memory hash table when it is flushed to // ** disk. If successful, SQLITE_OK is returned and (*piOrigin) set to // ** the queried value. Or, if an error occurs, an error code is returned // ** and the final value of (*piOrigin) is undefined. // */ func _sqlite3Fts5IndexGetOrigin(tls *libc.TLS, p uintptr, piOrigin uintptr) (r int32) { var pStruct uintptr _ = pStruct pStruct = _fts5StructureRead(tls, p) if pStruct != 0 { **(**Ti64)(__ccgo_up(piOrigin)) = libc.Int64FromUint64((*TFts5Structure)(unsafe.Pointer(pStruct)).FnOriginCntr) _fts5StructureRelease(tls, pStruct) } return _fts5IndexReturn(tls, p) } func _sqlite3Fts5PoslistNext64(tls *libc.TLS, a uintptr, n int32, pi uintptr, piOff uintptr) (r int32) { bp := tls.Alloc(16) defer tls.Free(16) var i, v1 int32 var iOff Ti64 var _ /* iVal at bp+0 */ Tu32 _, _, _ = i, iOff, v1 i = **(**int32)(__ccgo_up(pi)) if i >= n { /* EOF */ **(**Ti64)(__ccgo_up(piOff)) = int64(-int32(1)) return int32(1) } else { iOff = **(**Ti64)(__ccgo_up(piOff)) v1 = i i = i + 1 **(**Tu32)(__ccgo_up(bp)) = uint32(**(**Tu8)(__ccgo_up(a + uintptr(v1)))) if **(**Tu32)(__ccgo_up(bp))&uint32(0x80) != 0 { i = i - 1 i = i + _sqlite3Fts5GetVarint32(tls, a+uintptr(i), bp) } if **(**Tu32)(__ccgo_up(bp)) <= uint32(1) { if **(**Tu32)(__ccgo_up(bp)) == uint32(0) { **(**int32)(__ccgo_up(pi)) = i return 0 } v1 = i i = i + 1 **(**Tu32)(__ccgo_up(bp)) = uint32(**(**Tu8)(__ccgo_up(a + uintptr(v1)))) if **(**Tu32)(__ccgo_up(bp))&uint32(0x80) != 0 { i = i - 1 i = i + _sqlite3Fts5GetVarint32(tls, a+uintptr(i), bp) } iOff = libc.Int64FromUint32(**(**Tu32)(__ccgo_up(bp))) << int32(32) v1 = i i = i + 1 **(**Tu32)(__ccgo_up(bp)) = uint32(**(**Tu8)(__ccgo_up(a + uintptr(v1)))) if **(**Tu32)(__ccgo_up(bp))&uint32(0x80) != 0 { i = i - 1 i = i + _sqlite3Fts5GetVarint32(tls, a+uintptr(i), bp) } if **(**Tu32)(__ccgo_up(bp)) < uint32(2) { /* This is a corrupt record. So stop parsing it here. */ **(**Ti64)(__ccgo_up(piOff)) = int64(-int32(1)) return int32(1) } **(**Ti64)(__ccgo_up(piOff)) = iOff + libc.Int64FromUint32((**(**Tu32)(__ccgo_up(bp))-libc.Uint32FromInt32(2))&libc.Uint32FromInt32(0x7FFFFFFF)) } else { **(**Ti64)(__ccgo_up(piOff)) = iOff&(libc.Int64FromInt32(0x7FFFFFFF)<> int32(24) & int32(0x00FF)) **(**Tu8)(__ccgo_up(aBuf + 1)) = libc.Uint8FromInt32(iVal >> int32(16) & int32(0x00FF)) **(**Tu8)(__ccgo_up(aBuf + 2)) = libc.Uint8FromInt32(iVal >> int32(8) & int32(0x00FF)) **(**Tu8)(__ccgo_up(aBuf + 3)) = libc.Uint8FromInt32(iVal >> 0 & int32(0x00FF)) } func _sqlite3Fts5UnicodeAscii(tls *libc.TLS, aArray uintptr, aAscii uintptr) { var bToken, i, iTbl, n int32 _, _, _, _ = bToken, i, iTbl, n i = 0 iTbl = 0 for i < int32(128) { bToken = libc.Int32FromUint8(**(**Tu8)(__ccgo_up(aArray + uintptr(libc.Int32FromUint16(_aFts5UnicodeData[iTbl])&int32(0x1F))))) n = libc.Int32FromUint16(_aFts5UnicodeData[iTbl])>>int32(5) + i for { if !(i < int32(128) && i < n) { break } **(**Tu8)(__ccgo_up(aAscii + uintptr(i))) = libc.Uint8FromInt32(bToken) goto _1 _1: ; i = i + 1 } iTbl = iTbl + 1 } **(**Tu8)(__ccgo_up(aAscii)) = uint8(0) /* 0x00 is never a token character */ } /* ** 2015 May 30 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ****************************************************************************** ** ** Routines for varint serialization and deserialization. */ /* #include "fts5Int.h" */ func _sqlite3Fts5UnicodeCategory(tls *libc.TLS, iCode Tu32) (r int32) { var iHi, iLo, iRes, iTest, ret, v1 int32 var iKey Tu16 _, _, _, _, _, _, _ = iHi, iKey, iLo, iRes, iTest, ret, v1 iRes = -int32(1) if iCode >= libc.Uint32FromInt32(libc.Int32FromInt32(1)<>int32(16)]) iHi = libc.Int32FromUint16(_aFts5UnicodeBlock[uint32(1)+iCode>>libc.Int32FromInt32(16)]) iKey = uint16(iCode & libc.Uint32FromInt32(0xFFFF)) for iHi > iLo { iTest = (iHi + iLo) / int32(2) if libc.Int32FromUint16(iKey) >= libc.Int32FromUint16(_aFts5UnicodeMap[iTest]) { iRes = iTest iLo = iTest + int32(1) } else { iHi = iTest } } if iRes < 0 { return 0 } if libc.Int32FromUint16(iKey) >= libc.Int32FromUint16(_aFts5UnicodeMap[iRes])+libc.Int32FromUint16(_aFts5UnicodeData[iRes])>>int32(5) { return 0 } ret = libc.Int32FromUint16(_aFts5UnicodeData[iRes]) & int32(0x1F) if ret != int32(30) { return ret } if (libc.Int32FromUint16(iKey)-libc.Int32FromUint16(_aFts5UnicodeMap[iRes]))&int32(0x01) != 0 { v1 = int32(5) } else { v1 = int32(9) } return v1 } // C documentation // // /* // ** Return true if the argument interpreted as a unicode codepoint // ** is a diacritical modifier character. // */ func _sqlite3Fts5UnicodeIsdiacritic(tls *libc.TLS, c int32) (r int32) { var mask0, mask1, v1 uint32 _, _, _ = mask0, mask1, v1 mask0 = uint32(0x08029FDF) mask1 = uint32(0x000361F8) if c < int32(768) || c > int32(817) { return 0 } if c < libc.Int32FromInt32(768)+libc.Int32FromInt32(32) { v1 = mask0 & (libc.Uint32FromInt32(1) << (c - int32(768))) } else { v1 = mask1 & (libc.Uint32FromInt32(1) << (c - int32(768) - int32(32))) } return libc.Int32FromUint32(v1) } // C documentation // // /* // ** Interpret the given string as a boolean value. // */ func _sqlite3GetBoolean(tls *libc.TLS, z uintptr, dflt Tu8) (r Tu8) { return libc.BoolUint8(libc.Int32FromUint8(_getSafetyLevel(tls, z, int32(1), dflt)) != 0) } /* The sqlite3GetBoolean() function is used by other modules but the ** remainder of this file is specific to PRAGMA processing. So omit ** the rest of the file if PRAGMAs are omitted from the build. */ // C documentation // // /* // ** Return the length (in bytes) of the token that begins at z[0]. // ** Store the token type in *tokenType before returning. // */ func _sqlite3GetToken(tls *libc.TLS, z uintptr, tokenType uintptr) (r Ti64) { var c, delim, v3 int32 var i, n Ti64 var v6 bool _, _, _, _, _, _ = c, delim, i, n, v3, v6 switch libc.Int32FromUint8(_aiClass[**(**uint8)(__ccgo_up(z))]) { /* Switch on the character-class of the first byte ** of the token. See the comment on the CC_ defines ** above. */ case int32(CC_SPACE): i = int64(1) for { if !(libc.Int32FromUint8(_sqlite3CtypeMap[**(**uint8)(__ccgo_up(z + uintptr(i)))])&int32(0x01) != 0) { break } goto _1 _1: ; i = i + 1 } **(**int32)(__ccgo_up(tokenType)) = int32(TK_SPACE) return i case int32(CC_MINUS): if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + 1))) == int32('-') { i = int64(2) for { v3 = libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i)))) c = v3 if !(v3 != 0 && c != int32('\n')) { break } goto _2 _2: ; i = i + 1 } **(**int32)(__ccgo_up(tokenType)) = int32(TK_COMMENT) return i } else { if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + 1))) == int32('>') { **(**int32)(__ccgo_up(tokenType)) = int32(TK_PTR) return int64(int32(2) + libc.BoolInt32(libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + 2))) == int32('>'))) } } **(**int32)(__ccgo_up(tokenType)) = int32(TK_MINUS) return int64(1) case int32(CC_LP): **(**int32)(__ccgo_up(tokenType)) = int32(TK_LP) return int64(1) case int32(CC_RP): **(**int32)(__ccgo_up(tokenType)) = int32(TK_RP) return int64(1) case int32(CC_SEMI): **(**int32)(__ccgo_up(tokenType)) = int32(TK_SEMI) return int64(1) case int32(CC_PLUS): **(**int32)(__ccgo_up(tokenType)) = int32(TK_PLUS) return int64(1) case int32(CC_STAR): **(**int32)(__ccgo_up(tokenType)) = int32(TK_STAR) return int64(1) case int32(CC_SLASH): if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + 1))) != int32('*') || libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + 2))) == 0 { **(**int32)(__ccgo_up(tokenType)) = int32(TK_SLASH) return int64(1) } i = int64(3) c = libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + 2))) for { if v6 = c != int32('*') || libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i)))) != int32('/'); v6 { v3 = libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i)))) c = v3 } if !(v6 && v3 != 0) { break } goto _4 _4: ; i = i + 1 } if c != 0 { i = i + 1 } **(**int32)(__ccgo_up(tokenType)) = int32(TK_COMMENT) return i case int32(CC_PERCENT): **(**int32)(__ccgo_up(tokenType)) = int32(TK_REM) return int64(1) case int32(CC_EQ): **(**int32)(__ccgo_up(tokenType)) = int32(TK_EQ) return int64(int32(1) + libc.BoolInt32(libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + 1))) == int32('='))) case int32(CC_LT): v3 = libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + 1))) c = v3 if v3 == int32('=') { **(**int32)(__ccgo_up(tokenType)) = int32(TK_LE) return int64(2) } else { if c == int32('>') { **(**int32)(__ccgo_up(tokenType)) = int32(TK_NE) return int64(2) } else { if c == int32('<') { **(**int32)(__ccgo_up(tokenType)) = int32(TK_LSHIFT) return int64(2) } else { **(**int32)(__ccgo_up(tokenType)) = int32(TK_LT) return int64(1) } } } fallthrough case int32(CC_GT): v3 = libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + 1))) c = v3 if v3 == int32('=') { **(**int32)(__ccgo_up(tokenType)) = int32(TK_GE) return int64(2) } else { if c == int32('>') { **(**int32)(__ccgo_up(tokenType)) = int32(TK_RSHIFT) return int64(2) } else { **(**int32)(__ccgo_up(tokenType)) = int32(TK_GT) return int64(1) } } fallthrough case int32(CC_BANG): if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + 1))) != int32('=') { **(**int32)(__ccgo_up(tokenType)) = int32(TK_ILLEGAL) return int64(1) } else { **(**int32)(__ccgo_up(tokenType)) = int32(TK_NE) return int64(2) } fallthrough case int32(CC_PIPE): if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + 1))) != int32('|') { **(**int32)(__ccgo_up(tokenType)) = int32(TK_BITOR) return int64(1) } else { **(**int32)(__ccgo_up(tokenType)) = int32(TK_CONCAT) return int64(2) } fallthrough case int32(CC_COMMA): **(**int32)(__ccgo_up(tokenType)) = int32(TK_COMMA) return int64(1) case int32(CC_AND): **(**int32)(__ccgo_up(tokenType)) = int32(TK_BITAND) return int64(1) case int32(CC_TILDA): **(**int32)(__ccgo_up(tokenType)) = int32(TK_BITNOT) return int64(1) case int32(CC_QUOTE): delim = libc.Int32FromUint8(**(**uint8)(__ccgo_up(z))) i = int64(1) for { v3 = libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i)))) c = v3 if !(v3 != 0) { break } if c == delim { if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i+int64(1))))) == delim { i = i + 1 } else { break } } goto _9 _9: ; i = i + 1 } if c == int32('\'') { **(**int32)(__ccgo_up(tokenType)) = int32(TK_STRING) return i + int64(1) } else { if c != 0 { **(**int32)(__ccgo_up(tokenType)) = int32(TK_ID) return i + int64(1) } else { **(**int32)(__ccgo_up(tokenType)) = int32(TK_ILLEGAL) return i } } fallthrough case int32(CC_DOT): if !(libc.Int32FromUint8(_sqlite3CtypeMap[**(**uint8)(__ccgo_up(z + 1))])&libc.Int32FromInt32(0x04) != 0) { **(**int32)(__ccgo_up(tokenType)) = int32(TK_DOT) return int64(1) } /* If the next character is a digit, this is a floating point ** number that begins with ".". Fall thru into the next case */ fallthrough case int32(CC_DIGIT): **(**int32)(__ccgo_up(tokenType)) = int32(TK_INTEGER) if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z))) == int32('0') && (libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + 1))) == int32('x') || libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + 1))) == int32('X')) && libc.Int32FromUint8(_sqlite3CtypeMap[**(**uint8)(__ccgo_up(z + 2))])&int32(0x08) != 0 { i = int64(3) for { if !(int32(1) != 0) { break } if libc.Int32FromUint8(_sqlite3CtypeMap[**(**uint8)(__ccgo_up(z + uintptr(i)))])&int32(0x08) == 0 { if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i)))) == int32('_') { **(**int32)(__ccgo_up(tokenType)) = int32(TK_QNUMBER) } else { break } } goto _11 _11: ; i = i + 1 } } else { i = 0 for { if !(int32(1) != 0) { break } if libc.Int32FromUint8(_sqlite3CtypeMap[**(**uint8)(__ccgo_up(z + uintptr(i)))])&int32(0x04) == 0 { if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i)))) == int32('_') { **(**int32)(__ccgo_up(tokenType)) = int32(TK_QNUMBER) } else { break } } goto _12 _12: ; i = i + 1 } if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i)))) == int32('.') { if **(**int32)(__ccgo_up(tokenType)) == int32(TK_INTEGER) { **(**int32)(__ccgo_up(tokenType)) = int32(TK_FLOAT) } i = i + 1 for { if !(int32(1) != 0) { break } if libc.Int32FromUint8(_sqlite3CtypeMap[**(**uint8)(__ccgo_up(z + uintptr(i)))])&int32(0x04) == 0 { if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i)))) == int32('_') { **(**int32)(__ccgo_up(tokenType)) = int32(TK_QNUMBER) } else { break } } goto _13 _13: ; i = i + 1 } } if (libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i)))) == int32('e') || libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i)))) == int32('E')) && (libc.Int32FromUint8(_sqlite3CtypeMap[**(**uint8)(__ccgo_up(z + uintptr(i+int64(1))))])&int32(0x04) != 0 || (libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i+int64(1))))) == int32('+') || libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i+int64(1))))) == int32('-')) && libc.Int32FromUint8(_sqlite3CtypeMap[**(**uint8)(__ccgo_up(z + uintptr(i+int64(2))))])&int32(0x04) != 0) { if **(**int32)(__ccgo_up(tokenType)) == int32(TK_INTEGER) { **(**int32)(__ccgo_up(tokenType)) = int32(TK_FLOAT) } i = i + int64(2) for { if !(int32(1) != 0) { break } if libc.Int32FromUint8(_sqlite3CtypeMap[**(**uint8)(__ccgo_up(z + uintptr(i)))])&int32(0x04) == 0 { if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i)))) == int32('_') { **(**int32)(__ccgo_up(tokenType)) = int32(TK_QNUMBER) } else { break } } goto _14 _14: ; i = i + 1 } } } for libc.Int32FromUint8(_sqlite3CtypeMap[**(**uint8)(__ccgo_up(z + uintptr(i)))])&int32(0x46) != 0 { **(**int32)(__ccgo_up(tokenType)) = int32(TK_ILLEGAL) i = i + 1 } return i case int32(CC_QUOTE2): i = int64(1) c = libc.Int32FromUint8(**(**uint8)(__ccgo_up(z))) for { if v6 = c != int32(']'); v6 { v3 = libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i)))) c = v3 } if !(v6 && v3 != 0) { break } goto _15 _15: ; i = i + 1 } if c == int32(']') { v3 = int32(TK_ID) } else { v3 = int32(TK_ILLEGAL) } **(**int32)(__ccgo_up(tokenType)) = v3 return i case int32(CC_VARNUM): **(**int32)(__ccgo_up(tokenType)) = int32(TK_VARIABLE) i = int64(1) for { if !(libc.Int32FromUint8(_sqlite3CtypeMap[**(**uint8)(__ccgo_up(z + uintptr(i)))])&int32(0x04) != 0) { break } goto _19 _19: ; i = i + 1 } return i case int32(CC_DOLLAR): fallthrough case int32(CC_VARALPHA): n = 0 **(**int32)(__ccgo_up(tokenType)) = int32(TK_VARIABLE) i = int64(1) for { v3 = libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i)))) c = v3 if !(v3 != 0) { break } if libc.Int32FromUint8(_sqlite3CtypeMap[libc.Uint8FromInt32(c)])&int32(0x46) != 0 { n = n + 1 } else { if c == int32('(') && n > 0 { for { i = i + 1 goto _23 _23: ; v3 = libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i)))) c = v3 if !(v3 != 0 && !(libc.Int32FromUint8(_sqlite3CtypeMap[libc.Uint8FromInt32(c)])&libc.Int32FromInt32(0x01) != 0) && c != int32(')')) { break } } if c == int32(')') { i = i + 1 } else { **(**int32)(__ccgo_up(tokenType)) = int32(TK_ILLEGAL) } break } else { if c == int32(':') && libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i+int64(1))))) == int32(':') { i = i + 1 } else { break } } } goto _20 _20: ; i = i + 1 } if n == 0 { **(**int32)(__ccgo_up(tokenType)) = int32(TK_ILLEGAL) } return i case int32(CC_KYWD0): if libc.Int32FromUint8(_aiClass[**(**uint8)(__ccgo_up(z + 1))]) > int32(CC_KYWD) { i = int64(1) break } i = int64(2) for { if !(libc.Int32FromUint8(_aiClass[**(**uint8)(__ccgo_up(z + uintptr(i)))]) <= int32(CC_KYWD)) { break } goto _24 _24: ; i = i + 1 } if libc.Int32FromUint8(_sqlite3CtypeMap[**(**uint8)(__ccgo_up(z + uintptr(i)))])&int32(0x46) != 0 { /* This token started out using characters that can appear in keywords, ** but z[i] is a character not allowed within keywords, so this must ** be an identifier instead */ i = i + 1 break } **(**int32)(__ccgo_up(tokenType)) = int32(TK_ID) return _keywordCode(tls, z, i, tokenType) case CC_X: if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + 1))) == int32('\'') { **(**int32)(__ccgo_up(tokenType)) = int32(TK_BLOB) i = int64(2) for { if !(libc.Int32FromUint8(_sqlite3CtypeMap[**(**uint8)(__ccgo_up(z + uintptr(i)))])&int32(0x08) != 0) { break } goto _25 _25: ; i = i + 1 } if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i)))) != int32('\'') || i%int64(2) != 0 { **(**int32)(__ccgo_up(tokenType)) = int32(TK_ILLEGAL) for **(**uint8)(__ccgo_up(z + uintptr(i))) != 0 && libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + uintptr(i)))) != int32('\'') { i = i + 1 } } if **(**uint8)(__ccgo_up(z + uintptr(i))) != 0 { i = i + 1 } return i } /* If it is not a BLOB literal, then it must be an ID, since no ** SQL keywords start with the letter 'x'. Fall through */ fallthrough case int32(CC_KYWD): fallthrough case int32(CC_ID): i = int64(1) case int32(CC_BOM): if libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + 1))) == int32(0xbb) && libc.Int32FromUint8(**(**uint8)(__ccgo_up(z + 2))) == int32(0xbf) { **(**int32)(__ccgo_up(tokenType)) = int32(TK_SPACE) return int64(3) } i = int64(1) case int32(CC_NUL): **(**int32)(__ccgo_up(tokenType)) = int32(TK_ILLEGAL) return 0 default: **(**int32)(__ccgo_up(tokenType)) = int32(TK_ILLEGAL) return int64(1) } for libc.Int32FromUint8(_sqlite3CtypeMap[**(**uint8)(__ccgo_up(z + uintptr(i)))])&int32(0x46) != 0 { i = i + 1 } **(**int32)(__ccgo_up(tokenType)) = int32(TK_ID) return i } // C documentation // // /* // ** Read a 64-bit variable-length integer from memory starting at p[0]. // ** Return the number of bytes read. The value is stored in *v. // */ func _sqlite3GetVarint(tls *libc.TLS, p uintptr, v uintptr) (r Tu8) { var a, b, s Tu32 _, _, _ = a, b, s if int32(**(**int8)(__ccgo_up(p))) >= 0 { **(**Tu64)(__ccgo_up(v)) = uint64(**(**uint8)(__ccgo_up(p))) return uint8(1) } if int32(**(**int8)(__ccgo_up(p + 1))) >= 0 { **(**Tu64)(__ccgo_up(v)) = uint64(libc.Uint32FromInt32(libc.Int32FromUint8(**(**uint8)(__ccgo_up(p)))&libc.Int32FromInt32(0x7f))<> int32(18) **(**Tu64)(__ccgo_up(v)) = uint64(s)<> int32(18) **(**Tu64)(__ccgo_up(v)) = uint64(s)<> int32(11) **(**Tu64)(__ccgo_up(v)) = uint64(s)<> int32(4) **(**Tu64)(__ccgo_up(v)) = uint64(s)<> int32(3) s = s | b **(**Tu64)(__ccgo_up(v)) = uint64(s)<>int32(6))) return libc.Uint8FromInt32(h & libc.Int32FromInt32(0xf)) } // C documentation // // /* Make the IdChar function accessible from ctime.c and alter.c */ func _sqlite3IsIdChar(tls *libc.TLS, c Tu8) (r int32) { return libc.BoolInt32(libc.Int32FromUint8(_sqlite3CtypeMap[c])&int32(0x46) != 0) } // C documentation // // /* // ** This function returns the collation sequence for database native text // ** encoding identified by the string zName. // ** // ** If the requested collation sequence is not available, or not available // ** in the database native encoding, the collation factory is invoked to // ** request it. If the collation factory does not supply such a sequence, // ** and the sequence is available in another text encoding, then that is // ** returned instead. // ** // ** If no versions of the requested collations sequence are available, or // ** another error occurs, NULL is returned and an error message written into // ** pParse. // ** // ** This routine is a wrapper around sqlite3FindCollSeq(). This routine // ** invokes the collation factory if the named collation cannot be found // ** and generates an error message. // ** // ** See also: sqlite3FindCollSeq(), sqlite3GetCollSeq() // */ func _sqlite3LocateCollSeq(tls *libc.TLS, pParse uintptr, zName uintptr) (r uintptr) { var db, pColl uintptr var enc, initbusy Tu8 _, _, _, _ = db, enc, initbusy, pColl db = (*TParse)(unsafe.Pointer(pParse)).Fdb enc = (*Tsqlite3)(unsafe.Pointer(db)).Fenc initbusy = (*Tsqlite3)(unsafe.Pointer(db)).Finit1.Fbusy pColl = _sqlite3FindCollSeq(tls, db, enc, zName, libc.Int32FromUint8(initbusy)) if !(initbusy != 0) && (!(pColl != 0) || !((*TCollSeq)(unsafe.Pointer(pColl)).FxCmp != 0)) { pColl = _sqlite3GetCollSeq(tls, pParse, enc, pColl, zName) } return pColl } // C documentation // // /* // ** Find (an approximate) sum of two LogEst values. This computation is // ** not a simple "+" operator because LogEst is stored as a logarithmic // ** value. // ** // */ func _sqlite3LogEstAdd(tls *libc.TLS, a TLogEst, b TLogEst) (r TLogEst) { if int32(a) >= int32(b) { if int32(a) > int32(b)+int32(49) { return a } if int32(a) > int32(b)+int32(31) { return int16(int32(a) + int32(1)) } return int16(int32(a) + libc.Int32FromUint8(_x[int32(a)-int32(b)])) } else { if int32(b) > int32(a)+int32(49) { return b } if int32(b) > int32(a)+int32(31) { return int16(int32(b) + int32(1)) } return int16(int32(b) + libc.Int32FromUint8(_x[int32(b)-int32(a)])) } return r } // C documentation // // /* // ** Convert a LogEst into an integer. // */ func _sqlite3LogEstToInt(tls *libc.TLS, x TLogEst) (r Tu64) { var n Tu64 var v1 uint64 _, _ = n, v1 n = libc.Uint64FromInt32(int32(x) % int32(10)) x = int16(int32(x) / libc.Int32FromInt32(10)) if n >= uint64(5) { n = n - uint64(2) } else { if n >= uint64(1) { n = n - uint64(1) } } if int32(x) > int32(60) { return libc.Uint64FromInt64(libc.Int64FromUint32(0xffffffff) | libc.Int64FromInt32(0x7fffffff)<= int32(3) { v1 = (n + uint64(8)) << (int32(x) - int32(3)) } else { v1 = (n + uint64(8)) >> (int32(3) - int32(x)) } return v1 } // C documentation // // /* // ** Count the number of slots of lookaside memory that are outstanding // */ func _sqlite3LookasideUsed(tls *libc.TLS, db uintptr, pHighwater uintptr) (r int32) { var nFree, nInit Tu32 _, _ = nFree, nInit nInit = _countLookasideSlots(tls, (*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpInit) nFree = _countLookasideSlots(tls, (*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpFree) nInit = nInit + _countLookasideSlots(tls, (*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpSmallInit) nFree = nFree + _countLookasideSlots(tls, (*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FpSmallFree) if pHighwater != 0 { **(**int32)(__ccgo_up(pHighwater)) = libc.Int32FromUint32((*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FnSlot - nInit) } return libc.Int32FromUint32((*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FnSlot - (nInit + nFree)) } // C documentation // // /* // ** Allocate memory. This routine is like sqlite3_malloc() except that it // ** assumes the memory subsystem has already been initialized. // */ func _sqlite3Malloc(tls *libc.TLS, n Tu64) (r uintptr) { bp := tls.Alloc(16) defer tls.Free(16) var _ /* p at bp+0 */ uintptr if n == uint64(0) || n > uint64(SQLITE_MAX_ALLOCATION_SIZE) { **(**uintptr)(__ccgo_up(bp)) = uintptr(0) } else { if _sqlite3Config.FbMemstat != 0 { Xsqlite3_mutex_enter(tls, _mem0.Fmutex) _mallocWithAlarm(tls, libc.Int32FromUint64(n), bp) Xsqlite3_mutex_leave(tls, _mem0.Fmutex) } else { **(**uintptr)(__ccgo_up(bp)) = (*(*func(*libc.TLS, int32) uintptr)(unsafe.Pointer(&struct{ uintptr }{_sqlite3Config.Fm.FxMalloc})))(tls, libc.Int32FromUint64(n)) } } /* IMP: R-11148-40995 */ return **(**uintptr)(__ccgo_up(bp)) } // C documentation // // /* // ** Compare the values contained by the two memory cells, returning // ** negative, zero or positive if pMem1 is less than, equal to, or greater // ** than pMem2. Sorting order is NULL's first, followed by numbers (integers // ** and reals) sorted numerically, followed by text ordered by the collating // ** sequence pColl and finally blob's ordered by memcmp(). // ** // ** Two NULL values are considered equal by this function. // */ func _sqlite3MemCompare(tls *libc.TLS, pMem1 uintptr, pMem2 uintptr, pColl uintptr) (r int32) { var combined_flags, f1, f2 int32 _, _, _ = combined_flags, f1, f2 f1 = libc.Int32FromUint16((*TMem)(unsafe.Pointer(pMem1)).Fflags) f2 = libc.Int32FromUint16((*TMem)(unsafe.Pointer(pMem2)).Fflags) combined_flags = f1 | f2 /* If one value is NULL, it is less than the other. If both values ** are NULL, return 0. */ if combined_flags&int32(MEM_Null) != 0 { return f2&int32(MEM_Null) - f1&int32(MEM_Null) } /* At least one of the two values is a number */ if combined_flags&(libc.Int32FromInt32(MEM_Int)|libc.Int32FromInt32(MEM_Real)|libc.Int32FromInt32(MEM_IntReal)) != 0 { if f1&f2&(libc.Int32FromInt32(MEM_Int)|libc.Int32FromInt32(MEM_IntReal)) != 0 { if *(*Ti64)(unsafe.Pointer(pMem1)) < *(*Ti64)(unsafe.Pointer(pMem2)) { return -int32(1) } if *(*Ti64)(unsafe.Pointer(pMem1)) > *(*Ti64)(unsafe.Pointer(pMem2)) { return +libc.Int32FromInt32(1) } return 0 } if f1&f2&int32(MEM_Real) != 0 { if *(*float64)(unsafe.Pointer(pMem1)) < *(*float64)(unsafe.Pointer(pMem2)) { return -int32(1) } if *(*float64)(unsafe.Pointer(pMem1)) > *(*float64)(unsafe.Pointer(pMem2)) { return +libc.Int32FromInt32(1) } return 0 } if f1&(libc.Int32FromInt32(MEM_Int)|libc.Int32FromInt32(MEM_IntReal)) != 0 { if f2&int32(MEM_Real) != 0 { return _sqlite3IntFloatCompare(tls, *(*Ti64)(unsafe.Pointer(pMem1)), *(*float64)(unsafe.Pointer(pMem2))) } else { if f2&(libc.Int32FromInt32(MEM_Int)|libc.Int32FromInt32(MEM_IntReal)) != 0 { if *(*Ti64)(unsafe.Pointer(pMem1)) < *(*Ti64)(unsafe.Pointer(pMem2)) { return -int32(1) } if *(*Ti64)(unsafe.Pointer(pMem1)) > *(*Ti64)(unsafe.Pointer(pMem2)) { return +libc.Int32FromInt32(1) } return 0 } else { return -int32(1) } } } if f1&int32(MEM_Real) != 0 { if f2&(libc.Int32FromInt32(MEM_Int)|libc.Int32FromInt32(MEM_IntReal)) != 0 { return -_sqlite3IntFloatCompare(tls, *(*Ti64)(unsafe.Pointer(pMem2)), *(*float64)(unsafe.Pointer(pMem1))) } else { return -int32(1) } } return +libc.Int32FromInt32(1) } /* If one value is a string and the other is a blob, the string is less. ** If both are strings, compare using the collating functions. */ if combined_flags&int32(MEM_Str) != 0 { if f1&int32(MEM_Str) == 0 { return int32(1) } if f2&int32(MEM_Str) == 0 { return -int32(1) } /* The collation sequence must be defined at this point, even if ** the user deletes the collation sequence after the vdbe program is ** compiled (this was not always the case). */ if pColl != 0 { return _vdbeCompareMemString(tls, pMem1, pMem2, pColl, uintptr(0)) } /* If a NULL pointer was passed as the collate function, fall through ** to the blob case and use memcmp(). */ } /* Both values must be blobs. Compare using memcmp(). */ return _sqlite3BlobCompare(tls, pMem1, pMem2) } // C documentation // // /* // ** Invoke sqlite3AtoF() on the text value of pMem. Write the // ** translation of the text input into *pValue. // ** // ** The caller must ensure that pMem->db!=0 and that pMem is in // ** mode MEM_Str or MEM_Blob. // ** // ** Result code invariants: // ** // ** rc==0 => ERROR: Input string not well-formed, or OOM // ** rc<0 => Some prefix of the input is well-formed // ** rc>0 => All of the input is well-formed // ** (rc&2)==0 => The number is expressed as an integer, with no // ** decimal point or eNNN suffix. // */ func _sqlite3MemRealValueRC(tls *libc.TLS, pMem uintptr, pValue uintptr) (r int32) { if (*TMem)(unsafe.Pointer(pMem)).Fz == uintptr(0) { **(**float64)(__ccgo_up(pValue)) = float64(0) return 0 } else { if libc.Int32FromUint8((*TMem)(unsafe.Pointer(pMem)).Fenc) == int32(SQLITE_UTF8) && (libc.Int32FromUint16((*TMem)(unsafe.Pointer(pMem)).Fflags)&int32(MEM_Term) != 0 || _sqlite3VdbeMemZeroTerminateIfAble(tls, pMem) != 0) { return _sqlite3AtoF(tls, (*TMem)(unsafe.Pointer(pMem)).Fz, pValue) } else { if (*TMem)(unsafe.Pointer(pMem)).Fn == 0 { **(**float64)(__ccgo_up(pValue)) = float64(0) return 0 } else { return _sqlite3MemRealValueRCSlowPath(tls, pMem, pValue) } } } return r } // C documentation // // /* // ** Generate code that will // ** // ** (1) acquire a lock for table pTab then // ** (2) open pTab as cursor iCur. // ** // ** If pTab is a WITHOUT ROWID table, then it is the PRIMARY KEY index // ** for that table that is actually opened. // */ func _sqlite3OpenTable(tls *libc.TLS, pParse uintptr, iCur int32, iDb int32, pTab uintptr, opcode int32) { var pPk, v uintptr var v1 int32 _, _, _ = pPk, v, v1 v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe if !((*Tsqlite3)(unsafe.Pointer((*TParse)(unsafe.Pointer(pParse)).Fdb)).FnoSharedCache != 0) { if opcode == int32(OP_OpenWrite) { v1 = int32(1) } else { v1 = 0 } _sqlite3TableLock(tls, pParse, iDb, (*TTable)(unsafe.Pointer(pTab)).Ftnum, libc.Uint8FromInt32(v1), (*TTable)(unsafe.Pointer(pTab)).FzName) } if (*TTable)(unsafe.Pointer(pTab)).FtabFlags&uint32(TF_WithoutRowid) == uint32(0) { _sqlite3VdbeAddOp4Int(tls, v, opcode, iCur, libc.Int32FromUint32((*TTable)(unsafe.Pointer(pTab)).Ftnum), iDb, int32((*TTable)(unsafe.Pointer(pTab)).FnNVCol)) } else { pPk = _sqlite3PrimaryKeyIndex(tls, pTab) _sqlite3VdbeAddOp3(tls, v, opcode, iCur, libc.Int32FromUint32((*TIndex)(unsafe.Pointer(pPk)).Ftnum), iDb) _sqlite3VdbeSetP4KeyInfo(tls, pParse, pPk) } } func _sqlite3OsOpenMalloc(tls *libc.TLS, pVfs uintptr, zFile uintptr, ppFile uintptr, flags int32, pOutFlags uintptr) (r int32) { var pFile uintptr var rc int32 _, _ = pFile, rc pFile = _sqlite3MallocZero(tls, libc.Uint64FromInt32((*Tsqlite3_vfs)(unsafe.Pointer(pVfs)).FszOsFile)) if pFile != 0 { rc = _sqlite3OsOpen(tls, pVfs, zFile, pFile, flags, pOutFlags) if rc != SQLITE_OK { Xsqlite3_free(tls, pFile) **(**uintptr)(__ccgo_up(ppFile)) = uintptr(0) } else { **(**uintptr)(__ccgo_up(ppFile)) = pFile } } else { **(**uintptr)(__ccgo_up(ppFile)) = uintptr(0) rc = int32(SQLITE_NOMEM) } return rc } // C documentation // // /* Create a TK_IS or TK_ISNOT operator, perhaps optimized to // ** TK_ISNULL or TK_NOTNULL or TK_TRUEFALSE. */ func _sqlite3PExprIs(tls *libc.TLS, pParse uintptr, op int32, pLeft uintptr, pRight uintptr) (r uintptr) { var v1 int32 _ = v1 if pRight != 0 && libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pRight)).Fop) == int32(TK_NULL) { _sqlite3ExprDeferredDelete(tls, pParse, pRight) if op == int32(TK_IS) { v1 = int32(TK_ISNULL) } else { v1 = int32(TK_NOTNULL) } return _sqlite3PExprIsNull(tls, pParse, v1, pLeft) } return _sqlite3PExpr(tls, pParse, op, pLeft, pRight) } // C documentation // // /* Create a TK_ISNULL or TK_NOTNULL expression, perhaps optimized to // ** to TK_TRUEFALSE, if possible */ func _sqlite3PExprIsNull(tls *libc.TLS, pParse uintptr, op int32, pLeft uintptr) (r uintptr) { var p uintptr _ = p p = pLeft for libc.Int32FromUint8((*TExpr)(unsafe.Pointer(p)).Fop) == int32(TK_UPLUS) || libc.Int32FromUint8((*TExpr)(unsafe.Pointer(p)).Fop) == int32(TK_UMINUS) { p = (*TExpr)(unsafe.Pointer(p)).FpLeft } switch libc.Int32FromUint8((*TExpr)(unsafe.Pointer(p)).Fop) { case int32(TK_INTEGER): fallthrough case int32(TK_STRING): fallthrough case int32(TK_FLOAT): fallthrough case int32(TK_BLOB): _sqlite3ExprDeferredDelete(tls, pParse, pLeft) return _sqlite3ExprInt32(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, libc.BoolInt32(op == int32(TK_NOTNULL))) default: break } return _sqlite3PExpr(tls, pParse, op, pLeft, uintptr(0)) } // C documentation // // /* // ** Begin a write-transaction on the specified pager object. If a // ** write-transaction has already been opened, this function is a no-op. // ** // ** If the exFlag argument is false, then acquire at least a RESERVED // ** lock on the database file. If exFlag is true, then acquire at least // ** an EXCLUSIVE lock. If such a lock is already held, no locking // ** functions need be called. // ** // ** If the subjInMemory argument is non-zero, then any sub-journal opened // ** within this transaction will be opened as an in-memory file. This // ** has no effect if the sub-journal is already opened (as it may be when // ** running in exclusive mode) or if the transaction does not require a // ** sub-journal. If the subjInMemory argument is zero, then any required // ** sub-journal is implemented in-memory if pPager is an in-memory database, // ** or using a temporary file otherwise. // */ func _sqlite3PagerBegin(tls *libc.TLS, pPager uintptr, exFlag int32, subjInMemory int32) (r int32) { var rc int32 _ = rc rc = SQLITE_OK if (*TPager)(unsafe.Pointer(pPager)).FerrCode != 0 { return (*TPager)(unsafe.Pointer(pPager)).FerrCode } (*TPager)(unsafe.Pointer(pPager)).FsubjInMemory = libc.Uint8FromInt32(subjInMemory) if libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FeState) == int32(PAGER_READER) { if (*TPager)(unsafe.Pointer(pPager)).FpWal != uintptr(0) { /* If the pager is configured to use locking_mode=exclusive, and an ** exclusive lock on the database is not already held, obtain it now. */ if (*TPager)(unsafe.Pointer(pPager)).FexclusiveMode != 0 && _sqlite3WalExclusiveMode(tls, (*TPager)(unsafe.Pointer(pPager)).FpWal, -int32(1)) != 0 { rc = _pagerLockDb(tls, pPager, int32(EXCLUSIVE_LOCK)) if rc != SQLITE_OK { return rc } _sqlite3WalExclusiveMode(tls, (*TPager)(unsafe.Pointer(pPager)).FpWal, int32(1)) } /* Grab the write lock on the log file. If successful, upgrade to ** PAGER_RESERVED state. Otherwise, return an error code to the caller. ** The busy-handler is not invoked if another connection already ** holds the write-lock. If possible, the upper layer will call it. */ rc = _sqlite3WalBeginWriteTransaction(tls, (*TPager)(unsafe.Pointer(pPager)).FpWal) } else { /* Obtain a RESERVED lock on the database file. If the exFlag parameter ** is true, then immediately upgrade this to an EXCLUSIVE lock. The ** busy-handler callback can be used when upgrading to the EXCLUSIVE ** lock, but not when obtaining the RESERVED lock. */ rc = _pagerLockDb(tls, pPager, int32(RESERVED_LOCK)) if rc == SQLITE_OK && exFlag != 0 { rc = _pager_wait_on_lock(tls, pPager, int32(EXCLUSIVE_LOCK)) } } if rc == SQLITE_OK { /* Change to WRITER_LOCKED state. ** ** WAL mode sets Pager.eState to PAGER_WRITER_LOCKED or CACHEMOD ** when it has an open transaction, but never to DBMOD or FINISHED. ** This is because in those states the code to roll back savepoint ** transactions may copy data from the sub-journal into the database ** file as well as into the page cache. Which would be incorrect in ** WAL mode. */ (*TPager)(unsafe.Pointer(pPager)).FeState = uint8(PAGER_WRITER_LOCKED) (*TPager)(unsafe.Pointer(pPager)).FdbHintSize = (*TPager)(unsafe.Pointer(pPager)).FdbSize (*TPager)(unsafe.Pointer(pPager)).FdbFileSize = (*TPager)(unsafe.Pointer(pPager)).FdbSize (*TPager)(unsafe.Pointer(pPager)).FdbOrigSize = (*TPager)(unsafe.Pointer(pPager)).FdbSize (*TPager)(unsafe.Pointer(pPager)).FjournalOff = 0 } } return rc } // C documentation // // /* // ** Unless this is an in-memory or temporary database, clear the pager cache. // */ func _sqlite3PagerClearCache(tls *libc.TLS, pPager uintptr) { if libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FtempFile) == 0 { _pager_reset(tls, pPager) } } // C documentation // // /* // ** Shutdown the page cache. Free all memory and close all files. // ** // ** If a transaction was in progress when this routine is called, that // ** transaction is rolled back. All outstanding pages are invalidated // ** and their memory is freed. Any attempt to use a page associated // ** with this page cache after this function returns will likely // ** result in a coredump. // ** // ** This function always succeeds. If a transaction is active an attempt // ** is made to roll it back. If an error occurs during the rollback // ** a hot journal may be left in the filesystem but no error is returned // ** to the caller. // */ func _sqlite3PagerClose(tls *libc.TLS, pPager uintptr, db uintptr) (r int32) { var a, pTmp uintptr _, _ = a, pTmp pTmp = (*TPager)(unsafe.Pointer(pPager)).FpTmpSpace _sqlite3BeginBenignMalloc(tls) _pagerFreeMapHdrs(tls, pPager) /* pPager->errCode = 0; */ (*TPager)(unsafe.Pointer(pPager)).FexclusiveMode = uint8(0) a = uintptr(0) if db != 0 && uint64(0) == (*Tsqlite3)(unsafe.Pointer(db)).Fflags&uint64(SQLITE_NoCkptOnClose) && SQLITE_OK == _databaseIsUnmoved(tls, pPager) { a = pTmp } _sqlite3WalClose(tls, (*TPager)(unsafe.Pointer(pPager)).FpWal, db, libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FwalSyncFlags), int32((*TPager)(unsafe.Pointer(pPager)).FpageSize), a) (*TPager)(unsafe.Pointer(pPager)).FpWal = uintptr(0) _pager_reset(tls, pPager) if (*TPager)(unsafe.Pointer(pPager)).FmemDb != 0 { _pager_unlock(tls, pPager) } else { /* If it is open, sync the journal file before calling UnlockAndRollback. ** If this is not done, then an unsynced portion of the open journal ** file may be played back into the database. If a power failure occurs ** while this is happening, the database could become corrupt. ** ** If an error occurs while trying to sync the journal, shift the pager ** into the ERROR state. This causes UnlockAndRollback to unlock the ** database and close the journal file without attempting to roll it ** back or finalize it. The next database user will have to do hot-journal ** rollback before accessing the database file. */ if (*Tsqlite3_file)(unsafe.Pointer((*TPager)(unsafe.Pointer(pPager)).Fjfd)).FpMethods != uintptr(0) { _pager_error(tls, pPager, _pagerSyncHotJournal(tls, pPager)) } _pagerUnlockAndRollback(tls, pPager) } _sqlite3EndBenignMalloc(tls) _sqlite3OsClose(tls, (*TPager)(unsafe.Pointer(pPager)).Fjfd) _sqlite3OsClose(tls, (*TPager)(unsafe.Pointer(pPager)).Ffd) _sqlite3PageFree(tls, pTmp) _sqlite3PcacheClose(tls, (*TPager)(unsafe.Pointer(pPager)).FpPCache) Xsqlite3_free(tls, pPager) return SQLITE_OK } // C documentation // // /* // ** This function is called to close the connection to the log file prior // ** to switching from WAL to rollback mode. // ** // ** Before closing the log file, this function attempts to take an // ** EXCLUSIVE lock on the database file. If this cannot be obtained, an // ** error (SQLITE_BUSY) is returned and the log connection is not closed. // ** If successful, the EXCLUSIVE lock is not released before returning. // */ func _sqlite3PagerCloseWal(tls *libc.TLS, pPager uintptr, db uintptr) (r int32) { bp := tls.Alloc(16) defer tls.Free(16) var rc int32 var _ /* logexists at bp+0 */ int32 _ = rc rc = SQLITE_OK /* If the log file is not already open, but does exist in the file-system, ** it may need to be checkpointed before the connection can switch to ** rollback mode. Open it now so this can happen. */ if !((*TPager)(unsafe.Pointer(pPager)).FpWal != 0) { **(**int32)(__ccgo_up(bp)) = 0 rc = _pagerLockDb(tls, pPager, int32(SHARED_LOCK)) if rc == SQLITE_OK { rc = _sqlite3OsAccess(tls, (*TPager)(unsafe.Pointer(pPager)).FpVfs, (*TPager)(unsafe.Pointer(pPager)).FzWal, SQLITE_ACCESS_EXISTS, bp) } if rc == SQLITE_OK && **(**int32)(__ccgo_up(bp)) != 0 { rc = _pagerOpenWal(tls, pPager) } } /* Checkpoint and close the log. Because an EXCLUSIVE lock is held on ** the database file, the log and log-summary files will be deleted. */ if rc == SQLITE_OK && (*TPager)(unsafe.Pointer(pPager)).FpWal != 0 { rc = _pagerExclusiveLock(tls, pPager) if rc == SQLITE_OK { rc = _sqlite3WalClose(tls, (*TPager)(unsafe.Pointer(pPager)).FpWal, db, libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FwalSyncFlags), int32((*TPager)(unsafe.Pointer(pPager)).FpageSize), (*TPager)(unsafe.Pointer(pPager)).FpTmpSpace) (*TPager)(unsafe.Pointer(pPager)).FpWal = uintptr(0) _pagerFixMaplimit(tls, pPager) if rc != 0 && !((*TPager)(unsafe.Pointer(pPager)).FexclusiveMode != 0) { _pagerUnlockDb(tls, pPager, int32(SHARED_LOCK)) } } } return rc } // C documentation // // /* // ** Sync the database file for the pager pPager. zSuper points to the name // ** of a super-journal file that should be written into the individual // ** journal file. zSuper may be NULL, which is interpreted as no // ** super-journal (a single database transaction). // ** // ** This routine ensures that: // ** // ** * The database file change-counter is updated, // ** * the journal is synced (unless the atomic-write optimization is used), // ** * all dirty pages are written to the database file, // ** * the database file is truncated (if required), and // ** * the database file synced. // ** // ** The only thing that remains to commit the transaction is to finalize // ** (delete, truncate or zero the first part of) the journal file (or // ** delete the super-journal file if specified). // ** // ** Note that if zSuper==NULL, this does not overwrite a previous value // ** passed to an sqlite3PagerCommitPhaseOne() call. // ** // ** If the final parameter - noSync - is true, then the database file itself // ** is not synced. The caller must call sqlite3PagerSync() directly to // ** sync the database file before calling CommitPhaseTwo() to delete the // ** journal file in this case. // */ func _sqlite3PagerCommitPhaseOne(tls *libc.TLS, pPager uintptr, zSuper uintptr, noSync int32) (r int32) { bp := tls.Alloc(16) defer tls.Free(16) var nNew TPgno var pList uintptr var rc int32 var _ /* pPageOne at bp+0 */ uintptr _, _, _ = nNew, pList, rc rc = SQLITE_OK /* Return code */ /* If a prior error occurred, report that error again. */ if (*TPager)(unsafe.Pointer(pPager)).FerrCode != 0 { return (*TPager)(unsafe.Pointer(pPager)).FerrCode } /* Provide the ability to easily simulate an I/O error during testing */ if _sqlite3FaultSim(tls, int32(400)) != 0 { return int32(SQLITE_IOERR) } /* If no database changes have been made, return early. */ if libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FeState) < int32(PAGER_WRITER_CACHEMOD) { return SQLITE_OK } if 0 == _pagerFlushOnCommit(tls, pPager, int32(1)) { /* If this is an in-memory db, or no pages have been written to, or this ** function has already been called, it is mostly a no-op. However, any ** backup in progress needs to be restarted. */ _sqlite3BackupRestart(tls, (*TPager)(unsafe.Pointer(pPager)).FpBackup) } else { if (*TPager)(unsafe.Pointer(pPager)).FpWal != uintptr(0) { **(**uintptr)(__ccgo_up(bp)) = uintptr(0) pList = _sqlite3PcacheDirtyList(tls, (*TPager)(unsafe.Pointer(pPager)).FpPCache) if pList == uintptr(0) { /* Must have at least one page for the WAL commit flag. ** Ticket [2d1a5c67dfc2363e44f29d9bbd57f] 2011-05-18 */ rc = _sqlite3PagerGet(tls, pPager, uint32(1), bp, 0) pList = **(**uintptr)(__ccgo_up(bp)) (*TPgHdr)(unsafe.Pointer(pList)).FpDirty = uintptr(0) } if pList != 0 { rc = _pagerWalFrames(tls, pPager, pList, (*TPager)(unsafe.Pointer(pPager)).FdbSize, int32(1)) } _sqlite3PagerUnref(tls, **(**uintptr)(__ccgo_up(bp))) if rc == SQLITE_OK { _sqlite3PcacheCleanAll(tls, (*TPager)(unsafe.Pointer(pPager)).FpPCache) } } else { /* The bBatch boolean is true if the batch-atomic-write commit method ** should be used. No rollback journal is created if batch-atomic-write ** is enabled. */ rc = _pager_incr_changecounter(tls, pPager, 0) if rc != SQLITE_OK { goto commit_phase_one_exit } /* Write the super-journal name into the journal file. If a ** super-journal file name has already been written to the journal file, ** or if zSuper is NULL (no super-journal), then this call is a no-op. */ rc = _writeSuperJournal(tls, pPager, zSuper) if rc != SQLITE_OK { goto commit_phase_one_exit } /* Sync the journal file and write all dirty pages to the database. ** If the atomic-update optimization is being used, this sync will not ** create the journal file or perform any real IO. ** ** Because the change-counter page was just modified, unless the ** atomic-update optimization is used it is almost certain that the ** journal requires a sync here. However, in locking_mode=exclusive ** on a system under memory pressure it is just possible that this is ** not the case. In this case it is likely enough that the redundant ** xSync() call will be changed to a no-op by the OS anyhow. */ rc = _syncJournal(tls, pPager, 0) if rc != SQLITE_OK { goto commit_phase_one_exit } pList = _sqlite3PcacheDirtyList(tls, (*TPager)(unsafe.Pointer(pPager)).FpPCache) if true { rc = _pager_write_pagelist(tls, pPager, pList) } if rc != SQLITE_OK { goto commit_phase_one_exit } _sqlite3PcacheCleanAll(tls, (*TPager)(unsafe.Pointer(pPager)).FpPCache) /* If the file on disk is smaller than the database image, use ** pager_truncate to grow the file here. This can happen if the database ** image was extended as part of the current transaction and then the ** last page in the db image moved to the free-list. In this case the ** last page is never written out to disk, leaving the database file ** undersized. Fix this now if it is the case. */ if (*TPager)(unsafe.Pointer(pPager)).FdbSize > (*TPager)(unsafe.Pointer(pPager)).FdbFileSize { nNew = (*TPager)(unsafe.Pointer(pPager)).FdbSize - libc.BoolUint32((*TPager)(unsafe.Pointer(pPager)).FdbSize == (*TPager)(unsafe.Pointer(pPager)).FlckPgno) rc = _pager_truncate(tls, pPager, nNew) if rc != SQLITE_OK { goto commit_phase_one_exit } } /* Finally, sync the database file. */ if !(noSync != 0) { rc = _sqlite3PagerSync(tls, pPager, zSuper) } } } goto commit_phase_one_exit commit_phase_one_exit: ; if rc == SQLITE_OK && !((*TPager)(unsafe.Pointer(pPager)).FpWal != libc.UintptrFromInt32(0)) { (*TPager)(unsafe.Pointer(pPager)).FeState = uint8(PAGER_WRITER_FINISHED) } return rc } // C documentation // // /* // ** When this function is called, the database file has been completely // ** updated to reflect the changes made by the current transaction and // ** synced to disk. The journal file still exists in the file-system // ** though, and if a failure occurs at this point it will eventually // ** be used as a hot-journal and the current transaction rolled back. // ** // ** This function finalizes the journal file, either by deleting, // ** truncating or partially zeroing it, so that it cannot be used // ** for hot-journal rollback. Once this is done the transaction is // ** irrevocably committed. // ** // ** If an error occurs, an IO error code is returned and the pager // ** moves into the error state. Otherwise, SQLITE_OK is returned. // */ func _sqlite3PagerCommitPhaseTwo(tls *libc.TLS, pPager uintptr) (r int32) { var rc int32 _ = rc rc = SQLITE_OK /* Return code */ /* This routine should not be called if a prior error has occurred. ** But if (due to a coding error elsewhere in the system) it does get ** called, just return the same error code without doing anything. */ if (*TPager)(unsafe.Pointer(pPager)).FerrCode != 0 { return (*TPager)(unsafe.Pointer(pPager)).FerrCode } (*TPager)(unsafe.Pointer(pPager)).FiDataVersion = (*TPager)(unsafe.Pointer(pPager)).FiDataVersion + 1 /* An optimization. If the database was not actually modified during ** this transaction, the pager is running in exclusive-mode and is ** using persistent journals, then this function is a no-op. ** ** The start of the journal file currently contains a single journal ** header with the nRec field set to 0. If such a journal is used as ** a hot-journal during hot-journal rollback, 0 changes will be made ** to the database file. So there is no need to zero the journal ** header. Since the pager is in exclusive mode, there is no need ** to drop any locks either. */ if libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FeState) == int32(PAGER_WRITER_LOCKED) && (*TPager)(unsafe.Pointer(pPager)).FexclusiveMode != 0 && libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FjournalMode) == int32(PAGER_JOURNALMODE_PERSIST) { (*TPager)(unsafe.Pointer(pPager)).FeState = uint8(PAGER_READER) return SQLITE_OK } rc = _pager_end_transaction(tls, pPager, libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FsetSuper), int32(1)) return _pager_error(tls, pPager, rc) } // C documentation // // /* // ** Return the current journal mode. // */ func _sqlite3PagerGetJournalMode(tls *libc.TLS, pPager uintptr) (r int32) { return libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FjournalMode) } // C documentation // // /* // ** Get/set the locking-mode for this pager. Parameter eMode must be one // ** of PAGER_LOCKINGMODE_QUERY, PAGER_LOCKINGMODE_NORMAL or // ** PAGER_LOCKINGMODE_EXCLUSIVE. If the parameter is not _QUERY, then // ** the locking-mode is set to the value specified. // ** // ** The returned value is either PAGER_LOCKINGMODE_NORMAL or // ** PAGER_LOCKINGMODE_EXCLUSIVE, indicating the current (possibly updated) // ** locking-mode. // */ func _sqlite3PagerLockingMode(tls *libc.TLS, pPager uintptr, eMode int32) (r int32) { if eMode >= 0 && !((*TPager)(unsafe.Pointer(pPager)).FtempFile != 0) && !(_sqlite3WalHeapMemory(tls, (*TPager)(unsafe.Pointer(pPager)).FpWal) != 0) { (*TPager)(unsafe.Pointer(pPager)).FexclusiveMode = libc.Uint8FromInt32(eMode) } return libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FexclusiveMode) } // C documentation // // /* // ** Return TRUE if the pager is in a state where it is OK to change the // ** journalmode. Journalmode changes can only happen when the database // ** is unmodified. // */ func _sqlite3PagerOkToChangeJournalMode(tls *libc.TLS, pPager uintptr) (r int32) { if libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FeState) >= int32(PAGER_WRITER_CACHEMOD) { return 0 } if (*Tsqlite3_file)(unsafe.Pointer((*TPager)(unsafe.Pointer(pPager)).Fjfd)).FpMethods != uintptr(0) && (*TPager)(unsafe.Pointer(pPager)).FjournalOff > 0 { return 0 } return int32(1) } // C documentation // // /* // ** This function may only be called when a read-transaction is open on // ** the pager. It returns the total number of pages in the database. // ** // ** However, if the file is between 1 and bytes in size, then // ** this is considered a 1 page file. // */ func _sqlite3PagerPagecount(tls *libc.TLS, pPager uintptr, pnPage uintptr) { **(**int32)(__ccgo_up(pnPage)) = libc.Int32FromUint32((*TPager)(unsafe.Pointer(pPager)).FdbSize) } // C documentation // // /* // ** If a write transaction is open, then all changes made within the // ** transaction are reverted and the current write-transaction is closed. // ** The pager falls back to PAGER_READER state if successful, or PAGER_ERROR // ** state if an error occurs. // ** // ** If the pager is already in PAGER_ERROR state when this function is called, // ** it returns Pager.errCode immediately. No work is performed in this case. // ** // ** Otherwise, in rollback mode, this function performs two functions: // ** // ** 1) It rolls back the journal file, restoring all database file and // ** in-memory cache pages to the state they were in when the transaction // ** was opened, and // ** // ** 2) It finalizes the journal file, so that it is not used for hot // ** rollback at any point in the future. // ** // ** Finalization of the journal file (task 2) is only performed if the // ** rollback is successful. // ** // ** In WAL mode, all cache-entries containing data modified within the // ** current transaction are either expelled from the cache or reverted to // ** their pre-transaction state by re-reading data from the database or // ** WAL files. The WAL transaction is then closed. // */ func _sqlite3PagerRollback(tls *libc.TLS, pPager uintptr) (r int32) { var eState, rc, rc2 int32 _, _, _ = eState, rc, rc2 rc = SQLITE_OK /* Return code */ /* PagerRollback() is a no-op if called in READER or OPEN state. If ** the pager is already in the ERROR state, the rollback is not ** attempted here. Instead, the error code is returned to the caller. */ if libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FeState) == int32(PAGER_ERROR) { return (*TPager)(unsafe.Pointer(pPager)).FerrCode } if libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FeState) <= int32(PAGER_READER) { return SQLITE_OK } if (*TPager)(unsafe.Pointer(pPager)).FpWal != uintptr(0) { rc = _sqlite3PagerSavepoint(tls, pPager, int32(SAVEPOINT_ROLLBACK), -int32(1)) rc2 = _pager_end_transaction(tls, pPager, libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FsetSuper), 0) if rc == SQLITE_OK { rc = rc2 } } else { if !((*Tsqlite3_file)(unsafe.Pointer((*TPager)(unsafe.Pointer(pPager)).Fjfd)).FpMethods != libc.UintptrFromInt32(0)) || libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FeState) == int32(PAGER_WRITER_LOCKED) { eState = libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FeState) rc = _pager_end_transaction(tls, pPager, 0, 0) if !((*TPager)(unsafe.Pointer(pPager)).FmemDb != 0) && eState > int32(PAGER_WRITER_LOCKED) { /* This can happen using journal_mode=off. Move the pager to the error ** state to indicate that the contents of the cache may not be trusted. ** Any active readers will get SQLITE_ABORT. */ (*TPager)(unsafe.Pointer(pPager)).FerrCode = int32(SQLITE_ABORT) (*TPager)(unsafe.Pointer(pPager)).FeState = uint8(PAGER_ERROR) _setGetterMethod(tls, pPager) return rc } } else { rc = _pager_playback(tls, pPager, 0) } } /* If an error occurs during a ROLLBACK, we can no longer trust the pager ** cache. So call pager_error() on the way out to make any error persistent. */ return _pager_error(tls, pPager, rc) } // C documentation // // /* // ** Set the journal-mode for this pager. Parameter eMode must be one of: // ** // ** PAGER_JOURNALMODE_DELETE // ** PAGER_JOURNALMODE_TRUNCATE // ** PAGER_JOURNALMODE_PERSIST // ** PAGER_JOURNALMODE_OFF // ** PAGER_JOURNALMODE_MEMORY // ** PAGER_JOURNALMODE_WAL // ** // ** The journalmode is set to the value specified if the change is allowed. // ** The change may be disallowed for the following reasons: // ** // ** * An in-memory database can only have its journal_mode set to _OFF // ** or _MEMORY. // ** // ** * Temporary databases cannot have _WAL journalmode. // ** // ** The returned indicate the current (possibly updated) journal-mode. // */ func _sqlite3PagerSetJournalMode(tls *libc.TLS, pPager uintptr, eMode int32) (r int32) { var eOld Tu8 var rc, state int32 _, _, _ = eOld, rc, state eOld = (*TPager)(unsafe.Pointer(pPager)).FjournalMode /* Prior journalmode */ /* The eMode parameter is always valid */ /* This routine is only called from the OP_JournalMode opcode, and ** the logic there will never allow a temporary file to be changed ** to WAL mode. */ /* Do allow the journalmode of an in-memory database to be set to ** anything other than MEMORY or OFF */ if (*TPager)(unsafe.Pointer(pPager)).FmemDb != 0 { if eMode != int32(PAGER_JOURNALMODE_MEMORY) && eMode != int32(PAGER_JOURNALMODE_OFF) { eMode = libc.Int32FromUint8(eOld) } } if eMode != libc.Int32FromUint8(eOld) { /* Change the journal mode. */ (*TPager)(unsafe.Pointer(pPager)).FjournalMode = libc.Uint8FromInt32(eMode) /* When transitioning from TRUNCATE or PERSIST to any other journal ** mode except WAL, unless the pager is in locking_mode=exclusive mode, ** delete the journal file. */ if !((*TPager)(unsafe.Pointer(pPager)).FexclusiveMode != 0) && libc.Int32FromUint8(eOld)&int32(5) == int32(1) && eMode&int32(1) == 0 { /* In this case we would like to delete the journal file. If it is ** not possible, then that is not a problem. Deleting the journal file ** here is an optimization only. ** ** Before deleting the journal file, obtain a RESERVED lock on the ** database file. This ensures that the journal file is not deleted ** while it is in use by some other client. */ _sqlite3OsClose(tls, (*TPager)(unsafe.Pointer(pPager)).Fjfd) if libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FeLock) >= int32(RESERVED_LOCK) { _sqlite3OsDelete(tls, (*TPager)(unsafe.Pointer(pPager)).FpVfs, (*TPager)(unsafe.Pointer(pPager)).FzJournal, 0) } else { rc = SQLITE_OK state = libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FeState) if state == PAGER_OPEN { rc = _sqlite3PagerSharedLock(tls, pPager) } if libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FeState) == int32(PAGER_READER) { rc = _pagerLockDb(tls, pPager, int32(RESERVED_LOCK)) } if rc == SQLITE_OK { _sqlite3OsDelete(tls, (*TPager)(unsafe.Pointer(pPager)).FpVfs, (*TPager)(unsafe.Pointer(pPager)).FzJournal, 0) } if rc == SQLITE_OK && state == int32(PAGER_READER) { _pagerUnlockDb(tls, pPager, int32(SHARED_LOCK)) } else { if state == PAGER_OPEN { _pager_unlock(tls, pPager) } } } } else { if eMode == int32(PAGER_JOURNALMODE_OFF) || eMode == int32(PAGER_JOURNALMODE_MEMORY) { _sqlite3OsClose(tls, (*TPager)(unsafe.Pointer(pPager)).Fjfd) } } } /* Return the new journal mode */ return libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FjournalMode) } // C documentation // // /* // ** Sync the database file to disk. This is a no-op for in-memory databases // ** or pages with the Pager.noSync flag set. // ** // ** If successful, or if called on a pager for which it is a no-op, this // ** function returns SQLITE_OK. Otherwise, an IO error code is returned. // */ func _sqlite3PagerSync(tls *libc.TLS, pPager uintptr, zSuper uintptr) (r int32) { var pArg uintptr var rc int32 _, _ = pArg, rc rc = SQLITE_OK pArg = zSuper rc = _sqlite3OsFileControl(tls, (*TPager)(unsafe.Pointer(pPager)).Ffd, int32(SQLITE_FCNTL_SYNC), pArg) if rc == int32(SQLITE_NOTFOUND) { rc = SQLITE_OK } if rc == SQLITE_OK && !((*TPager)(unsafe.Pointer(pPager)).FnoSync != 0) { rc = _sqlite3OsSync(tls, (*TPager)(unsafe.Pointer(pPager)).Ffd, libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FsyncFlags)) } return rc } // C documentation // // /* // ** Release a page reference. // ** // ** The sqlite3PagerUnref() and sqlite3PagerUnrefNotNull() may only be used // ** if we know that the page being released is not the last reference to page1. // ** The btree layer always holds page1 open until the end, so these first // ** two routines can be used to release any page other than BtShared.pPage1. // ** The assert() at tag-20230419-2 proves that this constraint is always // ** honored. // ** // ** Use sqlite3PagerUnrefPageOne() to release page1. This latter routine // ** checks the total number of outstanding pages and if the number of // ** pages reaches zero it drops the database lock. // */ func _sqlite3PagerUnrefNotNull(tls *libc.TLS, pPg uintptr) { if libc.Int32FromUint16((*TDbPage)(unsafe.Pointer(pPg)).Fflags)&int32(PGHDR_MMAP) != 0 { /* Page1 is never memory mapped */ _pagerReleaseMapPage(tls, pPg) } else { _sqlite3PcacheRelease(tls, pPg) } /* Do not use this routine to release the last reference to page1 */ /* tag-20230419-2 */ } // C documentation // // /* // ** Mark a data page as writeable. This routine must be called before // ** making changes to a page. The caller must check the return value // ** of this function and be careful not to change any page data unless // ** this routine returns SQLITE_OK. // ** // ** The difference between this function and pager_write() is that this // ** function also deals with the special case where 2 or more pages // ** fit on a single disk sector. In this case all co-resident pages // ** must have been written to the journal file before returning. // ** // ** If an error occurs, SQLITE_NOMEM or an IO error code is returned // ** as appropriate. Otherwise, SQLITE_OK. // */ func _sqlite3PagerWrite(tls *libc.TLS, pPg uintptr) (r int32) { var pPager uintptr _ = pPager pPager = (*TPgHdr)(unsafe.Pointer(pPg)).FpPager if libc.Int32FromUint16((*TPgHdr)(unsafe.Pointer(pPg)).Fflags)&int32(PGHDR_WRITEABLE) != 0 && (*TPager)(unsafe.Pointer(pPager)).FdbSize >= (*TPgHdr)(unsafe.Pointer(pPg)).Fpgno { if (*TPager)(unsafe.Pointer(pPager)).FnSavepoint != 0 { return _subjournalPageIfRequired(tls, pPg) } return SQLITE_OK } else { if (*TPager)(unsafe.Pointer(pPager)).FerrCode != 0 { return (*TPager)(unsafe.Pointer(pPager)).FerrCode } else { if (*TPager)(unsafe.Pointer(pPager)).FsectorSize > libc.Uint32FromInt64((*TPager)(unsafe.Pointer(pPager)).FpageSize) { return _pagerWriteLargeSector(tls, pPg) } else { return _pager_write(tls, pPg) } } } return r } /* ** Return TRUE if the page given in the argument was previously passed ** to sqlite3PagerWrite(). In other words, return TRUE if it is ok ** to change the content of the page. */ // C documentation // // /* // ** Free all memory allocations in the pParse object // */ func _sqlite3ParseObjectReset(tls *libc.TLS, pParse uintptr) { var db, pCleanup uintptr var v1 int32 _, _, _ = db, pCleanup, v1 db = (*TParse)(unsafe.Pointer(pParse)).Fdb if (*TParse)(unsafe.Pointer(pParse)).FaTableLock != 0 { _sqlite3DbNNFreeNN(tls, db, (*TParse)(unsafe.Pointer(pParse)).FaTableLock) } for (*TParse)(unsafe.Pointer(pParse)).FpCleanup != 0 { pCleanup = (*TParse)(unsafe.Pointer(pParse)).FpCleanup (*TParse)(unsafe.Pointer(pParse)).FpCleanup = (*TParseCleanup)(unsafe.Pointer(pCleanup)).FpNext (*(*func(*libc.TLS, uintptr, uintptr))(unsafe.Pointer(&struct{ uintptr }{(*TParseCleanup)(unsafe.Pointer(pCleanup)).FxCleanup})))(tls, db, (*TParseCleanup)(unsafe.Pointer(pCleanup)).FpPtr) _sqlite3DbNNFreeNN(tls, db, pCleanup) } if (*TParse)(unsafe.Pointer(pParse)).FaLabel != 0 { _sqlite3DbNNFreeNN(tls, db, (*TParse)(unsafe.Pointer(pParse)).FaLabel) } if (*TParse)(unsafe.Pointer(pParse)).FpConstExpr != 0 { _sqlite3ExprListDelete(tls, db, (*TParse)(unsafe.Pointer(pParse)).FpConstExpr) } (*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FbDisable -= uint32((*TParse)(unsafe.Pointer(pParse)).FdisableLookaside) if (*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FbDisable != 0 { v1 = 0 } else { v1 = libc.Int32FromUint16((*Tsqlite3)(unsafe.Pointer(db)).Flookaside.FszTrue) } (*Tsqlite3)(unsafe.Pointer(db)).Flookaside.Fsz = libc.Uint16FromInt32(v1) (*Tsqlite3)(unsafe.Pointer(db)).FpParse = (*TParse)(unsafe.Pointer(pParse)).FpOuterParse } // C documentation // // /* // ** Return the fallback token corresponding to canonical token iToken, or // ** 0 if iToken has no fallback. // */ func _sqlite3ParserFallback(tls *libc.TLS, iToken int32) (r int32) { return libc.Int32FromUint16(_yyFallback[iToken]) } /************** End of parse.c ***********************************************/ /************** Begin file tokenize.c ****************************************/ /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** An tokenizer for SQL ** ** This file contains C code that splits an SQL input string up into ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. */ /* #include "sqliteInt.h" */ /* #include */ /* Character classes for tokenizing ** ** In the sqlite3GetToken() function, a switch() on aiClass[c] is implemented ** using a lookup table, whereas a switch() directly on c uses a binary search. ** The lookup table is much faster. To maximize speed, and to ensure that ** a lookup table is used, all of the classes need to be small integers and ** all of them need to be used within the switch. */ // C documentation // // /* // ** Drop a page from the cache. There must be exactly one reference to the // ** page. This function deletes that reference, so after it returns the // ** page pointed to by p is invalid. // */ func _sqlite3PcacheDrop(tls *libc.TLS, p uintptr) { if libc.Int32FromUint16((*TPgHdr)(unsafe.Pointer(p)).Fflags)&int32(PGHDR_DIRTY) != 0 { _pcacheManageDirtyList(tls, p, uint8(PCACHE_DIRTYLIST_REMOVE)) } (*TPCache)(unsafe.Pointer((*TPgHdr)(unsafe.Pointer(p)).FpCache)).FnRefSum = (*TPCache)(unsafe.Pointer((*TPgHdr)(unsafe.Pointer(p)).FpCache)).FnRefSum - 1 (*(*func(*libc.TLS, uintptr, uintptr, int32))(unsafe.Pointer(&struct{ uintptr }{_sqlite3Config.Fpcache2.FxUnpin})))(tls, (*TPCache)(unsafe.Pointer((*TPgHdr)(unsafe.Pointer(p)).FpCache)).FpCache, (*TPgHdr)(unsafe.Pointer(p)).FpPage, int32(1)) } // C documentation // // /* // ** Try to obtain a page from the cache. // ** // ** This routine returns a pointer to an sqlite3_pcache_page object if // ** such an object is already in cache, or if a new one is created. // ** This routine returns a NULL pointer if the object was not in cache // ** and could not be created. // ** // ** The createFlags should be 0 to check for existing pages and should // ** be 3 (not 1, but 3) to try to create a new page. // ** // ** If the createFlag is 0, then NULL is always returned if the page // ** is not already in the cache. If createFlag is 1, then a new page // ** is created only if that can be done without spilling dirty pages // ** and without exceeding the cache size limit. // ** // ** The caller needs to invoke sqlite3PcacheFetchFinish() to properly // ** initialize the sqlite3_pcache_page object and convert it into a // ** PgHdr object. The sqlite3PcacheFetch() and sqlite3PcacheFetchFinish() // ** routines are split this way for performance reasons. When separated // ** they can both (usually) operate without having to push values to // ** the stack on entry and pop them back off on exit, which saves a // ** lot of pushing and popping. // */ func _sqlite3PcacheFetch(tls *libc.TLS, pCache uintptr, pgno TPgno, createFlag int32) (r uintptr) { var eCreate int32 var pRes uintptr _, _ = eCreate, pRes /* eCreate defines what to do if the page does not exist. ** 0 Do not allocate a new page. (createFlag==0) ** 1 Allocate a new page if doing so is inexpensive. ** (createFlag==1 AND bPurgeable AND pDirty) ** 2 Allocate a new page even it doing so is difficult. ** (createFlag==1 AND !(bPurgeable AND pDirty) */ eCreate = createFlag & libc.Int32FromUint8((*TPCache)(unsafe.Pointer(pCache)).FeCreate) pRes = (*(*func(*libc.TLS, uintptr, uint32, int32) uintptr)(unsafe.Pointer(&struct{ uintptr }{_sqlite3Config.Fpcache2.FxFetch})))(tls, (*TPCache)(unsafe.Pointer(pCache)).FpCache, pgno, eCreate) return pRes } // C documentation // // /* // ** If the sqlite3PcacheFetch() routine is unable to allocate a new // ** page because no clean pages are available for reuse and the cache // ** size limit has been reached, then this routine can be invoked to // ** try harder to allocate a page. This routine might invoke the stress // ** callback to spill dirty pages to the journal. It will then try to // ** allocate the new page and will only fail to allocate a new page on // ** an OOM error. // ** // ** This routine should be invoked only after sqlite3PcacheFetch() fails. // */ func _sqlite3PcacheFetchStress(tls *libc.TLS, pCache uintptr, pgno TPgno, ppPage uintptr) (r int32) { var pPg uintptr var rc, v3 int32 _, _, _ = pPg, rc, v3 if libc.Int32FromUint8((*TPCache)(unsafe.Pointer(pCache)).FeCreate) == int32(2) { return 0 } if _sqlite3PcachePagecount(tls, pCache) > (*TPCache)(unsafe.Pointer(pCache)).FszSpill { /* Find a dirty page to write-out and recycle. First try to find a ** page that does not require a journal-sync (one with PGHDR_NEED_SYNC ** cleared), but if that is not possible settle for any other ** unreferenced dirty page. ** ** If the LRU page in the dirty list that has a clear PGHDR_NEED_SYNC ** flag is currently referenced, then the following may leave pSynced ** set incorrectly (pointing to other than the LRU page with NEED_SYNC ** cleared). This is Ok, as pSynced is just an optimization. */ pPg = (*TPCache)(unsafe.Pointer(pCache)).FpSynced for { if !(pPg != 0 && ((*TPgHdr)(unsafe.Pointer(pPg)).FnRef != 0 || libc.Int32FromUint16((*TPgHdr)(unsafe.Pointer(pPg)).Fflags)&int32(PGHDR_NEED_SYNC) != 0)) { break } goto _1 _1: ; pPg = (*TPgHdr)(unsafe.Pointer(pPg)).FpDirtyPrev } (*TPCache)(unsafe.Pointer(pCache)).FpSynced = pPg if !(pPg != 0) { pPg = (*TPCache)(unsafe.Pointer(pCache)).FpDirtyTail for { if !(pPg != 0 && (*TPgHdr)(unsafe.Pointer(pPg)).FnRef != 0) { break } goto _2 _2: ; pPg = (*TPgHdr)(unsafe.Pointer(pPg)).FpDirtyPrev } } if pPg != 0 { rc = (*(*func(*libc.TLS, uintptr, uintptr) int32)(unsafe.Pointer(&struct{ uintptr }{(*TPCache)(unsafe.Pointer(pCache)).FxStress})))(tls, (*TPCache)(unsafe.Pointer(pCache)).FpStress, pPg) if rc != SQLITE_OK && rc != int32(SQLITE_BUSY) { return rc } } } **(**uintptr)(__ccgo_up(ppPage)) = (*(*func(*libc.TLS, uintptr, uint32, int32) uintptr)(unsafe.Pointer(&struct{ uintptr }{_sqlite3Config.Fpcache2.FxFetch})))(tls, (*TPCache)(unsafe.Pointer(pCache)).FpCache, pgno, int32(2)) if **(**uintptr)(__ccgo_up(ppPage)) == uintptr(0) { v3 = int32(SQLITE_NOMEM) } else { v3 = SQLITE_OK } return v3 } // C documentation // // /* // ** Change the page number of page p to newPgno. // */ func _sqlite3PcacheMove(tls *libc.TLS, p uintptr, newPgno TPgno) { var pCache, pOther, pXPage uintptr _, _, _ = pCache, pOther, pXPage pCache = (*TPgHdr)(unsafe.Pointer(p)).FpCache pOther = (*(*func(*libc.TLS, uintptr, uint32, int32) uintptr)(unsafe.Pointer(&struct{ uintptr }{_sqlite3Config.Fpcache2.FxFetch})))(tls, (*TPCache)(unsafe.Pointer(pCache)).FpCache, newPgno, 0) if pOther != 0 { pXPage = (*Tsqlite3_pcache_page)(unsafe.Pointer(pOther)).FpExtra (*TPgHdr)(unsafe.Pointer(pXPage)).FnRef = (*TPgHdr)(unsafe.Pointer(pXPage)).FnRef + 1 (*TPCache)(unsafe.Pointer(pCache)).FnRefSum = (*TPCache)(unsafe.Pointer(pCache)).FnRefSum + 1 _sqlite3PcacheDrop(tls, pXPage) } (*(*func(*libc.TLS, uintptr, uintptr, uint32, uint32))(unsafe.Pointer(&struct{ uintptr }{_sqlite3Config.Fpcache2.FxRekey})))(tls, (*TPCache)(unsafe.Pointer(pCache)).FpCache, (*TPgHdr)(unsafe.Pointer(p)).FpPage, (*TPgHdr)(unsafe.Pointer(p)).Fpgno, newPgno) (*TPgHdr)(unsafe.Pointer(p)).Fpgno = newPgno if libc.Int32FromUint16((*TPgHdr)(unsafe.Pointer(p)).Fflags)&int32(PGHDR_DIRTY) != 0 && libc.Int32FromUint16((*TPgHdr)(unsafe.Pointer(p)).Fflags)&int32(PGHDR_NEED_SYNC) != 0 { _pcacheManageDirtyList(tls, p, uint8(PCACHE_DIRTYLIST_FRONT)) } } // C documentation // // /* // ** This function is called to free superfluous dynamically allocated memory // ** held by the pager system. Memory in use by any SQLite pager allocated // ** by the current thread may be sqlite3_free()ed. // ** // ** nReq is the number of bytes of memory required. Once this much has // ** been released, the function returns. The return value is the total number // ** of bytes of memory released. // */ func _sqlite3PcacheReleaseMemory(tls *libc.TLS, nReq int32) (r int32) { var nFree int32 var p, v1 uintptr var v2 bool _, _, _, _ = nFree, p, v1, v2 nFree = 0 if _sqlite3Config.FpPage == uintptr(0) { Xsqlite3_mutex_enter(tls, (*TPGroup)(unsafe.Pointer(uintptr(unsafe.Pointer(&_pcache1_g)))).Fmutex) for { if v2 = nReq < 0 || nFree < nReq; v2 { v1 = _pcache1_g.Fgrp.Flru.FpLruPrev p = v1 } if !(v2 && v1 != uintptr(0) && libc.Int32FromUint16((*TPgHdr1)(unsafe.Pointer(p)).FisAnchor) == 0) { break } nFree = nFree + _pcache1MemSize(tls, (*TPgHdr1)(unsafe.Pointer(p)).Fpage.FpBuf) _pcache1PinPage(tls, p) _pcache1RemoveFromHash(tls, p, int32(1)) } Xsqlite3_mutex_leave(tls, (*TPGroup)(unsafe.Pointer(uintptr(unsafe.Pointer(&_pcache1_g)))).Fmutex) } return nFree } /************** End of pcache1.c *********************************************/ /************** Begin file rowset.c ******************************************/ /* ** 2008 December 3 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This module implements an object we call a "RowSet". ** ** The RowSet object is a collection of rowids. Rowids ** are inserted into the RowSet in an arbitrary order. Inserts ** can be intermixed with tests to see if a given rowid has been ** previously inserted into the RowSet. ** ** After all inserts are finished, it is possible to extract the ** elements of the RowSet in sorted order. Once this extraction ** process has started, no new elements may be inserted. ** ** Hence, the primitive operations for a RowSet are: ** ** CREATE ** INSERT ** TEST ** SMALLEST ** DESTROY ** ** The CREATE and DESTROY primitives are the constructor and destructor, ** obviously. The INSERT primitive adds a new element to the RowSet. ** TEST checks to see if an element is already in the RowSet. SMALLEST ** extracts the least value from the RowSet. ** ** The INSERT primitive might allocate additional memory. Memory is ** allocated in chunks so most INSERTs do no allocation. There is an ** upper bound on the size of allocated memory. No memory is freed ** until DESTROY. ** ** The TEST primitive includes a "batch" number. The TEST primitive ** will only see elements that were inserted before the last change ** in the batch number. In other words, if an INSERT occurs between ** two TESTs where the TESTs have the same batch number, then the ** value added by the INSERT will not be visible to the second TEST. ** The initial batch number is zero, so if the very first TEST contains ** a non-zero batch number, it will see all prior INSERTs. ** ** No INSERTs may occurs after a SMALLEST. An assertion will fail if ** that is attempted. ** ** The cost of an INSERT is roughly constant. (Sometimes new memory ** has to be allocated on an INSERT.) The cost of a TEST with a new ** batch number is O(NlogN) where N is the number of elements in the RowSet. ** The cost of a TEST using the same batch number is O(logN). The cost ** of the first SMALLEST is O(NlogN). Second and subsequent SMALLEST ** primitives are constant time. The cost of DESTROY is O(N). ** ** TEST and SMALLEST may not be used by the same RowSet. This used to ** be possible, but the feature was not used, so it was removed in order ** to simplify the code. */ /* #include "sqliteInt.h" */ /* ** Target size for allocation chunks. */ /* ** The number of rowset entries per allocation chunk. */ // C documentation // // /* // ** Check to see if zTabName is really the name of a pragma. If it is, // ** then register an eponymous virtual table for that pragma and return // ** a pointer to the Module object for the new virtual table. // */ func _sqlite3PragmaVtabRegister(tls *libc.TLS, db uintptr, zName uintptr) (r uintptr) { var pName uintptr _ = pName pName = _pragmaLocate(tls, zName+uintptr(7)) if pName == uintptr(0) { return uintptr(0) } if libc.Int32FromUint8((*TPragmaName)(unsafe.Pointer(pName)).FmPragFlg)&(libc.Int32FromInt32(PragFlg_Result0)|libc.Int32FromInt32(PragFlg_Result1)) == 0 { return uintptr(0) } return _sqlite3VtabCreateModule(tls, db, zName, uintptr(unsafe.Pointer(&_pragmaVtabModule)), pName, uintptr(0)) } /************** End of pragma.c **********************************************/ /************** Begin file prepare.c *****************************************/ /* ** 2005 May 25 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the implementation of the sqlite3_prepare() ** interface, and routines that contribute to loading the database schema ** from disk. */ /* #include "sqliteInt.h" */ // C documentation // // /* // ** Change the size of an existing memory allocation // */ func _sqlite3Realloc(tls *libc.TLS, pOld uintptr, nBytes Tu64) (r uintptr) { var nDiff, nNew, nOld int32 var nUsed, v1 Tsqlite3_int64 var pNew uintptr var v2 bool _, _, _, _, _, _, _ = nDiff, nNew, nOld, nUsed, pNew, v1, v2 if pOld == uintptr(0) { return _sqlite3Malloc(tls, nBytes) /* IMP: R-04300-56712 */ } if nBytes == uint64(0) { Xsqlite3_free(tls, pOld) /* IMP: R-26507-47431 */ return uintptr(0) } if nBytes > uint64(SQLITE_MAX_ALLOCATION_SIZE) { return uintptr(0) } nOld = _sqlite3MallocSize(tls, pOld) /* IMPLEMENTATION-OF: R-46199-30249 SQLite guarantees that the second ** argument to xRealloc is always a value returned by a prior call to ** xRoundup. */ nNew = (*(*func(*libc.TLS, int32) int32)(unsafe.Pointer(&struct{ uintptr }{_sqlite3Config.Fm.FxRoundup})))(tls, libc.Int32FromUint64(nBytes)) if nOld == nNew { pNew = pOld } else { if _sqlite3Config.FbMemstat != 0 { Xsqlite3_mutex_enter(tls, _mem0.Fmutex) _sqlite3StatusHighwater(tls, int32(SQLITE_STATUS_MALLOC_SIZE), libc.Int32FromUint64(nBytes)) nDiff = nNew - nOld if v2 = nDiff > 0; v2 { v1 = _sqlite3StatusValue(tls, SQLITE_STATUS_MEMORY_USED) nUsed = v1 } if v2 && v1 >= _mem0.FalarmThreshold-int64(nDiff) { _sqlite3MallocAlarm(tls, nDiff) if _mem0.FhardLimit > 0 && nUsed >= _mem0.FhardLimit-int64(nDiff) { Xsqlite3_mutex_leave(tls, _mem0.Fmutex) return uintptr(0) } } pNew = (*(*func(*libc.TLS, uintptr, int32) uintptr)(unsafe.Pointer(&struct{ uintptr }{_sqlite3Config.Fm.FxRealloc})))(tls, pOld, nNew) if pNew == uintptr(0) && _mem0.FalarmThreshold > 0 { _sqlite3MallocAlarm(tls, libc.Int32FromUint64(nBytes)) pNew = (*(*func(*libc.TLS, uintptr, int32) uintptr)(unsafe.Pointer(&struct{ uintptr }{_sqlite3Config.Fm.FxRealloc})))(tls, pOld, nNew) } if pNew != 0 { nNew = _sqlite3MallocSize(tls, pNew) _sqlite3StatusUp(tls, SQLITE_STATUS_MEMORY_USED, nNew-nOld) } Xsqlite3_mutex_leave(tls, _mem0.Fmutex) } else { pNew = (*(*func(*libc.TLS, uintptr, int32) uintptr)(unsafe.Pointer(&struct{ uintptr }{_sqlite3Config.Fm.FxRealloc})))(tls, pOld, nNew) } } /* IMP: R-11148-40995 */ return pNew } // C documentation // // /* // ** Initialize a SelectDest structure. // */ func _sqlite3SelectDestInit(tls *libc.TLS, pDest uintptr, eDest int32, iParm int32) { (*TSelectDest)(unsafe.Pointer(pDest)).FeDest = libc.Uint8FromInt32(eDest) (*TSelectDest)(unsafe.Pointer(pDest)).FiSDParm = iParm (*TSelectDest)(unsafe.Pointer(pDest)).FiSDParm2 = 0 (*TSelectDest)(unsafe.Pointer(pDest)).FzAffSdst = uintptr(0) (*TSelectDest)(unsafe.Pointer(pDest)).FiSdst = 0 (*TSelectDest)(unsafe.Pointer(pDest)).FnSdst = 0 } // C documentation // // /* // ** Extract the iCol-th column from the nRec-byte record in pRec. Write // ** the column value into *ppVal. If *ppVal is initially NULL then a new // ** sqlite3_value object is allocated. // ** // ** If *ppVal is initially NULL then the caller is responsible for // ** ensuring that the value written into *ppVal is eventually freed. // ** // ** If the buffer does not contain a well-formed record, this routine may // ** read several bytes past the end of the buffer. Callers must therefore // ** ensure that any buffer which may contain a corrupt record is padded // ** with at least 8 bytes of addressable memory. // */ func _sqlite3Stat4Column(tls *libc.TLS, db uintptr, pRec uintptr, nRec int32, iCol int32, ppVal uintptr) (r int32) { bp := tls.Alloc(16) defer tls.Free(16) var a, pMem, v4 uintptr var i, v1 int32 var iField Ti64 var iHdr, szField Tu32 var _ /* nHdr at bp+4 */ Tu32 var _ /* t at bp+0 */ Tu32 _, _, _, _, _, _, _, _ = a, i, iField, iHdr, pMem, szField, v1, v4 **(**Tu32)(__ccgo_up(bp)) = uint32(0) /* Next unread data byte */ szField = uint32(0) /* Column index */ a = pRec /* Typecast byte array */ pMem = **(**uintptr)(__ccgo_up(ppVal)) /* Write result into this Mem object */ if libc.Int32FromUint8(**(**Tu8)(__ccgo_up(a))) < libc.Int32FromUint8(libc.Uint8FromInt32(0x80)) { **(**Tu32)(__ccgo_up(bp + 4)) = uint32(**(**Tu8)(__ccgo_up(a))) v1 = libc.Int32FromInt32(1) } else { v1 = libc.Int32FromUint8(_sqlite3GetVarint32(tls, a, bp+4)) } iHdr = uint32(libc.Uint8FromInt32(v1)) if **(**Tu32)(__ccgo_up(bp + 4)) > libc.Uint32FromInt32(nRec) || iHdr >= **(**Tu32)(__ccgo_up(bp + 4)) { return _sqlite3CorruptError(tls, int32(87782)) } iField = libc.Int64FromUint32(**(**Tu32)(__ccgo_up(bp + 4))) i = 0 for { if !(i <= iCol) { break } if libc.Int32FromUint8(**(**Tu8)(__ccgo_up(a + uintptr(iHdr)))) < libc.Int32FromUint8(libc.Uint8FromInt32(0x80)) { **(**Tu32)(__ccgo_up(bp)) = uint32(**(**Tu8)(__ccgo_up(a + uintptr(iHdr)))) v1 = libc.Int32FromInt32(1) } else { v1 = libc.Int32FromUint8(_sqlite3GetVarint32(tls, a+uintptr(iHdr), bp)) } iHdr = iHdr + uint32(libc.Uint8FromInt32(v1)) if iHdr > **(**Tu32)(__ccgo_up(bp + 4)) { return _sqlite3CorruptError(tls, int32(87788)) } szField = _sqlite3VdbeSerialTypeLen(tls, **(**Tu32)(__ccgo_up(bp))) iField = iField + libc.Int64FromUint32(szField) goto _2 _2: ; i = i + 1 } if iField > int64(nRec) { return _sqlite3CorruptError(tls, int32(87794)) } if pMem == uintptr(0) { v4 = _sqlite3ValueNew(tls, db) **(**uintptr)(__ccgo_up(ppVal)) = v4 pMem = v4 if pMem == uintptr(0) { return int32(SQLITE_NOMEM) } } _sqlite3VdbeSerialGet(tls, a+uintptr(iField-libc.Int64FromUint32(szField)), **(**Tu32)(__ccgo_up(bp)), pMem) (*TMem)(unsafe.Pointer(pMem)).Fenc = (*Tsqlite3)(unsafe.Pointer(db)).Fenc return SQLITE_OK } func _sqlite3StrAccumEnlargeIfNeeded(tls *libc.TLS, p uintptr, N Ti64) (r int32) { if N+libc.Int64FromUint32((*TStrAccum)(unsafe.Pointer(p)).FnChar) >= libc.Int64FromUint32((*TStrAccum)(unsafe.Pointer(p)).FnAlloc) { _sqlite3StrAccumEnlarge(tls, p, N) } return libc.Int32FromUint8((*TStrAccum)(unsafe.Pointer(p)).FaccError) } // C documentation // // /* // ** Initialize a string accumulator. // ** // ** p: The accumulator to be initialized. // ** db: Pointer to a database connection. May be NULL. Lookaside // ** memory is used if not NULL. db->mallocFailed is set appropriately // ** when not NULL. // ** zBase: An initial buffer. May be NULL in which case the initial buffer // ** is malloced. // ** n: Size of zBase in bytes. If total space requirements never exceed // ** n then no memory allocations ever occur. // ** mx: Maximum number of bytes to accumulate. If mx==0 then no memory // ** allocations will ever occur. // */ func _sqlite3StrAccumInit(tls *libc.TLS, p uintptr, db uintptr, zBase uintptr, n int32, mx int32) { (*TStrAccum)(unsafe.Pointer(p)).FzText = zBase (*TStrAccum)(unsafe.Pointer(p)).Fdb = db (*TStrAccum)(unsafe.Pointer(p)).FnAlloc = libc.Uint32FromInt32(n) (*TStrAccum)(unsafe.Pointer(p)).FmxAlloc = libc.Uint32FromInt32(mx) (*TStrAccum)(unsafe.Pointer(p)).FnChar = uint32(0) (*TStrAccum)(unsafe.Pointer(p)).FaccError = uint8(0) (*TStrAccum)(unsafe.Pointer(p)).FprintfFlags = uint8(0) } // C documentation // // /* // ** Set the StrAccum object to an error mode. // */ func _sqlite3StrAccumSetError(tls *libc.TLS, p uintptr, eError Tu8) { (*TStrAccum)(unsafe.Pointer(p)).FaccError = eError if (*TStrAccum)(unsafe.Pointer(p)).FmxAlloc != 0 { Xsqlite3_str_reset(tls, p) } if libc.Int32FromUint8(eError) == int32(SQLITE_TOOBIG) { _sqlite3ErrorToParser(tls, (*TStrAccum)(unsafe.Pointer(p)).Fdb, libc.Int32FromUint8(eError)) } } func _sqlite3StrICmp(tls *libc.TLS, zLeft uintptr, zRight uintptr) (r int32) { var a, b uintptr var c, x int32 _, _, _, _ = a, b, c, x a = zLeft b = zRight for { c = libc.Int32FromUint8(**(**uint8)(__ccgo_up(a))) x = libc.Int32FromUint8(**(**uint8)(__ccgo_up(b))) if c == x { if c == 0 { break } } else { c = libc.Int32FromUint8(_sqlite3UpperToLower[c]) - libc.Int32FromUint8(_sqlite3UpperToLower[x]) if c != 0 { break } } a = a + 1 b = b + 1 goto _1 _1: } return c } // C documentation // // /* // ** Backwards Compatibility Hack: // ** // ** Historical versions of SQLite accepted strings as column names in // ** indexes and PRIMARY KEY constraints and in UNIQUE constraints. Example: // ** // ** CREATE TABLE xyz(a,b,c,d,e,PRIMARY KEY('a'),UNIQUE('b','c' COLLATE trim) // ** CREATE INDEX abc ON xyz('c','d' DESC,'e' COLLATE nocase DESC); // ** // ** This is goofy. But to preserve backwards compatibility we continue to // ** accept it. This routine does the necessary conversion. It converts // ** the expression given in its argument from a TK_STRING into a TK_ID // ** if the expression is just a TK_STRING with an optional COLLATE clause. // ** If the expression is anything other than TK_STRING, the expression is // ** unchanged. // */ func _sqlite3StringToId(tls *libc.TLS, p uintptr) { if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(p)).Fop) == int32(TK_STRING) { (*TExpr)(unsafe.Pointer(p)).Fop = uint8(TK_ID) } else { if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(p)).Fop) == int32(TK_COLLATE) && libc.Int32FromUint8((*TExpr)(unsafe.Pointer((*TExpr)(unsafe.Pointer(p)).FpLeft)).Fop) == int32(TK_STRING) { (*TExpr)(unsafe.Pointer((*TExpr)(unsafe.Pointer(p)).FpLeft)).Fop = uint8(TK_ID) } } } // C documentation // // /* // ** Convert an table column number into a index column number. That is, // ** for the column iCol in the table (as defined by the CREATE TABLE statement) // ** find the (first) offset of that column in index pIdx. Or return -1 // ** if column iCol is not used in index pIdx. // */ func _sqlite3TableColumnToIndex(tls *libc.TLS, pIdx uintptr, iCol int32) (r int32) { var i int32 var iCol16 Ti16 _, _ = i, iCol16 iCol16 = int16(iCol) i = 0 for { if !(i < libc.Int32FromUint16((*TIndex)(unsafe.Pointer(pIdx)).FnColumn)) { break } if int32(iCol16) == int32(**(**Ti16)(__ccgo_up((*TIndex)(unsafe.Pointer(pIdx)).FaiColumn + uintptr(i)*2))) { return i } goto _1 _1: ; i = i + 1 } return -int32(1) } // C documentation // // /* // ** This function returns true if main-memory should be used instead of // ** a temporary file for transient pager files and statement journals. // ** The value returned depends on the value of db->temp_store (runtime // ** parameter) and the compile time value of SQLITE_TEMP_STORE. The // ** following table describes the relationship between these two values // ** and this functions return value. // ** // ** SQLITE_TEMP_STORE db->temp_store Location of temporary database // ** ----------------- -------------- ------------------------------ // ** 0 any file (return 0) // ** 1 1 file (return 0) // ** 1 2 memory (return 1) // ** 1 0 file (return 0) // ** 2 1 file (return 0) // ** 2 2 memory (return 1) // ** 2 0 memory (return 1) // ** 3 any memory (return 1) // */ func _sqlite3TempInMemory(tls *libc.TLS, db uintptr) (r int32) { return libc.BoolInt32(libc.Int32FromUint8((*Tsqlite3)(unsafe.Pointer(db)).Ftemp_store) == int32(2)) } // C documentation // // /* // ** Generate a Token object from a string // */ func _sqlite3TokenInit(tls *libc.TLS, p uintptr, z uintptr) { (*TToken)(unsafe.Pointer(p)).Fz = z (*TToken)(unsafe.Pointer(p)).Fn = libc.Uint32FromInt32(_sqlite3Strlen30(tls, z)) } /* Convenient short-hand */ // C documentation // // /* // ** Construct a trigger step that implements a DELETE statement and return // ** a pointer to that trigger step. The parser calls this routine when it // ** sees a DELETE statement inside the body of a CREATE TRIGGER. // */ func _sqlite3TriggerDeleteStep(tls *libc.TLS, pParse uintptr, pTabList uintptr, pWhere uintptr, zStart uintptr, zEnd uintptr) (r uintptr) { var db, pTriggerStep uintptr _, _ = db, pTriggerStep db = (*TParse)(unsafe.Pointer(pParse)).Fdb pTriggerStep = _triggerStepAllocate(tls, pParse, uint8(TK_DELETE), pTabList, zStart, zEnd) if pTriggerStep != 0 { if libc.Int32FromUint8((*TParse)(unsafe.Pointer(pParse)).FeParseMode) >= int32(PARSE_MODE_RENAME) { (*TTriggerStep)(unsafe.Pointer(pTriggerStep)).FpWhere = pWhere pWhere = uintptr(0) } else { (*TTriggerStep)(unsafe.Pointer(pTriggerStep)).FpWhere = _sqlite3ExprDup(tls, db, pWhere, int32(EXPRDUP_REDUCE)) } (*TTriggerStep)(unsafe.Pointer(pTriggerStep)).Forconf = uint8(OE_Default) } _sqlite3ExprDelete(tls, db, pWhere) return pTriggerStep } // C documentation // // /* // ** Build a trigger step out of an INSERT statement. Return a pointer // ** to the new trigger step. // ** // ** The parser calls this routine when it sees an INSERT inside the // ** body of a trigger. // */ func _sqlite3TriggerInsertStep(tls *libc.TLS, pParse uintptr, pTabList uintptr, pColumn uintptr, pSelect uintptr, orconf Tu8, pUpsert uintptr, zStart uintptr, zEnd uintptr) (r uintptr) { var db, pTriggerStep uintptr _, _ = db, pTriggerStep db = (*TParse)(unsafe.Pointer(pParse)).Fdb pTriggerStep = _triggerStepAllocate(tls, pParse, uint8(TK_INSERT), pTabList, zStart, zEnd) if pTriggerStep != 0 { if libc.Int32FromUint8((*TParse)(unsafe.Pointer(pParse)).FeParseMode) >= int32(PARSE_MODE_RENAME) { (*TTriggerStep)(unsafe.Pointer(pTriggerStep)).FpSelect = pSelect pSelect = uintptr(0) } else { (*TTriggerStep)(unsafe.Pointer(pTriggerStep)).FpSelect = _sqlite3SelectDup(tls, db, pSelect, int32(EXPRDUP_REDUCE)) } (*TTriggerStep)(unsafe.Pointer(pTriggerStep)).FpIdList = pColumn (*TTriggerStep)(unsafe.Pointer(pTriggerStep)).FpUpsert = pUpsert (*TTriggerStep)(unsafe.Pointer(pTriggerStep)).Forconf = orconf if pUpsert != 0 { _sqlite3HasExplicitNulls(tls, pParse, (*TUpsert)(unsafe.Pointer(pUpsert)).FpUpsertTarget) } } else { _sqlite3IdListDelete(tls, db, pColumn) _sqlite3UpsertDelete(tls, db, pUpsert) } _sqlite3SelectDelete(tls, db, pSelect) return pTriggerStep } // C documentation // // /* // ** Construct a trigger step that implements an UPDATE statement and return // ** a pointer to that trigger step. The parser calls this routine when it // ** sees an UPDATE statement inside the body of a CREATE TRIGGER. // */ func _sqlite3TriggerUpdateStep(tls *libc.TLS, pParse uintptr, pTabList uintptr, pFrom uintptr, pEList uintptr, pWhere uintptr, orconf Tu8, zStart uintptr, zEnd uintptr) (r uintptr) { bp := tls.Alloc(16) defer tls.Free(16) var db, pFromDup, pSub, pTriggerStep uintptr var _ /* as at bp+0 */ TToken _, _, _, _ = db, pFromDup, pSub, pTriggerStep db = (*TParse)(unsafe.Pointer(pParse)).Fdb pTriggerStep = _triggerStepAllocate(tls, pParse, uint8(TK_UPDATE), pTabList, zStart, zEnd) if pTriggerStep != 0 { pFromDup = uintptr(0) if libc.Int32FromUint8((*TParse)(unsafe.Pointer(pParse)).FeParseMode) >= int32(PARSE_MODE_RENAME) { (*TTriggerStep)(unsafe.Pointer(pTriggerStep)).FpExprList = pEList (*TTriggerStep)(unsafe.Pointer(pTriggerStep)).FpWhere = pWhere pFromDup = pFrom pEList = uintptr(0) pWhere = uintptr(0) pFrom = uintptr(0) } else { (*TTriggerStep)(unsafe.Pointer(pTriggerStep)).FpExprList = _sqlite3ExprListDup(tls, db, pEList, int32(EXPRDUP_REDUCE)) (*TTriggerStep)(unsafe.Pointer(pTriggerStep)).FpWhere = _sqlite3ExprDup(tls, db, pWhere, int32(EXPRDUP_REDUCE)) pFromDup = _sqlite3SrcListDup(tls, db, pFrom, int32(EXPRDUP_REDUCE)) } (*TTriggerStep)(unsafe.Pointer(pTriggerStep)).Forconf = orconf if pFromDup != 0 && !(libc.Int32FromUint8((*TParse)(unsafe.Pointer(pParse)).FeParseMode) >= libc.Int32FromInt32(PARSE_MODE_RENAME)) { **(**TToken)(__ccgo_up(bp)) = TToken{} pSub = _sqlite3SelectNew(tls, pParse, uintptr(0), pFromDup, uintptr(0), uintptr(0), uintptr(0), uintptr(0), uint32(SF_NestedFrom), uintptr(0)) pFromDup = _sqlite3SrcListAppendFromTerm(tls, pParse, uintptr(0), uintptr(0), uintptr(0), bp, pSub, uintptr(0)) } if pFromDup != 0 && (*TTriggerStep)(unsafe.Pointer(pTriggerStep)).FpSrc != 0 { (*TTriggerStep)(unsafe.Pointer(pTriggerStep)).FpSrc = _sqlite3SrcListAppendList(tls, pParse, (*TTriggerStep)(unsafe.Pointer(pTriggerStep)).FpSrc, pFromDup) } else { _sqlite3SrcListDelete(tls, db, pFromDup) } } _sqlite3ExprListDelete(tls, db, pEList) _sqlite3ExprDelete(tls, db, pWhere) _sqlite3SrcListDelete(tls, db, pFrom) return pTriggerStep } // C documentation // // /* // ** pZ is a UTF-8 encoded unicode string. If nByte is less than zero, // ** return the number of unicode characters in pZ up to (but not including) // ** the first 0x00 byte. If nByte is not less than zero, return the // ** number of unicode characters in the first nByte of pZ (or up to // ** the first 0x00, whichever comes first). // */ func _sqlite3Utf8CharLen(tls *libc.TLS, zIn uintptr, nByte int32) (r1 int32) { var r int32 var z, zTerm, v1 uintptr _, _, _, _ = r, z, zTerm, v1 r = 0 z = zIn if nByte >= 0 { zTerm = z + uintptr(nByte) } else { zTerm = uintptr(-libc.Int32FromInt32(1)) } for libc.Int32FromUint8(**(**Tu8)(__ccgo_up(z))) != 0 && z < zTerm { v1 = z z = z + 1 if libc.Int32FromUint8(**(**Tu8)(__ccgo_up(v1))) >= int32(0xc0) { for libc.Int32FromUint8(**(**Tu8)(__ccgo_up(z)))&int32(0xc0) == int32(0x80) { z = z + 1 } } r = r + 1 } return r } /* This test function is not currently used by the automated test-suite. ** Hence it is only available in debug builds. */ // C documentation // // /* // ** Translate a single UTF-8 character. Return the unicode value. // ** // ** During translation, assume that the byte that zTerm points // ** is a 0x00. // ** // ** Write a pointer to the next unread byte back into *pzNext. // ** // ** Notes On Invalid UTF-8: // ** // ** * This routine never allows a 7-bit character (0x00 through 0x7f) to // ** be encoded as a multi-byte character. Any multi-byte character that // ** attempts to encode a value between 0x00 and 0x7f is rendered as 0xfffd. // ** // ** * This routine never allows a UTF16 surrogate value to be encoded. // ** If a multi-byte character attempts to encode a value between // ** 0xd800 and 0xe000 then it is rendered as 0xfffd. // ** // ** * Bytes in the range of 0x80 through 0xbf which occur as the first // ** byte of a character are interpreted as single-byte characters // ** and rendered as themselves even though they are technically // ** invalid characters. // ** // ** * This routine accepts over-length UTF8 encodings // ** for unicode values 0x80 and greater. It does not change over-length // ** encodings to 0xfffd as some systems recommend. // */ func _sqlite3Utf8Read(tls *libc.TLS, pz uintptr) (r Tu32) { var c uint32 var v1, v2 uintptr _, _, _ = c, v1, v2 /* Same as READ_UTF8() above but without the zTerm parameter. ** For this routine, we assume the UTF8 string is always zero-terminated. */ v2 = pz v1 = *(*uintptr)(unsafe.Pointer(v2)) *(*uintptr)(unsafe.Pointer(v2)) = *(*uintptr)(unsafe.Pointer(v2)) + 1 c = uint32(**(**uint8)(__ccgo_up(v1))) if c >= uint32(0xc0) { c = uint32(_sqlite3Utf8Trans1[c-uint32(0xc0)]) for libc.Int32FromUint8(**(**uint8)(__ccgo_up(**(**uintptr)(__ccgo_up(pz)))))&int32(0xc0) == int32(0x80) { v2 = pz v1 = *(*uintptr)(unsafe.Pointer(v2)) *(*uintptr)(unsafe.Pointer(v2)) = *(*uintptr)(unsafe.Pointer(v2)) + 1 c = c<= uint32(0xc0) { c = uint32(_sqlite3Utf8Trans1[c-uint32(0xc0)]) if n > int32(4) { n = int32(4) } for i < n && libc.Int32FromUint8(**(**Tu8)(__ccgo_up(z + uintptr(i))))&int32(0xc0) == int32(0x80) { c = c<= int32(VDBE_READY_STATE) { rc = _sqlite3VdbeReset(tls, p) } _sqlite3VdbeDelete(tls, p) return rc } func _sqlite3VdbeIntValue(tls *libc.TLS, pMem uintptr) (r Ti64) { var flags int32 _ = flags flags = libc.Int32FromUint16((*TMem)(unsafe.Pointer(pMem)).Fflags) if flags&(libc.Int32FromInt32(MEM_Int)|libc.Int32FromInt32(MEM_IntReal)) != 0 { return *(*Ti64)(unsafe.Pointer(pMem)) } else { if flags&int32(MEM_Real) != 0 { return _sqlite3RealToI64(tls, *(*float64)(unsafe.Pointer(pMem))) } else { if flags&(libc.Int32FromInt32(MEM_Str)|libc.Int32FromInt32(MEM_Blob)) != 0 && (*TMem)(unsafe.Pointer(pMem)).Fz != uintptr(0) { return _memIntValue(tls, pMem) } else { return 0 } } } return r } // C documentation // // /* // ** The MEM structure is already a MEM_Real or MEM_IntReal. Try to // ** make it a MEM_Int if we can. // */ func _sqlite3VdbeIntegerAffinity(tls *libc.TLS, pMem uintptr) { var ix Ti64 _ = ix if libc.Int32FromUint16((*TMem)(unsafe.Pointer(pMem)).Fflags)&int32(MEM_IntReal) != 0 { (*TMem)(unsafe.Pointer(pMem)).Fflags = libc.Uint16FromInt32(libc.Int32FromUint16((*TMem)(unsafe.Pointer(pMem)).Fflags) & ^(libc.Int32FromInt32(MEM_TypeMask)|libc.Int32FromInt32(MEM_Zero)) | int32(MEM_Int)) } else { ix = _sqlite3RealToI64(tls, *(*float64)(unsafe.Pointer(pMem))) /* Only mark the value as an integer if ** ** (1) the round-trip conversion real->int->real is a no-op, and ** (2) The integer is neither the largest nor the smallest ** possible integer (ticket #3922) ** ** The second and third terms in the following conditional enforces ** the second condition under the assumption that addition overflow causes ** values to wrap around. */ if *(*float64)(unsafe.Pointer(pMem)) == float64(ix) && ix > int64(-libc.Int32FromInt32(1))-(libc.Int64FromUint32(0xffffffff)|libc.Int64FromInt32(0x7fffffff)<= 0 { if (*Tsqlite3)(unsafe.Pointer(db)).FpErr != 0 || (*TVdbe)(unsafe.Pointer(p)).FzErrMsg != 0 { _sqlite3VdbeTransferError(tls, p) } else { (*Tsqlite3)(unsafe.Pointer(db)).FerrCode = (*TVdbe)(unsafe.Pointer(p)).Frc } } /* Reset register contents and reclaim error message memory. */ if (*TVdbe)(unsafe.Pointer(p)).FzErrMsg != 0 { _sqlite3DbFree(tls, db, (*TVdbe)(unsafe.Pointer(p)).FzErrMsg) (*TVdbe)(unsafe.Pointer(p)).FzErrMsg = uintptr(0) } (*TVdbe)(unsafe.Pointer(p)).FpResultRow = uintptr(0) /* Save profiling information from this VDBE run. */ return (*TVdbe)(unsafe.Pointer(p)).Frc & (*Tsqlite3)(unsafe.Pointer(db)).FerrMask } func _sqlite3VdbeSerialGet(tls *libc.TLS, buf uintptr, serial_type Tu32, pMem uintptr) { switch serial_type { case uint32(10): /* Internal use only: NULL with virtual table ** UPDATE no-change flag set */ (*TMem)(unsafe.Pointer(pMem)).Fflags = libc.Uint16FromInt32(libc.Int32FromInt32(MEM_Null) | libc.Int32FromInt32(MEM_Zero)) (*TMem)(unsafe.Pointer(pMem)).Fn = 0 *(*int32)(unsafe.Pointer(&(*TMem)(unsafe.Pointer(pMem)).Fu)) = 0 return case uint32(11): /* Reserved for future use */ fallthrough case uint32(0): /* Null */ /* EVIDENCE-OF: R-24078-09375 Value is a NULL. */ (*TMem)(unsafe.Pointer(pMem)).Fflags = uint16(MEM_Null) return case uint32(1): /* EVIDENCE-OF: R-44885-25196 Value is an 8-bit twos-complement ** integer. */ *(*Ti64)(unsafe.Pointer(pMem)) = int64(libc.Int8FromUint8(**(**uint8)(__ccgo_up(buf)))) (*TMem)(unsafe.Pointer(pMem)).Fflags = uint16(MEM_Int) return case uint32(2): /* 2-byte signed integer */ /* EVIDENCE-OF: R-49794-35026 Value is a big-endian 16-bit ** twos-complement integer. */ *(*Ti64)(unsafe.Pointer(pMem)) = int64(libc.Int32FromInt32(256)*int32(libc.Int8FromUint8(**(**uint8)(__ccgo_up(buf)))) | libc.Int32FromUint8(**(**uint8)(__ccgo_up(buf + 1)))) (*TMem)(unsafe.Pointer(pMem)).Fflags = uint16(MEM_Int) return case uint32(3): /* 3-byte signed integer */ /* EVIDENCE-OF: R-37839-54301 Value is a big-endian 24-bit ** twos-complement integer. */ *(*Ti64)(unsafe.Pointer(pMem)) = int64(libc.Int32FromInt32(65536)*int32(libc.Int8FromUint8(**(**uint8)(__ccgo_up(buf)))) | libc.Int32FromUint8(**(**uint8)(__ccgo_up(buf + 1)))< 0 { return 0 } return _viewGetColumnNames(tls, pParse, pTable) } // C documentation // // /* Return the value to pass to a sqlite3_wal_hook callback, the // ** number of frames in the WAL at the point of the last commit since // ** sqlite3WalCallback() was called. If no commits have occurred since // ** the last call, then return 0. // */ func _sqlite3WalCallback(tls *libc.TLS, pWal uintptr) (r int32) { var ret Tu32 _ = ret ret = uint32(0) if pWal != 0 { ret = (*TWal)(unsafe.Pointer(pWal)).FiCallback (*TWal)(unsafe.Pointer(pWal)).FiCallback = uint32(0) } return libc.Int32FromUint32(ret) } // C documentation // // /* // ** Close a connection to a log file. // */ func _sqlite3WalClose(tls *libc.TLS, pWal uintptr, db uintptr, sync_flags int32, nBuf int32, zBuf uintptr) (r int32) { bp := tls.Alloc(16) defer tls.Free(16) var isDelete, rc, v1 int32 var v2 bool var _ /* bPersist at bp+0 */ int32 _, _, _, _ = isDelete, rc, v1, v2 rc = SQLITE_OK if pWal != 0 { isDelete = 0 /* True to unlink wal and wal-index files */ /* If an EXCLUSIVE lock can be obtained on the database file (using the ** ordinary, rollback-mode locking methods, this guarantees that the ** connection associated with this log file is the only connection to ** the database. In this case checkpoint the database and unlink both ** the wal and wal-index files. ** ** The EXCLUSIVE lock is not released before returning. */ if v2 = zBuf != uintptr(0); v2 { v1 = _sqlite3OsLock(tls, (*TWal)(unsafe.Pointer(pWal)).FpDbFd, int32(SQLITE_LOCK_EXCLUSIVE)) rc = v1 } if v2 && SQLITE_OK == v1 { if libc.Int32FromUint8((*TWal)(unsafe.Pointer(pWal)).FexclusiveMode) == WAL_NORMAL_MODE { (*TWal)(unsafe.Pointer(pWal)).FexclusiveMode = uint8(WAL_EXCLUSIVE_MODE) } rc = _sqlite3WalCheckpoint(tls, pWal, db, SQLITE_CHECKPOINT_PASSIVE, uintptr(0), uintptr(0), sync_flags, nBuf, zBuf, uintptr(0), uintptr(0)) if rc == SQLITE_OK { **(**int32)(__ccgo_up(bp)) = -int32(1) _sqlite3OsFileControlHint(tls, (*TWal)(unsafe.Pointer(pWal)).FpDbFd, int32(SQLITE_FCNTL_PERSIST_WAL), bp) if **(**int32)(__ccgo_up(bp)) != int32(1) { /* Try to delete the WAL file if the checkpoint completed and ** fsynced (rc==SQLITE_OK) and if we are not in persistent-wal ** mode (!bPersist) */ isDelete = int32(1) } else { if (*TWal)(unsafe.Pointer(pWal)).FmxWalSize >= 0 { /* Try to truncate the WAL file to zero bytes if the checkpoint ** completed and fsynced (rc==SQLITE_OK) and we are in persistent ** WAL mode (bPersist) and if the PRAGMA journal_size_limit is a ** non-negative value (pWal->mxWalSize>=0). Note that we truncate ** to zero bytes as truncating to the journal_size_limit might ** leave a corrupt WAL file on disk. */ _walLimitSize(tls, pWal, 0) } } } } _walIndexClose(tls, pWal, isDelete) _sqlite3OsClose(tls, (*TWal)(unsafe.Pointer(pWal)).FpWalFd) if isDelete != 0 { _sqlite3BeginBenignMalloc(tls) _sqlite3OsDelete(tls, (*TWal)(unsafe.Pointer(pWal)).FpVfs, (*TWal)(unsafe.Pointer(pWal)).FzWalName, 0) _sqlite3EndBenignMalloc(tls) } Xsqlite3_free(tls, (*TWal)(unsafe.Pointer(pWal)).FapWiData) Xsqlite3_free(tls, pWal) } return rc } // C documentation // // /* // ** This function is called to change the WAL subsystem into or out // ** of locking_mode=EXCLUSIVE. // ** // ** If op is zero, then attempt to change from locking_mode=EXCLUSIVE // ** into locking_mode=NORMAL. This means that we must acquire a lock // ** on the pWal->readLock byte. If the WAL is already in locking_mode=NORMAL // ** or if the acquisition of the lock fails, then return 0. If the // ** transition out of exclusive-mode is successful, return 1. This // ** operation must occur while the pager is still holding the exclusive // ** lock on the main database file. // ** // ** If op is one, then change from locking_mode=NORMAL into // ** locking_mode=EXCLUSIVE. This means that the pWal->readLock must // ** be released. Return 1 if the transition is made and 0 if the // ** WAL is already in exclusive-locking mode - meaning that this // ** routine is a no-op. The pager must already hold the exclusive lock // ** on the main database file before invoking this operation. // ** // ** If op is negative, then do a dry-run of the op==1 case but do // ** not actually change anything. The pager uses this to see if it // ** should acquire the database exclusive lock prior to invoking // ** the op==1 case. // */ func _sqlite3WalExclusiveMode(tls *libc.TLS, pWal uintptr, op int32) (r int32) { var rc int32 _ = rc /* pWal->readLock is usually set, but might be -1 if there was a ** prior error while attempting to acquire are read-lock. This cannot ** happen if the connection is actually in exclusive mode (as no xShmLock ** locks are taken in this case). Nor should the pager attempt to ** upgrade to exclusive-mode following such an error. */ if op == 0 { if libc.Int32FromUint8((*TWal)(unsafe.Pointer(pWal)).FexclusiveMode) != WAL_NORMAL_MODE { (*TWal)(unsafe.Pointer(pWal)).FexclusiveMode = uint8(WAL_NORMAL_MODE) if _walLockShared(tls, pWal, int32(3)+int32((*TWal)(unsafe.Pointer(pWal)).FreadLock)) != SQLITE_OK { (*TWal)(unsafe.Pointer(pWal)).FexclusiveMode = uint8(WAL_EXCLUSIVE_MODE) } rc = libc.BoolInt32(libc.Int32FromUint8((*TWal)(unsafe.Pointer(pWal)).FexclusiveMode) == WAL_NORMAL_MODE) } else { /* Already in locking_mode=NORMAL */ rc = 0 } } else { if op > 0 { _walUnlockShared(tls, pWal, int32(3)+int32((*TWal)(unsafe.Pointer(pWal)).FreadLock)) (*TWal)(unsafe.Pointer(pWal)).FexclusiveMode = uint8(WAL_EXCLUSIVE_MODE) rc = int32(1) } else { rc = libc.BoolInt32(libc.Int32FromUint8((*TWal)(unsafe.Pointer(pWal)).FexclusiveMode) == WAL_NORMAL_MODE) } } return rc } // C documentation // // /* // ** Return true if the argument is non-NULL and the WAL module is using // ** heap-memory for the wal-index. Otherwise, if the argument is NULL or the // ** WAL module is using shared-memory, return false. // */ func _sqlite3WalHeapMemory(tls *libc.TLS, pWal uintptr) (r int32) { return libc.BoolInt32(pWal != 0 && libc.Int32FromUint8((*TWal)(unsafe.Pointer(pWal)).FexclusiveMode) == int32(WAL_HEAPMEMORY_MODE)) } // C documentation // // /* // ** Read the contents of frame iRead from the wal file into buffer pOut // ** (which is nOut bytes in size). Return SQLITE_OK if successful, or an // ** error code otherwise. // */ func _sqlite3WalReadFrame(tls *libc.TLS, pWal uintptr, iRead Tu32, nOut int32, pOut uintptr) (r int32) { var iOffset Ti64 var sz, v1 int32 _, _, _ = iOffset, sz, v1 sz = libc.Int32FromUint16((*TWal)(unsafe.Pointer(pWal)).Fhdr.FszPage) sz = sz&int32(0xfe00) + sz&int32(0x0001)< sz { v1 = sz } else { v1 = nOut } return _sqlite3OsRead(tls, (*TWal)(unsafe.Pointer(pWal)).FpWalFd, pOut, v1, iOffset) } // C documentation // // /* // ** Attempt to reduce the value of the WalCkptInfo.nBackfillAttempted // ** variable so that older snapshots can be accessed. To do this, loop // ** through all wal frames from nBackfillAttempted to (nBackfill+1), // ** comparing their content to the corresponding page with the database // ** file, if any. Set nBackfillAttempted to the frame number of the // ** first frame for which the wal file content matches the db file. // ** // ** This is only really safe if the file-system is such that any page // ** writes made by earlier checkpointers were atomic operations, which // ** is not always true. It is also possible that nBackfillAttempted // ** may be left set to a value larger than expected, if a wal frame // ** contains content that duplicate of an earlier version of the same // ** page. // ** // ** SQLITE_OK is returned if successful, or an SQLite error code if an // ** error occurs. It is not an error if nBackfillAttempted cannot be // ** decreased at all. // */ func _sqlite3WalSnapshotRecover(tls *libc.TLS, pWal uintptr) (r int32) { var pBuf1, pBuf2 uintptr var rc int32 _, _, _ = pBuf1, pBuf2, rc rc = _walLockExclusive(tls, pWal, int32(WAL_CKPT_LOCK), int32(1)) if rc == SQLITE_OK { pBuf1 = Xsqlite3_malloc(tls, libc.Int32FromUint32((*TWal)(unsafe.Pointer(pWal)).FszPage)) pBuf2 = Xsqlite3_malloc(tls, libc.Int32FromUint32((*TWal)(unsafe.Pointer(pWal)).FszPage)) if pBuf1 == uintptr(0) || pBuf2 == uintptr(0) { rc = int32(SQLITE_NOMEM) } else { (*TWal)(unsafe.Pointer(pWal)).FckptLock = uint8(1) rc = _walSnapshotRecover(tls, pWal, pBuf1, pBuf2) (*TWal)(unsafe.Pointer(pWal)).FckptLock = uint8(0) } Xsqlite3_free(tls, pBuf1) Xsqlite3_free(tls, pBuf2) _walUnlockExclusive(tls, pWal, int32(WAL_CKPT_LOCK), int32(1)) } return rc } // C documentation // // /* // ** Walk all expressions associated with SELECT statement p. Do // ** not invoke the SELECT callback on p, but do (of course) invoke // ** any expr callbacks and SELECT callbacks that come from subqueries. // ** Return WRC_Abort or WRC_Continue. // */ func _sqlite3WalkSelectExpr(tls *libc.TLS, pWalker uintptr, p uintptr) (r int32) { var pParse, v1 uintptr var rc int32 var v2 bool _, _, _, _ = pParse, rc, v1, v2 if _sqlite3WalkExprList(tls, pWalker, (*TSelect)(unsafe.Pointer(p)).FpEList) != 0 { return int32(WRC_Abort) } if _sqlite3WalkExpr(tls, pWalker, (*TSelect)(unsafe.Pointer(p)).FpWhere) != 0 { return int32(WRC_Abort) } if _sqlite3WalkExprList(tls, pWalker, (*TSelect)(unsafe.Pointer(p)).FpGroupBy) != 0 { return int32(WRC_Abort) } if _sqlite3WalkExpr(tls, pWalker, (*TSelect)(unsafe.Pointer(p)).FpHaving) != 0 { return int32(WRC_Abort) } if _sqlite3WalkExprList(tls, pWalker, (*TSelect)(unsafe.Pointer(p)).FpOrderBy) != 0 { return int32(WRC_Abort) } if _sqlite3WalkExpr(tls, pWalker, (*TSelect)(unsafe.Pointer(p)).FpLimit) != 0 { return int32(WRC_Abort) } if (*TSelect)(unsafe.Pointer(p)).FpWinDefn != 0 { if v2 = (*TWalker)(unsafe.Pointer(pWalker)).FxSelectCallback2 == __ccgo_fp(_sqlite3WalkWinDefnDummyCallback); !v2 { v1 = (*TWalker)(unsafe.Pointer(pWalker)).FpParse pParse = v1 } if v2 || v1 != uintptr(0) && libc.Int32FromUint8((*TParse)(unsafe.Pointer(pParse)).FeParseMode) >= int32(PARSE_MODE_RENAME) || (*TWalker)(unsafe.Pointer(pWalker)).FxSelectCallback2 == __ccgo_fp(_sqlite3SelectPopWith) { /* The following may return WRC_Abort if there are unresolvable ** symbols (e.g. a table that does not exist) in a window definition. */ rc = _walkWindowList(tls, pWalker, (*TSelect)(unsafe.Pointer(p)).FpWinDefn, 0) return rc } } return WRC_Continue } // C documentation // // /* // ** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN // ** command, or if stmt_scanstatus_v2() stats are enabled, or if SQLITE_DEBUG // ** was defined at compile-time. If it is not a no-op, a single OP_Explain // ** opcode is added to the output to describe the table scan strategy in pLevel. // ** // ** If an OP_Explain opcode is added to the VM, its address is returned. // ** Otherwise, if no OP_Explain is coded, zero is returned. // */ func _sqlite3WhereExplainOneScan(tls *libc.TLS, pParse uintptr, pTabList uintptr, pLevel uintptr, wctrlFlags Tu16) (r int32) { var addr, ret int32 var v, v1 uintptr _, _, _, _ = addr, ret, v, v1 ret = 0 if (*TParse)(unsafe.Pointer(pParse)).FpToplevel != 0 { v1 = (*TParse)(unsafe.Pointer(pParse)).FpToplevel } else { v1 = pParse } if libc.Int32FromUint8((*TParse)(unsafe.Pointer(v1)).Fexplain) == int32(2) || libc.Bool(0 != 0) { if (*TWhereLoop)(unsafe.Pointer((*TWhereLevel)(unsafe.Pointer(pLevel)).FpWLoop)).FwsFlags&uint32(WHERE_MULTI_OR) == uint32(0) && libc.Int32FromUint16(wctrlFlags)&int32(WHERE_OR_SUBCLAUSE) == 0 { v = (*TParse)(unsafe.Pointer(pParse)).FpVdbe addr = _sqlite3VdbeCurrentAddr(tls, v) ret = _sqlite3VdbeAddOp3(tls, v, int32(OP_Explain), addr, (*TParse)(unsafe.Pointer(pParse)).FaddrExplain, int32((*TWhereLoop)(unsafe.Pointer((*TWhereLevel)(unsafe.Pointer(pLevel)).FpWLoop)).FrRun)) _sqlite3WhereAddExplainText(tls, pParse, addr, pTabList, pLevel, wctrlFlags) } } return ret } func _sqlite3WhereExprUsageNN(tls *libc.TLS, pMaskSet uintptr, p uintptr) (r TBitmask) { if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(p)).Fop) == int32(TK_COLUMN) && !((*TExpr)(unsafe.Pointer(p)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_FixedCol)) != libc.Uint32FromInt32(0)) { return _sqlite3WhereGetMask(tls, pMaskSet, (*TExpr)(unsafe.Pointer(p)).FiTable) } else { if (*TExpr)(unsafe.Pointer(p)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_TokenOnly)|libc.Int32FromInt32(EP_Leaf)) != uint32(0) { return uint64(0) } } return _sqlite3WhereExprUsageFull(tls, pMaskSet, p) } // C documentation // // /* // ** Return one of the WHERE_DISTINCT_xxxxx values to indicate how this // ** WHERE clause returns outputs for DISTINCT processing. // */ func _sqlite3WhereIsDistinct(tls *libc.TLS, pWInfo uintptr) (r int32) { return libc.Int32FromUint8((*TWhereInfo)(unsafe.Pointer(pWInfo)).FeDistinct) } // C documentation // // /* // ** This routine identifies subexpressions in the WHERE clause where // ** each subexpression is separated by the AND operator or some other // ** operator specified in the op parameter. The WhereClause structure // ** is filled with pointers to subexpressions. For example: // ** // ** WHERE a=='hello' AND coalesce(b,11)<10 AND (c+12!=d OR c==22) // ** \________/ \_______________/ \________________/ // ** slot[0] slot[1] slot[2] // ** // ** The original WHERE clause in pExpr is unaltered. All this routine // ** does is make slot[] entries point to substructure within pExpr. // ** // ** In the previous sentence and in the diagram, "slot[]" refers to // ** the WhereClause.a[] array. The slot[] array grows as needed to contain // ** all terms of the WHERE clause. // */ func _sqlite3WhereSplit(tls *libc.TLS, pWC uintptr, pExpr uintptr, op Tu8) { var pE2 uintptr _ = pE2 pE2 = _sqlite3ExprSkipCollateAndLikely(tls, pExpr) (*TWhereClause)(unsafe.Pointer(pWC)).Fop = op if pE2 == uintptr(0) { return } if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pE2)).Fop) != libc.Int32FromUint8(op) { _whereClauseInsert(tls, pWC, pExpr, uint16(0)) } else { _sqlite3WhereSplit(tls, pWC, (*TExpr)(unsafe.Pointer(pE2)).FpLeft, op) _sqlite3WhereSplit(tls, pWC, (*TExpr)(unsafe.Pointer(pE2)).FpRight, op) } } // C documentation // // /* // ** Return 0 if the two window objects are identical, 1 if they are // ** different, or 2 if it cannot be determined if the objects are identical // ** or not. Identical window objects can be processed in a single scan. // */ func _sqlite3WindowCompare(tls *libc.TLS, pParse uintptr, p1 uintptr, p2 uintptr, bFilter int32) (r int32) { var res, v1 int32 _, _ = res, v1 if p1 == uintptr(0) || p2 == uintptr(0) { return int32(1) } if libc.Int32FromUint8((*TWindow)(unsafe.Pointer(p1)).FeFrmType) != libc.Int32FromUint8((*TWindow)(unsafe.Pointer(p2)).FeFrmType) { return int32(1) } if libc.Int32FromUint8((*TWindow)(unsafe.Pointer(p1)).FeStart) != libc.Int32FromUint8((*TWindow)(unsafe.Pointer(p2)).FeStart) { return int32(1) } if libc.Int32FromUint8((*TWindow)(unsafe.Pointer(p1)).FeEnd) != libc.Int32FromUint8((*TWindow)(unsafe.Pointer(p2)).FeEnd) { return int32(1) } if libc.Int32FromUint8((*TWindow)(unsafe.Pointer(p1)).FeExclude) != libc.Int32FromUint8((*TWindow)(unsafe.Pointer(p2)).FeExclude) { return int32(1) } if _sqlite3ExprCompare(tls, pParse, (*TWindow)(unsafe.Pointer(p1)).FpStart, (*TWindow)(unsafe.Pointer(p2)).FpStart, -int32(1)) != 0 { return int32(1) } if _sqlite3ExprCompare(tls, pParse, (*TWindow)(unsafe.Pointer(p1)).FpEnd, (*TWindow)(unsafe.Pointer(p2)).FpEnd, -int32(1)) != 0 { return int32(1) } v1 = _sqlite3ExprListCompare(tls, (*TWindow)(unsafe.Pointer(p1)).FpPartition, (*TWindow)(unsafe.Pointer(p2)).FpPartition, -int32(1)) res = v1 if v1 != 0 { return res } v1 = _sqlite3ExprListCompare(tls, (*TWindow)(unsafe.Pointer(p1)).FpOrderBy, (*TWindow)(unsafe.Pointer(p2)).FpOrderBy, -int32(1)) res = v1 if v1 != 0 { return res } if bFilter != 0 { v1 = _sqlite3ExprCompare(tls, pParse, (*TWindow)(unsafe.Pointer(p1)).FpFilter, (*TWindow)(unsafe.Pointer(p2)).FpFilter, -int32(1)) res = v1 if v1 != 0 { return res } } return 0 } // C documentation // // /* // ** When rewriting a query, if the new subquery in the FROM clause // ** contains TK_AGG_FUNCTION nodes that refer to an outer query, // ** then we have to increase the Expr->op2 values of those nodes // ** due to the extra subquery layer that was added. // ** // ** See also the incrAggDepth() routine in resolve.c // */ func _sqlite3WindowExtraAggFuncDepth(tls *libc.TLS, pWalker uintptr, pExpr uintptr) (r int32) { if libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop) == int32(TK_AGG_FUNCTION) && libc.Int32FromUint8((*TExpr)(unsafe.Pointer(pExpr)).Fop2) >= (*TWalker)(unsafe.Pointer(pWalker)).FwalkerDepth { (*TExpr)(unsafe.Pointer(pExpr)).Fop2 = (*TExpr)(unsafe.Pointer(pExpr)).Fop2 + 1 } return WRC_Continue } // C documentation // // /* // ** The argument expression is an PRECEDING or FOLLOWING offset. The // ** value should be a non-negative integer. If the value is not a // ** constant, change it to NULL. The fact that it is then a non-negative // ** integer will be caught later. But it is important not to leave // ** variable values in the expression tree. // */ func _sqlite3WindowOffsetExpr(tls *libc.TLS, pParse uintptr, pExpr uintptr) (r uintptr) { if 0 == _sqlite3ExprIsConstant(tls, uintptr(0), pExpr) { if libc.Int32FromUint8((*TParse)(unsafe.Pointer(pParse)).FeParseMode) >= int32(PARSE_MODE_RENAME) { _sqlite3RenameExprUnmap(tls, pParse, pExpr) } _sqlite3ExprDelete(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, pExpr) pExpr = _sqlite3ExprAlloc(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, int32(TK_NULL), uintptr(0), 0) } return pExpr } // C documentation // // /* // ** True if PRAGMA writable_schema is ON // */ func _sqlite3WritableSchema(tls *libc.TLS, db uintptr) (r int32) { return libc.BoolInt32((*Tsqlite3)(unsafe.Pointer(db)).Fflags&libc.Uint64FromInt32(libc.Int32FromInt32(SQLITE_WriteSchema)|libc.Int32FromInt32(SQLITE_Defensive)) == uint64(SQLITE_WriteSchema)) } // C documentation // // /* // ** This routine translates a standard POSIX errno code into something // ** useful to the clients of the sqlite3 functions. Specifically, it is // ** intended to translate a variety of "try again" errors into SQLITE_BUSY // ** and a variety of "please close the file descriptor NOW" errors into // ** SQLITE_IOERR // ** // ** Errors during initialization of locks, or file system support for locks, // ** should handle ENOLCK, ENOTSUP, EOPNOTSUPP separately. // */ func _sqliteErrorFromPosixError(tls *libc.TLS, posixError int32, sqliteIOErr int32) (r int32) { switch posixError { case int32(EACCES): fallthrough case int32(EAGAIN): fallthrough case int32(ETIMEDOUT): fallthrough case int32(EBUSY): fallthrough case int32(EINTR): fallthrough case int32(ENOLCK): /* random NFS retry error, unless during file system support * introspection, in which it actually means what it says */ return int32(SQLITE_BUSY) case int32(EPERM): return int32(SQLITE_PERM) default: return sqliteIOErr } return r } func _statEof(tls *libc.TLS, pCursor uintptr) (r int32) { var pCsr uintptr _ = pCsr pCsr = pCursor return libc.Int32FromUint8((*TStatCursor)(unsafe.Pointer(pCsr)).FisEof) } func _statRowid(tls *libc.TLS, pCursor uintptr, pRowid uintptr) (r int32) { var pCsr uintptr _ = pCsr pCsr = pCursor **(**Tsqlite_int64)(__ccgo_up(pRowid)) = libc.Int64FromUint32((*TStatCursor)(unsafe.Pointer(pCsr)).FiPageno) return SQLITE_OK } // C documentation // // /* // ** Set the pFile->lastErrno. Do this in a subroutine as that provides // ** a convenient place to set a breakpoint. // */ func _storeLastErrno(tls *libc.TLS, pFile uintptr, error1 int32) { (*TunixFile)(unsafe.Pointer(pFile)).FlastErrno = error1 } // C documentation // // /* // ** Buffer zStr contains nStr bytes of utf-8 encoded text. Return 1 if zStr // ** contains character ch, or 0 if it does not. // */ func _strContainsChar(tls *libc.TLS, zStr uintptr, nStr int32, ch Tu32) (r int32) { bp := tls.Alloc(16) defer tls.Free(16) var tst Tu32 var zEnd, v2 uintptr var v1 uint32 var _ /* z at bp+0 */ uintptr _, _, _, _ = tst, zEnd, v1, v2 zEnd = zStr + uintptr(nStr) **(**uintptr)(__ccgo_up(bp)) = zStr for **(**uintptr)(__ccgo_up(bp)) < zEnd { if libc.Int32FromUint8(**(**Tu8)(__ccgo_up(**(**uintptr)(__ccgo_up(bp))))) < int32(0x80) { v2 = **(**uintptr)(__ccgo_up(bp)) **(**uintptr)(__ccgo_up(bp)) = **(**uintptr)(__ccgo_up(bp)) + 1 v1 = uint32(**(**Tu8)(__ccgo_up(v2))) } else { v1 = _sqlite3Utf8Read(tls, bp) } tst = v1 if tst == ch { return int32(1) } } return 0 } // C documentation // // /* // ** Append a record of the current state of page pPg to the sub-journal. // ** // ** If successful, set the bit corresponding to pPg->pgno in the bitvecs // ** for all open savepoints before returning. // ** // ** This function returns SQLITE_OK if everything is successful, an IO // ** error code if the attempt to write to the sub-journal fails, or // ** SQLITE_NOMEM if a malloc fails while setting a bit in a savepoint // ** bitvec. // */ func _subjournalPage(tls *libc.TLS, pPg uintptr) (r int32) { var offset Ti64 var pData, pData2, pPager uintptr var rc int32 _, _, _, _, _ = offset, pData, pData2, pPager, rc rc = SQLITE_OK pPager = (*TPgHdr)(unsafe.Pointer(pPg)).FpPager if libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FjournalMode) != int32(PAGER_JOURNALMODE_OFF) { /* Open the sub-journal, if it has not already been opened */ rc = _openSubJournal(tls, pPager) /* If the sub-journal was opened successfully (or was already open), ** write the journal record into the file. */ if rc == SQLITE_OK { pData = (*TPgHdr)(unsafe.Pointer(pPg)).FpData offset = libc.Int64FromUint32((*TPager)(unsafe.Pointer(pPager)).FnSubRec) * (int64(4) + (*TPager)(unsafe.Pointer(pPager)).FpageSize) pData2 = pData rc = _write32bits(tls, (*TPager)(unsafe.Pointer(pPager)).Fsjfd, offset, (*TPgHdr)(unsafe.Pointer(pPg)).Fpgno) if rc == SQLITE_OK { rc = _sqlite3OsWrite(tls, (*TPager)(unsafe.Pointer(pPager)).Fsjfd, pData2, int32((*TPager)(unsafe.Pointer(pPager)).FpageSize), offset+int64(4)) } } } if rc == SQLITE_OK { (*TPager)(unsafe.Pointer(pPager)).FnSubRec = (*TPager)(unsafe.Pointer(pPager)).FnSubRec + 1 rc = _addToSavepointBitvecs(tls, pPager, (*TPgHdr)(unsafe.Pointer(pPg)).Fpgno) } return rc } // C documentation // // /* subtype(X) // ** // ** Return the subtype of X // */ func _subtypeFunc(tls *libc.TLS, context uintptr, argc int32, argv uintptr) { _ = argc Xsqlite3_result_int(tls, context, libc.Int32FromUint32(Xsqlite3_value_subtype(tls, **(**uintptr)(__ccgo_up(argv))))) } func _tabIsReadOnly(tls *libc.TLS, pParse uintptr, pTab uintptr) (r int32) { var db uintptr _ = db if libc.Int32FromUint8((*TTable)(unsafe.Pointer(pTab)).FeTabType) == int32(TABTYP_VTAB) { return _vtabIsReadOnly(tls, pParse, pTab) } if (*TTable)(unsafe.Pointer(pTab)).FtabFlags&libc.Uint32FromInt32(libc.Int32FromInt32(TF_Readonly)|libc.Int32FromInt32(TF_Shadow)) == uint32(0) { return 0 } db = (*TParse)(unsafe.Pointer(pParse)).Fdb if (*TTable)(unsafe.Pointer(pTab)).FtabFlags&uint32(TF_Readonly) != uint32(0) { return libc.BoolInt32(_sqlite3WritableSchema(tls, db) == 0 && libc.Int32FromUint8((*TParse)(unsafe.Pointer(pParse)).Fnested) == 0) } return _sqlite3ReadOnlyShadowTables(tls, db) } // C documentation // // /* // ** The unicode() function. Return the integer unicode code-point value // ** for the first character of the input string. // */ func _unicodeFunc(tls *libc.TLS, context uintptr, argc int32, argv uintptr) { bp := tls.Alloc(16) defer tls.Free(16) var _ /* z at bp+0 */ uintptr **(**uintptr)(__ccgo_up(bp)) = Xsqlite3_value_text(tls, **(**uintptr)(__ccgo_up(argv))) _ = argc if **(**uintptr)(__ccgo_up(bp)) != 0 && **(**uint8)(__ccgo_up(**(**uintptr)(__ccgo_up(bp)))) != 0 { Xsqlite3_result_int(tls, context, libc.Int32FromUint32(_sqlite3Utf8Read(tls, bp))) } } // C documentation // // /* // ** Helper functions to obtain and relinquish the global mutex. The // ** global mutex is used to protect the unixInodeInfo objects used by // ** this file, all of which may be shared by multiple threads. // ** // ** Function unixMutexHeld() is used to assert() that the global mutex // ** is held when required. This function is only used as part of assert() // ** statements. e.g. // ** // ** unixEnterMutex() // ** assert( unixMutexHeld() ); // ** unixEnterLeave() // ** // ** To prevent deadlock, the global unixBigLock must must be acquired // ** before the unixInodeInfo.pLockMutex mutex, if both are held. It is // ** OK to get the pLockMutex without holding unixBigLock first, but if // ** that happens, the unixBigLock mutex must not be acquired until after // ** pLockMutex is released. // ** // ** OK: enter(unixBigLock), enter(pLockInfo) // ** OK: enter(unixBigLock) // ** OK: enter(pLockInfo) // ** ERROR: enter(pLockInfo), enter(unixBigLock) // */ var _unixBigLock = uintptr(0) // C documentation // // /* // ** Close a file. // */ func _unixClose(tls *libc.TLS, id uintptr) (r int32) { var pFile, pInode uintptr var rc int32 _, _, _ = pFile, pInode, rc rc = SQLITE_OK pFile = id pInode = (*TunixFile)(unsafe.Pointer(pFile)).FpInode _verifyDbFile(tls, pFile) _unixUnlock(tls, id, NO_LOCK) _unixEnterMutex(tls) /* unixFile.pInode is always valid here. Otherwise, a different close ** routine (e.g. nolockClose()) would be called instead. */ Xsqlite3_mutex_enter(tls, (*TunixInodeInfo)(unsafe.Pointer(pInode)).FpLockMutex) if (*TunixInodeInfo)(unsafe.Pointer(pInode)).FnLock != 0 { /* If there are outstanding locks, do not actually close the file just ** yet because that would clear those locks. Instead, add the file ** descriptor to pInode->pUnused list. It will be automatically closed ** when the last lock is cleared. */ _setPendingFd(tls, pFile) } Xsqlite3_mutex_leave(tls, (*TunixInodeInfo)(unsafe.Pointer(pInode)).FpLockMutex) _releaseInodeInfo(tls, pFile) rc = _closeUnixFile(tls, id) _unixLeaveMutex(tls) return rc } /************** End of the posix advisory lock implementation ***************** ******************************************************************************/ /****************************************************************************** ****************************** No-op Locking ********************************** ** ** Of the various locking implementations available, this is by far the ** simplest: locking is ignored. No attempt is made to lock the database ** file for reading or writing. ** ** This locking mode is appropriate for use on read-only databases ** (ex: databases that are burned into CD-ROM, for example.) It can ** also be used if the application employs some external mechanism to ** prevent simultaneous access of the same database by two or more ** database connections. But there is a serious risk of database ** corruption if this locking mode is used in situations where multiple ** database connections are accessing the same database file at the same ** time and one or more of those connections are writing. */ // C documentation // // /* // ** Find the current time (in Universal Coordinated Time). Write the // ** current time and date as a Julian Day number into *prNow and // ** return 0. Return 1 if the time and date cannot be found. // */ func _unixCurrentTime(tls *libc.TLS, NotUsed uintptr, prNow uintptr) (r int32) { bp := tls.Alloc(16) defer tls.Free(16) var rc int32 var _ /* i at bp+0 */ Tsqlite3_int64 _ = rc **(**Tsqlite3_int64)(__ccgo_up(bp)) = 0 _ = NotUsed rc = _unixCurrentTimeInt64(tls, uintptr(0), bp) **(**float64)(__ccgo_up(prNow)) = float64(**(**Tsqlite3_int64)(__ccgo_up(bp))) / float64(8.64e+07) return rc } // C documentation // // /* // ** Return the device characteristics for the file. // ** // ** This VFS is set up to return SQLITE_IOCAP_POWERSAFE_OVERWRITE by default. // ** However, that choice is controversial since technically the underlying // ** file system does not always provide powersafe overwrites. (In other // ** words, after a power-loss event, parts of the file that were never // ** written might end up being altered.) However, non-PSOW behavior is very, // ** very rare. And asserting PSOW makes a large reduction in the amount // ** of required I/O for journaling, since a lot of padding is eliminated. // ** Hence, while POWERSAFE_OVERWRITE is on by default, there is a file-control // ** available to turn it off and URI query parameter available to turn it off. // */ func _unixDeviceCharacteristics(tls *libc.TLS, id uintptr) (r int32) { var pFd uintptr _ = pFd pFd = id _setDeviceCharacteristics(tls, pFd) return (*TunixFile)(unsafe.Pointer(pFd)).FdeviceCharacteristics } func _unixDlClose(tls *libc.TLS, NotUsed uintptr, pHandle uintptr) { _ = NotUsed libc.Xdlclose(tls, pHandle) } func _unixDlOpen(tls *libc.TLS, NotUsed uintptr, zFilename uintptr) (r uintptr) { _ = NotUsed return libc.Xdlopen(tls, zFilename, libc.Int32FromInt32(RTLD_NOW)|libc.Int32FromInt32(RTLD_GLOBAL)) } func _unixDlSym(tls *libc.TLS, NotUsed uintptr, p uintptr, zSym uintptr) (r uintptr) { var x uintptr _ = x _ = NotUsed x = __ccgo_fp(libc.Xdlsym) return (*(*func(*libc.TLS, uintptr, uintptr) uintptr)(unsafe.Pointer(&struct{ uintptr }{x})))(tls, p, zSym) } func _unixEnterMutex(tls *libc.TLS) { /* Not a recursive mutex */ Xsqlite3_mutex_enter(tls, _unixBigLock) } var _unixEpoch = libc.Int64FromInt32(24405875) * libc.Int64FromInt32(8640000) func _unixLeaveMutex(tls *libc.TLS) { Xsqlite3_mutex_leave(tls, _unixBigLock) } // C documentation // // /* // ** Return the sector size in bytes of the underlying block device for // ** the specified file. This is almost always 512 bytes, but may be // ** larger for some devices. // ** // ** SQLite code assumes this function cannot fail. It also assumes that // ** if two files are created in the same file-system directory (i.e. // ** a database and its journal file) that the sector size will be the // ** same for both. // */ func _unixSectorSize(tls *libc.TLS, id uintptr) (r int32) { var pFd uintptr _ = pFd pFd = id _setDeviceCharacteristics(tls, pFd) return (*TunixFile)(unsafe.Pointer(pFd)).FsectorSize } // C documentation // // /* // ** Return the minimum number of 32KB shm regions that should be mapped at // ** a time, assuming that each mapping must be an integer multiple of the // ** current system page-size. // ** // ** Usually, this is 1. The exception seems to be systems that are configured // ** to use 64KB pages - in this case each mapping must cover at least two // ** shm regions. // */ func _unixShmRegionPerMap(tls *libc.TLS) (r int32) { var pgsz, shmsz int32 _, _ = pgsz, shmsz shmsz = libc.Int32FromInt32(32) * libc.Int32FromInt32(1024) /* SHM region size */ pgsz = (*(*func(*libc.TLS) int32)(unsafe.Pointer(&struct{ uintptr }{_aSyscall[int32(25)].FpCurrent})))(tls) /* System page size */ /* Page size must be a power of 2 */ if pgsz < shmsz { return int32(1) } return pgsz / shmsz } // C documentation // // /* // ** Lower the locking level on file descriptor pFile to eFileLock. eFileLock // ** must be either NO_LOCK or SHARED_LOCK. // ** // ** If the locking level of the file descriptor is already at or below // ** the requested locking level, this routine is a no-op. // */ func _unixUnlock(tls *libc.TLS, id uintptr, eFileLock int32) (r int32) { return _posixUnlock(tls, id, eFileLock, 0) } // C documentation // // /* // ** Write data from a buffer into a file. Return SQLITE_OK on success // ** or some other error code on failure. // */ func _unixWrite(tls *libc.TLS, id uintptr, pBuf uintptr, amt int32, offset Tsqlite3_int64) (r int32) { var pFile uintptr var wrote, v1 int32 _, _, _ = pFile, wrote, v1 pFile = id wrote = 0 /* If this is a database file (not a journal, super-journal or temp ** file), the bytes in the locking range should never be read or written. */ for { v1 = _seekAndWrite(tls, pFile, offset, pBuf, amt) wrote = v1 if !(v1 < amt && wrote > 0) { break } amt = amt - wrote offset = offset + int64(wrote) pBuf = pBuf + uintptr(wrote) } if amt > wrote { if wrote < 0 && (*TunixFile)(unsafe.Pointer(pFile)).FlastErrno != int32(ENOSPC) { /* lastErrno set by seekAndWrite */ return libc.Int32FromInt32(SQLITE_IOERR) | libc.Int32FromInt32(3)<xDel and memory in p->zMalloc. // ** // ** This is a helper routine invoked by sqlite3VdbeMemRelease() in // ** the unusual case where there really is memory in p that needs // ** to be freed. // */ func _vdbeMemClear(tls *libc.TLS, p uintptr) { if libc.Int32FromUint16((*TMem)(unsafe.Pointer(p)).Fflags)&(libc.Int32FromInt32(MEM_Agg)|libc.Int32FromInt32(MEM_Dyn)) != 0 { _vdbeMemClearExternAndSetNull(tls, p) } if (*TMem)(unsafe.Pointer(p)).FszMalloc != 0 { _sqlite3DbFreeNN(tls, (*TMem)(unsafe.Pointer(p)).Fdb, (*TMem)(unsafe.Pointer(p)).FzMalloc) (*TMem)(unsafe.Pointer(p)).FszMalloc = 0 } (*TMem)(unsafe.Pointer(p)).Fz = uintptr(0) } // C documentation // // /* // ** Read a varint from the stream of data accessed by p. Set *pnOut to // ** the value read. // */ func _vdbePmaReadVarint(tls *libc.TLS, p uintptr, pnOut uintptr) (r int32) { bp := tls.Alloc(32) defer tls.Free(32) var i, iBuf, rc, v1 int32 var _ /* a at bp+16 */ uintptr var _ /* aVarint at bp+0 */ [16]Tu8 _, _, _, _ = i, iBuf, rc, v1 if (*TPmaReader)(unsafe.Pointer(p)).FaMap != 0 { **(**Ti64)(__ccgo_up(p)) += libc.Int64FromUint8(_sqlite3GetVarint(tls, (*TPmaReader)(unsafe.Pointer(p)).FaMap+uintptr((*TPmaReader)(unsafe.Pointer(p)).FiReadOff), pnOut)) } else { iBuf = int32((*TPmaReader)(unsafe.Pointer(p)).FiReadOff % int64((*TPmaReader)(unsafe.Pointer(p)).FnBuffer)) if iBuf != 0 && (*TPmaReader)(unsafe.Pointer(p)).FnBuffer-iBuf >= int32(9) { **(**Ti64)(__ccgo_up(p)) += libc.Int64FromUint8(_sqlite3GetVarint(tls, (*TPmaReader)(unsafe.Pointer(p)).FaBuffer+uintptr(iBuf), pnOut)) } else { i = 0 for cond := true; cond; cond = libc.Int32FromUint8(**(**Tu8)(__ccgo_up(**(**uintptr)(__ccgo_up(bp + 16)))))&int32(0x80) != 0 { rc = _vdbePmaReadBlob(tls, p, int32(1), bp+16) if rc != 0 { return rc } v1 = i i = i + 1 (**(**[16]Tu8)(__ccgo_up(bp)))[v1&int32(0xf)] = **(**Tu8)(__ccgo_up(**(**uintptr)(__ccgo_up(bp + 16)))) } _sqlite3GetVarint(tls, bp, pnOut) } } return SQLITE_OK } // C documentation // // /* // ** Initialize PmaReader pReadr to scan through the PMA stored in file pFile // ** starting at offset iStart and ending at offset iEof-1. This function // ** leaves the PmaReader pointing to the first key in the PMA (or EOF if the // ** PMA is empty). // ** // ** If the pnByte parameter is NULL, then it is assumed that the file // ** contains a single PMA, and that that PMA omits the initial length varint. // */ func _vdbePmaReaderInit(tls *libc.TLS, pTask uintptr, pFile uintptr, iStart Ti64, pReadr uintptr, pnByte uintptr) (r int32) { bp := tls.Alloc(16) defer tls.Free(16) var rc int32 var v1 uintptr var _ /* nByte at bp+0 */ Tu64 _, _ = rc, v1 rc = _vdbePmaReaderSeek(tls, pTask, pReadr, pFile, iStart) if rc == SQLITE_OK { **(**Tu64)(__ccgo_up(bp)) = uint64(0) /* Size of PMA in bytes */ rc = _vdbePmaReadVarint(tls, pReadr, bp) (*TPmaReader)(unsafe.Pointer(pReadr)).FiEof = libc.Int64FromUint64(libc.Uint64FromInt64((*TPmaReader)(unsafe.Pointer(pReadr)).FiReadOff) + **(**Tu64)(__ccgo_up(bp))) v1 = pnByte *(*Ti64)(unsafe.Pointer(v1)) = Ti64(uint64(*(*Ti64)(unsafe.Pointer(v1))) + **(**Tu64)(__ccgo_up(bp))) } if rc == SQLITE_OK { rc = _vdbePmaReaderNext(tls, pReadr) } return rc } // C documentation // // /* // ** The first argument passed to this function is a serial-type that // ** corresponds to an integer - all values between 1 and 9 inclusive // ** except 7. The second points to a buffer containing an integer value // ** serialized according to serial_type. This function deserializes // ** and returns the value. // */ func _vdbeRecordDecodeInt(tls *libc.TLS, serial_type Tu32, aKey uintptr) (r Ti64) { bp := tls.Alloc(16) defer tls.Free(16) var _ /* x at bp+8 */ Tu64 var _ /* y at bp+0 */ Tu32 switch serial_type { case uint32(0): fallthrough case uint32(1): return int64(libc.Int8FromUint8(**(**Tu8)(__ccgo_up(aKey)))) case uint32(2): return int64(libc.Int32FromInt32(256)*int32(libc.Int8FromUint8(**(**Tu8)(__ccgo_up(aKey)))) | libc.Int32FromUint8(**(**Tu8)(__ccgo_up(aKey + 1)))) case uint32(3): return int64(libc.Int32FromInt32(65536)*int32(libc.Int8FromUint8(**(**Tu8)(__ccgo_up(aKey)))) | libc.Int32FromUint8(**(**Tu8)(__ccgo_up(aKey + 1)))< int32(7) && s2 > int32(7) { res = s1 - s2 } else { if s2 > int32(7) { res = +libc.Int32FromInt32(1) } else { if s1 > int32(7) { res = -int32(1) } else { res = s1 - s2 } } if res > 0 { if libc.Int32FromUint8(**(**Tu8)(__ccgo_up(v1)))&int32(0x80) != 0 { res = -int32(1) } } else { if libc.Int32FromUint8(**(**Tu8)(__ccgo_up(v2)))&int32(0x80) != 0 { res = +libc.Int32FromInt32(1) } } } } if res == 0 { if libc.Int32FromUint16((*TKeyInfo)(unsafe.Pointer((*TVdbeSorter)(unsafe.Pointer((*TSortSubtask)(unsafe.Pointer(pTask)).FpSorter)).FpKeyInfo)).FnKeyField) > int32(1) { res = _vdbeSorterCompareTail(tls, pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2) } } else { if **(**Tu8)(__ccgo_up((*TKeyInfo)(unsafe.Pointer((*TVdbeSorter)(unsafe.Pointer((*TSortSubtask)(unsafe.Pointer(pTask)).FpSorter)).FpKeyInfo)).FaSortFlags)) != 0 { res = res * -int32(1) } } return res } // C documentation // // /* // ** Return the SorterCompare function to compare values collected by the // ** sorter object passed as the only argument. // */ func _vdbeSorterGetCompare(tls *libc.TLS, p uintptr) (r TSorterCompare) { if libc.Int32FromUint8((*TVdbeSorter)(unsafe.Pointer(p)).FtypeMask) == int32(SORTER_TYPE_INTEGER) { return __ccgo_fp(_vdbeSorterCompareInt) } else { if libc.Int32FromUint8((*TVdbeSorter)(unsafe.Pointer(p)).FtypeMask) == int32(SORTER_TYPE_TEXT) { return __ccgo_fp(_vdbeSorterCompareText) } } return __ccgo_fp(_vdbeSorterCompare) } // C documentation // // /* // ** Compute a hash on a page number. The resulting hash value must land // ** between 0 and (HASHTABLE_NSLOT-1). The walNextHash() function advances // ** the hash to the next value in the event of a collision. // */ func _walHash(tls *libc.TLS, iPage Tu32) (r int32) { return libc.Int32FromUint32(iPage * uint32(HASHTABLE_HASH_1) & libc.Uint32FromInt32(libc.Int32FromInt32(HASHTABLE_NPAGE)*libc.Int32FromInt32(2)-libc.Int32FromInt32(1))) } // C documentation // // /* // ** Read the wal-index header from the wal-index and into pWal->hdr. // ** If the wal-header appears to be corrupt, try to reconstruct the // ** wal-index from the WAL before returning. // ** // ** Set *pChanged to 1 if the wal-index header value in pWal->hdr is // ** changed by this operation. If pWal->hdr is unchanged, set *pChanged // ** to 0. // ** // ** If the wal-index header is successfully read, return SQLITE_OK. // ** Otherwise an SQLite error code. // */ func _walIndexReadHdr(tls *libc.TLS, pWal uintptr, pChanged uintptr) (r int32) { bp := tls.Alloc(16) defer tls.Free(16) var bWriteLock, badHdr, rc, v1 int32 var v4 bool var _ /* page0 at bp+0 */ uintptr _, _, _, _, _ = bWriteLock, badHdr, rc, v1, v4 /* Chunk of wal-index containing header */ /* Ensure that page 0 of the wal-index (the page that contains the ** wal-index header) is mapped. Return early if an error occurs here. */ rc = _walIndexPage(tls, pWal, 0, bp) if rc != SQLITE_OK { /* READONLY changed to OK in walIndexPage */ if rc == libc.Int32FromInt32(SQLITE_READONLY)|libc.Int32FromInt32(5)<writeLock ** is zero, which prevents the SHM from growing */ } /* If the first page of the wal-index has been mapped, try to read the ** wal-index header immediately, without holding any lock. This usually ** works, but may fail if the wal-index header is corrupt or currently ** being modified by another thread or process. */ if **(**uintptr)(__ccgo_up(bp)) != 0 { v1 = _walIndexTryHdr(tls, pWal, pChanged) } else { v1 = int32(1) } badHdr = v1 /* If the first attempt failed, it might have been due to a race ** with a writer. So get a WRITE lock and try again. */ if badHdr != 0 { if libc.Int32FromUint8((*TWal)(unsafe.Pointer(pWal)).FbShmUnreliable) == 0 && libc.Int32FromUint8((*TWal)(unsafe.Pointer(pWal)).FreadOnly)&int32(WAL_SHM_RDONLY) != 0 { v1 = _walLockShared(tls, pWal, WAL_WRITE_LOCK) rc = v1 if SQLITE_OK == v1 { _walUnlockShared(tls, pWal, WAL_WRITE_LOCK) rc = libc.Int32FromInt32(SQLITE_READONLY) | libc.Int32FromInt32(1)< x<=y // ** x=y OR x=y --> x=y // ** x<=y OR x x<=y // ** // ** The following is NOT generated: // ** // ** xy --> x!=y // */ func _whereCombineDisjuncts(tls *libc.TLS, pSrc uintptr, pWC uintptr, pOne uintptr, pTwo uintptr) { var db, pA, pB, pNew uintptr var eOp Tu16 var idxNew, op int32 _, _, _, _, _, _, _ = db, eOp, idxNew, op, pA, pB, pNew eOp = libc.Uint16FromInt32(libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pOne)).FeOperator) | libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pTwo)).FeOperator)) /* Expressions associated with pOne and pTwo */ if (libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pOne)).FwtFlags)|libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pTwo)).FwtFlags))&int32(TERM_VNULL) != 0 { return } if libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pOne)).FeOperator)&(libc.Int32FromInt32(WO_EQ)|libc.Int32FromInt32(WO_EQ)<<(libc.Int32FromInt32(TK_LT)-libc.Int32FromInt32(TK_EQ))|libc.Int32FromInt32(WO_EQ)<<(libc.Int32FromInt32(TK_LE)-libc.Int32FromInt32(TK_EQ))|libc.Int32FromInt32(WO_EQ)<<(libc.Int32FromInt32(TK_GT)-libc.Int32FromInt32(TK_EQ))|libc.Int32FromInt32(WO_EQ)<<(libc.Int32FromInt32(TK_GE)-libc.Int32FromInt32(TK_EQ))) == 0 { return } if libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pTwo)).FeOperator)&(libc.Int32FromInt32(WO_EQ)|libc.Int32FromInt32(WO_EQ)<<(libc.Int32FromInt32(TK_LT)-libc.Int32FromInt32(TK_EQ))|libc.Int32FromInt32(WO_EQ)<<(libc.Int32FromInt32(TK_LE)-libc.Int32FromInt32(TK_EQ))|libc.Int32FromInt32(WO_EQ)<<(libc.Int32FromInt32(TK_GT)-libc.Int32FromInt32(TK_EQ))|libc.Int32FromInt32(WO_EQ)<<(libc.Int32FromInt32(TK_GE)-libc.Int32FromInt32(TK_EQ))) == 0 { return } if libc.Int32FromUint16(eOp)&(libc.Int32FromInt32(WO_EQ)|libc.Int32FromInt32(WO_EQ)<<(libc.Int32FromInt32(TK_LT)-libc.Int32FromInt32(TK_EQ))|libc.Int32FromInt32(WO_EQ)<<(libc.Int32FromInt32(TK_LE)-libc.Int32FromInt32(TK_EQ))) != libc.Int32FromUint16(eOp) && libc.Int32FromUint16(eOp)&(libc.Int32FromInt32(WO_EQ)|libc.Int32FromInt32(WO_EQ)<<(libc.Int32FromInt32(TK_GT)-libc.Int32FromInt32(TK_EQ))|libc.Int32FromInt32(WO_EQ)<<(libc.Int32FromInt32(TK_GE)-libc.Int32FromInt32(TK_EQ))) != libc.Int32FromUint16(eOp) { return } pA = (*TWhereTerm)(unsafe.Pointer(pOne)).FpExpr pB = (*TWhereTerm)(unsafe.Pointer(pTwo)).FpExpr if _sqlite3ExprCompare(tls, uintptr(0), (*TExpr)(unsafe.Pointer(pA)).FpLeft, (*TExpr)(unsafe.Pointer(pB)).FpLeft, -int32(1)) != 0 { return } if _sqlite3ExprCompare(tls, uintptr(0), (*TExpr)(unsafe.Pointer(pA)).FpRight, (*TExpr)(unsafe.Pointer(pB)).FpRight, -int32(1)) != 0 { return } if libc.BoolInt32((*TExpr)(unsafe.Pointer(pA)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_Commuted)) != uint32(0)) != libc.BoolInt32((*TExpr)(unsafe.Pointer(pB)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_Commuted)) != uint32(0)) { return } /* If we reach this point, it means the two subterms can be combined */ if libc.Int32FromUint16(eOp)&(libc.Int32FromUint16(eOp)-int32(1)) != 0 { if libc.Int32FromUint16(eOp)&(libc.Int32FromInt32(WO_EQ)<<(libc.Int32FromInt32(TK_LT)-libc.Int32FromInt32(TK_EQ))|libc.Int32FromInt32(WO_EQ)<<(libc.Int32FromInt32(TK_LE)-libc.Int32FromInt32(TK_EQ))) != 0 { eOp = libc.Uint16FromInt32(libc.Int32FromInt32(WO_EQ) << (libc.Int32FromInt32(TK_LE) - libc.Int32FromInt32(TK_EQ))) } else { eOp = libc.Uint16FromInt32(libc.Int32FromInt32(WO_EQ) << (libc.Int32FromInt32(TK_GE) - libc.Int32FromInt32(TK_EQ))) } } db = (*TParse)(unsafe.Pointer((*TWhereInfo)(unsafe.Pointer((*TWhereClause)(unsafe.Pointer(pWC)).FpWInfo)).FpParse)).Fdb pNew = _sqlite3ExprDup(tls, db, pA, 0) if pNew == uintptr(0) { return } op = int32(TK_EQ) for { if !(libc.Int32FromUint16(eOp) != int32(WO_EQ)<<(op-int32(TK_EQ))) { break } goto _1 _1: ; op = op + 1 } (*TExpr)(unsafe.Pointer(pNew)).Fop = libc.Uint8FromInt32(op) idxNew = _whereClauseInsert(tls, pWC, pNew, libc.Uint16FromInt32(libc.Int32FromInt32(TERM_VIRTUAL)|libc.Int32FromInt32(TERM_DYNAMIC))) _exprAnalyze(tls, pSrc, pWC, idxNew) } // C documentation // // /* // ** Try to adjust the cost and number of output rows of WhereLoop pTemplate // ** upwards or downwards so that: // ** // ** (1) pTemplate costs less than any other WhereLoops that are a proper // ** subset of pTemplate // ** // ** (2) pTemplate costs more than any other WhereLoops for which pTemplate // ** is a proper subset. // ** // ** To say "WhereLoop X is a proper subset of Y" means that X uses fewer // ** WHERE clause terms than Y and that every WHERE clause term used by X is // ** also used by Y. // */ func _whereLoopAdjustCost(tls *libc.TLS, p uintptr, pTemplate uintptr) { var v2 int32 _ = v2 if (*TWhereLoop)(unsafe.Pointer(pTemplate)).FwsFlags&uint32(WHERE_INDEXED) == uint32(0) { return } for { if !(p != 0) { break } if libc.Int32FromUint8((*TWhereLoop)(unsafe.Pointer(p)).FiTab) != libc.Int32FromUint8((*TWhereLoop)(unsafe.Pointer(pTemplate)).FiTab) { goto _1 } if (*TWhereLoop)(unsafe.Pointer(p)).FwsFlags&uint32(WHERE_INDEXED) == uint32(0) { goto _1 } if _whereLoopCheaperProperSubset(tls, p, pTemplate) != 0 { /* Adjust pTemplate cost downward so that it is cheaper than its ** subset p. */ if int32((*TWhereLoop)(unsafe.Pointer(p)).FrRun) < int32((*TWhereLoop)(unsafe.Pointer(pTemplate)).FrRun) { v2 = int32((*TWhereLoop)(unsafe.Pointer(p)).FrRun) } else { v2 = int32((*TWhereLoop)(unsafe.Pointer(pTemplate)).FrRun) } (*TWhereLoop)(unsafe.Pointer(pTemplate)).FrRun = int16(v2) if int32((*TWhereLoop)(unsafe.Pointer(p)).FnOut)-int32(1) < int32((*TWhereLoop)(unsafe.Pointer(pTemplate)).FnOut) { v2 = int32((*TWhereLoop)(unsafe.Pointer(p)).FnOut) - int32(1) } else { v2 = int32((*TWhereLoop)(unsafe.Pointer(pTemplate)).FnOut) } (*TWhereLoop)(unsafe.Pointer(pTemplate)).FnOut = int16(v2) } else { if _whereLoopCheaperProperSubset(tls, pTemplate, p) != 0 { /* Adjust pTemplate cost upward so that it is costlier than p since ** pTemplate is a proper subset of p */ if int32((*TWhereLoop)(unsafe.Pointer(p)).FrRun) > int32((*TWhereLoop)(unsafe.Pointer(pTemplate)).FrRun) { v2 = int32((*TWhereLoop)(unsafe.Pointer(p)).FrRun) } else { v2 = int32((*TWhereLoop)(unsafe.Pointer(pTemplate)).FrRun) } (*TWhereLoop)(unsafe.Pointer(pTemplate)).FrRun = int16(v2) if int32((*TWhereLoop)(unsafe.Pointer(p)).FnOut)+int32(1) > int32((*TWhereLoop)(unsafe.Pointer(pTemplate)).FnOut) { v2 = int32((*TWhereLoop)(unsafe.Pointer(p)).FnOut) + int32(1) } else { v2 = int32((*TWhereLoop)(unsafe.Pointer(pTemplate)).FnOut) } (*TWhereLoop)(unsafe.Pointer(pTemplate)).FnOut = int16(v2) } } goto _1 _1: ; p = (*TWhereLoop)(unsafe.Pointer(p)).FpNextLoop } } // C documentation // // /* // ** Clear the WhereLoop.u union. Leave WhereLoop.pLTerm intact. // */ func _whereLoopClearUnion(tls *libc.TLS, db uintptr, p uintptr) { if (*TWhereLoop)(unsafe.Pointer(p)).FwsFlags&libc.Uint32FromInt32(libc.Int32FromInt32(WHERE_VIRTUALTABLE)|libc.Int32FromInt32(WHERE_AUTO_INDEX)) != 0 { if (*TWhereLoop)(unsafe.Pointer(p)).FwsFlags&uint32(WHERE_VIRTUALTABLE) != uint32(0) && int32(Tu32(*(*uint8)(unsafe.Pointer(p + 24 + 4))&0x1>>0)) != 0 { Xsqlite3_free(tls, (*(*struct { FidxNum int32 F__ccgo4 uint8 FisOrdered Ti8 FomitMask Tu16 FidxStr uintptr FmHandleIn Tu32 })(unsafe.Pointer(p + 24))).FidxStr) libc.SetBitFieldPtr8Uint32(p+24+4, libc.Uint32FromInt32(0), 0, 0x1) (*(*struct { FidxNum int32 F__ccgo4 uint8 FisOrdered Ti8 FomitMask Tu16 FidxStr uintptr FmHandleIn Tu32 })(unsafe.Pointer(p + 24))).FidxStr = uintptr(0) } else { if (*TWhereLoop)(unsafe.Pointer(p)).FwsFlags&uint32(WHERE_AUTO_INDEX) != uint32(0) && (*(*struct { FnEq Tu16 FnBtm Tu16 FnTop Tu16 FnDistinctCol Tu16 FpIndex uintptr FpOrderBy uintptr })(unsafe.Pointer(p + 24))).FpIndex != uintptr(0) { _sqlite3DbFree(tls, db, (*TIndex)(unsafe.Pointer((*(*struct { FnEq Tu16 FnBtm Tu16 FnTop Tu16 FnDistinctCol Tu16 FpIndex uintptr FpOrderBy uintptr })(unsafe.Pointer(p + 24))).FpIndex)).FzColAff) _sqlite3DbFreeNN(tls, db, (*(*struct { FnEq Tu16 FnBtm Tu16 FnTop Tu16 FnDistinctCol Tu16 FpIndex uintptr FpOrderBy uintptr })(unsafe.Pointer(p + 24))).FpIndex) (*(*struct { FnEq Tu16 FnBtm Tu16 FnTop Tu16 FnDistinctCol Tu16 FpIndex uintptr FpOrderBy uintptr })(unsafe.Pointer(p + 24))).FpIndex = uintptr(0) } } } } // C documentation // // /* // ** If it is not NULL, pTerm is a term that provides an upper or lower // ** bound on a range scan. Without considering pTerm, it is estimated // ** that the scan will visit nNew rows. This function returns the number // ** estimated to be visited after taking pTerm into account. // ** // ** If the user explicitly specified a likelihood() value for this term, // ** then the return value is the likelihood multiplied by the number of // ** input rows. Otherwise, this function assumes that an "IS NOT NULL" term // ** has a likelihood of 0.50, and any other term a likelihood of 0.25. // */ func _whereRangeAdjust(tls *libc.TLS, pTerm uintptr, nNew TLogEst) (r TLogEst) { var nRet TLogEst _ = nRet nRet = nNew if pTerm != 0 { if int32((*TWhereTerm)(unsafe.Pointer(pTerm)).FtruthProb) <= 0 { nRet = int16(int32(nRet) + int32((*TWhereTerm)(unsafe.Pointer(pTerm)).FtruthProb)) } else { if libc.Int32FromUint16((*TWhereTerm)(unsafe.Pointer(pTerm)).FwtFlags)&int32(TERM_VNULL) == 0 { nRet = int16(int32(nRet) - libc.Int32FromInt32(20)) } } } return nRet } // C documentation // // /* // ** If the right-hand branch of the expression is a TK_COLUMN, then return // ** a pointer to the right-hand branch. Otherwise, return NULL. // */ func _whereRightSubexprIsColumn(tls *libc.TLS, p uintptr) (r uintptr) { p = _sqlite3ExprSkipCollateAndLikely(tls, (*TExpr)(unsafe.Pointer(p)).FpRight) if p != uintptr(0) && libc.Int32FromUint8((*TExpr)(unsafe.Pointer(p)).Fop) == int32(TK_COLUMN) && !((*TExpr)(unsafe.Pointer(p)).Fflags&libc.Uint32FromInt32(libc.Int32FromInt32(EP_FixedCol)) != libc.Uint32FromInt32(0)) { return p } return uintptr(0) } // C documentation // // /* // ** Return the cost of sorting nRow rows, assuming that the keys have // ** nOrderby columns and that the first nSorted columns are already in // ** order. // */ func _whereSortingCost(tls *libc.TLS, pWInfo uintptr, nRow TLogEst, nOrderBy int32, nSorted int32) (r TLogEst) { var nCol, rSortCost TLogEst _, _ = nCol, rSortCost /* TUNING: sorting cost proportional to the number of output columns: */ nCol = _sqlite3LogEst(tls, libc.Uint64FromInt32(((*TExprList)(unsafe.Pointer((*TSelect)(unsafe.Pointer((*TWhereInfo)(unsafe.Pointer(pWInfo)).FpSelect)).FpEList)).FnExpr+int32(59))/int32(30))) rSortCost = int16(int32(nRow) + int32(nCol)) if nSorted > 0 { /* Scale the result by (Y/X) */ rSortCost = int16(int32(rSortCost) + (int32(_sqlite3LogEst(tls, libc.Uint64FromInt32((nOrderBy-nSorted)*int32(100)/nOrderBy))) - libc.Int32FromInt32(66))) } /* Multiple by log(M) where M is the number of output rows. ** Use the LIMIT for M if it is smaller. Or if this sort is for ** a DISTINCT operator, M will be the number of distinct output ** rows, so fudge it downwards a bit. */ if libc.Int32FromUint16((*TWhereInfo)(unsafe.Pointer(pWInfo)).FwctrlFlags)&int32(WHERE_USE_LIMIT) != 0 { rSortCost = int16(int32(rSortCost) + libc.Int32FromInt32(10)) /* TUNING: Extra 2.0x if using LIMIT */ if nSorted != 0 { rSortCost = int16(int32(rSortCost) + libc.Int32FromInt32(6)) /* TUNING: Extra 1.5x if also using partial sort */ } if int32((*TWhereInfo)(unsafe.Pointer(pWInfo)).FiLimit) < int32(nRow) { nRow = (*TWhereInfo)(unsafe.Pointer(pWInfo)).FiLimit } } else { if libc.Int32FromUint16((*TWhereInfo)(unsafe.Pointer(pWInfo)).FwctrlFlags)&int32(WHERE_WANT_DISTINCT) != 0 { /* TUNING: In the sort for a DISTINCT operator, assume that the DISTINCT ** reduces the number of output rows by a factor of 2 */ if int32(nRow) > int32(10) { nRow = int16(int32(nRow) - libc.Int32FromInt32(10)) } } } rSortCost = int16(int32(rSortCost) + int32(_estLog(tls, nRow))) return rSortCost } // C documentation // // /* // ** Generate VM code to invoke either xValue() (bFin==0) or xFinalize() // ** (bFin==1) for each window function in the linked list starting at // ** pMWin. Or, for built-in window-functions that do not use the standard // ** API, generate the equivalent VM code. // */ func _windowAggFinal(tls *libc.TLS, p uintptr, bFin int32) { var nArg int32 var pMWin, pParse, pWin, v uintptr _, _, _, _, _ = nArg, pMWin, pParse, pWin, v pParse = (*TWindowCodeArg)(unsafe.Pointer(p)).FpParse pMWin = (*TWindowCodeArg)(unsafe.Pointer(p)).FpMWin v = _sqlite3GetVdbe(tls, pParse) pWin = pMWin for { if !(pWin != 0) { break } if (*TWindow)(unsafe.Pointer(pMWin)).FregStartRowid == 0 && (*TFuncDef)(unsafe.Pointer((*TWindow)(unsafe.Pointer(pWin)).FpWFunc)).FfuncFlags&uint32(SQLITE_FUNC_MINMAX) != 0 && libc.Int32FromUint8((*TWindow)(unsafe.Pointer(pWin)).FeStart) != int32(TK_UNBOUNDED) { _sqlite3VdbeAddOp2(tls, v, int32(OP_Null), 0, (*TWindow)(unsafe.Pointer(pWin)).FregResult) _sqlite3VdbeAddOp1(tls, v, int32(OP_Last), (*TWindow)(unsafe.Pointer(pWin)).FcsrApp) _sqlite3VdbeAddOp3(tls, v, int32(OP_Column), (*TWindow)(unsafe.Pointer(pWin)).FcsrApp, 0, (*TWindow)(unsafe.Pointer(pWin)).FregResult) _sqlite3VdbeJumpHere(tls, v, _sqlite3VdbeCurrentAddr(tls, v)-int32(2)) } else { if (*TWindow)(unsafe.Pointer(pWin)).FregApp != 0 { } else { nArg = _windowArgCount(tls, pWin) if bFin != 0 { _sqlite3VdbeAddOp2(tls, v, int32(OP_AggFinal), (*TWindow)(unsafe.Pointer(pWin)).FregAccum, nArg) _sqlite3VdbeAppendP4(tls, v, (*TWindow)(unsafe.Pointer(pWin)).FpWFunc, -int32(8)) _sqlite3VdbeAddOp2(tls, v, int32(OP_Copy), (*TWindow)(unsafe.Pointer(pWin)).FregAccum, (*TWindow)(unsafe.Pointer(pWin)).FregResult) _sqlite3VdbeAddOp2(tls, v, int32(OP_Null), 0, (*TWindow)(unsafe.Pointer(pWin)).FregAccum) } else { _sqlite3VdbeAddOp3(tls, v, int32(OP_AggValue), (*TWindow)(unsafe.Pointer(pWin)).FregAccum, nArg, (*TWindow)(unsafe.Pointer(pWin)).FregResult) _sqlite3VdbeAppendP4(tls, v, (*TWindow)(unsafe.Pointer(pWin)).FpWFunc, -int32(8)) } } } goto _1 _1: ; pWin = (*TWindow)(unsafe.Pointer(pWin)).FpNextWin } } // C documentation // // /* // ** Helper function for sqlite3WindowCodeStep(). Each call to this function // ** generates VM code for a single RETURN_ROW, AGGSTEP or AGGINVERSE // ** operation. Refer to the header comment for sqlite3WindowCodeStep() for // ** details. // */ func _windowCodeOp(tls *libc.TLS, p uintptr, op int32, regCountdown int32, jumpOnEof int32) (r int32) { var addrContinue, addrNextRange, bPeer, csr, lblDone, nReg, reg, regRowid1, regRowid2, regTmp, ret, v1, v2 int32 var pMWin, pParse, v uintptr _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = addrContinue, addrNextRange, bPeer, csr, lblDone, nReg, pMWin, pParse, reg, regRowid1, regRowid2, regTmp, ret, v, v1, v2 pParse = (*TWindowCodeArg)(unsafe.Pointer(p)).FpParse pMWin = (*TWindowCodeArg)(unsafe.Pointer(p)).FpMWin ret = 0 v = (*TWindowCodeArg)(unsafe.Pointer(p)).FpVdbe addrContinue = 0 bPeer = libc.BoolInt32(libc.Int32FromUint8((*TWindow)(unsafe.Pointer(pMWin)).FeFrmType) != int32(TK_ROWS)) lblDone = _sqlite3VdbeMakeLabel(tls, pParse) addrNextRange = 0 /* Special case - WINDOW_AGGINVERSE is always a no-op if the frame ** starts with UNBOUNDED PRECEDING. */ if op == int32(WINDOW_AGGINVERSE) && libc.Int32FromUint8((*TWindow)(unsafe.Pointer(pMWin)).FeStart) == int32(TK_UNBOUNDED) { return 0 } if regCountdown > 0 { if libc.Int32FromUint8((*TWindow)(unsafe.Pointer(pMWin)).FeFrmType) == int32(TK_RANGE) { addrNextRange = _sqlite3VdbeCurrentAddr(tls, v) if op == int32(WINDOW_AGGINVERSE) { if libc.Int32FromUint8((*TWindow)(unsafe.Pointer(pMWin)).FeStart) == int32(TK_FOLLOWING) { _windowCodeRangeTest(tls, p, int32(OP_Le), (*TWindowCodeArg)(unsafe.Pointer(p)).Fcurrent.Fcsr, regCountdown, (*TWindowCodeArg)(unsafe.Pointer(p)).Fstart.Fcsr, lblDone) } else { _windowCodeRangeTest(tls, p, int32(OP_Ge), (*TWindowCodeArg)(unsafe.Pointer(p)).Fstart.Fcsr, regCountdown, (*TWindowCodeArg)(unsafe.Pointer(p)).Fcurrent.Fcsr, lblDone) } } else { _windowCodeRangeTest(tls, p, int32(OP_Gt), (*TWindowCodeArg)(unsafe.Pointer(p)).Fend.Fcsr, regCountdown, (*TWindowCodeArg)(unsafe.Pointer(p)).Fcurrent.Fcsr, lblDone) } } else { _sqlite3VdbeAddOp3(tls, v, int32(OP_IfPos), regCountdown, lblDone, int32(1)) } } if op == int32(WINDOW_RETURN_ROW) && (*TWindow)(unsafe.Pointer(pMWin)).FregStartRowid == 0 { _windowAggFinal(tls, p, 0) } addrContinue = _sqlite3VdbeCurrentAddr(tls, v) /* If this is a (RANGE BETWEEN a FOLLOWING AND b FOLLOWING) or ** (RANGE BETWEEN b PRECEDING AND a PRECEDING) frame, ensure the ** start cursor does not advance past the end cursor within the ** temporary table. It otherwise might, if (a>b). Also ensure that, ** if the input cursor is still finding new rows, that the end ** cursor does not go past it to EOF. */ if libc.Int32FromUint8((*TWindow)(unsafe.Pointer(pMWin)).FeStart) == libc.Int32FromUint8((*TWindow)(unsafe.Pointer(pMWin)).FeEnd) && regCountdown != 0 && libc.Int32FromUint8((*TWindow)(unsafe.Pointer(pMWin)).FeFrmType) == int32(TK_RANGE) { regRowid1 = _sqlite3GetTempReg(tls, pParse) regRowid2 = _sqlite3GetTempReg(tls, pParse) if op == int32(WINDOW_AGGINVERSE) { _sqlite3VdbeAddOp2(tls, v, int32(OP_Rowid), (*TWindowCodeArg)(unsafe.Pointer(p)).Fstart.Fcsr, regRowid1) _sqlite3VdbeAddOp2(tls, v, int32(OP_Rowid), (*TWindowCodeArg)(unsafe.Pointer(p)).Fend.Fcsr, regRowid2) _sqlite3VdbeAddOp3(tls, v, int32(OP_Ge), regRowid2, lblDone, regRowid1) } else { if (*TWindowCodeArg)(unsafe.Pointer(p)).FregRowid != 0 { _sqlite3VdbeAddOp2(tls, v, int32(OP_Rowid), (*TWindowCodeArg)(unsafe.Pointer(p)).Fend.Fcsr, regRowid1) _sqlite3VdbeAddOp3(tls, v, int32(OP_Ge), (*TWindowCodeArg)(unsafe.Pointer(p)).FregRowid, lblDone, regRowid1) } } _sqlite3ReleaseTempReg(tls, pParse, regRowid1) _sqlite3ReleaseTempReg(tls, pParse, regRowid2) } switch op { case int32(WINDOW_RETURN_ROW): csr = (*TWindowCodeArg)(unsafe.Pointer(p)).Fcurrent.Fcsr reg = (*TWindowCodeArg)(unsafe.Pointer(p)).Fcurrent.Freg _windowReturnOneRow(tls, p) case int32(WINDOW_AGGINVERSE): csr = (*TWindowCodeArg)(unsafe.Pointer(p)).Fstart.Fcsr reg = (*TWindowCodeArg)(unsafe.Pointer(p)).Fstart.Freg if (*TWindow)(unsafe.Pointer(pMWin)).FregStartRowid != 0 { _sqlite3VdbeAddOp2(tls, v, int32(OP_AddImm), (*TWindow)(unsafe.Pointer(pMWin)).FregStartRowid, int32(1)) } else { _windowAggStep(tls, p, pMWin, csr, int32(1), (*TWindowCodeArg)(unsafe.Pointer(p)).FregArg) } default: csr = (*TWindowCodeArg)(unsafe.Pointer(p)).Fend.Fcsr reg = (*TWindowCodeArg)(unsafe.Pointer(p)).Fend.Freg if (*TWindow)(unsafe.Pointer(pMWin)).FregStartRowid != 0 { _sqlite3VdbeAddOp2(tls, v, int32(OP_AddImm), (*TWindow)(unsafe.Pointer(pMWin)).FregEndRowid, int32(1)) } else { _windowAggStep(tls, p, pMWin, csr, 0, (*TWindowCodeArg)(unsafe.Pointer(p)).FregArg) } break } if op == (*TWindowCodeArg)(unsafe.Pointer(p)).FeDelete { _sqlite3VdbeAddOp1(tls, v, int32(OP_Delete), csr) _sqlite3VdbeChangeP5(tls, v, uint16(OPFLAG_SAVEPOSITION)) } if jumpOnEof != 0 { _sqlite3VdbeAddOp2(tls, v, int32(OP_Next), csr, _sqlite3VdbeCurrentAddr(tls, v)+int32(2)) ret = _sqlite3VdbeAddOp0(tls, v, int32(OP_Goto)) } else { _sqlite3VdbeAddOp2(tls, v, int32(OP_Next), csr, _sqlite3VdbeCurrentAddr(tls, v)+int32(1)+bPeer) if bPeer != 0 { _sqlite3VdbeAddOp2(tls, v, int32(OP_Goto), 0, lblDone) } } if bPeer != 0 { if (*TWindow)(unsafe.Pointer(pMWin)).FpOrderBy != 0 { v1 = (*TExprList)(unsafe.Pointer((*TWindow)(unsafe.Pointer(pMWin)).FpOrderBy)).FnExpr } else { v1 = 0 } nReg = v1 if nReg != 0 { v2 = _sqlite3GetTempRange(tls, pParse, nReg) } else { v2 = 0 } regTmp = v2 _windowReadPeerValues(tls, p, csr, regTmp) _windowIfNewPeer(tls, pParse, (*TWindow)(unsafe.Pointer(pMWin)).FpOrderBy, regTmp, reg, addrContinue) _sqlite3ReleaseTempRange(tls, pParse, regTmp, nReg) } if addrNextRange != 0 { _sqlite3VdbeAddOp2(tls, v, int32(OP_Goto), 0, addrNextRange) } _sqlite3VdbeResolveLabel(tls, v, lblDone) return ret } // C documentation // // /* // ** Generate code to calculate the current values of all window functions in the // ** p->pMWin list by doing a full scan of the current window frame. Store the // ** results in the Window.regResult registers, ready to return the upper // ** layer. // */ func _windowFullScan(tls *libc.TLS, p uintptr) { var addr, addrEq, addrNext, csr, lblBrk, lblNext, nPeer, regCPeer, regCRowid, regPeer, regRowid, v1 int32 var pKeyInfo, pMWin, pParse, pWin, v uintptr _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ = addr, addrEq, addrNext, csr, lblBrk, lblNext, nPeer, pKeyInfo, pMWin, pParse, pWin, regCPeer, regCRowid, regPeer, regRowid, v, v1 pParse = (*TWindowCodeArg)(unsafe.Pointer(p)).FpParse pMWin = (*TWindowCodeArg)(unsafe.Pointer(p)).FpMWin v = (*TWindowCodeArg)(unsafe.Pointer(p)).FpVdbe regCRowid = 0 /* Current rowid value */ regCPeer = 0 /* Current peer values */ regRowid = 0 /* AggStep rowid value */ regPeer = 0 csr = (*TWindow)(unsafe.Pointer(pMWin)).FcsrApp if (*TWindow)(unsafe.Pointer(pMWin)).FpOrderBy != 0 { v1 = (*TExprList)(unsafe.Pointer((*TWindow)(unsafe.Pointer(pMWin)).FpOrderBy)).FnExpr } else { v1 = 0 } nPeer = v1 lblNext = _sqlite3VdbeMakeLabel(tls, pParse) lblBrk = _sqlite3VdbeMakeLabel(tls, pParse) regCRowid = _sqlite3GetTempReg(tls, pParse) regRowid = _sqlite3GetTempReg(tls, pParse) if nPeer != 0 { regCPeer = _sqlite3GetTempRange(tls, pParse, nPeer) regPeer = _sqlite3GetTempRange(tls, pParse, nPeer) } _sqlite3VdbeAddOp2(tls, v, int32(OP_Rowid), (*TWindow)(unsafe.Pointer(pMWin)).FiEphCsr, regCRowid) _windowReadPeerValues(tls, p, (*TWindow)(unsafe.Pointer(pMWin)).FiEphCsr, regCPeer) pWin = pMWin for { if !(pWin != 0) { break } _sqlite3VdbeAddOp2(tls, v, int32(OP_Null), 0, (*TWindow)(unsafe.Pointer(pWin)).FregAccum) goto _2 _2: ; pWin = (*TWindow)(unsafe.Pointer(pWin)).FpNextWin } _sqlite3VdbeAddOp3(tls, v, int32(OP_SeekGE), csr, lblBrk, (*TWindow)(unsafe.Pointer(pMWin)).FregStartRowid) addrNext = _sqlite3VdbeCurrentAddr(tls, v) _sqlite3VdbeAddOp2(tls, v, int32(OP_Rowid), csr, regRowid) _sqlite3VdbeAddOp3(tls, v, int32(OP_Gt), (*TWindow)(unsafe.Pointer(pMWin)).FregEndRowid, lblBrk, regRowid) if libc.Int32FromUint8((*TWindow)(unsafe.Pointer(pMWin)).FeExclude) == int32(TK_CURRENT) { _sqlite3VdbeAddOp3(tls, v, int32(OP_Eq), regCRowid, lblNext, regRowid) } else { if libc.Int32FromUint8((*TWindow)(unsafe.Pointer(pMWin)).FeExclude) != int32(TK_NO) { addrEq = 0 pKeyInfo = uintptr(0) if (*TWindow)(unsafe.Pointer(pMWin)).FpOrderBy != 0 { pKeyInfo = _sqlite3KeyInfoFromExprList(tls, pParse, (*TWindow)(unsafe.Pointer(pMWin)).FpOrderBy, 0, 0) } if libc.Int32FromUint8((*TWindow)(unsafe.Pointer(pMWin)).FeExclude) == int32(TK_TIES) { addrEq = _sqlite3VdbeAddOp3(tls, v, int32(OP_Eq), regCRowid, 0, regRowid) } if pKeyInfo != 0 { _windowReadPeerValues(tls, p, csr, regPeer) _sqlite3VdbeAddOp3(tls, v, int32(OP_Compare), regPeer, regCPeer, nPeer) _sqlite3VdbeAppendP4(tls, v, pKeyInfo, -int32(9)) addr = _sqlite3VdbeCurrentAddr(tls, v) + int32(1) _sqlite3VdbeAddOp3(tls, v, int32(OP_Jump), addr, lblNext, addr) } else { _sqlite3VdbeAddOp2(tls, v, int32(OP_Goto), 0, lblNext) } if addrEq != 0 { _sqlite3VdbeJumpHere(tls, v, addrEq) } } } _windowAggStep(tls, p, pMWin, csr, 0, (*TWindowCodeArg)(unsafe.Pointer(p)).FregArg) _sqlite3VdbeResolveLabel(tls, v, lblNext) _sqlite3VdbeAddOp2(tls, v, int32(OP_Next), csr, addrNext) _sqlite3VdbeJumpHere(tls, v, addrNext-int32(1)) _sqlite3VdbeJumpHere(tls, v, addrNext+int32(1)) _sqlite3ReleaseTempReg(tls, pParse, regRowid) _sqlite3ReleaseTempReg(tls, pParse, regCRowid) if nPeer != 0 { _sqlite3ReleaseTempRange(tls, pParse, regPeer, nPeer) _sqlite3ReleaseTempRange(tls, pParse, regCPeer, nPeer) } _windowAggFinal(tls, p, int32(1)) } // C documentation // // /* // ** Functions to serialize a 16 bit integer, 32 bit real number and // ** 64 bit integer. The value returned is the number of bytes written // ** to the argument buffer (always 2, 4 and 8 respectively). // */ func _writeInt16(tls *libc.TLS, p uintptr, i int32) { **(**Tu8)(__ccgo_up(p)) = libc.Uint8FromInt32(i >> int32(8) & int32(0xFF)) **(**Tu8)(__ccgo_up(p + 1)) = libc.Uint8FromInt32(i >> 0 & int32(0xFF)) } // C documentation // // /* The following function deletes the "minor type" or semantic value // ** associated with a symbol. The symbol can be either a terminal // ** or nonterminal. "yymajor" is the symbol code, and "yypminor" is // ** a pointer to the value to be deleted. The code used to do the // ** deletions is derived from the %destructor and/or %token_destructor // ** directives of the input grammar. // */ func _yy_destructor(tls *libc.TLS, yypParser uintptr, yymajor uint16, yypminor uintptr) { var pParse uintptr _ = pParse pParse = (*TyyParser)(unsafe.Pointer(yypParser)).FpParse switch libc.Int32FromUint16(yymajor) { /* Here is inserted the actions which take place when a ** terminal or non-terminal is destroyed. This can happen ** when the symbol is popped from the stack during a ** reduce or during error processing or when a parser is ** being destroyed before it is finished parsing. ** ** Note: during a reduce, the only symbols destroyed are those ** which appear on the RHS of the rule, but which are *not* used ** inside the C code. */ /********* Begin destructor definitions ***************************************/ case int32(206): /* select */ fallthrough case int32(241): /* selectnowith */ fallthrough case int32(242): /* oneselect */ fallthrough case int32(254): /* values */ fallthrough case int32(256): /* mvalues */ _sqlite3SelectDelete(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, *(*uintptr)(unsafe.Pointer(yypminor))) case int32(218): /* term */ fallthrough case int32(219): /* expr */ fallthrough case int32(248): /* where_opt */ fallthrough case int32(250): /* having_opt */ fallthrough case int32(270): /* where_opt_ret */ fallthrough case int32(281): /* case_operand */ fallthrough case int32(283): /* case_else */ fallthrough case int32(286): /* vinto */ fallthrough case int32(293): /* when_clause */ fallthrough case int32(297): /* key_opt */ fallthrough case int32(314): /* filter_clause */ _sqlite3ExprDelete(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, *(*uintptr)(unsafe.Pointer(yypminor))) case int32(223): /* eidlist_opt */ fallthrough case int32(233): /* sortlist */ fallthrough case int32(234): /* eidlist */ fallthrough case int32(246): /* selcollist */ fallthrough case int32(249): /* groupby_opt */ fallthrough case int32(251): /* orderby_opt */ fallthrough case int32(255): /* nexprlist */ fallthrough case int32(257): /* sclp */ fallthrough case int32(264): /* exprlist */ fallthrough case int32(271): /* setlist */ fallthrough case int32(280): /* paren_exprlist */ fallthrough case int32(282): /* case_exprlist */ fallthrough case int32(313): /* part_opt */ _sqlite3ExprListDelete(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, *(*uintptr)(unsafe.Pointer(yypminor))) case int32(240): /* fullname */ fallthrough case int32(247): /* from */ fallthrough case int32(259): /* seltablist */ fallthrough case int32(260): /* stl_prefix */ fallthrough case int32(265): /* xfullname */ _sqlite3SrcListDelete(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, *(*uintptr)(unsafe.Pointer(yypminor))) case int32(243): /* wqlist */ _sqlite3WithDelete(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, *(*uintptr)(unsafe.Pointer(yypminor))) case int32(253): /* window_clause */ fallthrough case int32(309): /* windowdefn_list */ _sqlite3WindowListDelete(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, *(*uintptr)(unsafe.Pointer(yypminor))) case int32(266): /* idlist */ fallthrough case int32(273): /* idlist_opt */ _sqlite3IdListDelete(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, *(*uintptr)(unsafe.Pointer(yypminor))) case int32(276): /* filter_over */ fallthrough case int32(310): /* windowdefn */ fallthrough case int32(311): /* window */ fallthrough case int32(312): /* frame_opt */ fallthrough case int32(315): /* over_clause */ _sqlite3WindowDelete(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, *(*uintptr)(unsafe.Pointer(yypminor))) case int32(289): /* trigger_cmd_list */ fallthrough case int32(294): /* trigger_cmd */ _sqlite3DeleteTriggerStep(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, *(*uintptr)(unsafe.Pointer(yypminor))) case int32(291): /* trigger_event */ _sqlite3IdListDelete(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, (*(*TTrigEvent)(unsafe.Pointer(yypminor))).Fb) case int32(317): /* frame_bound */ fallthrough case int32(318): /* frame_bound_s */ fallthrough case int32(319): /* frame_bound_e */ _sqlite3ExprDelete(tls, (*TParse)(unsafe.Pointer(pParse)).Fdb, (*(*TFrameBound)(unsafe.Pointer(yypminor))).FpExpr) break /********* End destructor definitions *****************************************/ fallthrough default: break /* If no destructor action specified: do nothing */ } } // C documentation // // /* // ** Find the appropriate action for a parser given the non-terminal // ** look-ahead token iLookAhead. // */ func _yy_find_reduce_action(tls *libc.TLS, stateno uint16, iLookAhead uint16) (r uint16) { var i int32 _ = i i = int32(_yy_reduce_ofst[stateno]) i = i + libc.Int32FromUint16(iLookAhead) return _yy_action[i] } // C documentation // // /* // ** Find the appropriate action for a parser given the terminal // ** look-ahead token iLookAhead. // */ func _yy_find_shift_action(tls *libc.TLS, iLookAhead uint16, stateno uint16) (r uint16) { var i, j int32 var iFallback uint16 _, _, _ = i, iFallback, j if libc.Int32FromUint16(stateno) > int32(YY_MAX_SHIFT) { return stateno } for cond := true; cond; cond = int32(1) != 0 { i = libc.Int32FromUint16(_yy_shift_ofst[stateno]) i = i + libc.Int32FromUint16(iLookAhead) if libc.Int32FromUint16(_yy_lookahead[i]) != libc.Int32FromUint16(iLookAhead) { /* Fallback token */ iFallback = _yyFallback[iLookAhead] if libc.Int32FromUint16(iFallback) != 0 { /* Fallback loop must terminate */ iLookAhead = iFallback continue } j = i - libc.Int32FromUint16(iLookAhead) + int32(YYWILDCARD) if libc.Int32FromUint16(_yy_lookahead[j]) == int32(YYWILDCARD) && libc.Int32FromUint16(iLookAhead) > 0 { return _yy_action[j] } return _yy_default[stateno] } else { return _yy_action[i] } } return r } // C documentation // // /* // ** The journal file must be open when this function is called. // ** // ** This function is a no-op if the journal file has not been written to // ** within the current transaction (i.e. if Pager.journalOff==0). // ** // ** If doTruncate is non-zero or the Pager.journalSizeLimit variable is // ** set to 0, then truncate the journal file to zero bytes in size. Otherwise, // ** zero the 28-byte header at the start of the journal file. In either case, // ** if the pager is not in no-sync mode, sync the journal file immediately // ** after writing or truncating it. // ** // ** If Pager.journalSizeLimit is set to a positive, non-zero value, and // ** following the truncation or zeroing described above the size of the // ** journal file in bytes is larger than this value, then truncate the // ** journal file to Pager.journalSizeLimit bytes. The journal file does // ** not need to be synced following this operation. // ** // ** If an IO error occurs, abandon processing and return the IO error code. // ** Otherwise, return SQLITE_OK. // */ func _zeroJournalHdr(tls *libc.TLS, pPager uintptr, doTruncate int32) (r int32) { bp := tls.Alloc(16) defer tls.Free(16) var iLimit Ti64 var rc int32 var _ /* sz at bp+0 */ Ti64 _, _ = iLimit, rc rc = SQLITE_OK /* Return code */ if (*TPager)(unsafe.Pointer(pPager)).FjournalOff != 0 { iLimit = (*TPager)(unsafe.Pointer(pPager)).FjournalSizeLimit /* Local cache of jsl */ if doTruncate != 0 || iLimit == 0 { rc = _sqlite3OsTruncate(tls, (*TPager)(unsafe.Pointer(pPager)).Fjfd, 0) } else { rc = _sqlite3OsWrite(tls, (*TPager)(unsafe.Pointer(pPager)).Fjfd, uintptr(unsafe.Pointer(&_zeroHdr)), int32(28), 0) } if rc == SQLITE_OK && !((*TPager)(unsafe.Pointer(pPager)).FnoSync != 0) { rc = _sqlite3OsSync(tls, (*TPager)(unsafe.Pointer(pPager)).Fjfd, int32(SQLITE_SYNC_DATAONLY)|libc.Int32FromUint8((*TPager)(unsafe.Pointer(pPager)).FsyncFlags)) } /* At this point the transaction is committed but the write lock ** is still held on the file. If there is a size limit configured for ** the persistent journal and the journal file currently consumes more ** space than that limit allows for, truncate it now. There is no need ** to sync the file following this operation. */ if rc == SQLITE_OK && iLimit > 0 { rc = _sqlite3OsFileSize(tls, (*TPager)(unsafe.Pointer(pPager)).Fjfd, bp) if rc == SQLITE_OK && **(**Ti64)(__ccgo_up(bp)) > iLimit { rc = _sqlite3OsTruncate(tls, (*TPager)(unsafe.Pointer(pPager)).Fjfd, iLimit) } } } return rc } // C documentation // // /* // ** The zeroblob(N) function returns a zero-filled blob of size N bytes. // */ func _zeroblobFunc(tls *libc.TLS, context uintptr, argc int32, argv uintptr) { var n Ti64 var rc int32 _, _ = n, rc _ = argc n = Xsqlite3_value_int64(tls, **(**uintptr)(__ccgo_up(argv))) if n < 0 { n = 0 } rc = Xsqlite3_result_zeroblob64(tls, context, libc.Uint64FromInt64(n)) /* IMP: R-00293-64994 */ if rc != 0 { Xsqlite3_result_error_code(tls, context, rc) } } type blkcnt_t = Tblkcnt_t type blksize_t = Tblksize_t type clockid_t = Tclockid_t type double_t = Tdouble_t const fdatasync = 0 type finder_type = Tfinder_type /**************************************************************************** **************************** sqlite3_vfs methods **************************** ** ** This division contains the implementation of methods on the ** sqlite3_vfs object. */ type flock = Tflock type id_t = Tid_t func init() { p := unsafe.Pointer(&_nolockIoFinder) *(*uintptr)(unsafe.Add(p, 0)) = __ccgo_fp(_nolockIoFinderImpl) } func init() { p := unsafe.Pointer(&_posixIoFinder) *(*uintptr)(unsafe.Add(p, 0)) = __ccgo_fp(_posixIoFinderImpl) } type itimerval = Titimerval type key_t = Tkey_t type nlink_t = Tnlink_t type quad_t = Tquad_t type sigset_t = Tsigset_t type stat = Tstat const static_assert = 0 type suseconds_t = Tsuseconds_t const threadid = 0 type u_int16_t = Tu_int16_t type u_int32_t = Tu_int32_t type u_int64_t = Tu_int64_t type u_int8_t = Tu_int8_t type u_quad_t = Tu_quad_t type uint = Tuint type unixFile = TunixFile type unixFileId = TunixFileId type unixInodeInfo = TunixInodeInfo type unixShm = TunixShm type unixShmNode = TunixShmNode type unix_syscall = Tunix_syscall type ushort = Tushort type vxworksFileId = TvxworksFileId /*************** End of Unique File ID Utility Used By VxWorks **************** ******************************************************************************/ /****************************************************************************** *************************** Posix Advisory Locking **************************** ** ** POSIX advisory locks are broken by design. ANSI STD 1003.1 (1996) ** section 6.5.2.2 lines 483 through 490 specify that when a process ** sets or clears a lock, that operation overrides any prior locks set ** by the same process. It does not explicitly say so, but this implies ** that it overrides locks set by the same process using a different ** file descriptor. Consider this test case: ** ** int fd1 = open("./file1", O_RDWR|O_CREAT, 0644); ** int fd2 = open("./file2", O_RDWR|O_CREAT, 0644); ** ** Suppose ./file1 and ./file2 are really the same file (because ** one is a hard or symbolic link to the other) then if you set ** an exclusive lock on fd1, then try to get an exclusive lock ** on fd2, it works. I would have expected the second lock to ** fail since there was already a lock on the file due to fd1. ** But not so. Since both locks came from the same process, the ** second overrides the first, even though they were on different ** file descriptors opened on different file names. ** ** This means that we cannot use POSIX locks to synchronize file access ** among competing threads of the same process. POSIX locks will work fine ** to synchronize access for threads in separate processes, but not ** threads within the same process. ** ** To work around the problem, SQLite has to manage file locks internally ** on its own. Whenever a new database is opened, we have to find the ** specific inode of the database file (the inode is determined by the ** st_dev and st_ino fields of the stat structure that fstat() fills in) ** and check for locks already existing on that inode. When locks are ** created or removed, we have to look at our own internal record of the ** locks to see if another thread has previously set a lock on that same ** inode. ** ** (Aside: The use of inode numbers as unique IDs does not work on VxWorks. ** For VxWorks, we have to use the alternative unique ID system based on ** canonical filename and implemented in the previous division.) ** ** The sqlite3_file structure for POSIX is no longer just an integer file ** descriptor. It is now a structure that holds the integer file ** descriptor and a pointer to a structure that describes the internal ** locks on the corresponding inode. There is one locking structure ** per inode, so if the same inode is opened twice, both unixFile structures ** point to the same locking structure. The locking structure keeps ** a reference count (so we will know when to delete it) and a "cnt" ** field that tells us its internal lock status. cnt==0 means the ** file is unlocked. cnt==-1 means the file has an exclusive lock. ** cnt>0 means there are cnt shared locks on the file. ** ** Any attempt to lock or unlock a file first checks the locking ** structure. The fcntl() system call is only invoked to set a ** POSIX lock if the internal lock structure transitions between ** a locked and an unlocked state. ** ** But wait: there are yet more problems with POSIX advisory locks. ** ** If you close a file descriptor that points to a file that has locks, ** all locks on that file that are owned by the current process are ** released. To work around this problem, each unixInodeInfo object ** maintains a count of the number of pending locks on the inode. ** When an attempt is made to close an unixFile, if there are ** other unixFile open on the same inode that are holding locks, the call ** to close() the file descriptor is deferred until all of the locks clear. ** The unixInodeInfo structure keeps a list of file descriptors that need to ** be closed and that list is walked (and cleared) when the last lock ** clears. ** ** Yet another problem: LinuxThreads do not play well with posix locks. ** ** Many older versions of linux use the LinuxThreads library which is ** not posix compliant. Under LinuxThreads, a lock created by thread ** A cannot be modified or overridden by a different thread B. ** Only thread A can modify the lock. Locking behavior is correct ** if the application uses the newer Native Posix Thread Library (NPTL) ** on linux - with NPTL a lock created by thread A can override locks ** in thread B. But there is no way to know at compile-time which ** threading library is being used. So there is no way to know at ** compile-time whether or not thread A can override locks on thread B. ** One has to do a run-time check to discover the behavior of the ** current process. ** ** SQLite used to support LinuxThreads. But support for LinuxThreads ** was dropped beginning with version 3.7.0. SQLite will still work with ** LinuxThreads provided that (1) there is no more than one connection ** per database file in the same process and (2) database connections ** do not move across threads. */ type winsize = Twinsize