2021-06-12 16:51:01 +02:00
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
#include "Library/SQLite.hpp"
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
#include <sqratConst.h>
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
#include <ctime>
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
#include <sqstdblob.h>
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
namespace SqMod {
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
// Error message when failed to bind value to parameter index.
|
|
|
|
#define SQMOD_BINDFAILED "Unable to bind ({}) parameter ({}) because [{}]"
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
SQMOD_DECL_TYPENAME(SQLiteConnectionTypename, _SC("SQLiteConnection"))
|
|
|
|
SQMOD_DECL_TYPENAME(SQLiteParameterTypename, _SC("SQLiteParameter"))
|
|
|
|
SQMOD_DECL_TYPENAME(SQLiteColumnTypename, _SC("SQLiteColumn"))
|
|
|
|
SQMOD_DECL_TYPENAME(SQLiteStatementTypename, _SC("SQLiteStatement"))
|
|
|
|
SQMOD_DECL_TYPENAME(SQLiteTransactionTypename, _SC("SQLiteTransaction"))
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
static const EnumElement g_MainEnum[] = {
|
|
|
|
{_SC("ABORT"), SQLITE_ABORT},
|
|
|
|
{_SC("ABORT_ROLLBACK"), SQLITE_ABORT_ROLLBACK},
|
|
|
|
{_SC("ACCESS_EXISTS"), SQLITE_ACCESS_EXISTS},
|
|
|
|
{_SC("ACCESS_READ"), SQLITE_ACCESS_READ},
|
|
|
|
{_SC("ACCESS_READWRITE"), SQLITE_ACCESS_READWRITE},
|
|
|
|
{_SC("ALTER_TABLE"), SQLITE_ALTER_TABLE},
|
|
|
|
{_SC("ANALYZE"), SQLITE_ANALYZE},
|
|
|
|
{_SC("ANY"), SQLITE_ANY},
|
|
|
|
{_SC("ATTACH"), SQLITE_ATTACH},
|
|
|
|
{_SC("AUTH"), SQLITE_AUTH},
|
|
|
|
{_SC("AUTH_USER"), SQLITE_AUTH_USER},
|
|
|
|
{_SC("BLOB"), SQLITE_BLOB},
|
|
|
|
{_SC("BUSY"), SQLITE_BUSY},
|
|
|
|
{_SC("BUSY_RECOVERY"), SQLITE_BUSY_RECOVERY},
|
|
|
|
{_SC("BUSY_SNAPSHOT"), SQLITE_BUSY_SNAPSHOT},
|
|
|
|
{_SC("CANTOPEN"), SQLITE_CANTOPEN},
|
|
|
|
{_SC("CANTOPEN_CONVPATH"), SQLITE_CANTOPEN_CONVPATH},
|
|
|
|
{_SC("CANTOPEN_FULLPATH"), SQLITE_CANTOPEN_FULLPATH},
|
|
|
|
{_SC("CANTOPEN_ISDIR"), SQLITE_CANTOPEN_ISDIR},
|
|
|
|
{_SC("CANTOPEN_NOTEMPDIR"), SQLITE_CANTOPEN_NOTEMPDIR},
|
|
|
|
{_SC("CHECKPOINT_FULL"), SQLITE_CHECKPOINT_FULL},
|
|
|
|
{_SC("CHECKPOINT_PASSIVE"), SQLITE_CHECKPOINT_PASSIVE},
|
|
|
|
{_SC("CHECKPOINT_RESTART"), SQLITE_CHECKPOINT_RESTART},
|
|
|
|
{_SC("CHECKPOINT_TRUNCATE"), SQLITE_CHECKPOINT_TRUNCATE},
|
|
|
|
{_SC("CONFIG_COVERING_INDEX_SCAN"), SQLITE_CONFIG_COVERING_INDEX_SCAN},
|
|
|
|
{_SC("CONFIG_GETMALLOC"), SQLITE_CONFIG_GETMALLOC},
|
|
|
|
{_SC("CONFIG_GETMUTEX"), SQLITE_CONFIG_GETMUTEX},
|
|
|
|
{_SC("CONFIG_GETPCACHE"), SQLITE_CONFIG_GETPCACHE},
|
|
|
|
{_SC("CONFIG_GETPCACHE2"), SQLITE_CONFIG_GETPCACHE2},
|
|
|
|
{_SC("CONFIG_HEAP"), SQLITE_CONFIG_HEAP},
|
|
|
|
{_SC("CONFIG_LOG"), SQLITE_CONFIG_LOG},
|
|
|
|
{_SC("CONFIG_LOOKASIDE"), SQLITE_CONFIG_LOOKASIDE},
|
|
|
|
{_SC("CONFIG_MALLOC"), SQLITE_CONFIG_MALLOC},
|
|
|
|
{_SC("CONFIG_MEMSTATUS"), SQLITE_CONFIG_MEMSTATUS},
|
|
|
|
{_SC("CONFIG_MMAP_SIZE"), SQLITE_CONFIG_MMAP_SIZE},
|
|
|
|
{_SC("CONFIG_MULTITHREAD"), SQLITE_CONFIG_MULTITHREAD},
|
|
|
|
{_SC("CONFIG_MUTEX"), SQLITE_CONFIG_MUTEX},
|
|
|
|
{_SC("CONFIG_PAGECACHE"), SQLITE_CONFIG_PAGECACHE},
|
|
|
|
{_SC("CONFIG_PCACHE"), SQLITE_CONFIG_PCACHE},
|
|
|
|
{_SC("CONFIG_PCACHE2"), SQLITE_CONFIG_PCACHE2},
|
|
|
|
{_SC("CONFIG_PCACHE_HDRSZ"), SQLITE_CONFIG_PCACHE_HDRSZ},
|
|
|
|
{_SC("CONFIG_PMASZ"), SQLITE_CONFIG_PMASZ},
|
|
|
|
{_SC("CONFIG_SCRATCH"), SQLITE_CONFIG_SCRATCH},
|
|
|
|
{_SC("CONFIG_SERIALIZED"), SQLITE_CONFIG_SERIALIZED},
|
|
|
|
{_SC("CONFIG_SINGLETHREAD"), SQLITE_CONFIG_SINGLETHREAD},
|
|
|
|
{_SC("CONFIG_SQLLOG"), SQLITE_CONFIG_SQLLOG},
|
|
|
|
{_SC("CONFIG_URI"), SQLITE_CONFIG_URI},
|
|
|
|
{_SC("CONFIG_WIN32_HEAPSIZE"), SQLITE_CONFIG_WIN32_HEAPSIZE},
|
|
|
|
{_SC("CONSTRAINT"), SQLITE_CONSTRAINT},
|
|
|
|
{_SC("CONSTRAINT_CHECK"), SQLITE_CONSTRAINT_CHECK},
|
|
|
|
{_SC("CONSTRAINT_COMMITHOOK"), SQLITE_CONSTRAINT_COMMITHOOK},
|
|
|
|
{_SC("CONSTRAINT_FOREIGNKEY"), SQLITE_CONSTRAINT_FOREIGNKEY},
|
|
|
|
{_SC("CONSTRAINT_FUNCTION"), SQLITE_CONSTRAINT_FUNCTION},
|
|
|
|
{_SC("CONSTRAINT_NOTNULL"), SQLITE_CONSTRAINT_NOTNULL},
|
|
|
|
{_SC("CONSTRAINT_PRIMARYKEY"), SQLITE_CONSTRAINT_PRIMARYKEY},
|
|
|
|
{_SC("CONSTRAINT_ROWID"), SQLITE_CONSTRAINT_ROWID},
|
|
|
|
{_SC("CONSTRAINT_TRIGGER"), SQLITE_CONSTRAINT_TRIGGER},
|
|
|
|
{_SC("CONSTRAINT_UNIQUE"), SQLITE_CONSTRAINT_UNIQUE},
|
|
|
|
{_SC("CONSTRAINT_VTAB"), SQLITE_CONSTRAINT_VTAB},
|
|
|
|
{_SC("COPY"), SQLITE_COPY},
|
|
|
|
{_SC("CORRUPT"), SQLITE_CORRUPT},
|
|
|
|
{_SC("CORRUPT_VTAB"), SQLITE_CORRUPT_VTAB},
|
|
|
|
{_SC("CREATE_INDEX"), SQLITE_CREATE_INDEX},
|
|
|
|
{_SC("CREATE_TABLE"), SQLITE_CREATE_TABLE},
|
|
|
|
{_SC("CREATE_TEMP_INDEX"), SQLITE_CREATE_TEMP_INDEX},
|
|
|
|
{_SC("CREATE_TEMP_TABLE"), SQLITE_CREATE_TEMP_TABLE},
|
|
|
|
{_SC("CREATE_TEMP_TRIGGER"), SQLITE_CREATE_TEMP_TRIGGER},
|
|
|
|
{_SC("CREATE_TEMP_VIEW"), SQLITE_CREATE_TEMP_VIEW},
|
|
|
|
{_SC("CREATE_TRIGGER"), SQLITE_CREATE_TRIGGER},
|
|
|
|
{_SC("CREATE_VIEW"), SQLITE_CREATE_VIEW},
|
|
|
|
{_SC("CREATE_VTABLE"), SQLITE_CREATE_VTABLE},
|
|
|
|
{_SC("DBCONFIG_ENABLE_FKEY"), SQLITE_DBCONFIG_ENABLE_FKEY},
|
|
|
|
{_SC("DBCONFIG_ENABLE_TRIGGER"), SQLITE_DBCONFIG_ENABLE_TRIGGER},
|
|
|
|
{_SC("DBCONFIG_LOOKASIDE"), SQLITE_DBCONFIG_LOOKASIDE},
|
|
|
|
{_SC("DBSTATUS_CACHE_HIT"), SQLITE_DBSTATUS_CACHE_HIT},
|
|
|
|
{_SC("DBSTATUS_CACHE_MISS"), SQLITE_DBSTATUS_CACHE_MISS},
|
|
|
|
{_SC("DBSTATUS_CACHE_USED"), SQLITE_DBSTATUS_CACHE_USED},
|
|
|
|
{_SC("DBSTATUS_CACHE_WRITE"), SQLITE_DBSTATUS_CACHE_WRITE},
|
|
|
|
{_SC("DBSTATUS_DEFERRED_FKS"), SQLITE_DBSTATUS_DEFERRED_FKS},
|
|
|
|
{_SC("DBSTATUS_LOOKASIDE_HIT"), SQLITE_DBSTATUS_LOOKASIDE_HIT},
|
|
|
|
{_SC("DBSTATUS_LOOKASIDE_MISS_FULL"), SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL},
|
|
|
|
{_SC("DBSTATUS_LOOKASIDE_MISS_SIZE"), SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE},
|
|
|
|
{_SC("DBSTATUS_LOOKASIDE_USED"), SQLITE_DBSTATUS_LOOKASIDE_USED},
|
|
|
|
{_SC("DBSTATUS_MAX"), SQLITE_DBSTATUS_MAX},
|
|
|
|
{_SC("DBSTATUS_SCHEMA_USED"), SQLITE_DBSTATUS_SCHEMA_USED},
|
|
|
|
{_SC("DBSTATUS_STMT_USED"), SQLITE_DBSTATUS_STMT_USED},
|
|
|
|
{_SC("DELETE"), SQLITE_DELETE},
|
|
|
|
{_SC("DENY"), SQLITE_DENY},
|
|
|
|
{_SC("DETACH"), SQLITE_DETACH},
|
|
|
|
{_SC("DETERMINISTIC"), SQLITE_DETERMINISTIC},
|
|
|
|
{_SC("DONE"), SQLITE_DONE},
|
|
|
|
{_SC("DROP_INDEX"), SQLITE_DROP_INDEX},
|
|
|
|
{_SC("DROP_TABLE"), SQLITE_DROP_TABLE},
|
|
|
|
{_SC("DROP_TEMP_INDEX"), SQLITE_DROP_TEMP_INDEX},
|
|
|
|
{_SC("DROP_TEMP_TABLE"), SQLITE_DROP_TEMP_TABLE},
|
|
|
|
{_SC("DROP_TEMP_TRIGGER"), SQLITE_DROP_TEMP_TRIGGER},
|
|
|
|
{_SC("DROP_TEMP_VIEW"), SQLITE_DROP_TEMP_VIEW},
|
|
|
|
{_SC("DROP_TRIGGER"), SQLITE_DROP_TRIGGER},
|
|
|
|
{_SC("DROP_VIEW"), SQLITE_DROP_VIEW},
|
|
|
|
{_SC("DROP_VTABLE"), SQLITE_DROP_VTABLE},
|
|
|
|
{_SC("EMPTY"), SQLITE_EMPTY},
|
|
|
|
{_SC("ERROR"), SQLITE_ERROR},
|
|
|
|
{_SC("FAIL"), SQLITE_FAIL},
|
|
|
|
{_SC("FCNTL_BUSYHANDLER"), SQLITE_FCNTL_BUSYHANDLER},
|
|
|
|
{_SC("FCNTL_CHUNK_SIZE"), SQLITE_FCNTL_CHUNK_SIZE},
|
|
|
|
{_SC("FCNTL_COMMIT_PHASETWO"), SQLITE_FCNTL_COMMIT_PHASETWO},
|
|
|
|
{_SC("FCNTL_FILE_POINTER"), SQLITE_FCNTL_FILE_POINTER},
|
|
|
|
{_SC("FCNTL_GET_LOCKPROXYFILE"), SQLITE_FCNTL_GET_LOCKPROXYFILE},
|
|
|
|
{_SC("FCNTL_HAS_MOVED"), SQLITE_FCNTL_HAS_MOVED},
|
|
|
|
{_SC("FCNTL_LAST_ERRNO"), SQLITE_FCNTL_LAST_ERRNO},
|
|
|
|
{_SC("FCNTL_LOCKSTATE"), SQLITE_FCNTL_LOCKSTATE},
|
|
|
|
{_SC("FCNTL_MMAP_SIZE"), SQLITE_FCNTL_MMAP_SIZE},
|
|
|
|
{_SC("FCNTL_OVERWRITE"), SQLITE_FCNTL_OVERWRITE},
|
|
|
|
{_SC("FCNTL_PERSIST_WAL"), SQLITE_FCNTL_PERSIST_WAL},
|
|
|
|
{_SC("FCNTL_POWERSAFE_OVERWRITE"), SQLITE_FCNTL_POWERSAFE_OVERWRITE},
|
|
|
|
{_SC("FCNTL_PRAGMA"), SQLITE_FCNTL_PRAGMA},
|
|
|
|
{_SC("FCNTL_RBU"), SQLITE_FCNTL_RBU},
|
|
|
|
{_SC("FCNTL_SET_LOCKPROXYFILE"), SQLITE_FCNTL_SET_LOCKPROXYFILE},
|
|
|
|
{_SC("FCNTL_SIZE_HINT"), SQLITE_FCNTL_SIZE_HINT},
|
|
|
|
{_SC("FCNTL_SYNC"), SQLITE_FCNTL_SYNC},
|
|
|
|
{_SC("FCNTL_SYNC_OMITTED"), SQLITE_FCNTL_SYNC_OMITTED},
|
|
|
|
{_SC("FCNTL_TEMPFILENAME"), SQLITE_FCNTL_TEMPFILENAME},
|
|
|
|
{_SC("FCNTL_TRACE"), SQLITE_FCNTL_TRACE},
|
|
|
|
{_SC("FCNTL_VFSNAME"), SQLITE_FCNTL_VFSNAME},
|
|
|
|
{_SC("FCNTL_WAL_BLOCK"), SQLITE_FCNTL_WAL_BLOCK},
|
|
|
|
{_SC("FCNTL_WIN32_AV_RETRY"), SQLITE_FCNTL_WIN32_AV_RETRY},
|
|
|
|
{_SC("FCNTL_WIN32_SET_HANDLE"), SQLITE_FCNTL_WIN32_SET_HANDLE},
|
|
|
|
{_SC("FCNTL_ZIPVFS"), SQLITE_FCNTL_ZIPVFS},
|
|
|
|
{_SC("FLOAT"), SQLITE_FLOAT},
|
|
|
|
{_SC("FORMAT"), SQLITE_FORMAT},
|
|
|
|
{_SC("FULL"), SQLITE_FULL},
|
|
|
|
{_SC("FUNCTION"), SQLITE_FUNCTION},
|
|
|
|
{_SC("IGNORE"), SQLITE_IGNORE},
|
|
|
|
{_SC("INDEX_CONSTRAINT_EQ"), SQLITE_INDEX_CONSTRAINT_EQ},
|
|
|
|
{_SC("INDEX_CONSTRAINT_GE"), SQLITE_INDEX_CONSTRAINT_GE},
|
|
|
|
{_SC("INDEX_CONSTRAINT_GT"), SQLITE_INDEX_CONSTRAINT_GT},
|
|
|
|
{_SC("INDEX_CONSTRAINT_LE"), SQLITE_INDEX_CONSTRAINT_LE},
|
|
|
|
{_SC("INDEX_CONSTRAINT_LT"), SQLITE_INDEX_CONSTRAINT_LT},
|
|
|
|
{_SC("INDEX_CONSTRAINT_MATCH"), SQLITE_INDEX_CONSTRAINT_MATCH},
|
|
|
|
{_SC("INDEX_SCAN_UNIQUE"), SQLITE_INDEX_SCAN_UNIQUE},
|
|
|
|
{_SC("INSERT"), SQLITE_INSERT},
|
|
|
|
{_SC("INTEGER"), SQLITE_INTEGER},
|
|
|
|
{_SC("INTERNAL"), SQLITE_INTERNAL},
|
|
|
|
{_SC("INTERRUPT"), SQLITE_INTERRUPT},
|
|
|
|
{_SC("IOCAP_ATOMIC"), SQLITE_IOCAP_ATOMIC},
|
|
|
|
{_SC("IOCAP_ATOMIC16K"), SQLITE_IOCAP_ATOMIC16K},
|
|
|
|
{_SC("IOCAP_ATOMIC1K"), SQLITE_IOCAP_ATOMIC1K},
|
|
|
|
{_SC("IOCAP_ATOMIC2K"), SQLITE_IOCAP_ATOMIC2K},
|
|
|
|
{_SC("IOCAP_ATOMIC32K"), SQLITE_IOCAP_ATOMIC32K},
|
|
|
|
{_SC("IOCAP_ATOMIC4K"), SQLITE_IOCAP_ATOMIC4K},
|
|
|
|
{_SC("IOCAP_ATOMIC512"), SQLITE_IOCAP_ATOMIC512},
|
|
|
|
{_SC("IOCAP_ATOMIC64K"), SQLITE_IOCAP_ATOMIC64K},
|
|
|
|
{_SC("IOCAP_ATOMIC8K"), SQLITE_IOCAP_ATOMIC8K},
|
|
|
|
{_SC("IOCAP_IMMUTABLE"), SQLITE_IOCAP_IMMUTABLE},
|
|
|
|
{_SC("IOCAP_POWERSAFE_OVERWRITE"), SQLITE_IOCAP_POWERSAFE_OVERWRITE},
|
|
|
|
{_SC("IOCAP_SAFE_APPEND"), SQLITE_IOCAP_SAFE_APPEND},
|
|
|
|
{_SC("IOCAP_SEQUENTIAL"), SQLITE_IOCAP_SEQUENTIAL},
|
|
|
|
{_SC("IOCAP_UNDELETABLE_WHEN_OPEN"), SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN},
|
|
|
|
{_SC("IOERR"), SQLITE_IOERR},
|
|
|
|
{_SC("IOERR_ACCESS"), SQLITE_IOERR_ACCESS},
|
|
|
|
{_SC("IOERR_BLOCKED"), SQLITE_IOERR_BLOCKED},
|
|
|
|
{_SC("IOERR_CHECKRESERVEDLOCK"), SQLITE_IOERR_CHECKRESERVEDLOCK},
|
|
|
|
{_SC("IOERR_CLOSE"), SQLITE_IOERR_CLOSE},
|
|
|
|
{_SC("IOERR_CONVPATH"), SQLITE_IOERR_CONVPATH},
|
|
|
|
{_SC("IOERR_DELETE"), SQLITE_IOERR_DELETE},
|
|
|
|
{_SC("IOERR_DELETE_NOENT"), SQLITE_IOERR_DELETE_NOENT},
|
|
|
|
{_SC("IOERR_DIR_CLOSE"), SQLITE_IOERR_DIR_CLOSE},
|
|
|
|
{_SC("IOERR_DIR_FSYNC"), SQLITE_IOERR_DIR_FSYNC},
|
|
|
|
{_SC("IOERR_FSTAT"), SQLITE_IOERR_FSTAT},
|
|
|
|
{_SC("IOERR_FSYNC"), SQLITE_IOERR_FSYNC},
|
|
|
|
{_SC("IOERR_GETTEMPPATH"), SQLITE_IOERR_GETTEMPPATH},
|
|
|
|
{_SC("IOERR_LOCK"), SQLITE_IOERR_LOCK},
|
|
|
|
{_SC("IOERR_MMAP"), SQLITE_IOERR_MMAP},
|
|
|
|
{_SC("IOERR_NOMEM"), SQLITE_IOERR_NOMEM},
|
|
|
|
{_SC("IOERR_RDLOCK"), SQLITE_IOERR_RDLOCK},
|
|
|
|
{_SC("IOERR_READ"), SQLITE_IOERR_READ},
|
|
|
|
{_SC("IOERR_SEEK"), SQLITE_IOERR_SEEK},
|
|
|
|
{_SC("IOERR_SHMLOCK"), SQLITE_IOERR_SHMLOCK},
|
|
|
|
{_SC("IOERR_SHMMAP"), SQLITE_IOERR_SHMMAP},
|
|
|
|
{_SC("IOERR_SHMOPEN"), SQLITE_IOERR_SHMOPEN},
|
|
|
|
{_SC("IOERR_SHMSIZE"), SQLITE_IOERR_SHMSIZE},
|
|
|
|
{_SC("IOERR_SHORT_READ"), SQLITE_IOERR_SHORT_READ},
|
|
|
|
{_SC("IOERR_TRUNCATE"), SQLITE_IOERR_TRUNCATE},
|
|
|
|
{_SC("IOERR_UNLOCK"), SQLITE_IOERR_UNLOCK},
|
|
|
|
{_SC("IOERR_VNODE"), SQLITE_IOERR_VNODE},
|
|
|
|
{_SC("IOERR_WRITE"), SQLITE_IOERR_WRITE},
|
|
|
|
{_SC("LIMIT_ATTACHED"), SQLITE_LIMIT_ATTACHED},
|
|
|
|
{_SC("LIMIT_COLUMN"), SQLITE_LIMIT_COLUMN},
|
|
|
|
{_SC("LIMIT_COMPOUND_SELECT"), SQLITE_LIMIT_COMPOUND_SELECT},
|
|
|
|
{_SC("LIMIT_EXPR_DEPTH"), SQLITE_LIMIT_EXPR_DEPTH},
|
|
|
|
{_SC("LIMIT_FUNCTION_ARG"), SQLITE_LIMIT_FUNCTION_ARG},
|
|
|
|
{_SC("LIMIT_LENGTH"), SQLITE_LIMIT_LENGTH},
|
|
|
|
{_SC("LIMIT_LIKE_PATTERN_LENGTH"), SQLITE_LIMIT_LIKE_PATTERN_LENGTH},
|
|
|
|
{_SC("LIMIT_SQL_LENGTH"), SQLITE_LIMIT_SQL_LENGTH},
|
|
|
|
{_SC("LIMIT_TRIGGER_DEPTH"), SQLITE_LIMIT_TRIGGER_DEPTH},
|
|
|
|
{_SC("LIMIT_VARIABLE_NUMBER"), SQLITE_LIMIT_VARIABLE_NUMBER},
|
|
|
|
{_SC("LIMIT_VDBE_OP"), SQLITE_LIMIT_VDBE_OP},
|
|
|
|
{_SC("LIMIT_WORKER_THREADS"), SQLITE_LIMIT_WORKER_THREADS},
|
|
|
|
{_SC("LOCKED"), SQLITE_LOCKED},
|
|
|
|
{_SC("LOCKED_SHAREDCACHE"), SQLITE_LOCKED_SHAREDCACHE},
|
|
|
|
{_SC("LOCK_EXCLUSIVE"), SQLITE_LOCK_EXCLUSIVE},
|
|
|
|
{_SC("LOCK_NONE"), SQLITE_LOCK_NONE},
|
|
|
|
{_SC("LOCK_PENDING"), SQLITE_LOCK_PENDING},
|
|
|
|
{_SC("LOCK_RESERVED"), SQLITE_LOCK_RESERVED},
|
|
|
|
{_SC("LOCK_SHARED"), SQLITE_LOCK_SHARED},
|
|
|
|
{_SC("MISMATCH"), SQLITE_MISMATCH},
|
|
|
|
{_SC("MISUSE"), SQLITE_MISUSE},
|
|
|
|
{_SC("MUTEX_FAST"), SQLITE_MUTEX_FAST},
|
|
|
|
{_SC("MUTEX_RECURSIVE"), SQLITE_MUTEX_RECURSIVE},
|
|
|
|
{_SC("MUTEX_STATIC_APP1"), SQLITE_MUTEX_STATIC_APP1},
|
|
|
|
{_SC("MUTEX_STATIC_APP2"), SQLITE_MUTEX_STATIC_APP2},
|
|
|
|
{_SC("MUTEX_STATIC_APP3"), SQLITE_MUTEX_STATIC_APP3},
|
|
|
|
{_SC("MUTEX_STATIC_LRU"), SQLITE_MUTEX_STATIC_LRU},
|
|
|
|
{_SC("MUTEX_STATIC_LRU2"), SQLITE_MUTEX_STATIC_LRU2},
|
|
|
|
{_SC("MUTEX_STATIC_MASTER"), SQLITE_MUTEX_STATIC_MASTER},
|
|
|
|
{_SC("MUTEX_STATIC_MEM"), SQLITE_MUTEX_STATIC_MEM},
|
|
|
|
{_SC("MUTEX_STATIC_MEM2"), SQLITE_MUTEX_STATIC_MEM2},
|
|
|
|
{_SC("MUTEX_STATIC_OPEN"), SQLITE_MUTEX_STATIC_OPEN},
|
|
|
|
{_SC("MUTEX_STATIC_PMEM"), SQLITE_MUTEX_STATIC_PMEM},
|
|
|
|
{_SC("MUTEX_STATIC_PRNG"), SQLITE_MUTEX_STATIC_PRNG},
|
|
|
|
{_SC("MUTEX_STATIC_VFS1"), SQLITE_MUTEX_STATIC_VFS1},
|
|
|
|
{_SC("MUTEX_STATIC_VFS2"), SQLITE_MUTEX_STATIC_VFS2},
|
|
|
|
{_SC("MUTEX_STATIC_VFS3"), SQLITE_MUTEX_STATIC_VFS3},
|
|
|
|
{_SC("NOLFS"), SQLITE_NOLFS},
|
|
|
|
{_SC("NOMEM"), SQLITE_NOMEM},
|
|
|
|
{_SC("NOTADB"), SQLITE_NOTADB},
|
|
|
|
{_SC("NOTFOUND"), SQLITE_NOTFOUND},
|
|
|
|
{_SC("NOTICE"), SQLITE_NOTICE},
|
|
|
|
{_SC("NOTICE_RECOVER_ROLLBACK"), SQLITE_NOTICE_RECOVER_ROLLBACK},
|
|
|
|
{_SC("NOTICE_RECOVER_WAL"), SQLITE_NOTICE_RECOVER_WAL},
|
|
|
|
{_SC("NULL"), SQLITE_NULL},
|
|
|
|
{_SC("OK"), SQLITE_OK},
|
|
|
|
{_SC("OPEN_AUTOPROXY"), SQLITE_OPEN_AUTOPROXY},
|
|
|
|
{_SC("OPEN_CREATE"), SQLITE_OPEN_CREATE},
|
|
|
|
{_SC("OPEN_DELETEONCLOSE"), SQLITE_OPEN_DELETEONCLOSE},
|
|
|
|
{_SC("OPEN_EXCLUSIVE"), SQLITE_OPEN_EXCLUSIVE},
|
|
|
|
{_SC("OPEN_FULLMUTEX"), SQLITE_OPEN_FULLMUTEX},
|
|
|
|
{_SC("OPEN_MAIN_DB"), SQLITE_OPEN_MAIN_DB},
|
|
|
|
{_SC("OPEN_MAIN_JOURNAL"), SQLITE_OPEN_MAIN_JOURNAL},
|
|
|
|
{_SC("OPEN_MASTER_JOURNAL"), SQLITE_OPEN_MASTER_JOURNAL},
|
|
|
|
{_SC("OPEN_MEMORY"), SQLITE_OPEN_MEMORY},
|
|
|
|
{_SC("OPEN_NOMUTEX"), SQLITE_OPEN_NOMUTEX},
|
|
|
|
{_SC("OPEN_PRIVATECACHE"), SQLITE_OPEN_PRIVATECACHE},
|
|
|
|
{_SC("OPEN_READONLY"), SQLITE_OPEN_READONLY},
|
|
|
|
{_SC("OPEN_READWRITE"), SQLITE_OPEN_READWRITE},
|
|
|
|
{_SC("OPEN_SHAREDCACHE"), SQLITE_OPEN_SHAREDCACHE},
|
|
|
|
{_SC("OPEN_SUBJOURNAL"), SQLITE_OPEN_SUBJOURNAL},
|
|
|
|
{_SC("OPEN_TEMP_DB"), SQLITE_OPEN_TEMP_DB},
|
|
|
|
{_SC("OPEN_TEMP_JOURNAL"), SQLITE_OPEN_TEMP_JOURNAL},
|
|
|
|
{_SC("OPEN_TRANSIENT_DB"), SQLITE_OPEN_TRANSIENT_DB},
|
|
|
|
{_SC("OPEN_URI"), SQLITE_OPEN_URI},
|
|
|
|
{_SC("OPEN_WAL"), SQLITE_OPEN_WAL},
|
|
|
|
{_SC("PERM"), SQLITE_PERM},
|
|
|
|
{_SC("PRAGMA"), SQLITE_PRAGMA},
|
|
|
|
{_SC("PROTOCOL"), SQLITE_PROTOCOL},
|
|
|
|
{_SC("RANGE"), SQLITE_RANGE},
|
|
|
|
{_SC("READ"), SQLITE_READ},
|
|
|
|
{_SC("READONLY"), SQLITE_READONLY},
|
|
|
|
{_SC("READONLY_CANTLOCK"), SQLITE_READONLY_CANTLOCK},
|
|
|
|
{_SC("READONLY_DBMOVED"), SQLITE_READONLY_DBMOVED},
|
|
|
|
{_SC("READONLY_RECOVERY"), SQLITE_READONLY_RECOVERY},
|
|
|
|
{_SC("READONLY_ROLLBACK"), SQLITE_READONLY_ROLLBACK},
|
|
|
|
{_SC("RECURSIVE"), SQLITE_RECURSIVE},
|
|
|
|
{_SC("REINDEX"), SQLITE_REINDEX},
|
|
|
|
{_SC("REPLACE"), SQLITE_REPLACE},
|
|
|
|
{_SC("ROLLBACK"), SQLITE_ROLLBACK},
|
|
|
|
{_SC("ROW"), SQLITE_ROW},
|
|
|
|
{_SC("SAVEPOINT"), SQLITE_SAVEPOINT},
|
|
|
|
{_SC("SCANSTAT_EST"), SQLITE_SCANSTAT_EST},
|
|
|
|
{_SC("SCANSTAT_EXPLAIN"), SQLITE_SCANSTAT_EXPLAIN},
|
|
|
|
{_SC("SCANSTAT_NAME"), SQLITE_SCANSTAT_NAME},
|
|
|
|
{_SC("SCANSTAT_NLOOP"), SQLITE_SCANSTAT_NLOOP},
|
|
|
|
{_SC("SCANSTAT_NVISIT"), SQLITE_SCANSTAT_NVISIT},
|
|
|
|
{_SC("SCANSTAT_SELECTID"), SQLITE_SCANSTAT_SELECTID},
|
|
|
|
{_SC("SCHEMA"), SQLITE_SCHEMA},
|
|
|
|
{_SC("SELECT"), SQLITE_SELECT},
|
|
|
|
{_SC("SHM_EXCLUSIVE"), SQLITE_SHM_EXCLUSIVE},
|
|
|
|
{_SC("SHM_LOCK"), SQLITE_SHM_LOCK},
|
|
|
|
{_SC("SHM_NLOCK"), SQLITE_SHM_NLOCK},
|
|
|
|
{_SC("SHM_SHARED"), SQLITE_SHM_SHARED},
|
|
|
|
{_SC("SHM_UNLOCK"), SQLITE_SHM_UNLOCK},
|
|
|
|
{_SC("STATUS_MALLOC_COUNT"), SQLITE_STATUS_MALLOC_COUNT},
|
|
|
|
{_SC("STATUS_MALLOC_SIZE"), SQLITE_STATUS_MALLOC_SIZE},
|
|
|
|
{_SC("STATUS_MEMORY_USED"), SQLITE_STATUS_MEMORY_USED},
|
|
|
|
{_SC("STATUS_PAGECACHE_OVERFLOW"), SQLITE_STATUS_PAGECACHE_OVERFLOW},
|
|
|
|
{_SC("STATUS_PAGECACHE_SIZE"), SQLITE_STATUS_PAGECACHE_SIZE},
|
|
|
|
{_SC("STATUS_PAGECACHE_USED"), SQLITE_STATUS_PAGECACHE_USED},
|
|
|
|
{_SC("STATUS_PARSER_STACK"), SQLITE_STATUS_PARSER_STACK},
|
|
|
|
{_SC("STATUS_SCRATCH_OVERFLOW"), SQLITE_STATUS_SCRATCH_OVERFLOW},
|
|
|
|
{_SC("STATUS_SCRATCH_SIZE"), SQLITE_STATUS_SCRATCH_SIZE},
|
|
|
|
{_SC("STATUS_SCRATCH_USED"), SQLITE_STATUS_SCRATCH_USED},
|
|
|
|
{_SC("STMTSTATUS_AUTOINDEX"), SQLITE_STMTSTATUS_AUTOINDEX},
|
|
|
|
{_SC("STMTSTATUS_FULLSCAN_STEP"), SQLITE_STMTSTATUS_FULLSCAN_STEP},
|
|
|
|
{_SC("STMTSTATUS_SORT"), SQLITE_STMTSTATUS_SORT},
|
|
|
|
{_SC("STMTSTATUS_VM_STEP"), SQLITE_STMTSTATUS_VM_STEP},
|
|
|
|
{_SC("SYNC_DATAONLY"), SQLITE_SYNC_DATAONLY},
|
|
|
|
{_SC("SYNC_FULL"), SQLITE_SYNC_FULL},
|
|
|
|
{_SC("SYNC_NORMAL"), SQLITE_SYNC_NORMAL},
|
|
|
|
{_SC("TESTCTRL_ALWAYS"), SQLITE_TESTCTRL_ALWAYS},
|
|
|
|
{_SC("TESTCTRL_ASSERT"), SQLITE_TESTCTRL_ASSERT},
|
|
|
|
{_SC("TESTCTRL_BENIGN_MALLOC_HOOKS"), SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS},
|
|
|
|
{_SC("TESTCTRL_BITVEC_TEST"), SQLITE_TESTCTRL_BITVEC_TEST},
|
|
|
|
{_SC("TESTCTRL_BYTEORDER"), SQLITE_TESTCTRL_BYTEORDER},
|
|
|
|
{_SC("TESTCTRL_EXPLAIN_STMT"), SQLITE_TESTCTRL_EXPLAIN_STMT},
|
|
|
|
{_SC("TESTCTRL_FAULT_INSTALL"), SQLITE_TESTCTRL_FAULT_INSTALL},
|
|
|
|
{_SC("TESTCTRL_FIRST"), SQLITE_TESTCTRL_FIRST},
|
|
|
|
{_SC("TESTCTRL_IMPOSTER"), SQLITE_TESTCTRL_IMPOSTER},
|
|
|
|
{_SC("TESTCTRL_ISINIT"), SQLITE_TESTCTRL_ISINIT},
|
|
|
|
{_SC("TESTCTRL_ISKEYWORD"), SQLITE_TESTCTRL_ISKEYWORD},
|
|
|
|
{_SC("TESTCTRL_LAST"), SQLITE_TESTCTRL_LAST},
|
|
|
|
{_SC("TESTCTRL_LOCALTIME_FAULT"), SQLITE_TESTCTRL_LOCALTIME_FAULT},
|
|
|
|
{_SC("TESTCTRL_NEVER_CORRUPT"), SQLITE_TESTCTRL_NEVER_CORRUPT},
|
|
|
|
{_SC("TESTCTRL_OPTIMIZATIONS"), SQLITE_TESTCTRL_OPTIMIZATIONS},
|
|
|
|
{_SC("TESTCTRL_PENDING_BYTE"), SQLITE_TESTCTRL_PENDING_BYTE},
|
|
|
|
{_SC("TESTCTRL_PRNG_RESET"), SQLITE_TESTCTRL_PRNG_RESET},
|
|
|
|
{_SC("TESTCTRL_PRNG_RESTORE"), SQLITE_TESTCTRL_PRNG_RESTORE},
|
|
|
|
{_SC("TESTCTRL_PRNG_SAVE"), SQLITE_TESTCTRL_PRNG_SAVE},
|
|
|
|
{_SC("TESTCTRL_RESERVE"), SQLITE_TESTCTRL_RESERVE},
|
|
|
|
{_SC("TESTCTRL_SCRATCHMALLOC"), SQLITE_TESTCTRL_SCRATCHMALLOC},
|
|
|
|
{_SC("TESTCTRL_SORTER_MMAP"), SQLITE_TESTCTRL_SORTER_MMAP},
|
|
|
|
{_SC("TESTCTRL_VDBE_COVERAGE"), SQLITE_TESTCTRL_VDBE_COVERAGE},
|
|
|
|
{_SC("TEXT"), SQLITE_TEXT},
|
|
|
|
{_SC("TOOBIG"), SQLITE_TOOBIG},
|
|
|
|
{_SC("TRANSACTION"), SQLITE_TRANSACTION},
|
|
|
|
{_SC("UPDATE"), SQLITE_UPDATE},
|
|
|
|
{_SC("UTF16"), SQLITE_UTF16},
|
|
|
|
{_SC("UTF16BE"), SQLITE_UTF16BE},
|
|
|
|
{_SC("UTF16LE"), SQLITE_UTF16LE},
|
|
|
|
{_SC("UTF16_ALIGNED"), SQLITE_UTF16_ALIGNED},
|
|
|
|
{_SC("UTF8"), SQLITE_UTF8},
|
|
|
|
{_SC("VERSION_NUMBER"), SQLITE_VERSION_NUMBER},
|
|
|
|
{_SC("VTAB_CONSTRAINT_SUPPORT"), SQLITE_VTAB_CONSTRAINT_SUPPORT},
|
|
|
|
{_SC("WARNING"), SQLITE_WARNING},
|
|
|
|
{_SC("WARNING_AUTOINDEX"), SQLITE_WARNING_AUTOINDEX}
|
|
|
|
};
|
|
|
|
|
2022-07-04 18:39:41 +02:00
|
|
|
// ------------------------------------------------------------------------------------------------
|
2022-07-19 18:29:32 +02:00
|
|
|
LightObj GetSQLiteFromSession(Poco::Data::SessionImpl * session)
|
2022-07-04 18:39:41 +02:00
|
|
|
{
|
|
|
|
// Create a reference counted connection handle instance
|
|
|
|
SQLiteConnRef ref(new SQLiteConnHnd(session));
|
|
|
|
// Transform it into a connection instance and yield it as a script object
|
|
|
|
return LightObj(SqTypeIdentity< SQLiteConnection >{}, SqVM(), ref);
|
|
|
|
}
|
|
|
|
|
2021-06-12 16:51:01 +02:00
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
static inline bool IsDigitsOnly(const SQChar * str)
|
|
|
|
{
|
|
|
|
while (std::isdigit(*str) || std::isspace(*str))
|
|
|
|
{
|
|
|
|
++str;
|
|
|
|
}
|
|
|
|
// Return whether we reached the end while searching
|
|
|
|
return *str == '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
2022-07-04 18:39:41 +02:00
|
|
|
Object GetConnectionObj(const SQLiteConnRef & conn)
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
return Object(new SQLiteConnection(conn));
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
2022-07-04 18:39:41 +02:00
|
|
|
Object GetStatementObj(const SQLiteStmtRef & stmt)
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
return Object(new SQLiteStatement(stmt));
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
bool IsQueryEmpty(const SQChar * str)
|
|
|
|
{
|
|
|
|
// Is the pointer valid?
|
|
|
|
if (!str || *str == '\0')
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// See if the query contains any alpha numeric characters
|
|
|
|
while (*str != 0)
|
|
|
|
{
|
|
|
|
if (std::isalnum(*(str++)) != 0)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// At this point we consider the query empty
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
const SQChar * GetErrStr(int32_t status)
|
|
|
|
{
|
|
|
|
return sqlite3_errstr(status);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SetSoftHeapLimit(int32_t limit)
|
|
|
|
{
|
|
|
|
sqlite3_soft_heap_limit(limit);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
int32_t ReleaseMemory(int32_t bytes)
|
|
|
|
{
|
|
|
|
return sqlite3_release_memory(bytes);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
2021-09-10 20:27:28 +02:00
|
|
|
SQInteger GetMemoryUsage()
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
// Obtain the initial stack size
|
|
|
|
const StackGuard sg;
|
|
|
|
// Push a long integer instance with the requested value on the stack
|
2021-09-10 20:27:28 +02:00
|
|
|
return sqlite3_memory_used();
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
2021-09-10 20:27:28 +02:00
|
|
|
SQInteger GetMemoryHighwaterMark(bool reset)
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
// Obtain the initial stack size
|
|
|
|
const StackGuard sg;
|
|
|
|
// Push a long integer instance with the requested value on the stack
|
2021-09-10 20:27:28 +02:00
|
|
|
return sqlite3_memory_highwater(reset);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
LightObj EscapeString(StackStrF & str)
|
|
|
|
{
|
|
|
|
// Is there even a string to escape?
|
|
|
|
if (str.mLen <= 0)
|
|
|
|
{
|
|
|
|
return LightObj(_SC(""), 0); // Default to empty string
|
|
|
|
}
|
|
|
|
// Allocate a memory buffer
|
|
|
|
std::vector< SQChar > b;
|
2021-09-12 14:12:35 +02:00
|
|
|
// Allocate extra space to make sure there's room for a null terminator since we need it
|
|
|
|
// This is a f* up from SQLite devs not returning the number of written characters from snprintf
|
|
|
|
// So we can figure out if we actually had room for the null terminator or not
|
2021-09-12 14:13:20 +02:00
|
|
|
b.reserve(static_cast< size_t >(str.mLen * 2 + 1));
|
2021-06-12 16:51:01 +02:00
|
|
|
// Attempt to escape the specified string
|
|
|
|
sqlite3_snprintf(static_cast<int>(b.capacity()), b.data(), "%q", str.mPtr);
|
|
|
|
// Return the resulted string
|
2021-09-12 14:12:35 +02:00
|
|
|
LightObj o(b.data(), -1);
|
|
|
|
return o;
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
LightObj EscapeStringEx(SQChar spec, StackStrF & str)
|
|
|
|
{
|
|
|
|
// Validate the specified format specifier
|
|
|
|
if ((spec != 'q') && (spec != 'Q') && (spec != 'w') && (spec != 's'))
|
|
|
|
{
|
|
|
|
STHROWF("Unknown format specifier: '{:c}'", spec);
|
|
|
|
}
|
|
|
|
// Is there even a string to escape?
|
|
|
|
else if (!str.mLen)
|
|
|
|
{
|
|
|
|
return LightObj(_SC(""), 0); // Default to empty string
|
|
|
|
}
|
|
|
|
// Utility that allows changing the format specifier temporarily
|
|
|
|
SQChar fs[] = _SC("%q");
|
|
|
|
// Apply the format specifier
|
|
|
|
fs[1] = spec;
|
|
|
|
// Allocate a memory buffer
|
|
|
|
std::vector< SQChar > b;
|
2021-09-12 14:12:35 +02:00
|
|
|
// Allocate extra space to make sure there's room for a null terminator since we need it (see above)
|
2021-09-12 14:13:20 +02:00
|
|
|
b.reserve(static_cast< size_t >(str.mLen * 2 + 1));
|
2021-06-12 16:51:01 +02:00
|
|
|
// Attempt to escape the specified string
|
|
|
|
sqlite3_snprintf(static_cast<int>(b.capacity()), b.data(), fs, str.mPtr);
|
|
|
|
// Return the resulted string
|
|
|
|
return LightObj(b.data());
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
LightObj ArrayToQueryColumns(Array & arr)
|
|
|
|
{
|
|
|
|
// Do we even have any elements to process?
|
|
|
|
if (arr.Length() <= 0)
|
|
|
|
{
|
|
|
|
return LightObj(_SC(""), 0); // Default to empty string
|
|
|
|
}
|
|
|
|
size_t size_estimate = 0;
|
|
|
|
// Allocate a vector with the required amount of column names
|
|
|
|
std::vector< String > values(static_cast< size_t >(arr.Length()));
|
|
|
|
// Attempt to extract the array elements as strings
|
|
|
|
arr.GetArray< String >(&values[0], static_cast<int>(values.size()));
|
|
|
|
// Attempt to estimate the size of the buffer we'll need
|
|
|
|
for (const auto & v : values) size_estimate += v.size();
|
|
|
|
// Used to know the position of the next column name
|
|
|
|
size_t offset = 0;
|
|
|
|
// Obtain the start of the array
|
|
|
|
auto itr = values.begin();
|
|
|
|
// Allocate a memory buffer
|
|
|
|
std::vector< SQChar > b;
|
|
|
|
b.reserve(size_estimate + (size_estimate / 2));
|
|
|
|
// Process all elements within range
|
|
|
|
for (; itr != values.end() && offset < b.capacity(); ++itr)
|
|
|
|
{
|
|
|
|
// Is the name valid?
|
|
|
|
if (itr->empty())
|
|
|
|
{
|
|
|
|
STHROWF("Invalid column name");
|
|
|
|
}
|
|
|
|
// Attempt to append the column name to the buffer
|
|
|
|
sqlite3_snprintf(static_cast< int >(b.capacity() - offset), b.data() + offset, "[%q], ", itr->c_str());
|
|
|
|
// Add the column name size to the offset
|
|
|
|
offset += itr->size();
|
|
|
|
// Also include the comma and space in the offset
|
|
|
|
offset += 2;
|
|
|
|
}
|
|
|
|
// Trim the last coma and space
|
|
|
|
if (offset >= 2)
|
|
|
|
{
|
|
|
|
b.data()[offset-2] = '\0'; // NOLINT(readability-simplify-subscript-expr)
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
b.data()[0] = '\0'; // NOLINT(readability-simplify-subscript-expr)
|
|
|
|
}
|
|
|
|
// Return the resulted string
|
|
|
|
return LightObj(b.data());
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
LightObj TableToQueryColumns(Table & tbl)
|
|
|
|
{
|
|
|
|
auto len = tbl.GetSize();
|
|
|
|
// Do we even have any elements to process?
|
|
|
|
if (len <= 0)
|
|
|
|
{
|
|
|
|
return LightObj(_SC(""), 0); // Default to empty string
|
|
|
|
}
|
|
|
|
size_t size_estimate = 0;
|
|
|
|
// Allocate a vector with the required amount of column names
|
|
|
|
std::vector< String > values(static_cast< size_t >(len));
|
|
|
|
// Process all elements within range
|
|
|
|
for (Table::iterator itr; tbl.Next(itr);)
|
|
|
|
{
|
|
|
|
// Transform the key to string
|
|
|
|
values.emplace_back(itr.getName());
|
|
|
|
// Add to buffer size estimate
|
|
|
|
size_estimate += values.back().size();
|
|
|
|
}
|
|
|
|
// Used to know the position of the next column name
|
|
|
|
size_t offset = 0;
|
|
|
|
// Obtain the start of the array
|
|
|
|
auto itr = values.begin();
|
|
|
|
// Allocate a memory buffer
|
|
|
|
std::vector< SQChar > b;
|
|
|
|
b.reserve(size_estimate + (size_estimate / 2));
|
|
|
|
// Process all elements within range
|
|
|
|
for (; itr != values.end() && offset < b.capacity(); ++itr)
|
|
|
|
{
|
|
|
|
// Is the name valid?
|
|
|
|
if (itr->empty())
|
|
|
|
{
|
|
|
|
STHROWF("Invalid column name");
|
|
|
|
}
|
|
|
|
// Attempt to append the column name to the buffer
|
|
|
|
sqlite3_snprintf(static_cast< int >(b.capacity() - offset), b.data() + offset, "[%q], ", itr->c_str());
|
|
|
|
// Add the column name size to the offset
|
|
|
|
offset += itr->size();
|
|
|
|
// Also include the comma and space in the offset
|
|
|
|
offset += 2;
|
|
|
|
}
|
|
|
|
// Trim the last coma and space
|
|
|
|
if (offset >= 2)
|
|
|
|
{
|
|
|
|
b.data()[offset-2] = '\0'; // NOLINT(readability-simplify-subscript-expr)
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
b.data()[0] = '\0'; // NOLINT(readability-simplify-subscript-expr)
|
|
|
|
}
|
|
|
|
// Return the resulted string
|
|
|
|
return LightObj(b.data());
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
SQLiteConnHnd::SQLiteConnHnd()
|
|
|
|
: mPtr(nullptr)
|
|
|
|
, mStatus(SQLITE_OK)
|
|
|
|
, mQueue()
|
|
|
|
, mFlags(0)
|
|
|
|
, mName()
|
|
|
|
, mVFS()
|
2022-07-04 18:39:41 +02:00
|
|
|
, mSession()
|
2021-06-12 16:51:01 +02:00
|
|
|
, mMemory(false)
|
|
|
|
, mTrace(false)
|
|
|
|
, mProfile(false)
|
|
|
|
{
|
|
|
|
/* ... */
|
|
|
|
}
|
|
|
|
|
2022-07-04 18:39:41 +02:00
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
SQLiteConnHnd::SQLiteConnHnd(Poco::Data::SessionImpl * session)
|
|
|
|
: SQLiteConnHnd()
|
|
|
|
{
|
2022-07-19 18:29:32 +02:00
|
|
|
mSession.assign(session, true);
|
|
|
|
// Retrieve the internal handle property
|
|
|
|
mPtr = Poco::AnyCast< sqlite3 * >(session->getProperty("handle"));
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
SQLiteConnHnd::SQLiteConnHnd(Poco::AutoPtr< Poco::Data::SessionImpl > && session)
|
|
|
|
: SQLiteConnHnd()
|
|
|
|
{
|
|
|
|
mSession == std::forward< Poco::AutoPtr< Poco::Data::SessionImpl > >(session);
|
2022-07-04 18:39:41 +02:00
|
|
|
// Retrieve the internal handle property
|
|
|
|
mPtr = Poco::AnyCast< sqlite3 * >(session->getProperty("handle"));
|
|
|
|
}
|
|
|
|
|
2021-06-12 16:51:01 +02:00
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
SQLiteConnHnd::~SQLiteConnHnd()
|
|
|
|
{
|
|
|
|
// Is there anything to close?
|
|
|
|
if (mPtr != nullptr)
|
|
|
|
{
|
|
|
|
// Flush remaining queries in the queue and ignore the result
|
|
|
|
Flush(static_cast<uint32_t>(mQueue.size()), NullObject(), NullFunction());
|
|
|
|
// NOTE: Should we call sqlite3_interrupt(...) before closing?
|
|
|
|
// Attempt to close the database
|
2022-07-04 18:39:41 +02:00
|
|
|
// If this connection is a pooled session then let it clean itself up
|
|
|
|
if (mSession.isNull() && (sqlite3_close(mPtr)) != SQLITE_OK)
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
LogErr("Unable to close SQLite connection [%s]", sqlite3_errmsg(mPtr));
|
|
|
|
}
|
2022-07-04 18:39:41 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
mSession.reset();
|
|
|
|
}
|
|
|
|
// Prevent further use of this connection
|
|
|
|
mPtr = nullptr;
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteConnHnd::Create(const SQChar * name, int32_t flags, const SQChar * vfs)
|
|
|
|
{
|
|
|
|
// Make sure a previous connection doesn't exist
|
2022-07-19 18:29:32 +02:00
|
|
|
if (Access())
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
STHROWF("Unable to connect to database. Database already connected");
|
|
|
|
}
|
|
|
|
// Make sure the name is valid
|
|
|
|
else if (!name || *name == '\0')
|
|
|
|
{
|
|
|
|
STHROWF("Unable to connect to database. The name is invalid");
|
|
|
|
}
|
|
|
|
// Attempt to create the database connection
|
|
|
|
else if ((mStatus = sqlite3_open_v2(name, &mPtr, flags, vfs)) != SQLITE_OK)
|
|
|
|
{
|
|
|
|
// Grab the error message before destroying the handle
|
|
|
|
String msg(sqlite3_errmsg(mPtr) ? sqlite3_errmsg(mPtr) : _SC("Unknown reason"));
|
|
|
|
// Must be destroyed regardless of result
|
|
|
|
sqlite3_close(mPtr);
|
|
|
|
// Prevent further use of this handle
|
|
|
|
mPtr = nullptr;
|
|
|
|
// Now its safe to throw the error
|
|
|
|
STHROWF("Unable to connect to database [{}]", msg.c_str());
|
|
|
|
}
|
|
|
|
// Let's save the specified information
|
|
|
|
mName.assign(name);
|
|
|
|
mFlags = flags;
|
|
|
|
mVFS.assign(vfs ? vfs : _SC(""));
|
|
|
|
// Optional check if database is initially stored in memory
|
|
|
|
mMemory = (mName == _SC(":memory:"));
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
int32_t SQLiteConnHnd::Flush(uint32_t num, Object & env, Function & func)
|
|
|
|
{
|
|
|
|
// Do we even have a valid connection?
|
2022-07-19 18:29:32 +02:00
|
|
|
if (!Access())
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
return -1; // No connection!
|
|
|
|
}
|
|
|
|
// Is there anything to flush?
|
|
|
|
else if (!num || mQueue.empty())
|
|
|
|
{
|
|
|
|
return 0; // Nothing to process!
|
|
|
|
}
|
|
|
|
// Can we even flush that many?
|
|
|
|
else if (num > mQueue.size())
|
|
|
|
{
|
|
|
|
num = static_cast<uint32_t>(mQueue.size());
|
|
|
|
}
|
|
|
|
// Generate the function that should be called upon error
|
|
|
|
Function callback = Function(env.GetObj(), func.GetFunc(), env.GetVM());
|
|
|
|
// Obtain iterators to the range of queries that should be flushed
|
|
|
|
auto itr = mQueue.begin();
|
|
|
|
auto end = mQueue.begin() + num;
|
|
|
|
// Attempt to begin the flush transaction
|
|
|
|
if ((mStatus = sqlite3_exec(mPtr, "BEGIN", nullptr, nullptr, nullptr)) != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF("Unable to begin flush transaction [{}]", sqlite3_errmsg(mPtr));
|
|
|
|
}
|
|
|
|
// Process all queries within range of selection
|
|
|
|
for (; itr != end; ++itr)
|
|
|
|
{
|
|
|
|
// Should we manually terminate this query?
|
|
|
|
/*
|
|
|
|
if (*(*itr).rbegin() != ';')
|
|
|
|
{
|
|
|
|
itr->push_back(';');
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
// Attempt to execute the currently processed query string
|
|
|
|
if ((mStatus = sqlite3_exec(mPtr, itr->c_str(), nullptr, nullptr, nullptr)) == SQLITE_OK)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// Do we have to execute any callback to resolve our issue?
|
|
|
|
else if (!callback.IsNull())
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
// Ask the callback whether the query processing should end here
|
|
|
|
SharedPtr< bool > ret = callback.Evaluate< bool >(mStatus, *itr);
|
|
|
|
// Should we break here?
|
|
|
|
if (!!ret && !(*ret))
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (const Sqrat::Exception & e)
|
|
|
|
{
|
|
|
|
LogErr("Squirrel error caught in flush handler [%s]", e.what());
|
|
|
|
}
|
|
|
|
catch (const std::exception & e)
|
|
|
|
{
|
|
|
|
LogErr("Program error caught in flush handler [%s]", e.what());
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
LogErr("Unknown error caught in flush handler");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Erase all queries till end or till the point of failure (if any occurred)
|
|
|
|
mQueue.erase(mQueue.begin(), itr);
|
|
|
|
// Attempt to commit changes requested during transaction
|
|
|
|
if ((mStatus = sqlite3_exec(mPtr, "COMMIT", nullptr, nullptr, nullptr)) == SQLITE_OK)
|
|
|
|
{
|
|
|
|
return sqlite3_changes(mPtr);
|
|
|
|
}
|
|
|
|
// Attempt to roll back erroneous changes
|
|
|
|
else if ((mStatus = sqlite3_exec(mPtr, "ROLLBACK", nullptr, nullptr, nullptr)) != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF("Unable to rollback flush transaction [{}]", sqlite3_errmsg(mPtr));
|
|
|
|
}
|
|
|
|
// The transaction failed somehow but we managed to rollback
|
|
|
|
else
|
|
|
|
{
|
|
|
|
STHROWF("Unable to commit flush transaction [{}]", sqlite3_errmsg(mPtr));
|
|
|
|
}
|
|
|
|
// Operation failed
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
2022-07-04 18:39:41 +02:00
|
|
|
SQLiteStmtHnd::SQLiteStmtHnd(SQLiteConnRef conn)
|
2021-06-12 16:51:01 +02:00
|
|
|
: mPtr(nullptr)
|
|
|
|
, mStatus(SQLITE_OK)
|
2022-07-19 18:29:32 +02:00
|
|
|
, mConnection(std::move(conn))
|
2021-06-12 16:51:01 +02:00
|
|
|
, mQuery()
|
|
|
|
, mColumns(0)
|
|
|
|
, mParameters(0)
|
|
|
|
, mIndexes()
|
|
|
|
, mGood(false)
|
|
|
|
, mDone(false)
|
|
|
|
{
|
|
|
|
/* ... */
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
SQLiteStmtHnd::~SQLiteStmtHnd()
|
|
|
|
{
|
|
|
|
// Is there anything to finalize?
|
|
|
|
if (mPtr != nullptr)
|
|
|
|
{
|
|
|
|
// Attempt to finalize the statement
|
|
|
|
if ((sqlite3_finalize(mPtr)) != SQLITE_OK)
|
|
|
|
{
|
2022-07-19 18:29:32 +02:00
|
|
|
LogErr("Unable to finalize SQLite statement [%s]", mConnection->ErrMsg());
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteStmtHnd::Create(const SQChar * query, SQInteger length)
|
|
|
|
{
|
|
|
|
// Make sure a previous statement doesn't exist
|
2022-07-19 18:29:32 +02:00
|
|
|
if (Access())
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
STHROWF("Unable to prepare statement. Statement already prepared");
|
|
|
|
}
|
|
|
|
// Is the specified database connection is valid?
|
2022-07-19 18:29:32 +02:00
|
|
|
else if (!mConnection)
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
STHROWF("Unable to prepare statement. Invalid connection handle");
|
|
|
|
}
|
|
|
|
// Is the specified query string valid?
|
|
|
|
else if (!query || !length || *query == '\0')
|
|
|
|
{
|
|
|
|
STHROWF("Unable to prepare statement. Invalid or empty query string");
|
|
|
|
}
|
|
|
|
// Save the query string
|
|
|
|
mQuery.assign(query, static_cast< size_t >(length));
|
|
|
|
// Attempt to prepare a statement with the specified query string
|
2022-07-19 18:29:32 +02:00
|
|
|
if ((mStatus = sqlite3_prepare_v2(mConnection->mPtr, mQuery.c_str(), ConvTo< int32_t >::From(mQuery.size()),
|
2021-06-12 16:51:01 +02:00
|
|
|
&mPtr, nullptr)) != SQLITE_OK)
|
|
|
|
{
|
|
|
|
// Clear the query string since it failed
|
|
|
|
mQuery.clear();
|
|
|
|
// Explicitly make sure the handle is null
|
|
|
|
mPtr = nullptr;
|
|
|
|
// Now it's safe to throw the error
|
2022-07-19 18:29:32 +02:00
|
|
|
STHROWF("Unable to prepare statement [{}]", mConnection->ErrMsg());
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Obtain the number of available columns
|
|
|
|
mColumns = sqlite3_column_count(mPtr);
|
|
|
|
// Obtain the number of available parameters
|
|
|
|
mParameters = sqlite3_bind_parameter_count(mPtr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
int32_t SQLiteStmtHnd::GetColumnIndex(const SQChar * name, SQInteger length)
|
|
|
|
{
|
|
|
|
// Validate the handle
|
2022-07-19 18:29:32 +02:00
|
|
|
if (!Access())
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
STHROWF("Invalid SQLite statement");
|
|
|
|
}
|
|
|
|
// Are the names cached?
|
|
|
|
else if (mIndexes.empty())
|
|
|
|
{
|
|
|
|
for (int32_t i = 0; i < mColumns; ++i)
|
|
|
|
{
|
|
|
|
// Get the column name at the current index
|
|
|
|
auto column_name = static_cast< const SQChar * >(sqlite3_column_name(mPtr, i));
|
|
|
|
// Validate the name
|
|
|
|
if (!column_name)
|
|
|
|
{
|
|
|
|
STHROWF("Unable to retrieve column name for index {}", i);
|
|
|
|
}
|
|
|
|
// Save it to guarantee the same lifetime as this instance
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mIndexes[name] = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const String str(name, length < 0 ? std::strlen(name) : length);
|
|
|
|
// Attempt to find the specified column
|
|
|
|
auto itr = mIndexes.find(str);
|
|
|
|
// Was there a column with the specified name?
|
|
|
|
if (itr != mIndexes.end())
|
|
|
|
{
|
|
|
|
return itr->second;
|
|
|
|
}
|
|
|
|
// No such column exists (expecting the invoker to validate the result)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
const char * SQLiteStmtHnd::ErrStr() const
|
|
|
|
{
|
2022-07-19 18:29:32 +02:00
|
|
|
return mConnection ? sqlite3_errstr(sqlite3_errcode(mConnection->Access())) : _SC("");
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
const char * SQLiteStmtHnd::ErrMsg() const
|
|
|
|
{
|
2022-07-19 18:29:32 +02:00
|
|
|
return mConnection ? sqlite3_errmsg(mConnection->Access()) : _SC("");
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
int32_t SQLiteStmtHnd::ErrNo() const
|
|
|
|
{
|
2022-07-19 18:29:32 +02:00
|
|
|
return mConnection ? sqlite3_errcode(mConnection->Access()) : SQLITE_NOMEM;
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
int32_t SQLiteStmtHnd::ExErrNo() const
|
|
|
|
{
|
2022-07-19 18:29:32 +02:00
|
|
|
return mConnection ? sqlite3_extended_errcode(mConnection->Access()) : SQLITE_NOMEM;
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteConnection::TraceOutput(void * /*ptr*/, const char * sql)
|
|
|
|
{
|
|
|
|
LogInf("SQLite Trace: %s", sql);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteConnection::ProfileOutput(void * /*ptr*/, const char * sql, sqlite3_uint64 time)
|
|
|
|
{
|
2021-09-04 18:09:10 +02:00
|
|
|
LogInf("SQLite profile (time: %llu): %s", time, sql);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
|
|
|
void SQLiteConnection::Validate(const char * file, int32_t line) const
|
|
|
|
{
|
|
|
|
if (!m_Handle)
|
|
|
|
{
|
2021-08-18 20:36:59 +02:00
|
|
|
SqThrowF(SQMOD_RTFMT("Invalid SQLite connection reference =>[{}:{}]"), file, line);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
void SQLiteConnection::Validate() const
|
|
|
|
{
|
|
|
|
if (!m_Handle)
|
|
|
|
{
|
2021-07-03 13:09:58 +02:00
|
|
|
SqThrowF(fmt::runtime("Invalid SQLite connection reference"));
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // _DEBUG
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
|
|
|
void SQLiteConnection::ValidateCreated(const char * file, int32_t line) const
|
|
|
|
{
|
|
|
|
if (!m_Handle)
|
|
|
|
{
|
2021-08-18 20:36:59 +02:00
|
|
|
SqThrowF(SQMOD_RTFMT("Invalid SQLite connection reference =>[{}:{}]"), file, line);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
2022-07-19 18:29:32 +02:00
|
|
|
else if (m_Handle->Access() == nullptr)
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
2021-08-18 20:36:59 +02:00
|
|
|
SqThrowF(SQMOD_RTFMT("Invalid SQLite connection =>[{}:{}]"), file, line);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
void SQLiteConnection::ValidateCreated() const
|
|
|
|
{
|
|
|
|
if (!m_Handle)
|
|
|
|
{
|
2021-07-03 13:09:58 +02:00
|
|
|
SqThrowF(fmt::runtime("Invalid SQLite connection reference"));
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
2022-07-19 18:29:32 +02:00
|
|
|
else if (m_Handle->Access() == nullptr)
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
2021-07-03 13:09:58 +02:00
|
|
|
SqThrowF(fmt::runtime("Invalid SQLite connection"));
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // _DEBUG
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
2022-07-04 18:39:41 +02:00
|
|
|
const SQLiteConnRef & SQLiteConnection::GetValid(const char * file, int32_t line) const
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
Validate(file, line);
|
|
|
|
return m_Handle;
|
|
|
|
}
|
|
|
|
#else
|
2022-07-04 18:39:41 +02:00
|
|
|
const SQLiteConnRef & SQLiteConnection::GetValid() const
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
Validate();
|
|
|
|
return m_Handle;
|
|
|
|
}
|
|
|
|
#endif // _DEBUG
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
2022-07-04 18:39:41 +02:00
|
|
|
const SQLiteConnRef & SQLiteConnection::GetCreated(const char * file, int32_t line) const
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
ValidateCreated(file, line);
|
|
|
|
return m_Handle;
|
|
|
|
}
|
|
|
|
#else
|
2022-07-04 18:39:41 +02:00
|
|
|
const SQLiteConnRef & SQLiteConnection::GetCreated() const
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
ValidateCreated();
|
|
|
|
return m_Handle;
|
|
|
|
}
|
|
|
|
#endif // _DEBUG
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteConnection::Open(StackStrF & name)
|
|
|
|
{
|
|
|
|
// Should we create a connection handle?
|
|
|
|
if (!m_Handle)
|
|
|
|
{
|
2022-07-04 18:39:41 +02:00
|
|
|
m_Handle = SQLiteConnRef(new SQLiteConnHnd());
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
// Make sure another database isn't opened
|
|
|
|
if (SQMOD_GET_VALID(*this)->mPtr != nullptr)
|
|
|
|
{
|
|
|
|
STHROWF("Already referencing a valid database connection");
|
|
|
|
}
|
|
|
|
// Effing signed/unsigned warnings everywhere. I just need it to shut up.
|
|
|
|
constexpr unsigned OPEN_READWRITE_F = SQLITE_OPEN_READWRITE;
|
|
|
|
constexpr unsigned OPEN_CREATE_F = SQLITE_OPEN_CREATE;
|
|
|
|
// Perform the requested operation
|
|
|
|
m_Handle->Create(name.mPtr, OPEN_READWRITE_F | OPEN_CREATE_F, nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteConnection::Open(StackStrF & name, int32_t flags)
|
|
|
|
{
|
|
|
|
// Should we create a connection handle?
|
|
|
|
if (!m_Handle)
|
|
|
|
{
|
2022-07-04 18:39:41 +02:00
|
|
|
m_Handle = SQLiteConnRef(new SQLiteConnHnd());
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
// Make sure another database isn't opened
|
|
|
|
if (SQMOD_GET_VALID(*this)->mPtr != nullptr)
|
|
|
|
{
|
|
|
|
STHROWF("Already referencing a valid database connection");
|
|
|
|
}
|
|
|
|
// Perform the requested operation
|
|
|
|
m_Handle->Create(name.mPtr, flags, nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteConnection::Open(StackStrF & name, int32_t flags, StackStrF & vfs)
|
|
|
|
{
|
|
|
|
// Should we create a connection handle?
|
|
|
|
if (!m_Handle)
|
|
|
|
{
|
2022-07-04 18:39:41 +02:00
|
|
|
m_Handle = SQLiteConnRef(new SQLiteConnHnd());
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
// Make sure another database isn't opened
|
|
|
|
if (SQMOD_GET_VALID(*this)->mPtr != nullptr)
|
|
|
|
{
|
|
|
|
STHROWF("Already referencing a valid database connection");
|
|
|
|
}
|
|
|
|
// Perform the requested operation
|
|
|
|
m_Handle->Create(name.mPtr, flags, vfs.mPtr);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
int32_t SQLiteConnection::Exec(StackStrF & str)
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Attempt to execute the specified query
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_exec(m_Handle->Access(), str.mPtr, nullptr, nullptr, nullptr);
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the execution result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF("Unable to execute query [{}]", m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
// Return rows affected by this query
|
2022-07-19 18:29:32 +02:00
|
|
|
return sqlite3_changes(m_Handle->Access());
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
Object SQLiteConnection::Query(StackStrF & str) const
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Return the requested information
|
|
|
|
return Object(new SQLiteStatement(m_Handle, str));
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteConnection::Queue(StackStrF & str)
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE(*this);
|
|
|
|
// Is there a query to commit?
|
|
|
|
if (!str.mLen || IsQueryEmpty(str.mPtr))
|
|
|
|
{
|
|
|
|
STHROWF("No query string to queue");
|
|
|
|
}
|
|
|
|
// Add the specified string to the queue
|
|
|
|
m_Handle->mQueue.emplace_back(str.mPtr, str.mLen);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
bool SQLiteConnection::IsReadOnly() const
|
|
|
|
{
|
|
|
|
// Request the desired information
|
|
|
|
const int result = sqlite3_db_readonly(SQMOD_GET_CREATED(*this)->mPtr, "main");
|
|
|
|
// Verify the result
|
|
|
|
if (result == -1)
|
|
|
|
{
|
|
|
|
STHROWF("'main' is not the name of a database on connection");
|
|
|
|
}
|
|
|
|
// Return the requested information
|
|
|
|
return (result != 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
bool SQLiteConnection::TableExists(StackStrF & name) const
|
|
|
|
{
|
|
|
|
StackStrF query("SELECT count(*) FROM [sqlite_master] WHERE [type]='table' AND [name]=?");
|
|
|
|
// Prepare a statement to inspect the master table
|
|
|
|
SQLiteStatement stmt(SQMOD_GET_CREATED(*this), query);
|
|
|
|
// Could the statement be created?
|
|
|
|
if (stmt.IsValid())
|
|
|
|
{
|
|
|
|
// Bind the specified name onto the statement parameter
|
|
|
|
SQLiteParameter(stmt.GetHandle(), 1).SetString(name);
|
|
|
|
// Attempt to step the statement and obtain a value
|
|
|
|
if (stmt.Step())
|
|
|
|
{
|
|
|
|
return (sqlite3_column_int(stmt, 0) == 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Assume it doesn't exist
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteConnection::SetTracing(bool SQ_UNUSED_ARG(toggle)) // NOLINT(readability-convert-member-functions-to-static)
|
|
|
|
{
|
|
|
|
#if defined(SQLITE_OMIT_TRACE) || defined(SQLITE_OMIT_DEPRECATED)
|
|
|
|
STHROWF("The module was compiled without this feature");
|
|
|
|
#else
|
|
|
|
// Check whether changes are necessary
|
|
|
|
if (SQMOD_GET_CREATED(*this)->mTrace == toggle)
|
|
|
|
{
|
|
|
|
return; // No point in proceeding
|
|
|
|
}
|
|
|
|
// Do we have to disable it?
|
|
|
|
else if (m_Handle->mTrace)
|
|
|
|
{
|
2022-07-19 18:29:32 +02:00
|
|
|
sqlite3_trace(m_Handle->Access(), nullptr, nullptr);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
// Go ahead and enable tracing
|
|
|
|
else
|
|
|
|
{
|
2022-07-19 18:29:32 +02:00
|
|
|
sqlite3_trace(m_Handle->Access(), &SQLiteConnection::TraceOutput, nullptr);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteConnection::SetProfiling(bool SQ_UNUSED_ARG(toggle)) // NOLINT(readability-convert-member-functions-to-static)
|
|
|
|
{
|
|
|
|
#if defined(SQLITE_OMIT_TRACE) || defined(SQLITE_OMIT_DEPRECATED)
|
|
|
|
STHROWF("The module was compiled without this feature");
|
|
|
|
#else
|
|
|
|
// Check whether changes are necessary
|
|
|
|
if (SQMOD_GET_CREATED(*this)->mProfile == toggle)
|
|
|
|
{
|
|
|
|
return; // No point in proceeding
|
|
|
|
}
|
|
|
|
// Do we have to disable it?
|
|
|
|
else if (m_Handle->mProfile)
|
|
|
|
{
|
2022-07-19 18:29:32 +02:00
|
|
|
sqlite3_profile(m_Handle->Access(), nullptr, nullptr);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
// Go ahead and enable profiling
|
|
|
|
else
|
|
|
|
{
|
2022-07-19 18:29:32 +02:00
|
|
|
sqlite3_profile(m_Handle->Access(), &SQLiteConnection::ProfileOutput, nullptr);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteConnection::SetBusyTimeout(int32_t millis)
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Apply the requested timeout
|
2022-07-19 18:29:32 +02:00
|
|
|
if ((m_Handle->mStatus = sqlite3_busy_timeout(m_Handle->Access(), millis)) != SQLITE_OK)
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
STHROWF("Unable to set busy timeout [{}]", m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
int32_t SQLiteConnection::GetInfo(int32_t operation, bool highwater, bool reset)
|
|
|
|
{
|
|
|
|
// Where to retrieve the information
|
|
|
|
int32_t cur_value;
|
|
|
|
int32_t hiwtr_value;
|
|
|
|
// Attempt to retrieve the specified information
|
|
|
|
if ((m_Handle->mStatus = sqlite3_db_status(SQMOD_GET_CREATED(*this)->mPtr, operation, &cur_value, &hiwtr_value, reset)) != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF("Unable to get runtime status information", m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
// Return the high-water value if requested
|
|
|
|
else if (highwater)
|
|
|
|
{
|
|
|
|
return hiwtr_value;
|
|
|
|
}
|
|
|
|
// Return the requested information
|
|
|
|
return cur_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteConnection::ReserveQueue(uint32_t num)
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE(*this);
|
|
|
|
// Perform the requested operation
|
|
|
|
m_Handle->mQueue.reserve(m_Handle->mQueue.size() + num);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteConnection::PopQueue()
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE(*this);
|
|
|
|
// Perform the requested operation
|
|
|
|
if (!SQMOD_GET_VALID(*this)->mQueue.empty())
|
|
|
|
{
|
|
|
|
m_Handle->mQueue.pop_back();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
int32_t SQLiteConnection::Flush()
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Perform the requested operation
|
|
|
|
return m_Handle->Flush(static_cast<uint32_t>(m_Handle->mQueue.size()), NullObject(), NullFunction());
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
int32_t SQLiteConnection::Flush(SQInteger num)
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Perform the requested operation
|
|
|
|
return m_Handle->Flush(ConvTo< uint32_t >::From(num), NullObject(), NullFunction());
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
int32_t SQLiteConnection::Flush(Object & env, Function & func)
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Perform the requested operation
|
|
|
|
return m_Handle->Flush(static_cast<uint32_t>(m_Handle->mQueue.size()), env, func);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
int32_t SQLiteConnection::Flush(SQInteger num, Object & env, Function & func)
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Perform the requested operation
|
|
|
|
return m_Handle->Flush(ConvTo< uint32_t >::From(num), env, func);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
|
|
|
void SQLiteParameter::Validate(const char * file, int32_t line) const
|
|
|
|
{
|
|
|
|
// Are we pointing to a valid index?
|
|
|
|
if (m_Index < 0)
|
|
|
|
{
|
2021-08-18 20:36:59 +02:00
|
|
|
SqThrowF(SQMOD_RTFMT("Invalid column index: {} < 0 =>[{}:{}]"), m_Index, file, line);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
// Do we have a valid statement handle?
|
|
|
|
else if (!m_Handle)
|
|
|
|
{
|
2021-08-18 20:36:59 +02:00
|
|
|
SqThrowF(SQMOD_RTFMT("Invalid SQLite statement reference =>[{}:{}]"), file, line);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
void SQLiteParameter::Validate() const
|
|
|
|
{
|
|
|
|
// Are we pointing to a valid index?
|
|
|
|
if (m_Index < 0)
|
|
|
|
{
|
2021-07-03 13:09:58 +02:00
|
|
|
SqThrowF(fmt::runtime("Invalid column index: {} < 0"), m_Index);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
// Do we have a valid statement handle?
|
|
|
|
else if (!m_Handle)
|
|
|
|
{
|
2021-07-03 13:09:58 +02:00
|
|
|
SqThrowF(fmt::runtime("Invalid SQLite statement reference"));
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // _DEBUG
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
|
|
|
void SQLiteParameter::ValidateCreated(const char * file, int32_t line) const
|
|
|
|
{
|
|
|
|
// Are we pointing to a valid index?
|
|
|
|
if (m_Index < 0)
|
|
|
|
{
|
2021-08-18 20:36:59 +02:00
|
|
|
SqThrowF(SQMOD_RTFMT("Invalid column index: {} < 0 =>[{}:{}]"), m_Index, file, line);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
else if (!m_Handle)
|
|
|
|
{
|
2021-08-18 20:36:59 +02:00
|
|
|
SqThrowF(SQMOD_RTFMT("Invalid SQLite statement reference =>[{}:{}]"), file, line);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
2022-07-19 18:29:32 +02:00
|
|
|
else if (m_Handle->Access() == nullptr)
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
2021-08-18 20:36:59 +02:00
|
|
|
SqThrowF(SQMOD_RTFMT("Invalid SQLite statement =>[{}:{}]"), file, line);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
void SQLiteParameter::ValidateCreated() const
|
|
|
|
{
|
|
|
|
// Are we pointing to a valid index?
|
|
|
|
if (m_Index < 0)
|
|
|
|
{
|
2021-07-03 13:09:58 +02:00
|
|
|
SqThrowF(fmt::runtime("Invalid column index: {} < 0"), m_Index);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
else if (!m_Handle)
|
|
|
|
{
|
2021-07-03 13:09:58 +02:00
|
|
|
SqThrowF(fmt::runtime("Invalid SQLite statement reference"));
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
2022-07-19 18:29:32 +02:00
|
|
|
else if (m_Handle->Access() == nullptr)
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
2021-07-03 13:09:58 +02:00
|
|
|
SqThrowF(fmt::runtime("Invalid SQLite statement"));
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // _DEBUG
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
2022-07-04 18:39:41 +02:00
|
|
|
const SQLiteStmtRef & SQLiteParameter::GetValid(const char * file, int32_t line) const
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
Validate(file, line);
|
|
|
|
return m_Handle;
|
|
|
|
}
|
|
|
|
#else
|
2022-07-04 18:39:41 +02:00
|
|
|
const SQLiteStmtRef & SQLiteParameter::GetValid() const
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
Validate();
|
|
|
|
return m_Handle;
|
|
|
|
}
|
|
|
|
#endif // _DEBUG
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
2022-07-04 18:39:41 +02:00
|
|
|
const SQLiteStmtRef & SQLiteParameter::GetCreated(const char * file, int32_t line) const
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
ValidateCreated(file, line);
|
|
|
|
return m_Handle;
|
|
|
|
}
|
|
|
|
#else
|
2022-07-04 18:39:41 +02:00
|
|
|
const SQLiteStmtRef & SQLiteParameter::GetCreated() const
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
ValidateCreated();
|
|
|
|
return m_Handle;
|
|
|
|
}
|
|
|
|
#endif // _DEBUG
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
|
|
|
void SQLiteParameter::ValidateParam(int32_t idx, const char * file, int32_t line) const
|
|
|
|
{
|
|
|
|
ValidateCreated(file, line);
|
|
|
|
// Is the specified index in range?
|
|
|
|
if (!m_Handle->CheckParameter(idx))
|
|
|
|
{
|
2021-08-18 20:36:59 +02:00
|
|
|
SqThrowF(SQMOD_RTFMT("Parameter index is out of range ({}:{}) =>[{}:{}]"), idx, m_Handle->mParameters,
|
2021-06-12 16:51:01 +02:00
|
|
|
file, line);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
void SQLiteParameter::ValidateParam(int32_t idx) const
|
|
|
|
{
|
|
|
|
ValidateCreated();
|
|
|
|
// Is the specified index in range?
|
|
|
|
if (!m_Handle->CheckParameter(idx))
|
|
|
|
{
|
2021-07-03 13:09:58 +02:00
|
|
|
SqThrowF(fmt::runtime("SQLiteParameter index is out of range ({}:{})"), idx, m_Handle->mParameters);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // _DEBUG
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteParameter::SetIndex(const Object & param)
|
|
|
|
{
|
|
|
|
// Where the index will be extracted
|
|
|
|
int32_t idx = 0;
|
|
|
|
// Grab the object virtual machine
|
|
|
|
HSQUIRRELVM vm = param.GetVM();
|
|
|
|
// Remember the current stack size
|
|
|
|
const StackGuard sg(vm);
|
|
|
|
// Push the specified object onto the stack
|
|
|
|
Var< const Object & >::push(vm, param);
|
|
|
|
// Identify the type of parameter was given
|
|
|
|
switch (param.GetType())
|
|
|
|
{
|
|
|
|
// Is this a string value?
|
|
|
|
case OT_STRING:
|
|
|
|
{
|
|
|
|
// Obtain the object from the stack as a string
|
|
|
|
StackStrF val(vm, -1);
|
|
|
|
// Validate the result
|
|
|
|
if (SQ_FAILED(val.Proc(false)))
|
|
|
|
{
|
|
|
|
STHROWF("{}", LastErrorString(vm));
|
|
|
|
}
|
|
|
|
// Is the obtained string empty?
|
|
|
|
else if (val.mLen <= 0)
|
|
|
|
{
|
|
|
|
STHROWF("Cannot use an empty parameter name");
|
|
|
|
}
|
|
|
|
// Attempt to find a parameter with the specified name
|
2022-07-19 18:29:32 +02:00
|
|
|
idx = sqlite3_bind_parameter_index(SQMOD_GET_CREATED(*this)->Access(), val.mPtr);
|
2021-06-12 16:51:01 +02:00
|
|
|
} break;
|
|
|
|
// Is this an integer value? (or at least can be easily converted to one)
|
|
|
|
case OT_INTEGER:
|
|
|
|
case OT_FLOAT:
|
|
|
|
case OT_BOOL:
|
|
|
|
{
|
|
|
|
idx = ConvTo< int32_t >::From(PopStackInteger(vm, -1));
|
|
|
|
} break;
|
|
|
|
// Is this an instance that we can extract either a string or integer from it?
|
|
|
|
case OT_INSTANCE:
|
|
|
|
{
|
|
|
|
// Obtain the object from the stack as a string
|
|
|
|
StackStrF val(vm, -1);
|
|
|
|
// Validate the result
|
|
|
|
if (SQ_FAILED(val.Proc(false)))
|
|
|
|
{
|
|
|
|
STHROWF("{}", LastErrorString(vm));
|
|
|
|
}
|
|
|
|
// Is the obtained string empty?
|
|
|
|
else if (val.mLen <= 0)
|
|
|
|
{
|
|
|
|
STHROWF("Cannot use an empty parameter name");
|
|
|
|
}
|
|
|
|
// Check if this value is made only of digits
|
|
|
|
else if (IsDigitsOnly(val.mPtr))
|
|
|
|
{
|
|
|
|
idx = ConvNum< int32_t >::FromStr(val.mPtr);
|
|
|
|
}
|
|
|
|
// Attempt to find a parameter with the specified name
|
|
|
|
else
|
|
|
|
{
|
2022-07-19 18:29:32 +02:00
|
|
|
idx = sqlite3_bind_parameter_index(SQMOD_GET_CREATED(*this)->Access(), val.mPtr);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
} break;
|
|
|
|
// We don't recognize this kind of value!
|
|
|
|
default: STHROWF("Unknown parameter index of type ({})", SqTypeName(param.GetType()));
|
|
|
|
}
|
|
|
|
// Assign the index with a failsafe to invalid on error
|
|
|
|
AutoAssign< int32_t > aa(m_Index, 0, idx);
|
|
|
|
// Validate the obtained parameter index
|
|
|
|
SQMOD_VALIDATE_PARAM(*this, idx);
|
|
|
|
// Don't fall back to the invalid index anymore
|
|
|
|
aa.Set(idx);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
Object SQLiteParameter::GetStatement() const
|
|
|
|
{
|
|
|
|
return GetStatementObj(m_Handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
Object SQLiteParameter::GetConnection() const
|
|
|
|
{
|
2022-07-19 18:29:32 +02:00
|
|
|
return GetConnectionObj(SQMOD_GET_VALID(*this)->mConnection);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteParameter::SetValue(const Object & value)
|
|
|
|
{
|
|
|
|
switch (value.GetType())
|
|
|
|
{
|
|
|
|
case OT_NULL:
|
|
|
|
{
|
|
|
|
SetNull();
|
|
|
|
} break;
|
|
|
|
case OT_INTEGER:
|
|
|
|
{
|
|
|
|
SetInteger(value.Cast< SQInteger >());
|
|
|
|
} break;
|
|
|
|
case OT_FLOAT:
|
|
|
|
{
|
|
|
|
SetFloat(value.Cast< SQFloat >());
|
|
|
|
} break;
|
|
|
|
case OT_BOOL:
|
|
|
|
{
|
|
|
|
SetBool(value.Cast< bool >());
|
|
|
|
} break;
|
|
|
|
case OT_STRING:
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Remember the current stack size
|
|
|
|
const StackGuard sg;
|
|
|
|
// Push the object onto the stack
|
|
|
|
Var< Object >::push(SqVM(), value);
|
|
|
|
// Pop the object from the stack as a string
|
|
|
|
const Var< const SQChar * > str(SqVM(), -1);
|
|
|
|
// Attempt to bind the specified value
|
|
|
|
SetStringRaw(str.value, ConvTo< SQInteger >::From(str.size));
|
|
|
|
} break;
|
|
|
|
default: STHROWF("No known conversion for the specified value type");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteParameter::SetBool(bool value)
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Attempt to bind the specified value
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_bind_int(m_Handle->Access(), m_Index, value);
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF(SQMOD_BINDFAILED, "bool", m_Index, m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteParameter::SetChar(SQInteger value)
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Attempt to bind the specified value
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_bind_int(m_Handle->Access(), m_Index, ConvTo< SQChar >::From(value));
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF(SQMOD_BINDFAILED, "char", m_Index, m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteParameter::SetInteger(SQInteger value)
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Attempt to bind the specified value
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_bind_integer(m_Handle->Access(), m_Index, value);
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF(SQMOD_BINDFAILED, "integer", m_Index, m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteParameter::SetInt8(SQInteger value)
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Attempt to bind the specified value
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_bind_int(m_Handle->Access(), m_Index, ConvTo< int8_t >::From(value));
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF(SQMOD_BINDFAILED, "int8", m_Index, m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteParameter::SetUint8(SQInteger value)
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Attempt to bind the specified value
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_bind_int(m_Handle->Access(), m_Index, ConvTo< uint8_t >::From(value));
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF(SQMOD_BINDFAILED, "uint8", m_Index, m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteParameter::SetInt16(SQInteger value)
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Attempt to bind the specified value
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_bind_int(m_Handle->Access(), m_Index, ConvTo< int16_t >::From(value));
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF(SQMOD_BINDFAILED, "int16", m_Index, m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteParameter::SetUint16(SQInteger value)
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Attempt to bind the specified value
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_bind_int(m_Handle->Access(), m_Index, ConvTo< uint16_t >::From(value));
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF(SQMOD_BINDFAILED, "uint16", m_Index, m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteParameter::SetInt32(SQInteger value)
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Attempt to bind the specified value
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_bind_int(m_Handle->Access(), m_Index, ConvTo< int32_t >::From(value));
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF(SQMOD_BINDFAILED, "int32", m_Index, m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteParameter::SetUint32(SQInteger value)
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Attempt to bind the specified value
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_bind_int(m_Handle->Access(), m_Index, static_cast< int32_t >(ConvTo< uint32_t >::From(value)));
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF(SQMOD_BINDFAILED, "uint32", m_Index, m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
2021-09-10 20:27:28 +02:00
|
|
|
void SQLiteParameter::SetInt64(SQInteger value)
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Attempt to bind the specified value
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_bind_int64(m_Handle->Access(), m_Index, value);
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF(SQMOD_BINDFAILED, "int64", m_Index, m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
2021-09-10 20:27:28 +02:00
|
|
|
void SQLiteParameter::SetUint64(SQInteger value)
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Attempt to bind the specified value
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_bind_int64(m_Handle->Access(), m_Index, value);
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF(SQMOD_BINDFAILED, "uint64", m_Index, m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteParameter::SetFloat(SQFloat value)
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Attempt to bind the specified value
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_bind_double(m_Handle->Access(), m_Index, value);
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF(SQMOD_BINDFAILED, "float", m_Index, m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteParameter::SetFloat32(SQFloat value)
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Attempt to bind the specified value
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_bind_double(m_Handle->Access(), m_Index, ConvTo< float >::From(value));
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF(SQMOD_BINDFAILED, "float32", m_Index, m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteParameter::SetFloat64(SQFloat value)
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Attempt to bind the specified value
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_bind_double(m_Handle->Access(), m_Index, value);
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF(SQMOD_BINDFAILED, "float64", m_Index, m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteParameter::SetString(StackStrF & value)
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Attempt to bind the specified value
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_bind_text(m_Handle->Access(), m_Index, value.mPtr, static_cast<int>(value.mLen), SQLITE_TRANSIENT);
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF(SQMOD_BINDFAILED, "string", m_Index, m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteParameter::SetStringRaw(const SQChar * value, SQInteger length)
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Attempt to bind the specified value
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_bind_text(m_Handle->Access(), m_Index, value, static_cast<int>(length), SQLITE_TRANSIENT);
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF(SQMOD_BINDFAILED, "string", m_Index, m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteParameter::SetZeroBlob(SQInteger size)
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Attempt to bind the specified value
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_bind_zeroblob(m_Handle->Access(), m_Index, ConvTo< int32_t >::From(size));
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF(SQMOD_BINDFAILED, "blob", m_Index, m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteParameter::SetBlob(const Object & value)
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// The blob data pointer and size
|
|
|
|
SQUserPointer ptr = nullptr;
|
|
|
|
SQInteger len;
|
|
|
|
// Grab the associated object virtual machine
|
|
|
|
HSQUIRRELVM vm = value.GetVM();
|
|
|
|
// Extract the blob data from the specified object
|
|
|
|
{
|
|
|
|
// Remember the current stack size
|
|
|
|
const StackGuard sg(vm);
|
|
|
|
// Push the specified object onto the stack
|
|
|
|
Var< const Object & >::push(vm, value);
|
|
|
|
// Grab the blob data pointer
|
|
|
|
if (SQ_FAILED(sqstd_getblob(vm, -1, &ptr)))
|
|
|
|
{
|
|
|
|
STHROWF("Unable to obtain the blob data");
|
|
|
|
}
|
|
|
|
// Grab the blob data size
|
|
|
|
len = sqstd_getblobsize(vm, -1);
|
|
|
|
}
|
|
|
|
// Attempt to bind the specified value
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_bind_blob(m_Handle->Access(), m_Index, ptr, static_cast<int>(len), SQLITE_TRANSIENT);
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF(SQMOD_BINDFAILED, "blob", m_Index, m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteParameter::SetData(const SqBuffer & value)
|
|
|
|
{
|
|
|
|
// Grab the internal buffer
|
|
|
|
Buffer & buff = *value.GetRef();
|
|
|
|
// Attempt to bind the specified value
|
|
|
|
#ifdef _SQ64
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_bind_blob64(m_Handle->Access(), m_Index, buff.Data(), buff.Position(), SQLITE_TRANSIENT);
|
2021-06-12 16:51:01 +02:00
|
|
|
#else
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_bind_blob(m_Handle->Access(), m_Index, buff.Data(), buff.Position(), SQLITE_TRANSIENT);
|
2021-06-12 16:51:01 +02:00
|
|
|
#endif
|
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF(SQMOD_BINDFAILED, "buffer", m_Index, m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteParameter::SetDataEx(const SqBuffer & value, SQInteger offset, SQInteger length)
|
|
|
|
{
|
|
|
|
// Grab the internal buffer
|
|
|
|
Buffer & buff = *value.GetRef();
|
|
|
|
// Make sure we are within range
|
|
|
|
if (offset < 0)
|
|
|
|
{
|
|
|
|
STHROWF("Negative buffer offset is not allowed: {}", offset);
|
|
|
|
}
|
|
|
|
else if (offset < 0)
|
|
|
|
{
|
|
|
|
STHROWF("Negative buffer length is not allowed: {}", length);
|
|
|
|
}
|
|
|
|
else if (offset + length > buff.Capacity())
|
|
|
|
{
|
|
|
|
STHROWF("Buffer range is outside boundaries: ({}+{}) > {}", offset, length, buff.Capacity());
|
|
|
|
}
|
|
|
|
// Attempt to bind the specified value
|
|
|
|
#ifdef _SQ64
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_bind_blob64(m_Handle->Access(), m_Index, (buff.Data() + offset), static_cast< sqlite3_uint64 >(offset + length), SQLITE_TRANSIENT);
|
2021-06-12 16:51:01 +02:00
|
|
|
#else
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_bind_blob(m_Handle->Access(), m_Index, (buff.Data() + offset), static_cast< int >(offset + length), SQLITE_TRANSIENT);
|
2021-06-12 16:51:01 +02:00
|
|
|
#endif
|
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF(SQMOD_BINDFAILED, "buffer", m_Index, m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteParameter::SetDate(const Date & value)
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Attempt to generate the specified date string
|
|
|
|
auto str = fmt::format("{} 00:00:00", value.ToString());
|
|
|
|
// Attempt to bind the specified value
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_bind_text(m_Handle->Access(), m_Index, str.data(), static_cast< int >(str.size()), SQLITE_TRANSIENT);
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF(SQMOD_BINDFAILED, "date", m_Index, m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteParameter::SetDateEx(SQInteger year, SQInteger month, SQInteger day)
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Convert the specified values within the proper ranges
|
|
|
|
const uint16_t y = ConvTo< uint16_t >::From(year);
|
|
|
|
const uint8_t m = ConvTo< uint8_t >::From(month), d = ConvTo< uint8_t >::From(day);
|
|
|
|
// Validate the specified date
|
|
|
|
if (!Chrono::ValidDate(y, m, d))
|
|
|
|
{
|
|
|
|
STHROWF("Invalid date ({}-{}-{})", y, m, d);
|
|
|
|
}
|
|
|
|
// Attempt to generate the specified date string
|
|
|
|
auto str = fmt::format("{}-{}-{} 00:00:00", y, m, d);
|
|
|
|
// Attempt to bind the specified value
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_bind_text(m_Handle->Access(), m_Index, str.data(), static_cast< int >(str.size()), SQLITE_TRANSIENT);
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF(SQMOD_BINDFAILED, "date", m_Index, m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteParameter::SetTime(const Time & value)
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Attempt to bind the specified value
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_bind_int(m_Handle->Access(), m_Index, static_cast<int>(value.GetTimestamp().GetSecondsI()));
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF(SQMOD_BINDFAILED, "time", m_Index, m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteParameter::SetTimeEx(SQInteger hour, SQInteger minute, SQInteger second)
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Convert the specified values within the proper ranges
|
|
|
|
const uint8_t h = ConvTo< uint8_t >::From(hour)
|
|
|
|
, m = ConvTo< uint8_t >::From(minute)
|
|
|
|
, s = ConvTo< uint8_t >::From(second);
|
|
|
|
// Is the specified hour within range?
|
|
|
|
if (h >= 24)
|
|
|
|
{
|
|
|
|
STHROWF("Hour value is out of range: {} >= 24", h);
|
|
|
|
}
|
|
|
|
// Is the specified minute within range?
|
|
|
|
else if (m >= 60)
|
|
|
|
{
|
|
|
|
STHROWF("Minute value is out of range: {} >= 60", m);
|
|
|
|
}
|
|
|
|
// Is the specified second within range?
|
|
|
|
else if (s >= 60)
|
|
|
|
{
|
|
|
|
STHROWF("Second value is out of range: {} >= 60", s);
|
|
|
|
}
|
|
|
|
// Calculate the number of seconds in the specified time and bind the resulted value
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_bind_int(m_Handle->Access(), m_Index, (h * (60 * 60)) + (m * 60) + s);
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF(SQMOD_BINDFAILED, "time", m_Index, m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteParameter::SetDatetime(const Datetime & value)
|
|
|
|
{
|
|
|
|
SetDatetimeEx(value.GetYear(), value.GetMonth(), value.GetDay(), value.GetHour(), value.GetMinute(), value.GetSecond());
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteParameter::SetDatetimeEx(SQInteger year, SQInteger month, SQInteger day, SQInteger hour, SQInteger minute, SQInteger second)
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Convert the specified values within the proper ranges
|
|
|
|
const uint16_t y = ConvTo< uint16_t >::From(year);
|
|
|
|
const uint8_t mo = ConvTo< uint8_t >::From(month)
|
|
|
|
, d = ConvTo< uint8_t >::From(day)
|
|
|
|
, h = ConvTo< uint8_t >::From(hour)
|
|
|
|
, mi = ConvTo< uint8_t >::From(minute)
|
|
|
|
, s = ConvTo< uint8_t >::From(second);
|
|
|
|
// Validate the specified date
|
|
|
|
if (!Chrono::ValidDate(y, mo, d))
|
|
|
|
{
|
|
|
|
STHROWF("Invalid date ({}-{}-{})", y, mo, d);
|
|
|
|
}
|
|
|
|
// Is the specified hour within range?
|
|
|
|
else if (h >= 24)
|
|
|
|
{
|
|
|
|
STHROWF("Hour value is out of range: {} >= 24", h);
|
|
|
|
}
|
|
|
|
// Is the specified minute within range?
|
|
|
|
else if (mi >= 60)
|
|
|
|
{
|
|
|
|
STHROWF("Minute value is out of range: {} >= 60", mi);
|
|
|
|
}
|
|
|
|
// Is the specified second within range?
|
|
|
|
else if (s >= 60)
|
|
|
|
{
|
|
|
|
STHROWF("Second value is out of range: {} >= 60", s);
|
|
|
|
}
|
|
|
|
// Attempt to generate the specified date string
|
|
|
|
auto str = fmt::format(_SC("{:04}-{:02}-{:02} {:02}:{:02}:{:02}"), y, mo, d, h, mi, s);
|
|
|
|
// Attempt to bind the specified value
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_bind_text(m_Handle->Access(), m_Index, str.data(), static_cast< int >(str.size()), SQLITE_TRANSIENT);
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF(SQMOD_BINDFAILED, "date-time", m_Index, m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteParameter::SetNow()
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Attempt to bind the specified value
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_bind_int(m_Handle->Access(), m_Index,
|
2021-06-12 16:51:01 +02:00
|
|
|
static_cast< int32_t >(std::time(nullptr)));
|
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF(SQMOD_BINDFAILED, "time-stamp", m_Index, m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteParameter::SetNull()
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Attempt to bind the specified value
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_bind_null(m_Handle->Access(), m_Index);
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF(SQMOD_BINDFAILED, "null", m_Index, m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
|
|
|
void SQLiteColumn::Validate(const char * file, int32_t line) const
|
|
|
|
{
|
|
|
|
// Are we pointing to a valid index?
|
|
|
|
if (m_Index < 0)
|
|
|
|
{
|
2021-08-18 20:36:59 +02:00
|
|
|
SqThrowF(SQMOD_RTFMT("Invalid column index: {} < 0 =>[{}:{}]"), m_Index, file, line);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
// Do we have a valid statement handle?
|
|
|
|
else if (!m_Handle)
|
|
|
|
{
|
2021-08-18 20:36:59 +02:00
|
|
|
SqThrowF(SQMOD_RTFMT("Invalid SQLite statement reference =>[{}:{}]"), file, line);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
void SQLiteColumn::Validate() const
|
|
|
|
{
|
|
|
|
// Are we pointing to a valid index?
|
|
|
|
if (m_Index < 0)
|
|
|
|
{
|
2021-07-03 13:09:58 +02:00
|
|
|
SqThrowF(fmt::runtime("Invalid column index: {} < 0"), m_Index);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
// Do we have a valid statement handle?
|
|
|
|
else if (!m_Handle)
|
|
|
|
{
|
2021-07-03 13:09:58 +02:00
|
|
|
SqThrowF(fmt::runtime("Invalid SQLite statement reference"));
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // _DEBUG
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
|
|
|
void SQLiteColumn::ValidateCreated(const char * file, int32_t line) const
|
|
|
|
{
|
|
|
|
// Are we pointing to a valid index?
|
|
|
|
if (m_Index < 0)
|
|
|
|
{
|
2021-08-18 20:36:59 +02:00
|
|
|
SqThrowF(SQMOD_RTFMT("Invalid column index: {} < 0 =>[{}:{}]"), m_Index, file, line);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
else if (!m_Handle)
|
|
|
|
{
|
2021-08-18 20:36:59 +02:00
|
|
|
SqThrowF(SQMOD_RTFMT("Invalid SQLite statement reference =>[{}:{}]"), file, line);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
2022-07-19 18:29:32 +02:00
|
|
|
else if (m_Handle->Access() == nullptr)
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
2021-08-18 20:36:59 +02:00
|
|
|
SqThrowF(SQMOD_RTFMT("Invalid SQLite statement =>[{}:{}]"), file, line);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
void SQLiteColumn::ValidateCreated() const
|
|
|
|
{
|
|
|
|
// Are we pointing to a valid index?
|
|
|
|
if (m_Index < 0)
|
|
|
|
{
|
2021-07-03 13:09:58 +02:00
|
|
|
SqThrowF(fmt::runtime("Invalid column index: {} < 0"), m_Index);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
else if (!m_Handle)
|
|
|
|
{
|
2021-07-03 13:09:58 +02:00
|
|
|
SqThrowF(fmt::runtime("Invalid SQLite statement reference"));
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
2022-07-19 18:29:32 +02:00
|
|
|
else if (m_Handle->Access() == nullptr)
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
2021-07-03 13:09:58 +02:00
|
|
|
SqThrowF(fmt::runtime("Invalid SQLite statement"));
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // _DEBUG
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
2022-07-04 18:39:41 +02:00
|
|
|
const SQLiteStmtRef & SQLiteColumn::GetValid(const char * file, int32_t line) const
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
Validate(file, line);
|
|
|
|
return m_Handle;
|
|
|
|
}
|
|
|
|
#else
|
2022-07-04 18:39:41 +02:00
|
|
|
const SQLiteStmtRef & SQLiteColumn::GetValid() const
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
Validate();
|
|
|
|
return m_Handle;
|
|
|
|
}
|
|
|
|
#endif // _DEBUG
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
2022-07-04 18:39:41 +02:00
|
|
|
const SQLiteStmtRef & SQLiteColumn::GetCreated(const char * file, int32_t line) const
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
ValidateCreated(file, line);
|
|
|
|
return m_Handle;
|
|
|
|
}
|
|
|
|
#else
|
2022-07-04 18:39:41 +02:00
|
|
|
const SQLiteStmtRef & SQLiteColumn::GetCreated() const
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
ValidateCreated();
|
|
|
|
return m_Handle;
|
|
|
|
}
|
|
|
|
#endif // _DEBUG
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
|
|
|
void SQLiteColumn::ValidateColumn(int32_t idx, const char * file, int32_t line) const
|
|
|
|
{
|
|
|
|
ValidateCreated(file, line);
|
|
|
|
// Is the specified index in range?
|
|
|
|
if (!m_Handle->CheckColumn(idx))
|
|
|
|
{
|
2021-08-18 20:36:59 +02:00
|
|
|
SqThrowF(SQMOD_RTFMT("Column index is out of range: {}:{} =>[{}:{}]"), idx, m_Handle->mColumns,
|
2021-06-12 16:51:01 +02:00
|
|
|
file, line);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
void SQLiteColumn::ValidateColumn(int32_t idx) const
|
|
|
|
{
|
|
|
|
ValidateCreated();
|
|
|
|
// Is the specified index in range?
|
|
|
|
if (!m_Handle->CheckColumn(idx))
|
|
|
|
{
|
2021-07-03 13:09:58 +02:00
|
|
|
SqThrowF(fmt::runtime("Column index is out of range: {}:{}"), idx, m_Handle->mColumns);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // _DEBUG
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
|
|
|
void SQLiteColumn::ValidateRow(const char * file, int32_t line) const
|
|
|
|
{
|
|
|
|
ValidateCreated(file, line);
|
|
|
|
// Do we have any rows available?
|
|
|
|
if (!m_Handle->mGood)
|
|
|
|
{
|
|
|
|
STHROWF("No row available =>[{}:{}]", file, line);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
void SQLiteColumn::ValidateRow() const
|
|
|
|
{
|
|
|
|
ValidateCreated();
|
|
|
|
// Do we have any rows available?
|
|
|
|
if (!m_Handle->mGood)
|
|
|
|
{
|
|
|
|
STHROWF("No row available");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // _DEBUG
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void SQLiteColumn::SetIndex(const Object & column)
|
|
|
|
{
|
|
|
|
// Where the index will be extracted
|
|
|
|
int32_t idx = -1;
|
|
|
|
// Grab the object virtual machine
|
|
|
|
HSQUIRRELVM vm = column.GetVM();
|
|
|
|
// Remember the current stack size
|
|
|
|
const StackGuard sg(vm);
|
|
|
|
// Push the specified object onto the stack
|
|
|
|
Var< const Object & >::push(vm, column);
|
|
|
|
// Identify the type of column was given
|
|
|
|
switch (column.GetType())
|
|
|
|
{
|
|
|
|
// Is this a string value?
|
|
|
|
case OT_STRING:
|
|
|
|
{
|
|
|
|
// Obtain the object from the stack as a string
|
|
|
|
StackStrF val(vm, -1);
|
|
|
|
// Validate the result
|
|
|
|
if (SQ_FAILED(val.Proc(false)))
|
|
|
|
{
|
|
|
|
STHROWF("{}", LastErrorString(vm));
|
|
|
|
}
|
|
|
|
// Is the obtained string empty?
|
|
|
|
else if (val.mLen <= 0)
|
|
|
|
{
|
|
|
|
STHROWF("Cannot use an empty column name");
|
|
|
|
}
|
|
|
|
// Attempt to find a column with the specified name
|
|
|
|
idx = m_Handle->GetColumnIndex(val.mPtr);
|
|
|
|
} break;
|
|
|
|
// Is this an integer value? (or at least can be easily converted to one)
|
|
|
|
case OT_INTEGER:
|
|
|
|
case OT_FLOAT:
|
|
|
|
case OT_BOOL:
|
|
|
|
{
|
|
|
|
idx = ConvTo< int32_t >::From(PopStackInteger(vm, -1));
|
|
|
|
} break;
|
|
|
|
// Is this an instance that we can extract either a string or integer from it?
|
|
|
|
case OT_INSTANCE:
|
|
|
|
{
|
|
|
|
// Obtain the object from the stack as a string
|
|
|
|
StackStrF val(vm, -1);
|
|
|
|
// Validate the result
|
|
|
|
if (SQ_FAILED(val.Proc(false)))
|
|
|
|
{
|
|
|
|
STHROWF("{}", LastErrorString(vm));
|
|
|
|
}
|
|
|
|
// Is the obtained string empty?
|
|
|
|
else if (val.mLen <= 0)
|
|
|
|
{
|
|
|
|
STHROWF("Cannot use an empty column name");
|
|
|
|
}
|
|
|
|
// Check if this value is made only of digits
|
|
|
|
else if (IsDigitsOnly(val.mPtr))
|
|
|
|
{
|
|
|
|
idx = ConvNum< int32_t >::FromStr(val.mPtr);
|
|
|
|
}
|
|
|
|
// Attempt to find a column with the specified name
|
|
|
|
else
|
|
|
|
{
|
|
|
|
idx = m_Handle->GetColumnIndex(val.mPtr);
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
// We don't recognize this kind of value!
|
|
|
|
default: STHROWF("Unknown column index of type ({})", SqTypeName(column.GetType()));
|
|
|
|
}
|
|
|
|
// Assign the index with a failsafe to invalid on error
|
|
|
|
AutoAssign< int32_t > aa(m_Index, -1, idx);
|
|
|
|
// Validate the obtained column index
|
|
|
|
SQMOD_VALIDATE_COLUMN(*this, idx);
|
|
|
|
// Don't fall back to the invalid index anymore
|
|
|
|
aa.Set(idx);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
Object SQLiteColumn::GetStatement() const
|
|
|
|
{
|
|
|
|
return GetStatementObj(m_Handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
Object SQLiteColumn::GetConnection() const
|
|
|
|
{
|
2022-07-19 18:29:32 +02:00
|
|
|
return GetConnectionObj(SQMOD_GET_VALID(*this)->mConnection);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
bool SQLiteColumn::IsNull() const
|
|
|
|
{
|
|
|
|
return (sqlite3_column_type(SQMOD_GET_CREATED(*this)->mPtr, m_Index) == SQLITE_NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
const SQChar * SQLiteColumn::GetName() const
|
|
|
|
{
|
|
|
|
return sqlite3_column_name(SQMOD_GET_CREATED(*this)->mPtr, m_Index);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
const SQChar * SQLiteColumn::GetOriginName() const // NOLINT(readability-convert-member-functions-to-static)
|
|
|
|
{
|
|
|
|
#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
|
|
|
return sqlite3_column_origin_name(SQMOD_GET_CREATED(*this)->mPtr, m_Index);
|
|
|
|
#else
|
|
|
|
STHROWF("The module was compiled without this feature");
|
|
|
|
// Request failed
|
|
|
|
return _SC("");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
int32_t SQLiteColumn::GetType() const
|
|
|
|
{
|
|
|
|
return sqlite3_column_type(SQMOD_GET_CREATED(*this)->mPtr, m_Index);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
int32_t SQLiteColumn::GetBytes() const
|
|
|
|
{
|
|
|
|
return sqlite3_column_bytes(SQMOD_GET_CREATED(*this)->mPtr, m_Index);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
Object SQLiteColumn::GetValue() const
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_ROW(*this);
|
|
|
|
// Obtain the initial stack size
|
|
|
|
const StackGuard sg;
|
|
|
|
// Identify which type of value must be pushed on the stack
|
2022-07-19 18:29:32 +02:00
|
|
|
switch (sqlite3_column_type(m_Handle->Access(), m_Index))
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
// Is this a null value?
|
|
|
|
case SQLITE_NULL:
|
|
|
|
{
|
|
|
|
sq_pushnull(SqVM());
|
|
|
|
} break;
|
|
|
|
// Is this an integer?
|
|
|
|
case SQLITE_INTEGER:
|
|
|
|
{
|
2022-07-19 18:29:32 +02:00
|
|
|
sq_pushinteger(SqVM(), sqlite3_column_integer(m_Handle->Access(), m_Index));
|
2021-06-12 16:51:01 +02:00
|
|
|
} break;
|
|
|
|
// Is this a floating point?
|
|
|
|
case SQLITE_FLOAT:
|
|
|
|
{
|
|
|
|
sq_pushfloat(SqVM(),
|
2022-07-19 18:29:32 +02:00
|
|
|
ConvTo< SQFloat >::From(sqlite3_column_double(m_Handle->Access(), m_Index)));
|
2021-06-12 16:51:01 +02:00
|
|
|
} break;
|
|
|
|
// Is this a string?
|
|
|
|
case SQLITE_TEXT:
|
|
|
|
{
|
|
|
|
sq_pushstring(SqVM(),
|
2022-07-19 18:29:32 +02:00
|
|
|
reinterpret_cast< const SQChar * >(sqlite3_column_text(m_Handle->Access(), m_Index)),
|
|
|
|
sqlite3_column_bytes(m_Handle->Access(), m_Index));
|
2021-06-12 16:51:01 +02:00
|
|
|
} break;
|
|
|
|
// Is this raw data?
|
|
|
|
case SQLITE_BLOB:
|
|
|
|
{
|
|
|
|
// Retrieve the size of the blob that must be allocated
|
2022-07-19 18:29:32 +02:00
|
|
|
const int32_t size = sqlite3_column_bytes(m_Handle->Access(), m_Index);
|
2021-06-12 16:51:01 +02:00
|
|
|
// Retrieve the the actual blob data that must be returned
|
2022-07-19 18:29:32 +02:00
|
|
|
auto data = reinterpret_cast< const char * >(sqlite3_column_blob(m_Handle->Access(), m_Index));
|
2021-06-12 16:51:01 +02:00
|
|
|
// Attempt to create a buffer with the blob data on the stack
|
|
|
|
Var< const SqBuffer & >::push(SqVM(), SqBuffer(data, size, 0));
|
|
|
|
} break;
|
|
|
|
// Unknown type
|
|
|
|
default: STHROWF("Unknown value to fetch at index: {}", m_Index);
|
|
|
|
}
|
|
|
|
// Obtain the object with the value from the stack and return it
|
|
|
|
return Var< Object >(SqVM(), -1).value;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
Object SQLiteColumn::GetNumber() const
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_ROW(*this);
|
|
|
|
// Obtain the initial stack size
|
|
|
|
const StackGuard sg;
|
|
|
|
// Identify which type of value must be pushed on the stack
|
2022-07-19 18:29:32 +02:00
|
|
|
switch (sqlite3_column_type(m_Handle->Access(), m_Index))
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
// Is this a null value?
|
|
|
|
case SQLITE_NULL:
|
|
|
|
{
|
|
|
|
sq_pushinteger(SqVM(), 0);
|
|
|
|
} break;
|
|
|
|
// Is this an integer?
|
|
|
|
case SQLITE_INTEGER:
|
|
|
|
{
|
2022-07-19 18:29:32 +02:00
|
|
|
sq_pushinteger(SqVM(), sqlite3_column_integer(m_Handle->Access(), m_Index));
|
2021-06-12 16:51:01 +02:00
|
|
|
} break;
|
|
|
|
// Is this a floating point?
|
|
|
|
case SQLITE_FLOAT:
|
|
|
|
{
|
|
|
|
sq_pushfloat(SqVM(),
|
2022-07-19 18:29:32 +02:00
|
|
|
ConvTo< SQFloat >::From(sqlite3_column_double(m_Handle->Access(), m_Index)));
|
2021-06-12 16:51:01 +02:00
|
|
|
} break;
|
|
|
|
// Is this a string?
|
|
|
|
case SQLITE_TEXT:
|
|
|
|
{
|
2022-07-19 18:29:32 +02:00
|
|
|
auto str = reinterpret_cast< const SQChar * >(sqlite3_column_text(m_Handle->Access(), m_Index));
|
2021-06-12 16:51:01 +02:00
|
|
|
// Is there even a string to parse?
|
|
|
|
if (!str || *str == '\0')
|
|
|
|
{
|
|
|
|
sq_pushinteger(SqVM(), 0);
|
|
|
|
}
|
|
|
|
// Can we treat this string as a float?
|
|
|
|
else if (!std::strchr(str, '.'))
|
|
|
|
{
|
|
|
|
sq_pushfloat(SqVM(),
|
|
|
|
ConvTo< SQFloat >::From(std::strtod(str, nullptr)));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sq_pushinteger(SqVM(),
|
|
|
|
ConvTo< SQInteger >::From(std::strtoll(str, nullptr, 10)));
|
|
|
|
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
// Unknown type
|
|
|
|
default: STHROWF("Unknown number to fetch at index: {}", m_Index);
|
|
|
|
}
|
|
|
|
// Obtain the object with the value from the stack and return it
|
|
|
|
return Var< Object >(SqVM(), -1).value;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
SQInteger SQLiteColumn::GetInteger() const
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_ROW(*this);
|
|
|
|
// Return the requested information
|
2022-07-19 18:29:32 +02:00
|
|
|
return sqlite3_column_integer(m_Handle->Access(), m_Index);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
SQFloat SQLiteColumn::GetFloat() const
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_ROW(*this);
|
|
|
|
// Return the requested information
|
2022-07-19 18:29:32 +02:00
|
|
|
return ConvTo< SQFloat >::From(sqlite3_column_double(m_Handle->Access(), m_Index));
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
2021-09-10 20:27:28 +02:00
|
|
|
SQInteger SQLiteColumn::GetLong() const
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_ROW(*this);
|
|
|
|
// Return the requested information
|
2022-07-19 18:29:32 +02:00
|
|
|
return sqlite3_column_int64(m_Handle->Access(), m_Index);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
Object SQLiteColumn::GetString() const
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_ROW(*this);
|
|
|
|
// Obtain the initial stack size
|
|
|
|
const StackGuard sg;
|
|
|
|
// Push the column text on the stack
|
2022-07-19 18:29:32 +02:00
|
|
|
sq_pushstring(SqVM(), reinterpret_cast< const SQChar * >(sqlite3_column_text(m_Handle->Access(), m_Index)),
|
|
|
|
sqlite3_column_bytes(m_Handle->Access(), m_Index));
|
2021-06-12 16:51:01 +02:00
|
|
|
// Get the object from the stack and return it
|
|
|
|
return Var< Object >(SqVM(), -1).value;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
bool SQLiteColumn::GetBoolean() const
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_ROW(*this);
|
|
|
|
// Return the requested information
|
2022-07-19 18:29:32 +02:00
|
|
|
return sqlite3_column_int(m_Handle->Access(), m_Index) > 0;
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
SQChar SQLiteColumn::GetChar() const
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_ROW(*this);
|
|
|
|
// Return the requested information
|
2022-07-19 18:29:32 +02:00
|
|
|
return (SQChar)sqlite3_column_int(m_Handle->Access(), m_Index);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
Object SQLiteColumn::GetBuffer() const
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_ROW(*this);
|
|
|
|
// Remember the current stack size
|
|
|
|
const StackGuard sg;
|
|
|
|
// Retrieve the size of the blob that must be allocated
|
2022-07-19 18:29:32 +02:00
|
|
|
const int32_t size = sqlite3_column_bytes(m_Handle->Access(), m_Index);
|
2021-06-12 16:51:01 +02:00
|
|
|
// Retrieve the the actual blob data that must be returned
|
2022-07-19 18:29:32 +02:00
|
|
|
auto data = reinterpret_cast< const char * >(sqlite3_column_blob(m_Handle->Access(), m_Index));
|
2021-06-12 16:51:01 +02:00
|
|
|
// Attempt to create a buffer with the blob data on the stack
|
|
|
|
Var< const SqBuffer & >::push(SqVM(), SqBuffer(data, size, 0));
|
|
|
|
// Get the object from the stack and return it
|
|
|
|
return Var< Object >(SqVM(), -1).value;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
Object SQLiteColumn::GetBlob() const
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_ROW(*this);
|
|
|
|
// Obtain the initial stack size
|
|
|
|
const StackGuard sg;
|
|
|
|
// Obtain the size of the data
|
2022-07-19 18:29:32 +02:00
|
|
|
const int32_t sz = sqlite3_column_bytes(m_Handle->Access(), m_Index);
|
2021-06-12 16:51:01 +02:00
|
|
|
// Allocate a blob of the same size
|
|
|
|
SQUserPointer p = sqstd_createblob(SqVM(), sz);
|
|
|
|
// Obtain a pointer to the data
|
2022-07-19 18:29:32 +02:00
|
|
|
const void * b = sqlite3_column_blob(m_Handle->Access(), m_Index);
|
2021-06-12 16:51:01 +02:00
|
|
|
// Could the memory blob be allocated?
|
|
|
|
if (!p)
|
|
|
|
{
|
|
|
|
STHROWF("Unable to allocate space for column blob value");
|
|
|
|
}
|
|
|
|
// Is there any data to read?
|
|
|
|
else if (!b)
|
|
|
|
{
|
|
|
|
// Pop the memory blob from the stack
|
|
|
|
sq_pop(SqVM(), 1);
|
|
|
|
// Push a null value instead
|
|
|
|
sq_pushnull(SqVM());
|
|
|
|
}
|
|
|
|
// Copy the data into the memory blob
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::memcpy(p, b, static_cast< size_t >(sz));
|
|
|
|
}
|
|
|
|
// Get the object from the stack and return it
|
|
|
|
return Var< Object >(SqVM(), -1).value;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
|
|
|
void SQLiteStatement::Validate(const char * file, int32_t line) const
|
|
|
|
{
|
|
|
|
if (!m_Handle)
|
|
|
|
{
|
2021-08-18 20:36:59 +02:00
|
|
|
SqThrowF(SQMOD_RTFMT("Invalid SQLite statement reference =>[{}:{}]"), file, line);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
void SQLiteStatement::Validate() const
|
|
|
|
{
|
|
|
|
if (!m_Handle)
|
|
|
|
{
|
2021-07-03 13:09:58 +02:00
|
|
|
SqThrowF(fmt::runtime("Invalid SQLite statement reference"));
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // _DEBUG
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
|
|
|
void SQLiteStatement::ValidateCreated(const char * file, int32_t line) const
|
|
|
|
{
|
|
|
|
if (!m_Handle)
|
|
|
|
{
|
2021-08-18 20:36:59 +02:00
|
|
|
SqThrowF(SQMOD_RTFMT("Invalid SQLite statement reference =>[{}:{}]"), file, line);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
2022-07-19 18:29:32 +02:00
|
|
|
else if (m_Handle->Access() == nullptr)
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
2021-08-18 20:36:59 +02:00
|
|
|
SqThrowF(SQMOD_RTFMT("Invalid SQLite statement =>[{}:{}]"), file, line);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
void SQLiteStatement::ValidateCreated() const
|
|
|
|
{
|
|
|
|
if (!m_Handle)
|
|
|
|
{
|
2021-07-03 13:09:58 +02:00
|
|
|
SqThrowF(fmt::runtime("Invalid SQLite statement reference"));
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
2022-07-19 18:29:32 +02:00
|
|
|
else if (m_Handle->Access() == nullptr)
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
2021-07-03 13:09:58 +02:00
|
|
|
SqThrowF(fmt::runtime("Invalid SQLite statement"));
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // _DEBUG
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
2022-07-04 18:39:41 +02:00
|
|
|
const SQLiteStmtRef & SQLiteStatement::GetValid(const char * file, int32_t line) const
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
Validate(file, line);
|
|
|
|
return m_Handle;
|
|
|
|
}
|
|
|
|
#else
|
2022-07-04 18:39:41 +02:00
|
|
|
const SQLiteStmtRef & SQLiteStatement::GetValid() const
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
Validate();
|
|
|
|
return m_Handle;
|
|
|
|
}
|
|
|
|
#endif // _DEBUG
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
2022-07-04 18:39:41 +02:00
|
|
|
const SQLiteStmtRef & SQLiteStatement::GetCreated(const char * file, int32_t line) const
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
ValidateCreated(file, line);
|
|
|
|
return m_Handle;
|
|
|
|
}
|
|
|
|
#else
|
2022-07-04 18:39:41 +02:00
|
|
|
const SQLiteStmtRef & SQLiteStatement::GetCreated() const
|
2021-06-12 16:51:01 +02:00
|
|
|
{
|
|
|
|
ValidateCreated();
|
|
|
|
return m_Handle;
|
|
|
|
}
|
|
|
|
#endif // _DEBUG
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
|
|
|
void SQLiteStatement::ValidateColumn(int32_t idx, const char * file, int32_t line) const
|
|
|
|
{
|
|
|
|
ValidateCreated(file, line);
|
|
|
|
// Is the specified index in range?
|
|
|
|
if (!m_Handle->CheckColumn(idx))
|
|
|
|
{
|
2021-08-18 20:36:59 +02:00
|
|
|
SqThrowF(SQMOD_RTFMT("Column index is out of range: {}:{} =>[{}:{}]"), idx, m_Handle->mColumns, file, line);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
void SQLiteStatement::ValidateColumn(int32_t idx) const
|
|
|
|
{
|
|
|
|
ValidateCreated();
|
|
|
|
// Is the specified index in range?
|
|
|
|
if (!m_Handle->CheckColumn(idx))
|
|
|
|
{
|
2021-07-03 13:09:58 +02:00
|
|
|
SqThrowF(fmt::runtime("Column index is out of range: {}:{}"), idx, m_Handle->mColumns);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // _DEBUG
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
|
|
|
void SQLiteStatement::ValidateParam(int32_t idx, const char * file, int32_t line) const
|
|
|
|
{
|
|
|
|
ValidateCreated(file, line);
|
|
|
|
// Is the specified index in range?
|
|
|
|
if (!m_Handle->CheckParameter(idx))
|
|
|
|
{
|
2021-08-18 20:36:59 +02:00
|
|
|
SqThrowF(SQMOD_RTFMT("Parameter index is out of range: {}:{} =>[{}:{}]"), idx, m_Handle->mParameters, file, line);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
void SQLiteStatement::ValidateParam(int32_t idx) const
|
|
|
|
{
|
|
|
|
ValidateCreated();
|
|
|
|
// Is the specified index in range?
|
|
|
|
if (!m_Handle->CheckParameter(idx))
|
|
|
|
{
|
2021-07-03 13:09:58 +02:00
|
|
|
SqThrowF(fmt::runtime("Parameter index is out of range: {}:{}"), idx, m_Handle->mParameters);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // _DEBUG
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
|
|
|
|
void SQLiteStatement::ValidateRow(const char * file, int32_t line) const
|
|
|
|
{
|
|
|
|
ValidateCreated(file, line);
|
|
|
|
// Do we have any rows available?
|
|
|
|
if (!m_Handle->mGood)
|
|
|
|
{
|
2021-08-18 20:36:59 +02:00
|
|
|
SqThrowF(SQMOD_RTFMT("No row available =>[{}:{}]"), file, line);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
void SQLiteStatement::ValidateRow() const
|
|
|
|
{
|
|
|
|
ValidateCreated();
|
|
|
|
// Do we have any rows available?
|
|
|
|
if (!m_Handle->mGood)
|
|
|
|
{
|
2021-07-03 13:09:58 +02:00
|
|
|
SqThrowF(fmt::runtime("No row available"));
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // _DEBUG
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
SQLiteStatement::SQLiteStatement(const SQLiteConnection & connection, StackStrF & query)
|
|
|
|
: m_Handle(new SQLiteStmtHnd(connection.GetHandle()))
|
|
|
|
{
|
|
|
|
SQMOD_GET_VALID(*this)->Create(query.mPtr, query.mLen);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
Object SQLiteStatement::GetConnection() const
|
|
|
|
{
|
2022-07-19 18:29:32 +02:00
|
|
|
return Object(new SQLiteConnection(SQMOD_GET_VALID(*this)->mConnection));
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
SQLiteStatement & SQLiteStatement::Reset()
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Specify that we don't have a row available and we haven't finished stepping
|
|
|
|
m_Handle->mGood = false;
|
|
|
|
m_Handle->mDone = false;
|
|
|
|
// Attempt to reset the statement to it's initial state
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_reset(m_Handle->Access());
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF("Unable to reset statement [{}]", m_Handle->ErrStr());
|
|
|
|
}
|
|
|
|
// Allow further chaining of operations
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
SQLiteStatement & SQLiteStatement::Clear()
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Specify that we don't have a row available and we haven't finished stepping
|
|
|
|
m_Handle->mGood = false;
|
|
|
|
m_Handle->mDone = false;
|
|
|
|
// Attempt to clear the statement
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_clear_bindings(m_Handle->Access());
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF("Unable to clear statement [{}]", m_Handle->ErrStr());
|
|
|
|
}
|
|
|
|
// Allow further chaining of operations
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
int32_t SQLiteStatement::Exec()
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Did we reset first?
|
|
|
|
if (m_Handle->mDone)
|
|
|
|
{
|
|
|
|
STHROWF("Executed without resetting first");
|
|
|
|
}
|
|
|
|
// Attempt to step the statement
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_step(m_Handle->Access());
|
2021-06-12 16:51:01 +02:00
|
|
|
// Have we finished stepping?
|
|
|
|
if (m_Handle->mStatus == SQLITE_DONE)
|
|
|
|
{
|
|
|
|
// Specify that we don't have row available and we finished stepping
|
|
|
|
m_Handle->mGood = false;
|
|
|
|
m_Handle->mDone = true;
|
|
|
|
// Return the changes made by this statement
|
2022-07-19 18:29:32 +02:00
|
|
|
return sqlite3_changes(m_Handle->mConnection->mPtr);
|
2021-06-12 16:51:01 +02:00
|
|
|
}
|
|
|
|
// Specify that we don't have any row and we haven't finished stepping
|
|
|
|
m_Handle->mGood = false;
|
|
|
|
m_Handle->mDone = false;
|
|
|
|
// Inspect the result
|
|
|
|
switch (m_Handle->mStatus)
|
|
|
|
{
|
|
|
|
// We don't expect any rows to be returned in this case!
|
|
|
|
case SQLITE_ROW: STHROWF("Results were found");
|
|
|
|
// fall through
|
|
|
|
case SQLITE_BUSY: STHROWF("Database was busy");
|
|
|
|
// fall through
|
|
|
|
case SQLITE_ERROR: STHROWF("Runtime error occurred");
|
|
|
|
// fall through
|
|
|
|
case SQLITE_MISUSE: STHROWF("Statement misuse");
|
|
|
|
// fall through
|
|
|
|
default: STHROWF("Unknown failure [{}]", m_Handle->ErrStr());
|
|
|
|
}
|
|
|
|
// Operation failed (shouldn't reach this point!)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
bool SQLiteStatement::Step()
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_CREATED(*this);
|
|
|
|
// Did we reset first?
|
|
|
|
if (m_Handle->mDone)
|
|
|
|
{
|
|
|
|
STHROWF("Stepped without resetting first");
|
|
|
|
}
|
|
|
|
// Attempt to step the statement
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_step(m_Handle->Access());
|
2021-06-12 16:51:01 +02:00
|
|
|
// Do we have a row available?
|
|
|
|
if (m_Handle->mStatus == SQLITE_ROW)
|
|
|
|
{
|
|
|
|
// Specify that we have a row available
|
|
|
|
return (m_Handle->mGood = true);
|
|
|
|
}
|
|
|
|
// Have we finished stepping?
|
|
|
|
else if (m_Handle->mStatus == SQLITE_DONE)
|
|
|
|
{
|
|
|
|
// Specify that we finished stepping
|
|
|
|
m_Handle->mDone = true;
|
|
|
|
// Specify that we don't have a row available
|
|
|
|
return (m_Handle->mGood = false);
|
|
|
|
}
|
|
|
|
// Specify that we don't have any row and we haven't finished stepping
|
|
|
|
m_Handle->mGood = false;
|
|
|
|
m_Handle->mDone = false;
|
|
|
|
// Inspect the result
|
|
|
|
switch (m_Handle->mStatus)
|
|
|
|
{
|
|
|
|
case SQLITE_BUSY: STHROWF("Database was busy");
|
|
|
|
// fall through
|
|
|
|
case SQLITE_ERROR: STHROWF("Runtime error occurred");
|
|
|
|
// fall through
|
|
|
|
case SQLITE_MISUSE: STHROWF("Statement misuse");
|
|
|
|
// fall through
|
|
|
|
default: STHROWF("Unknown failure [{}]", m_Handle->ErrStr());
|
|
|
|
}
|
|
|
|
// Operation failed (shouldn't reach this point!)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
SQLiteStatement & SQLiteStatement::SetArray(int32_t idx, const Array & arr)
|
|
|
|
{
|
|
|
|
// Obtain a script iterator
|
|
|
|
Array::iterator itr;
|
|
|
|
// Create a parameter instance to bind the values
|
|
|
|
SQLiteParameter param(m_Handle);
|
|
|
|
// Process each element until _next returns null
|
|
|
|
while (idx <= m_Handle->mParameters && arr.Next(itr))
|
|
|
|
{
|
|
|
|
// Update the parameter index
|
|
|
|
param.SetIndex(idx++);
|
|
|
|
// Bind it to the current index
|
|
|
|
param.SetValue(Object(itr.getValue()));
|
|
|
|
}
|
|
|
|
// Allow further chaining of operations
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
SQLiteStatement & SQLiteStatement::SetTable(const Table & tbl)
|
|
|
|
{
|
|
|
|
// Is there anything to bind?
|
|
|
|
if (tbl.GetSize() <= 0)
|
|
|
|
{
|
|
|
|
return *this; // Nothing to bind!
|
|
|
|
}
|
|
|
|
// Obtain a table iterator
|
|
|
|
Table::iterator itr;
|
|
|
|
// Create a parameter instance to bind the values
|
|
|
|
SQLiteParameter param(m_Handle);
|
|
|
|
// Process each element until _next returns null
|
|
|
|
while (tbl.Next(itr))
|
|
|
|
{
|
|
|
|
// Update the parameter index
|
|
|
|
param.SetIndex(itr.getName());
|
|
|
|
// Bind it to the current index
|
|
|
|
param.SetValue(Object(itr.getValue()));
|
|
|
|
}
|
|
|
|
// Allow further chaining of operations
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
Array SQLiteStatement::GetArray(int32_t min, int32_t max) const
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_ROW(*this);
|
|
|
|
// Is the specified minimum index valid?
|
|
|
|
if (min < 0)
|
|
|
|
{
|
|
|
|
STHROWF("Minimum is bellow zero: {}", min);
|
|
|
|
}
|
|
|
|
// Is the minimum actually the minimum?
|
|
|
|
else if (min > max)
|
|
|
|
{
|
|
|
|
STHROWF("Minimum is higher than maximum: {} > {}", min, max);
|
|
|
|
}
|
|
|
|
// Is the minimum in range?
|
|
|
|
else if (!m_Handle->CheckColumn(min))
|
|
|
|
{
|
|
|
|
STHROWF("Minimum is out of range: {}:{}", min, m_Handle->mColumns);
|
|
|
|
}
|
|
|
|
// Is the maximum in range?
|
|
|
|
else if (!m_Handle->CheckColumn(max))
|
|
|
|
{
|
|
|
|
STHROWF("Maximum is out of range: {}:{}", max, m_Handle->mColumns);
|
|
|
|
}
|
|
|
|
// Allocate an array large enough to hold the values from selected columns
|
|
|
|
Array arr(SqVM(), max-min);
|
|
|
|
// Create a column instance to retrieve the values
|
|
|
|
SQLiteColumn column(m_Handle);
|
|
|
|
// Array element counter
|
|
|
|
int32_t elem = 0;
|
|
|
|
// Process the range of selected columns
|
|
|
|
while (min <= max)
|
|
|
|
{
|
|
|
|
// Update the column index
|
|
|
|
column.SetIndex(min++);
|
|
|
|
// Retrieve the column value and bind it to the array
|
|
|
|
arr.SetValue(elem++, column.GetValue());
|
|
|
|
}
|
|
|
|
// Return the resulted array
|
|
|
|
return arr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
Table SQLiteStatement::GetTable(int32_t min, int32_t max) const
|
|
|
|
{
|
|
|
|
SQMOD_VALIDATE_ROW(*this);
|
|
|
|
// Is the specified minimum index valid?
|
|
|
|
if (min < 0)
|
|
|
|
{
|
|
|
|
STHROWF("Minimum is bellow zero: {}", min);
|
|
|
|
}
|
|
|
|
// Is the minimum actually the minimum?
|
|
|
|
else if (min > max)
|
|
|
|
{
|
|
|
|
STHROWF("Minimum is higher than maximum: {} > {}", min, max);
|
|
|
|
}
|
|
|
|
// Is the minimum in range>
|
|
|
|
else if (!m_Handle->CheckColumn(min))
|
|
|
|
{
|
|
|
|
STHROWF("Minimum is out of range: {}:{}", min, m_Handle->mColumns);
|
|
|
|
}
|
|
|
|
// Is the maximum in range?
|
|
|
|
else if (!m_Handle->CheckColumn(max))
|
|
|
|
{
|
|
|
|
STHROWF("Maximum is out of range: {}:{}", max, m_Handle->mColumns);
|
|
|
|
}
|
|
|
|
// Create a table to hold the selected column values
|
|
|
|
Table tbl(SqVM());
|
|
|
|
// Create a column instance to retrieve the values
|
|
|
|
SQLiteColumn column(m_Handle);
|
|
|
|
// Process the range of selected columns
|
|
|
|
while (min <= max)
|
|
|
|
{
|
|
|
|
// Attempt to obtain the column name
|
2022-07-19 18:29:32 +02:00
|
|
|
const SQChar * name = sqlite3_column_name(m_Handle->Access(), min);
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the obtained name
|
|
|
|
if (!name)
|
|
|
|
{
|
|
|
|
STHROWF("Unable to retrieve name of column ({})", min);
|
|
|
|
}
|
|
|
|
// Update the column index
|
|
|
|
column.SetIndex(min++);
|
|
|
|
// Retrieve the column value and bind it to the table
|
|
|
|
tbl.SetValue(name, column.GetValue());
|
|
|
|
}
|
|
|
|
// Return the resulted table
|
|
|
|
return tbl;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
SQLiteTransaction::SQLiteTransaction(const SQLiteConnection & db)
|
|
|
|
: SQLiteTransaction(db.GetHandle())
|
|
|
|
{
|
|
|
|
/* ... */
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
2022-07-04 18:39:41 +02:00
|
|
|
SQLiteTransaction::SQLiteTransaction(SQLiteConnRef db)
|
2021-06-12 16:51:01 +02:00
|
|
|
: m_Handle(std::move(db)), m_Committed(false)
|
|
|
|
{
|
|
|
|
// Was the specified database connection valid?
|
|
|
|
if (!m_Handle)
|
|
|
|
{
|
|
|
|
STHROWF("Invalid connection handle");
|
|
|
|
}
|
|
|
|
// Attempt to begin transaction
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_exec(m_Handle->Access(), "BEGIN", nullptr, nullptr, nullptr);
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF("Unable to begin transaction [{}]", m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
SQLiteTransaction::~SQLiteTransaction()
|
|
|
|
{
|
|
|
|
// Was this transaction successfully committed?
|
|
|
|
if (m_Committed)
|
|
|
|
{
|
|
|
|
return; // We're done here!
|
|
|
|
}
|
|
|
|
// Attempt to roll back changes because this failed to commit
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_exec(m_Handle->Access(), "ROLLBACK", nullptr, nullptr, nullptr);
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
// We cannot throw exceptions in destructor
|
|
|
|
LogErr("Unable to rollback transaction [%s]", m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
bool SQLiteTransaction::Commit()
|
|
|
|
{
|
|
|
|
// We shouldn't even be here if there wasn't a valid connection but let's be sure
|
|
|
|
if (!m_Handle)
|
|
|
|
{
|
|
|
|
STHROWF("Invalid database connection");
|
|
|
|
}
|
|
|
|
// Was this transaction already committed?
|
|
|
|
else if (m_Committed)
|
|
|
|
{
|
|
|
|
STHROWF("Transaction was already committed");
|
|
|
|
}
|
|
|
|
// Attempt to commit the change during this transaction
|
2022-07-19 18:29:32 +02:00
|
|
|
m_Handle->mStatus = sqlite3_exec(m_Handle->Access(), "COMMIT", nullptr, nullptr, nullptr);
|
2021-06-12 16:51:01 +02:00
|
|
|
// Validate the result
|
|
|
|
if (m_Handle->mStatus != SQLITE_OK)
|
|
|
|
{
|
|
|
|
STHROWF("Unable to commit transaction [{}]", m_Handle->ErrMsg());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_Committed = true; // Everything was committed successfully
|
|
|
|
}
|
|
|
|
// Return the result
|
|
|
|
return m_Committed;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ================================================================================================
|
|
|
|
void Register_SQLite(HSQUIRRELVM vm)
|
|
|
|
{
|
|
|
|
Enumeration e(vm);
|
|
|
|
EnumElements(g_MainEnum).Bind(e);
|
|
|
|
ConstTable(vm).Enum(_SC("SQLiteOpt"), e);
|
|
|
|
|
|
|
|
Table sqlns(vm);
|
|
|
|
|
|
|
|
sqlns.Func(_SC("IsQueryEmpty"), &IsQueryEmpty)
|
|
|
|
.Func(_SC("GetErrStr"), &GetErrStr)
|
|
|
|
.Func(_SC("SetSoftHeapLimit"), &SetSoftHeapLimit)
|
|
|
|
.Func(_SC("ReleaseMemory"), &ReleaseMemory)
|
|
|
|
.Func(_SC("MemoryUsage"), &GetMemoryUsage)
|
|
|
|
.Func(_SC("MemoryHighwaterMark"), &GetMemoryHighwaterMark)
|
|
|
|
.Func(_SC("ArrayToQueryColumns"), &ArrayToQueryColumns)
|
|
|
|
.Func(_SC("TableToQueryColumns"), &TableToQueryColumns)
|
|
|
|
.FmtFunc(_SC("EscapeString"), &EscapeString)
|
|
|
|
.FmtFunc(_SC("EscapeStringEx"), &EscapeStringEx)
|
|
|
|
.FmtFunc(_SC("Escape"), &EscapeString)
|
|
|
|
.FmtFunc(_SC("EscapeEx"), &EscapeStringEx);
|
|
|
|
|
|
|
|
sqlns.Bind(_SC("Connection"),
|
|
|
|
Class< SQLiteConnection >(sqlns.GetVM(), SQLiteConnectionTypename::Str)
|
|
|
|
// Constructors
|
|
|
|
.Ctor()
|
|
|
|
.Ctor< StackStrF & >()
|
|
|
|
.Ctor< StackStrF &, int32_t >()
|
|
|
|
.Ctor< StackStrF &, int32_t, StackStrF & >()
|
|
|
|
// Meta-methods
|
|
|
|
.SquirrelFunc(_SC("_typename"), &SQLiteConnectionTypename::Fn)
|
|
|
|
.Func(_SC("_tostring"), &SQLiteConnection::ToString)
|
|
|
|
// Properties
|
|
|
|
.Prop(_SC("IsValid"), &SQLiteConnection::IsValid)
|
|
|
|
.Prop(_SC("Connected"), &SQLiteConnection::IsConnected)
|
|
|
|
.Prop(_SC("References"), &SQLiteConnection::GetRefCount)
|
|
|
|
.Prop(_SC("Status"), &SQLiteConnection::GetStatus)
|
|
|
|
.Prop(_SC("Flags"), &SQLiteConnection::GetFlags)
|
|
|
|
.Prop(_SC("Name"), &SQLiteConnection::GetName)
|
|
|
|
.Prop(_SC("VFS"), &SQLiteConnection::GetVFS)
|
|
|
|
.Prop(_SC("ErrCode"), &SQLiteConnection::GetErrorCode)
|
|
|
|
.Prop(_SC("ExErrCode"), &SQLiteConnection::GetExtendedErrorCode)
|
|
|
|
.Prop(_SC("ExtendedErrCode"), &SQLiteConnection::GetExtendedErrorCode)
|
|
|
|
.Prop(_SC("ErrStr"), &SQLiteConnection::GetErrStr)
|
|
|
|
.Prop(_SC("ErrMsg"), &SQLiteConnection::GetErrMsg)
|
|
|
|
.Prop(_SC("ReadOnly"), &SQLiteConnection::IsReadOnly)
|
|
|
|
.Prop(_SC("Autocommit"), &SQLiteConnection::GetAutoCommit)
|
|
|
|
.Prop(_SC("LastInsertRowId"), &SQLiteConnection::GetLastInsertRowID)
|
|
|
|
.Prop(_SC("Changes"), &SQLiteConnection::GetChanges)
|
|
|
|
.Prop(_SC("TotalChanges"), &SQLiteConnection::GetTotalChanges)
|
|
|
|
.Prop(_SC("Trace"), &SQLiteConnection::GetTracing, &SQLiteConnection::SetTracing)
|
|
|
|
.Prop(_SC("Profile"), &SQLiteConnection::GetProfiling, &SQLiteConnection::SetProfiling)
|
|
|
|
.Prop(_SC("QueueSize"), &SQLiteConnection::QueueSize)
|
|
|
|
// Member Methods
|
|
|
|
.Func(_SC("Release"), &SQLiteConnection::Release)
|
|
|
|
.FmtFunc(_SC("Exec"), &SQLiteConnection::Exec)
|
|
|
|
.FmtFunc(_SC("Queue"), &SQLiteConnection::Queue)
|
|
|
|
.FmtFunc(_SC("Query"), &SQLiteConnection::Query)
|
|
|
|
.FmtFunc(_SC("TableExists"), &SQLiteConnection::TableExists)
|
|
|
|
.Func(_SC("InterruptOperation"), &SQLiteConnection::InterruptOperation)
|
|
|
|
.Func(_SC("SetBusyTimeout"), &SQLiteConnection::SetBusyTimeout)
|
|
|
|
.Func(_SC("ReleaseMemory"), &SQLiteConnection::ReleaseMemory)
|
|
|
|
.Func(_SC("ReserveQueue"), &SQLiteConnection::ReserveQueue)
|
|
|
|
.Func(_SC("CompactQueue"), &SQLiteConnection::CompactQueue)
|
|
|
|
.Func(_SC("ClearQueue"), &SQLiteConnection::ClearQueue)
|
|
|
|
.Func(_SC("PopQueue"), &SQLiteConnection::PopQueue)
|
|
|
|
// Member Overloads
|
|
|
|
.Overload< void (SQLiteConnection::*)(StackStrF &) >(_SC("Open"), &SQLiteConnection::Open)
|
|
|
|
.Overload< void (SQLiteConnection::*)(StackStrF &, int32_t) >(_SC("Open"), &SQLiteConnection::Open)
|
|
|
|
.Overload< void (SQLiteConnection::*)(StackStrF &, int32_t, StackStrF &) >(_SC("Open"), &SQLiteConnection::Open)
|
|
|
|
.Overload< int32_t (SQLiteConnection::*)(int32_t) >(_SC("GetInfo"), &SQLiteConnection::GetInfo)
|
|
|
|
.Overload< int32_t (SQLiteConnection::*)(int32_t, bool) >(_SC("GetInfo"), &SQLiteConnection::GetInfo)
|
|
|
|
.Overload< int32_t (SQLiteConnection::*)(int32_t, bool, bool) >(_SC("GetInfo"), &SQLiteConnection::GetInfo)
|
|
|
|
.Overload< int32_t (SQLiteConnection::*)(void) >(_SC("Flush"), &SQLiteConnection::Flush)
|
|
|
|
.Overload< int32_t (SQLiteConnection::*)(SQInteger) >(_SC("Flush"), &SQLiteConnection::Flush)
|
|
|
|
.Overload< int32_t (SQLiteConnection::*)(Object &, Function &) >(_SC("Flush"), &SQLiteConnection::Flush)
|
|
|
|
.Overload< int32_t (SQLiteConnection::*)(SQInteger, Object &, Function &) >(_SC("Flush"), &SQLiteConnection::Flush)
|
|
|
|
);
|
|
|
|
|
|
|
|
sqlns.Bind(_SC("Parameter"),
|
|
|
|
Class< SQLiteParameter >(sqlns.GetVM(), SQLiteParameterTypename::Str)
|
|
|
|
// Constructors
|
|
|
|
.Ctor()
|
|
|
|
.Ctor< const SQLiteParameter & >()
|
|
|
|
// Meta-methods
|
|
|
|
.SquirrelFunc(_SC("_typename"), &SQLiteParameterTypename::Fn)
|
|
|
|
.Func(_SC("_tostring"), &SQLiteParameter::ToString)
|
|
|
|
// Properties
|
|
|
|
.Prop(_SC("IsValid"), &SQLiteParameter::IsValid)
|
|
|
|
.Prop(_SC("References"), &SQLiteParameter::GetRefCount)
|
|
|
|
.Prop(_SC("Index"), &SQLiteParameter::GetIndex)
|
|
|
|
.Prop(_SC("Statement"), &SQLiteParameter::GetStatement)
|
|
|
|
.Prop(_SC("Connection"), &SQLiteParameter::GetConnection)
|
|
|
|
.Prop(_SC("References"), &SQLiteParameter::GetRefCount)
|
|
|
|
.Prop(_SC("Name"), &SQLiteParameter::GetName)
|
|
|
|
// Member Methods
|
|
|
|
.Func(_SC("Release"), &SQLiteParameter::Release)
|
|
|
|
.Func(_SC("SetValue"), &SQLiteParameter::SetValue)
|
|
|
|
.Func(_SC("SetBool"), &SQLiteParameter::SetBool)
|
|
|
|
.Func(_SC("SetChar"), &SQLiteParameter::SetChar)
|
|
|
|
.Func(_SC("SetInteger"), &SQLiteParameter::SetInteger)
|
|
|
|
.Func(_SC("SetInt8"), &SQLiteParameter::SetInt8)
|
|
|
|
.Func(_SC("SetUint8"), &SQLiteParameter::SetUint8)
|
|
|
|
.Func(_SC("SetInt16"), &SQLiteParameter::SetInt16)
|
|
|
|
.Func(_SC("SetUint16"), &SQLiteParameter::SetUint16)
|
|
|
|
.Func(_SC("SetInt32"), &SQLiteParameter::SetInt32)
|
|
|
|
.Func(_SC("SetUint32"), &SQLiteParameter::SetUint32)
|
|
|
|
.Func(_SC("SetInt64"), &SQLiteParameter::SetInt64)
|
|
|
|
.Func(_SC("SetUint64"), &SQLiteParameter::SetUint64)
|
|
|
|
.Func(_SC("SetFloat"), &SQLiteParameter::SetFloat)
|
|
|
|
.Func(_SC("SetFloat32"), &SQLiteParameter::SetFloat32)
|
|
|
|
.Func(_SC("SetFloat64"), &SQLiteParameter::SetFloat64)
|
|
|
|
.FmtFunc(_SC("SetString"), &SQLiteParameter::SetString)
|
|
|
|
.Func(_SC("SetZeroBlob"), &SQLiteParameter::SetZeroBlob)
|
|
|
|
.Func(_SC("SetBlob"), &SQLiteParameter::SetBlob)
|
|
|
|
.Func(_SC("SetData"), &SQLiteParameter::SetData)
|
|
|
|
.Func(_SC("SetDataEx"), &SQLiteParameter::SetDataEx)
|
|
|
|
.Func(_SC("SetDate"), &SQLiteParameter::SetDate)
|
|
|
|
.Func(_SC("SetDateEx"), &SQLiteParameter::SetDateEx)
|
|
|
|
.Func(_SC("SetTime"), &SQLiteParameter::SetTime)
|
|
|
|
.Func(_SC("SetTimeEx"), &SQLiteParameter::SetTimeEx)
|
|
|
|
.Func(_SC("SetDatetime"), &SQLiteParameter::SetDatetime)
|
|
|
|
.Func(_SC("SetDatetimeEx"), &SQLiteParameter::SetDatetimeEx)
|
|
|
|
.Func(_SC("SetNow"), &SQLiteParameter::SetNow)
|
|
|
|
.Func(_SC("SetNull"), &SQLiteParameter::SetNull)
|
|
|
|
);
|
|
|
|
|
|
|
|
sqlns.Bind(_SC("Column"),
|
|
|
|
Class< SQLiteColumn >(sqlns.GetVM(), SQLiteColumnTypename::Str)
|
|
|
|
// Constructors
|
|
|
|
.Ctor()
|
|
|
|
.Ctor< const SQLiteColumn & >()
|
|
|
|
// Meta-methods
|
|
|
|
.SquirrelFunc(_SC("_typename"), &SQLiteColumnTypename::Fn)
|
|
|
|
.Func(_SC("_tostring"), &SQLiteColumn::ToString)
|
|
|
|
// Properties
|
|
|
|
.Prop(_SC("IsValid"), &SQLiteColumn::IsValid)
|
|
|
|
.Prop(_SC("References"), &SQLiteColumn::GetRefCount)
|
|
|
|
.Prop(_SC("Index"), &SQLiteColumn::GetIndex)
|
|
|
|
.Prop(_SC("Statement"), &SQLiteColumn::GetStatement)
|
|
|
|
.Prop(_SC("Connection"), &SQLiteColumn::GetConnection)
|
|
|
|
.Prop(_SC("IsNull"), &SQLiteColumn::IsNull)
|
|
|
|
.Prop(_SC("Name"), &SQLiteColumn::GetName)
|
|
|
|
.Prop(_SC("OriginName"), &SQLiteColumn::GetOriginName)
|
|
|
|
.Prop(_SC("Type"), &SQLiteColumn::GetType)
|
|
|
|
.Prop(_SC("Bytes"), &SQLiteColumn::GetBytes)
|
|
|
|
.Prop(_SC("Value"), &SQLiteColumn::GetValue)
|
|
|
|
.Prop(_SC("Number"), &SQLiteColumn::GetNumber)
|
|
|
|
.Prop(_SC("Integer"), &SQLiteColumn::GetInteger)
|
|
|
|
.Prop(_SC("Float"), &SQLiteColumn::GetFloat)
|
|
|
|
.Prop(_SC("Long"), &SQLiteColumn::GetLong)
|
|
|
|
.Prop(_SC("String"), &SQLiteColumn::GetString)
|
|
|
|
.Prop(_SC("Boolean"), &SQLiteColumn::GetBoolean)
|
|
|
|
.Prop(_SC("Char"), &SQLiteColumn::GetChar)
|
|
|
|
.Prop(_SC("Buffer"), &SQLiteColumn::GetBuffer)
|
|
|
|
.Prop(_SC("Blob"), &SQLiteColumn::GetBlob)
|
|
|
|
// Member Methods
|
|
|
|
.Func(_SC("Release"), &SQLiteColumn::Release)
|
|
|
|
);
|
|
|
|
|
|
|
|
sqlns.Bind(_SC("Statement"),
|
|
|
|
Class< SQLiteStatement >(sqlns.GetVM(), SQLiteStatementTypename::Str)
|
|
|
|
// Constructors
|
|
|
|
.Ctor()
|
|
|
|
.Ctor< const SQLiteStatement & >()
|
|
|
|
.Ctor< const SQLiteConnection &, StackStrF & >()
|
|
|
|
// Meta-methods
|
|
|
|
.SquirrelFunc(_SC("_typename"), &SQLiteStatementTypename::Fn)
|
|
|
|
.Func(_SC("_tostring"), &SQLiteStatement::ToString)
|
|
|
|
// Properties
|
|
|
|
.Prop(_SC("IsValid"), &SQLiteStatement::IsValid)
|
|
|
|
.Prop(_SC("Prepared"), &SQLiteStatement::IsPrepared)
|
|
|
|
.Prop(_SC("References"), &SQLiteStatement::GetReferences)
|
|
|
|
.Prop(_SC("Connection"), &SQLiteStatement::GetConnection)
|
|
|
|
.Prop(_SC("Status"), &SQLiteStatement::GetStatus)
|
|
|
|
.Prop(_SC("ErrCode"), &SQLiteStatement::GetErrorCode)
|
|
|
|
.Prop(_SC("ExErrCode"), &SQLiteStatement::GetExtendedErrorCode)
|
|
|
|
.Prop(_SC("ExtendedErrCode"), &SQLiteStatement::GetExtendedErrorCode)
|
|
|
|
.Prop(_SC("ErrStr"), &SQLiteStatement::GetErrStr)
|
|
|
|
.Prop(_SC("ErrMsg"), &SQLiteStatement::GetErrMsg)
|
|
|
|
.Prop(_SC("Columns"), &SQLiteStatement::GetColumns)
|
|
|
|
.Prop(_SC("Parameters"), &SQLiteStatement::GetParameters)
|
|
|
|
.Prop(_SC("Query"), &SQLiteStatement::GetQuery)
|
|
|
|
.Prop(_SC("Good"), &SQLiteStatement::GetGood)
|
|
|
|
.Prop(_SC("Done"), &SQLiteStatement::GetDone)
|
|
|
|
.Prop(_SC("DataCount"), &SQLiteStatement::GetDataCount)
|
|
|
|
// Member Methods
|
|
|
|
.Func(_SC("Release"), &SQLiteStatement::Release)
|
|
|
|
.Func(_SC("CheckParameter"), &SQLiteStatement::CheckParameter)
|
|
|
|
.FmtFunc(_SC("GetParameterIndex"), &SQLiteStatement::GetParameterIndex)
|
|
|
|
.Func(_SC("GetParameterName"), &SQLiteStatement::GetParameterName)
|
|
|
|
.Func(_SC("CheckColumn"), &SQLiteStatement::CheckColumn)
|
|
|
|
.Func(_SC("IsColumnNull"), &SQLiteStatement::IsColumnNull)
|
|
|
|
.FmtFunc(_SC("ColumnIndex"), &SQLiteStatement::GetColumnIndex)
|
|
|
|
.Func(_SC("ColumnName"), &SQLiteStatement::GetColumnName)
|
|
|
|
.Func(_SC("ColumnOriginName"), &SQLiteStatement::GetColumnOriginName)
|
|
|
|
.Func(_SC("ColumnType"), &SQLiteStatement::GetColumnType)
|
|
|
|
.Func(_SC("ColumnBytes"), &SQLiteStatement::GetColumnBytes)
|
|
|
|
.Func(_SC("Reset"), &SQLiteStatement::Reset)
|
|
|
|
.Func(_SC("Clear"), &SQLiteStatement::Clear)
|
|
|
|
.Func(_SC("Exec"), &SQLiteStatement::Exec)
|
|
|
|
.Func(_SC("Step"), &SQLiteStatement::Step)
|
|
|
|
.Func(_SC("Param"), &SQLiteStatement::GetParameter)
|
|
|
|
.Func(_SC("Parameter"), &SQLiteStatement::GetParameter)
|
|
|
|
.Func(_SC("SetValue"), &SQLiteStatement::SetValue)
|
|
|
|
.Func(_SC("SetBool"), &SQLiteStatement::SetBool)
|
|
|
|
.Func(_SC("SetChar"), &SQLiteStatement::SetChar)
|
|
|
|
.Func(_SC("SetInteger"), &SQLiteStatement::SetInteger)
|
|
|
|
.Func(_SC("SetInt8"), &SQLiteStatement::SetInt8)
|
|
|
|
.Func(_SC("SetUint8"), &SQLiteStatement::SetUint8)
|
|
|
|
.Func(_SC("SetInt16"), &SQLiteStatement::SetInt16)
|
|
|
|
.Func(_SC("SetUint16"), &SQLiteStatement::SetUint16)
|
|
|
|
.Func(_SC("SetInt32"), &SQLiteStatement::SetInt32)
|
|
|
|
.Func(_SC("SetUint32"), &SQLiteStatement::SetUint32)
|
|
|
|
.Func(_SC("SetInt64"), &SQLiteStatement::SetInt64)
|
|
|
|
.Func(_SC("SetUint64"), &SQLiteStatement::SetUint64)
|
|
|
|
.Func(_SC("SetFloat"), &SQLiteStatement::SetFloat)
|
|
|
|
.Func(_SC("SetFloat32"), &SQLiteStatement::SetFloat32)
|
|
|
|
.Func(_SC("SetFloat64"), &SQLiteStatement::SetFloat64)
|
|
|
|
.FmtFunc(_SC("SetString"), &SQLiteStatement::SetString)
|
|
|
|
.Func(_SC("SetZeroBlob"), &SQLiteStatement::SetZeroBlob)
|
|
|
|
.Func(_SC("SetBlob"), &SQLiteStatement::SetBlob)
|
|
|
|
.Func(_SC("SetData"), &SQLiteStatement::SetData)
|
|
|
|
.Func(_SC("SetDate"), &SQLiteStatement::SetDate)
|
|
|
|
.Func(_SC("SetDateEx"), &SQLiteStatement::SetDateEx)
|
|
|
|
.Func(_SC("SetTime"), &SQLiteStatement::SetTime)
|
|
|
|
.Func(_SC("SetTimeEx"), &SQLiteStatement::SetTimeEx)
|
|
|
|
.Func(_SC("SetDatetime"), &SQLiteStatement::SetDatetime)
|
|
|
|
.Func(_SC("SetDatetimeEx"), &SQLiteStatement::SetDatetimeEx)
|
|
|
|
.Func(_SC("SetNow"), &SQLiteStatement::SetNow)
|
|
|
|
.Func(_SC("SetNull"), &SQLiteStatement::SetNull)
|
|
|
|
.Func(_SC("SetArray"), &SQLiteStatement::SetArray)
|
|
|
|
.Func(_SC("SetTable"), &SQLiteStatement::SetTable)
|
|
|
|
.Func(_SC("Field"), &SQLiteStatement::GetColumn)
|
|
|
|
.Func(_SC("Column"), &SQLiteStatement::GetColumn)
|
|
|
|
.Func(_SC("GetValue"), &SQLiteStatement::GetValue)
|
|
|
|
.Func(_SC("GetNumber"), &SQLiteStatement::GetNumber)
|
|
|
|
.Func(_SC("GetInteger"), &SQLiteStatement::GetInteger)
|
|
|
|
.Func(_SC("GetFloat"), &SQLiteStatement::GetFloat)
|
|
|
|
.Func(_SC("GetLong"), &SQLiteStatement::GetLong)
|
|
|
|
.Func(_SC("GetString"), &SQLiteStatement::GetString)
|
|
|
|
.Func(_SC("GetBoolean"), &SQLiteStatement::GetBoolean)
|
|
|
|
.Func(_SC("GetChar"), &SQLiteStatement::GetChar)
|
|
|
|
.Func(_SC("GetBuffer"), &SQLiteStatement::GetBuffer)
|
|
|
|
.Func(_SC("GetBlob"), &SQLiteStatement::GetBlob)
|
|
|
|
// Member overloads
|
|
|
|
.Overload< Array (SQLiteStatement::*)(void) const >(_SC("GetArray"), &SQLiteStatement::GetArray)
|
|
|
|
.Overload< Array (SQLiteStatement::*)(int32_t) const >(_SC("GetArray"), &SQLiteStatement::GetArray)
|
|
|
|
.Overload< Array (SQLiteStatement::*)(int32_t, int32_t) const >(_SC("GetArray"), &SQLiteStatement::GetArray)
|
|
|
|
.Overload< Table (SQLiteStatement::*)(void) const >(_SC("GetTable"), &SQLiteStatement::GetTable)
|
|
|
|
.Overload< Table (SQLiteStatement::*)(int32_t) const >(_SC("GetTable"), &SQLiteStatement::GetTable)
|
|
|
|
.Overload< Table (SQLiteStatement::*)(int32_t, int32_t) const >(_SC("GetTable"), &SQLiteStatement::GetTable)
|
|
|
|
);
|
|
|
|
|
|
|
|
sqlns.Bind(_SC("Transaction"),
|
|
|
|
Class< SQLiteTransaction, NoCopy< SQLiteTransaction > >(sqlns.GetVM(), SQLiteTransactionTypename::Str)
|
|
|
|
// Constructors
|
|
|
|
.Ctor< const SQLiteConnection & >()
|
|
|
|
// Meta-methods
|
|
|
|
.SquirrelFunc(_SC("_typename"), &SQLiteTransactionTypename::Fn)
|
|
|
|
.Func(_SC("_tostring"), &SQLiteTransaction::ToString)
|
|
|
|
// Properties
|
|
|
|
.Prop(_SC("IsValid"), &SQLiteTransaction::IsValid)
|
|
|
|
.Prop(_SC("Committed"), &SQLiteTransaction::Commited)
|
|
|
|
// Member Methods
|
|
|
|
.Func(_SC("Commit"), &SQLiteTransaction::Commit)
|
|
|
|
);
|
|
|
|
|
|
|
|
RootTable(vm).Bind(_SC("SQLite"), sqlns);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // Namespace:: SqMod
|