mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2024-11-08 00:37:15 +01:00
Initial untested SQLite module.
This commit is contained in:
parent
f4a11ef825
commit
6e7abfc354
393
cbp/ModSQLite.cbp
Normal file
393
cbp/ModSQLite.cbp
Normal file
@ -0,0 +1,393 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||
<CodeBlocks_project_file>
|
||||
<FileVersion major="1" minor="6" />
|
||||
<Project>
|
||||
<Option title="Mod SQLite" />
|
||||
<Option pch_mode="2" />
|
||||
<Option compiler="gcc" />
|
||||
<Build>
|
||||
<Target title="Win32 Debug Dynamic">
|
||||
<Option output="../bin/win32-d/mod_sqlite32" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
|
||||
<Option working_dir="../bin/win32-d/" />
|
||||
<Option object_output="../obj/mingw32-d/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-m32" />
|
||||
<Add option="-g" />
|
||||
<Add option="-D_DEBUG" />
|
||||
<Add directory="../config/mingw32" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-m32" />
|
||||
<Add directory="../lib/mingw32-d" />
|
||||
</Linker>
|
||||
<ExtraCommands>
|
||||
<Add after='cmd /c copy /Y "$(PROJECT_DIR)$(TARGET_OUTPUT_FILE)" "$(PROJECT_DIR)..\bin\plugins\$(TARGET_OUTPUT_BASENAME).dll"' />
|
||||
</ExtraCommands>
|
||||
</Target>
|
||||
<Target title="Win32 Release Dynamic">
|
||||
<Option output="../bin/win32/mod_sqlite32" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
|
||||
<Option working_dir="../bin/win32/" />
|
||||
<Option object_output="../obj/mingw32/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-O3" />
|
||||
<Add option="-m32" />
|
||||
<Add option="-DNDEBUG" />
|
||||
<Add directory="../config/mingw32" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-s" />
|
||||
<Add option="-m32" />
|
||||
<Add directory="../lib/mingw32" />
|
||||
</Linker>
|
||||
<ExtraCommands>
|
||||
<Add after='cmd /c copy /Y "$(PROJECT_DIR)$(TARGET_OUTPUT_FILE)" "$(PROJECT_DIR)..\bin\plugins\$(TARGET_OUTPUT_BASENAME).dll"' />
|
||||
</ExtraCommands>
|
||||
</Target>
|
||||
<Target title="Win64 Debug Dynamic">
|
||||
<Option output="../bin/win64-d/mod_sqlite64" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
|
||||
<Option working_dir="../bin/win64-d/" />
|
||||
<Option object_output="../obj/mingw64-d/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-m64" />
|
||||
<Add option="-g" />
|
||||
<Add option="-D_DEBUG" />
|
||||
<Add option="-D_SQ64" />
|
||||
<Add directory="../config/mingw64" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-m64" />
|
||||
<Add directory="../lib/mingw64-d" />
|
||||
</Linker>
|
||||
<ExtraCommands>
|
||||
<Add after='cmd /c copy /Y "$(PROJECT_DIR)$(TARGET_OUTPUT_FILE)" "$(PROJECT_DIR)..\bin\plugins\$(TARGET_OUTPUT_BASENAME).dll"' />
|
||||
</ExtraCommands>
|
||||
</Target>
|
||||
<Target title="Win64 Release Dynamic">
|
||||
<Option output="../bin/win64/mod_sqlite64" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
|
||||
<Option working_dir="../bin/win64/" />
|
||||
<Option object_output="../obj/mingw64/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-O3" />
|
||||
<Add option="-m64" />
|
||||
<Add option="-DNDEBUG" />
|
||||
<Add option="-D_SQ64" />
|
||||
<Add directory="../config/mingw64" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-s" />
|
||||
<Add option="-m64" />
|
||||
<Add directory="../lib/mingw64" />
|
||||
</Linker>
|
||||
<ExtraCommands>
|
||||
<Add after='cmd /c copy /Y "$(PROJECT_DIR)$(TARGET_OUTPUT_FILE)" "$(PROJECT_DIR)..\bin\plugins\$(TARGET_OUTPUT_BASENAME).dll"' />
|
||||
</ExtraCommands>
|
||||
</Target>
|
||||
<Target title="Linux32 Debug Dynamic">
|
||||
<Option output="../bin/linux32-d/mod_sqlite32" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
|
||||
<Option working_dir="../bin/linux32-d/" />
|
||||
<Option object_output="../obj/gcc32-d/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-m32" />
|
||||
<Add option="-g" />
|
||||
<Add option="-fPIC" />
|
||||
<Add option="-D_DEBUG" />
|
||||
<Add directory="../config/gcc32" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-m32" />
|
||||
<Add directory="../lib/gcc32-d" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Linux32 Release Dynamic">
|
||||
<Option output="../bin/linux32/mod_sqlite32" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
|
||||
<Option working_dir="../bin/linux32/" />
|
||||
<Option object_output="../obj/gcc32/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-O3" />
|
||||
<Add option="-m32" />
|
||||
<Add option="-fPIC" />
|
||||
<Add option="-DNDEBUG" />
|
||||
<Add directory="../config/gcc32" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-s" />
|
||||
<Add option="-m32" />
|
||||
<Add directory="../lib/gcc32" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Linux64 Debug Dynamic">
|
||||
<Option output="../bin/linux64-d/mod_sqlite64" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
|
||||
<Option working_dir="../bin/linux64-d/" />
|
||||
<Option object_output="../obj/gcc64-d/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-m64" />
|
||||
<Add option="-g" />
|
||||
<Add option="-fPIC" />
|
||||
<Add option="-D_DEBUG" />
|
||||
<Add option="-D_SQ64" />
|
||||
<Add directory="../config/gcc64" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-m64" />
|
||||
<Add directory="../lib/gcc64-d" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Linux64 Release Dynamic">
|
||||
<Option output="../bin/linux64/mod_sqlite64" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
|
||||
<Option working_dir="../bin/linux64/" />
|
||||
<Option object_output="../obj/gcc64/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-O3" />
|
||||
<Add option="-m64" />
|
||||
<Add option="-fPIC" />
|
||||
<Add option="-DNDEBUG" />
|
||||
<Add option="-D_SQ64" />
|
||||
<Add directory="../config/gcc64" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-s" />
|
||||
<Add option="-m64" />
|
||||
<Add directory="../lib/gcc64" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Win32 Debug Standalone">
|
||||
<Option output="../bin/win32-d/mod_sqlite32" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
|
||||
<Option working_dir="../bin/win32-d/" />
|
||||
<Option object_output="../obj/mingw32-d/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-m32" />
|
||||
<Add option="-g" />
|
||||
<Add option="-static-libgcc" />
|
||||
<Add option="-static-libstdc++" />
|
||||
<Add option="-enable-static" />
|
||||
<Add option="-D_DEBUG" />
|
||||
<Add directory="../config/mingw32" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-m32" />
|
||||
<Add option="-static" />
|
||||
<Add directory="../lib/mingw32-d" />
|
||||
</Linker>
|
||||
<ExtraCommands>
|
||||
<Add after='cmd /c copy /Y "$(PROJECT_DIR)$(TARGET_OUTPUT_FILE)" "$(PROJECT_DIR)..\bin\plugins\$(TARGET_OUTPUT_BASENAME).dll"' />
|
||||
</ExtraCommands>
|
||||
</Target>
|
||||
<Target title="Win32 Release Standalone">
|
||||
<Option output="../bin/win32/mod_sqlite32" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
|
||||
<Option working_dir="../bin/win32/" />
|
||||
<Option object_output="../obj/mingw32/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-O3" />
|
||||
<Add option="-m32" />
|
||||
<Add option="-static-libgcc" />
|
||||
<Add option="-static-libstdc++" />
|
||||
<Add option="-enable-static" />
|
||||
<Add option="-DNDEBUG" />
|
||||
<Add directory="../config/mingw32" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-s" />
|
||||
<Add option="-m32" />
|
||||
<Add option="-static" />
|
||||
<Add directory="../lib/mingw32" />
|
||||
</Linker>
|
||||
<ExtraCommands>
|
||||
<Add after='cmd /c copy /Y "$(PROJECT_DIR)$(TARGET_OUTPUT_FILE)" "$(PROJECT_DIR)..\bin\plugins\$(TARGET_OUTPUT_BASENAME).dll"' />
|
||||
</ExtraCommands>
|
||||
</Target>
|
||||
<Target title="Win64 Debug Standalone">
|
||||
<Option output="../bin/win64-d/mod_sqlite64" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
|
||||
<Option working_dir="../bin/win64-d/" />
|
||||
<Option object_output="../obj/mingw64-d/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-m64" />
|
||||
<Add option="-g" />
|
||||
<Add option="-static-libgcc" />
|
||||
<Add option="-static-libstdc++" />
|
||||
<Add option="-enable-static" />
|
||||
<Add option="-D_DEBUG" />
|
||||
<Add option="-D_SQ64" />
|
||||
<Add directory="../config/mingw64" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-m64" />
|
||||
<Add option="-static" />
|
||||
<Add directory="../lib/mingw64-d" />
|
||||
</Linker>
|
||||
<ExtraCommands>
|
||||
<Add after='cmd /c copy /Y "$(PROJECT_DIR)$(TARGET_OUTPUT_FILE)" "$(PROJECT_DIR)..\bin\plugins\$(TARGET_OUTPUT_BASENAME).dll"' />
|
||||
</ExtraCommands>
|
||||
</Target>
|
||||
<Target title="Win64 Release Standalone">
|
||||
<Option output="../bin/win64/mod_sqlite64" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
|
||||
<Option working_dir="../bin/win64/" />
|
||||
<Option object_output="../obj/mingw64/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-O3" />
|
||||
<Add option="-m64" />
|
||||
<Add option="-static-libgcc" />
|
||||
<Add option="-static-libstdc++" />
|
||||
<Add option="-enable-static" />
|
||||
<Add option="-DNDEBUG" />
|
||||
<Add option="-D_SQ64" />
|
||||
<Add directory="../config/mingw64" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-s" />
|
||||
<Add option="-m64" />
|
||||
<Add option="-static" />
|
||||
<Add directory="../lib/mingw64" />
|
||||
</Linker>
|
||||
<ExtraCommands>
|
||||
<Add after='cmd /c copy /Y "$(PROJECT_DIR)$(TARGET_OUTPUT_FILE)" "$(PROJECT_DIR)..\bin\plugins\$(TARGET_OUTPUT_BASENAME).dll"' />
|
||||
</ExtraCommands>
|
||||
</Target>
|
||||
<Target title="Linux32 Debug Standalone">
|
||||
<Option output="../bin/linux32-d/mod_sqlite32" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
|
||||
<Option working_dir="../bin/linux32-d/" />
|
||||
<Option object_output="../obj/gcc32-d/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-m32" />
|
||||
<Add option="-g" />
|
||||
<Add option="-static-libgcc" />
|
||||
<Add option="-static-libstdc++" />
|
||||
<Add option="-enable-static" />
|
||||
<Add option="-fPIC" />
|
||||
<Add option="-D_DEBUG" />
|
||||
<Add directory="../config/gcc32" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-m32" />
|
||||
<Add option="-Bstatic" />
|
||||
<Add directory="../lib/gcc32-d" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Linux32 Release Standalone">
|
||||
<Option output="../bin/linux32/mod_sqlite32" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
|
||||
<Option working_dir="../bin/linux32/" />
|
||||
<Option object_output="../obj/gcc32/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-O3" />
|
||||
<Add option="-m32" />
|
||||
<Add option="-static-libgcc" />
|
||||
<Add option="-static-libstdc++" />
|
||||
<Add option="-enable-static" />
|
||||
<Add option="-fPIC" />
|
||||
<Add option="-DNDEBUG" />
|
||||
<Add directory="../config/gcc32" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-s" />
|
||||
<Add option="-m32" />
|
||||
<Add option="-Bstatic" />
|
||||
<Add directory="../lib/gcc32" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Linux64 Debug Standalone">
|
||||
<Option output="../bin/linux64-d/mod_sqlite64" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
|
||||
<Option working_dir="../bin/linux64-d/" />
|
||||
<Option object_output="../obj/gcc64-d/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-m64" />
|
||||
<Add option="-g" />
|
||||
<Add option="-static-libgcc" />
|
||||
<Add option="-static-libstdc++" />
|
||||
<Add option="-enable-static" />
|
||||
<Add option="-fPIC" />
|
||||
<Add option="-D_DEBUG" />
|
||||
<Add option="-D_SQ64" />
|
||||
<Add directory="../config/gcc64" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-m64" />
|
||||
<Add option="-Bstatic" />
|
||||
<Add directory="../lib/gcc64-d" />
|
||||
</Linker>
|
||||
</Target>
|
||||
<Target title="Linux64 Release Standalone">
|
||||
<Option output="../bin/linux64/mod_sqlite64" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="0" extension_auto="1" />
|
||||
<Option working_dir="../bin/linux64/" />
|
||||
<Option object_output="../obj/gcc64/" />
|
||||
<Option type="3" />
|
||||
<Option compiler="gcc" />
|
||||
<Compiler>
|
||||
<Add option="-O3" />
|
||||
<Add option="-m64" />
|
||||
<Add option="-static-libgcc" />
|
||||
<Add option="-static-libstdc++" />
|
||||
<Add option="-enable-static" />
|
||||
<Add option="-fPIC" />
|
||||
<Add option="-DNDEBUG" />
|
||||
<Add option="-D_SQ64" />
|
||||
<Add directory="../config/gcc64" />
|
||||
</Compiler>
|
||||
<Linker>
|
||||
<Add option="-s" />
|
||||
<Add option="-m64" />
|
||||
<Add option="-Bstatic" />
|
||||
<Add directory="../lib/gcc64" />
|
||||
</Linker>
|
||||
</Target>
|
||||
</Build>
|
||||
<Compiler>
|
||||
<Add option="-Wextra" />
|
||||
<Add option="-Wall" />
|
||||
<Add option="-DSQMOD_PLUGIN_API" />
|
||||
<Add directory="../modules/sqlite" />
|
||||
<Add directory="../shared" />
|
||||
<Add directory="../include" />
|
||||
<Add directory="../config/common" />
|
||||
</Compiler>
|
||||
<Unit filename="../external/SQLite/sqlite3.c">
|
||||
<Option compilerVar="CC" />
|
||||
<Option compiler="gcc" use="1" buildCommand="$compiler -Wno-unused-but-set-variable -Wno-unused-parameter -Wno-sign-compare $options $includes -c $file -o $object" />
|
||||
</Unit>
|
||||
<Unit filename="../modules/sqlite/Column.cpp" />
|
||||
<Unit filename="../modules/sqlite/Column.hpp" />
|
||||
<Unit filename="../modules/sqlite/Common.cpp" />
|
||||
<Unit filename="../modules/sqlite/Common.hpp" />
|
||||
<Unit filename="../modules/sqlite/Connection.cpp" />
|
||||
<Unit filename="../modules/sqlite/Connection.hpp" />
|
||||
<Unit filename="../modules/sqlite/Module.cpp" />
|
||||
<Unit filename="../modules/sqlite/Module.hpp" />
|
||||
<Unit filename="../modules/sqlite/Statement.cpp" />
|
||||
<Unit filename="../modules/sqlite/Statement.hpp" />
|
||||
<Unit filename="../shared/SqMod.cpp" />
|
||||
<Extensions>
|
||||
<code_completion />
|
||||
<envvars />
|
||||
<debugger />
|
||||
<lib_finder disable_auto="1" />
|
||||
</Extensions>
|
||||
</Project>
|
||||
</CodeBlocks_project_file>
|
264
modules/sqlite/Column.cpp
Normal file
264
modules/sqlite/Column.cpp
Normal file
@ -0,0 +1,264 @@
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Column.hpp"
|
||||
#include "Connection.hpp"
|
||||
#include "Statement.hpp"
|
||||
#include "Module.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <sqrat.h>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQInteger Column::Typename(HSQUIRRELVM vm)
|
||||
{
|
||||
static SQChar name[] = _SC("SqSQLiteColumn");
|
||||
sq_pushstring(vm, name, sizeof(name));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool Column::Validate() const
|
||||
{
|
||||
// Are we pointing to a valid index?
|
||||
if (m_Index < 0)
|
||||
_SqMod->SqThrow("Invalid column index");
|
||||
// Do we belong to a valid statement?
|
||||
else if (!m_Stmt)
|
||||
_SqMod->SqThrow("Invalid SQLite statement reference");
|
||||
// Requirements satisfied
|
||||
else
|
||||
return true;
|
||||
// Validation failed
|
||||
return false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool Column::RowAvailable() const
|
||||
{
|
||||
// Are we pointing to a valid index?
|
||||
if (m_Index < 0)
|
||||
_SqMod->SqThrow("Invalid column index");
|
||||
// Do we belong to a valid statement?
|
||||
else if (!m_Stmt)
|
||||
_SqMod->SqThrow("Invalid SQLite statement reference");
|
||||
// Do we have any rows available?
|
||||
else if (!m_Stmt->mGood)
|
||||
_SqMod->SqThrow("No row available");
|
||||
// Requirements satisfied
|
||||
else
|
||||
return true;
|
||||
// Validation failed
|
||||
return false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Statement Column::GetStatement() const
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate())
|
||||
return Statement(m_Stmt);
|
||||
// Request failed
|
||||
return Statement();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Connection Column::GetConnection() const
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate())
|
||||
return Connection(m_Stmt->mConn);
|
||||
// Request failed
|
||||
return Connection();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Int32 Column::GetNumber() const
|
||||
{
|
||||
// Validate the handle and index
|
||||
if (RowAvailable())
|
||||
return sqlite3_column_int(m_Stmt, m_Index);
|
||||
// Request failed
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQInteger Column::GetInteger() const
|
||||
{
|
||||
// Validate the handle and index
|
||||
if (RowAvailable())
|
||||
#ifdef _SQ64
|
||||
return sqlite3_column_int64(m_Stmt, m_Index);
|
||||
#else
|
||||
return sqlite3_column_int(m_Stmt, m_Index);
|
||||
#endif
|
||||
// Request failed
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQFloat Column::GetFloat() const
|
||||
{
|
||||
// Validate the handle and index
|
||||
if (RowAvailable())
|
||||
return (SQFloat)sqlite3_column_double(m_Stmt, m_Index);
|
||||
// Request failed
|
||||
return SQFloat(0.0);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Object Column::GetLong() const
|
||||
{
|
||||
// Validate the handle and index
|
||||
if (!RowAvailable())
|
||||
return Object(); // Request failed
|
||||
// Obtain the initial stack size
|
||||
const Int32 top = sq_gettop(_SqVM);
|
||||
// Push a long integer instance with the requested value on the stack
|
||||
_SqMod->PushSLongObject(_SqVM, sqlite3_column_int64(m_Stmt, m_Index));
|
||||
// Obtain the object from the stack
|
||||
Var< Object > inst(_SqVM, -1);
|
||||
// Remove an pushed values (if any) to restore the stack
|
||||
sq_pop(_SqVM, sq_gettop(_SqVM) - top);
|
||||
// Return the long integer instance
|
||||
return inst.value;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Object Column::GetString() const
|
||||
{
|
||||
// Validate the handle and index
|
||||
if (RowAvailable())
|
||||
return Object(); // Request failed
|
||||
// Obtain the initial stack size
|
||||
const Int32 top = sq_gettop(_SqVM);
|
||||
// Push the column text on the stack
|
||||
sq_pushstring(_SqVM, (CSStr)sqlite3_column_text(m_Stmt, m_Index),
|
||||
sqlite3_column_bytes(m_Stmt, m_Index));
|
||||
// Obtain the object from the stack
|
||||
Var< Object > inst(_SqVM, -1);
|
||||
// Remove an pushed values (if any) to restore the stack
|
||||
sq_pop(_SqVM, sq_gettop(_SqVM) - top);
|
||||
// Return the long integer instance
|
||||
return inst.value;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool Column::GetBoolean() const
|
||||
{
|
||||
// Validate the handle and index
|
||||
if (RowAvailable())
|
||||
return sqlite3_column_int(m_Stmt, m_Index) > 0;
|
||||
// Request failed
|
||||
return false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Object Column::GetBlob() const
|
||||
{
|
||||
// Validate the handle and index
|
||||
if (RowAvailable())
|
||||
return Object(); // Request failed
|
||||
// Obtain the initial stack size
|
||||
const Int32 top = sq_gettop(_SqVM);
|
||||
// Obtain the size of the data
|
||||
const Int32 sz = sqlite3_column_bytes(m_Stmt, m_Index);
|
||||
// Allocate a blob of the same size
|
||||
SQUserPointer p = sqstd_createblob(_SqVM, sz);
|
||||
// Obtain a pointer to the data
|
||||
const void * b = sqlite3_column_blob(m_Stmt, m_Index);
|
||||
// Could the memory blob be allocated?
|
||||
if (!p)
|
||||
{
|
||||
_SqMod->SqThrow("Unable to allocate space for column blob value");
|
||||
// Request failed
|
||||
return Object();
|
||||
}
|
||||
// Is there any data to read?
|
||||
else if (!b)
|
||||
{
|
||||
// Pop the memory blob from the stack
|
||||
sq_pop(_SqVM, sq_gettop(_SqVM) - top);
|
||||
// Now throw the error
|
||||
_SqMod->SqThrow("Unable to read data from column blob value");
|
||||
// Request failed
|
||||
return Object();
|
||||
}
|
||||
// Copy the data into the memory blob
|
||||
else
|
||||
memcpy(p, b, sz);
|
||||
// Obtain the object from the stack
|
||||
Var< Object > inst(_SqVM, -1);
|
||||
// Remove an pushed values (if any) to restore the stack
|
||||
sq_pop(_SqVM, sq_gettop(_SqVM) - top);
|
||||
// Return the long integer instance
|
||||
return inst.value;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQChar Column::GetChar() const
|
||||
{
|
||||
// Validate the handle and index
|
||||
if (RowAvailable())
|
||||
return (SQChar)sqlite3_column_int(m_Stmt, m_Index);
|
||||
// Request failed
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool Column::IsNull() const
|
||||
{
|
||||
// Can we make the request?
|
||||
if (Validate())
|
||||
return (sqlite3_column_type(m_Stmt, m_Index) == SQLITE_NULL);
|
||||
// Request failed
|
||||
return true;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
CSStr Column::GetName() const
|
||||
{
|
||||
// Can we make the request?
|
||||
if (Validate())
|
||||
return sqlite3_column_name(m_Stmt, m_Index);
|
||||
// Request failed
|
||||
return _SC("");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
CSStr Column::GetOriginName() const
|
||||
{
|
||||
#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
||||
// Can we make the request?
|
||||
if (Validate())
|
||||
return sqlite3_column_origin_name(m_Stmt, m_Index);
|
||||
#else
|
||||
_SqMod->SqThrow("The module was compiled without this feature");
|
||||
#endif
|
||||
// Request failed
|
||||
return _SC("");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Int32 Column::GetType() const
|
||||
{
|
||||
// Can we make the request?
|
||||
if (Validate())
|
||||
return sqlite3_column_type(m_Stmt, m_Index);
|
||||
// Request failed
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Int32 Column::GetBytes() const
|
||||
{
|
||||
// Can we make the request?
|
||||
if (Validate())
|
||||
return sqlite3_column_bytes(m_Stmt, m_Index);
|
||||
// Request failed
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
} // Namespace:: SqMod
|
245
modules/sqlite/Column.hpp
Normal file
245
modules/sqlite/Column.hpp
Normal file
@ -0,0 +1,245 @@
|
||||
#ifndef _SQSQLITE_COLUMN_HPP_
|
||||
#define _SQSQLITE_COLUMN_HPP_
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Common.hpp"
|
||||
#include "SqAPI.h"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Helper class used to manage statement columns.
|
||||
*/
|
||||
class Column
|
||||
{
|
||||
// --------------------------------------------------------------------------------------------
|
||||
friend class Statement;
|
||||
|
||||
private:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
Int32 m_Index; // The index of the managed column.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
StmtHnd m_Stmt; // The statement where the column exist.
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Validate the statement reference and index, and throw an error if they're invalid.
|
||||
*/
|
||||
bool Validate() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Validate the statement reference, index and row, and throw an error if they're invalid.
|
||||
*/
|
||||
bool RowAvailable() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Base constructor.
|
||||
*/
|
||||
Column(const StmtHnd & stmt, Int32 idx)
|
||||
: m_Index(idx), m_Stmt(stmt)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Default constructor (null).
|
||||
*/
|
||||
Column()
|
||||
: m_Index(-1), m_Stmt()
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor.
|
||||
*/
|
||||
Column(const Column & o)
|
||||
: m_Index(o.m_Index), m_Stmt(o.m_Stmt)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Destructor.
|
||||
*/
|
||||
~Column()
|
||||
{
|
||||
/* Let the reference manager destroy the statement when necessary. */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy assignment operator.
|
||||
*/
|
||||
Column operator = (const Column & o)
|
||||
{
|
||||
m_Index = o.m_Index;
|
||||
m_Stmt = o.m_Stmt;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Perform an equality comparison between two connection handles.
|
||||
*/
|
||||
bool operator == (const Column & o) const
|
||||
{
|
||||
return (m_Index == o.m_Index);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Perform an inequality comparison between two connection handles.
|
||||
*/
|
||||
bool operator != (const Column & o) const
|
||||
{
|
||||
return (m_Index != o.m_Index);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Implicit conversion to boolean for use in boolean operations.
|
||||
*/
|
||||
operator bool () const
|
||||
{
|
||||
return m_Index >= 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to compare two instances of this type.
|
||||
*/
|
||||
Int32 Cmp(const Column & o) const
|
||||
{
|
||||
if (m_Stmt == o.m_Stmt)
|
||||
return 0;
|
||||
else if (m_Stmt.HndPtr() > o.m_Stmt.HndPtr())
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to convert an instance of this type to a string.
|
||||
*/
|
||||
CSStr ToString() const
|
||||
{
|
||||
return FmtStr(_SC("%d"), m_Index);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to retrieve the name from instances of this type.
|
||||
*/
|
||||
static SQInteger Typename(HSQUIRRELVM vm);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* See whether this statement is valid.
|
||||
*/
|
||||
bool IsValid() const
|
||||
{
|
||||
return (bool)m_Stmt; // An invalid statement means an invalid column
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Return the number of active references to this statement handle.
|
||||
*/
|
||||
Uint32 GetRefCount() const
|
||||
{
|
||||
return m_Stmt.Count();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the associated column index.
|
||||
*/
|
||||
Int32 GetIndex() const
|
||||
{
|
||||
return m_Index;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the associated database statement.
|
||||
*/
|
||||
Statement GetStatement() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the associated database connection.
|
||||
*/
|
||||
Connection GetConnection() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Release the reference to the associated database statement and index.
|
||||
*/
|
||||
void Release()
|
||||
{
|
||||
m_Stmt = StmtHnd();
|
||||
m_Index = -1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value inside the associated column cel as a 32bit integer.
|
||||
*/
|
||||
Int32 GetNumber() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value inside the associated column cel as a native script integer.
|
||||
*/
|
||||
SQInteger GetInteger() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value inside the associated column cel as a native script floating point.
|
||||
*/
|
||||
SQFloat GetFloat() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value inside the associated column cel as a long integer.
|
||||
*/
|
||||
Object GetLong() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value inside the associated column cel as a string.
|
||||
*/
|
||||
Object GetString() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value inside the associated column cel as a boolean.
|
||||
*/
|
||||
bool GetBoolean() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value inside the associated column cel as a memory blob.
|
||||
*/
|
||||
Object GetBlob() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value inside the associated column cel as a character.
|
||||
*/
|
||||
SQChar GetChar() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Check whether the associated column is null.
|
||||
*/
|
||||
bool IsNull() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the name of the associated column index.
|
||||
*/
|
||||
CSStr GetName() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the column origin name if the library was compiled with such feature.
|
||||
*/
|
||||
CSStr GetOriginName() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the type identifier of the associated column index.
|
||||
*/
|
||||
Int32 GetType() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the size in bytes of the associated column index.
|
||||
*/
|
||||
Int32 GetBytes() const;
|
||||
};
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
#endif // _SQSQLITE_COLUMN_HPP_
|
427
modules/sqlite/Common.cpp
Normal file
427
modules/sqlite/Common.cpp
Normal file
@ -0,0 +1,427 @@
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Common.hpp"
|
||||
#include "Module.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <sqrat.h>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static SQChar g_Buffer[4096]; // Common buffer to reduce memory allocations.
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
CSStr FmtStr(CSStr str, ...)
|
||||
{
|
||||
// Initialize the argument list
|
||||
va_list args;
|
||||
va_start (args, str);
|
||||
// Write the requested contents
|
||||
if (snprintf(g_Buffer, sizeof(g_Buffer), str, args) < 0)
|
||||
g_Buffer[0] = 0; /* make sure the string is terminated */
|
||||
// Release the argument list
|
||||
va_end(args);
|
||||
// Return the data from the buffer
|
||||
return g_Buffer;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
CSStr QFmtStr(CSStr str, ...)
|
||||
{
|
||||
// Initialize the argument list
|
||||
va_list args;
|
||||
va_start (args, str);
|
||||
// Write the requested contents
|
||||
sqlite3_vsnprintf(sizeof(g_Buffer), g_Buffer, str, args);
|
||||
// Release the argument list
|
||||
va_end(args);
|
||||
// Return the data from the buffer
|
||||
return g_Buffer;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool IsQueryEmpty(CSStr str)
|
||||
{
|
||||
// Is the pointer valid?
|
||||
if (!str)
|
||||
return true;
|
||||
// Currently processed character
|
||||
SQChar c = 0;
|
||||
// See if the query contains any alpha numeric characters
|
||||
while ((c = *str) != 0)
|
||||
{
|
||||
if (isalnum(c) != 0)
|
||||
return false;
|
||||
++str;
|
||||
}
|
||||
// At this point we consider the query empty
|
||||
return true;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
ConnHnd::Handle::~Handle()
|
||||
{
|
||||
// Is there anything to close?
|
||||
if (!mPtr)
|
||||
return; // Nothing to close
|
||||
// Are we dealing with a memory leak? Technically shouldn't reach this situation!
|
||||
else if (mRef != 0)
|
||||
// Should we deal with undefined behavior instead? How bad is one connection left open?
|
||||
_SqMod->LogErr("SQLite connection is still referenced.");
|
||||
else
|
||||
{
|
||||
// NOTE: Should we call sqlite3_interrupt(...) before closing?
|
||||
Object env;
|
||||
Function func;
|
||||
// Flush remaining queries in the queue and ignore the result
|
||||
Flush(mQueue.size(), env, func);
|
||||
// Attempt to close the database
|
||||
if ((sqlite3_close(mPtr)) != SQLITE_OK)
|
||||
_SqMod->LogErr("Unable to close SQLite connection [%s]", sqlite3_errmsg(mPtr));
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ConnHnd::Handle::Create(CSStr name, Int32 flags, CSStr vfs)
|
||||
{
|
||||
// Make sure a previous connection doesn't exist
|
||||
if (mPtr)
|
||||
{
|
||||
_SqMod->SqThrow("Unable to connect to database. Database already connected");
|
||||
// Unable to proceed
|
||||
return;
|
||||
}
|
||||
// Make sure the name is valid
|
||||
else if (!name || strlen(name) <= 0)
|
||||
{
|
||||
_SqMod->SqThrow("Unable to connect to database. The name is invalid");
|
||||
// Unable to proceed
|
||||
return;
|
||||
}
|
||||
// Attempt to create the database connection
|
||||
else if ((mStatus = sqlite3_open_v2(name, &mPtr, flags, vfs)) != SQLITE_OK)
|
||||
{
|
||||
// Must be destroyed regardless of result
|
||||
sqlite3_close(mPtr);
|
||||
// Explicitly make sure it's null
|
||||
mPtr = NULL;
|
||||
// Now its safe to throw the error
|
||||
_SqMod->SqThrow("Unable to connect to database [%s]", sqlite3_errstr(mStatus));
|
||||
// Unable to proceed
|
||||
return;
|
||||
}
|
||||
// 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.compare(_SC(":memory:")) == 0);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Int32 ConnHnd::Handle::Flush(Uint32 num, Object & env, Function & func)
|
||||
{
|
||||
// Do we even have a valid connection?
|
||||
if (!mPtr)
|
||||
return -1;
|
||||
// Is there anything to flush?
|
||||
else if (!num || mQueue.empty())
|
||||
return 0;
|
||||
// Can we even flush that many?
|
||||
else if (num > mQueue.size())
|
||||
num = mQueue.size();
|
||||
// Generate the function that should be called upon error
|
||||
Function callback = Function(env.GetVM(), env.GetObject(), func.GetFunc());
|
||||
// Obtain iterators to the range of queries that should be flushed
|
||||
QueryList::iterator itr = mQueue.begin();
|
||||
QueryList::iterator end = mQueue.begin() + num;
|
||||
// Attempt to begin the flush transaction
|
||||
if ((mStatus = sqlite3_exec(mPtr, "BEGIN", NULL, NULL, NULL)) != SQLITE_OK)
|
||||
{
|
||||
_SqMod->SqThrow("Unable to begin transaction [%s]", sqlite3_errmsg(mPtr));
|
||||
// Unable to proceed
|
||||
return -1;
|
||||
}
|
||||
// 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(), NULL, NULL, NULL)) == SQLITE_OK)
|
||||
continue;
|
||||
// Do we have to execute any callback to resolve our issue?
|
||||
else if (!callback.IsNull())
|
||||
{
|
||||
// Ask the callback whether the query processing should end here
|
||||
SharedPtr< bool > ret = callback.Evaluate< bool, Int32, CSStr >(mStatus, itr->c_str());
|
||||
// Should we break here?
|
||||
if (!!ret && (*ret == false))
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 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", NULL, NULL, NULL)) == SQLITE_OK)
|
||||
return sqlite3_changes(mPtr);
|
||||
// Attempt to roll back erroneous changes
|
||||
else if ((mStatus = sqlite3_exec(mPtr, "ROLLBACK", NULL, NULL, NULL)) != SQLITE_OK)
|
||||
_SqMod->SqThrow("Unable to rollback transaction [%s]", sqlite3_errmsg(mPtr));
|
||||
// The transaction failed somehow but we managed to rollback
|
||||
else
|
||||
_SqMod->SqThrow("Unable to commit transaction because [%s]", sqlite3_errmsg(mPtr));
|
||||
// Operation failed
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
StmtHnd::Handle::~Handle()
|
||||
{
|
||||
// Is there anything to finalize?
|
||||
if (!mPtr)
|
||||
return; // Nothing to finalize
|
||||
// Are we dealing with a memory leak? Technically shouldn't reach this situation!
|
||||
else if (mRef != 0)
|
||||
// Should we deal with undefined behavior instead? How bad is one statement left alive?
|
||||
_SqMod->LogErr("SQLite statement is still referenced.");
|
||||
else
|
||||
{
|
||||
// Attempt to finalize the statement
|
||||
if ((sqlite3_finalize(mPtr)) != SQLITE_OK)
|
||||
_SqMod->LogErr("Unable to finalize SQLite statement [%s]", mConn.ErrMsg());
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void StmtHnd::Handle::Create(CSStr query)
|
||||
{
|
||||
// Make sure a previous statement doesn't exist
|
||||
if (mPtr)
|
||||
{
|
||||
_SqMod->SqThrow("Unable to prepare statement. Statement already prepared");
|
||||
// Unable to proceed
|
||||
return;
|
||||
}
|
||||
// Is the specified database connection is valid?
|
||||
else if (!mConn)
|
||||
{
|
||||
_SqMod->SqThrow("Unable to prepare statement. Invalid connection handle");
|
||||
// Unable to proceed
|
||||
return;
|
||||
}
|
||||
// Save the query string and therefore multiple strlen(...) calls
|
||||
mQuery.assign(query ? query : _SC(""));
|
||||
// Is the specified query string we just saved, valid?
|
||||
if (mQuery.empty())
|
||||
_SqMod->SqThrow("Unable to prepare statement. Invalid query string");
|
||||
// Attempt to prepare a statement with the specified query string
|
||||
else if ((mStatus = sqlite3_prepare_v2(mConn, mQuery.c_str(), (Int32)mQuery.size(),
|
||||
&mPtr, NULL)) != SQLITE_OK)
|
||||
{
|
||||
// Clear the query string since it failed
|
||||
mQuery.clear();
|
||||
// Now it's safe to throw the error
|
||||
_SqMod->SqThrow("Unable to prepare statement [%s]", mConn.ErrMsg());
|
||||
// Explicitly make sure the handle is null
|
||||
mPtr = NULL;
|
||||
}
|
||||
else
|
||||
// Obtain the number of available columns
|
||||
mColumns = sqlite3_column_count(mPtr);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Int32 StmtHnd::Handle::GetColumnIndex(CSStr name)
|
||||
{
|
||||
// Validate the handle
|
||||
if (!mPtr)
|
||||
_SqMod->SqThrow("Invalid SQLite statement");
|
||||
// Are the names cached?
|
||||
else if (mIndexes.empty())
|
||||
{
|
||||
for (Int32 i = 0; i < mColumns; ++i)
|
||||
{
|
||||
// Get the column name at the current index
|
||||
CSStr name = (CSStr)sqlite3_column_name(mPtr, i);
|
||||
// Validate the name
|
||||
if (!name)
|
||||
_SqMod->SqThrow("Unable to retrieve column name for index (%d)", i);
|
||||
// Save it to guarantee the same lifetime as this instance
|
||||
else
|
||||
mIndexes[name] = i;
|
||||
}
|
||||
}
|
||||
// Attempt to find the specified column
|
||||
const Indexes::iterator itr = mIndexes.find(name);
|
||||
// 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;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SetSoftHeapLimit(Int32 limit)
|
||||
{
|
||||
sqlite3_soft_heap_limit(limit);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Int32 ReleaseMemory(Int32 bytes)
|
||||
{
|
||||
return sqlite3_release_memory(bytes);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Object GetMemoryUsage()
|
||||
{
|
||||
// Obtain the initial stack size
|
||||
const Int32 top = sq_gettop(_SqVM);
|
||||
// Push a long integer instance with the requested value on the stack
|
||||
_SqMod->PushSLongObject(_SqVM, sqlite3_memory_used());
|
||||
// Obtain the object from the stack
|
||||
Var< Object > inst(_SqVM, -1);
|
||||
// Remove an pushed values (if any) to restore the stack
|
||||
sq_pop(_SqVM, sq_gettop(_SqVM) - top);
|
||||
// Return the long integer instance
|
||||
return inst.value;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Object GetMemoryHighwaterMark(bool reset)
|
||||
{
|
||||
// Obtain the initial stack size
|
||||
const Int32 top = sq_gettop(_SqVM);
|
||||
// Push a long integer instance with the requested value on the stack
|
||||
_SqMod->PushSLongObject(_SqVM, sqlite3_memory_highwater(reset));
|
||||
// Obtain the object from the stack
|
||||
Var< Object > inst(_SqVM, -1);
|
||||
// Remove an pushed values (if any) to restore the stack
|
||||
sq_pop(_SqVM, sq_gettop(_SqVM) - top);
|
||||
// Return the long integer instance
|
||||
return inst.value;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
CSStr EscapeString(CSStr str)
|
||||
{
|
||||
// Is there even a string to escape?
|
||||
if (!str)
|
||||
return _SC(""); // Default to empty string
|
||||
// Attempt to escape the specified string
|
||||
sqlite3_snprintf(sizeof(g_Buffer), g_Buffer, "%q", str);
|
||||
// Return the resulted string
|
||||
return g_Buffer;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
CCStr EscapeStringEx(SQChar spec, CCStr str)
|
||||
{
|
||||
// Utility that allows changing the format specifier temporarily
|
||||
static SQChar fs[] = _SC("%q");
|
||||
// Validate the specified format specifier
|
||||
if (spec != 'q' && spec != 'Q' && spec != 'w' && spec != 's')
|
||||
{
|
||||
_SqMod->SqThrow("Unknown format specifier: %c", spec);
|
||||
// Default to empty string
|
||||
return _SC("");
|
||||
}
|
||||
// Is there even a string to escape?
|
||||
else if (!str)
|
||||
return _SC(""); // Default to empty string
|
||||
// Apply the format specifier
|
||||
fs[1] = spec;
|
||||
// Attempt to escape the specified string
|
||||
sqlite3_snprintf(sizeof(g_Buffer), g_Buffer, fs, str);
|
||||
// Restore the format specifier
|
||||
fs[1] = '1';
|
||||
// Return the resulted string
|
||||
return g_Buffer;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
CCStr ArrayToQueryColumns(Array & arr)
|
||||
{
|
||||
// Do we even have any elements to process?
|
||||
if (arr.Length() <= 0)
|
||||
return _SC(""); // Default to empty string
|
||||
// Allocate a vector with the required amount of column names
|
||||
std::vector< String > values(arr.Length());
|
||||
// Attempt to extract the array elements as strings
|
||||
arr.GetArray< String >(&values[0], values.size());
|
||||
// Used to know the position of the next column name
|
||||
Uint32 offset = 0;
|
||||
// Obtain the start of the array
|
||||
std::vector< String >::iterator itr = values.begin();
|
||||
// Process all elements within range
|
||||
for (; itr != values.end() && offset < sizeof(g_Buffer); ++itr)
|
||||
{
|
||||
// Is the name valid?
|
||||
if (itr->empty())
|
||||
{
|
||||
_SqMod->SqThrow("Invalid column name");
|
||||
// Default to empty string
|
||||
return _SC("");
|
||||
}
|
||||
// Attempt to append the column name to the buffer
|
||||
sqlite3_snprintf(sizeof(g_Buffer) - offset, g_Buffer + 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)
|
||||
g_Buffer[offset-2] = 0;
|
||||
else
|
||||
g_Buffer[0] = 0;
|
||||
// Return the resulted string
|
||||
return g_Buffer;
|
||||
}
|
||||
|
||||
CCStr TableToQueryColumns(Table & tbl)
|
||||
{
|
||||
// Used to know the position of the next column name
|
||||
Uint32 offset = 0;
|
||||
// Used to obtain the column name temporarily
|
||||
String name;
|
||||
// Obtain the start of the table
|
||||
Table::iterator itr;
|
||||
// Process all elements within range
|
||||
while (tbl.Next(itr))
|
||||
{
|
||||
// Use the element key as the column name
|
||||
name.assign(itr.getName());
|
||||
// Is the name valid?
|
||||
if (name.empty())
|
||||
{
|
||||
_SqMod->SqThrow("Invalid column name");
|
||||
// Default to empty string
|
||||
return _SC("");
|
||||
}
|
||||
// Attempt to append the column name to the buffer
|
||||
sqlite3_snprintf(sizeof(g_Buffer) - offset, g_Buffer + offset, "[%q], ", name.c_str());
|
||||
// Add the column name size to the offset
|
||||
offset += name.size();
|
||||
// Also include the comma and space in the offset
|
||||
offset += 2;
|
||||
}
|
||||
// Trim the last coma and space
|
||||
if (offset >= 2)
|
||||
g_Buffer[offset-2] = 0;
|
||||
else
|
||||
g_Buffer[0] = 0;
|
||||
// Return the resulted string
|
||||
return g_Buffer;
|
||||
}
|
||||
|
||||
} // Namespace:: SqMod
|
770
modules/sqlite/Common.hpp
Normal file
770
modules/sqlite/Common.hpp
Normal file
@ -0,0 +1,770 @@
|
||||
#ifndef _SQSQLITE_COMMON_HPP_
|
||||
#define _SQSQLITE_COMMON_HPP_
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "ModBase.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <assert.h>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <sqlite3.h>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Forward declarations.
|
||||
*/
|
||||
class Connection;
|
||||
class Statement;
|
||||
class Column;
|
||||
class Transaction;
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* SOFTWARE INFORMATION
|
||||
*/
|
||||
#define SQSQLITE_NAME "Squirrel SQLite Module"
|
||||
#define SQSQLITE_AUTHOR "Sandu Liviu Catalin (S.L.C)"
|
||||
#define SQSQLITE_COPYRIGHT "Copyright (C) 2016 Sandu Liviu Catalin"
|
||||
#define SQSQLITE_HOST_NAME "SqModSQLiteHost"
|
||||
#define SQSQLITE_VERSION 001
|
||||
#define SQSQLITE_VERSION_STR "0.0.1"
|
||||
#define SQSQLITE_VERSION_MAJOR 0
|
||||
#define SQSQLITE_VERSION_MINOR 0
|
||||
#define SQSQLITE_VERSION_PATCH 1
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Generate a formatted string.
|
||||
*/
|
||||
CSStr FmtStr(CSStr str, ...);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Generate a formatted query.
|
||||
*/
|
||||
CSStr QFmtStr(CSStr str, ...);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Tests if a certain query string is empty.
|
||||
*/
|
||||
bool IsQueryEmpty(CSStr str);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Manages a reference counted database connection handle.
|
||||
*/
|
||||
class ConnHnd
|
||||
{
|
||||
// --------------------------------------------------------------------------------------------
|
||||
friend class Connection;
|
||||
friend class Statement;
|
||||
|
||||
public:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef sqlite3 Type; // The managed type.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef Type* Pointer; // Pointer to the managed type.
|
||||
typedef const Type* ConstPtr; // Constant pointer to the managed type.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef Type& Reference; // Reference to the managed type.
|
||||
typedef const Type& ConstRef; // Constant reference to the managed type.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef unsigned int Counter; // Reference counter type.
|
||||
|
||||
protected:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef std::vector< String > QueryList; // Container used to queue queries.
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* The structure that holds the data associated with a certain connection.
|
||||
*/
|
||||
struct Handle
|
||||
{
|
||||
// --------------------------------------------------------------------------------------------
|
||||
Pointer mPtr; // The connection handle resource.
|
||||
Counter mRef; // Reference count to the managed handle.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
Int32 mStatus; // The last status code of this connection handle.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
QueryList mQueue; // A queue of queries to be executed in groups.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
Int32 mFlags; // The flags used to create the database connection handle.
|
||||
String mName; // The specified name to be used as the database file.
|
||||
String mVFS; // The specified virtual file system.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
bool mMemory; // Whether the database exists in memory and not disk.
|
||||
bool mTrace; // Whether tracing was activated on the database.
|
||||
bool mProfile; // Whether profiling was activated on the database.
|
||||
|
||||
/* ----------------------------------------------------------------------------------------
|
||||
* Base constructor.
|
||||
*/
|
||||
Handle(Counter counter)
|
||||
: mPtr(NULL)
|
||||
, mRef(counter)
|
||||
, mStatus(SQLITE_OK)
|
||||
, mQueue()
|
||||
, mFlags(0)
|
||||
, mName()
|
||||
, mVFS()
|
||||
, mMemory(false)
|
||||
, mTrace(false)
|
||||
, mProfile(false)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Destructor.
|
||||
*/
|
||||
~Handle();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Create the database connection resource.
|
||||
*/
|
||||
void Create(CSStr name, Int32 flags, CSStr vfs);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Execute a specific amount of queries from the queue.
|
||||
*/
|
||||
Int32 Flush(Uint32 num, Object & env, Function & func);
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
Handle* m_Hnd;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Grab a strong reference to a connection handle.
|
||||
*/
|
||||
void Grab()
|
||||
{
|
||||
if (m_Hnd)
|
||||
++(m_Hnd->mRef);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Drop a strong reference to a connection handle.
|
||||
*/
|
||||
void Drop()
|
||||
{
|
||||
if (m_Hnd && --(m_Hnd->mRef) == 0)
|
||||
delete m_Hnd; // Let the destructor take care of cleaning up (if necessary)
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Base constructor.
|
||||
*/
|
||||
ConnHnd(CSStr name)
|
||||
: m_Hnd(name ? new Handle(1) : NULL)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Default constructor (null).
|
||||
*/
|
||||
ConnHnd()
|
||||
: m_Hnd(NULL)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor.
|
||||
*/
|
||||
ConnHnd(const ConnHnd & o)
|
||||
: m_Hnd(o.m_Hnd)
|
||||
|
||||
{
|
||||
Grab();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Destructor.
|
||||
*/
|
||||
~ConnHnd()
|
||||
{
|
||||
Drop();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy assignment operator.
|
||||
*/
|
||||
ConnHnd & operator = (const ConnHnd & o)
|
||||
{
|
||||
if (m_Hnd != o.m_Hnd)
|
||||
{
|
||||
Drop();
|
||||
m_Hnd = o.m_Hnd;
|
||||
Grab();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Status assignment operator.
|
||||
*/
|
||||
ConnHnd & operator = (Int32 status)
|
||||
{
|
||||
if (m_Hnd)
|
||||
m_Hnd->mStatus = status;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Perform an equality comparison between two connection handles.
|
||||
*/
|
||||
bool operator == (const ConnHnd & o) const
|
||||
{
|
||||
return (m_Hnd == o.m_Hnd);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Perform an inequality comparison between two connection handles.
|
||||
*/
|
||||
bool operator != (const ConnHnd & o) const
|
||||
{
|
||||
return (m_Hnd != o.m_Hnd);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Perform an equality comparison with an integer value status.
|
||||
*/
|
||||
bool operator == (Int32 status) const
|
||||
{
|
||||
if (m_Hnd)
|
||||
return (m_Hnd->mStatus == status);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Perform an inequality comparison with an integer value status.
|
||||
*/
|
||||
bool operator != (Int32 status) const
|
||||
{
|
||||
if (m_Hnd)
|
||||
return (m_Hnd->mStatus != status);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Implicit conversion to boolean for use in boolean operations.
|
||||
*/
|
||||
operator bool () const
|
||||
{
|
||||
return !m_Hnd || !(m_Hnd->mPtr);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Implicit conversion to the managed instance.
|
||||
*/
|
||||
operator Pointer ()
|
||||
{
|
||||
return m_Hnd ? m_Hnd->mPtr : NULL;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Implicit conversion to the managed instance.
|
||||
*/
|
||||
operator Pointer () const
|
||||
{
|
||||
return m_Hnd ? m_Hnd->mPtr : NULL;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Implicit conversion to the managed instance.
|
||||
*/
|
||||
operator Reference ()
|
||||
{
|
||||
assert(m_Hnd && m_Hnd->mPtr);
|
||||
return *(m_Hnd->mPtr);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Implicit conversion to the managed instance.
|
||||
*/
|
||||
operator ConstRef () const
|
||||
{
|
||||
assert(m_Hnd && m_Hnd->mPtr);
|
||||
return *(m_Hnd->mPtr);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Member operator for dereferencing the managed pointer.
|
||||
*/
|
||||
Handle * operator -> () const
|
||||
{
|
||||
assert(m_Ptr);
|
||||
return m_Hnd;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Indirection operator for obtaining a reference of the managed pointer.
|
||||
*/
|
||||
Handle & operator * () const
|
||||
{
|
||||
assert(m_Ptr);
|
||||
return *m_Hnd;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the raw handle structure pointer.
|
||||
*/
|
||||
Handle * HndPtr()
|
||||
{
|
||||
return m_Hnd;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the raw handle structure pointer.
|
||||
*/
|
||||
Handle * HndPtr() const
|
||||
{
|
||||
return m_Hnd;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the number of active references to the managed instance.
|
||||
*/
|
||||
Counter Count() const
|
||||
{
|
||||
assert(m_Ptr);
|
||||
return m_Hnd ? m_Hnd->mRef : 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the message of the last received error code.
|
||||
*/
|
||||
CCStr ErrStr() const
|
||||
{
|
||||
assert(m_Ptr); // SQLite does it's null pointer validations internally
|
||||
return sqlite3_errstr(sqlite3_errcode(m_Hnd->mPtr));
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Return the last error message associated with this database connection.
|
||||
*/
|
||||
CCStr ErrMsg() const
|
||||
{
|
||||
assert(m_Ptr); // SQLite does it's null pointer validations internally
|
||||
return sqlite3_errmsg(m_Hnd->mPtr);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Return the numeric result code for the most recent failed API call (if any).
|
||||
*/
|
||||
Int32 ErrNo() const
|
||||
{
|
||||
assert(m_Ptr); // SQLite does it's null pointer validations internally
|
||||
return sqlite3_errcode(m_Hnd->mPtr);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Return the extended numeric result code for the most recent failed API call (if any).
|
||||
*/
|
||||
Int32 ExErrNo() const
|
||||
{
|
||||
assert(m_Ptr); // SQLite does it's null pointer validations internally
|
||||
return sqlite3_extended_errcode(m_Hnd->mPtr);
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Manages a reference counted database statement handle.
|
||||
*/
|
||||
class StmtHnd
|
||||
{
|
||||
// --------------------------------------------------------------------------------------------
|
||||
friend class Connection;
|
||||
friend class Statement;
|
||||
|
||||
public:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef sqlite3_stmt Type; // The managed type.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef Type* Pointer; // Pointer to the managed type.
|
||||
typedef const Type* ConstPtr; // Constant pointer to the managed type.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef Type& Reference; // Reference to the managed type.
|
||||
typedef const Type& ConstRef; // Constant reference to the managed type.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef unsigned int Counter; // Reference counter type.
|
||||
|
||||
protected:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef std::map< String, int > Indexes; // Container used to identify column indexes.
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* The structure that holds the data associated with a certain statement.
|
||||
*/
|
||||
struct Handle
|
||||
{
|
||||
// --------------------------------------------------------------------------------------------
|
||||
Pointer mPtr; // The statement handle resource.
|
||||
Counter mRef; // Reference count to the managed handle.
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
Int32 mStatus; // The last status code of this connection handle.
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
ConnHnd mConn; // The handle to the associated database connection.
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
String mQuery; // The query string used to create this statement.
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
Int32 mColumns; // The amount of columns available in this statement.
|
||||
Indexes mIndexes; // An associative container with column names and their index.
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
bool mGood; // True when a row has been fetched with step.
|
||||
bool mDone; // True when the last step had no more rows to fetch.
|
||||
|
||||
/* ----------------------------------------------------------------------------------------
|
||||
* Base constructor.
|
||||
*/
|
||||
Handle(const ConnHnd & conn, Counter counter)
|
||||
: mPtr(NULL)
|
||||
, mRef(counter)
|
||||
, mStatus(SQLITE_OK)
|
||||
, mConn(conn)
|
||||
, mQuery()
|
||||
, mColumns(0)
|
||||
, mIndexes()
|
||||
, mGood(false)
|
||||
, mDone(false)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Destructor.
|
||||
*/
|
||||
~Handle();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Create the database statement resource.
|
||||
*/
|
||||
void Create(CSStr query);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Check whether a specific index is in range.
|
||||
*/
|
||||
bool CheckIndex(Int32 idx) const
|
||||
{
|
||||
return (idx >= 0) && (idx < mColumns);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the column index associated with the specified name.
|
||||
*/
|
||||
Int32 GetColumnIndex(CSStr name);
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
Handle* m_Hnd;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Grab a strong reference to a statement handle.
|
||||
*/
|
||||
void Grab()
|
||||
{
|
||||
if (m_Hnd)
|
||||
++(m_Hnd->mRef);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Drop a strong reference to a statement handle.
|
||||
*/
|
||||
void Drop()
|
||||
{
|
||||
if (m_Hnd && --(m_Hnd->mRef) == 0)
|
||||
delete m_Hnd; // Let the destructor take care of cleaning up (if necessary)
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Base constructor.
|
||||
*/
|
||||
StmtHnd(const ConnHnd & db)
|
||||
: m_Hnd(new Handle(db, 1))
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Default constructor (null).
|
||||
*/
|
||||
StmtHnd()
|
||||
: m_Hnd(NULL)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor.
|
||||
*/
|
||||
StmtHnd(const StmtHnd & o)
|
||||
: m_Hnd(o.m_Hnd)
|
||||
|
||||
{
|
||||
Grab();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Destructor.
|
||||
*/
|
||||
~StmtHnd()
|
||||
{
|
||||
Drop();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy assignment operator.
|
||||
*/
|
||||
StmtHnd & operator = (const StmtHnd & o)
|
||||
{
|
||||
if (m_Hnd != o.m_Hnd)
|
||||
{
|
||||
Drop();
|
||||
m_Hnd = o.m_Hnd;
|
||||
Grab();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Status assignment operator.
|
||||
*/
|
||||
StmtHnd & operator = (Int32 status)
|
||||
{
|
||||
if (m_Hnd)
|
||||
m_Hnd->mStatus = status;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Perform an equality comparison between two statement handles.
|
||||
*/
|
||||
bool operator == (const StmtHnd & o) const
|
||||
{
|
||||
return (m_Hnd == o.m_Hnd);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Perform an inequality comparison between two statement handles.
|
||||
*/
|
||||
bool operator != (const StmtHnd & o) const
|
||||
{
|
||||
return (m_Hnd != o.m_Hnd);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Perform an equality comparison with an integer value status.
|
||||
*/
|
||||
bool operator == (Int32 status) const
|
||||
{
|
||||
if (m_Hnd)
|
||||
return (m_Hnd->mStatus == status);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Perform an inequality comparison with an integer value status.
|
||||
*/
|
||||
bool operator != (Int32 status) const
|
||||
{
|
||||
if (m_Hnd)
|
||||
return (m_Hnd->mStatus != status);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Implicit conversion to boolean for use in boolean operations.
|
||||
*/
|
||||
operator bool () const
|
||||
{
|
||||
return !m_Hnd || !(m_Hnd->mPtr);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Implicit conversion to the managed instance.
|
||||
*/
|
||||
operator Pointer ()
|
||||
{
|
||||
return m_Hnd ? m_Hnd->mPtr : NULL;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Implicit conversion to the managed instance.
|
||||
*/
|
||||
operator Pointer () const
|
||||
{
|
||||
return m_Hnd ? m_Hnd->mPtr : NULL;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Implicit conversion to the managed instance.
|
||||
*/
|
||||
operator Reference ()
|
||||
{
|
||||
assert(m_Hnd && m_Hnd->mPtr);
|
||||
return *(m_Hnd->mPtr);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Implicit conversion to the managed instance.
|
||||
*/
|
||||
operator ConstRef () const
|
||||
{
|
||||
assert(m_Hnd && m_Hnd->mPtr);
|
||||
return *(m_Hnd->mPtr);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Member operator for dereferencing the managed pointer.
|
||||
*/
|
||||
Handle * operator -> () const
|
||||
{
|
||||
assert(m_Ptr);
|
||||
return m_Hnd;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Indirection operator for obtaining a reference of the managed pointer.
|
||||
*/
|
||||
Handle & operator * () const
|
||||
{
|
||||
assert(m_Ptr);
|
||||
return *m_Hnd;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the raw handle structure pointer.
|
||||
*/
|
||||
Handle * HndPtr()
|
||||
{
|
||||
return m_Hnd;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the raw handle structure pointer.
|
||||
*/
|
||||
Handle * HndPtr() const
|
||||
{
|
||||
return m_Hnd;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the number of active references to the managed instance.
|
||||
*/
|
||||
Counter Count() const
|
||||
{
|
||||
assert(m_Ptr);
|
||||
return m_Hnd ? m_Hnd->mRef : 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the message of the last received error code.
|
||||
*/
|
||||
CCStr ErrStr() const
|
||||
{
|
||||
assert(m_Ptr); // SQLite does it's null pointer validations internally
|
||||
return m_Hnd->mConn.ErrStr();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Return the last error message associated with this database connection.
|
||||
*/
|
||||
CCStr ErrMsg() const
|
||||
{
|
||||
assert(m_Ptr); // SQLite does it's null pointer validations internally
|
||||
return m_Hnd->mConn.ErrMsg();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Return the numeric result code for the most recent failed API call (if any).
|
||||
*/
|
||||
Int32 ErrNo() const
|
||||
{
|
||||
assert(m_Ptr); // SQLite does it's null pointer validations internally
|
||||
return m_Hnd->mConn.ErrNo();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Return the extended numeric result code for the most recent failed API call (if any).
|
||||
*/
|
||||
Int32 ExErrNo() const
|
||||
{
|
||||
assert(m_Ptr); // SQLite does it's null pointer validations internally
|
||||
return m_Hnd->mConn.ExErrNo();
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
void SetSoftHeapLimit(Int32 limit);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
Int32 ReleaseMemory(Int32 bytes);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
Object GetMemoryUsage();
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
Object GetMemoryHighwaterMark(bool reset);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
CSStr EscapeString(CSStr str);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
CCStr EscapeStringEx(SQChar spec, CCStr str);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
CCStr ArrayToQueryColumns(Array & arr);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
*
|
||||
*/
|
||||
CCStr TableToQueryColumns(Table & tbl);
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
#endif // _SQSQLITE_COMMON_HPP_
|
575
modules/sqlite/Connection.cpp
Normal file
575
modules/sqlite/Connection.cpp
Normal file
@ -0,0 +1,575 @@
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Connection.hpp"
|
||||
#include "Statement.hpp"
|
||||
#include "Module.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <sqrat.h>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQInteger Connection::Typename(HSQUIRRELVM vm)
|
||||
{
|
||||
static SQChar name[] = _SC("SqSQLiteConnection");
|
||||
sq_pushstring(vm, name, sizeof(name));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool Connection::Validate() const
|
||||
{
|
||||
if (m_Handle)
|
||||
return true;
|
||||
// Invalid connection reference
|
||||
_SqMod->SqThrow("Invalid SQLite connection reference");
|
||||
return false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Connection::Connection()
|
||||
: m_Handle()
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Connection::Connection(CSStr name)
|
||||
: m_Handle(name)
|
||||
{
|
||||
if (m_Handle.m_Hnd)
|
||||
m_Handle->Create(name, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Connection::Connection(CSStr name, Int32 flags)
|
||||
: m_Handle(name)
|
||||
{
|
||||
if (m_Handle.m_Hnd)
|
||||
m_Handle->Create(name, flags, NULL);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Connection::Connection(CSStr name, Int32 flags, CSStr vfs)
|
||||
: m_Handle(name)
|
||||
{
|
||||
if (m_Handle.m_Hnd)
|
||||
m_Handle->Create(name, flags, vfs);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Int32 Connection::Exec(CSStr str)
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate() && (m_Handle = sqlite3_exec(m_Handle, str, NULL, NULL, NULL)) != SQLITE_OK)
|
||||
_SqMod->SqThrow("Unable to execute query [%s]", m_Handle.ErrMsg());
|
||||
// Return rows affected by this query
|
||||
else
|
||||
return sqlite3_changes(m_Handle);
|
||||
// Operation failed
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Statement Connection::Query(CSStr str) const
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate())
|
||||
return Statement(m_Handle, str);
|
||||
// Request failed
|
||||
return Statement();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Connection::Queue(CSStr str)
|
||||
{
|
||||
// Validate the handle
|
||||
if (!Validate())
|
||||
return; // Nothing to commit
|
||||
// Is there a query to commit?
|
||||
else if (IsQueryEmpty(str))
|
||||
_SqMod->SqThrow("No query to queue");
|
||||
// Add the specified string to the queue
|
||||
else
|
||||
m_Handle->mQueue.push_back(str);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool Connection::IsReadOnly() const
|
||||
{
|
||||
// Validate the handle
|
||||
if (!Validate())
|
||||
return false;
|
||||
// Request the desired information
|
||||
const int result = sqlite3_db_readonly(m_Handle, "main");
|
||||
// Verify the result
|
||||
if (result == -1)
|
||||
_SqMod->SqThrow("'main' is not the name of a database on connection");
|
||||
// Return the result
|
||||
else
|
||||
return (result != 1);
|
||||
// Inexistent is same as read-only
|
||||
return true;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool Connection::TableExists(CCStr name) const
|
||||
{
|
||||
// Validate the handle
|
||||
if (!Validate())
|
||||
return false;
|
||||
// Prepare a statement to inspect the master table
|
||||
Statement stmt(m_Handle, "SELECT count(*) FROM [sqlite_master] WHERE [type]='table' AND [name]=?");
|
||||
// Could the statement be created?
|
||||
if (stmt.IsValid())
|
||||
{
|
||||
// Bind the specified name onto the statement parameter
|
||||
stmt.IndexBindS(1, 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;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Object Connection::GetLastInsertRowID() const
|
||||
{
|
||||
// Validate the handle
|
||||
if (!Validate())
|
||||
return Object();
|
||||
// Obtain the initial stack size
|
||||
const Int32 top = sq_gettop(_SqVM);
|
||||
// Push a long integer instance with the requested value on the stack
|
||||
_SqMod->PushSLongObject(_SqVM, sqlite3_last_insert_rowid(m_Handle));
|
||||
// Obtain the object from the stack
|
||||
Var< Object > inst(_SqVM, -1);
|
||||
// Removed pushed values (if any)
|
||||
sq_pop(_SqVM, sq_gettop(_SqVM) - top);
|
||||
// Return the long integer instance
|
||||
return inst.value;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Connection::SetBusyTimeout(Int32 millis)
|
||||
{
|
||||
// Validate the handle and apply requested timeout
|
||||
if (Validate() && ((m_Handle = sqlite3_busy_timeout(m_Handle, millis)) != SQLITE_OK))
|
||||
_SqMod->SqThrow("Unable to set busy timeout [%s]", m_Handle.ErrMsg());
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Int32 Connection::GetInfo(Int32 operation, bool highwater, bool reset)
|
||||
{
|
||||
// Don't even bother to continue if there's no valid connection handle
|
||||
if (!Validate())
|
||||
return -1;
|
||||
// Where to retrieve the information
|
||||
Int32 cur_value;
|
||||
Int32 hiwtr_value;
|
||||
// Attempt to retrieve the specified information
|
||||
if((m_Handle = sqlite3_db_status(m_Handle, operation, &cur_value, &hiwtr_value, reset)) != SQLITE_OK)
|
||||
_SqMod->SqThrow("Unable to get runtime status information", m_Handle.ErrMsg());
|
||||
// Return what was requested
|
||||
else if (highwater)
|
||||
return hiwtr_value;
|
||||
else
|
||||
return cur_value;
|
||||
// Request failed
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Connection Connection::CopyToMemory()
|
||||
{
|
||||
// Validate the handle
|
||||
if (!Validate())
|
||||
return Connection();
|
||||
// Is the database already in memory?
|
||||
else if (m_Handle->mMemory)
|
||||
{
|
||||
_SqMod->SqThrow("The database is already in memory");
|
||||
// No reason to move it again
|
||||
return Connection();
|
||||
}
|
||||
// Destination database
|
||||
ConnHnd db(_SC(""));
|
||||
// Attempt to open an in-memory database
|
||||
db->Create(_SC(":memory:"), SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
|
||||
// See if the database could be opened
|
||||
if (!db)
|
||||
// The creation process already generated the error
|
||||
return Connection();
|
||||
// Clear any previous error (there shouldn't be any but just in case)
|
||||
Sqrat::Error::Clear(_SqVM);
|
||||
// Begin a transaction to replicate the schema of origin database
|
||||
if ((m_Handle = sqlite3_exec(m_Handle, "BEGIN", NULL, NULL, NULL)) != SQLITE_OK)
|
||||
_SqMod->SqThrow("Unable to begin schema replication [%s]", m_Handle.ErrMsg());
|
||||
// Attempt to replicate the schema of origin database to the in-memory one
|
||||
else if ((m_Handle = sqlite3_exec(m_Handle,
|
||||
"SELECT [sql] FROM [sqlite_master] WHERE [sql] NOT NULL AND [tbl_name] != 'sqlite_sequence'",
|
||||
&Connection::ProcessDDLRow, db->mPtr, NULL)) != SQLITE_OK)
|
||||
{
|
||||
// Did the error occurred from the DDL process function?
|
||||
if (Sqrat::Error::Occurred(_SqVM))
|
||||
{
|
||||
// Obtain the occurred message
|
||||
String msg(Sqrat::Error::Message(_SqVM));
|
||||
// Throw the resulted message but also include the point where it failed
|
||||
_SqMod->SqThrow("Unable to replicate schema [%s]", msg.c_str());
|
||||
}
|
||||
// Obtain the message from the connection handle if possible
|
||||
else
|
||||
_SqMod->SqThrow("Unable to replicate schema [%s]", m_Handle.ErrMsg());
|
||||
}
|
||||
// Attempt to commit the changes to the database schema replication
|
||||
else if ((m_Handle = sqlite3_exec(m_Handle, "COMMIT", NULL, NULL, NULL)) != SQLITE_OK)
|
||||
_SqMod->SqThrow("Unable to commit schema replication [%s]", m_Handle.ErrMsg());
|
||||
// Attempt to attach the origin database to the in-memory one
|
||||
else if ((db = sqlite3_exec(db, QFmtStr("ATTACH DATABASE '%q' as origin", m_Handle->mName.c_str()),
|
||||
NULL, NULL, NULL)) != SQLITE_OK)
|
||||
_SqMod->SqThrow("Unable to attach origin [%s]", db.ErrMsg());
|
||||
// Begin a transaction to replicate the data of origin database
|
||||
else if ((db = sqlite3_exec(db, "BEGIN", NULL, NULL, NULL) != SQLITE_OK))
|
||||
_SqMod->SqThrow("Unable to begin data replication [%s]", db.ErrMsg());
|
||||
// Attempt to replicate the data of origin database to the in-memory one
|
||||
else if ((db = sqlite3_exec(db, "SELECT [name] FROM [origin.sqlite_master] WHERE [type]='table'",
|
||||
&Connection::ProcessDMLRow, db->mPtr, NULL)) != SQLITE_OK)
|
||||
{
|
||||
// Did the error occurred from the DML process function?
|
||||
if (Sqrat::Error::Occurred(_SqVM))
|
||||
{
|
||||
// Obtain the occurred message
|
||||
String msg(Sqrat::Error::Message(_SqVM));
|
||||
// Throw the resulted message but also include the point where it failed
|
||||
_SqMod->SqThrow("Unable to replicate data [%s]", msg.c_str());
|
||||
}
|
||||
// Obtain the message from the connection handle if possible
|
||||
else
|
||||
_SqMod->SqThrow("Unable to replicate data [%s]", db.ErrMsg());
|
||||
}
|
||||
// Attempt to commit the changes to the database data replication
|
||||
else if ((db = sqlite3_exec(db, "COMMIT", NULL, NULL, NULL)) != SQLITE_OK)
|
||||
{
|
||||
_SqMod->SqThrow("Unable to commit data replication [%s]", db.ErrMsg());
|
||||
// Attempt to rollback changes from the data copy operation
|
||||
if ((db = sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL)) != SQLITE_OK)
|
||||
_SqMod->SqThrow("Unable to rollback data replication [%s]", db.ErrMsg());
|
||||
// Attempt to detach the disk origin from in-memory database
|
||||
else if ((db = sqlite3_exec(db, "DETACH DATABASE origin", NULL, NULL, NULL)) != SQLITE_OK)
|
||||
_SqMod->SqThrow("Unable to detach origin [%s]", db.ErrMsg());
|
||||
}
|
||||
// At this point everything went fine and the database instance should be returned
|
||||
else
|
||||
return Connection(db);
|
||||
// Failed to replicate the database
|
||||
return Connection();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Connection::CopyToDatabase(Connection & db)
|
||||
{
|
||||
// Make sure that we have two valid database handles
|
||||
if (Validate() && db.Validate())
|
||||
_SqMod->SqThrow("Invalid database connections");
|
||||
// Attempt to take the snapshot and return the result
|
||||
else
|
||||
TakeSnapshot(db.m_Handle);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Int32 Connection::Flush(Uint32 num)
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate())
|
||||
{
|
||||
// We need to supply a null callback
|
||||
Object env;
|
||||
Function func;
|
||||
// Attempt to flush the requested amount of queries
|
||||
return m_Handle->Flush(num, env, func);
|
||||
}
|
||||
// Request failed
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Int32 Connection::Flush(Uint32 num, Object & env, Function & func)
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate())
|
||||
// Attempt to flush the requested amount of queries
|
||||
return m_Handle->Flush(num, env, func);
|
||||
// Request failed
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Connection::TraceOutput(void * /*ptr*/, CCStr sql)
|
||||
{
|
||||
_SqMod->LogInf("SQLite Trace: %s", sql);
|
||||
}
|
||||
|
||||
void Connection::ProfileOutput(void * /*ptr*/, CCStr sql, sqlite3_uint64 time)
|
||||
{
|
||||
_SqMod->LogInf("SQLite profile (time: %llu): %s", time, sql);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
int Connection::ProcessDDLRow(void * db, int columns_count, char ** values, char ** /*columns*/)
|
||||
{
|
||||
// Make sure that exactly one column exists in the result
|
||||
if (columns_count != 1)
|
||||
_SqMod->SqThrow("Error occurred during DDL: columns != 1");
|
||||
// Execute the sql statement in values[0] in the received database connection
|
||||
else if (sqlite3_exec((sqlite3 *)db, values[0], NULL, NULL, NULL) != SQLITE_OK)
|
||||
_SqMod->SqThrow("Error occurred during DDL execution: %s", sqlite3_errmsg((sqlite3 *)db));
|
||||
else
|
||||
// Continue processing
|
||||
return 0;
|
||||
// Operation aborted
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Connection::ProcessDMLRow(void * db, int columns_count, char ** values, char ** /*columns*/)
|
||||
{
|
||||
// Make sure that exactly one column exists in the result
|
||||
if(columns_count != 1)
|
||||
{
|
||||
_SqMod->SqThrow("Error occurred during DML: columns != 1");
|
||||
// Operation aborted
|
||||
return -1;
|
||||
}
|
||||
// Generate the query string with the received values
|
||||
char * sql = sqlite3_mprintf("INSERT INTO main.%q SELECT * FROM origin.%q", values[0], values[0]);
|
||||
// Attempt to execute the generated query string on the received database connection
|
||||
if (sqlite3_exec((sqlite3 *)db, sql, NULL, NULL, NULL) != SQLITE_OK)
|
||||
_SqMod->SqThrow("Error occurred during DML execution: %s", sqlite3_errmsg((sqlite3 *)db));
|
||||
else
|
||||
{
|
||||
// Free the generated query string
|
||||
sqlite3_free(sql);
|
||||
// Continue processing
|
||||
return 0;
|
||||
}
|
||||
// Free the generated query string
|
||||
sqlite3_free(sql);
|
||||
// Operation aborted
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Connection::TakeSnapshot(ConnHnd & destination)
|
||||
{
|
||||
// Attempt to initialize a backup structure
|
||||
sqlite3_backup * backup = sqlite3_backup_init(destination, "main", m_Handle, "main");
|
||||
// See if the backup structure could be created
|
||||
if (!backup)
|
||||
_SqMod->SqThrow("Unable to initialize the backup structure [%s]", destination.ErrMsg());
|
||||
// -1 to copy the entire source database to the destination
|
||||
else if ((m_Handle = sqlite3_backup_step(backup, -1)) != SQLITE_DONE)
|
||||
_SqMod->SqThrow("Unable to copy source [%s]", m_Handle.ErrStr());
|
||||
// Clean up resources allocated by sqlite3_backup_init()
|
||||
if ((m_Handle = sqlite3_backup_finish(backup)) != SQLITE_OK)
|
||||
_SqMod->SqThrow("Unable to finalize backup [%s]", m_Handle.ErrStr());
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQInteger Connection::ExecF(HSQUIRRELVM vm)
|
||||
{
|
||||
const Int32 top = sq_gettop(vm);
|
||||
// Do we even have enough arguments?
|
||||
if (top <= 1)
|
||||
return sq_throwerror(vm, "Missing the query string");
|
||||
// Obtain the connection instance
|
||||
Var< Connection * > inst(vm, 1);
|
||||
// Do we have a valid connection instance?
|
||||
if (!inst.value)
|
||||
return sq_throwerror(vm, "Invalid connection instance");
|
||||
// Do we have a valid connection reference?
|
||||
else if (!inst.value->m_Handle)
|
||||
return sq_throwerror(vm, "Invalid SQLite connection reference");
|
||||
// Is the specified message value a string or something convertible to string?
|
||||
else if (top == 2 && ((sq_gettype(vm, -1) == OT_STRING) || !SQ_FAILED(sq_tostring(vm, -1))))
|
||||
{
|
||||
CCStr sql = NULL;
|
||||
// Attempt to retrieve the string from the stack
|
||||
if (SQ_FAILED(sq_getstring(vm, -1, &sql)))
|
||||
{
|
||||
// If the value was converted to a string then pop the string
|
||||
sq_pop(vm, sq_gettop(vm) - top);
|
||||
// Now we can throw the error message
|
||||
return sq_throwerror(vm, "Unable to retrieve the query");
|
||||
}
|
||||
// Attempt to execute the specified query
|
||||
if ((inst.value->m_Handle = sqlite3_exec(inst.value->m_Handle, sql, NULL, NULL, NULL)) != SQLITE_OK)
|
||||
{
|
||||
// If the value was converted to a string then pop the string
|
||||
sq_pop(vm, sq_gettop(vm) - top);
|
||||
// Generate the error message and throw the resulted string
|
||||
return sq_throwerror(vm, FmtStr("Unable to execute query [%s]", inst.value->m_Handle.ErrMsg()));
|
||||
}
|
||||
// If the value was converted to a string then pop the string
|
||||
sq_pop(vm, sq_gettop(vm) - top);
|
||||
// Push the result onto the stack
|
||||
sq_pushinteger(vm, sqlite3_changes(inst.value->m_Handle));
|
||||
}
|
||||
// Do we have enough values to call the format function?
|
||||
else if (top > 2)
|
||||
{
|
||||
SStr sql = NULL;
|
||||
SQInteger len = 0;
|
||||
// Attempt to generate the specified string format
|
||||
SQRESULT ret = sqstd_format(vm, 3, &len, &sql);
|
||||
// Did the format failed?
|
||||
if (SQ_FAILED(ret))
|
||||
return ret;
|
||||
// Attempt to execute the resulted query
|
||||
if ((inst.value->m_Handle = sqlite3_exec(inst.value->m_Handle, sql, NULL, NULL, NULL)) != SQLITE_OK)
|
||||
{
|
||||
// Generate the error message and throw the resulted string
|
||||
return sq_throwerror(vm, FmtStr("Unable to execute query [%s]", inst.value->m_Handle.ErrMsg()));
|
||||
}
|
||||
// Push the result onto the stack
|
||||
sq_pushinteger(vm, sqlite3_changes(inst.value->m_Handle));
|
||||
}
|
||||
// All methods of retrieving the message value failed
|
||||
else
|
||||
return sq_throwerror(vm, "Unable to extract the query string");
|
||||
// At this point we should have a return value on the stack
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQInteger Connection::QueueF(HSQUIRRELVM vm)
|
||||
{
|
||||
const Int32 top = sq_gettop(vm);
|
||||
// Do we even have enough arguments?
|
||||
if (top <= 1)
|
||||
return sq_throwerror(vm, "Missing the query string");
|
||||
// Obtain the connection instance
|
||||
Var< Connection * > inst(vm, 1);
|
||||
// Do we have a valid connection instance?
|
||||
if (!inst.value)
|
||||
return sq_throwerror(vm, "Invalid connection instance");
|
||||
// Do we have a valid connection reference?
|
||||
else if (!inst.value->m_Handle)
|
||||
return sq_throwerror(vm, "Invalid SQLite connection reference");
|
||||
// Is the specified message value a string or something convertible to string?
|
||||
else if (top == 2 && ((sq_gettype(vm, -1) == OT_STRING) || !SQ_FAILED(sq_tostring(vm, -1))))
|
||||
{
|
||||
CCStr sql = NULL;
|
||||
// Attempt to retrieve the string from the stack
|
||||
if (SQ_FAILED(sq_getstring(vm, -1, &sql)))
|
||||
{
|
||||
// If the value was converted to a string then pop the string
|
||||
sq_pop(vm, sq_gettop(vm) - top);
|
||||
// Now we can throw the error message
|
||||
return sq_throwerror(vm, "Unable to retrieve the query");
|
||||
}
|
||||
// Is there even a query to queue?
|
||||
else if (IsQueryEmpty(sql))
|
||||
{
|
||||
// If the value was converted to a string then pop the string
|
||||
sq_pop(vm, sq_gettop(vm) - top);
|
||||
return sq_throwerror(vm,"No query to queue");
|
||||
}
|
||||
// Attempt to queue the specified query
|
||||
inst.value->m_Handle->mQueue.push_back(sql);
|
||||
// If the value was converted to a string then pop the string
|
||||
sq_pop(vm, sq_gettop(vm) - top);
|
||||
}
|
||||
// Do we have enough values to call the format function?
|
||||
else if (top > 2)
|
||||
{
|
||||
SStr sql = NULL;
|
||||
SQInteger len = 0;
|
||||
// Attempt to generate the specified string format
|
||||
SQRESULT ret = sqstd_format(vm, 3, &len, &sql);
|
||||
// Did the format failed?
|
||||
if (SQ_FAILED(ret))
|
||||
return ret;
|
||||
// Is there even a query to queue?
|
||||
else if (IsQueryEmpty(sql))
|
||||
return sq_throwerror(vm,"No query to queue");
|
||||
// Attempt to queue the specified query
|
||||
inst.value->m_Handle->mQueue.push_back(sql);
|
||||
}
|
||||
// All methods of retrieving the message value failed
|
||||
else
|
||||
return sq_throwerror(vm, "Unable to extract the query string");
|
||||
// This function does not return a value
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQInteger Connection::QueryF(HSQUIRRELVM vm)
|
||||
{
|
||||
const Int32 top = sq_gettop(vm);
|
||||
// Do we even have enough arguments?
|
||||
if (top <= 1)
|
||||
return sq_throwerror(vm, "Missing the query string");
|
||||
// Obtain the connection instance
|
||||
Var< Connection * > inst(vm, 1);
|
||||
// Do we have a valid connection instance?
|
||||
if (!inst.value)
|
||||
return sq_throwerror(vm, "Invalid connection instance");
|
||||
// Do we have a valid connection reference?
|
||||
else if (!inst.value->m_Handle)
|
||||
return sq_throwerror(vm, "Invalid SQLite connection reference");
|
||||
// Is the specified message value a string or something convertible to string?
|
||||
else if (top == 2 && ((sq_gettype(vm, -1) == OT_STRING) || !SQ_FAILED(sq_tostring(vm, -1))))
|
||||
{
|
||||
CCStr sql = NULL;
|
||||
// Attempt to retrieve the string from the stack
|
||||
if (SQ_FAILED(sq_getstring(vm, -1, &sql)))
|
||||
{
|
||||
// If the value was converted to a string then pop the string
|
||||
sq_pop(vm, sq_gettop(vm) - top);
|
||||
// Now we can throw the error message
|
||||
return sq_throwerror(vm, "Unable to retrieve the query");
|
||||
}
|
||||
// Attempt to create a statement with the specified query
|
||||
ClassType< Statement >::PushInstance(vm, new Statement(inst.value->m_Handle, sql));
|
||||
// If the value was converted to a string then pop the string
|
||||
sq_pop(vm, sq_gettop(vm) - top);
|
||||
// See if any errors occured
|
||||
if (Sqrat::Error::Occurred(vm))
|
||||
{
|
||||
// Obtain the error message from sqrat
|
||||
String msg = Sqrat::Error::Message(vm);
|
||||
// Throw the error message further down the line
|
||||
return sq_throwerror(vm, msg.c_str());
|
||||
}
|
||||
}
|
||||
// Do we have enough values to call the format function?
|
||||
else if (top > 2)
|
||||
{
|
||||
SStr sql = NULL;
|
||||
SQInteger len = 0;
|
||||
// Attempt to generate the specified string format
|
||||
SQRESULT ret = sqstd_format(vm, 3, &len, &sql);
|
||||
// Did the format failed?
|
||||
if (SQ_FAILED(ret))
|
||||
return ret;
|
||||
// Attempt to create a statement with the specified query
|
||||
ClassType< Statement >::PushInstance(vm, new Statement(inst.value->m_Handle, sql));
|
||||
// See if any errors occured
|
||||
if (Sqrat::Error::Occurred(vm))
|
||||
{
|
||||
// Obtain the error message from sqrat
|
||||
String msg = Sqrat::Error::Message(vm);
|
||||
// Throw the error message further down the line
|
||||
return sq_throwerror(vm, msg.c_str());
|
||||
}
|
||||
}
|
||||
// All methods of retrieving the message value failed
|
||||
else
|
||||
return sq_throwerror(vm, "Unable to extract the query string");
|
||||
// At this point we should have a return value on the stack
|
||||
return 1;
|
||||
}
|
||||
|
||||
} // Namespace:: SqMod
|
578
modules/sqlite/Connection.hpp
Normal file
578
modules/sqlite/Connection.hpp
Normal file
@ -0,0 +1,578 @@
|
||||
#ifndef _SQSQLITE_CONNECTION_HPP_
|
||||
#define _SQSQLITE_CONNECTION_HPP_
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Common.hpp"
|
||||
#include "SqAPI.h"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Class used to manage a connection to an SQLite database.
|
||||
*/
|
||||
class Connection
|
||||
{
|
||||
protected:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Create the database connection resource.
|
||||
*/
|
||||
void Create(CSStr name, Int32 flags, CSStr vfs);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Validate the document reference and throw an error if invalid.
|
||||
*/
|
||||
bool Validate() const;
|
||||
|
||||
private:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
ConnHnd m_Handle; /* The handle to the managed database connection resource. */
|
||||
|
||||
public:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to open the specified database.
|
||||
*/
|
||||
Connection();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Explicit constructor.
|
||||
*/
|
||||
Connection(CSStr name);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Explicit constructor.
|
||||
*/
|
||||
Connection(CSStr name, Int32 flags);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Explicit constructor.
|
||||
*/
|
||||
Connection(CSStr name, Int32 flags, CSStr vfs);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Direct handle constructor.
|
||||
*/
|
||||
Connection(const ConnHnd & h)
|
||||
: m_Handle(h)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor.
|
||||
*/
|
||||
Connection(const Connection & o)
|
||||
: m_Handle(o.m_Handle)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Destructor.
|
||||
*/
|
||||
~Connection()
|
||||
{
|
||||
/* Let the reference manager destroy the connection when necessary. */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy assignment operator.
|
||||
*/
|
||||
Connection & operator = (const Connection & o)
|
||||
{
|
||||
m_Handle = o.m_Handle;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Perform an equality comparison between two connections.
|
||||
*/
|
||||
bool operator == (const Connection & o) const
|
||||
{
|
||||
return (m_Handle == o.m_Handle);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Perform an inequality comparison between two connections.
|
||||
*/
|
||||
bool operator != (const Connection & o) const
|
||||
{
|
||||
return (m_Handle != o.m_Handle);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Implicit conversion to the raw connection handle.
|
||||
*/
|
||||
operator sqlite3 * ()
|
||||
{
|
||||
return m_Handle;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Implicit conversion to the raw connection handle.
|
||||
*/
|
||||
operator sqlite3 * () const
|
||||
{
|
||||
return m_Handle;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to compare two instances of this type.
|
||||
*/
|
||||
Int32 Cmp(const Connection & o) const
|
||||
{
|
||||
if (m_Handle == m_Handle)
|
||||
return 0;
|
||||
else if (m_Handle.m_Hnd > o.m_Handle.m_Hnd)
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to convert an instance of this type to a string.
|
||||
*/
|
||||
CSStr ToString() const
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate())
|
||||
return m_Handle->mName.c_str();
|
||||
// Request failed
|
||||
return _SC("");
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to retrieve the name from instances of this type.
|
||||
*/
|
||||
static SQInteger Typename(HSQUIRRELVM vm);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* See whether this connection is valid.
|
||||
*/
|
||||
bool IsValid() const
|
||||
{
|
||||
return m_Handle;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the associated connection handle.
|
||||
*/
|
||||
const ConnHnd & GetHandle() const
|
||||
{
|
||||
return m_Handle;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Return the number of active references to this connection handle.
|
||||
*/
|
||||
Uint32 GetRefCount() const
|
||||
{
|
||||
return m_Handle.Count();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Release the reference to the associated database connection.
|
||||
*/
|
||||
void Release()
|
||||
{
|
||||
m_Handle.Drop();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the last received status code.
|
||||
*/
|
||||
Int32 GetStatus() const
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate())
|
||||
return m_Handle->mStatus;
|
||||
// Request failed
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the flags used to create this database connection.
|
||||
*/
|
||||
Int32 GetFlags() const
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate())
|
||||
return m_Handle->mFlags;
|
||||
// Request failed
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the name used to create this database connection.
|
||||
*/
|
||||
CSStr GetName() const
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate())
|
||||
return m_Handle->mName.c_str();
|
||||
// Request failed
|
||||
return _SC("");
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the virtual file system used to create this database connection.
|
||||
*/
|
||||
CSStr GetVFS() const
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate())
|
||||
return m_Handle->mVFS.c_str();
|
||||
// Request failed
|
||||
return _SC("");
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Return the numeric result code for the most recent failed API call (if any).
|
||||
*/
|
||||
Int32 GetErrorCode() const
|
||||
{
|
||||
if (Validate())
|
||||
return m_Handle.ErrNo();
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Return the extended numeric result code for the most recent failed API call (if any).
|
||||
*/
|
||||
Int32 GetExtendedErrorCode() const
|
||||
{
|
||||
if (Validate())
|
||||
return m_Handle.ExErrNo();
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the message of the last received error code.
|
||||
*/
|
||||
CSStr GetErrStr() const
|
||||
{
|
||||
if (Validate())
|
||||
return m_Handle.ErrStr();
|
||||
return _SC("");
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Return the last error message associated with this database connection.
|
||||
*/
|
||||
CSStr GetErrMsg() const
|
||||
{
|
||||
if (Validate())
|
||||
return m_Handle.ErrMsg();
|
||||
return _SC("");
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to open the specified database.
|
||||
*/
|
||||
void Open(CSStr name)
|
||||
{
|
||||
if (m_Handle.m_Hnd)
|
||||
m_Handle->Create(name, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to open the specified database.
|
||||
*/
|
||||
void Open(CSStr name, Int32 flags)
|
||||
{
|
||||
if (m_Handle.m_Hnd)
|
||||
m_Handle->Create(name, flags, NULL);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to open the specified database.
|
||||
*/
|
||||
void Open(CSStr name, Int32 flags, CSStr vfs)
|
||||
{
|
||||
if (m_Handle.m_Hnd)
|
||||
m_Handle->Create(name, flags, vfs);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to execute the specified query.
|
||||
*/
|
||||
Int32 Exec(CSStr str);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to queue the specified query.
|
||||
*/
|
||||
void Queue(CSStr str);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to create a statement from the specified query.
|
||||
*/
|
||||
Statement Query(CSStr str) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* See if the database connection was opened in read-only mode.
|
||||
*/
|
||||
bool IsReadOnly() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Shortcut to test if a table exists.
|
||||
*/
|
||||
bool TableExists(CCStr name) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* See if the database connection is or is not in auto-commit mode.
|
||||
*/
|
||||
bool GetAutoCommit() const
|
||||
{
|
||||
// Request failed
|
||||
if (Validate())
|
||||
return sqlite3_get_autocommit(m_Handle);
|
||||
// Request failed
|
||||
return false;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Get the row-id of the most recent successful INSERT into the database from the current connection.
|
||||
*/
|
||||
Object GetLastInsertRowID() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Returns the number of database rows that were changed, inserted or deleted
|
||||
* by the most recently completed SQL statement.
|
||||
*/
|
||||
Int32 GetChanges() const
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate())
|
||||
return sqlite3_changes(m_Handle);
|
||||
// Request failed
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Returns the total number of row changes caused by INSERT, UPDATE or DELETE statements
|
||||
* since the database connection was opened.
|
||||
*/
|
||||
Int32 GetTotalChanges() const
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate())
|
||||
return sqlite3_total_changes(m_Handle);
|
||||
// Request failed
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* See if this database connection has tracing enabled.
|
||||
*/
|
||||
bool GetTracing() const
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate())
|
||||
return m_Handle->mTrace;
|
||||
// Request failed
|
||||
return false;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Activate or deactivate tracing on this database connection.
|
||||
*/
|
||||
void SetTracing(bool toggle)
|
||||
{
|
||||
// Validate the handle and check whether changes are necessary
|
||||
if (!Validate() || m_Handle->mTrace == toggle)
|
||||
return; /* No point in proceeding */
|
||||
// Do we have to disable it?
|
||||
else if (m_Handle->mTrace)
|
||||
sqlite3_trace(m_Handle, NULL, NULL);
|
||||
// Go ahead and enable tracing
|
||||
else
|
||||
sqlite3_trace(m_Handle, &Connection::TraceOutput, NULL);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* See if this database connection has profiling enabled.
|
||||
*/
|
||||
bool GetProfiling() const
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate())
|
||||
return m_Handle->mProfile;
|
||||
// Request failed
|
||||
return false;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Activate or deactivate profiling on this database connection.
|
||||
*/
|
||||
void SetProfiling(bool toggle)
|
||||
{
|
||||
// Validate the handle and check whether changes are necessary
|
||||
if (!Validate() || m_Handle->mProfile == toggle)
|
||||
return; /* No point in proceeding */
|
||||
// Do we have to disable it?
|
||||
else if (m_Handle->mProfile)
|
||||
sqlite3_profile(m_Handle, NULL, NULL);
|
||||
// Go ahead and enable profiling
|
||||
else
|
||||
sqlite3_profile(m_Handle, &Connection::ProfileOutput, NULL);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Set a busy handler that sleeps for a specified amount of time when a table is locked.
|
||||
*/
|
||||
void SetBusyTimeout(Int32 millis);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Causes any pending database operation to abort and return at its earliest opportunity.
|
||||
*/
|
||||
void InterruptOperation() const
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate())
|
||||
sqlite3_interrupt(m_Handle);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempts to free as much heap memory as possible from the database connection.
|
||||
*/
|
||||
void ReleaseMemory() const
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate())
|
||||
sqlite3_db_release_memory(m_Handle);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move the whole database into memory.
|
||||
*/
|
||||
Connection CopyToMemory();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Takes a snapshot of a database which is located in memory and saves it to a database file.
|
||||
*/
|
||||
void CopyToDatabase(Connection & db);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Returns internal runtime status information associated with the current database connection.
|
||||
*/
|
||||
Int32 GetInfo(Int32 operation)
|
||||
{
|
||||
return GetInfo(operation, false, false);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Returns internal runtime status information associated with the current database connection.
|
||||
*/
|
||||
Int32 GetInfo(Int32 operation, bool highwater = false)
|
||||
{
|
||||
return GetInfo(operation, highwater, false);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Returns internal runtime status information associated with the current database connection.
|
||||
*/
|
||||
Int32 GetInfo(Int32 operation, bool highwater = false, bool reset = false);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the number of queries in the queue.
|
||||
*/
|
||||
Uint32 QueueSize() const
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate())
|
||||
return (Uint32)m_Handle->mQueue.size();
|
||||
// Request failed
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Remove all queries from the queue without executing them.
|
||||
*/
|
||||
void ClearQueue() const
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate())
|
||||
m_Handle->mQueue.clear();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Remove the last query from the queue.
|
||||
*/
|
||||
void PopQueue() const
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate() && !m_Handle->mQueue.empty())
|
||||
m_Handle->mQueue.pop_back();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Flush all queries from the queue.
|
||||
*/
|
||||
Int32 Flush()
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate())
|
||||
return Flush(m_Handle->mQueue.size());
|
||||
// Request failed
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Flush a specific amount of queries from the queue.
|
||||
*/
|
||||
Int32 Flush(Uint32 num);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Flush a specific amount of queries from the queue.
|
||||
*/
|
||||
Int32 Flush(Uint32 num, Object & env, Function & func);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to execute the specified query.
|
||||
*/
|
||||
static SQInteger ExecF(HSQUIRRELVM vm);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to queue the specified query.
|
||||
*/
|
||||
static SQInteger QueueF(HSQUIRRELVM vm);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to create a statement from the specified query.
|
||||
*/
|
||||
static SQInteger QueryF(HSQUIRRELVM vm);
|
||||
|
||||
protected:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Callback function for ActivateTracing()
|
||||
*/
|
||||
static void TraceOutput(void * ptr, const char * sql);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Callback function for ActivateProfiling()
|
||||
*/
|
||||
static void ProfileOutput(void * ptr, const char * sql, sqlite3_uint64 time);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Build and modify the structure of tables and other objects in the memory database.
|
||||
*/
|
||||
static int ProcessDDLRow(void * db, int columns_count, char ** values, char ** columns);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Insert all data from the origin database into the memory database.
|
||||
*/
|
||||
static int ProcessDMLRow(void * db, int columns_count, char ** values, char ** columns);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Takes and saves a snapshot of the memory database in a file.
|
||||
*/
|
||||
void TakeSnapshot(ConnHnd & destination);
|
||||
};
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
#endif // _SQSQLITE_CONNECTION_HPP_
|
813
modules/sqlite/Module.cpp
Normal file
813
modules/sqlite/Module.cpp
Normal file
@ -0,0 +1,813 @@
|
||||
// --------------------------------------------------------------------------------------------
|
||||
#include "Module.hpp"
|
||||
#include "Common.hpp"
|
||||
#include "Connection.hpp"
|
||||
#include "Statement.hpp"
|
||||
#include "Column.hpp"
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
#include <sqrat.h>
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
namespace SqMod {
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
PluginFuncs* _Func = NULL;
|
||||
PluginCallbacks* _Clbk = NULL;
|
||||
PluginInfo* _Info = NULL;
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
HSQAPI _SqAPI = NULL;
|
||||
HSQEXPORTS _SqMod = NULL;
|
||||
HSQUIRRELVM _SqVM = NULL;
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Bind speciffic functions to certain server events.
|
||||
*/
|
||||
void BindCallbacks();
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Undo changes made with BindCallbacks().
|
||||
*/
|
||||
void UnbindCallbacks();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Register the module API under the specified virtual machine.
|
||||
*/
|
||||
void RegisterAPI(HSQUIRRELVM vm);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Initialize the plugin by obtaining the API provided by the host plugin.
|
||||
*/
|
||||
void OnSquirrelInitialize()
|
||||
{
|
||||
// Attempt to import the plugin API exported by the host plugin
|
||||
_SqMod = sq_api_import(_Func);
|
||||
// Did we failed to obtain the plugin exports?
|
||||
if(!_SqMod)
|
||||
OutputError("Failed to attach [%s] on host plugin.", SQSQLITE_NAME);
|
||||
else
|
||||
{
|
||||
// Obtain the Squirrel API
|
||||
_SqAPI = _SqMod->GetSquirrelAPI();
|
||||
// Expand the Squirrel API into global functions
|
||||
sq_api_expand(_SqAPI);
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Load the module on the virtual machine provided by the host module.
|
||||
*/
|
||||
void OnSquirrelLoad()
|
||||
{
|
||||
// Make sure that we have a valid plugin API
|
||||
if (!_SqMod)
|
||||
return; /* Unable to proceed. */
|
||||
// Obtain the Squirrel API and VM
|
||||
_SqVM = _SqMod->GetSquirrelVM();
|
||||
// Make sure that a valid virtual machine exists
|
||||
if (!_SqVM)
|
||||
return; /* Unable to proceed. */
|
||||
// Set this as the default database
|
||||
DefaultVM::Set(_SqVM);
|
||||
// Register the module API
|
||||
RegisterAPI(_SqVM);
|
||||
// Notify about the current status
|
||||
OutputMessage("Registered: %s", SQSQLITE_NAME);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* The virtual machine is about to be terminated and script resources should be released.
|
||||
*/
|
||||
void OnSquirrelTerminate()
|
||||
{
|
||||
OutputMessage("Terminating: %s", SQSQLITE_NAME);
|
||||
// Release the current database (if any)
|
||||
DefaultVM::Set(NULL);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Validate the module API to make sure we don't run into issues.
|
||||
*/
|
||||
bool CheckAPIVer(CCStr ver)
|
||||
{
|
||||
// Obtain the numeric representation of the API version
|
||||
long vernum = strtol(ver, NULL, 10);
|
||||
// Check against version mismatch
|
||||
if (vernum == SQMOD_API_VER)
|
||||
return true;
|
||||
// Log the incident
|
||||
OutputError("API version mismatch on %s", SQSQLITE_NAME);
|
||||
OutputMessage("=> Requested: %ld Have: %ld", vernum, SQMOD_API_VER);
|
||||
// Invoker should not attempt to communicate through the module API
|
||||
return false;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* React to command sent by other plugins.
|
||||
*/
|
||||
static int OnInternalCommand(unsigned int type, const char * text)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case SQMOD_INITIALIZE_CMD:
|
||||
if (CheckAPIVer(text))
|
||||
OnSquirrelInitialize();
|
||||
break;
|
||||
case SQMOD_LOAD_CMD:
|
||||
OnSquirrelLoad();
|
||||
break;
|
||||
case SQMOD_TERMINATE_CMD:
|
||||
OnSquirrelTerminate();
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* The server was initialized and this plugin was loaded successfully.
|
||||
*/
|
||||
static int OnInitServer()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void OnShutdownServer(void)
|
||||
{
|
||||
// The server may still send callbacks
|
||||
UnbindCallbacks();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BindCallbacks()
|
||||
{
|
||||
_Clbk->OnInitServer = OnInitServer;
|
||||
_Clbk->OnInternalCommand = OnInternalCommand;
|
||||
_Clbk->OnShutdownServer = OnShutdownServer;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void UnbindCallbacks()
|
||||
{
|
||||
_Clbk->OnInitServer = NULL;
|
||||
_Clbk->OnInternalCommand = NULL;
|
||||
_Clbk->OnShutdownServer = NULL;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
void RegisterAPI(HSQUIRRELVM vm)
|
||||
{
|
||||
Table sqlns(vm);
|
||||
|
||||
sqlns.Bind(_SC("Connection"), Class< Connection >(vm, _SC("SqSQLiteConnection"))
|
||||
/* Constructors */
|
||||
.Ctor()
|
||||
.Ctor< CCStr >()
|
||||
.Ctor< CCStr, Int32 >()
|
||||
.Ctor< CCStr, Int32, CCStr >()
|
||||
/* Metamethods */
|
||||
.Func(_SC("_cmp"), &Connection::Cmp)
|
||||
.SquirrelFunc(_SC("_typename"), &Connection::Typename)
|
||||
.Func(_SC("_tostring"), &Connection::ToString)
|
||||
/* Properties */
|
||||
.Prop(_SC("Valid"), &Connection::IsValid)
|
||||
.Prop(_SC("Refs"), &Connection::GetRefCount)
|
||||
.Prop(_SC("Connected"), &Connection::IsValid)
|
||||
.Prop(_SC("Status"), &Connection::GetStatus)
|
||||
.Prop(_SC("Flags"), &Connection::GetFlags)
|
||||
.Prop(_SC("Name"), &Connection::GetName)
|
||||
.Prop(_SC("VFS"), &Connection::GetVFS)
|
||||
.Prop(_SC("ErrCode"), &Connection::GetErrorCode)
|
||||
.Prop(_SC("ExErrCode"), &Connection::GetExtendedErrorCode)
|
||||
.Prop(_SC("ExtendedErrCode"), &Connection::GetExtendedErrorCode)
|
||||
.Prop(_SC("ErrStr"), &Connection::GetErrStr)
|
||||
.Prop(_SC("ErrMsg"), &Connection::GetErrMsg)
|
||||
.Prop(_SC("ReadOnly"), &Connection::IsReadOnly)
|
||||
.Prop(_SC("Autocommit"), &Connection::GetAutoCommit)
|
||||
.Prop(_SC("LastInsertRowId"), &Connection::GetLastInsertRowID)
|
||||
.Prop(_SC("Changes"), &Connection::GetChanges)
|
||||
.Prop(_SC("TotalChanges"), &Connection::GetTotalChanges)
|
||||
.Prop(_SC("Trace"), &Connection::GetTracing, &Connection::SetTracing)
|
||||
.Prop(_SC("Profile"), &Connection::GetProfiling, &Connection::SetProfiling)
|
||||
.Prop(_SC("BusyTimeout"), (Int32 (Connection::*)(void) const)(NULL), &Connection::SetBusyTimeout)
|
||||
.Prop(_SC("QueueSize"), &Connection::QueueSize)
|
||||
/* Functions */
|
||||
.Func(_SC("Release"), &Connection::Release)
|
||||
.Overload< void (Connection::*)(CSStr) >(_SC("Open"), &Connection::Open)
|
||||
.Overload< void (Connection::*)(CSStr, Int32) >(_SC("Open"), &Connection::Open)
|
||||
.Overload< void (Connection::*)(CSStr, Int32, CSStr) >(_SC("Open"), &Connection::Open)
|
||||
.Func(_SC("Exec"), &Connection::Exec)
|
||||
.Func(_SC("Queue"), &Connection::Queue)
|
||||
.Func(_SC("Query"), &Connection::Query)
|
||||
.Func(_SC("TableExists"), &Connection::TableExists)
|
||||
.Func(_SC("InterruptOperation"), &Connection::InterruptOperation)
|
||||
.Func(_SC("ReleaseMemory"), &Connection::ReleaseMemory)
|
||||
.Func(_SC("CopyToMemory"), &Connection::CopyToMemory)
|
||||
.Func(_SC("CopyToDatabase"), &Connection::CopyToDatabase)
|
||||
.Overload< Int32 (Connection::*)(Int32) >(_SC("GetInfo"), &Connection::GetInfo)
|
||||
.Overload< Int32 (Connection::*)(Int32, bool) >(_SC("GetInfo"), &Connection::GetInfo)
|
||||
.Overload< Int32 (Connection::*)(Int32, bool, bool) >(_SC("GetInfo"), &Connection::GetInfo)
|
||||
.Func(_SC("ClearQueue"), &Connection::ClearQueue)
|
||||
.Func(_SC("PopQueue"), &Connection::PopQueue)
|
||||
.Overload< Int32 (Connection::*)(void) >(_SC("Flush"), &Connection::Flush)
|
||||
.Overload< Int32 (Connection::*)(Uint32) >(_SC("Flush"), &Connection::Flush)
|
||||
.Overload< Int32 (Connection::*)(Uint32, Object &, Function &) >(_SC("Flush"), &Connection::Flush)
|
||||
.SquirrelFunc(_SC("ExecF"), &Connection::ExecF)
|
||||
.SquirrelFunc(_SC("QueueF"), &Connection::QueueF)
|
||||
.SquirrelFunc(_SC("QueryF"), &Connection::QueryF)
|
||||
);
|
||||
|
||||
sqlns.Bind(_SC("Statement"), Class< Statement >(vm, _SC("SqSQLiteStatement"))
|
||||
/* Constructors */
|
||||
.Ctor()
|
||||
.Ctor< const Connection &, CCStr >()
|
||||
.Ctor< const Statement & >()
|
||||
/* Metamethods */
|
||||
.Func(_SC("_cmp"), &Statement::Cmp)
|
||||
.SquirrelFunc(_SC("_typename"), &Statement::Typename)
|
||||
.Func(_SC("_tostring"), &Statement::ToString)
|
||||
/* Properties */
|
||||
.Prop(_SC("Valid"), &Statement::IsValid)
|
||||
.Prop(_SC("Refs"), &Statement::GetRefCount)
|
||||
.Prop(_SC("Connection"), &Statement::GetConnection)
|
||||
.Prop(_SC("Prepared"), &Statement::IsValid)
|
||||
.Prop(_SC("Status"), &Statement::GetStatus)
|
||||
.Prop(_SC("ErrCode"), &Statement::GetErrorCode)
|
||||
.Prop(_SC("ExErrCode"), &Statement::GetExtendedErrorCode)
|
||||
.Prop(_SC("ExtendedErrCode"), &Statement::GetExtendedErrorCode)
|
||||
.Prop(_SC("ErrStr"), &Statement::GetErrStr)
|
||||
.Prop(_SC("ErrMsg"), &Statement::GetErrMsg)
|
||||
.Prop(_SC("Columns"), &Statement::GetColumns)
|
||||
.Prop(_SC("Query"), &Statement::GetQuery)
|
||||
.Prop(_SC("Good"), &Statement::GetGood)
|
||||
.Prop(_SC("Done"), &Statement::GetDone)
|
||||
/* Functions */
|
||||
.Func(_SC("Release"), &Statement::Release)
|
||||
.Func(_SC("Reset"), &Statement::Reset)
|
||||
.Func(_SC("Clear"), &Statement::Clear)
|
||||
.Func(_SC("Exec"), &Statement::Exec)
|
||||
.Func(_SC("Step"), &Statement::Step)
|
||||
.Func(_SC("IBindA"), &Statement::IndexBindA)
|
||||
.Func(_SC("IBindI"), &Statement::IndexBindI)
|
||||
.Func(_SC("IBindL"), &Statement::IndexBindL)
|
||||
.Func(_SC("IBindV"), &Statement::IndexBindV)
|
||||
.Func(_SC("IBindF"), &Statement::IndexBindF)
|
||||
.Func(_SC("IBindS"), &Statement::IndexBindS)
|
||||
.Func(_SC("IBindB"), &Statement::IndexBindB)
|
||||
.Func(_SC("IBindN"), &Statement::IndexBindN)
|
||||
.Func(_SC("NBindT"), &Statement::NameBindT)
|
||||
.Func(_SC("NBindI"), &Statement::NameBindI)
|
||||
.Func(_SC("NBindL"), &Statement::NameBindL)
|
||||
.Func(_SC("NBindV"), &Statement::NameBindV)
|
||||
.Func(_SC("NBindF"), &Statement::NameBindF)
|
||||
.Func(_SC("NBindS"), &Statement::NameBindS)
|
||||
.Func(_SC("NBindB"), &Statement::NameBindB)
|
||||
.Func(_SC("NBindN"), &Statement::NameBindN)
|
||||
.Func(_SC("IBind"), &Statement::IndexBind)
|
||||
.Func(_SC("NBind"), &Statement::NameBind)
|
||||
.Func(_SC("FetchI"), &Statement::FetchColumnIndex)
|
||||
.Func(_SC("FetchN"), &Statement::FetchColumnName)
|
||||
.Overload< Array (Statement::*)(void) const >(_SC("FetchA"), &Statement::FetchArray)
|
||||
.Overload< Array (Statement::*)(Int32) const >(_SC("FetchA"), &Statement::FetchArray)
|
||||
.Overload< Array (Statement::*)(Int32, Int32) const >(_SC("FetchA"), &Statement::FetchArray)
|
||||
.Overload< Table (Statement::*)(void) const >(_SC("FetchT"), &Statement::FetchTable)
|
||||
.Overload< Table (Statement::*)(Int32) const >(_SC("FetchT"), &Statement::FetchTable)
|
||||
.Overload< Table (Statement::*)(Int32, Int32) const >(_SC("FetchT"), &Statement::FetchTable)
|
||||
.Func(_SC("CheckIndex"), &Statement::CheckIndex)
|
||||
.Func(_SC("IsColumnNull"), &Statement::IsColumnNull)
|
||||
.Func(_SC("ColumnIndex"), &Statement::GetColumnIndex)
|
||||
.Func(_SC("ColumnName"), &Statement::GetColumnName)
|
||||
.Func(_SC("ColumnOriginName"), &Statement::GetColumnOriginName)
|
||||
.Func(_SC("ColumnType"), &Statement::GetColumnType)
|
||||
.Func(_SC("ColumnBytes"), &Statement::GetColumnBytes)
|
||||
.Func(_SC("GetI"), &Statement::GetColumnByIndex)
|
||||
.Func(_SC("GetN"), &Statement::GetColumnByName)
|
||||
);
|
||||
|
||||
sqlns.Bind(_SC("Column"), Class< Column >(vm, _SC("SqSQLiteColumn"))
|
||||
/* Constructors */
|
||||
.Ctor()
|
||||
.Ctor< const Column & >()
|
||||
/* Metamethods */
|
||||
.Func(_SC("_cmp"), &Column::Cmp)
|
||||
.SquirrelFunc(_SC("_typename"), &Column::Typename)
|
||||
.Func(_SC("_tostring"), &Column::ToString)
|
||||
/* Properties */
|
||||
.Prop(_SC("Valid"), &Column::IsValid)
|
||||
.Prop(_SC("Refs"), &Column::GetRefCount)
|
||||
.Prop(_SC("Index"), &Column::GetIndex)
|
||||
.Prop(_SC("Statement"), &Column::GetNumber)
|
||||
.Prop(_SC("Connection"), &Column::GetConnection)
|
||||
.Prop(_SC("Number"), &Column::GetNumber)
|
||||
.Prop(_SC("Integer"), &Column::GetInteger)
|
||||
.Prop(_SC("Float"), &Column::GetFloat)
|
||||
.Prop(_SC("Long"), &Column::GetLong)
|
||||
.Prop(_SC("String"), &Column::GetString)
|
||||
.Prop(_SC("Boolean"), &Column::GetBoolean)
|
||||
.Prop(_SC("Blob"), &Column::GetBlob)
|
||||
.Prop(_SC("Char"), &Column::GetChar)
|
||||
.Prop(_SC("IsNull"), &Column::IsNull)
|
||||
.Prop(_SC("Name"), &Column::GetName)
|
||||
.Prop(_SC("OriginName"), &Column::GetOriginName)
|
||||
.Prop(_SC("Type"), &Column::GetType)
|
||||
.Prop(_SC("Bytes"), &Column::GetBytes)
|
||||
/* Functions */
|
||||
.Func(_SC("Release"), &Column::Release)
|
||||
);
|
||||
|
||||
sqlns.Func(_SC("SetSoftHeapLimit"), &SetSoftHeapLimit);
|
||||
sqlns.Func(_SC("ReleaseMemory"), &ReleaseMemory);
|
||||
sqlns.Func(_SC("MemoryUsage"), &GetMemoryUsage);
|
||||
sqlns.Func(_SC("EscapeString"), &EscapeString);
|
||||
sqlns.Func(_SC("EscapeStringEx"), &EscapeStringEx);
|
||||
sqlns.Func(_SC("Escape"), &EscapeString);
|
||||
sqlns.Func(_SC("EscapeEx"), &EscapeStringEx);
|
||||
sqlns.Func(_SC("ArrayToQueryColumns"), &ArrayToQueryColumns);
|
||||
sqlns.Func(_SC("TableToQueryColumns"), &TableToQueryColumns);
|
||||
|
||||
RootTable(vm).Bind(_SC("SQLite"), sqlns);
|
||||
|
||||
/*
|
||||
ConstTable(vm).Enum(_SC("ESQLite"), Enumeration(vm)
|
||||
.Const(_SC("ABORT"), SQLITE_ABORT)
|
||||
.Const(_SC("ABORT_ROLLBACK"), SQLITE_ABORT_ROLLBACK)
|
||||
.Const(_SC("ACCESS_EXISTS"), SQLITE_ACCESS_EXISTS)
|
||||
.Const(_SC("ACCESS_READ"), SQLITE_ACCESS_READ)
|
||||
.Const(_SC("ACCESS_READWRITE"), SQLITE_ACCESS_READWRITE)
|
||||
.Const(_SC("ALTER_TABLE"), SQLITE_ALTER_TABLE)
|
||||
.Const(_SC("ANALYZE"), SQLITE_ANALYZE)
|
||||
.Const(_SC("ANY"), SQLITE_ANY)
|
||||
.Const(_SC("ATTACH"), SQLITE_ATTACH)
|
||||
.Const(_SC("AUTH"), SQLITE_AUTH)
|
||||
.Const(_SC("AUTH_USER"), SQLITE_AUTH_USER)
|
||||
.Const(_SC("BLOB"), SQLITE_BLOB)
|
||||
.Const(_SC("BUSY"), SQLITE_BUSY)
|
||||
.Const(_SC("BUSY_RECOVERY"), SQLITE_BUSY_RECOVERY)
|
||||
.Const(_SC("BUSY_SNAPSHOT"), SQLITE_BUSY_SNAPSHOT)
|
||||
.Const(_SC("CANTOPEN"), SQLITE_CANTOPEN)
|
||||
.Const(_SC("CANTOPEN_CONVPATH"), SQLITE_CANTOPEN_CONVPATH)
|
||||
.Const(_SC("CANTOPEN_FULLPATH"), SQLITE_CANTOPEN_FULLPATH)
|
||||
.Const(_SC("CANTOPEN_ISDIR"), SQLITE_CANTOPEN_ISDIR)
|
||||
.Const(_SC("CANTOPEN_NOTEMPDIR"), SQLITE_CANTOPEN_NOTEMPDIR)
|
||||
.Const(_SC("CHECKPOINT_FULL"), SQLITE_CHECKPOINT_FULL)
|
||||
.Const(_SC("CHECKPOINT_PASSIVE"), SQLITE_CHECKPOINT_PASSIVE)
|
||||
.Const(_SC("CHECKPOINT_RESTART"), SQLITE_CHECKPOINT_RESTART)
|
||||
.Const(_SC("CHECKPOINT_TRUNCATE"), SQLITE_CHECKPOINT_TRUNCATE)
|
||||
.Const(_SC("CONFIG_COVERING_INDEX_SCAN"), SQLITE_CONFIG_COVERING_INDEX_SCAN)
|
||||
.Const(_SC("CONFIG_GETMALLOC"), SQLITE_CONFIG_GETMALLOC)
|
||||
.Const(_SC("CONFIG_GETMUTEX"), SQLITE_CONFIG_GETMUTEX)
|
||||
.Const(_SC("CONFIG_GETPCACHE"), SQLITE_CONFIG_GETPCACHE)
|
||||
.Const(_SC("CONFIG_GETPCACHE2"), SQLITE_CONFIG_GETPCACHE2)
|
||||
.Const(_SC("CONFIG_HEAP"), SQLITE_CONFIG_HEAP)
|
||||
.Const(_SC("CONFIG_LOG"), SQLITE_CONFIG_LOG)
|
||||
.Const(_SC("CONFIG_LOOKASIDE"), SQLITE_CONFIG_LOOKASIDE)
|
||||
.Const(_SC("CONFIG_MALLOC"), SQLITE_CONFIG_MALLOC)
|
||||
.Const(_SC("CONFIG_MEMSTATUS"), SQLITE_CONFIG_MEMSTATUS)
|
||||
.Const(_SC("CONFIG_MMAP_SIZE"), SQLITE_CONFIG_MMAP_SIZE)
|
||||
.Const(_SC("CONFIG_MULTITHREAD"), SQLITE_CONFIG_MULTITHREAD)
|
||||
.Const(_SC("CONFIG_MUTEX"), SQLITE_CONFIG_MUTEX)
|
||||
.Const(_SC("CONFIG_PAGECACHE"), SQLITE_CONFIG_PAGECACHE)
|
||||
.Const(_SC("CONFIG_PCACHE"), SQLITE_CONFIG_PCACHE)
|
||||
.Const(_SC("CONFIG_PCACHE2"), SQLITE_CONFIG_PCACHE2)
|
||||
.Const(_SC("CONFIG_PCACHE_HDRSZ"), SQLITE_CONFIG_PCACHE_HDRSZ)
|
||||
.Const(_SC("CONFIG_PMASZ"), SQLITE_CONFIG_PMASZ)
|
||||
.Const(_SC("CONFIG_SCRATCH"), SQLITE_CONFIG_SCRATCH)
|
||||
.Const(_SC("CONFIG_SERIALIZED"), SQLITE_CONFIG_SERIALIZED)
|
||||
.Const(_SC("CONFIG_SINGLETHREAD"), SQLITE_CONFIG_SINGLETHREAD)
|
||||
.Const(_SC("CONFIG_SQLLOG"), SQLITE_CONFIG_SQLLOG)
|
||||
.Const(_SC("CONFIG_URI"), SQLITE_CONFIG_URI)
|
||||
.Const(_SC("CONFIG_WIN32_HEAPSIZE"), SQLITE_CONFIG_WIN32_HEAPSIZE)
|
||||
.Const(_SC("CONSTRAINT"), SQLITE_CONSTRAINT)
|
||||
.Const(_SC("CONSTRAINT_CHECK"), SQLITE_CONSTRAINT_CHECK)
|
||||
.Const(_SC("CONSTRAINT_COMMITHOOK"), SQLITE_CONSTRAINT_COMMITHOOK)
|
||||
.Const(_SC("CONSTRAINT_FOREIGNKEY"), SQLITE_CONSTRAINT_FOREIGNKEY)
|
||||
.Const(_SC("CONSTRAINT_FUNCTION"), SQLITE_CONSTRAINT_FUNCTION)
|
||||
.Const(_SC("CONSTRAINT_NOTNULL"), SQLITE_CONSTRAINT_NOTNULL)
|
||||
.Const(_SC("CONSTRAINT_PRIMARYKEY"), SQLITE_CONSTRAINT_PRIMARYKEY)
|
||||
.Const(_SC("CONSTRAINT_ROWID"), SQLITE_CONSTRAINT_ROWID)
|
||||
.Const(_SC("CONSTRAINT_TRIGGER"), SQLITE_CONSTRAINT_TRIGGER)
|
||||
.Const(_SC("CONSTRAINT_UNIQUE"), SQLITE_CONSTRAINT_UNIQUE)
|
||||
.Const(_SC("CONSTRAINT_VTAB"), SQLITE_CONSTRAINT_VTAB)
|
||||
.Const(_SC("COPY"), SQLITE_COPY)
|
||||
.Const(_SC("CORRUPT"), SQLITE_CORRUPT)
|
||||
.Const(_SC("CORRUPT_VTAB"), SQLITE_CORRUPT_VTAB)
|
||||
.Const(_SC("CREATE_INDEX"), SQLITE_CREATE_INDEX)
|
||||
.Const(_SC("CREATE_TABLE"), SQLITE_CREATE_TABLE)
|
||||
.Const(_SC("CREATE_TEMP_INDEX"), SQLITE_CREATE_TEMP_INDEX)
|
||||
.Const(_SC("CREATE_TEMP_TABLE"), SQLITE_CREATE_TEMP_TABLE)
|
||||
.Const(_SC("CREATE_TEMP_TRIGGER"), SQLITE_CREATE_TEMP_TRIGGER)
|
||||
.Const(_SC("CREATE_TEMP_VIEW"), SQLITE_CREATE_TEMP_VIEW)
|
||||
.Const(_SC("CREATE_TRIGGER"), SQLITE_CREATE_TRIGGER)
|
||||
.Const(_SC("CREATE_VIEW"), SQLITE_CREATE_VIEW)
|
||||
.Const(_SC("CREATE_VTABLE"), SQLITE_CREATE_VTABLE)
|
||||
.Const(_SC("DBCONFIG_ENABLE_FKEY"), SQLITE_DBCONFIG_ENABLE_FKEY)
|
||||
.Const(_SC("DBCONFIG_ENABLE_TRIGGER"), SQLITE_DBCONFIG_ENABLE_TRIGGER)
|
||||
.Const(_SC("DBCONFIG_LOOKASIDE"), SQLITE_DBCONFIG_LOOKASIDE)
|
||||
.Const(_SC("DBSTATUS_CACHE_HIT"), SQLITE_DBSTATUS_CACHE_HIT)
|
||||
.Const(_SC("DBSTATUS_CACHE_MISS"), SQLITE_DBSTATUS_CACHE_MISS)
|
||||
.Const(_SC("DBSTATUS_CACHE_USED"), SQLITE_DBSTATUS_CACHE_USED)
|
||||
.Const(_SC("DBSTATUS_CACHE_WRITE"), SQLITE_DBSTATUS_CACHE_WRITE)
|
||||
.Const(_SC("DBSTATUS_DEFERRED_FKS"), SQLITE_DBSTATUS_DEFERRED_FKS)
|
||||
.Const(_SC("DBSTATUS_LOOKASIDE_HIT"), SQLITE_DBSTATUS_LOOKASIDE_HIT)
|
||||
.Const(_SC("DBSTATUS_LOOKASIDE_MISS_FULL"), SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL)
|
||||
.Const(_SC("DBSTATUS_LOOKASIDE_MISS_SIZE"), SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE)
|
||||
.Const(_SC("DBSTATUS_LOOKASIDE_USED"), SQLITE_DBSTATUS_LOOKASIDE_USED)
|
||||
.Const(_SC("DBSTATUS_MAX"), SQLITE_DBSTATUS_MAX)
|
||||
.Const(_SC("DBSTATUS_SCHEMA_USED"), SQLITE_DBSTATUS_SCHEMA_USED)
|
||||
.Const(_SC("DBSTATUS_STMT_USED"), SQLITE_DBSTATUS_STMT_USED)
|
||||
.Const(_SC("DELETE"), SQLITE_DELETE)
|
||||
.Const(_SC("DENY"), SQLITE_DENY)
|
||||
.Const(_SC("DETACH"), SQLITE_DETACH)
|
||||
.Const(_SC("DETERMINISTIC"), SQLITE_DETERMINISTIC)
|
||||
.Const(_SC("DONE"), SQLITE_DONE)
|
||||
.Const(_SC("DROP_INDEX"), SQLITE_DROP_INDEX)
|
||||
.Const(_SC("DROP_TABLE"), SQLITE_DROP_TABLE)
|
||||
.Const(_SC("DROP_TEMP_INDEX"), SQLITE_DROP_TEMP_INDEX)
|
||||
.Const(_SC("DROP_TEMP_TABLE"), SQLITE_DROP_TEMP_TABLE)
|
||||
.Const(_SC("DROP_TEMP_TRIGGER"), SQLITE_DROP_TEMP_TRIGGER)
|
||||
.Const(_SC("DROP_TEMP_VIEW"), SQLITE_DROP_TEMP_VIEW)
|
||||
.Const(_SC("DROP_TRIGGER"), SQLITE_DROP_TRIGGER)
|
||||
.Const(_SC("DROP_VIEW"), SQLITE_DROP_VIEW)
|
||||
.Const(_SC("DROP_VTABLE"), SQLITE_DROP_VTABLE)
|
||||
.Const(_SC("EMPTY"), SQLITE_EMPTY)
|
||||
.Const(_SC("ERROR"), SQLITE_ERROR)
|
||||
.Const(_SC("FAIL"), SQLITE_FAIL)
|
||||
.Const(_SC("FCNTL_BUSYHANDLER"), SQLITE_FCNTL_BUSYHANDLER)
|
||||
.Const(_SC("FCNTL_CHUNK_SIZE"), SQLITE_FCNTL_CHUNK_SIZE)
|
||||
.Const(_SC("FCNTL_COMMIT_PHASETWO"), SQLITE_FCNTL_COMMIT_PHASETWO)
|
||||
.Const(_SC("FCNTL_FILE_POINTER"), SQLITE_FCNTL_FILE_POINTER)
|
||||
.Const(_SC("FCNTL_GET_LOCKPROXYFILE"), SQLITE_FCNTL_GET_LOCKPROXYFILE)
|
||||
.Const(_SC("FCNTL_HAS_MOVED"), SQLITE_FCNTL_HAS_MOVED)
|
||||
.Const(_SC("FCNTL_LAST_ERRNO"), SQLITE_FCNTL_LAST_ERRNO)
|
||||
.Const(_SC("FCNTL_LOCKSTATE"), SQLITE_FCNTL_LOCKSTATE)
|
||||
.Const(_SC("FCNTL_MMAP_SIZE"), SQLITE_FCNTL_MMAP_SIZE)
|
||||
.Const(_SC("FCNTL_OVERWRITE"), SQLITE_FCNTL_OVERWRITE)
|
||||
.Const(_SC("FCNTL_PERSIST_WAL"), SQLITE_FCNTL_PERSIST_WAL)
|
||||
.Const(_SC("FCNTL_POWERSAFE_OVERWRITE"), SQLITE_FCNTL_POWERSAFE_OVERWRITE)
|
||||
.Const(_SC("FCNTL_PRAGMA"), SQLITE_FCNTL_PRAGMA)
|
||||
.Const(_SC("FCNTL_RBU"), SQLITE_FCNTL_RBU)
|
||||
.Const(_SC("FCNTL_SET_LOCKPROXYFILE"), SQLITE_FCNTL_SET_LOCKPROXYFILE)
|
||||
.Const(_SC("FCNTL_SIZE_HINT"), SQLITE_FCNTL_SIZE_HINT)
|
||||
.Const(_SC("FCNTL_SYNC"), SQLITE_FCNTL_SYNC)
|
||||
.Const(_SC("FCNTL_SYNC_OMITTED"), SQLITE_FCNTL_SYNC_OMITTED)
|
||||
.Const(_SC("FCNTL_TEMPFILENAME"), SQLITE_FCNTL_TEMPFILENAME)
|
||||
.Const(_SC("FCNTL_TRACE"), SQLITE_FCNTL_TRACE)
|
||||
.Const(_SC("FCNTL_VFSNAME"), SQLITE_FCNTL_VFSNAME)
|
||||
.Const(_SC("FCNTL_WAL_BLOCK"), SQLITE_FCNTL_WAL_BLOCK)
|
||||
.Const(_SC("FCNTL_WIN32_AV_RETRY"), SQLITE_FCNTL_WIN32_AV_RETRY)
|
||||
.Const(_SC("FCNTL_WIN32_SET_HANDLE"), SQLITE_FCNTL_WIN32_SET_HANDLE)
|
||||
.Const(_SC("FCNTL_ZIPVFS"), SQLITE_FCNTL_ZIPVFS)
|
||||
.Const(_SC("FLOAT"), SQLITE_FLOAT)
|
||||
.Const(_SC("FORMAT"), SQLITE_FORMAT)
|
||||
.Const(_SC("FULL"), SQLITE_FULL)
|
||||
.Const(_SC("FUNCTION"), SQLITE_FUNCTION)
|
||||
.Const(_SC("IGNORE"), SQLITE_IGNORE)
|
||||
.Const(_SC("INDEX_CONSTRAINT_EQ"), SQLITE_INDEX_CONSTRAINT_EQ)
|
||||
.Const(_SC("INDEX_CONSTRAINT_GE"), SQLITE_INDEX_CONSTRAINT_GE)
|
||||
.Const(_SC("INDEX_CONSTRAINT_GT"), SQLITE_INDEX_CONSTRAINT_GT)
|
||||
.Const(_SC("INDEX_CONSTRAINT_LE"), SQLITE_INDEX_CONSTRAINT_LE)
|
||||
.Const(_SC("INDEX_CONSTRAINT_LT"), SQLITE_INDEX_CONSTRAINT_LT)
|
||||
.Const(_SC("INDEX_CONSTRAINT_MATCH"), SQLITE_INDEX_CONSTRAINT_MATCH)
|
||||
.Const(_SC("INDEX_SCAN_UNIQUE"), SQLITE_INDEX_SCAN_UNIQUE)
|
||||
.Const(_SC("INSERT"), SQLITE_INSERT)
|
||||
.Const(_SC("INTEGER"), SQLITE_INTEGER)
|
||||
.Const(_SC("INTERNAL"), SQLITE_INTERNAL)
|
||||
.Const(_SC("INTERRUPT"), SQLITE_INTERRUPT)
|
||||
.Const(_SC("IOCAP_ATOMIC"), SQLITE_IOCAP_ATOMIC)
|
||||
.Const(_SC("IOCAP_ATOMIC16K"), SQLITE_IOCAP_ATOMIC16K)
|
||||
.Const(_SC("IOCAP_ATOMIC1K"), SQLITE_IOCAP_ATOMIC1K)
|
||||
.Const(_SC("IOCAP_ATOMIC2K"), SQLITE_IOCAP_ATOMIC2K)
|
||||
.Const(_SC("IOCAP_ATOMIC32K"), SQLITE_IOCAP_ATOMIC32K)
|
||||
.Const(_SC("IOCAP_ATOMIC4K"), SQLITE_IOCAP_ATOMIC4K)
|
||||
.Const(_SC("IOCAP_ATOMIC512"), SQLITE_IOCAP_ATOMIC512)
|
||||
.Const(_SC("IOCAP_ATOMIC64K"), SQLITE_IOCAP_ATOMIC64K)
|
||||
.Const(_SC("IOCAP_ATOMIC8K"), SQLITE_IOCAP_ATOMIC8K)
|
||||
.Const(_SC("IOCAP_IMMUTABLE"), SQLITE_IOCAP_IMMUTABLE)
|
||||
.Const(_SC("IOCAP_POWERSAFE_OVERWRITE"), SQLITE_IOCAP_POWERSAFE_OVERWRITE)
|
||||
.Const(_SC("IOCAP_SAFE_APPEND"), SQLITE_IOCAP_SAFE_APPEND)
|
||||
.Const(_SC("IOCAP_SEQUENTIAL"), SQLITE_IOCAP_SEQUENTIAL)
|
||||
.Const(_SC("IOCAP_UNDELETABLE_WHEN_OPEN"), SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN)
|
||||
.Const(_SC("IOERR"), SQLITE_IOERR)
|
||||
.Const(_SC("IOERR_ACCESS"), SQLITE_IOERR_ACCESS)
|
||||
.Const(_SC("IOERR_BLOCKED"), SQLITE_IOERR_BLOCKED)
|
||||
.Const(_SC("IOERR_CHECKRESERVEDLOCK"), SQLITE_IOERR_CHECKRESERVEDLOCK)
|
||||
.Const(_SC("IOERR_CLOSE"), SQLITE_IOERR_CLOSE)
|
||||
.Const(_SC("IOERR_CONVPATH"), SQLITE_IOERR_CONVPATH)
|
||||
.Const(_SC("IOERR_DELETE"), SQLITE_IOERR_DELETE)
|
||||
.Const(_SC("IOERR_DELETE_NOENT"), SQLITE_IOERR_DELETE_NOENT)
|
||||
.Const(_SC("IOERR_DIR_CLOSE"), SQLITE_IOERR_DIR_CLOSE)
|
||||
.Const(_SC("IOERR_DIR_FSYNC"), SQLITE_IOERR_DIR_FSYNC)
|
||||
.Const(_SC("IOERR_FSTAT"), SQLITE_IOERR_FSTAT)
|
||||
.Const(_SC("IOERR_FSYNC"), SQLITE_IOERR_FSYNC)
|
||||
.Const(_SC("IOERR_GETTEMPPATH"), SQLITE_IOERR_GETTEMPPATH)
|
||||
.Const(_SC("IOERR_LOCK"), SQLITE_IOERR_LOCK)
|
||||
.Const(_SC("IOERR_MMAP"), SQLITE_IOERR_MMAP)
|
||||
.Const(_SC("IOERR_NOMEM"), SQLITE_IOERR_NOMEM)
|
||||
.Const(_SC("IOERR_RDLOCK"), SQLITE_IOERR_RDLOCK)
|
||||
.Const(_SC("IOERR_READ"), SQLITE_IOERR_READ)
|
||||
.Const(_SC("IOERR_SEEK"), SQLITE_IOERR_SEEK)
|
||||
.Const(_SC("IOERR_SHMLOCK"), SQLITE_IOERR_SHMLOCK)
|
||||
.Const(_SC("IOERR_SHMMAP"), SQLITE_IOERR_SHMMAP)
|
||||
.Const(_SC("IOERR_SHMOPEN"), SQLITE_IOERR_SHMOPEN)
|
||||
.Const(_SC("IOERR_SHMSIZE"), SQLITE_IOERR_SHMSIZE)
|
||||
.Const(_SC("IOERR_SHORT_READ"), SQLITE_IOERR_SHORT_READ)
|
||||
.Const(_SC("IOERR_TRUNCATE"), SQLITE_IOERR_TRUNCATE)
|
||||
.Const(_SC("IOERR_UNLOCK"), SQLITE_IOERR_UNLOCK)
|
||||
.Const(_SC("IOERR_VNODE"), SQLITE_IOERR_VNODE)
|
||||
.Const(_SC("IOERR_WRITE"), SQLITE_IOERR_WRITE)
|
||||
.Const(_SC("LIMIT_ATTACHED"), SQLITE_LIMIT_ATTACHED)
|
||||
.Const(_SC("LIMIT_COLUMN"), SQLITE_LIMIT_COLUMN)
|
||||
.Const(_SC("LIMIT_COMPOUND_SELECT"), SQLITE_LIMIT_COMPOUND_SELECT)
|
||||
.Const(_SC("LIMIT_EXPR_DEPTH"), SQLITE_LIMIT_EXPR_DEPTH)
|
||||
.Const(_SC("LIMIT_FUNCTION_ARG"), SQLITE_LIMIT_FUNCTION_ARG)
|
||||
.Const(_SC("LIMIT_LENGTH"), SQLITE_LIMIT_LENGTH)
|
||||
.Const(_SC("LIMIT_LIKE_PATTERN_LENGTH"), SQLITE_LIMIT_LIKE_PATTERN_LENGTH)
|
||||
.Const(_SC("LIMIT_SQL_LENGTH"), SQLITE_LIMIT_SQL_LENGTH)
|
||||
.Const(_SC("LIMIT_TRIGGER_DEPTH"), SQLITE_LIMIT_TRIGGER_DEPTH)
|
||||
.Const(_SC("LIMIT_VARIABLE_NUMBER"), SQLITE_LIMIT_VARIABLE_NUMBER)
|
||||
.Const(_SC("LIMIT_VDBE_OP"), SQLITE_LIMIT_VDBE_OP)
|
||||
.Const(_SC("LIMIT_WORKER_THREADS"), SQLITE_LIMIT_WORKER_THREADS)
|
||||
.Const(_SC("LOCKED"), SQLITE_LOCKED)
|
||||
.Const(_SC("LOCKED_SHAREDCACHE"), SQLITE_LOCKED_SHAREDCACHE)
|
||||
.Const(_SC("LOCK_EXCLUSIVE"), SQLITE_LOCK_EXCLUSIVE)
|
||||
.Const(_SC("LOCK_NONE"), SQLITE_LOCK_NONE)
|
||||
.Const(_SC("LOCK_PENDING"), SQLITE_LOCK_PENDING)
|
||||
.Const(_SC("LOCK_RESERVED"), SQLITE_LOCK_RESERVED)
|
||||
.Const(_SC("LOCK_SHARED"), SQLITE_LOCK_SHARED)
|
||||
.Const(_SC("MISMATCH"), SQLITE_MISMATCH)
|
||||
.Const(_SC("MISUSE"), SQLITE_MISUSE)
|
||||
.Const(_SC("MUTEX_FAST"), SQLITE_MUTEX_FAST)
|
||||
.Const(_SC("MUTEX_RECURSIVE"), SQLITE_MUTEX_RECURSIVE)
|
||||
.Const(_SC("MUTEX_STATIC_APP1"), SQLITE_MUTEX_STATIC_APP1)
|
||||
.Const(_SC("MUTEX_STATIC_APP2"), SQLITE_MUTEX_STATIC_APP2)
|
||||
.Const(_SC("MUTEX_STATIC_APP3"), SQLITE_MUTEX_STATIC_APP3)
|
||||
.Const(_SC("MUTEX_STATIC_LRU"), SQLITE_MUTEX_STATIC_LRU)
|
||||
.Const(_SC("MUTEX_STATIC_LRU2"), SQLITE_MUTEX_STATIC_LRU2)
|
||||
.Const(_SC("MUTEX_STATIC_MASTER"), SQLITE_MUTEX_STATIC_MASTER)
|
||||
.Const(_SC("MUTEX_STATIC_MEM"), SQLITE_MUTEX_STATIC_MEM)
|
||||
.Const(_SC("MUTEX_STATIC_MEM2"), SQLITE_MUTEX_STATIC_MEM2)
|
||||
.Const(_SC("MUTEX_STATIC_OPEN"), SQLITE_MUTEX_STATIC_OPEN)
|
||||
.Const(_SC("MUTEX_STATIC_PMEM"), SQLITE_MUTEX_STATIC_PMEM)
|
||||
.Const(_SC("MUTEX_STATIC_PRNG"), SQLITE_MUTEX_STATIC_PRNG)
|
||||
.Const(_SC("MUTEX_STATIC_VFS1"), SQLITE_MUTEX_STATIC_VFS1)
|
||||
.Const(_SC("MUTEX_STATIC_VFS2"), SQLITE_MUTEX_STATIC_VFS2)
|
||||
.Const(_SC("MUTEX_STATIC_VFS3"), SQLITE_MUTEX_STATIC_VFS3)
|
||||
.Const(_SC("NOLFS"), SQLITE_NOLFS)
|
||||
.Const(_SC("NOMEM"), SQLITE_NOMEM)
|
||||
.Const(_SC("NOTADB"), SQLITE_NOTADB)
|
||||
.Const(_SC("NOTFOUND"), SQLITE_NOTFOUND)
|
||||
.Const(_SC("NOTICE"), SQLITE_NOTICE)
|
||||
.Const(_SC("NOTICE_RECOVER_ROLLBACK"), SQLITE_NOTICE_RECOVER_ROLLBACK)
|
||||
.Const(_SC("NOTICE_RECOVER_WAL"), SQLITE_NOTICE_RECOVER_WAL)
|
||||
.Const(_SC("NULL"), SQLITE_NULL)
|
||||
.Const(_SC("OK"), SQLITE_OK)
|
||||
.Const(_SC("OPEN_AUTOPROXY"), SQLITE_OPEN_AUTOPROXY)
|
||||
.Const(_SC("OPEN_CREATE"), SQLITE_OPEN_CREATE)
|
||||
.Const(_SC("OPEN_DELETEONCLOSE"), SQLITE_OPEN_DELETEONCLOSE)
|
||||
.Const(_SC("OPEN_EXCLUSIVE"), SQLITE_OPEN_EXCLUSIVE)
|
||||
.Const(_SC("OPEN_FULLMUTEX"), SQLITE_OPEN_FULLMUTEX)
|
||||
.Const(_SC("OPEN_MAIN_DB"), SQLITE_OPEN_MAIN_DB)
|
||||
.Const(_SC("OPEN_MAIN_JOURNAL"), SQLITE_OPEN_MAIN_JOURNAL)
|
||||
.Const(_SC("OPEN_MASTER_JOURNAL"), SQLITE_OPEN_MASTER_JOURNAL)
|
||||
.Const(_SC("OPEN_MEMORY"), SQLITE_OPEN_MEMORY)
|
||||
.Const(_SC("OPEN_NOMUTEX"), SQLITE_OPEN_NOMUTEX)
|
||||
.Const(_SC("OPEN_PRIVATECACHE"), SQLITE_OPEN_PRIVATECACHE)
|
||||
.Const(_SC("OPEN_READONLY"), SQLITE_OPEN_READONLY)
|
||||
.Const(_SC("OPEN_READWRITE"), SQLITE_OPEN_READWRITE)
|
||||
.Const(_SC("OPEN_SHAREDCACHE"), SQLITE_OPEN_SHAREDCACHE)
|
||||
.Const(_SC("OPEN_SUBJOURNAL"), SQLITE_OPEN_SUBJOURNAL)
|
||||
.Const(_SC("OPEN_TEMP_DB"), SQLITE_OPEN_TEMP_DB)
|
||||
.Const(_SC("OPEN_TEMP_JOURNAL"), SQLITE_OPEN_TEMP_JOURNAL)
|
||||
.Const(_SC("OPEN_TRANSIENT_DB"), SQLITE_OPEN_TRANSIENT_DB)
|
||||
.Const(_SC("OPEN_URI"), SQLITE_OPEN_URI)
|
||||
.Const(_SC("OPEN_WAL"), SQLITE_OPEN_WAL)
|
||||
.Const(_SC("PERM"), SQLITE_PERM)
|
||||
.Const(_SC("PRAGMA"), SQLITE_PRAGMA)
|
||||
.Const(_SC("PROTOCOL"), SQLITE_PROTOCOL)
|
||||
.Const(_SC("RANGE"), SQLITE_RANGE)
|
||||
.Const(_SC("READ"), SQLITE_READ)
|
||||
.Const(_SC("READONLY"), SQLITE_READONLY)
|
||||
.Const(_SC("READONLY_CANTLOCK"), SQLITE_READONLY_CANTLOCK)
|
||||
.Const(_SC("READONLY_DBMOVED"), SQLITE_READONLY_DBMOVED)
|
||||
.Const(_SC("READONLY_RECOVERY"), SQLITE_READONLY_RECOVERY)
|
||||
.Const(_SC("READONLY_ROLLBACK"), SQLITE_READONLY_ROLLBACK)
|
||||
.Const(_SC("RECURSIVE"), SQLITE_RECURSIVE)
|
||||
.Const(_SC("REINDEX"), SQLITE_REINDEX)
|
||||
.Const(_SC("REPLACE"), SQLITE_REPLACE)
|
||||
.Const(_SC("ROLLBACK"), SQLITE_ROLLBACK)
|
||||
.Const(_SC("ROW"), SQLITE_ROW)
|
||||
.Const(_SC("SAVEPOINT"), SQLITE_SAVEPOINT)
|
||||
.Const(_SC("SCANSTAT_EST"), SQLITE_SCANSTAT_EST)
|
||||
.Const(_SC("SCANSTAT_EXPLAIN"), SQLITE_SCANSTAT_EXPLAIN)
|
||||
.Const(_SC("SCANSTAT_NAME"), SQLITE_SCANSTAT_NAME)
|
||||
.Const(_SC("SCANSTAT_NLOOP"), SQLITE_SCANSTAT_NLOOP)
|
||||
.Const(_SC("SCANSTAT_NVISIT"), SQLITE_SCANSTAT_NVISIT)
|
||||
.Const(_SC("SCANSTAT_SELECTID"), SQLITE_SCANSTAT_SELECTID)
|
||||
.Const(_SC("SCHEMA"), SQLITE_SCHEMA)
|
||||
.Const(_SC("SELECT"), SQLITE_SELECT)
|
||||
.Const(_SC("SHM_EXCLUSIVE"), SQLITE_SHM_EXCLUSIVE)
|
||||
.Const(_SC("SHM_LOCK"), SQLITE_SHM_LOCK)
|
||||
.Const(_SC("SHM_NLOCK"), SQLITE_SHM_NLOCK)
|
||||
.Const(_SC("SHM_SHARED"), SQLITE_SHM_SHARED)
|
||||
.Const(_SC("SHM_UNLOCK"), SQLITE_SHM_UNLOCK)
|
||||
.Const(_SC("SOURCE_ID"), SQLITE_SOURCE_ID)
|
||||
.Const(_SC("STATUS_MALLOC_COUNT"), SQLITE_STATUS_MALLOC_COUNT)
|
||||
.Const(_SC("STATUS_MALLOC_SIZE"), SQLITE_STATUS_MALLOC_SIZE)
|
||||
.Const(_SC("STATUS_MEMORY_USED"), SQLITE_STATUS_MEMORY_USED)
|
||||
.Const(_SC("STATUS_PAGECACHE_OVERFLOW"), SQLITE_STATUS_PAGECACHE_OVERFLOW)
|
||||
.Const(_SC("STATUS_PAGECACHE_SIZE"), SQLITE_STATUS_PAGECACHE_SIZE)
|
||||
.Const(_SC("STATUS_PAGECACHE_USED"), SQLITE_STATUS_PAGECACHE_USED)
|
||||
.Const(_SC("STATUS_PARSER_STACK"), SQLITE_STATUS_PARSER_STACK)
|
||||
.Const(_SC("STATUS_SCRATCH_OVERFLOW"), SQLITE_STATUS_SCRATCH_OVERFLOW)
|
||||
.Const(_SC("STATUS_SCRATCH_SIZE"), SQLITE_STATUS_SCRATCH_SIZE)
|
||||
.Const(_SC("STATUS_SCRATCH_USED"), SQLITE_STATUS_SCRATCH_USED)
|
||||
.Const(_SC("STMTSTATUS_AUTOINDEX"), SQLITE_STMTSTATUS_AUTOINDEX)
|
||||
.Const(_SC("STMTSTATUS_FULLSCAN_STEP"), SQLITE_STMTSTATUS_FULLSCAN_STEP)
|
||||
.Const(_SC("STMTSTATUS_SORT"), SQLITE_STMTSTATUS_SORT)
|
||||
.Const(_SC("STMTSTATUS_VM_STEP"), SQLITE_STMTSTATUS_VM_STEP)
|
||||
.Const(_SC("SYNC_DATAONLY"), SQLITE_SYNC_DATAONLY)
|
||||
.Const(_SC("SYNC_FULL"), SQLITE_SYNC_FULL)
|
||||
.Const(_SC("SYNC_NORMAL"), SQLITE_SYNC_NORMAL)
|
||||
.Const(_SC("TESTCTRL_ALWAYS"), SQLITE_TESTCTRL_ALWAYS)
|
||||
.Const(_SC("TESTCTRL_ASSERT"), SQLITE_TESTCTRL_ASSERT)
|
||||
.Const(_SC("TESTCTRL_BENIGN_MALLOC_HOOKS"), SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS)
|
||||
.Const(_SC("TESTCTRL_BITVEC_TEST"), SQLITE_TESTCTRL_BITVEC_TEST)
|
||||
.Const(_SC("TESTCTRL_BYTEORDER"), SQLITE_TESTCTRL_BYTEORDER)
|
||||
.Const(_SC("TESTCTRL_EXPLAIN_STMT"), SQLITE_TESTCTRL_EXPLAIN_STMT)
|
||||
.Const(_SC("TESTCTRL_FAULT_INSTALL"), SQLITE_TESTCTRL_FAULT_INSTALL)
|
||||
.Const(_SC("TESTCTRL_FIRST"), SQLITE_TESTCTRL_FIRST)
|
||||
.Const(_SC("TESTCTRL_IMPOSTER"), SQLITE_TESTCTRL_IMPOSTER)
|
||||
.Const(_SC("TESTCTRL_ISINIT"), SQLITE_TESTCTRL_ISINIT)
|
||||
.Const(_SC("TESTCTRL_ISKEYWORD"), SQLITE_TESTCTRL_ISKEYWORD)
|
||||
.Const(_SC("TESTCTRL_LAST"), SQLITE_TESTCTRL_LAST)
|
||||
.Const(_SC("TESTCTRL_LOCALTIME_FAULT"), SQLITE_TESTCTRL_LOCALTIME_FAULT)
|
||||
.Const(_SC("TESTCTRL_NEVER_CORRUPT"), SQLITE_TESTCTRL_NEVER_CORRUPT)
|
||||
.Const(_SC("TESTCTRL_OPTIMIZATIONS"), SQLITE_TESTCTRL_OPTIMIZATIONS)
|
||||
.Const(_SC("TESTCTRL_PENDING_BYTE"), SQLITE_TESTCTRL_PENDING_BYTE)
|
||||
.Const(_SC("TESTCTRL_PRNG_RESET"), SQLITE_TESTCTRL_PRNG_RESET)
|
||||
.Const(_SC("TESTCTRL_PRNG_RESTORE"), SQLITE_TESTCTRL_PRNG_RESTORE)
|
||||
.Const(_SC("TESTCTRL_PRNG_SAVE"), SQLITE_TESTCTRL_PRNG_SAVE)
|
||||
.Const(_SC("TESTCTRL_RESERVE"), SQLITE_TESTCTRL_RESERVE)
|
||||
.Const(_SC("TESTCTRL_SCRATCHMALLOC"), SQLITE_TESTCTRL_SCRATCHMALLOC)
|
||||
.Const(_SC("TESTCTRL_SORTER_MMAP"), SQLITE_TESTCTRL_SORTER_MMAP)
|
||||
.Const(_SC("TESTCTRL_VDBE_COVERAGE"), SQLITE_TESTCTRL_VDBE_COVERAGE)
|
||||
.Const(_SC("TEXT"), SQLITE_TEXT)
|
||||
.Const(_SC("TOOBIG"), SQLITE_TOOBIG)
|
||||
.Const(_SC("TRANSACTION"), SQLITE_TRANSACTION)
|
||||
.Const(_SC("UPDATE"), SQLITE_UPDATE)
|
||||
.Const(_SC("UTF16"), SQLITE_UTF16)
|
||||
.Const(_SC("UTF16BE"), SQLITE_UTF16BE)
|
||||
.Const(_SC("UTF16LE"), SQLITE_UTF16LE)
|
||||
.Const(_SC("UTF16_ALIGNED"), SQLITE_UTF16_ALIGNED)
|
||||
.Const(_SC("UTF8"), SQLITE_UTF8)
|
||||
.Const(_SC("VERSION"), SQLITE_VERSION)
|
||||
.Const(_SC("VERSION_NUMBER"), SQLITE_VERSION_NUMBER)
|
||||
.Const(_SC("VTAB_CONSTRAINT_SUPPORT"), SQLITE_VTAB_CONSTRAINT_SUPPORT)
|
||||
.Const(_SC("WARNING"), SQLITE_WARNING)
|
||||
.Const(_SC("WARNING_AUTOINDEX"), SQLITE_WARNING_AUTOINDEX)
|
||||
);
|
||||
*/
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
void OutputMessageImpl(const char * msg, va_list args)
|
||||
{
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
HANDLE hstdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
CONSOLE_SCREEN_BUFFER_INFO csb_before;
|
||||
GetConsoleScreenBufferInfo( hstdout, &csb_before);
|
||||
SetConsoleTextAttribute(hstdout, FOREGROUND_GREEN);
|
||||
printf("[SQMOD] ");
|
||||
|
||||
SetConsoleTextAttribute(hstdout, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY);
|
||||
vprintf(msg, args);
|
||||
puts("");
|
||||
|
||||
SetConsoleTextAttribute(hstdout, csb_before.wAttributes);
|
||||
#else
|
||||
printf("%c[0;32m[SQMOD]%c[0;37m", 27, 27, msg);
|
||||
vprintf(msg, args);
|
||||
puts("");
|
||||
#endif
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
void OutputErrorImpl(const char * msg, va_list args)
|
||||
{
|
||||
#if defined(WIN32) || defined(_WIN32)
|
||||
HANDLE hstdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
CONSOLE_SCREEN_BUFFER_INFO csb_before;
|
||||
GetConsoleScreenBufferInfo( hstdout, &csb_before);
|
||||
SetConsoleTextAttribute(hstdout, FOREGROUND_RED | FOREGROUND_INTENSITY);
|
||||
printf("[SQMOD] ");
|
||||
|
||||
SetConsoleTextAttribute(hstdout, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY);
|
||||
vprintf(msg, args);
|
||||
puts("");
|
||||
|
||||
SetConsoleTextAttribute(hstdout, csb_before.wAttributes);
|
||||
#else
|
||||
printf("%c[0;32m[SQMOD]%c[0;37m", 27, 27, msg);
|
||||
vprintf(msg, args);
|
||||
puts("");
|
||||
#endif
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
void OutputDebug(const char * msg, ...)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
// Initialize the arguments list
|
||||
va_list args;
|
||||
va_start(args, msg);
|
||||
// Call the output function
|
||||
OutputMessageImpl(msg, args);
|
||||
// Finalize the arguments list
|
||||
va_end(args);
|
||||
#else
|
||||
SQMOD_UNUSED_VAR(msg);
|
||||
#endif
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
void OutputMessage(const char * msg, ...)
|
||||
{
|
||||
// Initialize the arguments list
|
||||
va_list args;
|
||||
va_start(args, msg);
|
||||
// Call the output function
|
||||
OutputMessageImpl(msg, args);
|
||||
// Finalize the arguments list
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
void OutputError(const char * msg, ...)
|
||||
{
|
||||
// Initialize the arguments list
|
||||
va_list args;
|
||||
va_start(args, msg);
|
||||
// Call the output function
|
||||
OutputErrorImpl(msg, args);
|
||||
// Finalize the arguments list
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
SQMOD_API_EXPORT unsigned int VcmpPluginInit(PluginFuncs* functions, PluginCallbacks* callbacks, PluginInfo* info)
|
||||
{
|
||||
using namespace SqMod;
|
||||
// Output plugin header
|
||||
puts("");
|
||||
OutputMessage("--------------------------------------------------------------------");
|
||||
OutputMessage("Plugin: %s", SQSQLITE_NAME);
|
||||
OutputMessage("Author: %s", SQSQLITE_AUTHOR);
|
||||
OutputMessage("Legal: %s", SQSQLITE_COPYRIGHT);
|
||||
OutputMessage("--------------------------------------------------------------------");
|
||||
puts("");
|
||||
// Attempt to find the host plugin ID
|
||||
int host_plugin_id = functions->FindPlugin((char *)(SQMOD_HOST_NAME));
|
||||
// See if our plugin was loaded after the host plugin
|
||||
if (host_plugin_id < 0)
|
||||
{
|
||||
OutputError("%s could find the host plugin", SQSQLITE_NAME);
|
||||
// Don't load!
|
||||
return SQMOD_FAILURE;
|
||||
}
|
||||
// Should never reach this point but just in case
|
||||
else if (host_plugin_id > (info->nPluginId))
|
||||
{
|
||||
OutputError("%s loaded after the host plugin", SQSQLITE_NAME);
|
||||
// Don't load!
|
||||
return SQMOD_FAILURE;
|
||||
}
|
||||
// Store server proxies
|
||||
_Func = functions;
|
||||
_Clbk = callbacks;
|
||||
_Info = info;
|
||||
// Assign plugin information
|
||||
_Info->uPluginVer = SQSQLITE_VERSION;
|
||||
strcpy(_Info->szName, SQSQLITE_HOST_NAME);
|
||||
// Bind callbacks
|
||||
BindCallbacks();
|
||||
// Notify that the plugin was successfully loaded
|
||||
OutputMessage("Successfully loaded %s", SQSQLITE_NAME);
|
||||
// Dummy spacing
|
||||
puts("");
|
||||
// Done!
|
||||
return SQMOD_SUCCESS;
|
||||
}
|
41
modules/sqlite/Module.hpp
Normal file
41
modules/sqlite/Module.hpp
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef _SQSQLITE_MODULE_HPP_
|
||||
#define _SQSQLITE_MODULE_HPP_
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "SqMod.h"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Proxies to comunicate with the server.
|
||||
*/
|
||||
extern PluginFuncs* _Func;
|
||||
extern PluginCallbacks* _Clbk;
|
||||
extern PluginInfo* _Info;
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Proxies to comunicate with the Squirrel plugin.
|
||||
*/
|
||||
extern HSQAPI _SqAPI;
|
||||
extern HSQEXPORTS _SqMod;
|
||||
extern HSQUIRRELVM _SqVM;
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Output a message only if the _DEBUG was defined.
|
||||
*/
|
||||
void OutputDebug(const char * msg, ...);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Output a formatted user message to the console.
|
||||
*/
|
||||
void OutputMessage(const char * msg, ...);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Output a formatted error message to the console.
|
||||
*/
|
||||
void OutputError(const char * msg, ...);
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
#endif // _SQSQLITE_MODULE_HPP_
|
1139
modules/sqlite/Statement.cpp
Normal file
1139
modules/sqlite/Statement.cpp
Normal file
File diff suppressed because it is too large
Load Diff
499
modules/sqlite/Statement.hpp
Normal file
499
modules/sqlite/Statement.hpp
Normal file
@ -0,0 +1,499 @@
|
||||
#ifndef _SQSQLITE_STATEMENT_HPP
|
||||
#define _SQSQLITE_STATEMENT_HPP
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Common.hpp"
|
||||
#include "SqAPI.h"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Class used to manage an SQLite statement.
|
||||
*/
|
||||
class Statement
|
||||
{
|
||||
private:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
StmtHnd m_Handle; /* The handle to the managed database statement resource. */
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
static CSStr s_BadParamI; /* Error message when failed to bind value to parameter index. */
|
||||
static CSStr s_BadParamS; /* Error message when failed to bind value to parameter name. */
|
||||
|
||||
protected:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Validate the statement reference and throw an error if invalid.
|
||||
*/
|
||||
bool Validate() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Validate the statement reference and index, and throw an error if they're invalid.
|
||||
*/
|
||||
bool ValidateIndex(Int32 idx) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Validate the statement reference and row, and throw an error if they're invalid.
|
||||
*/
|
||||
bool RowAvailable() const;
|
||||
|
||||
public:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Default constructor.
|
||||
*/
|
||||
Statement();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Construct a statement under the specified connection using the specified string.
|
||||
*/
|
||||
Statement(const ConnHnd & connection, CSStr query);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Construct a statement under the specified connection using the specified string.
|
||||
*/
|
||||
Statement(const Connection & connection, CSStr query);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Direct handle constructor.
|
||||
*/
|
||||
Statement(const StmtHnd & h)
|
||||
: m_Handle(h)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor.
|
||||
*/
|
||||
Statement(const Statement & o)
|
||||
: m_Handle(o.m_Handle)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Destructor.
|
||||
*/
|
||||
~Statement()
|
||||
{
|
||||
/* Let the reference manager destroy the statement when necessary. */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy assignment operator.
|
||||
*/
|
||||
Statement & operator = (const Statement & o)
|
||||
{
|
||||
m_Handle = o.m_Handle;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Perform an equality comparison between two connections.
|
||||
*/
|
||||
bool operator == (const Statement & o) const
|
||||
{
|
||||
return (m_Handle.m_Hnd == o.m_Handle.m_Hnd);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Perform an inequality comparison between two connections.
|
||||
*/
|
||||
bool operator != (const Statement & o) const
|
||||
{
|
||||
return (m_Handle.m_Hnd != o.m_Handle.m_Hnd);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Implicit conversion to the raw connection handle.
|
||||
*/
|
||||
operator sqlite3_stmt * ()
|
||||
{
|
||||
return (sqlite3_stmt *)m_Handle;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Implicit conversion to the raw connection handle.
|
||||
*/
|
||||
operator sqlite3_stmt * () const
|
||||
{
|
||||
return (sqlite3_stmt *)m_Handle;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to compare two instances of this type.
|
||||
*/
|
||||
Int32 Cmp(const Statement & o) const
|
||||
{
|
||||
if (m_Handle.m_Hnd == o.m_Handle.m_Hnd)
|
||||
return 0;
|
||||
else if (m_Handle.m_Hnd > o.m_Handle.m_Hnd)
|
||||
return 1;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to convert an instance of this type to a string.
|
||||
*/
|
||||
CSStr ToString() const
|
||||
{
|
||||
// Validate the handle
|
||||
if (m_Handle)
|
||||
return m_Handle->mQuery.c_str();
|
||||
// Request failed
|
||||
return _SC("");
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to retrieve the name from instances of this type.
|
||||
*/
|
||||
static SQInteger Typename(HSQUIRRELVM vm);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* See whether this statement is valid.
|
||||
*/
|
||||
bool IsValid() const
|
||||
{
|
||||
return (bool)m_Handle;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the associated statement handle.
|
||||
*/
|
||||
const StmtHnd & GetHandle() const
|
||||
{
|
||||
return m_Handle;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Return the number of active references to this statement handle.
|
||||
*/
|
||||
Uint32 GetRefCount() const
|
||||
{
|
||||
return m_Handle.Count();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the associated database connection.
|
||||
*/
|
||||
Connection GetConnection() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Release the reference to the associated database statement.
|
||||
*/
|
||||
void Release()
|
||||
{
|
||||
m_Handle.Drop();
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the last received status code.
|
||||
*/
|
||||
Int32 GetStatus() const
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate())
|
||||
return m_Handle->mStatus;
|
||||
// Request failed
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Return the numeric result code for the most recent failed API call (if any).
|
||||
*/
|
||||
Int32 GetErrorCode() const
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate())
|
||||
return m_Handle.ErrNo();
|
||||
// Request failed
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Return the extended numeric result code for the most recent failed API call (if any).
|
||||
*/
|
||||
Int32 GetExtendedErrorCode() const
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate())
|
||||
return m_Handle.ExErrNo();
|
||||
// Request failed
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the message of the last received error code.
|
||||
*/
|
||||
CSStr GetErrStr() const
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate())
|
||||
return m_Handle.ErrStr();
|
||||
// Request failed
|
||||
return _SC("");
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Return the last error message associated with this database connection.
|
||||
*/
|
||||
CSStr GetErrMsg() const
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate())
|
||||
return m_Handle.ErrMsg();
|
||||
// Request failed
|
||||
return _SC("");
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the amount of requested columns.
|
||||
*/
|
||||
Int32 GetColumns() const
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate())
|
||||
return m_Handle->mColumns;
|
||||
// Request failed
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the query string used to create this statement.
|
||||
*/
|
||||
CSStr GetQuery() const
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate())
|
||||
return m_Handle->mQuery.c_str();
|
||||
// Request failed
|
||||
return _SC("");
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* See if the last step retrieved a valid row.
|
||||
*/
|
||||
bool GetGood() const
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate())
|
||||
return m_Handle->mGood;
|
||||
// Request failed
|
||||
return false;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* See if there are any steps left.
|
||||
*/
|
||||
bool GetDone() const
|
||||
{
|
||||
// Validate the handle
|
||||
if (Validate())
|
||||
return m_Handle->mDone;
|
||||
// Request failed
|
||||
return false;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Reset the statement back to its initial position to be stepped again.
|
||||
*/
|
||||
void Reset();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Clear any values binded to this statement.
|
||||
*/
|
||||
void Clear();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Execute this statement and don't expect any rows to be returned.
|
||||
*/
|
||||
Int32 Exec();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Step the statement and expect a row to be returned.
|
||||
*/
|
||||
bool Step();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to bind the values from an array starting at the specified index.
|
||||
*/
|
||||
void IndexBindA(Int32 idx, Array & arr);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to bind the a integer value at the the specified parameter index.
|
||||
*/
|
||||
void IndexBindI(Int32 idx, Int32 value);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to bind the a long integer value at the the specified parameter index.
|
||||
*/
|
||||
void IndexBindL(Int32 idx, Object & value);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to bind the a native integer value at the the specified parameter index.
|
||||
*/
|
||||
void IndexBindV(Int32 idx, SQInteger value);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to bind the a floating point value at the the specified parameter index.
|
||||
*/
|
||||
void IndexBindF(Int32 idx, SQFloat value);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to bind the a string value at the the specified parameter index.
|
||||
*/
|
||||
void IndexBindS(Int32 idx, CSStr value);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to bind the a boolean value at the the specified parameter index.
|
||||
*/
|
||||
void IndexBindB(Int32 idx, bool value);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to bind the a null value at the the specified parameter index.
|
||||
*/
|
||||
void IndexBindN(Int32 idx);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to bind the values from an associative container.
|
||||
*/
|
||||
void NameBindT(Table & tbl);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to bind the a integer value at the specified parameter name.
|
||||
*/
|
||||
void NameBindI(CSStr name, Int32 value);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to bind the a long integer value at the specified parameter name.
|
||||
*/
|
||||
void NameBindL(CSStr name, Object & value);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to bind the a native integer value at the specified parameter name.
|
||||
*/
|
||||
void NameBindV(CSStr name, SQInteger value);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to bind the a floating point value at the specified parameter name.
|
||||
*/
|
||||
void NameBindF(CSStr name, SQFloat value);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to bind the a string value at the specified parameter name.
|
||||
*/
|
||||
void NameBindS(CSStr name, CSStr value);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to bind the a boolean value at the specified parameter name.
|
||||
*/
|
||||
void NameBindB(CSStr name, bool value);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to bind the a null value at the specified parameter name.
|
||||
*/
|
||||
void NameBindN(CSStr name);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to bind the specified value at the specified parameter index.
|
||||
*/
|
||||
void IndexBind(Int32 idx, Object & value);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to bind the specified value at the specified parameter name.
|
||||
*/
|
||||
void NameBind(CSStr name, Object & value);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Fetch the value at the specifie column index.
|
||||
*/
|
||||
Object FetchColumnIndex(Int32 idx) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Fetch the value at the specifie column name.
|
||||
*/
|
||||
Object FetchColumnName(CSStr name) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Fetch the row as an array container.
|
||||
*/
|
||||
Array FetchArray() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Fetch the row as an array container.
|
||||
*/
|
||||
Array FetchArray(Int32 min) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Fetch the row as an array container.
|
||||
*/
|
||||
Array FetchArray(Int32 min, Int32 max) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Fetch the row as an associative container.
|
||||
*/
|
||||
Table FetchTable() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Fetch the row as an associative container.
|
||||
*/
|
||||
Table FetchTable(Int32 min) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Fetch the row as an associative container.
|
||||
*/
|
||||
Table FetchTable(Int32 min, Int32 max) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Check whether a specific index is in range.
|
||||
*/
|
||||
bool CheckIndex(Int32 idx) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Check whether the specified column is null.
|
||||
*/
|
||||
bool IsColumnNull(Int32 idx) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the column index associated with the specified name.
|
||||
*/
|
||||
Int32 GetColumnIndex(CSStr name) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the column name associated with the specified index.
|
||||
*/
|
||||
CSStr GetColumnName(Int32 idx) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the column origin name if the library was compiled with such feature.
|
||||
*/
|
||||
CSStr GetColumnOriginName(Int32 idx) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the type identifier of the column associated with the specified index.
|
||||
*/
|
||||
Int32 GetColumnType(Int32 idx) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the size in bytes of the column associated with the specified index.
|
||||
*/
|
||||
Int32 GetColumnBytes(Int32 idx) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the column with the specified index.
|
||||
*/
|
||||
Column GetColumnByIndex(Int32 idx) const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the column with the specified name.
|
||||
*/
|
||||
Column GetColumnByName(CSStr name) const;
|
||||
};
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
#endif // _SQSQLITE_STATEMENT_HPP
|
Loading…
Reference in New Issue
Block a user