mirror of
				https://github.com/VCMP-SqMod/SqMod.git
				synced 2025-11-04 00:07:19 +01:00 
			
		
		
		
	Integrate SQLite module.
Integrate the SQLite module into the host plugin and get it to compile.
This commit is contained in:
		@@ -16,8 +16,8 @@
 | 
			
		||||
#endif // SQMOD_OS_WINDOWS
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Library/Numeric/LongInt.hpp"
 | 
			
		||||
#include <sqstdstring.h>
 | 
			
		||||
#include "Library/Numeric/LongInt.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
@@ -812,276 +812,4 @@ SQFloat PopStackFloat(HSQUIRRELVM vm, SQInteger idx)
 | 
			
		||||
    return 0.0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Int64 PopStackSLong(HSQUIRRELVM vm, SQInteger idx)
 | 
			
		||||
{
 | 
			
		||||
    // Identify which type must be extracted
 | 
			
		||||
    switch (sq_gettype(vm, idx))
 | 
			
		||||
    {
 | 
			
		||||
        case OT_INTEGER:
 | 
			
		||||
        {
 | 
			
		||||
            SQInteger val;
 | 
			
		||||
            sq_getinteger(vm, idx, &val);
 | 
			
		||||
            return static_cast< Int64 >(val);
 | 
			
		||||
        } break;
 | 
			
		||||
        case OT_FLOAT:
 | 
			
		||||
        {
 | 
			
		||||
            SQFloat val;
 | 
			
		||||
            sq_getfloat(vm, idx, &val);
 | 
			
		||||
            return ConvTo< Int64 >::From(val);
 | 
			
		||||
        } break;
 | 
			
		||||
        case OT_BOOL:
 | 
			
		||||
        {
 | 
			
		||||
            SQBool val;
 | 
			
		||||
            sq_getbool(vm, idx, &val);
 | 
			
		||||
            return static_cast< Int64 >(val);
 | 
			
		||||
        } break;
 | 
			
		||||
        case OT_STRING:
 | 
			
		||||
        {
 | 
			
		||||
            CSStr val = nullptr;
 | 
			
		||||
            // Attempt to retrieve and convert the string
 | 
			
		||||
            if (SQ_SUCCEEDED(sq_getstring(vm, idx, &val)) && val != nullptr && *val != '\0')
 | 
			
		||||
            {
 | 
			
		||||
                return std::strtoll(val, nullptr, 10);
 | 
			
		||||
            }
 | 
			
		||||
        } break;
 | 
			
		||||
        case OT_ARRAY:
 | 
			
		||||
        case OT_TABLE:
 | 
			
		||||
        case OT_CLASS:
 | 
			
		||||
        case OT_USERDATA:
 | 
			
		||||
        {
 | 
			
		||||
            return static_cast< Int64 >(sq_getsize(vm, idx));
 | 
			
		||||
        } break;
 | 
			
		||||
        case OT_INSTANCE:
 | 
			
		||||
        {
 | 
			
		||||
            // Attempt to treat the value as a signed long instance
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                return Var< const SLongInt & >(vm, idx).value.GetNum();
 | 
			
		||||
            }
 | 
			
		||||
            catch (...)
 | 
			
		||||
            {
 | 
			
		||||
                // Just ignore it...
 | 
			
		||||
            }
 | 
			
		||||
            // Attempt to treat the value as a unsigned long instance
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                return ConvTo< Int64 >::From(Var< const ULongInt & >(vm, idx).value.GetNum());
 | 
			
		||||
            }
 | 
			
		||||
            catch (...)
 | 
			
		||||
            {
 | 
			
		||||
                // Just ignore it...
 | 
			
		||||
            }
 | 
			
		||||
            // Attempt to get the size of the instance as a fall back
 | 
			
		||||
            return static_cast< Int64 >(sq_getsize(vm, idx));
 | 
			
		||||
        } break;
 | 
			
		||||
        default: break;
 | 
			
		||||
    }
 | 
			
		||||
    // Default to 0
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Uint64 PopStackULong(HSQUIRRELVM vm, SQInteger idx)
 | 
			
		||||
{
 | 
			
		||||
    // Identify which type must be extracted
 | 
			
		||||
    switch (sq_gettype(vm, idx))
 | 
			
		||||
    {
 | 
			
		||||
        case OT_INTEGER:
 | 
			
		||||
        {
 | 
			
		||||
            SQInteger val;
 | 
			
		||||
            sq_getinteger(vm, idx, &val);
 | 
			
		||||
            return ConvTo< Uint64 >::From(val);
 | 
			
		||||
        } break;
 | 
			
		||||
        case OT_FLOAT:
 | 
			
		||||
        {
 | 
			
		||||
            SQFloat val;
 | 
			
		||||
            sq_getfloat(vm, idx, &val);
 | 
			
		||||
            return ConvTo< Uint64 >::From(val);
 | 
			
		||||
        } break;
 | 
			
		||||
        case OT_BOOL:
 | 
			
		||||
        {
 | 
			
		||||
            SQBool val;
 | 
			
		||||
            sq_getbool(vm, idx, &val);
 | 
			
		||||
            return ConvTo< Uint64 >::From(val);
 | 
			
		||||
        } break;
 | 
			
		||||
        case OT_STRING:
 | 
			
		||||
        {
 | 
			
		||||
            CSStr val = nullptr;
 | 
			
		||||
            // Attempt to retrieve and convert the string
 | 
			
		||||
            if (SQ_SUCCEEDED(sq_getstring(vm, idx, &val)) && val != nullptr && *val != '\0')
 | 
			
		||||
            {
 | 
			
		||||
                return std::strtoull(val, nullptr, 10);
 | 
			
		||||
            }
 | 
			
		||||
        } break;
 | 
			
		||||
        case OT_ARRAY:
 | 
			
		||||
        case OT_TABLE:
 | 
			
		||||
        case OT_CLASS:
 | 
			
		||||
        case OT_USERDATA:
 | 
			
		||||
        {
 | 
			
		||||
            return ConvTo< Uint64 >::From(sq_getsize(vm, idx));
 | 
			
		||||
        } break;
 | 
			
		||||
        case OT_INSTANCE:
 | 
			
		||||
        {
 | 
			
		||||
            // Attempt to treat the value as a signed long instance
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                return ConvTo< Uint64 >::From(Var< const SLongInt & >(vm, idx).value.GetNum());
 | 
			
		||||
            }
 | 
			
		||||
            catch (...)
 | 
			
		||||
            {
 | 
			
		||||
                // Just ignore it...
 | 
			
		||||
            }
 | 
			
		||||
            // Attempt to treat the value as a unsigned long instance
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                return Var< const ULongInt & >(vm, idx).value.GetNum();
 | 
			
		||||
            }
 | 
			
		||||
            catch (...)
 | 
			
		||||
            {
 | 
			
		||||
                // Just ignore it...
 | 
			
		||||
            }
 | 
			
		||||
            // Attempt to get the size of the instance as a fall back
 | 
			
		||||
            return ConvTo< Uint64 >::From(sq_getsize(vm, idx));
 | 
			
		||||
        } break;
 | 
			
		||||
        default: break;
 | 
			
		||||
    }
 | 
			
		||||
    // Default to 0
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#ifdef SQMOD_PLUGIN_API
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
bool CheckModuleAPIVer(CCStr ver, CCStr mod)
 | 
			
		||||
{
 | 
			
		||||
    // Obtain the numeric representation of the API version
 | 
			
		||||
    const LongI vernum = std::strtol(ver, nullptr, 10);
 | 
			
		||||
    // Check against version mismatch
 | 
			
		||||
    if (vernum == SQMOD_API_VER)
 | 
			
		||||
    {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    // Log the incident
 | 
			
		||||
    OutputError("API version mismatch on %s", mod);
 | 
			
		||||
    OutputMessage("=> Requested: %ld Have: %ld", vernum, SQMOD_API_VER);
 | 
			
		||||
    // Invoker should not attempt to communicate through the module API
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
bool CheckModuleOrder(PluginFuncs * vcapi, Uint32 mod_id, CCStr mod)
 | 
			
		||||
{
 | 
			
		||||
    // Make sure a valid server API was provided
 | 
			
		||||
    if (!vcapi)
 | 
			
		||||
    {
 | 
			
		||||
        OutputError("Invalid pointer to server API structure");
 | 
			
		||||
        // Validation failed!
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    // Attempt to find the host plug-in identifier
 | 
			
		||||
    const int plugin_id = vcapi->FindPlugin(SQMOD_HOST_NAME);
 | 
			
		||||
    // See if our module was loaded after the host plug-in
 | 
			
		||||
    if (plugin_id < 0)
 | 
			
		||||
    {
 | 
			
		||||
        OutputError("%s: could find the host plug-in", mod);
 | 
			
		||||
        // Validation failed!
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    // Should never reach this point but just in case
 | 
			
		||||
    else if (static_cast< Uint32 >(plugin_id) > mod_id)
 | 
			
		||||
    {
 | 
			
		||||
        OutputError("%s: loaded after the host plug-in", mod);
 | 
			
		||||
        // Validation failed!
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    // Loaded in the correct order
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void ImportModuleAPI(PluginFuncs * vcapi, CCStr mod)
 | 
			
		||||
{
 | 
			
		||||
    // Make sure a valid server API was provided
 | 
			
		||||
    if (!vcapi)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("%s: Invalid pointer to server API structure", mod);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    size_t exports_struct_size;
 | 
			
		||||
 | 
			
		||||
    // Attempt to find the host plug-in identifier
 | 
			
		||||
    int plugin_id = vcapi->FindPlugin(SQMOD_HOST_NAME);
 | 
			
		||||
    // Validate the obtained plug-in identifier
 | 
			
		||||
    if (plugin_id < 0)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("%s: Unable to obtain the host plug-in identifier", mod);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Attempt to retrieve the host plug-in exports
 | 
			
		||||
    const void ** raw_plugin_exports = vcapi->GetPluginExports(plugin_id, &exports_struct_size);
 | 
			
		||||
    // See if the size of the exports structure matches
 | 
			
		||||
    if (exports_struct_size <= 0)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("%s: Incompatible host plug-in exports structure", mod);
 | 
			
		||||
    }
 | 
			
		||||
    // See if we have any exports from the host plug-in
 | 
			
		||||
    else if (raw_plugin_exports == nullptr)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("%s: Unable to obtain pointer host plug-in exports", mod);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Obtain pointer to the exports structure
 | 
			
		||||
    const SQMODEXPORTS * plugin_exports = *reinterpret_cast< const SQMODEXPORTS ** >(raw_plugin_exports);
 | 
			
		||||
    // See if we have a valid pointer to the exports structure
 | 
			
		||||
    if (plugin_exports == nullptr)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("%s: Invalid pointer to host plug-in exports structure", mod);
 | 
			
		||||
    }
 | 
			
		||||
    else if (plugin_exports->PopulateModuleAPI == nullptr || plugin_exports->PopulateSquirrelAPI == nullptr)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("%s: Invalid pointer to host plug-in import functions", mod);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Prepare a structure to obtain the module API
 | 
			
		||||
    SQMODAPI sqmodapi;
 | 
			
		||||
    // Attempt to populate the structure
 | 
			
		||||
    switch (plugin_exports->PopulateModuleAPI(&sqmodapi, sizeof(SQMODAPI)))
 | 
			
		||||
    {
 | 
			
		||||
        case -1:    STHROWF("%s: Incompatible module API structure", mod);
 | 
			
		||||
        // fall through
 | 
			
		||||
        case 0:     STHROWF("%s: Invalid pointer to module API structure", mod);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Prepare a structure to obtain the squirrel API
 | 
			
		||||
    SQLIBAPI sqlibapi;
 | 
			
		||||
    // Attempt to populate the structure
 | 
			
		||||
    switch (plugin_exports->PopulateSquirrelAPI(&sqlibapi, sizeof(SQLIBAPI)))
 | 
			
		||||
    {
 | 
			
		||||
        case -1:    STHROWF("%s: Incompatible squirrel API structure", mod);
 | 
			
		||||
        // fall through
 | 
			
		||||
        case 0:     STHROWF("%s: Invalid pointer to squirrel API structure", mod);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Attempt to expand the obtained API
 | 
			
		||||
    if (!sqmod_api_expand(&sqmodapi))
 | 
			
		||||
    {
 | 
			
		||||
        // Collapse the API first
 | 
			
		||||
        sqmod_api_collapse();
 | 
			
		||||
        // Now it's safe to throw the exception
 | 
			
		||||
        STHROWF("%s: Unable to expand module API structure", mod);
 | 
			
		||||
    }
 | 
			
		||||
    else if (!sqlib_api_expand(&sqlibapi))
 | 
			
		||||
    {
 | 
			
		||||
        // Collapse the API first
 | 
			
		||||
        sqmod_api_collapse();
 | 
			
		||||
        sqlib_api_collapse();
 | 
			
		||||
        // Now it's safe to throw the exception
 | 
			
		||||
        STHROWF("%s: Unable to expand module API structure", mod);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // SQMOD_PLUGIN_API
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,8 @@
 | 
			
		||||
#ifndef _BASE_UTILITY_HPP_
 | 
			
		||||
#define _BASE_UTILITY_HPP_
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#ifdef SQMOD_PLUGIN_API
 | 
			
		||||
    #include <ModBase.hpp>
 | 
			
		||||
    #include <SqMod.h>
 | 
			
		||||
#else
 | 
			
		||||
    #include <SqBase.hpp>
 | 
			
		||||
    #include <vcmp.h>
 | 
			
		||||
#endif // SQMOD_PLUGIN_API
 | 
			
		||||
#include <SqBase.hpp>
 | 
			
		||||
#include <vcmp.h>
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include <cmath>
 | 
			
		||||
@@ -1487,36 +1481,4 @@ SQInteger PopStackInteger(HSQUIRRELVM vm, SQInteger idx);
 | 
			
		||||
*/
 | 
			
		||||
SQFloat PopStackFloat(HSQUIRRELVM vm, SQInteger idx);
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Attempt to pop the value at the specified index on the stack as a signed long integer.
 | 
			
		||||
*/
 | 
			
		||||
Int64 PopStackSLong(HSQUIRRELVM vm, SQInteger idx);
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Attempt to pop the value at the specified index on the stack as an unsigned long integer.
 | 
			
		||||
*/
 | 
			
		||||
Uint64 PopStackULong(HSQUIRRELVM vm, SQInteger idx);
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#ifdef SQMOD_PLUGIN_API
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Validate the module API to make sure we don't run into issues.
 | 
			
		||||
*/
 | 
			
		||||
bool CheckModuleAPIVer(CCStr ver, CCStr mod);
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Make sure that the module was loaded after the host plug-in.
 | 
			
		||||
*/
 | 
			
		||||
bool CheckModuleOrder(PluginFuncs * vcapi, Uint32 mod_id, CCStr mod);
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Used by the modules to import the API from the host plug-in.
 | 
			
		||||
*/
 | 
			
		||||
void ImportModuleAPI(PluginFuncs * vcapi, CCStr mod);
 | 
			
		||||
 | 
			
		||||
#endif // SQMOD_PLUGIN_API
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
 | 
			
		||||
#endif // _BASE_UTILITY_HPP_
 | 
			
		||||
 
 | 
			
		||||
@@ -45,6 +45,15 @@ add_library(SqModule MODULE
 | 
			
		||||
	Library/Numeric/LongInt.cpp Library/Numeric/LongInt.hpp
 | 
			
		||||
	Library/Numeric/Math.cpp Library/Numeric/Math.hpp
 | 
			
		||||
	Library/Numeric/Random.cpp Library/Numeric/Random.hpp
 | 
			
		||||
	Library/SQLite.cpp Library/SQLite.hpp
 | 
			
		||||
	Library/SQLite/Constants.cpp
 | 
			
		||||
	Library/SQLite/Column.cpp Library/SQLite/Column.hpp
 | 
			
		||||
	Library/SQLite/Common.cpp Library/SQLite/Common.hpp
 | 
			
		||||
	Library/SQLite/Connection.cpp Library/SQLite/Connection.hpp
 | 
			
		||||
	Library/SQLite/Handle.cpp Library/SQLite/Handle.hpp
 | 
			
		||||
	Library/SQLite/Parameter.cpp Library/SQLite/Parameter.hpp
 | 
			
		||||
	Library/SQLite/Statement.cpp Library/SQLite/Statement.hpp
 | 
			
		||||
	Library/SQLite/Transaction.cpp Library/SQLite/Transaction.hpp
 | 
			
		||||
	Library/String.cpp Library/String.hpp
 | 
			
		||||
	Library/System.cpp Library/System.hpp
 | 
			
		||||
	Library/System/Dir.cpp Library/System/Dir.hpp
 | 
			
		||||
 
 | 
			
		||||
@@ -116,6 +116,144 @@ void LongInt< Uint64 >::Random(Type m, Type n)
 | 
			
		||||
    m_Data = GetRandomUint64(m, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Int64 PopStackSLong(HSQUIRRELVM vm, SQInteger idx)
 | 
			
		||||
{
 | 
			
		||||
    // Identify which type must be extracted
 | 
			
		||||
    switch (sq_gettype(vm, idx))
 | 
			
		||||
    {
 | 
			
		||||
        case OT_INTEGER:
 | 
			
		||||
        {
 | 
			
		||||
            SQInteger val;
 | 
			
		||||
            sq_getinteger(vm, idx, &val);
 | 
			
		||||
            return static_cast< Int64 >(val);
 | 
			
		||||
        } break;
 | 
			
		||||
        case OT_FLOAT:
 | 
			
		||||
        {
 | 
			
		||||
            SQFloat val;
 | 
			
		||||
            sq_getfloat(vm, idx, &val);
 | 
			
		||||
            return ConvTo< Int64 >::From(val);
 | 
			
		||||
        } break;
 | 
			
		||||
        case OT_BOOL:
 | 
			
		||||
        {
 | 
			
		||||
            SQBool val;
 | 
			
		||||
            sq_getbool(vm, idx, &val);
 | 
			
		||||
            return static_cast< Int64 >(val);
 | 
			
		||||
        } break;
 | 
			
		||||
        case OT_STRING:
 | 
			
		||||
        {
 | 
			
		||||
            CSStr val = nullptr;
 | 
			
		||||
            // Attempt to retrieve and convert the string
 | 
			
		||||
            if (SQ_SUCCEEDED(sq_getstring(vm, idx, &val)) && val != nullptr && *val != '\0')
 | 
			
		||||
            {
 | 
			
		||||
                return std::strtoll(val, nullptr, 10);
 | 
			
		||||
            }
 | 
			
		||||
        } break;
 | 
			
		||||
        case OT_ARRAY:
 | 
			
		||||
        case OT_TABLE:
 | 
			
		||||
        case OT_CLASS:
 | 
			
		||||
        case OT_USERDATA:
 | 
			
		||||
        {
 | 
			
		||||
            return static_cast< Int64 >(sq_getsize(vm, idx));
 | 
			
		||||
        } break;
 | 
			
		||||
        case OT_INSTANCE:
 | 
			
		||||
        {
 | 
			
		||||
            // Attempt to treat the value as a signed long instance
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                return Var< const SLongInt & >(vm, idx).value.GetNum();
 | 
			
		||||
            }
 | 
			
		||||
            catch (...)
 | 
			
		||||
            {
 | 
			
		||||
                // Just ignore it...
 | 
			
		||||
            }
 | 
			
		||||
            // Attempt to treat the value as a unsigned long instance
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                return ConvTo< Int64 >::From(Var< const ULongInt & >(vm, idx).value.GetNum());
 | 
			
		||||
            }
 | 
			
		||||
            catch (...)
 | 
			
		||||
            {
 | 
			
		||||
                // Just ignore it...
 | 
			
		||||
            }
 | 
			
		||||
            // Attempt to get the size of the instance as a fall back
 | 
			
		||||
            return static_cast< Int64 >(sq_getsize(vm, idx));
 | 
			
		||||
        } break;
 | 
			
		||||
        default: break;
 | 
			
		||||
    }
 | 
			
		||||
    // Default to 0
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Uint64 PopStackULong(HSQUIRRELVM vm, SQInteger idx)
 | 
			
		||||
{
 | 
			
		||||
    // Identify which type must be extracted
 | 
			
		||||
    switch (sq_gettype(vm, idx))
 | 
			
		||||
    {
 | 
			
		||||
        case OT_INTEGER:
 | 
			
		||||
        {
 | 
			
		||||
            SQInteger val;
 | 
			
		||||
            sq_getinteger(vm, idx, &val);
 | 
			
		||||
            return ConvTo< Uint64 >::From(val);
 | 
			
		||||
        } break;
 | 
			
		||||
        case OT_FLOAT:
 | 
			
		||||
        {
 | 
			
		||||
            SQFloat val;
 | 
			
		||||
            sq_getfloat(vm, idx, &val);
 | 
			
		||||
            return ConvTo< Uint64 >::From(val);
 | 
			
		||||
        } break;
 | 
			
		||||
        case OT_BOOL:
 | 
			
		||||
        {
 | 
			
		||||
            SQBool val;
 | 
			
		||||
            sq_getbool(vm, idx, &val);
 | 
			
		||||
            return ConvTo< Uint64 >::From(val);
 | 
			
		||||
        } break;
 | 
			
		||||
        case OT_STRING:
 | 
			
		||||
        {
 | 
			
		||||
            CSStr val = nullptr;
 | 
			
		||||
            // Attempt to retrieve and convert the string
 | 
			
		||||
            if (SQ_SUCCEEDED(sq_getstring(vm, idx, &val)) && val != nullptr && *val != '\0')
 | 
			
		||||
            {
 | 
			
		||||
                return std::strtoull(val, nullptr, 10);
 | 
			
		||||
            }
 | 
			
		||||
        } break;
 | 
			
		||||
        case OT_ARRAY:
 | 
			
		||||
        case OT_TABLE:
 | 
			
		||||
        case OT_CLASS:
 | 
			
		||||
        case OT_USERDATA:
 | 
			
		||||
        {
 | 
			
		||||
            return ConvTo< Uint64 >::From(sq_getsize(vm, idx));
 | 
			
		||||
        } break;
 | 
			
		||||
        case OT_INSTANCE:
 | 
			
		||||
        {
 | 
			
		||||
            // Attempt to treat the value as a signed long instance
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                return ConvTo< Uint64 >::From(Var< const SLongInt & >(vm, idx).value.GetNum());
 | 
			
		||||
            }
 | 
			
		||||
            catch (...)
 | 
			
		||||
            {
 | 
			
		||||
                // Just ignore it...
 | 
			
		||||
            }
 | 
			
		||||
            // Attempt to treat the value as a unsigned long instance
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                return Var< const ULongInt & >(vm, idx).value.GetNum();
 | 
			
		||||
            }
 | 
			
		||||
            catch (...)
 | 
			
		||||
            {
 | 
			
		||||
                // Just ignore it...
 | 
			
		||||
            }
 | 
			
		||||
            // Attempt to get the size of the instance as a fall back
 | 
			
		||||
            return ConvTo< Uint64 >::From(sq_getsize(vm, idx));
 | 
			
		||||
        } break;
 | 
			
		||||
        default: break;
 | 
			
		||||
    }
 | 
			
		||||
    // Default to 0
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ================================================================================================
 | 
			
		||||
void Register_LongInt(HSQUIRRELVM vm)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -1275,6 +1275,16 @@ inline Int32 LongInt< Int64 >::Cmp(const LongInt< Uint64 > & o) const
 | 
			
		||||
typedef LongInt< Int64 > SLongInt;
 | 
			
		||||
typedef LongInt< Uint64 > ULongInt;
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Attempt to pop the value at the specified index on the stack as a signed long integer.
 | 
			
		||||
*/
 | 
			
		||||
Int64 PopStackSLong(HSQUIRRELVM vm, SQInteger idx);
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Attempt to pop the value at the specified index on the stack as an unsigned long integer.
 | 
			
		||||
*/
 | 
			
		||||
Uint64 PopStackULong(HSQUIRRELVM vm, SQInteger idx);
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
 | 
			
		||||
#endif // _LIBRARY_NUMERIC_LONGINT_HPP_
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										32
									
								
								module/Library/SQLite.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								module/Library/SQLite.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Library/SQLite.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
extern void Register_Constants(Table & sqlns);
 | 
			
		||||
extern void Register_Common(Table & sqlns);
 | 
			
		||||
extern void Register_Connection(Table & sqlns);
 | 
			
		||||
extern void Register_Statement(Table & sqlns);
 | 
			
		||||
extern void Register_Parameter(Table & sqlns);
 | 
			
		||||
extern void Register_Column(Table & sqlns);
 | 
			
		||||
extern void Register_Transaction(Table & sqlns);
 | 
			
		||||
 | 
			
		||||
// ================================================================================================
 | 
			
		||||
void Register_SQLite(HSQUIRRELVM vm)
 | 
			
		||||
{
 | 
			
		||||
    Table sqlns(vm);
 | 
			
		||||
 | 
			
		||||
    Register_Constants(sqlns);
 | 
			
		||||
    Register_Common(sqlns);
 | 
			
		||||
    Register_Connection(sqlns);
 | 
			
		||||
    Register_Statement(sqlns);
 | 
			
		||||
    Register_Parameter(sqlns);
 | 
			
		||||
    Register_Column(sqlns);
 | 
			
		||||
    Register_Transaction(sqlns);
 | 
			
		||||
 | 
			
		||||
    RootTable(vm).Bind(_SC("SQLite"), sqlns);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
							
								
								
									
										14
									
								
								module/Library/SQLite.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								module/Library/SQLite.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
#ifndef _LIBRARY_SQLITE_HPP_
 | 
			
		||||
#define _LIBRARY_SQLITE_HPP_
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Base/Shared.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
 | 
			
		||||
#endif // _LIBRARY_SQLITE_HPP_
 | 
			
		||||
							
								
								
									
										540
									
								
								module/Library/SQLite/Column.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										540
									
								
								module/Library/SQLite/Column.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,540 @@
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Library/SQLite/Column.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include <cstdlib>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include <sqstdblob.h>
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
SQMODE_DECL_TYPENAME(Typename, _SC("SqLiteColumn"))
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
static inline bool IsDigitsOnly(CSStr str)
 | 
			
		||||
{
 | 
			
		||||
    while (std::isdigit(*str) || std::isspace(*str))
 | 
			
		||||
    {
 | 
			
		||||
        ++str;
 | 
			
		||||
    }
 | 
			
		||||
    // Return whether we reached the end while searching
 | 
			
		||||
    return *str == '\0';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
void Column::Validate(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    // Are we pointing to a valid index?
 | 
			
		||||
    if (m_Index < 0)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid column index: %d < 0 =>[%s:%d]", m_Index, file, line);
 | 
			
		||||
    }
 | 
			
		||||
    // Do we have a valid statement handle?
 | 
			
		||||
    else if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid SQLite statement reference =>[%s:%d]", file, line);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
void Column::Validate() const
 | 
			
		||||
{
 | 
			
		||||
    // Are we pointing to a valid index?
 | 
			
		||||
    if (m_Index < 0)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid column index: %d < 0", m_Index);
 | 
			
		||||
    }
 | 
			
		||||
    // Do we have a valid statement handle?
 | 
			
		||||
    else if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid SQLite statement reference");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
void Column::ValidateCreated(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    // Are we pointing to a valid index?
 | 
			
		||||
    if (m_Index < 0)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid column index: %d < 0 =>[%s:%d]", m_Index, file, line);
 | 
			
		||||
    }
 | 
			
		||||
    else if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid SQLite statement reference =>[%s:%d]", file, line);
 | 
			
		||||
    }
 | 
			
		||||
    else if (m_Handle->mPtr == nullptr)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid SQLite statement =>[%s:%d]", file, line);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
void Column::ValidateCreated() const
 | 
			
		||||
{
 | 
			
		||||
    // Are we pointing to a valid index?
 | 
			
		||||
    if (m_Index < 0)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid column index: %d < 0", m_Index);
 | 
			
		||||
    }
 | 
			
		||||
    else if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid SQLite statement reference");
 | 
			
		||||
    }
 | 
			
		||||
    else if (m_Handle->mPtr == nullptr)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid SQLite statement");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
const StmtRef & Column::GetValid(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    Validate(file, line);
 | 
			
		||||
    return m_Handle;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
const StmtRef & Column::GetValid() const
 | 
			
		||||
{
 | 
			
		||||
    Validate();
 | 
			
		||||
    return m_Handle;
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
const StmtRef & Column::GetCreated(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    ValidateCreated(file, line);
 | 
			
		||||
    return m_Handle;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
const StmtRef & Column::GetCreated() const
 | 
			
		||||
{
 | 
			
		||||
    ValidateCreated();
 | 
			
		||||
    return m_Handle;
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
void Column::ValidateColumn(Int32 idx, CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    ValidateCreated(file, line);
 | 
			
		||||
    // Is the specified index in range?
 | 
			
		||||
    if (!m_Handle->CheckColumn(idx))
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Column index is out of range: %d:%d =>[%s:%d]", idx, m_Handle->mColumns,
 | 
			
		||||
                    file, line);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
void Column::ValidateColumn(Int32 idx) const
 | 
			
		||||
{
 | 
			
		||||
    ValidateCreated();
 | 
			
		||||
    // Is the specified index in range?
 | 
			
		||||
    if (!m_Handle->CheckColumn(idx))
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Column index is out of range: %d:%d", idx, m_Handle->mColumns);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
void Column::ValidateRow(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    ValidateCreated(file, line);
 | 
			
		||||
    // Do we have any rows available?
 | 
			
		||||
    if (!m_Handle->mGood)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("No row available =>[%s:%d]", file, line);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
void Column::ValidateRow() const
 | 
			
		||||
{
 | 
			
		||||
    ValidateCreated();
 | 
			
		||||
    // Do we have any rows available?
 | 
			
		||||
    if (!m_Handle->mGood)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("No row available");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Column::SetIndex(const Object & column)
 | 
			
		||||
{
 | 
			
		||||
    // Where the index will be extracted
 | 
			
		||||
    Int32 idx = -1;
 | 
			
		||||
    // Grab the object virtual machine
 | 
			
		||||
    HSQUIRRELVM vm = column.GetVM();
 | 
			
		||||
    // Remember the current stack size
 | 
			
		||||
    const StackGuard sg(vm);
 | 
			
		||||
    // Push the specified object onto the stack
 | 
			
		||||
    Var< const Object & >::push(vm, column);
 | 
			
		||||
    // Identify the type of column was given
 | 
			
		||||
    switch  (column.GetType())
 | 
			
		||||
    {
 | 
			
		||||
        // Is this a string value?
 | 
			
		||||
        case OT_STRING:
 | 
			
		||||
        {
 | 
			
		||||
            // Obtain the object from the stack as a string
 | 
			
		||||
            StackStrF val(vm, -1);
 | 
			
		||||
            // Validate the result
 | 
			
		||||
            if (SQ_FAILED(val.Proc(false)))
 | 
			
		||||
            {
 | 
			
		||||
                STHROWF("%s", LastErrorString(vm).c_str());
 | 
			
		||||
            }
 | 
			
		||||
            // Is the obtained string empty?
 | 
			
		||||
            else if (val.mLen <= 0)
 | 
			
		||||
            {
 | 
			
		||||
                STHROWF("Cannot use an empty column name");
 | 
			
		||||
            }
 | 
			
		||||
            // Attempt to find a column with the specified name
 | 
			
		||||
            idx = m_Handle->GetColumnIndex(val.mPtr);
 | 
			
		||||
        } break;
 | 
			
		||||
        // Is this an integer value? (or at least can be easily converted to one)
 | 
			
		||||
        case OT_INTEGER:
 | 
			
		||||
        case OT_FLOAT:
 | 
			
		||||
        case OT_BOOL:
 | 
			
		||||
        {
 | 
			
		||||
            idx = ConvTo< Int32 >::From(PopStackInteger(vm, -1));
 | 
			
		||||
        } break;
 | 
			
		||||
        // Is this an instance that we can extract either a string or integer from it?
 | 
			
		||||
        case OT_INSTANCE:
 | 
			
		||||
        {
 | 
			
		||||
            // Obtain the object from the stack as a string
 | 
			
		||||
            StackStrF val(vm, -1);
 | 
			
		||||
            // Validate the result
 | 
			
		||||
            if (SQ_FAILED(val.Proc(false)))
 | 
			
		||||
            {
 | 
			
		||||
                STHROWF("%s", LastErrorString(vm).c_str());
 | 
			
		||||
            }
 | 
			
		||||
            // Is the obtained string empty?
 | 
			
		||||
            else if (val.mLen <= 0)
 | 
			
		||||
            {
 | 
			
		||||
                STHROWF("Cannot use an empty column name");
 | 
			
		||||
            }
 | 
			
		||||
            // Check if this value is made only of digits
 | 
			
		||||
            else if (IsDigitsOnly(val.mPtr))
 | 
			
		||||
            {
 | 
			
		||||
                idx = ConvNum< Int32 >::FromStr(val.mPtr);
 | 
			
		||||
            }
 | 
			
		||||
            // Attempt to find a column with the specified name
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                idx = m_Handle->GetColumnIndex(val.mPtr);
 | 
			
		||||
            }
 | 
			
		||||
        } break;
 | 
			
		||||
        // We don't recognize this kind of value!
 | 
			
		||||
        default: STHROWF("Unknown column index of type (%s)", SqTypeName(column.GetType()));
 | 
			
		||||
    }
 | 
			
		||||
    // Assign the index with a failsafe to invalid on error
 | 
			
		||||
    AutoAssign< Int32 > aa(m_Index, -1, idx);
 | 
			
		||||
    // Validate the obtained column index
 | 
			
		||||
    SQMOD_VALIDATE_COLUMN(*this, idx);
 | 
			
		||||
    // Don't fall back to the invalid index anymore
 | 
			
		||||
    aa.Set(idx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Object Column::GetStatement() const
 | 
			
		||||
{
 | 
			
		||||
    return GetStatementObj(m_Handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Object Column::GetConnection() const
 | 
			
		||||
{
 | 
			
		||||
    return GetConnectionObj(SQMOD_GET_VALID(*this)->mConn);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
bool Column::IsNull() const
 | 
			
		||||
{
 | 
			
		||||
    return (sqlite3_column_type(SQMOD_GET_CREATED(*this)->mPtr, m_Index) == SQLITE_NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
CSStr Column::GetName() const
 | 
			
		||||
{
 | 
			
		||||
    return sqlite3_column_name(SQMOD_GET_CREATED(*this)->mPtr, m_Index);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
CSStr Column::GetOriginName() const
 | 
			
		||||
{
 | 
			
		||||
#ifdef SQLITE_ENABLE_COLUMN_METADATA
 | 
			
		||||
    return sqlite3_column_origin_name(SQMOD_GET_CREATED(*this)->mPtr, m_Index);
 | 
			
		||||
#else
 | 
			
		||||
    STHROWF("The module was compiled without this feature");
 | 
			
		||||
    // Request failed
 | 
			
		||||
    return _SC("");
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Int32 Column::GetType() const
 | 
			
		||||
{
 | 
			
		||||
    return sqlite3_column_type(SQMOD_GET_CREATED(*this)->mPtr, m_Index);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Int32 Column::GetBytes() const
 | 
			
		||||
{
 | 
			
		||||
    return sqlite3_column_bytes(SQMOD_GET_CREATED(*this)->mPtr, m_Index);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Object Column::GetValue() const
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_ROW(*this);
 | 
			
		||||
    // Obtain the initial stack size
 | 
			
		||||
    const StackGuard sg;
 | 
			
		||||
    // Identify which type of value must be pushed on the stack
 | 
			
		||||
    switch (sqlite3_column_type(m_Handle->mPtr, m_Index))
 | 
			
		||||
    {
 | 
			
		||||
        // Is this a null value?
 | 
			
		||||
        case SQLITE_NULL:
 | 
			
		||||
        {
 | 
			
		||||
            sq_pushnull(DefaultVM::Get());
 | 
			
		||||
        } break;
 | 
			
		||||
        // Is this an integer?
 | 
			
		||||
        case SQLITE_INTEGER:
 | 
			
		||||
        {
 | 
			
		||||
            sq_pushinteger(DefaultVM::Get(), sqlite3_column_integer(m_Handle->mPtr, m_Index));
 | 
			
		||||
        } break;
 | 
			
		||||
        // Is this a floating point?
 | 
			
		||||
        case SQLITE_FLOAT:
 | 
			
		||||
        {
 | 
			
		||||
            sq_pushfloat(DefaultVM::Get(),
 | 
			
		||||
                            ConvTo< SQFloat >::From(sqlite3_column_double(m_Handle->mPtr, m_Index)));
 | 
			
		||||
        } break;
 | 
			
		||||
        // Is this a string?
 | 
			
		||||
        case SQLITE_TEXT:
 | 
			
		||||
        {
 | 
			
		||||
            sq_pushstring(DefaultVM::Get(),
 | 
			
		||||
                            reinterpret_cast< CSStr >(sqlite3_column_text(m_Handle->mPtr, m_Index)),
 | 
			
		||||
                            sqlite3_column_bytes(m_Handle->mPtr, m_Index));
 | 
			
		||||
        } break;
 | 
			
		||||
        // Is this raw data?
 | 
			
		||||
        case SQLITE_BLOB:
 | 
			
		||||
        {
 | 
			
		||||
            // Retrieve the size of the blob that must be allocated
 | 
			
		||||
            const Int32 size = sqlite3_column_bytes(m_Handle->mPtr, m_Index);
 | 
			
		||||
            // Retrieve the the actual blob data that must be returned
 | 
			
		||||
            auto data = reinterpret_cast< CCStr >(sqlite3_column_blob(m_Handle->mPtr, m_Index));
 | 
			
		||||
            // Attempt to create a buffer with the blob data on the stack
 | 
			
		||||
            Var< const SqBuffer & >::push(DefaultVM::Get(), SqBuffer(data, size, 0));
 | 
			
		||||
        } break;
 | 
			
		||||
        // Unknown type
 | 
			
		||||
        default: STHROWF("Unknown value to fetch at index: %d", m_Index);
 | 
			
		||||
    }
 | 
			
		||||
    // Obtain the object with the value from the stack and return it
 | 
			
		||||
    return Var< Object >(DefaultVM::Get(), -1).value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Object Column::GetNumber() const
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_ROW(*this);
 | 
			
		||||
    // Obtain the initial stack size
 | 
			
		||||
    const StackGuard sg;
 | 
			
		||||
    // Identify which type of value must be pushed on the stack
 | 
			
		||||
    switch (sqlite3_column_type(m_Handle->mPtr, m_Index))
 | 
			
		||||
    {
 | 
			
		||||
        // Is this a null value?
 | 
			
		||||
        case SQLITE_NULL:
 | 
			
		||||
        {
 | 
			
		||||
            sq_pushinteger(DefaultVM::Get(), 0);
 | 
			
		||||
        } break;
 | 
			
		||||
        // Is this an integer?
 | 
			
		||||
        case SQLITE_INTEGER:
 | 
			
		||||
        {
 | 
			
		||||
            sq_pushinteger(DefaultVM::Get(), sqlite3_column_integer(m_Handle->mPtr, m_Index));
 | 
			
		||||
        } break;
 | 
			
		||||
        // Is this a floating point?
 | 
			
		||||
        case SQLITE_FLOAT:
 | 
			
		||||
        {
 | 
			
		||||
            sq_pushfloat(DefaultVM::Get(),
 | 
			
		||||
                            ConvTo< SQFloat >::From(sqlite3_column_double(m_Handle->mPtr, m_Index)));
 | 
			
		||||
        } break;
 | 
			
		||||
        // Is this a string?
 | 
			
		||||
        case SQLITE_TEXT:
 | 
			
		||||
        {
 | 
			
		||||
            auto str = reinterpret_cast< CSStr >(sqlite3_column_text(m_Handle->mPtr, m_Index));
 | 
			
		||||
            // Is there even a string to parse?
 | 
			
		||||
            if (!str || *str == '\0')
 | 
			
		||||
            {
 | 
			
		||||
                sq_pushinteger(DefaultVM::Get(), 0);
 | 
			
		||||
            }
 | 
			
		||||
            // Can we treat this string as a float?
 | 
			
		||||
            else if (!std::strchr(str, '.'))
 | 
			
		||||
            {
 | 
			
		||||
                sq_pushfloat(DefaultVM::Get(),
 | 
			
		||||
                                ConvTo< SQFloat >::From(std::strtod(str, nullptr)));
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                sq_pushinteger(DefaultVM::Get(),
 | 
			
		||||
                                ConvTo< SQInteger >::From(std::strtoll(str, nullptr, 10)));
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
        } break;
 | 
			
		||||
        // Unknown type
 | 
			
		||||
        default: STHROWF("Unknown number to fetch at index: %d", m_Index);
 | 
			
		||||
    }
 | 
			
		||||
    // Obtain the object with the value from the stack and return it
 | 
			
		||||
    return Var< Object >(DefaultVM::Get(), -1).value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
SQInteger Column::GetInteger() const
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_ROW(*this);
 | 
			
		||||
    // Return the requested information
 | 
			
		||||
    return sqlite3_column_integer(m_Handle->mPtr, m_Index);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
SQFloat Column::GetFloat() const
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_ROW(*this);
 | 
			
		||||
    // Return the requested information
 | 
			
		||||
    return ConvTo< SQFloat >::From(sqlite3_column_double(m_Handle->mPtr, m_Index));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Object Column::GetLong() const
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_ROW(*this);
 | 
			
		||||
    // Return the requested information
 | 
			
		||||
    return Object(new SLongInt(sqlite3_column_int64(m_Handle->mPtr, m_Index)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Object Column::GetString() const
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_ROW(*this);
 | 
			
		||||
    // Obtain the initial stack size
 | 
			
		||||
    const StackGuard sg;
 | 
			
		||||
    // Push the column text on the stack
 | 
			
		||||
    sq_pushstring(DefaultVM::Get(), reinterpret_cast< CSStr >(sqlite3_column_text(m_Handle->mPtr, m_Index)),
 | 
			
		||||
                            sqlite3_column_bytes(m_Handle->mPtr, m_Index));
 | 
			
		||||
    // Get the object from the stack and return it
 | 
			
		||||
    return Var< Object >(DefaultVM::Get(), -1).value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
bool Column::GetBoolean() const
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_ROW(*this);
 | 
			
		||||
    // Return the requested information
 | 
			
		||||
    return sqlite3_column_int(m_Handle->mPtr, m_Index) > 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
SQChar Column::GetChar() const
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_ROW(*this);
 | 
			
		||||
    // Return the requested information
 | 
			
		||||
    return (SQChar)sqlite3_column_int(m_Handle->mPtr, m_Index);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Object Column::GetBuffer() const
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_ROW(*this);
 | 
			
		||||
    // Remember the current stack size
 | 
			
		||||
    const StackGuard sg;
 | 
			
		||||
    // Retrieve the size of the blob that must be allocated
 | 
			
		||||
    const Int32 size = sqlite3_column_bytes(m_Handle->mPtr, m_Index);
 | 
			
		||||
    // Retrieve the the actual blob data that must be returned
 | 
			
		||||
    auto data = reinterpret_cast< CCStr >(sqlite3_column_blob(m_Handle->mPtr, m_Index));
 | 
			
		||||
    // Attempt to create a buffer with the blob data on the stack
 | 
			
		||||
    Var< const SqBuffer & >::push(DefaultVM::Get(), SqBuffer(data, size, 0));
 | 
			
		||||
    // Get the object from the stack and return it
 | 
			
		||||
    return Var< Object >(DefaultVM::Get(), -1).value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Object Column::GetBlob() const
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_ROW(*this);
 | 
			
		||||
    // Obtain the initial stack size
 | 
			
		||||
    const StackGuard sg;
 | 
			
		||||
    // Obtain the size of the data
 | 
			
		||||
    const Int32 sz = sqlite3_column_bytes(m_Handle->mPtr, m_Index);
 | 
			
		||||
    // Allocate a blob of the same size
 | 
			
		||||
    SQUserPointer p = sqstd_createblob(DefaultVM::Get(), sz);
 | 
			
		||||
    // Obtain a pointer to the data
 | 
			
		||||
    const void * b = sqlite3_column_blob(m_Handle->mPtr, m_Index);
 | 
			
		||||
    // Could the memory blob be allocated?
 | 
			
		||||
    if (!p)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Unable to allocate space for column blob value");
 | 
			
		||||
    }
 | 
			
		||||
    // Is there any data to read?
 | 
			
		||||
    else if (!b)
 | 
			
		||||
    {
 | 
			
		||||
        // Pop the memory blob from the stack
 | 
			
		||||
        sq_pop(DefaultVM::Get(), 1);
 | 
			
		||||
        // Push a null value instead
 | 
			
		||||
        sq_pushnull(DefaultVM::Get());
 | 
			
		||||
    }
 | 
			
		||||
    // Copy the data into the memory blob
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        std::memcpy(p, b, sz);
 | 
			
		||||
    }
 | 
			
		||||
    // Get the object from the stack and return it
 | 
			
		||||
    return Var< Object >(DefaultVM::Get(), -1).value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ================================================================================================
 | 
			
		||||
void Register_Column(Table & sqlns)
 | 
			
		||||
{
 | 
			
		||||
    sqlns.Bind(_SC("Column"),
 | 
			
		||||
        Class< Column >(sqlns.GetVM(), Typename::Str)
 | 
			
		||||
        // Constructors
 | 
			
		||||
        .Ctor()
 | 
			
		||||
        .Ctor< const Column & >()
 | 
			
		||||
        // Meta-methods
 | 
			
		||||
        .SquirrelFunc(_SC("_typename"), &Typename::Fn)
 | 
			
		||||
        .Func(_SC("_tostring"), &Column::ToString)
 | 
			
		||||
        // Properties
 | 
			
		||||
        .Prop(_SC("IsValid"), &Column::IsValid)
 | 
			
		||||
        .Prop(_SC("References"), &Column::GetRefCount)
 | 
			
		||||
        .Prop(_SC("Index"), &Column::GetIndex)
 | 
			
		||||
        .Prop(_SC("Statement"), &Column::GetStatement)
 | 
			
		||||
        .Prop(_SC("Connection"), &Column::GetConnection)
 | 
			
		||||
        .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)
 | 
			
		||||
        .Prop(_SC("Value"), &Column::GetValue)
 | 
			
		||||
        .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("Char"), &Column::GetChar)
 | 
			
		||||
        .Prop(_SC("Buffer"), &Column::GetBuffer)
 | 
			
		||||
        .Prop(_SC("Blob"), &Column::GetBlob)
 | 
			
		||||
        // Member Methods
 | 
			
		||||
        .Func(_SC("Release"), &Column::Release)
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
							
								
								
									
										339
									
								
								module/Library/SQLite/Column.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										339
									
								
								module/Library/SQLite/Column.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,339 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Library/SQLite/Handle.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Used to manage and interact with statement columns.
 | 
			
		||||
*/
 | 
			
		||||
class Column
 | 
			
		||||
{
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    friend class Statement;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    Int32       m_Index; // The index of the managed column.
 | 
			
		||||
    StmtRef     m_Handle; // The statement where the column exist.
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the managed statement handle and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    void Validate(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    void Validate() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the managed statement handle and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    void ValidateCreated(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    void ValidateCreated() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the managed statement handle and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    const StmtRef & GetValid(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    const StmtRef & GetValid() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the managed statement handle and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    const StmtRef & GetCreated(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    const StmtRef & GetCreated() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the statement reference and column index, and throw an error if they're invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    void ValidateColumn(Int32 idx, CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    void ValidateColumn(Int32 idx) const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the statement reference and row, and throw an error if they're invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    void ValidateRow(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    void ValidateRow() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Modify the index to the specified value.
 | 
			
		||||
    */
 | 
			
		||||
    void SetIndex(Int32 idx)
 | 
			
		||||
    {
 | 
			
		||||
        // Assign the index with a failsafe to invalid on error
 | 
			
		||||
        AutoAssign< Int32 > aa(m_Index, -1, idx);
 | 
			
		||||
        // Validate the obtained column index
 | 
			
		||||
        SQMOD_VALIDATE_COLUMN(*this, idx);
 | 
			
		||||
        // Don't fall back to the invalid index anymore
 | 
			
		||||
        aa.Set(idx);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Modify the index to the specified value.
 | 
			
		||||
    */
 | 
			
		||||
    void SetIndex(CSStr name)
 | 
			
		||||
    {
 | 
			
		||||
        SetIndex(SQMOD_GET_CREATED(*this)->GetColumnIndex(name));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Modify the index to the specified value.
 | 
			
		||||
    */
 | 
			
		||||
    void SetIndex(const Object & column);
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Default constructor (null).
 | 
			
		||||
    */
 | 
			
		||||
    Column()
 | 
			
		||||
        : m_Index(-1), m_Handle()
 | 
			
		||||
    {
 | 
			
		||||
        /* ... */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * No column constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Column(const StmtRef & stmt)
 | 
			
		||||
        : m_Index(-1), m_Handle(stmt)
 | 
			
		||||
    {
 | 
			
		||||
        /* ... */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Index constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Column(const StmtRef & stmt, Int32 idx)
 | 
			
		||||
        : m_Index(idx), m_Handle(stmt)
 | 
			
		||||
    {
 | 
			
		||||
        SQMOD_VALIDATE_COLUMN(*this, m_Index);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Name constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Column(const StmtRef & stmt, CSStr name)
 | 
			
		||||
        : m_Index(stmt ? stmt->GetColumnIndex(name) : -1), m_Handle(stmt)
 | 
			
		||||
    {
 | 
			
		||||
        SQMOD_VALIDATE_COLUMN(*this, m_Index);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Dynamic constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Column(const StmtRef & stmt, const Object & column)
 | 
			
		||||
        : m_Index(-1), m_Handle(stmt)
 | 
			
		||||
    {
 | 
			
		||||
        if (!m_Handle)
 | 
			
		||||
        {
 | 
			
		||||
            STHROWF("Invalid SQLite statement reference");
 | 
			
		||||
        }
 | 
			
		||||
        // Extract the index
 | 
			
		||||
        SetIndex(column);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Column(const Column & o) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Move constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Column(Column && o) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy assignment operator.
 | 
			
		||||
    */
 | 
			
		||||
    Column & operator = (const Column & o) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Move assignment operator.
 | 
			
		||||
    */
 | 
			
		||||
    Column & operator = (Column && o) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Perform an equality comparison between two table column indexes.
 | 
			
		||||
    */
 | 
			
		||||
    bool operator == (const Column & o) const
 | 
			
		||||
    {
 | 
			
		||||
        return (m_Index == o.m_Index);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Perform an inequality comparison between two table column indexes.
 | 
			
		||||
    */
 | 
			
		||||
    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 convert an instance of this type to a string.
 | 
			
		||||
    */
 | 
			
		||||
    CSStr ToString() const
 | 
			
		||||
    {
 | 
			
		||||
        CSStr val = nullptr;
 | 
			
		||||
        // Can we attempt to return the parameter name?
 | 
			
		||||
        if (m_Handle && m_Index)
 | 
			
		||||
        {
 | 
			
		||||
            val = sqlite3_column_name(m_Handle->mPtr, m_Index);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            val = ToStrF(_SC("%d"), m_Index);
 | 
			
		||||
        }
 | 
			
		||||
        // Return the value if valid
 | 
			
		||||
        return val ? val : _SC("");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * See whether the column is valid.
 | 
			
		||||
    */
 | 
			
		||||
    bool IsValid() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Handle; // An invalid statement means an invalid column
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Return the number of active references to the associated statement handle.
 | 
			
		||||
    */
 | 
			
		||||
    Uint32 GetRefCount() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Handle.Count();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the referenced column index.
 | 
			
		||||
    */
 | 
			
		||||
    Int32 GetIndex() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Index;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the referenced database statement.
 | 
			
		||||
    */
 | 
			
		||||
    Object GetStatement() const;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the referenced database connection.
 | 
			
		||||
    */
 | 
			
		||||
    Object GetConnection() const;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Release the reference to the referenced database statement and column index.
 | 
			
		||||
    */
 | 
			
		||||
    void Release()
 | 
			
		||||
    {
 | 
			
		||||
        m_Handle.Reset();
 | 
			
		||||
        m_Index = -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Check whether the referenced column is null.
 | 
			
		||||
    */
 | 
			
		||||
    bool IsNull() const;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the name of the referenced 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 referenced column index.
 | 
			
		||||
    */
 | 
			
		||||
    Int32 GetType() const;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the size in bytes of the referenced column index.
 | 
			
		||||
    */
 | 
			
		||||
    Int32 GetBytes() const;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value inside the referenced column as a dynamic type.
 | 
			
		||||
    */
 | 
			
		||||
    Object GetValue() const;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value inside the referenced column as a numeric type.
 | 
			
		||||
    */
 | 
			
		||||
    Object GetNumber() const;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value inside the referenced column as a native script integer.
 | 
			
		||||
    */
 | 
			
		||||
    SQInteger GetInteger() const;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value inside the referenced column as a native script floating point.
 | 
			
		||||
    */
 | 
			
		||||
    SQFloat GetFloat() const;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value inside the referenced column as a long integer.
 | 
			
		||||
    */
 | 
			
		||||
    Object GetLong() const;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value inside the referenced column as a string.
 | 
			
		||||
    */
 | 
			
		||||
    Object GetString() const;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value inside the referenced column as a boolean.
 | 
			
		||||
    */
 | 
			
		||||
    bool GetBoolean() const;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value inside the referenced column as a character.
 | 
			
		||||
    */
 | 
			
		||||
    SQChar GetChar() const;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value inside the referenced column as a memory buffer.
 | 
			
		||||
    */
 | 
			
		||||
    Object GetBuffer() const;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value inside the referenced column as a memory blob.
 | 
			
		||||
    */
 | 
			
		||||
    Object GetBlob() const;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
							
								
								
									
										219
									
								
								module/Library/SQLite/Common.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										219
									
								
								module/Library/SQLite/Common.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,219 @@
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Library/SQLite/Common.hpp"
 | 
			
		||||
#include "Library/SQLite/Connection.hpp"
 | 
			
		||||
#include "Library/SQLite/Statement.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Object GetConnectionObj(const ConnRef & conn)
 | 
			
		||||
{
 | 
			
		||||
    return Object(new Connection(conn));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Object GetStatementObj(const StmtRef & stmt)
 | 
			
		||||
{
 | 
			
		||||
    return Object(new Statement(stmt));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
bool IsQueryEmpty(CSStr str)
 | 
			
		||||
{
 | 
			
		||||
    // Is the pointer valid?
 | 
			
		||||
    if (!str || *str == '\0')
 | 
			
		||||
    {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    // Currently processed character
 | 
			
		||||
    SQChar c = 0;
 | 
			
		||||
    // See if the query contains any alpha numeric characters
 | 
			
		||||
    while ((c = *str) != 0)
 | 
			
		||||
    {
 | 
			
		||||
        if (std::isalnum(c) != 0)
 | 
			
		||||
        {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        ++str;
 | 
			
		||||
    }
 | 
			
		||||
    // At this point we consider the query empty
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
CSStr GetErrStr(Int32 status)
 | 
			
		||||
{
 | 
			
		||||
    return sqlite3_errstr(status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
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 StackGuard sg;
 | 
			
		||||
    // Push a long integer instance with the requested value on the stack
 | 
			
		||||
    return Object(new SLongInt(sqlite3_memory_used()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Object GetMemoryHighwaterMark(bool reset)
 | 
			
		||||
{
 | 
			
		||||
    // Obtain the initial stack size
 | 
			
		||||
    const StackGuard sg;
 | 
			
		||||
    // Push a long integer instance with the requested value on the stack
 | 
			
		||||
    return Object(new SLongInt(sqlite3_memory_highwater(reset)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
CSStr EscapeString(StackStrF & str)
 | 
			
		||||
{
 | 
			
		||||
    // Is there even a string to escape?
 | 
			
		||||
    if (str.mLen <= 0)
 | 
			
		||||
    {
 | 
			
		||||
        return _SC(""); // Default to empty string
 | 
			
		||||
    }
 | 
			
		||||
    // Attempt to escape the specified string
 | 
			
		||||
    sqlite3_snprintf(GetTempBuffSize(), GetTempBuff(), "%q", str.mPtr);
 | 
			
		||||
    // Return the resulted string
 | 
			
		||||
    return GetTempBuff();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
CCStr EscapeStringEx(SQChar spec, StackStrF & 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'))
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Unknown format specifier: '%c'", spec);
 | 
			
		||||
    }
 | 
			
		||||
    // Is there even a string to escape?
 | 
			
		||||
    else if (!str.mLen)
 | 
			
		||||
    {
 | 
			
		||||
        return _SC(""); // Default to empty string
 | 
			
		||||
    }
 | 
			
		||||
    // Apply the format specifier
 | 
			
		||||
    fs[1] = spec;
 | 
			
		||||
    // Attempt to escape the specified string
 | 
			
		||||
    sqlite3_snprintf(GetTempBuffSize(), GetTempBuff(), fs, str.mPtr);
 | 
			
		||||
    // Restore the format specifier
 | 
			
		||||
    fs[1] = 'q';
 | 
			
		||||
    // Return the resulted string
 | 
			
		||||
    return GetTempBuff();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
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
 | 
			
		||||
    auto itr = values.begin();
 | 
			
		||||
    // Process all elements within range
 | 
			
		||||
    for (; itr != values.end() && offset < GetTempBuffSize(); ++itr)
 | 
			
		||||
    {
 | 
			
		||||
        // Is the name valid?
 | 
			
		||||
        if (itr->empty())
 | 
			
		||||
        {
 | 
			
		||||
            STHROWF("Invalid column name");
 | 
			
		||||
        }
 | 
			
		||||
        // Attempt to append the column name to the buffer
 | 
			
		||||
        sqlite3_snprintf(static_cast< int >(GetTempBuffSize() - offset), GetTempBuff() + 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)
 | 
			
		||||
    {
 | 
			
		||||
        GetTempBuff()[offset-2] = '\0';
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        GetTempBuff()[0] = '\0';
 | 
			
		||||
    }
 | 
			
		||||
    // Return the resulted string
 | 
			
		||||
    return GetTempBuff();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
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())
 | 
			
		||||
        {
 | 
			
		||||
            STHROWF("Invalid or empty column name");
 | 
			
		||||
        }
 | 
			
		||||
        // Attempt to append the column name to the buffer
 | 
			
		||||
        sqlite3_snprintf(static_cast< int >(GetTempBuffSize() - offset), GetTempBuff() + 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)
 | 
			
		||||
    {
 | 
			
		||||
        GetTempBuff()[offset-2] = '\0';
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        GetTempBuff()[0] = '\0';
 | 
			
		||||
    }
 | 
			
		||||
    // Return the resulted string
 | 
			
		||||
    return GetTempBuff();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ================================================================================================
 | 
			
		||||
void Register_Common(Table & sqlns)
 | 
			
		||||
{
 | 
			
		||||
    sqlns.Func(_SC("IsQueryEmpty"), &IsQueryEmpty)
 | 
			
		||||
        .Func(_SC("GetErrStr"), &GetErrStr)
 | 
			
		||||
        .Func(_SC("SetSoftHeapLimit"), &SetSoftHeapLimit)
 | 
			
		||||
        .Func(_SC("ReleaseMemory"), &ReleaseMemory)
 | 
			
		||||
        .Func(_SC("MemoryUsage"), &GetMemoryUsage)
 | 
			
		||||
        .Func(_SC("MemoryHighwaterMark"), &GetMemoryHighwaterMark)
 | 
			
		||||
        .Func(_SC("ArrayToQueryColumns"), &ArrayToQueryColumns)
 | 
			
		||||
        .Func(_SC("TableToQueryColumns"), &TableToQueryColumns)
 | 
			
		||||
        .FmtFunc(_SC("EscapeString"), &EscapeString)
 | 
			
		||||
        .FmtFunc(_SC("EscapeStringEx"), &EscapeStringEx)
 | 
			
		||||
        .FmtFunc(_SC("Escape"), &EscapeString)
 | 
			
		||||
        .FmtFunc(_SC("EscapeEx"), &EscapeStringEx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
							
								
								
									
										153
									
								
								module/Library/SQLite/Common.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								module/Library/SQLite/Common.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,153 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Base/Shared.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Library/Numeric/LongInt.hpp"
 | 
			
		||||
#include "Library/Utils/Buffer.hpp"
 | 
			
		||||
#include "Library/Chrono/Date.hpp"
 | 
			
		||||
#include "Library/Chrono/Datetime.hpp"
 | 
			
		||||
#include "Library/Chrono/Time.hpp"
 | 
			
		||||
#include "Library/Chrono/Timestamp.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#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) 2018 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
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Handle validation.
 | 
			
		||||
*/
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    #define SQMOD_THROW_CURRENT(x, a)       (x).ThrowCurrent(a, __FILE__, __LINE__)
 | 
			
		||||
    #define SQMOD_VALIDATE(x)               (x).Validate(__FILE__, __LINE__)
 | 
			
		||||
    #define SQMOD_VALIDATE_CREATED(x)       (x).ValidateCreated(__FILE__, __LINE__)
 | 
			
		||||
    #define SQMOD_VALIDATE_PARAM(x, i)      (x).ValidateParam((i), __FILE__, __LINE__)
 | 
			
		||||
    #define SQMOD_VALIDATE_COLUMN(x, i)     (x).ValidateColumn((i), __FILE__, __LINE__)
 | 
			
		||||
    #define SQMOD_VALIDATE_ROW(x)           (x).ValidateRow(__FILE__, __LINE__)
 | 
			
		||||
    #define SQMOD_GET_VALID(x)              (x).GetValid(__FILE__, __LINE__)
 | 
			
		||||
    #define SQMOD_GET_CREATED(x)            (x).GetCreated(__FILE__, __LINE__)
 | 
			
		||||
#else
 | 
			
		||||
    #define SQMOD_THROW_CURRENT(x, a)       (x).ThrowCurrent(a)
 | 
			
		||||
    #define SQMOD_VALIDATE(x)               (x).Validate()
 | 
			
		||||
    #define SQMOD_VALIDATE_CREATED(x)       (x).ValidateCreated()
 | 
			
		||||
    #define SQMOD_VALIDATE_PARAM(x, i)      (x).ValidateParam((i))
 | 
			
		||||
    #define SQMOD_VALIDATE_COLUMN(x, i)     (x).ValidateColumn((i))
 | 
			
		||||
    #define SQMOD_VALIDATE_ROW(x)           (x).ValidateRow()
 | 
			
		||||
    #define SQMOD_GET_VALID(x)              (x).GetValid()
 | 
			
		||||
    #define SQMOD_GET_CREATED(x)            (x).GetCreated()
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Helper macros for architecture differences.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifdef _SQ64
 | 
			
		||||
    #define sqlite3_bind_integer    sqlite3_bind_int64
 | 
			
		||||
    #define sqlite3_column_integer  sqlite3_column_int64
 | 
			
		||||
#else
 | 
			
		||||
    #define sqlite3_bind_integer    sqlite3_bind_int
 | 
			
		||||
    #define sqlite3_column_integer  sqlite3_column_int
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Forward declarations.
 | 
			
		||||
*/
 | 
			
		||||
struct ConnHnd;
 | 
			
		||||
struct StmtHnd;
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Common typedefs.
 | 
			
		||||
*/
 | 
			
		||||
typedef SharedPtr< ConnHnd > ConnRef;
 | 
			
		||||
typedef SharedPtr< StmtHnd > StmtRef;
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Obtain a script object from a connection handle. (meant to avoid having to include the header)
 | 
			
		||||
*/
 | 
			
		||||
Object GetConnectionObj(const ConnRef & conn);
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Obtain a script object from a statement handle. (meant to avoid having to include the header)
 | 
			
		||||
*/
 | 
			
		||||
Object GetStatementObj(const StmtRef & stmt);
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Generate a formatted query.
 | 
			
		||||
*/
 | 
			
		||||
CSStr QFmtStr(CSStr str, ...);
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Tests if a certain query string is empty.
 | 
			
		||||
*/
 | 
			
		||||
bool IsQueryEmpty(CSStr str);
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Retrieve the string representation of a certain status code.
 | 
			
		||||
*/
 | 
			
		||||
CSStr GetErrStr(Int32 status);
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Set a specific heap limit.
 | 
			
		||||
*/
 | 
			
		||||
void SetSoftHeapLimit(Int32 limit);
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Release the specified amount of memory.
 | 
			
		||||
*/
 | 
			
		||||
Int32 ReleaseMemory(Int32 bytes);
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Retrieve the current memory usage.
 | 
			
		||||
*/
 | 
			
		||||
Object GetMemoryUsage();
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Retrieve the memory high watermark.
 | 
			
		||||
*/
 | 
			
		||||
Object GetMemoryHighwaterMark(bool reset);
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Retrieve the escaped version of the specified string.
 | 
			
		||||
*/
 | 
			
		||||
CSStr EscapeString(StackStrF & str);
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Retrieve the escaped version of the specified string using the supplied format specifier.
 | 
			
		||||
*/
 | 
			
		||||
CCStr EscapeStringEx(SQChar spec, StackStrF & str);
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Convert the values from the specified array to a list of column names string.
 | 
			
		||||
*/
 | 
			
		||||
CCStr ArrayToQueryColumns(Array & arr);
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Convert the keys from the specified array to a list of column names string.
 | 
			
		||||
*/
 | 
			
		||||
CCStr TableToQueryColumns(Table & tbl);
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
							
								
								
									
										407
									
								
								module/Library/SQLite/Connection.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										407
									
								
								module/Library/SQLite/Connection.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,407 @@
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Library/SQLite/Connection.hpp"
 | 
			
		||||
#include "Library/SQLite/Statement.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
SQMODE_DECL_TYPENAME(Typename, _SC("SqLiteConnection"))
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Connection::TraceOutput(void * /*ptr*/, CCStr sql)
 | 
			
		||||
{
 | 
			
		||||
    LogInf("SQLite Trace: %s", sql);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Connection::ProfileOutput(void * /*ptr*/, CCStr sql, sqlite3_uint64 time)
 | 
			
		||||
{
 | 
			
		||||
    LogInf("SQLite profile (time: %llu): %s", time, sql);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
void Connection::Validate(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid SQLite connection reference =>[%s:%d]", file, line);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
void Connection::Validate() const
 | 
			
		||||
{
 | 
			
		||||
    if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid SQLite connection reference");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
void Connection::ValidateCreated(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid SQLite connection reference =>[%s:%d]", file, line);
 | 
			
		||||
    }
 | 
			
		||||
    else if (m_Handle->mPtr == nullptr)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid SQLite connection =>[%s:%d]", file, line);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
void Connection::ValidateCreated() const
 | 
			
		||||
{
 | 
			
		||||
    if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid SQLite connection reference");
 | 
			
		||||
    }
 | 
			
		||||
    else if (m_Handle->mPtr == nullptr)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid SQLite connection");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
const ConnRef & Connection::GetValid(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    Validate(file, line);
 | 
			
		||||
    return m_Handle;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
const ConnRef & Connection::GetValid() const
 | 
			
		||||
{
 | 
			
		||||
    Validate();
 | 
			
		||||
    return m_Handle;
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
const ConnRef & Connection::GetCreated(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    ValidateCreated(file, line);
 | 
			
		||||
    return m_Handle;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
const ConnRef & Connection::GetCreated() const
 | 
			
		||||
{
 | 
			
		||||
    ValidateCreated();
 | 
			
		||||
    return m_Handle;
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Connection::Open(StackStrF & name)
 | 
			
		||||
{
 | 
			
		||||
    // Should we create a connection handle?
 | 
			
		||||
    if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        m_Handle = ConnRef(new ConnHnd());
 | 
			
		||||
    }
 | 
			
		||||
    // Make sure another database isn't opened
 | 
			
		||||
    if (SQMOD_GET_VALID(*this)->mPtr != nullptr)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Already referencing a valid database connection");
 | 
			
		||||
    }
 | 
			
		||||
    // Effing signed/unsigned warnings everywhere. I just need it to shut up.
 | 
			
		||||
    constexpr unsigned OPEN_READWRITE_F = SQLITE_OPEN_READWRITE;
 | 
			
		||||
    constexpr unsigned OPEN_CREATE_F = SQLITE_OPEN_CREATE;
 | 
			
		||||
    // Perform the requested operation
 | 
			
		||||
    m_Handle->Create(name.mPtr, OPEN_READWRITE_F | OPEN_CREATE_F, nullptr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Connection::Open(StackStrF & name, Int32 flags)
 | 
			
		||||
{
 | 
			
		||||
    // Should we create a connection handle?
 | 
			
		||||
    if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        m_Handle = ConnRef(new ConnHnd());
 | 
			
		||||
    }
 | 
			
		||||
    // Make sure another database isn't opened
 | 
			
		||||
    if (SQMOD_GET_VALID(*this)->mPtr != nullptr)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Already referencing a valid database connection");
 | 
			
		||||
    }
 | 
			
		||||
    // Perform the requested operation
 | 
			
		||||
    m_Handle->Create(name.mPtr, flags, nullptr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Connection::Open(StackStrF & name, Int32 flags, StackStrF & vfs)
 | 
			
		||||
{
 | 
			
		||||
    // Should we create a connection handle?
 | 
			
		||||
    if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        m_Handle = ConnRef(new ConnHnd());
 | 
			
		||||
    }
 | 
			
		||||
    // Make sure another database isn't opened
 | 
			
		||||
    if (SQMOD_GET_VALID(*this)->mPtr != nullptr)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Already referencing a valid database connection");
 | 
			
		||||
    }
 | 
			
		||||
    // Perform the requested operation
 | 
			
		||||
    m_Handle->Create(name.mPtr, flags, vfs.mPtr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Int32 Connection::Exec(StackStrF & str)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Attempt to execute the specified query
 | 
			
		||||
    m_Handle->mStatus = sqlite3_exec(m_Handle->mPtr, str.mPtr, nullptr, nullptr, nullptr);
 | 
			
		||||
    // Validate the execution result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Unable to execute query [%s]", m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
    // Return rows affected by this query
 | 
			
		||||
    return sqlite3_changes(m_Handle->mPtr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Object Connection::Query(StackStrF & str) const
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Return the requested information
 | 
			
		||||
    return Object(new Statement(m_Handle, str));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Connection::Queue(StackStrF & str)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE(*this);
 | 
			
		||||
    // Is there a query to commit?
 | 
			
		||||
    if (!str.mLen || IsQueryEmpty(str.mPtr))
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("No query string to queue");
 | 
			
		||||
    }
 | 
			
		||||
    // Add the specified string to the queue
 | 
			
		||||
    m_Handle->mQueue.emplace_back(str.mPtr, str.mLen);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
bool Connection::IsReadOnly() const
 | 
			
		||||
{
 | 
			
		||||
    // Request the desired information
 | 
			
		||||
    const int result = sqlite3_db_readonly(SQMOD_GET_CREATED(*this)->mPtr, "main");
 | 
			
		||||
    // Verify the result
 | 
			
		||||
    if (result == -1)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("'main' is not the name of a database on connection");
 | 
			
		||||
    }
 | 
			
		||||
    // Return the requested information
 | 
			
		||||
    return (result != 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
bool Connection::TableExists(StackStrF & name) const
 | 
			
		||||
{
 | 
			
		||||
    StackStrF query("SELECT count(*) FROM [sqlite_master] WHERE [type]='table' AND [name]=?");
 | 
			
		||||
    // Prepare a statement to inspect the master table
 | 
			
		||||
    Statement stmt(SQMOD_GET_CREATED(*this), query);
 | 
			
		||||
    // Could the statement be created?
 | 
			
		||||
    if (stmt.IsValid())
 | 
			
		||||
    {
 | 
			
		||||
        // Bind the specified name onto the statement parameter
 | 
			
		||||
        Parameter(stmt.GetHandle(), 1).SetString(name);
 | 
			
		||||
        // Attempt to step the statement and obtain a value
 | 
			
		||||
        if (stmt.Step())
 | 
			
		||||
        {
 | 
			
		||||
            return (sqlite3_column_int(stmt, 0) == 1);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // Assume it doesn't exist
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Connection::SetTracing(bool toggle)
 | 
			
		||||
{
 | 
			
		||||
    // Check whether changes are necessary
 | 
			
		||||
    if (SQMOD_GET_CREATED(*this)->mTrace == toggle)
 | 
			
		||||
    {
 | 
			
		||||
        return; // No point in proceeding
 | 
			
		||||
    }
 | 
			
		||||
    // Do we have to disable it?
 | 
			
		||||
    else if (m_Handle->mTrace)
 | 
			
		||||
    {
 | 
			
		||||
        sqlite3_trace(m_Handle->mPtr, nullptr, nullptr);
 | 
			
		||||
    }
 | 
			
		||||
    // Go ahead and enable tracing
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        sqlite3_trace(m_Handle->mPtr, &Connection::TraceOutput, nullptr);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Connection::SetProfiling(bool toggle)
 | 
			
		||||
{
 | 
			
		||||
    // Check whether changes are necessary
 | 
			
		||||
    if (SQMOD_GET_CREATED(*this)->mProfile == toggle)
 | 
			
		||||
    {
 | 
			
		||||
        return; // No point in proceeding
 | 
			
		||||
    }
 | 
			
		||||
    // Do we have to disable it?
 | 
			
		||||
    else if (m_Handle->mProfile)
 | 
			
		||||
    {
 | 
			
		||||
        sqlite3_profile(m_Handle->mPtr, nullptr, nullptr);
 | 
			
		||||
    }
 | 
			
		||||
    // Go ahead and enable profiling
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        sqlite3_profile(m_Handle->mPtr, &Connection::ProfileOutput, nullptr);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Connection::SetBusyTimeout(Int32 millis)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Apply the requested timeout
 | 
			
		||||
    if ((m_Handle->mStatus = sqlite3_busy_timeout(m_Handle->mPtr, millis)) != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Unable to set busy timeout [%s]", m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Int32 Connection::GetInfo(Int32 operation, bool highwater, bool reset)
 | 
			
		||||
{
 | 
			
		||||
    // Where to retrieve the information
 | 
			
		||||
    Int32 cur_value;
 | 
			
		||||
    Int32 hiwtr_value;
 | 
			
		||||
    // Attempt to retrieve the specified information
 | 
			
		||||
    if ((m_Handle->mStatus = sqlite3_db_status(SQMOD_GET_CREATED(*this)->mPtr, operation, &cur_value, &hiwtr_value, reset)) != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Unable to get runtime status information", m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
    // Return the high-water value if requested
 | 
			
		||||
    else if (highwater)
 | 
			
		||||
    {
 | 
			
		||||
        return hiwtr_value;
 | 
			
		||||
    }
 | 
			
		||||
    // Return the requested information
 | 
			
		||||
    return cur_value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Connection::ReserveQueue(Uint32 num)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE(*this);
 | 
			
		||||
    // Perform the requested operation
 | 
			
		||||
    m_Handle->mQueue.reserve(m_Handle->mQueue.size() + num);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Connection::PopQueue()
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE(*this);
 | 
			
		||||
    // Perform the requested operation
 | 
			
		||||
    if (!SQMOD_GET_VALID(*this)->mQueue.empty())
 | 
			
		||||
    {
 | 
			
		||||
        m_Handle->mQueue.pop_back();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Int32 Connection::Flush()
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Perform the requested operation
 | 
			
		||||
    return m_Handle->Flush(m_Handle->mQueue.size(), NullObject(), NullFunction());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Int32 Connection::Flush(SQInteger num)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Perform the requested operation
 | 
			
		||||
    return m_Handle->Flush(ConvTo< Uint32 >::From(num), NullObject(), NullFunction());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Int32 Connection::Flush(Object & env, Function & func)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Perform the requested operation
 | 
			
		||||
    return m_Handle->Flush(m_Handle->mQueue.size(), env, func);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Int32 Connection::Flush(SQInteger num, Object & env, Function & func)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Perform the requested operation
 | 
			
		||||
    return m_Handle->Flush(ConvTo< Uint32 >::From(num), env, func);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ================================================================================================
 | 
			
		||||
void Register_Connection(Table & sqlns)
 | 
			
		||||
{
 | 
			
		||||
    sqlns.Bind(_SC("Connection"),
 | 
			
		||||
        Class< Connection >(sqlns.GetVM(), Typename::Str)
 | 
			
		||||
        // Constructors
 | 
			
		||||
        .Ctor()
 | 
			
		||||
        .Ctor< StackStrF & >()
 | 
			
		||||
        .Ctor< StackStrF &, Int32 >()
 | 
			
		||||
        .Ctor< StackStrF &, Int32, StackStrF & >()
 | 
			
		||||
        // Meta-methods
 | 
			
		||||
        .SquirrelFunc(_SC("_typename"), &Typename::Fn)
 | 
			
		||||
        .Func(_SC("_tostring"), &Connection::ToString)
 | 
			
		||||
        // Properties
 | 
			
		||||
        .Prop(_SC("IsValid"), &Connection::IsValid)
 | 
			
		||||
        .Prop(_SC("Connected"), &Connection::IsConnected)
 | 
			
		||||
        .Prop(_SC("References"), &Connection::GetRefCount)
 | 
			
		||||
        .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("QueueSize"), &Connection::QueueSize)
 | 
			
		||||
        // Member Methods
 | 
			
		||||
        .Func(_SC("Release"), &Connection::Release)
 | 
			
		||||
        .FmtFunc(_SC("Exec"), &Connection::Exec)
 | 
			
		||||
        .FmtFunc(_SC("Queue"), &Connection::Queue)
 | 
			
		||||
        .FmtFunc(_SC("Query"), &Connection::Query)
 | 
			
		||||
        .FmtFunc(_SC("TableExists"), &Connection::TableExists)
 | 
			
		||||
        .Func(_SC("InterruptOperation"), &Connection::InterruptOperation)
 | 
			
		||||
        .Func(_SC("SetBusyTimeout"), &Connection::SetBusyTimeout)
 | 
			
		||||
        .Func(_SC("ReleaseMemory"), &Connection::ReleaseMemory)
 | 
			
		||||
        .Func(_SC("ReserveQueue"), &Connection::ReserveQueue)
 | 
			
		||||
        .Func(_SC("CompactQueue"), &Connection::CompactQueue)
 | 
			
		||||
        .Func(_SC("ClearQueue"), &Connection::ClearQueue)
 | 
			
		||||
        .Func(_SC("PopQueue"), &Connection::PopQueue)
 | 
			
		||||
        // Member Overloads
 | 
			
		||||
        .Overload< void (Connection::*)(StackStrF &) >(_SC("Open"), &Connection::Open)
 | 
			
		||||
        .Overload< void (Connection::*)(StackStrF &, Int32) >(_SC("Open"), &Connection::Open)
 | 
			
		||||
        .Overload< void (Connection::*)(StackStrF &, Int32, StackStrF &) >(_SC("Open"), &Connection::Open)
 | 
			
		||||
        .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)
 | 
			
		||||
        .Overload< Int32 (Connection::*)(void) >(_SC("Flush"), &Connection::Flush)
 | 
			
		||||
        .Overload< Int32 (Connection::*)(SQInteger) >(_SC("Flush"), &Connection::Flush)
 | 
			
		||||
        .Overload< Int32 (Connection::*)(Object &, Function &) >(_SC("Flush"), &Connection::Flush)
 | 
			
		||||
        .Overload< Int32 (Connection::*)(SQInteger, Object &, Function &) >(_SC("Flush"), &Connection::Flush)
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
							
								
								
									
										481
									
								
								module/Library/SQLite/Connection.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										481
									
								
								module/Library/SQLite/Connection.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,481 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Library/SQLite/Handle.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include <utility>
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Used to manage and interact with a database connection.
 | 
			
		||||
*/
 | 
			
		||||
class Connection
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    ConnRef m_Handle; // Reference to the managed connection.
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Callback function for ActivateTracing()
 | 
			
		||||
    */
 | 
			
		||||
    static void TraceOutput(void * ptr, CCStr sql);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Callback function for ActivateProfiling()
 | 
			
		||||
    */
 | 
			
		||||
    static void ProfileOutput(void * ptr, CCStr sql, sqlite3_uint64 time);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the managed connection handle and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    void Validate(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    void Validate() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the managed connection handle and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    void ValidateCreated(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    void ValidateCreated() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the managed connection handle and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    const ConnRef & GetValid(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    const ConnRef & GetValid() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the managed connection handle and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    const ConnRef & GetCreated(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    const ConnRef & GetCreated() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to open the specified database.
 | 
			
		||||
    */
 | 
			
		||||
    Connection()
 | 
			
		||||
        : m_Handle()
 | 
			
		||||
    {
 | 
			
		||||
        /* ... */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Explicit constructor.
 | 
			
		||||
    */
 | 
			
		||||
    explicit Connection(StackStrF & name)
 | 
			
		||||
        : m_Handle(new ConnHnd())
 | 
			
		||||
    {
 | 
			
		||||
        // Effing signed/unsigned warnings everywhere. I just need it to shut up.
 | 
			
		||||
        constexpr unsigned OPEN_READWRITE_F = SQLITE_OPEN_READWRITE;
 | 
			
		||||
        constexpr unsigned OPEN_CREATE_F = SQLITE_OPEN_CREATE;
 | 
			
		||||
        SQMOD_GET_VALID(*this)->Create(name.mPtr, OPEN_READWRITE_F | OPEN_CREATE_F, nullptr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Explicit constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Connection(StackStrF & name, Int32 flags)
 | 
			
		||||
        : m_Handle(new ConnHnd())
 | 
			
		||||
    {
 | 
			
		||||
        SQMOD_GET_VALID(*this)->Create(name.mPtr, flags, nullptr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Explicit constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Connection(StackStrF & name, Int32 flags, StackStrF & vfs)
 | 
			
		||||
        : m_Handle(new ConnHnd())
 | 
			
		||||
    {
 | 
			
		||||
        SQMOD_GET_VALID(*this)->Create(name.mPtr, flags, vfs.mPtr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Direct handle constructor.
 | 
			
		||||
    */
 | 
			
		||||
    explicit Connection(ConnRef c)
 | 
			
		||||
        : m_Handle(std::move(c))
 | 
			
		||||
    {
 | 
			
		||||
        /* ... */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Connection(const Connection & o) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Move constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Connection(Connection && o) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy assignment operator.
 | 
			
		||||
    */
 | 
			
		||||
    Connection & operator = (const Connection & o) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Move assignment operator.
 | 
			
		||||
    */
 | 
			
		||||
    Connection & operator = (Connection && o) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * 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 * () //NOLINT (intentionally implicit)
 | 
			
		||||
    {
 | 
			
		||||
        return m_Handle ? m_Handle->mPtr : nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Implicit conversion to the raw connection handle.
 | 
			
		||||
    */
 | 
			
		||||
    operator sqlite3 * () const //NOLINT (intentionally implicit)
 | 
			
		||||
    {
 | 
			
		||||
        return m_Handle ? m_Handle->mPtr : nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Used by the script engine to convert an instance of this type to a string.
 | 
			
		||||
    */
 | 
			
		||||
    const String & ToString() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Handle ? m_Handle->mName : NullString();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the associated connection handle.
 | 
			
		||||
    */
 | 
			
		||||
    const ConnRef & GetHandle() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Handle;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * See whether the managed connection handle is valid.
 | 
			
		||||
    */
 | 
			
		||||
    bool IsValid() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Handle;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * See whether the managed connection handle was connected.
 | 
			
		||||
    */
 | 
			
		||||
    bool IsConnected() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Handle && (m_Handle->mPtr != nullptr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * 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.Reset();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the last received status code.
 | 
			
		||||
    */
 | 
			
		||||
    Int32 GetStatus() const
 | 
			
		||||
    {
 | 
			
		||||
        return SQMOD_GET_VALID(*this)->mStatus;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the flags used to create this database connection.
 | 
			
		||||
    */
 | 
			
		||||
    Int32 GetFlags() const
 | 
			
		||||
    {
 | 
			
		||||
        return SQMOD_GET_VALID(*this)->mFlags;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the name used to create this database connection.
 | 
			
		||||
    */
 | 
			
		||||
    const String & GetName() const
 | 
			
		||||
    {
 | 
			
		||||
        return SQMOD_GET_VALID(*this)->mName;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the virtual file system used to create this database connection.
 | 
			
		||||
    */
 | 
			
		||||
    const String & GetVFS() const
 | 
			
		||||
    {
 | 
			
		||||
        return SQMOD_GET_VALID(*this)->mVFS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Return the numeric result code for the most recent failed API call (if any).
 | 
			
		||||
    */
 | 
			
		||||
    Int32 GetErrorCode() const
 | 
			
		||||
    {
 | 
			
		||||
        return SQMOD_GET_VALID(*this)->ErrNo();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Return the extended numeric result code for the most recent failed API call (if any).
 | 
			
		||||
    */
 | 
			
		||||
    Int32 GetExtendedErrorCode() const
 | 
			
		||||
    {
 | 
			
		||||
        return SQMOD_GET_VALID(*this)->ExErrNo();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the message of the last received error code.
 | 
			
		||||
    */
 | 
			
		||||
    CSStr GetErrStr() const
 | 
			
		||||
    {
 | 
			
		||||
        return SQMOD_GET_VALID(*this)->ErrStr();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Return the last error message associated with this database connection.
 | 
			
		||||
    */
 | 
			
		||||
    CSStr GetErrMsg() const
 | 
			
		||||
    {
 | 
			
		||||
        return SQMOD_GET_VALID(*this)->ErrMsg();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to open the specified database.
 | 
			
		||||
    */
 | 
			
		||||
    void Open(StackStrF & name);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to open the specified database.
 | 
			
		||||
    */
 | 
			
		||||
    void Open(StackStrF & name, Int32 flags);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to open the specified database.
 | 
			
		||||
    */
 | 
			
		||||
    void Open(StackStrF & name, Int32 flags, StackStrF & vfs);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to execute the specified query.
 | 
			
		||||
    */
 | 
			
		||||
    Int32 Exec(StackStrF & str);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to queue the specified query.
 | 
			
		||||
    */
 | 
			
		||||
    void Queue(StackStrF & str);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to create a statement from the specified query.
 | 
			
		||||
    */
 | 
			
		||||
    Object Query(StackStrF & 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(StackStrF & name) const;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * See if the database connection is or is not in auto-commit mode.
 | 
			
		||||
    */
 | 
			
		||||
    bool GetAutoCommit() const
 | 
			
		||||
    {
 | 
			
		||||
        return sqlite3_get_autocommit(SQMOD_GET_CREATED(*this)->mPtr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Get the row-id of the most recent successful INSERT into the database from the current connection.
 | 
			
		||||
    */
 | 
			
		||||
    Object GetLastInsertRowID() const
 | 
			
		||||
    {
 | 
			
		||||
        return Object(new SLongInt(sqlite3_last_insert_rowid(SQMOD_GET_CREATED(*this)->mPtr)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Returns the number of database rows that were changed, inserted or deleted
 | 
			
		||||
     * by the most recently completed SQL statement.
 | 
			
		||||
    */
 | 
			
		||||
    Int32 GetChanges() const
 | 
			
		||||
    {
 | 
			
		||||
        return sqlite3_changes(SQMOD_GET_CREATED(*this)->mPtr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Returns the total number of row changes caused by INSERT, UPDATE or DELETE statements
 | 
			
		||||
     * since the database connection was opened.
 | 
			
		||||
    */
 | 
			
		||||
    Int32 GetTotalChanges() const
 | 
			
		||||
    {
 | 
			
		||||
        return sqlite3_total_changes(SQMOD_GET_CREATED(*this)->mPtr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * See if this database connection has tracing enabled.
 | 
			
		||||
    */
 | 
			
		||||
    bool GetTracing() const
 | 
			
		||||
    {
 | 
			
		||||
        return SQMOD_GET_VALID(*this)->mTrace;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Activate or deactivate tracing on this database connection.
 | 
			
		||||
    */
 | 
			
		||||
    void SetTracing(bool toggle);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * See if this database connection has profiling enabled.
 | 
			
		||||
    */
 | 
			
		||||
    bool GetProfiling() const
 | 
			
		||||
    {
 | 
			
		||||
        return SQMOD_GET_VALID(*this)->mProfile;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Activate or deactivate profiling on this database connection.
 | 
			
		||||
    */
 | 
			
		||||
    void SetProfiling(bool toggle);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * 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
 | 
			
		||||
    {
 | 
			
		||||
        sqlite3_interrupt(SQMOD_GET_CREATED(*this)->mPtr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempts to free as much heap memory as possible from the database connection.
 | 
			
		||||
    */
 | 
			
		||||
    void ReleaseMemory() const
 | 
			
		||||
    {
 | 
			
		||||
        sqlite3_db_release_memory(SQMOD_GET_CREATED(*this)->mPtr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * 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)
 | 
			
		||||
    {
 | 
			
		||||
        return GetInfo(operation, highwater, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Returns internal runtime status information associated with the current database connection.
 | 
			
		||||
    */
 | 
			
		||||
    Int32 GetInfo(Int32 operation, bool highwater, bool reset);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the number of queries in the queue.
 | 
			
		||||
    */
 | 
			
		||||
    Uint32 QueueSize() const
 | 
			
		||||
    {
 | 
			
		||||
        return ConvTo< Uint32 >::From(SQMOD_GET_VALID(*this)->mQueue.size());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Reserve space upfront for the specified amount of queries in the query queue.
 | 
			
		||||
    */
 | 
			
		||||
    void ReserveQueue(Uint32 num);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Release memory that is not occupied from the query queue.
 | 
			
		||||
    */
 | 
			
		||||
    void CompactQueue()
 | 
			
		||||
    {
 | 
			
		||||
        SQMOD_GET_VALID(*this)->mQueue.shrink_to_fit();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Remove all queries from the queue without executing them.
 | 
			
		||||
    */
 | 
			
		||||
    void ClearQueue()
 | 
			
		||||
    {
 | 
			
		||||
        SQMOD_GET_VALID(*this)->mQueue.clear();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Remove the last query from the queue.
 | 
			
		||||
    */
 | 
			
		||||
    void PopQueue();
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Flush all queries from the queue.
 | 
			
		||||
    */
 | 
			
		||||
    Int32 Flush();
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Flush a specific amount of queries from the queue.
 | 
			
		||||
    */
 | 
			
		||||
    Int32 Flush(SQInteger num);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Flush all queries from the queue and handle errors manually.
 | 
			
		||||
    */
 | 
			
		||||
    Int32 Flush(Object & env, Function & func);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Flush a specific amount of queries from the queue and handle errors manually.
 | 
			
		||||
    */
 | 
			
		||||
    Int32 Flush(SQInteger num, Object & env, Function & func);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
							
								
								
									
										367
									
								
								module/Library/SQLite/Constants.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										367
									
								
								module/Library/SQLite/Constants.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,367 @@
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Library/SQLite/Common.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Helper class that represents an integral enumeration value. Used to reduce compilation times.
 | 
			
		||||
*/
 | 
			
		||||
struct EnumElement
 | 
			
		||||
{
 | 
			
		||||
    CSStr Name;
 | 
			
		||||
    Int32 Value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
static const EnumElement g_MainEnum[] = {
 | 
			
		||||
    {_SC("ABORT"),                                SQLITE_ABORT},
 | 
			
		||||
    {_SC("ABORT_ROLLBACK"),                       SQLITE_ABORT_ROLLBACK},
 | 
			
		||||
    {_SC("ACCESS_EXISTS"),                        SQLITE_ACCESS_EXISTS},
 | 
			
		||||
    {_SC("ACCESS_READ"),                          SQLITE_ACCESS_READ},
 | 
			
		||||
    {_SC("ACCESS_READWRITE"),                     SQLITE_ACCESS_READWRITE},
 | 
			
		||||
    {_SC("ALTER_TABLE"),                          SQLITE_ALTER_TABLE},
 | 
			
		||||
    {_SC("ANALYZE"),                              SQLITE_ANALYZE},
 | 
			
		||||
    {_SC("ANY"),                                  SQLITE_ANY},
 | 
			
		||||
    {_SC("ATTACH"),                               SQLITE_ATTACH},
 | 
			
		||||
    {_SC("AUTH"),                                 SQLITE_AUTH},
 | 
			
		||||
    {_SC("AUTH_USER"),                            SQLITE_AUTH_USER},
 | 
			
		||||
    {_SC("BLOB"),                                 SQLITE_BLOB},
 | 
			
		||||
    {_SC("BUSY"),                                 SQLITE_BUSY},
 | 
			
		||||
    {_SC("BUSY_RECOVERY"),                        SQLITE_BUSY_RECOVERY},
 | 
			
		||||
    {_SC("BUSY_SNAPSHOT"),                        SQLITE_BUSY_SNAPSHOT},
 | 
			
		||||
    {_SC("CANTOPEN"),                             SQLITE_CANTOPEN},
 | 
			
		||||
    {_SC("CANTOPEN_CONVPATH"),                    SQLITE_CANTOPEN_CONVPATH},
 | 
			
		||||
    {_SC("CANTOPEN_FULLPATH"),                    SQLITE_CANTOPEN_FULLPATH},
 | 
			
		||||
    {_SC("CANTOPEN_ISDIR"),                       SQLITE_CANTOPEN_ISDIR},
 | 
			
		||||
    {_SC("CANTOPEN_NOTEMPDIR"),                   SQLITE_CANTOPEN_NOTEMPDIR},
 | 
			
		||||
    {_SC("CHECKPOINT_FULL"),                      SQLITE_CHECKPOINT_FULL},
 | 
			
		||||
    {_SC("CHECKPOINT_PASSIVE"),                   SQLITE_CHECKPOINT_PASSIVE},
 | 
			
		||||
    {_SC("CHECKPOINT_RESTART"),                   SQLITE_CHECKPOINT_RESTART},
 | 
			
		||||
    {_SC("CHECKPOINT_TRUNCATE"),                  SQLITE_CHECKPOINT_TRUNCATE},
 | 
			
		||||
    {_SC("CONFIG_COVERING_INDEX_SCAN"),           SQLITE_CONFIG_COVERING_INDEX_SCAN},
 | 
			
		||||
    {_SC("CONFIG_GETMALLOC"),                     SQLITE_CONFIG_GETMALLOC},
 | 
			
		||||
    {_SC("CONFIG_GETMUTEX"),                      SQLITE_CONFIG_GETMUTEX},
 | 
			
		||||
    {_SC("CONFIG_GETPCACHE"),                     SQLITE_CONFIG_GETPCACHE},
 | 
			
		||||
    {_SC("CONFIG_GETPCACHE2"),                    SQLITE_CONFIG_GETPCACHE2},
 | 
			
		||||
    {_SC("CONFIG_HEAP"),                          SQLITE_CONFIG_HEAP},
 | 
			
		||||
    {_SC("CONFIG_LOG"),                           SQLITE_CONFIG_LOG},
 | 
			
		||||
    {_SC("CONFIG_LOOKASIDE"),                     SQLITE_CONFIG_LOOKASIDE},
 | 
			
		||||
    {_SC("CONFIG_MALLOC"),                        SQLITE_CONFIG_MALLOC},
 | 
			
		||||
    {_SC("CONFIG_MEMSTATUS"),                     SQLITE_CONFIG_MEMSTATUS},
 | 
			
		||||
    {_SC("CONFIG_MMAP_SIZE"),                     SQLITE_CONFIG_MMAP_SIZE},
 | 
			
		||||
    {_SC("CONFIG_MULTITHREAD"),                   SQLITE_CONFIG_MULTITHREAD},
 | 
			
		||||
    {_SC("CONFIG_MUTEX"),                         SQLITE_CONFIG_MUTEX},
 | 
			
		||||
    {_SC("CONFIG_PAGECACHE"),                     SQLITE_CONFIG_PAGECACHE},
 | 
			
		||||
    {_SC("CONFIG_PCACHE"),                        SQLITE_CONFIG_PCACHE},
 | 
			
		||||
    {_SC("CONFIG_PCACHE2"),                       SQLITE_CONFIG_PCACHE2},
 | 
			
		||||
    {_SC("CONFIG_PCACHE_HDRSZ"),                  SQLITE_CONFIG_PCACHE_HDRSZ},
 | 
			
		||||
    {_SC("CONFIG_PMASZ"),                         SQLITE_CONFIG_PMASZ},
 | 
			
		||||
    {_SC("CONFIG_SCRATCH"),                       SQLITE_CONFIG_SCRATCH},
 | 
			
		||||
    {_SC("CONFIG_SERIALIZED"),                    SQLITE_CONFIG_SERIALIZED},
 | 
			
		||||
    {_SC("CONFIG_SINGLETHREAD"),                  SQLITE_CONFIG_SINGLETHREAD},
 | 
			
		||||
    {_SC("CONFIG_SQLLOG"),                        SQLITE_CONFIG_SQLLOG},
 | 
			
		||||
    {_SC("CONFIG_URI"),                           SQLITE_CONFIG_URI},
 | 
			
		||||
    {_SC("CONFIG_WIN32_HEAPSIZE"),                SQLITE_CONFIG_WIN32_HEAPSIZE},
 | 
			
		||||
    {_SC("CONSTRAINT"),                           SQLITE_CONSTRAINT},
 | 
			
		||||
    {_SC("CONSTRAINT_CHECK"),                     SQLITE_CONSTRAINT_CHECK},
 | 
			
		||||
    {_SC("CONSTRAINT_COMMITHOOK"),                SQLITE_CONSTRAINT_COMMITHOOK},
 | 
			
		||||
    {_SC("CONSTRAINT_FOREIGNKEY"),                SQLITE_CONSTRAINT_FOREIGNKEY},
 | 
			
		||||
    {_SC("CONSTRAINT_FUNCTION"),                  SQLITE_CONSTRAINT_FUNCTION},
 | 
			
		||||
    {_SC("CONSTRAINT_NOTNULL"),                   SQLITE_CONSTRAINT_NOTNULL},
 | 
			
		||||
    {_SC("CONSTRAINT_PRIMARYKEY"),                SQLITE_CONSTRAINT_PRIMARYKEY},
 | 
			
		||||
    {_SC("CONSTRAINT_ROWID"),                     SQLITE_CONSTRAINT_ROWID},
 | 
			
		||||
    {_SC("CONSTRAINT_TRIGGER"),                   SQLITE_CONSTRAINT_TRIGGER},
 | 
			
		||||
    {_SC("CONSTRAINT_UNIQUE"),                    SQLITE_CONSTRAINT_UNIQUE},
 | 
			
		||||
    {_SC("CONSTRAINT_VTAB"),                      SQLITE_CONSTRAINT_VTAB},
 | 
			
		||||
    {_SC("COPY"),                                 SQLITE_COPY},
 | 
			
		||||
    {_SC("CORRUPT"),                              SQLITE_CORRUPT},
 | 
			
		||||
    {_SC("CORRUPT_VTAB"),                         SQLITE_CORRUPT_VTAB},
 | 
			
		||||
    {_SC("CREATE_INDEX"),                         SQLITE_CREATE_INDEX},
 | 
			
		||||
    {_SC("CREATE_TABLE"),                         SQLITE_CREATE_TABLE},
 | 
			
		||||
    {_SC("CREATE_TEMP_INDEX"),                    SQLITE_CREATE_TEMP_INDEX},
 | 
			
		||||
    {_SC("CREATE_TEMP_TABLE"),                    SQLITE_CREATE_TEMP_TABLE},
 | 
			
		||||
    {_SC("CREATE_TEMP_TRIGGER"),                  SQLITE_CREATE_TEMP_TRIGGER},
 | 
			
		||||
    {_SC("CREATE_TEMP_VIEW"),                     SQLITE_CREATE_TEMP_VIEW},
 | 
			
		||||
    {_SC("CREATE_TRIGGER"),                       SQLITE_CREATE_TRIGGER},
 | 
			
		||||
    {_SC("CREATE_VIEW"),                          SQLITE_CREATE_VIEW},
 | 
			
		||||
    {_SC("CREATE_VTABLE"),                        SQLITE_CREATE_VTABLE},
 | 
			
		||||
    {_SC("DBCONFIG_ENABLE_FKEY"),                 SQLITE_DBCONFIG_ENABLE_FKEY},
 | 
			
		||||
    {_SC("DBCONFIG_ENABLE_TRIGGER"),              SQLITE_DBCONFIG_ENABLE_TRIGGER},
 | 
			
		||||
    {_SC("DBCONFIG_LOOKASIDE"),                   SQLITE_DBCONFIG_LOOKASIDE},
 | 
			
		||||
    {_SC("DBSTATUS_CACHE_HIT"),                   SQLITE_DBSTATUS_CACHE_HIT},
 | 
			
		||||
    {_SC("DBSTATUS_CACHE_MISS"),                  SQLITE_DBSTATUS_CACHE_MISS},
 | 
			
		||||
    {_SC("DBSTATUS_CACHE_USED"),                  SQLITE_DBSTATUS_CACHE_USED},
 | 
			
		||||
    {_SC("DBSTATUS_CACHE_WRITE"),                 SQLITE_DBSTATUS_CACHE_WRITE},
 | 
			
		||||
    {_SC("DBSTATUS_DEFERRED_FKS"),                SQLITE_DBSTATUS_DEFERRED_FKS},
 | 
			
		||||
    {_SC("DBSTATUS_LOOKASIDE_HIT"),               SQLITE_DBSTATUS_LOOKASIDE_HIT},
 | 
			
		||||
    {_SC("DBSTATUS_LOOKASIDE_MISS_FULL"),         SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL},
 | 
			
		||||
    {_SC("DBSTATUS_LOOKASIDE_MISS_SIZE"),         SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE},
 | 
			
		||||
    {_SC("DBSTATUS_LOOKASIDE_USED"),              SQLITE_DBSTATUS_LOOKASIDE_USED},
 | 
			
		||||
    {_SC("DBSTATUS_MAX"),                         SQLITE_DBSTATUS_MAX},
 | 
			
		||||
    {_SC("DBSTATUS_SCHEMA_USED"),                 SQLITE_DBSTATUS_SCHEMA_USED},
 | 
			
		||||
    {_SC("DBSTATUS_STMT_USED"),                   SQLITE_DBSTATUS_STMT_USED},
 | 
			
		||||
    {_SC("DELETE"),                               SQLITE_DELETE},
 | 
			
		||||
    {_SC("DENY"),                                 SQLITE_DENY},
 | 
			
		||||
    {_SC("DETACH"),                               SQLITE_DETACH},
 | 
			
		||||
    {_SC("DETERMINISTIC"),                        SQLITE_DETERMINISTIC},
 | 
			
		||||
    {_SC("DONE"),                                 SQLITE_DONE},
 | 
			
		||||
    {_SC("DROP_INDEX"),                           SQLITE_DROP_INDEX},
 | 
			
		||||
    {_SC("DROP_TABLE"),                           SQLITE_DROP_TABLE},
 | 
			
		||||
    {_SC("DROP_TEMP_INDEX"),                      SQLITE_DROP_TEMP_INDEX},
 | 
			
		||||
    {_SC("DROP_TEMP_TABLE"),                      SQLITE_DROP_TEMP_TABLE},
 | 
			
		||||
    {_SC("DROP_TEMP_TRIGGER"),                    SQLITE_DROP_TEMP_TRIGGER},
 | 
			
		||||
    {_SC("DROP_TEMP_VIEW"),                       SQLITE_DROP_TEMP_VIEW},
 | 
			
		||||
    {_SC("DROP_TRIGGER"),                         SQLITE_DROP_TRIGGER},
 | 
			
		||||
    {_SC("DROP_VIEW"),                            SQLITE_DROP_VIEW},
 | 
			
		||||
    {_SC("DROP_VTABLE"),                          SQLITE_DROP_VTABLE},
 | 
			
		||||
    {_SC("EMPTY"),                                SQLITE_EMPTY},
 | 
			
		||||
    {_SC("ERROR"),                                SQLITE_ERROR},
 | 
			
		||||
    {_SC("FAIL"),                                 SQLITE_FAIL},
 | 
			
		||||
    {_SC("FCNTL_BUSYHANDLER"),                    SQLITE_FCNTL_BUSYHANDLER},
 | 
			
		||||
    {_SC("FCNTL_CHUNK_SIZE"),                     SQLITE_FCNTL_CHUNK_SIZE},
 | 
			
		||||
    {_SC("FCNTL_COMMIT_PHASETWO"),                SQLITE_FCNTL_COMMIT_PHASETWO},
 | 
			
		||||
    {_SC("FCNTL_FILE_POINTER"),                   SQLITE_FCNTL_FILE_POINTER},
 | 
			
		||||
    {_SC("FCNTL_GET_LOCKPROXYFILE"),              SQLITE_FCNTL_GET_LOCKPROXYFILE},
 | 
			
		||||
    {_SC("FCNTL_HAS_MOVED"),                      SQLITE_FCNTL_HAS_MOVED},
 | 
			
		||||
    {_SC("FCNTL_LAST_ERRNO"),                     SQLITE_FCNTL_LAST_ERRNO},
 | 
			
		||||
    {_SC("FCNTL_LOCKSTATE"),                      SQLITE_FCNTL_LOCKSTATE},
 | 
			
		||||
    {_SC("FCNTL_MMAP_SIZE"),                      SQLITE_FCNTL_MMAP_SIZE},
 | 
			
		||||
    {_SC("FCNTL_OVERWRITE"),                      SQLITE_FCNTL_OVERWRITE},
 | 
			
		||||
    {_SC("FCNTL_PERSIST_WAL"),                    SQLITE_FCNTL_PERSIST_WAL},
 | 
			
		||||
    {_SC("FCNTL_POWERSAFE_OVERWRITE"),            SQLITE_FCNTL_POWERSAFE_OVERWRITE},
 | 
			
		||||
    {_SC("FCNTL_PRAGMA"),                         SQLITE_FCNTL_PRAGMA},
 | 
			
		||||
    {_SC("FCNTL_RBU"),                            SQLITE_FCNTL_RBU},
 | 
			
		||||
    {_SC("FCNTL_SET_LOCKPROXYFILE"),              SQLITE_FCNTL_SET_LOCKPROXYFILE},
 | 
			
		||||
    {_SC("FCNTL_SIZE_HINT"),                      SQLITE_FCNTL_SIZE_HINT},
 | 
			
		||||
    {_SC("FCNTL_SYNC"),                           SQLITE_FCNTL_SYNC},
 | 
			
		||||
    {_SC("FCNTL_SYNC_OMITTED"),                   SQLITE_FCNTL_SYNC_OMITTED},
 | 
			
		||||
    {_SC("FCNTL_TEMPFILENAME"),                   SQLITE_FCNTL_TEMPFILENAME},
 | 
			
		||||
    {_SC("FCNTL_TRACE"),                          SQLITE_FCNTL_TRACE},
 | 
			
		||||
    {_SC("FCNTL_VFSNAME"),                        SQLITE_FCNTL_VFSNAME},
 | 
			
		||||
    {_SC("FCNTL_WAL_BLOCK"),                      SQLITE_FCNTL_WAL_BLOCK},
 | 
			
		||||
    {_SC("FCNTL_WIN32_AV_RETRY"),                 SQLITE_FCNTL_WIN32_AV_RETRY},
 | 
			
		||||
    {_SC("FCNTL_WIN32_SET_HANDLE"),               SQLITE_FCNTL_WIN32_SET_HANDLE},
 | 
			
		||||
    {_SC("FCNTL_ZIPVFS"),                         SQLITE_FCNTL_ZIPVFS},
 | 
			
		||||
    {_SC("FLOAT"),                                SQLITE_FLOAT},
 | 
			
		||||
    {_SC("FORMAT"),                               SQLITE_FORMAT},
 | 
			
		||||
    {_SC("FULL"),                                 SQLITE_FULL},
 | 
			
		||||
    {_SC("FUNCTION"),                             SQLITE_FUNCTION},
 | 
			
		||||
    {_SC("IGNORE"),                               SQLITE_IGNORE},
 | 
			
		||||
    {_SC("INDEX_CONSTRAINT_EQ"),                  SQLITE_INDEX_CONSTRAINT_EQ},
 | 
			
		||||
    {_SC("INDEX_CONSTRAINT_GE"),                  SQLITE_INDEX_CONSTRAINT_GE},
 | 
			
		||||
    {_SC("INDEX_CONSTRAINT_GT"),                  SQLITE_INDEX_CONSTRAINT_GT},
 | 
			
		||||
    {_SC("INDEX_CONSTRAINT_LE"),                  SQLITE_INDEX_CONSTRAINT_LE},
 | 
			
		||||
    {_SC("INDEX_CONSTRAINT_LT"),                  SQLITE_INDEX_CONSTRAINT_LT},
 | 
			
		||||
    {_SC("INDEX_CONSTRAINT_MATCH"),               SQLITE_INDEX_CONSTRAINT_MATCH},
 | 
			
		||||
    {_SC("INDEX_SCAN_UNIQUE"),                    SQLITE_INDEX_SCAN_UNIQUE},
 | 
			
		||||
    {_SC("INSERT"),                               SQLITE_INSERT},
 | 
			
		||||
    {_SC("INTEGER"),                              SQLITE_INTEGER},
 | 
			
		||||
    {_SC("INTERNAL"),                             SQLITE_INTERNAL},
 | 
			
		||||
    {_SC("INTERRUPT"),                            SQLITE_INTERRUPT},
 | 
			
		||||
    {_SC("IOCAP_ATOMIC"),                         SQLITE_IOCAP_ATOMIC},
 | 
			
		||||
    {_SC("IOCAP_ATOMIC16K"),                      SQLITE_IOCAP_ATOMIC16K},
 | 
			
		||||
    {_SC("IOCAP_ATOMIC1K"),                       SQLITE_IOCAP_ATOMIC1K},
 | 
			
		||||
    {_SC("IOCAP_ATOMIC2K"),                       SQLITE_IOCAP_ATOMIC2K},
 | 
			
		||||
    {_SC("IOCAP_ATOMIC32K"),                      SQLITE_IOCAP_ATOMIC32K},
 | 
			
		||||
    {_SC("IOCAP_ATOMIC4K"),                       SQLITE_IOCAP_ATOMIC4K},
 | 
			
		||||
    {_SC("IOCAP_ATOMIC512"),                      SQLITE_IOCAP_ATOMIC512},
 | 
			
		||||
    {_SC("IOCAP_ATOMIC64K"),                      SQLITE_IOCAP_ATOMIC64K},
 | 
			
		||||
    {_SC("IOCAP_ATOMIC8K"),                       SQLITE_IOCAP_ATOMIC8K},
 | 
			
		||||
    {_SC("IOCAP_IMMUTABLE"),                      SQLITE_IOCAP_IMMUTABLE},
 | 
			
		||||
    {_SC("IOCAP_POWERSAFE_OVERWRITE"),            SQLITE_IOCAP_POWERSAFE_OVERWRITE},
 | 
			
		||||
    {_SC("IOCAP_SAFE_APPEND"),                    SQLITE_IOCAP_SAFE_APPEND},
 | 
			
		||||
    {_SC("IOCAP_SEQUENTIAL"),                     SQLITE_IOCAP_SEQUENTIAL},
 | 
			
		||||
    {_SC("IOCAP_UNDELETABLE_WHEN_OPEN"),          SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN},
 | 
			
		||||
    {_SC("IOERR"),                                SQLITE_IOERR},
 | 
			
		||||
    {_SC("IOERR_ACCESS"),                         SQLITE_IOERR_ACCESS},
 | 
			
		||||
    {_SC("IOERR_BLOCKED"),                        SQLITE_IOERR_BLOCKED},
 | 
			
		||||
    {_SC("IOERR_CHECKRESERVEDLOCK"),              SQLITE_IOERR_CHECKRESERVEDLOCK},
 | 
			
		||||
    {_SC("IOERR_CLOSE"),                          SQLITE_IOERR_CLOSE},
 | 
			
		||||
    {_SC("IOERR_CONVPATH"),                       SQLITE_IOERR_CONVPATH},
 | 
			
		||||
    {_SC("IOERR_DELETE"),                         SQLITE_IOERR_DELETE},
 | 
			
		||||
    {_SC("IOERR_DELETE_NOENT"),                   SQLITE_IOERR_DELETE_NOENT},
 | 
			
		||||
    {_SC("IOERR_DIR_CLOSE"),                      SQLITE_IOERR_DIR_CLOSE},
 | 
			
		||||
    {_SC("IOERR_DIR_FSYNC"),                      SQLITE_IOERR_DIR_FSYNC},
 | 
			
		||||
    {_SC("IOERR_FSTAT"),                          SQLITE_IOERR_FSTAT},
 | 
			
		||||
    {_SC("IOERR_FSYNC"),                          SQLITE_IOERR_FSYNC},
 | 
			
		||||
    {_SC("IOERR_GETTEMPPATH"),                    SQLITE_IOERR_GETTEMPPATH},
 | 
			
		||||
    {_SC("IOERR_LOCK"),                           SQLITE_IOERR_LOCK},
 | 
			
		||||
    {_SC("IOERR_MMAP"),                           SQLITE_IOERR_MMAP},
 | 
			
		||||
    {_SC("IOERR_NOMEM"),                          SQLITE_IOERR_NOMEM},
 | 
			
		||||
    {_SC("IOERR_RDLOCK"),                         SQLITE_IOERR_RDLOCK},
 | 
			
		||||
    {_SC("IOERR_READ"),                           SQLITE_IOERR_READ},
 | 
			
		||||
    {_SC("IOERR_SEEK"),                           SQLITE_IOERR_SEEK},
 | 
			
		||||
    {_SC("IOERR_SHMLOCK"),                        SQLITE_IOERR_SHMLOCK},
 | 
			
		||||
    {_SC("IOERR_SHMMAP"),                         SQLITE_IOERR_SHMMAP},
 | 
			
		||||
    {_SC("IOERR_SHMOPEN"),                        SQLITE_IOERR_SHMOPEN},
 | 
			
		||||
    {_SC("IOERR_SHMSIZE"),                        SQLITE_IOERR_SHMSIZE},
 | 
			
		||||
    {_SC("IOERR_SHORT_READ"),                     SQLITE_IOERR_SHORT_READ},
 | 
			
		||||
    {_SC("IOERR_TRUNCATE"),                       SQLITE_IOERR_TRUNCATE},
 | 
			
		||||
    {_SC("IOERR_UNLOCK"),                         SQLITE_IOERR_UNLOCK},
 | 
			
		||||
    {_SC("IOERR_VNODE"),                          SQLITE_IOERR_VNODE},
 | 
			
		||||
    {_SC("IOERR_WRITE"),                          SQLITE_IOERR_WRITE},
 | 
			
		||||
    {_SC("LIMIT_ATTACHED"),                       SQLITE_LIMIT_ATTACHED},
 | 
			
		||||
    {_SC("LIMIT_COLUMN"),                         SQLITE_LIMIT_COLUMN},
 | 
			
		||||
    {_SC("LIMIT_COMPOUND_SELECT"),                SQLITE_LIMIT_COMPOUND_SELECT},
 | 
			
		||||
    {_SC("LIMIT_EXPR_DEPTH"),                     SQLITE_LIMIT_EXPR_DEPTH},
 | 
			
		||||
    {_SC("LIMIT_FUNCTION_ARG"),                   SQLITE_LIMIT_FUNCTION_ARG},
 | 
			
		||||
    {_SC("LIMIT_LENGTH"),                         SQLITE_LIMIT_LENGTH},
 | 
			
		||||
    {_SC("LIMIT_LIKE_PATTERN_LENGTH"),            SQLITE_LIMIT_LIKE_PATTERN_LENGTH},
 | 
			
		||||
    {_SC("LIMIT_SQL_LENGTH"),                     SQLITE_LIMIT_SQL_LENGTH},
 | 
			
		||||
    {_SC("LIMIT_TRIGGER_DEPTH"),                  SQLITE_LIMIT_TRIGGER_DEPTH},
 | 
			
		||||
    {_SC("LIMIT_VARIABLE_NUMBER"),                SQLITE_LIMIT_VARIABLE_NUMBER},
 | 
			
		||||
    {_SC("LIMIT_VDBE_OP"),                        SQLITE_LIMIT_VDBE_OP},
 | 
			
		||||
    {_SC("LIMIT_WORKER_THREADS"),                 SQLITE_LIMIT_WORKER_THREADS},
 | 
			
		||||
    {_SC("LOCKED"),                               SQLITE_LOCKED},
 | 
			
		||||
    {_SC("LOCKED_SHAREDCACHE"),                   SQLITE_LOCKED_SHAREDCACHE},
 | 
			
		||||
    {_SC("LOCK_EXCLUSIVE"),                       SQLITE_LOCK_EXCLUSIVE},
 | 
			
		||||
    {_SC("LOCK_NONE"),                            SQLITE_LOCK_NONE},
 | 
			
		||||
    {_SC("LOCK_PENDING"),                         SQLITE_LOCK_PENDING},
 | 
			
		||||
    {_SC("LOCK_RESERVED"),                        SQLITE_LOCK_RESERVED},
 | 
			
		||||
    {_SC("LOCK_SHARED"),                          SQLITE_LOCK_SHARED},
 | 
			
		||||
    {_SC("MISMATCH"),                             SQLITE_MISMATCH},
 | 
			
		||||
    {_SC("MISUSE"),                               SQLITE_MISUSE},
 | 
			
		||||
    {_SC("MUTEX_FAST"),                           SQLITE_MUTEX_FAST},
 | 
			
		||||
    {_SC("MUTEX_RECURSIVE"),                      SQLITE_MUTEX_RECURSIVE},
 | 
			
		||||
    {_SC("MUTEX_STATIC_APP1"),                    SQLITE_MUTEX_STATIC_APP1},
 | 
			
		||||
    {_SC("MUTEX_STATIC_APP2"),                    SQLITE_MUTEX_STATIC_APP2},
 | 
			
		||||
    {_SC("MUTEX_STATIC_APP3"),                    SQLITE_MUTEX_STATIC_APP3},
 | 
			
		||||
    {_SC("MUTEX_STATIC_LRU"),                     SQLITE_MUTEX_STATIC_LRU},
 | 
			
		||||
    {_SC("MUTEX_STATIC_LRU2"),                    SQLITE_MUTEX_STATIC_LRU2},
 | 
			
		||||
    {_SC("MUTEX_STATIC_MASTER"),                  SQLITE_MUTEX_STATIC_MASTER},
 | 
			
		||||
    {_SC("MUTEX_STATIC_MEM"),                     SQLITE_MUTEX_STATIC_MEM},
 | 
			
		||||
    {_SC("MUTEX_STATIC_MEM2"),                    SQLITE_MUTEX_STATIC_MEM2},
 | 
			
		||||
    {_SC("MUTEX_STATIC_OPEN"),                    SQLITE_MUTEX_STATIC_OPEN},
 | 
			
		||||
    {_SC("MUTEX_STATIC_PMEM"),                    SQLITE_MUTEX_STATIC_PMEM},
 | 
			
		||||
    {_SC("MUTEX_STATIC_PRNG"),                    SQLITE_MUTEX_STATIC_PRNG},
 | 
			
		||||
    {_SC("MUTEX_STATIC_VFS1"),                    SQLITE_MUTEX_STATIC_VFS1},
 | 
			
		||||
    {_SC("MUTEX_STATIC_VFS2"),                    SQLITE_MUTEX_STATIC_VFS2},
 | 
			
		||||
    {_SC("MUTEX_STATIC_VFS3"),                    SQLITE_MUTEX_STATIC_VFS3},
 | 
			
		||||
    {_SC("NOLFS"),                                SQLITE_NOLFS},
 | 
			
		||||
    {_SC("NOMEM"),                                SQLITE_NOMEM},
 | 
			
		||||
    {_SC("NOTADB"),                               SQLITE_NOTADB},
 | 
			
		||||
    {_SC("NOTFOUND"),                             SQLITE_NOTFOUND},
 | 
			
		||||
    {_SC("NOTICE"),                               SQLITE_NOTICE},
 | 
			
		||||
    {_SC("NOTICE_RECOVER_ROLLBACK"),              SQLITE_NOTICE_RECOVER_ROLLBACK},
 | 
			
		||||
    {_SC("NOTICE_RECOVER_WAL"),                   SQLITE_NOTICE_RECOVER_WAL},
 | 
			
		||||
    {_SC("NULL"),                                 SQLITE_NULL},
 | 
			
		||||
    {_SC("OK"),                                   SQLITE_OK},
 | 
			
		||||
    {_SC("OPEN_AUTOPROXY"),                       SQLITE_OPEN_AUTOPROXY},
 | 
			
		||||
    {_SC("OPEN_CREATE"),                          SQLITE_OPEN_CREATE},
 | 
			
		||||
    {_SC("OPEN_DELETEONCLOSE"),                   SQLITE_OPEN_DELETEONCLOSE},
 | 
			
		||||
    {_SC("OPEN_EXCLUSIVE"),                       SQLITE_OPEN_EXCLUSIVE},
 | 
			
		||||
    {_SC("OPEN_FULLMUTEX"),                       SQLITE_OPEN_FULLMUTEX},
 | 
			
		||||
    {_SC("OPEN_MAIN_DB"),                         SQLITE_OPEN_MAIN_DB},
 | 
			
		||||
    {_SC("OPEN_MAIN_JOURNAL"),                    SQLITE_OPEN_MAIN_JOURNAL},
 | 
			
		||||
    {_SC("OPEN_MASTER_JOURNAL"),                  SQLITE_OPEN_MASTER_JOURNAL},
 | 
			
		||||
    {_SC("OPEN_MEMORY"),                          SQLITE_OPEN_MEMORY},
 | 
			
		||||
    {_SC("OPEN_NOMUTEX"),                         SQLITE_OPEN_NOMUTEX},
 | 
			
		||||
    {_SC("OPEN_PRIVATECACHE"),                    SQLITE_OPEN_PRIVATECACHE},
 | 
			
		||||
    {_SC("OPEN_READONLY"),                        SQLITE_OPEN_READONLY},
 | 
			
		||||
    {_SC("OPEN_READWRITE"),                       SQLITE_OPEN_READWRITE},
 | 
			
		||||
    {_SC("OPEN_SHAREDCACHE"),                     SQLITE_OPEN_SHAREDCACHE},
 | 
			
		||||
    {_SC("OPEN_SUBJOURNAL"),                      SQLITE_OPEN_SUBJOURNAL},
 | 
			
		||||
    {_SC("OPEN_TEMP_DB"),                         SQLITE_OPEN_TEMP_DB},
 | 
			
		||||
    {_SC("OPEN_TEMP_JOURNAL"),                    SQLITE_OPEN_TEMP_JOURNAL},
 | 
			
		||||
    {_SC("OPEN_TRANSIENT_DB"),                    SQLITE_OPEN_TRANSIENT_DB},
 | 
			
		||||
    {_SC("OPEN_URI"),                             SQLITE_OPEN_URI},
 | 
			
		||||
    {_SC("OPEN_WAL"),                             SQLITE_OPEN_WAL},
 | 
			
		||||
    {_SC("PERM"),                                 SQLITE_PERM},
 | 
			
		||||
    {_SC("PRAGMA"),                               SQLITE_PRAGMA},
 | 
			
		||||
    {_SC("PROTOCOL"),                             SQLITE_PROTOCOL},
 | 
			
		||||
    {_SC("RANGE"),                                SQLITE_RANGE},
 | 
			
		||||
    {_SC("READ"),                                 SQLITE_READ},
 | 
			
		||||
    {_SC("READONLY"),                             SQLITE_READONLY},
 | 
			
		||||
    {_SC("READONLY_CANTLOCK"),                    SQLITE_READONLY_CANTLOCK},
 | 
			
		||||
    {_SC("READONLY_DBMOVED"),                     SQLITE_READONLY_DBMOVED},
 | 
			
		||||
    {_SC("READONLY_RECOVERY"),                    SQLITE_READONLY_RECOVERY},
 | 
			
		||||
    {_SC("READONLY_ROLLBACK"),                    SQLITE_READONLY_ROLLBACK},
 | 
			
		||||
    {_SC("RECURSIVE"),                            SQLITE_RECURSIVE},
 | 
			
		||||
    {_SC("REINDEX"),                              SQLITE_REINDEX},
 | 
			
		||||
    {_SC("REPLACE"),                              SQLITE_REPLACE},
 | 
			
		||||
    {_SC("ROLLBACK"),                             SQLITE_ROLLBACK},
 | 
			
		||||
    {_SC("ROW"),                                  SQLITE_ROW},
 | 
			
		||||
    {_SC("SAVEPOINT"),                            SQLITE_SAVEPOINT},
 | 
			
		||||
    {_SC("SCANSTAT_EST"),                         SQLITE_SCANSTAT_EST},
 | 
			
		||||
    {_SC("SCANSTAT_EXPLAIN"),                     SQLITE_SCANSTAT_EXPLAIN},
 | 
			
		||||
    {_SC("SCANSTAT_NAME"),                        SQLITE_SCANSTAT_NAME},
 | 
			
		||||
    {_SC("SCANSTAT_NLOOP"),                       SQLITE_SCANSTAT_NLOOP},
 | 
			
		||||
    {_SC("SCANSTAT_NVISIT"),                      SQLITE_SCANSTAT_NVISIT},
 | 
			
		||||
    {_SC("SCANSTAT_SELECTID"),                    SQLITE_SCANSTAT_SELECTID},
 | 
			
		||||
    {_SC("SCHEMA"),                               SQLITE_SCHEMA},
 | 
			
		||||
    {_SC("SELECT"),                               SQLITE_SELECT},
 | 
			
		||||
    {_SC("SHM_EXCLUSIVE"),                        SQLITE_SHM_EXCLUSIVE},
 | 
			
		||||
    {_SC("SHM_LOCK"),                             SQLITE_SHM_LOCK},
 | 
			
		||||
    {_SC("SHM_NLOCK"),                            SQLITE_SHM_NLOCK},
 | 
			
		||||
    {_SC("SHM_SHARED"),                           SQLITE_SHM_SHARED},
 | 
			
		||||
    {_SC("SHM_UNLOCK"),                           SQLITE_SHM_UNLOCK},
 | 
			
		||||
    {_SC("STATUS_MALLOC_COUNT"),                  SQLITE_STATUS_MALLOC_COUNT},
 | 
			
		||||
    {_SC("STATUS_MALLOC_SIZE"),                   SQLITE_STATUS_MALLOC_SIZE},
 | 
			
		||||
    {_SC("STATUS_MEMORY_USED"),                   SQLITE_STATUS_MEMORY_USED},
 | 
			
		||||
    {_SC("STATUS_PAGECACHE_OVERFLOW"),            SQLITE_STATUS_PAGECACHE_OVERFLOW},
 | 
			
		||||
    {_SC("STATUS_PAGECACHE_SIZE"),                SQLITE_STATUS_PAGECACHE_SIZE},
 | 
			
		||||
    {_SC("STATUS_PAGECACHE_USED"),                SQLITE_STATUS_PAGECACHE_USED},
 | 
			
		||||
    {_SC("STATUS_PARSER_STACK"),                  SQLITE_STATUS_PARSER_STACK},
 | 
			
		||||
    {_SC("STATUS_SCRATCH_OVERFLOW"),              SQLITE_STATUS_SCRATCH_OVERFLOW},
 | 
			
		||||
    {_SC("STATUS_SCRATCH_SIZE"),                  SQLITE_STATUS_SCRATCH_SIZE},
 | 
			
		||||
    {_SC("STATUS_SCRATCH_USED"),                  SQLITE_STATUS_SCRATCH_USED},
 | 
			
		||||
    {_SC("STMTSTATUS_AUTOINDEX"),                 SQLITE_STMTSTATUS_AUTOINDEX},
 | 
			
		||||
    {_SC("STMTSTATUS_FULLSCAN_STEP"),             SQLITE_STMTSTATUS_FULLSCAN_STEP},
 | 
			
		||||
    {_SC("STMTSTATUS_SORT"),                      SQLITE_STMTSTATUS_SORT},
 | 
			
		||||
    {_SC("STMTSTATUS_VM_STEP"),                   SQLITE_STMTSTATUS_VM_STEP},
 | 
			
		||||
    {_SC("SYNC_DATAONLY"),                        SQLITE_SYNC_DATAONLY},
 | 
			
		||||
    {_SC("SYNC_FULL"),                            SQLITE_SYNC_FULL},
 | 
			
		||||
    {_SC("SYNC_NORMAL"),                          SQLITE_SYNC_NORMAL},
 | 
			
		||||
    {_SC("TESTCTRL_ALWAYS"),                      SQLITE_TESTCTRL_ALWAYS},
 | 
			
		||||
    {_SC("TESTCTRL_ASSERT"),                      SQLITE_TESTCTRL_ASSERT},
 | 
			
		||||
    {_SC("TESTCTRL_BENIGN_MALLOC_HOOKS"),         SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS},
 | 
			
		||||
    {_SC("TESTCTRL_BITVEC_TEST"),                 SQLITE_TESTCTRL_BITVEC_TEST},
 | 
			
		||||
    {_SC("TESTCTRL_BYTEORDER"),                   SQLITE_TESTCTRL_BYTEORDER},
 | 
			
		||||
    {_SC("TESTCTRL_EXPLAIN_STMT"),                SQLITE_TESTCTRL_EXPLAIN_STMT},
 | 
			
		||||
    {_SC("TESTCTRL_FAULT_INSTALL"),               SQLITE_TESTCTRL_FAULT_INSTALL},
 | 
			
		||||
    {_SC("TESTCTRL_FIRST"),                       SQLITE_TESTCTRL_FIRST},
 | 
			
		||||
    {_SC("TESTCTRL_IMPOSTER"),                    SQLITE_TESTCTRL_IMPOSTER},
 | 
			
		||||
    {_SC("TESTCTRL_ISINIT"),                      SQLITE_TESTCTRL_ISINIT},
 | 
			
		||||
    {_SC("TESTCTRL_ISKEYWORD"),                   SQLITE_TESTCTRL_ISKEYWORD},
 | 
			
		||||
    {_SC("TESTCTRL_LAST"),                        SQLITE_TESTCTRL_LAST},
 | 
			
		||||
    {_SC("TESTCTRL_LOCALTIME_FAULT"),             SQLITE_TESTCTRL_LOCALTIME_FAULT},
 | 
			
		||||
    {_SC("TESTCTRL_NEVER_CORRUPT"),               SQLITE_TESTCTRL_NEVER_CORRUPT},
 | 
			
		||||
    {_SC("TESTCTRL_OPTIMIZATIONS"),               SQLITE_TESTCTRL_OPTIMIZATIONS},
 | 
			
		||||
    {_SC("TESTCTRL_PENDING_BYTE"),                SQLITE_TESTCTRL_PENDING_BYTE},
 | 
			
		||||
    {_SC("TESTCTRL_PRNG_RESET"),                  SQLITE_TESTCTRL_PRNG_RESET},
 | 
			
		||||
    {_SC("TESTCTRL_PRNG_RESTORE"),                SQLITE_TESTCTRL_PRNG_RESTORE},
 | 
			
		||||
    {_SC("TESTCTRL_PRNG_SAVE"),                   SQLITE_TESTCTRL_PRNG_SAVE},
 | 
			
		||||
    {_SC("TESTCTRL_RESERVE"),                     SQLITE_TESTCTRL_RESERVE},
 | 
			
		||||
    {_SC("TESTCTRL_SCRATCHMALLOC"),               SQLITE_TESTCTRL_SCRATCHMALLOC},
 | 
			
		||||
    {_SC("TESTCTRL_SORTER_MMAP"),                 SQLITE_TESTCTRL_SORTER_MMAP},
 | 
			
		||||
    {_SC("TESTCTRL_VDBE_COVERAGE"),               SQLITE_TESTCTRL_VDBE_COVERAGE},
 | 
			
		||||
    {_SC("TEXT"),                                 SQLITE_TEXT},
 | 
			
		||||
    {_SC("TOOBIG"),                               SQLITE_TOOBIG},
 | 
			
		||||
    {_SC("TRANSACTION"),                          SQLITE_TRANSACTION},
 | 
			
		||||
    {_SC("UPDATE"),                               SQLITE_UPDATE},
 | 
			
		||||
    {_SC("UTF16"),                                SQLITE_UTF16},
 | 
			
		||||
    {_SC("UTF16BE"),                              SQLITE_UTF16BE},
 | 
			
		||||
    {_SC("UTF16LE"),                              SQLITE_UTF16LE},
 | 
			
		||||
    {_SC("UTF16_ALIGNED"),                        SQLITE_UTF16_ALIGNED},
 | 
			
		||||
    {_SC("UTF8"),                                 SQLITE_UTF8},
 | 
			
		||||
    {_SC("VERSION_NUMBER"),                       SQLITE_VERSION_NUMBER},
 | 
			
		||||
    {_SC("VTAB_CONSTRAINT_SUPPORT"),              SQLITE_VTAB_CONSTRAINT_SUPPORT},
 | 
			
		||||
    {_SC("WARNING"),                              SQLITE_WARNING},
 | 
			
		||||
    {_SC("WARNING_AUTOINDEX"),                    SQLITE_WARNING_AUTOINDEX}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// ================================================================================================
 | 
			
		||||
void Register_Constants(Table & sqlns)
 | 
			
		||||
{
 | 
			
		||||
    Enumeration e(sqlns.GetVM());
 | 
			
		||||
 | 
			
		||||
    for (Uint32 n = 0; n < (sizeof(g_MainEnum) / sizeof(EnumElement)); ++n)
 | 
			
		||||
    {
 | 
			
		||||
        e.Const(g_MainEnum[n].Name, g_MainEnum[n].Value);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ConstTable(sqlns.GetVM()).Enum(_SC("ESQLite"), e);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
							
								
								
									
										297
									
								
								module/Library/SQLite/Handle.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										297
									
								
								module/Library/SQLite/Handle.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,297 @@
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Library/SQLite/Handle.hpp"
 | 
			
		||||
 | 
			
		||||
#include <utility>
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
ConnHnd::ConnHnd()
 | 
			
		||||
    : mPtr(nullptr)
 | 
			
		||||
    , mStatus(SQLITE_OK)
 | 
			
		||||
    , mQueue()
 | 
			
		||||
    , mFlags(0)
 | 
			
		||||
    , mName()
 | 
			
		||||
    , mVFS()
 | 
			
		||||
    , mMemory(false)
 | 
			
		||||
    , mTrace(false)
 | 
			
		||||
    , mProfile(false)
 | 
			
		||||
{
 | 
			
		||||
    /* ... */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
ConnHnd::~ConnHnd()
 | 
			
		||||
{
 | 
			
		||||
    // Is there anything to close?
 | 
			
		||||
    if (mPtr != nullptr)
 | 
			
		||||
    {
 | 
			
		||||
        // Flush remaining queries in the queue and ignore the result
 | 
			
		||||
        Flush(mQueue.size(), NullObject(), NullFunction());
 | 
			
		||||
        // NOTE: Should we call sqlite3_interrupt(...) before closing?
 | 
			
		||||
        // Attempt to close the database
 | 
			
		||||
        if ((sqlite3_close(mPtr)) != SQLITE_OK)
 | 
			
		||||
        {
 | 
			
		||||
            LogErr("Unable to close SQLite connection [%s]", sqlite3_errmsg(mPtr));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void ConnHnd::Create(CSStr name, Int32 flags, CSStr vfs)
 | 
			
		||||
{
 | 
			
		||||
    // Make sure a previous connection doesn't exist
 | 
			
		||||
    if (mPtr)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Unable to connect to database. Database already connected");
 | 
			
		||||
    }
 | 
			
		||||
    // Make sure the name is valid
 | 
			
		||||
    else if (!name || *name == '\0')
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Unable to connect to database. The name is invalid");
 | 
			
		||||
    }
 | 
			
		||||
    // Attempt to create the database connection
 | 
			
		||||
    else if ((mStatus = sqlite3_open_v2(name, &mPtr, flags, vfs)) != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        // Grab the error message before destroying the handle
 | 
			
		||||
        String msg(sqlite3_errmsg(mPtr) ? sqlite3_errmsg(mPtr) : _SC("Unknown reason"));
 | 
			
		||||
        // Must be destroyed regardless of result
 | 
			
		||||
        sqlite3_close(mPtr);
 | 
			
		||||
        // Prevent further use of this handle
 | 
			
		||||
        mPtr = nullptr;
 | 
			
		||||
        // Now its safe to throw the error
 | 
			
		||||
        STHROWF("Unable to connect to database [%s]", msg.c_str());
 | 
			
		||||
    }
 | 
			
		||||
    // Let's save the specified information
 | 
			
		||||
    mName.assign(name);
 | 
			
		||||
    mFlags = flags;
 | 
			
		||||
    mVFS.assign(vfs ? vfs : _SC(""));
 | 
			
		||||
    // Optional check if database is initially stored in memory
 | 
			
		||||
    mMemory = (mName == _SC(":memory:"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Int32 ConnHnd::Flush(Uint32 num, Object & env, Function & func)
 | 
			
		||||
{
 | 
			
		||||
    // Do we even have a valid connection?
 | 
			
		||||
    if (!mPtr)
 | 
			
		||||
    {
 | 
			
		||||
        return -1; // No connection!
 | 
			
		||||
    }
 | 
			
		||||
    // Is there anything to flush?
 | 
			
		||||
    else if (!num || mQueue.empty())
 | 
			
		||||
    {
 | 
			
		||||
        return 0; // Nothing to process!
 | 
			
		||||
    }
 | 
			
		||||
    // Can we even flush that many?
 | 
			
		||||
    else if (num > mQueue.size())
 | 
			
		||||
    {
 | 
			
		||||
        num = 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
 | 
			
		||||
    auto itr = mQueue.begin();
 | 
			
		||||
    auto end = mQueue.begin() + num;
 | 
			
		||||
    // Attempt to begin the flush transaction
 | 
			
		||||
    if ((mStatus = sqlite3_exec(mPtr, "BEGIN", nullptr, nullptr, nullptr)) != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Unable to begin flush transaction [%s]", sqlite3_errmsg(mPtr));
 | 
			
		||||
    }
 | 
			
		||||
    // Process all queries within range of selection
 | 
			
		||||
    for (; itr != end; ++itr)
 | 
			
		||||
    {
 | 
			
		||||
        // Should we manually terminate this query?
 | 
			
		||||
        /*
 | 
			
		||||
        if (*(*itr).rbegin() != ';')
 | 
			
		||||
        {
 | 
			
		||||
            itr->push_back(';');
 | 
			
		||||
        }
 | 
			
		||||
        */
 | 
			
		||||
        // Attempt to execute the currently processed query string
 | 
			
		||||
        if ((mStatus = sqlite3_exec(mPtr, itr->c_str(), nullptr, nullptr, nullptr)) == SQLITE_OK)
 | 
			
		||||
        {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        // Do we have to execute any callback to resolve our issue?
 | 
			
		||||
        else if (!callback.IsNull())
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                // Ask the callback whether the query processing should end here
 | 
			
		||||
                SharedPtr< bool > ret = callback.Evaluate< bool >(mStatus, *itr);
 | 
			
		||||
                // Should we break here?
 | 
			
		||||
                if (!!ret && !(*ret))
 | 
			
		||||
                {
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (const Sqrat::Exception & e)
 | 
			
		||||
            {
 | 
			
		||||
                LogErr("Squirrel error caught in flush handler [%s]", e.what());
 | 
			
		||||
            }
 | 
			
		||||
            catch (const std::exception & e)
 | 
			
		||||
            {
 | 
			
		||||
                LogErr("Program error caught in flush handler [%s]", e.what());
 | 
			
		||||
            }
 | 
			
		||||
            catch (...)
 | 
			
		||||
            {
 | 
			
		||||
                LogErr("Unknown error caught in flush handler");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    // Erase all queries till end or till the point of failure (if any occurred)
 | 
			
		||||
    mQueue.erase(mQueue.begin(), itr);
 | 
			
		||||
    // Attempt to commit changes requested during transaction
 | 
			
		||||
    if ((mStatus = sqlite3_exec(mPtr, "COMMIT", nullptr, nullptr, nullptr)) == SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        return sqlite3_changes(mPtr);
 | 
			
		||||
    }
 | 
			
		||||
    // Attempt to roll back erroneous changes
 | 
			
		||||
    else if ((mStatus = sqlite3_exec(mPtr, "ROLLBACK", nullptr, nullptr, nullptr)) != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Unable to rollback flush transaction [%s]", sqlite3_errmsg(mPtr));
 | 
			
		||||
    }
 | 
			
		||||
    // The transaction failed somehow but we managed to rollback
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Unable to commit flush transaction [%s]", sqlite3_errmsg(mPtr));
 | 
			
		||||
    }
 | 
			
		||||
    // Operation failed
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
StmtHnd::StmtHnd(ConnRef conn)
 | 
			
		||||
    : mPtr(nullptr)
 | 
			
		||||
    , mStatus(SQLITE_OK)
 | 
			
		||||
    , mConn(std::move(conn))
 | 
			
		||||
    , mQuery()
 | 
			
		||||
    , mColumns(0)
 | 
			
		||||
    , mParameters(0)
 | 
			
		||||
    , mIndexes()
 | 
			
		||||
    , mGood(false)
 | 
			
		||||
    , mDone(false)
 | 
			
		||||
{
 | 
			
		||||
    /* ... */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
StmtHnd::~StmtHnd()
 | 
			
		||||
{
 | 
			
		||||
    // Is there anything to finalize?
 | 
			
		||||
    if (mPtr != nullptr)
 | 
			
		||||
    {
 | 
			
		||||
        // Attempt to finalize the statement
 | 
			
		||||
        if ((sqlite3_finalize(mPtr)) != SQLITE_OK)
 | 
			
		||||
        {
 | 
			
		||||
            LogErr("Unable to finalize SQLite statement [%s]", mConn->ErrMsg());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void StmtHnd::Create(CSStr query, SQInteger length)
 | 
			
		||||
{
 | 
			
		||||
    // Make sure a previous statement doesn't exist
 | 
			
		||||
    if (mPtr)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Unable to prepare statement. Statement already prepared");
 | 
			
		||||
    }
 | 
			
		||||
    // Is the specified database connection is valid?
 | 
			
		||||
    else if (!mConn)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Unable to prepare statement. Invalid connection handle");
 | 
			
		||||
    }
 | 
			
		||||
    // Is the specified query string valid?
 | 
			
		||||
    else if (!query || !length || *query == '\0')
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Unable to prepare statement. Invalid or empty query string");
 | 
			
		||||
    }
 | 
			
		||||
    // Save the query string
 | 
			
		||||
    mQuery.assign(query, length);
 | 
			
		||||
    // Attempt to prepare a statement with the specified query string
 | 
			
		||||
    if ((mStatus = sqlite3_prepare_v2(mConn->mPtr, mQuery.c_str(), ConvTo< Int32 >::From(mQuery.size()),
 | 
			
		||||
                                            &mPtr, nullptr)) != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        // Clear the query string since it failed
 | 
			
		||||
        mQuery.clear();
 | 
			
		||||
        // Explicitly make sure the handle is null
 | 
			
		||||
        mPtr = nullptr;
 | 
			
		||||
        // Now it's safe to throw the error
 | 
			
		||||
        STHROWF("Unable to prepare statement [%s]", mConn->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        // Obtain the number of available columns
 | 
			
		||||
        mColumns = sqlite3_column_count(mPtr);
 | 
			
		||||
        // Obtain the number of available parameters
 | 
			
		||||
        mParameters = sqlite3_bind_parameter_count(mPtr);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Int32 StmtHnd::GetColumnIndex(CSStr name, SQInteger length)
 | 
			
		||||
{
 | 
			
		||||
    // Validate the handle
 | 
			
		||||
    if (!mPtr)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("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
 | 
			
		||||
            auto column_name = static_cast< CSStr >(sqlite3_column_name(mPtr, i));
 | 
			
		||||
            // Validate the name
 | 
			
		||||
            if (!column_name)
 | 
			
		||||
            {
 | 
			
		||||
                STHROWF("Unable to retrieve column name for index (%d)", i);
 | 
			
		||||
            }
 | 
			
		||||
            // Save it to guarantee the same lifetime as this instance
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                mIndexes[name] = i;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    const String str(name, length < 0 ? std::strlen(name) : length);
 | 
			
		||||
    // Attempt to find the specified column
 | 
			
		||||
    const Indexes::iterator itr = mIndexes.find(str);
 | 
			
		||||
    // Was there a column with the specified name?
 | 
			
		||||
    if (itr != mIndexes.end())
 | 
			
		||||
    {
 | 
			
		||||
        return itr->second;
 | 
			
		||||
    }
 | 
			
		||||
    // No such column exists (expecting the invoker to validate the result)
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
CCStr StmtHnd::ErrStr() const
 | 
			
		||||
{
 | 
			
		||||
    return mConn ? sqlite3_errstr(sqlite3_errcode(mConn->mPtr)) : _SC("");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
CCStr StmtHnd::ErrMsg() const
 | 
			
		||||
{
 | 
			
		||||
    return mConn ? sqlite3_errmsg(mConn->mPtr) : _SC("");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Int32 StmtHnd::ErrNo() const
 | 
			
		||||
{
 | 
			
		||||
    return mConn ? sqlite3_errcode(mConn->mPtr) : SQLITE_NOMEM;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Int32 StmtHnd::ExErrNo() const
 | 
			
		||||
{
 | 
			
		||||
    return mConn ? sqlite3_extended_errcode(mConn->mPtr) : SQLITE_NOMEM;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
							
								
								
									
										249
									
								
								module/Library/SQLite/Handle.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										249
									
								
								module/Library/SQLite/Handle.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,249 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Library/SQLite/Common.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <map>
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * The structure that holds the data associated with a certain connection.
 | 
			
		||||
*/
 | 
			
		||||
struct ConnHnd
 | 
			
		||||
{
 | 
			
		||||
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 std::vector< String > QueryList; // Container used to queue queries.
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    Pointer     mPtr; // The connection handle resource.
 | 
			
		||||
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    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.
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Default constructor.
 | 
			
		||||
    */
 | 
			
		||||
    ConnHnd();
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy constructor. (disabled)
 | 
			
		||||
    */
 | 
			
		||||
    ConnHnd(const ConnHnd & o) = delete;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Move constructor. (disabled)
 | 
			
		||||
    */
 | 
			
		||||
    ConnHnd(ConnHnd && o) = delete;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Destructor.
 | 
			
		||||
    */
 | 
			
		||||
    ~ConnHnd();
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy assignment operator. (disabled)
 | 
			
		||||
    */
 | 
			
		||||
    ConnHnd & operator = (const ConnHnd & o) = delete;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Move assignment operator. (disabled)
 | 
			
		||||
    */
 | 
			
		||||
    ConnHnd & operator = (ConnHnd && o) = delete;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * 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);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the message of the last received error code.
 | 
			
		||||
    */
 | 
			
		||||
    CCStr ErrStr() const
 | 
			
		||||
    {
 | 
			
		||||
        return sqlite3_errstr(sqlite3_errcode(mPtr));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Return the last error message associated with this database connection.
 | 
			
		||||
    */
 | 
			
		||||
    CCStr ErrMsg() const
 | 
			
		||||
    {
 | 
			
		||||
        return sqlite3_errmsg(mPtr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Return the numeric result code for the most recent failed API call (if any).
 | 
			
		||||
    */
 | 
			
		||||
    Int32 ErrNo() const
 | 
			
		||||
    {
 | 
			
		||||
        return sqlite3_errcode(mPtr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Return the extended numeric result code for the most recent failed API call (if any).
 | 
			
		||||
    */
 | 
			
		||||
    Int32 ExErrNo() const
 | 
			
		||||
    {
 | 
			
		||||
        return sqlite3_extended_errcode(mPtr);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * The structure that holds the data associated with a certain statement.
 | 
			
		||||
*/
 | 
			
		||||
struct StmtHnd
 | 
			
		||||
{
 | 
			
		||||
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 std::map< String, int > Indexes; // Container used to identify column indexes.
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    Pointer     mPtr; // The statement handle resource.
 | 
			
		||||
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    Int32       mStatus; // The last status code of this connection handle.
 | 
			
		||||
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    ConnRef     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.
 | 
			
		||||
    Int32       mParameters; // The amount of parameters 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.
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Default constructor.
 | 
			
		||||
    */
 | 
			
		||||
    StmtHnd(ConnRef conn);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy constructor. (disabled)
 | 
			
		||||
    */
 | 
			
		||||
    StmtHnd(const StmtHnd & o) = delete;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Move constructor. (disabled)
 | 
			
		||||
    */
 | 
			
		||||
    StmtHnd(StmtHnd && o) = delete;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Destructor.
 | 
			
		||||
    */
 | 
			
		||||
    ~StmtHnd();
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy assignment operator. (disabled)
 | 
			
		||||
    */
 | 
			
		||||
    StmtHnd & operator = (const StmtHnd & o) = delete;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Move assignment operator. (disabled)
 | 
			
		||||
    */
 | 
			
		||||
    StmtHnd & operator = (StmtHnd && o) = delete;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Create the database statement resource.
 | 
			
		||||
    */
 | 
			
		||||
    void Create(CSStr query, SQInteger length = -1);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Check whether a specific column index is in range.
 | 
			
		||||
    */
 | 
			
		||||
    bool CheckColumn(Int32 idx) const
 | 
			
		||||
    {
 | 
			
		||||
        return (idx >= 0) && (idx < mColumns);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Check whether a specific parameter index is in range.
 | 
			
		||||
    */
 | 
			
		||||
    bool CheckParameter(Int32 idx) const
 | 
			
		||||
    {
 | 
			
		||||
        return (idx >= 1) && (idx <= mParameters);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the column index associated with the specified name.
 | 
			
		||||
    */
 | 
			
		||||
    Int32 GetColumnIndex(CSStr name, SQInteger length = -1);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the message of the last received error code.
 | 
			
		||||
    */
 | 
			
		||||
    CCStr ErrStr() const;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Return the last error message associated with this database connection.
 | 
			
		||||
    */
 | 
			
		||||
    CCStr ErrMsg() const;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Return the numeric result code for the most recent failed API call (if any).
 | 
			
		||||
    */
 | 
			
		||||
    Int32 ErrNo() const;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Return the extended numeric result code for the most recent failed API call (if any).
 | 
			
		||||
    */
 | 
			
		||||
    Int32 ExErrNo() const;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
							
								
								
									
										789
									
								
								module/Library/SQLite/Parameter.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										789
									
								
								module/Library/SQLite/Parameter.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,789 @@
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Library/SQLite/Parameter.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include <ctime>
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include <sqstdblob.h>
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
// Error message when failed to bind value to parameter index.
 | 
			
		||||
#define SQMOD_BINDFAILED "Unable to bind (%s) parameter (%d) because [%s]"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
SQMODE_DECL_TYPENAME(Typename, _SC("SqLiteParameter"))
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
static inline bool IsDigitsOnly(CSStr str)
 | 
			
		||||
{
 | 
			
		||||
    while (std::isdigit(*str) || std::isspace(*str))
 | 
			
		||||
    {
 | 
			
		||||
        ++str;
 | 
			
		||||
    }
 | 
			
		||||
    // Return whether we reached the end while searching
 | 
			
		||||
    return *str == '\0';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
void Parameter::Validate(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    // Are we pointing to a valid index?
 | 
			
		||||
    if (m_Index < 0)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid column index: %d < 0 =>[%s:%d]", m_Index, file, line);
 | 
			
		||||
    }
 | 
			
		||||
    // Do we have a valid statement handle?
 | 
			
		||||
    else if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid SQLite statement reference =>[%s:%d]", file, line);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
void Parameter::Validate() const
 | 
			
		||||
{
 | 
			
		||||
    // Are we pointing to a valid index?
 | 
			
		||||
    if (m_Index < 0)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid column index: %d < 0", m_Index);
 | 
			
		||||
    }
 | 
			
		||||
    // Do we have a valid statement handle?
 | 
			
		||||
    else if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid SQLite statement reference");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
void Parameter::ValidateCreated(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    // Are we pointing to a valid index?
 | 
			
		||||
    if (m_Index < 0)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid column index: %d < 0 =>[%s:%d]", m_Index, file, line);
 | 
			
		||||
    }
 | 
			
		||||
    else if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid SQLite statement reference =>[%s:%d]", file, line);
 | 
			
		||||
    }
 | 
			
		||||
    else if (m_Handle->mPtr == nullptr)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid SQLite statement =>[%s:%d]", file, line);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
void Parameter::ValidateCreated() const
 | 
			
		||||
{
 | 
			
		||||
    // Are we pointing to a valid index?
 | 
			
		||||
    if (m_Index < 0)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid column index: %d < 0", m_Index);
 | 
			
		||||
    }
 | 
			
		||||
    else if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid SQLite statement reference");
 | 
			
		||||
    }
 | 
			
		||||
    else if (m_Handle->mPtr == nullptr)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid SQLite statement");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
const StmtRef & Parameter::GetValid(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    Validate(file, line);
 | 
			
		||||
    return m_Handle;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
const StmtRef & Parameter::GetValid() const
 | 
			
		||||
{
 | 
			
		||||
    Validate();
 | 
			
		||||
    return m_Handle;
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
const StmtRef & Parameter::GetCreated(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    ValidateCreated(file, line);
 | 
			
		||||
    return m_Handle;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
const StmtRef & Parameter::GetCreated() const
 | 
			
		||||
{
 | 
			
		||||
    ValidateCreated();
 | 
			
		||||
    return m_Handle;
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
void Parameter::ValidateParam(Int32 idx, CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    ValidateCreated(file, line);
 | 
			
		||||
    // Is the specified index in range?
 | 
			
		||||
    if (!m_Handle->CheckParameter(idx))
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Parameter index is out of range (%d:%d) =>[%s:%d]", idx, m_Handle->mParameters,
 | 
			
		||||
                    file, line);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
void Parameter::ValidateParam(Int32 idx) const
 | 
			
		||||
{
 | 
			
		||||
    ValidateCreated();
 | 
			
		||||
    // Is the specified index in range?
 | 
			
		||||
    if (!m_Handle->CheckParameter(idx))
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Parameter index is out of range (%d:%d)", idx, m_Handle->mParameters);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetIndex(const Object & param)
 | 
			
		||||
{
 | 
			
		||||
    // Where the index will be extracted
 | 
			
		||||
    Int32 idx = 0;
 | 
			
		||||
    // Grab the object virtual machine
 | 
			
		||||
    HSQUIRRELVM vm = param.GetVM();
 | 
			
		||||
    // Remember the current stack size
 | 
			
		||||
    const StackGuard sg(vm);
 | 
			
		||||
    // Push the specified object onto the stack
 | 
			
		||||
    Var< const Object & >::push(vm, param);
 | 
			
		||||
    // Identify the type of parameter was given
 | 
			
		||||
    switch  (param.GetType())
 | 
			
		||||
    {
 | 
			
		||||
        // Is this a string value?
 | 
			
		||||
        case OT_STRING:
 | 
			
		||||
        {
 | 
			
		||||
            // Obtain the object from the stack as a string
 | 
			
		||||
            StackStrF val(vm, -1);
 | 
			
		||||
            // Validate the result
 | 
			
		||||
            if (SQ_FAILED(val.Proc(false)))
 | 
			
		||||
            {
 | 
			
		||||
                STHROWF("%s", LastErrorString(vm).c_str());
 | 
			
		||||
            }
 | 
			
		||||
            // Is the obtained string empty?
 | 
			
		||||
            else if (val.mLen <= 0)
 | 
			
		||||
            {
 | 
			
		||||
                STHROWF("Cannot use an empty parameter name");
 | 
			
		||||
            }
 | 
			
		||||
            // Attempt to find a parameter with the specified name
 | 
			
		||||
            idx = sqlite3_bind_parameter_index(SQMOD_GET_CREATED(*this)->mPtr, val.mPtr);
 | 
			
		||||
        } break;
 | 
			
		||||
        // Is this an integer value? (or at least can be easily converted to one)
 | 
			
		||||
        case OT_INTEGER:
 | 
			
		||||
        case OT_FLOAT:
 | 
			
		||||
        case OT_BOOL:
 | 
			
		||||
        {
 | 
			
		||||
            idx = ConvTo< Int32 >::From(PopStackInteger(vm, -1));
 | 
			
		||||
        } break;
 | 
			
		||||
        // Is this an instance that we can extract either a string or integer from it?
 | 
			
		||||
        case OT_INSTANCE:
 | 
			
		||||
        {
 | 
			
		||||
            // Obtain the object from the stack as a string
 | 
			
		||||
            StackStrF val(vm, -1);
 | 
			
		||||
            // Validate the result
 | 
			
		||||
            if (SQ_FAILED(val.Proc(false)))
 | 
			
		||||
            {
 | 
			
		||||
                STHROWF("%s", LastErrorString(vm).c_str());
 | 
			
		||||
            }
 | 
			
		||||
            // Is the obtained string empty?
 | 
			
		||||
            else if (val.mLen <= 0)
 | 
			
		||||
            {
 | 
			
		||||
                STHROWF("Cannot use an empty parameter name");
 | 
			
		||||
            }
 | 
			
		||||
            // Check if this value is made only of digits
 | 
			
		||||
            else if (IsDigitsOnly(val.mPtr))
 | 
			
		||||
            {
 | 
			
		||||
                idx = ConvNum< Int32 >::FromStr(val.mPtr);
 | 
			
		||||
            }
 | 
			
		||||
            // Attempt to find a parameter with the specified name
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                idx = sqlite3_bind_parameter_index(SQMOD_GET_CREATED(*this)->mPtr, val.mPtr);
 | 
			
		||||
            }
 | 
			
		||||
        } break;
 | 
			
		||||
        // We don't recognize this kind of value!
 | 
			
		||||
        default: STHROWF("Unknown parameter index of type (%s)", SqTypeName(param.GetType()));
 | 
			
		||||
    }
 | 
			
		||||
    // Assign the index with a failsafe to invalid on error
 | 
			
		||||
    AutoAssign< Int32 > aa(m_Index, 0, idx);
 | 
			
		||||
    // Validate the obtained parameter index
 | 
			
		||||
    SQMOD_VALIDATE_PARAM(*this, idx);
 | 
			
		||||
    // Don't fall back to the invalid index anymore
 | 
			
		||||
    aa.Set(idx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Object Parameter::GetStatement() const
 | 
			
		||||
{
 | 
			
		||||
    return GetStatementObj(m_Handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Object Parameter::GetConnection() const
 | 
			
		||||
{
 | 
			
		||||
    return GetConnectionObj(SQMOD_GET_VALID(*this)->mConn);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetValue(const Object & value)
 | 
			
		||||
{
 | 
			
		||||
    switch (value.GetType())
 | 
			
		||||
    {
 | 
			
		||||
        case OT_NULL:
 | 
			
		||||
        {
 | 
			
		||||
            SetNull();
 | 
			
		||||
        } break;
 | 
			
		||||
        case OT_INTEGER:
 | 
			
		||||
        {
 | 
			
		||||
            SetInteger(value.Cast< SQInteger >());
 | 
			
		||||
        } break;
 | 
			
		||||
        case OT_FLOAT:
 | 
			
		||||
        {
 | 
			
		||||
            SetFloat(value.Cast< SQFloat >());
 | 
			
		||||
        } break;
 | 
			
		||||
        case OT_BOOL:
 | 
			
		||||
        {
 | 
			
		||||
            SetBool(value.Cast< bool >());
 | 
			
		||||
        } break;
 | 
			
		||||
        case OT_STRING:
 | 
			
		||||
        {
 | 
			
		||||
            SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
            // Remember the current stack size
 | 
			
		||||
            const StackGuard sg;
 | 
			
		||||
            // Push the object onto the stack
 | 
			
		||||
            Var< Object >::push(DefaultVM::Get(), value);
 | 
			
		||||
            // Pop the object from the stack as a string
 | 
			
		||||
            const Var< CSStr > str(DefaultVM::Get(), -1);
 | 
			
		||||
            // Attempt to bind the specified value
 | 
			
		||||
            SetStringRaw(str.value, ConvTo< SQInteger >::From(str.size));
 | 
			
		||||
        } break;
 | 
			
		||||
        default: STHROWF("No known conversion for the specified value type");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetBool(bool value)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Attempt to bind the specified value
 | 
			
		||||
    m_Handle->mStatus = sqlite3_bind_int(m_Handle->mPtr, m_Index, value);
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF(SQMOD_BINDFAILED, "bool", m_Index, m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetChar(SQInteger value)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Attempt to bind the specified value
 | 
			
		||||
    m_Handle->mStatus = sqlite3_bind_int(m_Handle->mPtr, m_Index, ConvTo< SQChar >::From(value));
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF(SQMOD_BINDFAILED, "char", m_Index, m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetInteger(SQInteger value)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Attempt to bind the specified value
 | 
			
		||||
    m_Handle->mStatus = sqlite3_bind_integer(m_Handle->mPtr, m_Index, value);
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF(SQMOD_BINDFAILED, "integer", m_Index, m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetInt8(SQInteger value)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Attempt to bind the specified value
 | 
			
		||||
    m_Handle->mStatus = sqlite3_bind_int(m_Handle->mPtr, m_Index, ConvTo< Int8 >::From(value));
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF(SQMOD_BINDFAILED, "int8", m_Index, m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetUint8(SQInteger value)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Attempt to bind the specified value
 | 
			
		||||
    m_Handle->mStatus = sqlite3_bind_int(m_Handle->mPtr, m_Index, ConvTo< Uint8 >::From(value));
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF(SQMOD_BINDFAILED, "uint8", m_Index, m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetInt16(SQInteger value)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Attempt to bind the specified value
 | 
			
		||||
    m_Handle->mStatus = sqlite3_bind_int(m_Handle->mPtr, m_Index, ConvTo< Int16 >::From(value));
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF(SQMOD_BINDFAILED, "int16", m_Index, m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetUint16(SQInteger value)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Attempt to bind the specified value
 | 
			
		||||
    m_Handle->mStatus = sqlite3_bind_int(m_Handle->mPtr, m_Index, ConvTo< Uint16 >::From(value));
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF(SQMOD_BINDFAILED, "uint16", m_Index, m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetInt32(SQInteger value)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Attempt to bind the specified value
 | 
			
		||||
    m_Handle->mStatus = sqlite3_bind_int(m_Handle->mPtr, m_Index, ConvTo< Int32 >::From(value));
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF(SQMOD_BINDFAILED, "int32", m_Index, m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetUint32(SQInteger value)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Attempt to bind the specified value
 | 
			
		||||
    m_Handle->mStatus = sqlite3_bind_int(m_Handle->mPtr, m_Index, ConvTo< Uint32 >::From(value));
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF(SQMOD_BINDFAILED, "uint32", m_Index, m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetInt64(const Object & value)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Attempt to bind the specified value
 | 
			
		||||
    m_Handle->mStatus = sqlite3_bind_int64(m_Handle->mPtr, m_Index, value.Cast< const SLongInt & >().GetNum());
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF(SQMOD_BINDFAILED, "int64", m_Index, m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetUint64(const Object & value)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Attempt to bind the specified value
 | 
			
		||||
    m_Handle->mStatus = sqlite3_bind_int64(m_Handle->mPtr, m_Index, value.Cast< const ULongInt & >().GetNum());
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF(SQMOD_BINDFAILED, "uint64", m_Index, m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetFloat(SQFloat value)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Attempt to bind the specified value
 | 
			
		||||
    m_Handle->mStatus = sqlite3_bind_double(m_Handle->mPtr, m_Index, value);
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF(SQMOD_BINDFAILED, "float", m_Index, m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetFloat32(SQFloat value)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Attempt to bind the specified value
 | 
			
		||||
    m_Handle->mStatus = sqlite3_bind_double(m_Handle->mPtr, m_Index, ConvTo< Float32 >::From(value));
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF(SQMOD_BINDFAILED, "float32", m_Index, m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetFloat64(SQFloat value)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Attempt to bind the specified value
 | 
			
		||||
    m_Handle->mStatus = sqlite3_bind_double(m_Handle->mPtr, m_Index, value);
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF(SQMOD_BINDFAILED, "float64", m_Index, m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetString(StackStrF & value)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Attempt to bind the specified value
 | 
			
		||||
    m_Handle->mStatus = sqlite3_bind_text(m_Handle->mPtr, m_Index, value.mPtr, value.mLen, SQLITE_TRANSIENT);
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF(SQMOD_BINDFAILED, "string", m_Index, m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetStringRaw(CSStr value, SQInteger length)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Attempt to bind the specified value
 | 
			
		||||
    m_Handle->mStatus = sqlite3_bind_text(m_Handle->mPtr, m_Index, value, length, SQLITE_TRANSIENT);
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF(SQMOD_BINDFAILED, "string", m_Index, m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetZeroBlob(SQInteger size)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Attempt to bind the specified value
 | 
			
		||||
    m_Handle->mStatus = sqlite3_bind_zeroblob(m_Handle->mPtr, m_Index, ConvTo< Int32 >::From(size));
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF(SQMOD_BINDFAILED, "blob", m_Index, m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetBlob(const Object & value)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // The blob data pointer and size
 | 
			
		||||
    SQUserPointer ptr = nullptr;
 | 
			
		||||
    SQInteger len = 0;
 | 
			
		||||
    // Grab the associated object virtual machine
 | 
			
		||||
    HSQUIRRELVM vm = value.GetVM();
 | 
			
		||||
    // Extract the blob data from the specified object
 | 
			
		||||
    {
 | 
			
		||||
        // Remember the current stack size
 | 
			
		||||
        const StackGuard sg(vm);
 | 
			
		||||
        // Push the specified object onto the stack
 | 
			
		||||
        Var< const Object & >::push(vm, value);
 | 
			
		||||
        // Grab the blob data pointer
 | 
			
		||||
        if (SQ_FAILED(sqstd_getblob(vm, -1, &ptr)))
 | 
			
		||||
        {
 | 
			
		||||
            STHROWF("Unable to obtain the blob data");
 | 
			
		||||
        }
 | 
			
		||||
        // Grab the blob data size
 | 
			
		||||
        len = sqstd_getblobsize(vm, -1);
 | 
			
		||||
    }
 | 
			
		||||
    // Attempt to bind the specified value
 | 
			
		||||
    m_Handle->mStatus = sqlite3_bind_blob(m_Handle->mPtr, m_Index, ptr, len, SQLITE_TRANSIENT);
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF(SQMOD_BINDFAILED, "blob", m_Index, m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetData(const SqBuffer & value)
 | 
			
		||||
{
 | 
			
		||||
    // Grab the internal buffer
 | 
			
		||||
    Buffer & buff = *value.GetRef();
 | 
			
		||||
    // Attempt to bind the specified value
 | 
			
		||||
#ifdef _SQ64
 | 
			
		||||
    m_Handle->mStatus = sqlite3_bind_blob64(m_Handle->mPtr, m_Index, buff.Data(), buff.Position(), SQLITE_TRANSIENT);
 | 
			
		||||
#else
 | 
			
		||||
    m_Handle->mStatus = sqlite3_bind_blob(m_Handle->mPtr, m_Index, buff.Data(), buff.Position(), SQLITE_TRANSIENT);
 | 
			
		||||
#endif
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF(SQMOD_BINDFAILED, "buffer", m_Index, m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetDataEx(const SqBuffer & value, SQInteger offset, SQInteger length)
 | 
			
		||||
{
 | 
			
		||||
    // Grab the internal buffer
 | 
			
		||||
    Buffer & buff = *value.GetRef();
 | 
			
		||||
    // Make sure we are within range
 | 
			
		||||
    if (offset < 0)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Negative buffer offset is not allowed: %d", offset);
 | 
			
		||||
    }
 | 
			
		||||
    else if (offset < 0)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Negative buffer length is not allowed: %d", length);
 | 
			
		||||
    }
 | 
			
		||||
    else if (offset + length > buff.Capacity())
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Buffer range is outside boundaries: (%d+%d) > %u", offset, length, buff.Capacity());
 | 
			
		||||
    }
 | 
			
		||||
    // Attempt to bind the specified value
 | 
			
		||||
#ifdef _SQ64
 | 
			
		||||
    m_Handle->mStatus = sqlite3_bind_blob64(m_Handle->mPtr, m_Index, (buff.Data() + offset), static_cast< int >(offset + length), SQLITE_TRANSIENT);
 | 
			
		||||
#else
 | 
			
		||||
        m_Handle->mStatus = sqlite3_bind_blob(m_Handle->mPtr, m_Index, (buff.Data() + offset), static_cast< int >(offset + length), SQLITE_TRANSIENT);
 | 
			
		||||
#endif
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF(SQMOD_BINDFAILED, "buffer", m_Index, m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetDate(const Date & value)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Attempt to generate the specified date string
 | 
			
		||||
    CSStr ptr = FmtStr(_SC("%s 00:00:00"), value.ToString());
 | 
			
		||||
    // Attempt to bind the specified value
 | 
			
		||||
    m_Handle->mStatus = sqlite3_bind_text(m_Handle->mPtr, m_Index, ptr, -1, SQLITE_TRANSIENT);
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF(SQMOD_BINDFAILED, "date", m_Index, m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetDateEx(SQInteger year, SQInteger month, SQInteger day)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Convert the specified values within the proper ranges
 | 
			
		||||
    const uint16_t y = ConvTo< uint16_t >::From(year);
 | 
			
		||||
    const uint8_t m = ConvTo< uint8_t >::From(month), d = ConvTo< uint8_t >::From(day);
 | 
			
		||||
    // Validate the specified date
 | 
			
		||||
    if (!Chrono::ValidDate(y, m, d))
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Invalid date (%u-%u-%u)", y, m, d);
 | 
			
		||||
    }
 | 
			
		||||
    // Attempt to generate the specified date string
 | 
			
		||||
    CSStr ptr = FmtStr(_SC("%u-%u-%u 00:00:00"), y, m, d);
 | 
			
		||||
    // Attempt to bind the specified value
 | 
			
		||||
    m_Handle->mStatus = sqlite3_bind_text(m_Handle->mPtr, m_Index, ptr, -1, SQLITE_TRANSIENT);
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF(SQMOD_BINDFAILED, "date", m_Index, m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetTime(const Time & value)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Attempt to bind the specified value
 | 
			
		||||
    m_Handle->mStatus = sqlite3_bind_int(m_Handle->mPtr, m_Index, value.GetTimestamp().GetSecondsI());
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF(SQMOD_BINDFAILED, "time", m_Index, m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetTimeEx(SQInteger hour, SQInteger minute, SQInteger second)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Convert the specified values within the proper ranges
 | 
			
		||||
    const uint8_t h = ConvTo< uint8_t >::From(hour)
 | 
			
		||||
                , m = ConvTo< uint8_t >::From(minute)
 | 
			
		||||
                , s = ConvTo< uint8_t >::From(second);
 | 
			
		||||
    // Is the specified hour within range?
 | 
			
		||||
    if (h >= 24)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Hour value is out of range: %u >= 24", h);
 | 
			
		||||
    }
 | 
			
		||||
    // Is the specified minute within range?
 | 
			
		||||
    else if (m >= 60)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Minute value is out of range: %u >= 60", m);
 | 
			
		||||
    }
 | 
			
		||||
    // Is the specified second within range?
 | 
			
		||||
    else if (s >= 60)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Second value is out of range: %u >= 60", s);
 | 
			
		||||
    }
 | 
			
		||||
    // Calculate the number of seconds in the specified time and bind the resulted value
 | 
			
		||||
    m_Handle->mStatus = sqlite3_bind_int(m_Handle->mPtr, m_Index, (h * (60 * 60)) + (m * 60) + s);
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF(SQMOD_BINDFAILED, "time", m_Index, m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetDatetime(const Datetime & value)
 | 
			
		||||
{
 | 
			
		||||
    SetDatetimeEx(value.GetYear(), value.GetMonth(), value.GetDay(), value.GetHour(), value.GetMinute(), value.GetSecond());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetDatetimeEx(SQInteger year, SQInteger month, SQInteger day, SQInteger hour, SQInteger minute, SQInteger second)
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Convert the specified values within the proper ranges
 | 
			
		||||
    const uint16_t y = ConvTo< uint16_t >::From(year);
 | 
			
		||||
    const uint8_t mo = ConvTo< uint8_t >::From(month)
 | 
			
		||||
                , d = ConvTo< uint8_t >::From(day)
 | 
			
		||||
                , h = ConvTo< uint8_t >::From(hour)
 | 
			
		||||
                , mi = ConvTo< uint8_t >::From(minute)
 | 
			
		||||
                , s = ConvTo< uint8_t >::From(second);
 | 
			
		||||
    // Validate the specified date
 | 
			
		||||
    if (!Chrono::ValidDate(y, mo, d))
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Invalid date (%u-%u-%u)", y, mo, d);
 | 
			
		||||
    }
 | 
			
		||||
    // Is the specified hour within range?
 | 
			
		||||
    else if (h >= 24)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Hour value is out of range: %u >= 24", h);
 | 
			
		||||
    }
 | 
			
		||||
    // Is the specified minute within range?
 | 
			
		||||
    else if (mi >= 60)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Minute value is out of range: %u >= 60", mi);
 | 
			
		||||
    }
 | 
			
		||||
    // Is the specified second within range?
 | 
			
		||||
    else if (s >= 60)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Second value is out of range: %u >= 60", s);
 | 
			
		||||
    }
 | 
			
		||||
    // Attempt to generate the specified date string
 | 
			
		||||
    CSStr ptr = FmtStr(_SC("%04u-%02u-%02u %02u:%02u:%02u"), y, mo, d, h, mi, s);
 | 
			
		||||
    // Attempt to bind the specified value
 | 
			
		||||
    m_Handle->mStatus = sqlite3_bind_text(m_Handle->mPtr, m_Index, ptr, -1, SQLITE_TRANSIENT);
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF(SQMOD_BINDFAILED, "date-time", m_Index, m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetNow()
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Attempt to bind the specified value
 | 
			
		||||
    m_Handle->mStatus = sqlite3_bind_int(m_Handle->mPtr, m_Index,
 | 
			
		||||
                                            static_cast< Int32 >(std::time(nullptr)));
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF(SQMOD_BINDFAILED, "time-stamp", m_Index, m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
void Parameter::SetNull()
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Attempt to bind the specified value
 | 
			
		||||
    m_Handle->mStatus = sqlite3_bind_null(m_Handle->mPtr, m_Index);
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF(SQMOD_BINDFAILED, "null", m_Index, m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ================================================================================================
 | 
			
		||||
void Register_Parameter(Table & sqlns)
 | 
			
		||||
{
 | 
			
		||||
    sqlns.Bind(_SC("Parameter"),
 | 
			
		||||
        Class< Parameter >(sqlns.GetVM(), Typename::Str)
 | 
			
		||||
        // Constructors
 | 
			
		||||
        .Ctor()
 | 
			
		||||
        .Ctor< const Parameter & >()
 | 
			
		||||
        // Meta-methods
 | 
			
		||||
        .SquirrelFunc(_SC("_typename"), &Typename::Fn)
 | 
			
		||||
        .Func(_SC("_tostring"), &Parameter::ToString)
 | 
			
		||||
        // Properties
 | 
			
		||||
        .Prop(_SC("IsValid"), &Parameter::IsValid)
 | 
			
		||||
        .Prop(_SC("References"), &Parameter::GetRefCount)
 | 
			
		||||
        .Prop(_SC("Index"), &Parameter::GetIndex)
 | 
			
		||||
        .Prop(_SC("Statement"), &Parameter::GetStatement)
 | 
			
		||||
        .Prop(_SC("Connection"), &Parameter::GetConnection)
 | 
			
		||||
        .Prop(_SC("References"), &Parameter::GetRefCount)
 | 
			
		||||
        .Prop(_SC("Name"), &Parameter::GetName)
 | 
			
		||||
        // Member Methods
 | 
			
		||||
        .Func(_SC("Release"), &Parameter::Release)
 | 
			
		||||
        .Func(_SC("SetValue"), &Parameter::SetValue)
 | 
			
		||||
        .Func(_SC("SetBool"), &Parameter::SetBool)
 | 
			
		||||
        .Func(_SC("SetChar"), &Parameter::SetChar)
 | 
			
		||||
        .Func(_SC("SetInteger"), &Parameter::SetInteger)
 | 
			
		||||
        .Func(_SC("SetInt8"), &Parameter::SetInt8)
 | 
			
		||||
        .Func(_SC("SetUint8"), &Parameter::SetUint8)
 | 
			
		||||
        .Func(_SC("SetInt16"), &Parameter::SetInt16)
 | 
			
		||||
        .Func(_SC("SetUint16"), &Parameter::SetUint16)
 | 
			
		||||
        .Func(_SC("SetInt32"), &Parameter::SetInt32)
 | 
			
		||||
        .Func(_SC("SetUint32"), &Parameter::SetUint32)
 | 
			
		||||
        .Func(_SC("SetInt64"), &Parameter::SetInt64)
 | 
			
		||||
        .Func(_SC("SetUint64"), &Parameter::SetUint64)
 | 
			
		||||
        .Func(_SC("SetFloat"), &Parameter::SetFloat)
 | 
			
		||||
        .Func(_SC("SetFloat32"), &Parameter::SetFloat32)
 | 
			
		||||
        .Func(_SC("SetFloat64"), &Parameter::SetFloat64)
 | 
			
		||||
        .FmtFunc(_SC("SetString"), &Parameter::SetString)
 | 
			
		||||
        .Func(_SC("SetZeroBlob"), &Parameter::SetZeroBlob)
 | 
			
		||||
        .Func(_SC("SetBlob"), &Parameter::SetBlob)
 | 
			
		||||
        .Func(_SC("SetData"), &Parameter::SetData)
 | 
			
		||||
        .Func(_SC("SetDataEx"), &Parameter::SetDataEx)
 | 
			
		||||
        .Func(_SC("SetDate"), &Parameter::SetDate)
 | 
			
		||||
        .Func(_SC("SetDateEx"), &Parameter::SetDateEx)
 | 
			
		||||
        .Func(_SC("SetTime"), &Parameter::SetTime)
 | 
			
		||||
        .Func(_SC("SetTimeEx"), &Parameter::SetTimeEx)
 | 
			
		||||
        .Func(_SC("SetDatetime"), &Parameter::SetDatetime)
 | 
			
		||||
        .Func(_SC("SetDatetimeEx"), &Parameter::SetDatetimeEx)
 | 
			
		||||
        .Func(_SC("SetNow"), &Parameter::SetNow)
 | 
			
		||||
        .Func(_SC("SetNull"), &Parameter::SetNull)
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
							
								
								
									
										411
									
								
								module/Library/SQLite/Parameter.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										411
									
								
								module/Library/SQLite/Parameter.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,411 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Library/SQLite/Handle.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include <cctype>
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Used to manage and interact with parameters from a database statement.
 | 
			
		||||
*/
 | 
			
		||||
class Parameter
 | 
			
		||||
{
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    friend class Statement;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    Int32       m_Index; // The index of the managed parameter.
 | 
			
		||||
    StmtRef     m_Handle; // Reference to the managed statement.
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the managed statement handle and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    void Validate(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    void Validate() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the managed statement handle and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    void ValidateCreated(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    void ValidateCreated() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the managed statement handle and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    const StmtRef & GetValid(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    const StmtRef & GetValid() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the managed statement handle and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    const StmtRef & GetCreated(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    const StmtRef & GetCreated() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the statement reference and parameter index, and throw an error if they're invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    void ValidateParam(Int32 idx, CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    void ValidateParam(Int32 idx) const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Modify the index to the specified value.
 | 
			
		||||
    */
 | 
			
		||||
    void SetIndex(Int32 idx)
 | 
			
		||||
    {
 | 
			
		||||
        // Assign the index with a failsafe to invalid on error
 | 
			
		||||
        AutoAssign< Int32 > aa(m_Index, -1, idx);
 | 
			
		||||
        // Validate the obtained parameter index
 | 
			
		||||
        SQMOD_VALIDATE_PARAM(*this, idx);
 | 
			
		||||
        // Don't fall back to the invalid index anymore
 | 
			
		||||
        aa.Set(idx);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Modify the index to the specified value.
 | 
			
		||||
    */
 | 
			
		||||
    void SetIndex(CSStr name)
 | 
			
		||||
    {
 | 
			
		||||
        SetIndex(sqlite3_bind_parameter_index(SQMOD_GET_CREATED(*this)->mPtr, name));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Modify the index to the specified value.
 | 
			
		||||
    */
 | 
			
		||||
    void SetIndex(const Object & param);
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Default constructor (null).
 | 
			
		||||
    */
 | 
			
		||||
    Parameter()
 | 
			
		||||
        : m_Index(0), m_Handle()
 | 
			
		||||
    {
 | 
			
		||||
        /* ... */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * No parameter constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Parameter(const StmtRef & stmt)
 | 
			
		||||
        : m_Index(0), m_Handle(stmt)
 | 
			
		||||
    {
 | 
			
		||||
        /* ... */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Index constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Parameter(const StmtRef & stmt, Int32 idx)
 | 
			
		||||
        : m_Index(idx), m_Handle(stmt)
 | 
			
		||||
    {
 | 
			
		||||
        SQMOD_VALIDATE_PARAM(*this, m_Index);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Name constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Parameter(const StmtRef & stmt, CSStr name)
 | 
			
		||||
        : m_Index(stmt ? sqlite3_bind_parameter_index(stmt->mPtr, name) : 0), m_Handle(stmt)
 | 
			
		||||
    {
 | 
			
		||||
        SQMOD_VALIDATE_PARAM(*this, m_Index);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Dynamic constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Parameter(const StmtRef & stmt, const Object & param)
 | 
			
		||||
        : m_Index(0), m_Handle(stmt)
 | 
			
		||||
    {
 | 
			
		||||
        if (!m_Handle)
 | 
			
		||||
        {
 | 
			
		||||
            STHROWF("Invalid SQLite statement reference");
 | 
			
		||||
        }
 | 
			
		||||
        // Extract the index
 | 
			
		||||
        SetIndex(param);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Parameter(const Parameter & o) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Move constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Parameter(Parameter && o) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy assignment operator.
 | 
			
		||||
    */
 | 
			
		||||
    Parameter & operator = (const Parameter & o) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Move assignment operator.
 | 
			
		||||
    */
 | 
			
		||||
    Parameter & operator = (Parameter && o) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Perform an equality comparison between two parameter indexes.
 | 
			
		||||
    */
 | 
			
		||||
    bool operator == (const Parameter & o) const
 | 
			
		||||
    {
 | 
			
		||||
        return (m_Index == o.m_Index);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Perform an inequality comparison between two parameter indexes.
 | 
			
		||||
    */
 | 
			
		||||
    bool operator != (const Parameter & 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 convert an instance of this type to a string.
 | 
			
		||||
    */
 | 
			
		||||
    CSStr ToString() const
 | 
			
		||||
    {
 | 
			
		||||
        CSStr val = nullptr;
 | 
			
		||||
        // Can we attempt to return the parameter name?
 | 
			
		||||
        if (m_Handle && m_Index)
 | 
			
		||||
        {
 | 
			
		||||
            val = sqlite3_bind_parameter_name(m_Handle->mPtr, m_Index);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            val = ToStrF(_SC("%d"), m_Index);
 | 
			
		||||
        }
 | 
			
		||||
        // Return the value if valid
 | 
			
		||||
        return val ? val : _SC("");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * See whether this statement is valid.
 | 
			
		||||
    */
 | 
			
		||||
    bool IsValid() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Handle; // An invalid statement means an invalid parameter
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Return the number of active references to this statement handle.
 | 
			
		||||
    */
 | 
			
		||||
    Uint32 GetRefCount() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Handle.Count();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the associated parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    Int32 GetIndex() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Index;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the associated database statement.
 | 
			
		||||
    */
 | 
			
		||||
    Object GetStatement() const;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the associated database connection.
 | 
			
		||||
    */
 | 
			
		||||
    Object GetConnection() const;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the name of the referenced parameter.
 | 
			
		||||
    */
 | 
			
		||||
    CSStr GetName() const
 | 
			
		||||
    {
 | 
			
		||||
        return sqlite3_bind_parameter_name(SQMOD_GET_CREATED(*this)->mPtr, m_Index);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Release the reference to the associated database statement and parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void Release()
 | 
			
		||||
    {
 | 
			
		||||
        m_Handle.Reset();
 | 
			
		||||
        m_Index = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a dynamic value at the referenced parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void SetValue(const Object & value);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a boolean value at the referenced parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void SetBool(bool value);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a character value at the referenced parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void SetChar(SQInteger value);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a native integer value at the referenced parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void SetInteger(SQInteger value);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a signed 8 bit integer value at the referenced parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void SetInt8(SQInteger value);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind an unsigned 8 bit integer value at the referenced parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void SetUint8(SQInteger value);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a signed 16 bit integer value at the referenced parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void SetInt16(SQInteger value);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind an unsigned 16 bit integer value at the referenced parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void SetUint16(SQInteger value);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a signed 32 bit integer value at the referenced parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void SetInt32(SQInteger value);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind an unsigned 32 bit integer value at the referenced parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void SetUint32(SQInteger value);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a signed 64 bit integer value at the referenced parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void SetInt64(const Object & value);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind an unsigned 64 bit integer value at the referenced parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void SetUint64(const Object & value);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a native floating point value at the referenced parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void SetFloat(SQFloat value);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a 32 bit floating point value at the referenced parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void SetFloat32(SQFloat value);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a 64 bit floating point value at the referenced parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void SetFloat64(SQFloat value);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a string value at the referenced parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void SetString(StackStrF & value);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a string value at the referenced parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void SetStringRaw(CSStr value, SQInteger length = -1);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a zeroed blob value at the referenced parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void SetZeroBlob(SQInteger size);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a blob value at the referenced parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void SetBlob(const Object & value);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a buffer value at the referenced parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void SetData(const SqBuffer & value);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a buffer value at the referenced parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void SetDataEx(const SqBuffer & value, SQInteger offset, SQInteger length);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a date value at the referenced parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void SetDate(const Date & value);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a date value at the referenced parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void SetDateEx(SQInteger year, SQInteger month, SQInteger day);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a time value at the referenced parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void SetTime(const Time & value);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a time value at the referenced parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void SetTimeEx(SQInteger hour, SQInteger minute, SQInteger second);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a date-time value at the referenced parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void SetDatetime(const Datetime & value);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a date-time value at the referenced parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void SetDatetimeEx(SQInteger year, SQInteger month, SQInteger day, SQInteger hour, SQInteger minute, SQInteger second);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind the current timestamp at the referenced parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void SetNow();
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a null value at the referenced parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    void SetNull();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
							
								
								
									
										525
									
								
								module/Library/SQLite/Statement.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										525
									
								
								module/Library/SQLite/Statement.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,525 @@
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Library/SQLite/Statement.hpp"
 | 
			
		||||
#include "Library/SQLite/Connection.hpp"
 | 
			
		||||
#include "Library/SQLite/Column.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include <cstring>
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
SQMODE_DECL_TYPENAME(Typename, _SC("SqLiteStatement"))
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
void Statement::Validate(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid SQLite statement reference =>[%s:%d]", file, line);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
void Statement::Validate() const
 | 
			
		||||
{
 | 
			
		||||
    if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid SQLite statement reference");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
void Statement::ValidateCreated(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid SQLite statement reference =>[%s:%d]", file, line);
 | 
			
		||||
    }
 | 
			
		||||
    else if (m_Handle->mPtr == nullptr)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid SQLite statement =>[%s:%d]", file, line);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
void Statement::ValidateCreated() const
 | 
			
		||||
{
 | 
			
		||||
    if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid SQLite statement reference");
 | 
			
		||||
    }
 | 
			
		||||
    else if (m_Handle->mPtr == nullptr)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Invalid SQLite statement");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
const StmtRef & Statement::GetValid(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    Validate(file, line);
 | 
			
		||||
    return m_Handle;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
const StmtRef & Statement::GetValid() const
 | 
			
		||||
{
 | 
			
		||||
    Validate();
 | 
			
		||||
    return m_Handle;
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
const StmtRef & Statement::GetCreated(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    ValidateCreated(file, line);
 | 
			
		||||
    return m_Handle;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
const StmtRef & Statement::GetCreated() const
 | 
			
		||||
{
 | 
			
		||||
    ValidateCreated();
 | 
			
		||||
    return m_Handle;
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
void Statement::ValidateColumn(Int32 idx, CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    ValidateCreated(file, line);
 | 
			
		||||
    // Is the specified index in range?
 | 
			
		||||
    if (!m_Handle->CheckColumn(idx))
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Column index is out of range: %d:%d =>[%s:%d]", idx, m_Handle->mColumns,
 | 
			
		||||
                    file, line);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
void Statement::ValidateColumn(Int32 idx) const
 | 
			
		||||
{
 | 
			
		||||
    ValidateCreated();
 | 
			
		||||
    // Is the specified index in range?
 | 
			
		||||
    if (!m_Handle->CheckColumn(idx))
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Column index is out of range: %d:%d", idx, m_Handle->mColumns);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
void Statement::ValidateParam(Int32 idx, CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    ValidateCreated(file, line);
 | 
			
		||||
    // Is the specified index in range?
 | 
			
		||||
    if (!m_Handle->CheckParameter(idx))
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Parameter index is out of range: %d:%d =>[%s:%d]", idx, m_Handle->mParameters,
 | 
			
		||||
                    file, line);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
void Statement::ValidateParam(Int32 idx) const
 | 
			
		||||
{
 | 
			
		||||
    ValidateCreated();
 | 
			
		||||
    // Is the specified index in range?
 | 
			
		||||
    if (!m_Handle->CheckParameter(idx))
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("Parameter index is out of range: %d:%d", idx, m_Handle->mParameters);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
void Statement::ValidateRow(CCStr file, Int32 line) const
 | 
			
		||||
{
 | 
			
		||||
    ValidateCreated(file, line);
 | 
			
		||||
    // Do we have any rows available?
 | 
			
		||||
    if (!m_Handle->mGood)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("No row available =>[%s:%d]", file, line);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
void Statement::ValidateRow() const
 | 
			
		||||
{
 | 
			
		||||
    ValidateCreated();
 | 
			
		||||
    // Do we have any rows available?
 | 
			
		||||
    if (!m_Handle->mGood)
 | 
			
		||||
    {
 | 
			
		||||
        SqThrowF("No row available");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Statement::Statement(const Connection & connection, StackStrF & query)
 | 
			
		||||
    : m_Handle(new StmtHnd(connection.GetHandle()))
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_GET_VALID(*this)->Create(query.mPtr, query.mLen);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Object Statement::GetConnection() const
 | 
			
		||||
{
 | 
			
		||||
    return Object(new Connection(SQMOD_GET_VALID(*this)->mConn));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Statement & Statement::Reset()
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Specify that we don't have a row available and we haven't finished stepping
 | 
			
		||||
    m_Handle->mGood = false;
 | 
			
		||||
    m_Handle->mDone = false;
 | 
			
		||||
    // Attempt to reset the statement to it's initial state
 | 
			
		||||
    m_Handle->mStatus = sqlite3_reset(m_Handle->mPtr);
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Unable to reset statement [%s]", m_Handle->ErrStr());
 | 
			
		||||
    }
 | 
			
		||||
    // Allow further chaining of operations
 | 
			
		||||
    return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Statement & Statement::Clear()
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Specify that we don't have a row available and we haven't finished stepping
 | 
			
		||||
    m_Handle->mGood = false;
 | 
			
		||||
    m_Handle->mDone = false;
 | 
			
		||||
    // Attempt to clear the statement
 | 
			
		||||
    m_Handle->mStatus = sqlite3_clear_bindings(m_Handle->mPtr);
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Unable to clear statement [%s]", m_Handle->ErrStr());
 | 
			
		||||
    }
 | 
			
		||||
    // Allow further chaining of operations
 | 
			
		||||
    return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Int32 Statement::Exec()
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Did we reset first?
 | 
			
		||||
    if (m_Handle->mDone)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Executed without resetting first");
 | 
			
		||||
    }
 | 
			
		||||
    // Attempt to step the statement
 | 
			
		||||
    m_Handle->mStatus = sqlite3_step(m_Handle->mPtr);
 | 
			
		||||
    // Have we finished stepping?
 | 
			
		||||
    if (m_Handle->mStatus == SQLITE_DONE)
 | 
			
		||||
    {
 | 
			
		||||
        // Specify that we don't have row available and we finished stepping
 | 
			
		||||
        m_Handle->mGood = false;
 | 
			
		||||
        m_Handle->mDone = true;
 | 
			
		||||
        // Return the changes made by this statement
 | 
			
		||||
        return sqlite3_changes(m_Handle->mConn->mPtr);
 | 
			
		||||
    }
 | 
			
		||||
    // Specify that we don't have any row and we haven't finished stepping
 | 
			
		||||
    m_Handle->mGood = false;
 | 
			
		||||
    m_Handle->mDone = false;
 | 
			
		||||
    // Inspect the result
 | 
			
		||||
    switch (m_Handle->mStatus)
 | 
			
		||||
    {
 | 
			
		||||
        // We don't expect any rows to be returned in this case!
 | 
			
		||||
        case SQLITE_ROW:    STHROWF("Results were found");
 | 
			
		||||
        // fall through
 | 
			
		||||
        case SQLITE_BUSY:   STHROWF("Database was busy");
 | 
			
		||||
        // fall through
 | 
			
		||||
        case SQLITE_ERROR:  STHROWF("Runtime error occurred");
 | 
			
		||||
        // fall through
 | 
			
		||||
        case SQLITE_MISUSE: STHROWF("Statement misuse");
 | 
			
		||||
        // fall through
 | 
			
		||||
        default:            STHROWF("Unknown failure [%s]", m_Handle->ErrStr());
 | 
			
		||||
    }
 | 
			
		||||
    // Operation failed (shouldn't reach this point!)
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
bool Statement::Step()
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_CREATED(*this);
 | 
			
		||||
    // Did we reset first?
 | 
			
		||||
    if (m_Handle->mDone)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Stepped without resetting first");
 | 
			
		||||
    }
 | 
			
		||||
    // Attempt to step the statement
 | 
			
		||||
    m_Handle->mStatus = sqlite3_step(m_Handle->mPtr);
 | 
			
		||||
    // Do we have a row available?
 | 
			
		||||
    if (m_Handle->mStatus == SQLITE_ROW)
 | 
			
		||||
    {
 | 
			
		||||
        // Specify that we have a row available
 | 
			
		||||
        return (m_Handle->mGood = true);
 | 
			
		||||
    }
 | 
			
		||||
    // Have we finished stepping?
 | 
			
		||||
    else if (m_Handle->mStatus == SQLITE_DONE)
 | 
			
		||||
    {
 | 
			
		||||
        // Specify that we finished stepping
 | 
			
		||||
        m_Handle->mDone = true;
 | 
			
		||||
        // Specify that we don't have a row available
 | 
			
		||||
        return (m_Handle->mGood = false);
 | 
			
		||||
    }
 | 
			
		||||
    // Specify that we don't have any row and we haven't finished stepping
 | 
			
		||||
    m_Handle->mGood = false;
 | 
			
		||||
    m_Handle->mDone = false;
 | 
			
		||||
    // Inspect the result
 | 
			
		||||
    switch (m_Handle->mStatus)
 | 
			
		||||
    {
 | 
			
		||||
        case SQLITE_BUSY:   STHROWF("Database was busy");
 | 
			
		||||
        // fall through
 | 
			
		||||
        case SQLITE_ERROR:  STHROWF("Runtime error occurred");
 | 
			
		||||
        // fall through
 | 
			
		||||
        case SQLITE_MISUSE: STHROWF("Statement misuse");
 | 
			
		||||
        // fall through
 | 
			
		||||
        default:            STHROWF("Unknown failure [%s]", m_Handle->ErrStr());
 | 
			
		||||
    }
 | 
			
		||||
    // Operation failed (shouldn't reach this point!)
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Statement & Statement::SetArray(Int32 idx, const Array & arr)
 | 
			
		||||
{
 | 
			
		||||
    // Obtain a script iterator
 | 
			
		||||
    Array::iterator itr;
 | 
			
		||||
    // Create a parameter instance to bind the values
 | 
			
		||||
    Parameter param(m_Handle);
 | 
			
		||||
    // Process each element until _next returns null
 | 
			
		||||
    while (idx <= m_Handle->mParameters && arr.Next(itr))
 | 
			
		||||
    {
 | 
			
		||||
        // Update the parameter index
 | 
			
		||||
        param.SetIndex(idx++);
 | 
			
		||||
        // Bind it to the current index
 | 
			
		||||
        param.SetValue(Object(itr.getValue()));
 | 
			
		||||
    }
 | 
			
		||||
    // Allow further chaining of operations
 | 
			
		||||
    return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Statement & Statement::SetTable(const Table & tbl)
 | 
			
		||||
{
 | 
			
		||||
    // Is there anything to bind?
 | 
			
		||||
    if (tbl.GetSize() <= 0)
 | 
			
		||||
    {
 | 
			
		||||
        return *this; // Nothing to bind!
 | 
			
		||||
    }
 | 
			
		||||
    // Obtain a table iterator
 | 
			
		||||
    Table::iterator itr;
 | 
			
		||||
    // Create a parameter instance to bind the values
 | 
			
		||||
    Parameter param(m_Handle);
 | 
			
		||||
    // Process each element until _next returns null
 | 
			
		||||
    while (tbl.Next(itr))
 | 
			
		||||
    {
 | 
			
		||||
        // Update the parameter index
 | 
			
		||||
        param.SetIndex(itr.getName());
 | 
			
		||||
        // Bind it to the current index
 | 
			
		||||
        param.SetValue(Object(itr.getValue()));
 | 
			
		||||
    }
 | 
			
		||||
    // Allow further chaining of operations
 | 
			
		||||
    return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Array Statement::GetArray(Int32 min, Int32 max) const
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_ROW(*this);
 | 
			
		||||
    // Is the specified minimum index valid?
 | 
			
		||||
    if (min < 0)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Minimum is bellow zero: %d", min);
 | 
			
		||||
    }
 | 
			
		||||
    // Is the minimum actually the minimum?
 | 
			
		||||
    else if (min > max)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Minimum is higher than maximum: %d > %d", min, max);
 | 
			
		||||
    }
 | 
			
		||||
    // Is the minimum in range?
 | 
			
		||||
    else if (!m_Handle->CheckColumn(min))
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Minimum is out of range: %d:%d", min, m_Handle->mColumns);
 | 
			
		||||
    }
 | 
			
		||||
    // Is the maximum in range?
 | 
			
		||||
    else if (!m_Handle->CheckColumn(max))
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Maximum is out of range: %d:%d", max, m_Handle->mColumns);
 | 
			
		||||
    }
 | 
			
		||||
    // Allocate an array large enough to hold the values from selected columns
 | 
			
		||||
    Array arr(DefaultVM::Get(), max-min);
 | 
			
		||||
    // Create a column instance to retrieve the values
 | 
			
		||||
    Column column(m_Handle);
 | 
			
		||||
    // Array element counter
 | 
			
		||||
    Int32 elem = 0;
 | 
			
		||||
    // Process the range of selected columns
 | 
			
		||||
    while (min <= max)
 | 
			
		||||
    {
 | 
			
		||||
        // Update the column index
 | 
			
		||||
        column.SetIndex(min++);
 | 
			
		||||
        // Retrieve the column value and bind it to the array
 | 
			
		||||
        arr.SetValue(elem++, column.GetValue());
 | 
			
		||||
    }
 | 
			
		||||
    // Return the resulted array
 | 
			
		||||
    return arr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Table Statement::GetTable(Int32 min, Int32 max) const
 | 
			
		||||
{
 | 
			
		||||
    SQMOD_VALIDATE_ROW(*this);
 | 
			
		||||
    // Is the specified minimum index valid?
 | 
			
		||||
    if (min < 0)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Minimum is bellow zero: %d", min);
 | 
			
		||||
    }
 | 
			
		||||
    // Is the minimum actually the minimum?
 | 
			
		||||
    else if (min > max)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Minimum is higher than maximum: %d > %d", min, max);
 | 
			
		||||
    }
 | 
			
		||||
    // Is the minimum in range>
 | 
			
		||||
    else if (!m_Handle->CheckColumn(min))
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Minimum is out of range: %d:%d", min, m_Handle->mColumns);
 | 
			
		||||
    }
 | 
			
		||||
    // Is the maximum in range?
 | 
			
		||||
    else if (!m_Handle->CheckColumn(max))
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Maximum is out of range: %d:%d", max, m_Handle->mColumns);
 | 
			
		||||
    }
 | 
			
		||||
    // Create a table to hold the selected column values
 | 
			
		||||
    Table tbl(DefaultVM::Get());
 | 
			
		||||
    // Create a column instance to retrieve the values
 | 
			
		||||
    Column column(m_Handle);
 | 
			
		||||
    // Process the range of selected columns
 | 
			
		||||
    while (min <= max)
 | 
			
		||||
    {
 | 
			
		||||
        // Attempt to obtain the column name
 | 
			
		||||
        CSStr name = sqlite3_column_name(m_Handle->mPtr, min);
 | 
			
		||||
        // Validate the obtained name
 | 
			
		||||
        if (!name)
 | 
			
		||||
        {
 | 
			
		||||
            STHROWF("Unable to retrieve name of column (%d)", min);
 | 
			
		||||
        }
 | 
			
		||||
        // Update the column index
 | 
			
		||||
        column.SetIndex(min++);
 | 
			
		||||
        // Retrieve the column value and bind it to the table
 | 
			
		||||
        tbl.SetValue(name, column.GetValue());
 | 
			
		||||
    }
 | 
			
		||||
    // Return the resulted table
 | 
			
		||||
    return tbl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ================================================================================================
 | 
			
		||||
void Register_Statement(Table & sqlns)
 | 
			
		||||
{
 | 
			
		||||
    sqlns.Bind(_SC("Statement"),
 | 
			
		||||
        Class< Statement >(sqlns.GetVM(), Typename::Str)
 | 
			
		||||
        // Constructors
 | 
			
		||||
        .Ctor()
 | 
			
		||||
        .Ctor< const Statement & >()
 | 
			
		||||
        .Ctor< const Connection &, StackStrF & >()
 | 
			
		||||
        // Meta-methods
 | 
			
		||||
        .SquirrelFunc(_SC("_typename"), &Typename::Fn)
 | 
			
		||||
        .Func(_SC("_tostring"), &Statement::ToString)
 | 
			
		||||
        // Properties
 | 
			
		||||
        .Prop(_SC("IsValid"), &Statement::IsValid)
 | 
			
		||||
        .Prop(_SC("Prepared"), &Statement::IsPrepared)
 | 
			
		||||
        .Prop(_SC("References"), &Statement::GetReferences)
 | 
			
		||||
        .Prop(_SC("Connection"), &Statement::GetConnection)
 | 
			
		||||
        .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("Parameters"), &Statement::GetParameters)
 | 
			
		||||
        .Prop(_SC("Query"), &Statement::GetQuery)
 | 
			
		||||
        .Prop(_SC("Good"), &Statement::GetGood)
 | 
			
		||||
        .Prop(_SC("Done"), &Statement::GetDone)
 | 
			
		||||
        .Prop(_SC("DataCount"), &Statement::GetDataCount)
 | 
			
		||||
        // Member Methods
 | 
			
		||||
        .Func(_SC("Release"), &Statement::Release)
 | 
			
		||||
        .Func(_SC("CheckParameter"), &Statement::CheckParameter)
 | 
			
		||||
        .FmtFunc(_SC("GetParameterIndex"), &Statement::GetParameterIndex)
 | 
			
		||||
        .Func(_SC("GetParameterName"), &Statement::GetParameterName)
 | 
			
		||||
        .Func(_SC("CheckColumn"), &Statement::CheckColumn)
 | 
			
		||||
        .Func(_SC("IsColumnNull"), &Statement::IsColumnNull)
 | 
			
		||||
        .FmtFunc(_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("Reset"), &Statement::Reset)
 | 
			
		||||
        .Func(_SC("Clear"), &Statement::Clear)
 | 
			
		||||
        .Func(_SC("Exec"), &Statement::Exec)
 | 
			
		||||
        .Func(_SC("Step"), &Statement::Step)
 | 
			
		||||
        .Func(_SC("Param"), &Statement::GetParameter)
 | 
			
		||||
        .Func(_SC("Parameter"), &Statement::GetParameter)
 | 
			
		||||
        .Func(_SC("SetValue"), &Statement::SetValue)
 | 
			
		||||
        .Func(_SC("SetBool"), &Statement::SetBool)
 | 
			
		||||
        .Func(_SC("SetChar"), &Statement::SetChar)
 | 
			
		||||
        .Func(_SC("SetInteger"), &Statement::SetInteger)
 | 
			
		||||
        .Func(_SC("SetInt8"), &Statement::SetInt8)
 | 
			
		||||
        .Func(_SC("SetUint8"), &Statement::SetUint8)
 | 
			
		||||
        .Func(_SC("SetInt16"), &Statement::SetInt16)
 | 
			
		||||
        .Func(_SC("SetUint16"), &Statement::SetUint16)
 | 
			
		||||
        .Func(_SC("SetInt32"), &Statement::SetInt32)
 | 
			
		||||
        .Func(_SC("SetUint32"), &Statement::SetUint32)
 | 
			
		||||
        .Func(_SC("SetInt64"), &Statement::SetInt64)
 | 
			
		||||
        .Func(_SC("SetUint64"), &Statement::SetUint64)
 | 
			
		||||
        .Func(_SC("SetFloat"), &Statement::SetFloat)
 | 
			
		||||
        .Func(_SC("SetFloat32"), &Statement::SetFloat32)
 | 
			
		||||
        .Func(_SC("SetFloat64"), &Statement::SetFloat64)
 | 
			
		||||
        .FmtFunc(_SC("SetString"), &Statement::SetString)
 | 
			
		||||
        .Func(_SC("SetZeroBlob"), &Statement::SetZeroBlob)
 | 
			
		||||
        .Func(_SC("SetBlob"), &Statement::SetBlob)
 | 
			
		||||
        .Func(_SC("SetData"), &Statement::SetData)
 | 
			
		||||
        .Func(_SC("SetDate"), &Statement::SetDate)
 | 
			
		||||
        .Func(_SC("SetDateEx"), &Statement::SetDateEx)
 | 
			
		||||
        .Func(_SC("SetTime"), &Statement::SetTime)
 | 
			
		||||
        .Func(_SC("SetTimeEx"), &Statement::SetTimeEx)
 | 
			
		||||
        .Func(_SC("SetDatetime"), &Statement::SetDatetime)
 | 
			
		||||
        .Func(_SC("SetDatetimeEx"), &Statement::SetDatetimeEx)
 | 
			
		||||
        .Func(_SC("SetNow"), &Statement::SetNow)
 | 
			
		||||
        .Func(_SC("SetNull"), &Statement::SetNull)
 | 
			
		||||
        .Func(_SC("SetArray"), &Statement::SetArray)
 | 
			
		||||
        .Func(_SC("SetTable"), &Statement::SetTable)
 | 
			
		||||
        .Func(_SC("Field"), &Statement::GetColumn)
 | 
			
		||||
        .Func(_SC("Column"), &Statement::GetColumn)
 | 
			
		||||
        .Func(_SC("GetValue"), &Statement::GetValue)
 | 
			
		||||
        .Func(_SC("GetNumber"), &Statement::GetNumber)
 | 
			
		||||
        .Func(_SC("GetInteger"), &Statement::GetInteger)
 | 
			
		||||
        .Func(_SC("GetFloat"), &Statement::GetFloat)
 | 
			
		||||
        .Func(_SC("GetLong"), &Statement::GetLong)
 | 
			
		||||
        .Func(_SC("GetString"), &Statement::GetString)
 | 
			
		||||
        .Func(_SC("GetBoolean"), &Statement::GetBoolean)
 | 
			
		||||
        .Func(_SC("GetChar"), &Statement::GetChar)
 | 
			
		||||
        .Func(_SC("GetBuffer"), &Statement::GetBuffer)
 | 
			
		||||
        .Func(_SC("GetBlob"), &Statement::GetBlob)
 | 
			
		||||
        // Member overloads
 | 
			
		||||
        .Overload< Array (Statement::*)(void) const >(_SC("GetArray"), &Statement::GetArray)
 | 
			
		||||
        .Overload< Array (Statement::*)(Int32) const >(_SC("GetArray"), &Statement::GetArray)
 | 
			
		||||
        .Overload< Array (Statement::*)(Int32, Int32) const >(_SC("GetArray"), &Statement::GetArray)
 | 
			
		||||
        .Overload< Table (Statement::*)(void) const >(_SC("GetTable"), &Statement::GetTable)
 | 
			
		||||
        .Overload< Table (Statement::*)(Int32) const >(_SC("GetTable"), &Statement::GetTable)
 | 
			
		||||
        .Overload< Table (Statement::*)(Int32, Int32) const >(_SC("GetTable"), &Statement::GetTable)
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
							
								
								
									
										868
									
								
								module/Library/SQLite/Statement.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										868
									
								
								module/Library/SQLite/Statement.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,868 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Library/SQLite/Handle.hpp"
 | 
			
		||||
#include "Library/SQLite/Parameter.hpp"
 | 
			
		||||
#include "Library/SQLite/Column.hpp"
 | 
			
		||||
#include "Library/Utils/Buffer.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Used to manage and interact a database statement.
 | 
			
		||||
*/
 | 
			
		||||
class Statement
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    StmtRef m_Handle; // Reference to the managed statement.
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the managed statement handle and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    void Validate(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    void Validate() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the managed statement handle and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    void ValidateCreated(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    void ValidateCreated() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the managed statement handle and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    const StmtRef & GetValid(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    const StmtRef & GetValid() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the managed statement handle and throw an error if invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    const StmtRef & GetCreated(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    const StmtRef & GetCreated() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the statement reference and column index, and throw an error if they're invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    void ValidateColumn(Int32 idx, CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    void ValidateColumn(Int32 idx) const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the statement reference and parameter index, and throw an error if they're invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    void ValidateParam(Int32 idx, CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    void ValidateParam(Int32 idx) const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Validate the statement reference and row, and throw an error if they're invalid.
 | 
			
		||||
    */
 | 
			
		||||
#if defined(_DEBUG) || defined(SQMOD_EXCEPTLOC)
 | 
			
		||||
    void ValidateRow(CCStr file, Int32 line) const;
 | 
			
		||||
#else
 | 
			
		||||
    void ValidateRow() const;
 | 
			
		||||
#endif // _DEBUG
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Default constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Statement()
 | 
			
		||||
        : m_Handle()
 | 
			
		||||
    {
 | 
			
		||||
        /* ... */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Construct a statement under the specified connection using the specified string.
 | 
			
		||||
    */
 | 
			
		||||
    Statement(const ConnRef & connection, StackStrF & query)
 | 
			
		||||
        : m_Handle(new StmtHnd(connection))
 | 
			
		||||
    {
 | 
			
		||||
        SQMOD_GET_VALID(*this)->Create(query.mPtr, query.mLen);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Construct a statement under the specified connection using the specified string.
 | 
			
		||||
    */
 | 
			
		||||
    Statement(const Connection & connection, StackStrF & query);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Direct handle constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Statement(const StmtRef & s)
 | 
			
		||||
        : m_Handle(s)
 | 
			
		||||
    {
 | 
			
		||||
        /* ... */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Statement(const Statement & o) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Move constructor.
 | 
			
		||||
    */
 | 
			
		||||
    Statement(Statement && o) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy assignment operator.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & operator = (const Statement & o) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Move assignment operator.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & operator = (Statement && o) = default;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Perform an equality comparison between two connections.
 | 
			
		||||
    */
 | 
			
		||||
    bool operator == (const Statement & o) const
 | 
			
		||||
    {
 | 
			
		||||
        return (m_Handle.Get() == o.m_Handle.Get());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Perform an inequality comparison between two connections.
 | 
			
		||||
    */
 | 
			
		||||
    bool operator != (const Statement & o) const
 | 
			
		||||
    {
 | 
			
		||||
        return (m_Handle.Get() != o.m_Handle.Get());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Implicit conversion to the raw connection handle.
 | 
			
		||||
    */
 | 
			
		||||
    operator sqlite3_stmt * ()
 | 
			
		||||
    {
 | 
			
		||||
        return m_Handle ? m_Handle->mPtr : nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Implicit conversion to the raw connection handle.
 | 
			
		||||
    */
 | 
			
		||||
    operator sqlite3_stmt * () const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Handle ? m_Handle->mPtr : nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Used by the script engine to convert an instance of this type to a string.
 | 
			
		||||
    */
 | 
			
		||||
    const String & ToString() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Handle ? m_Handle->mQuery : NullString();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the associated statement handle.
 | 
			
		||||
    */
 | 
			
		||||
    const StmtRef & GetHandle() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Handle;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * See whether the managed handle is valid.
 | 
			
		||||
    */
 | 
			
		||||
    bool IsValid() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Handle;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * See whether the managed statement is valid.
 | 
			
		||||
    */
 | 
			
		||||
    bool IsPrepared() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Handle && (m_Handle->mPtr != nullptr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Return the number of active references to this statement handle.
 | 
			
		||||
    */
 | 
			
		||||
    Uint32 GetReferences() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Handle.Count();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the associated database connection.
 | 
			
		||||
    */
 | 
			
		||||
    Object GetConnection() const;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Release the reference to the associated database statement.
 | 
			
		||||
    */
 | 
			
		||||
    void Release()
 | 
			
		||||
    {
 | 
			
		||||
        m_Handle.Reset();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the last received status code.
 | 
			
		||||
    */
 | 
			
		||||
    Int32 GetStatus() const
 | 
			
		||||
    {
 | 
			
		||||
        return SQMOD_GET_VALID(*this)->mStatus;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Return the numeric result code for the most recent failed API call (if any).
 | 
			
		||||
    */
 | 
			
		||||
    Int32 GetErrorCode() const
 | 
			
		||||
    {
 | 
			
		||||
        return SQMOD_GET_VALID(*this)->ErrNo();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Return the extended numeric result code for the most recent failed API call (if any).
 | 
			
		||||
    */
 | 
			
		||||
    Int32 GetExtendedErrorCode() const
 | 
			
		||||
    {
 | 
			
		||||
        return SQMOD_GET_VALID(*this)->ExErrNo();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the message of the last received error code.
 | 
			
		||||
    */
 | 
			
		||||
    CSStr GetErrStr() const
 | 
			
		||||
    {
 | 
			
		||||
        return SQMOD_GET_VALID(*this)->ErrStr();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Return the last error message associated with this database connection.
 | 
			
		||||
    */
 | 
			
		||||
    CSStr GetErrMsg() const
 | 
			
		||||
    {
 | 
			
		||||
        return SQMOD_GET_VALID(*this)->ErrMsg();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the amount of requested columns.
 | 
			
		||||
    */
 | 
			
		||||
    Int32 GetColumns() const
 | 
			
		||||
    {
 | 
			
		||||
        return SQMOD_GET_VALID(*this)->mColumns;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the amount of specified parameters.
 | 
			
		||||
    */
 | 
			
		||||
    Int32 GetParameters() const
 | 
			
		||||
    {
 | 
			
		||||
        return SQMOD_GET_VALID(*this)->mParameters;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the query string used to create this statement.
 | 
			
		||||
    */
 | 
			
		||||
    const String & GetQuery() const
 | 
			
		||||
    {
 | 
			
		||||
        return SQMOD_GET_VALID(*this)->mQuery;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * See if the last step retrieved a valid row.
 | 
			
		||||
    */
 | 
			
		||||
    bool GetGood() const
 | 
			
		||||
    {
 | 
			
		||||
        return SQMOD_GET_CREATED(*this)->mGood;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * See if there are any steps left.
 | 
			
		||||
    */
 | 
			
		||||
    bool GetDone() const
 | 
			
		||||
    {
 | 
			
		||||
        return SQMOD_GET_CREATED(*this)->mDone;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Check whether a specific parameter index is within range.
 | 
			
		||||
    */
 | 
			
		||||
    bool CheckParameter(Int32 idx) const
 | 
			
		||||
    {
 | 
			
		||||
        return SQMOD_GET_VALID(*this)->CheckParameter(idx);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the parameter index associated with the specified name.
 | 
			
		||||
    */
 | 
			
		||||
    Int32 GetParameterIndex(StackStrF & name) const
 | 
			
		||||
    {
 | 
			
		||||
        return sqlite3_bind_parameter_index(SQMOD_GET_VALID(*this)->mPtr, name.mPtr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the parameter name associated with the specified index.
 | 
			
		||||
    */
 | 
			
		||||
    CSStr GetParameterName(Int32 idx) const
 | 
			
		||||
    {
 | 
			
		||||
        // Validate the specified index
 | 
			
		||||
        if (!idx)
 | 
			
		||||
        {
 | 
			
		||||
            STHROWF("Invalid parameter index (%d)", idx);
 | 
			
		||||
        }
 | 
			
		||||
        // Attempt to locate the name at the specified index
 | 
			
		||||
        CSStr name = sqlite3_bind_parameter_name(SQMOD_GET_VALID(*this)->mPtr, idx);
 | 
			
		||||
        // Validate the obtained string
 | 
			
		||||
        if (!name)
 | 
			
		||||
        {
 | 
			
		||||
            STHROWF("No such parameter exists (%d)", idx);
 | 
			
		||||
        }
 | 
			
		||||
        // Return the obtained string
 | 
			
		||||
        return name;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Check whether a specific column index is within range.
 | 
			
		||||
    */
 | 
			
		||||
    bool CheckColumn(Int32 idx) const
 | 
			
		||||
    {
 | 
			
		||||
        return SQMOD_GET_VALID(*this)->CheckColumn(idx);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the amount of columns available in the current row.
 | 
			
		||||
    */
 | 
			
		||||
    Int32 GetDataCount() const
 | 
			
		||||
    {
 | 
			
		||||
        return sqlite3_data_count(SQMOD_GET_VALID(*this)->mPtr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Check whether the specified column is null.
 | 
			
		||||
    */
 | 
			
		||||
    bool IsColumnNull(Int32 idx) const
 | 
			
		||||
    {
 | 
			
		||||
        return (sqlite3_column_type(SQMOD_GET_VALID(*this)->mPtr, idx) == SQLITE_NULL);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the column index associated with the specified name.
 | 
			
		||||
    */
 | 
			
		||||
    Int32 GetColumnIndex(StackStrF & name) const
 | 
			
		||||
    {
 | 
			
		||||
        return SQMOD_GET_VALID(*this)->GetColumnIndex(name.mPtr, name.mLen);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the column name associated with the specified index.
 | 
			
		||||
    */
 | 
			
		||||
    CSStr GetColumnName(Int32 idx) const
 | 
			
		||||
    {
 | 
			
		||||
        return sqlite3_column_name(SQMOD_GET_VALID(*this)->mPtr, idx);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the column origin name if the library was compiled with such feature.
 | 
			
		||||
    */
 | 
			
		||||
    CSStr GetColumnOriginName(Int32 idx) const
 | 
			
		||||
    {
 | 
			
		||||
#ifdef SQLITE_ENABLE_COLUMN_METADATA
 | 
			
		||||
        return sqlite3_column_origin_name(SQMOD_GET_VALID(*this)->mPtr, idx);
 | 
			
		||||
#else
 | 
			
		||||
        // The compiler moans when extra warnings are enabled
 | 
			
		||||
        SQMOD_UNUSED_VAR(idx);
 | 
			
		||||
        // Stop the execution here!
 | 
			
		||||
        STHROWF("The module was compiled without this feature");
 | 
			
		||||
        // We have to return something
 | 
			
		||||
        return _SC("");
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the type identifier of the column associated with the specified index.
 | 
			
		||||
    */
 | 
			
		||||
    Int32 GetColumnType(Int32 idx) const
 | 
			
		||||
    {
 | 
			
		||||
        return sqlite3_column_type(SQMOD_GET_VALID(*this)->mPtr, idx);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the size in bytes of the column associated with the specified index.
 | 
			
		||||
    */
 | 
			
		||||
    Int32 GetColumnBytes(Int32 idx) const
 | 
			
		||||
    {
 | 
			
		||||
        return sqlite3_column_bytes(SQMOD_GET_VALID(*this)->mPtr, idx);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Reset the statement back to its initial position to be stepped again.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & Reset();
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Clear any values binded to this statement.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & 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();
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the parameter with the specified name or index.
 | 
			
		||||
    */
 | 
			
		||||
    Object GetParameter(const Object & param) const
 | 
			
		||||
    {
 | 
			
		||||
        return Object(new Parameter(m_Handle, param));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a dynamic value at the specified parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & SetValue(const Object & param, const Object & value)
 | 
			
		||||
    {
 | 
			
		||||
        Parameter(SQMOD_GET_CREATED(*this), param).SetValue(value);
 | 
			
		||||
        // Allow chaining of operations
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a boolean value at the specified parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & SetBool(const Object & param, bool value)
 | 
			
		||||
    {
 | 
			
		||||
        Parameter(SQMOD_GET_CREATED(*this), param).SetBool(value);
 | 
			
		||||
        // Allow chaining of operations
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a character value at the specified parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & SetChar(const Object & param, SQInteger value)
 | 
			
		||||
    {
 | 
			
		||||
        Parameter(SQMOD_GET_CREATED(*this), param).SetChar(value);
 | 
			
		||||
        // Allow chaining of operations
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a native integer value at the specified parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & SetInteger(const Object & param, SQInteger value)
 | 
			
		||||
    {
 | 
			
		||||
        Parameter(SQMOD_GET_CREATED(*this), param).SetInteger(value);
 | 
			
		||||
        // Allow chaining of operations
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a signed 8 bit integer value at the specified parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & SetInt8(const Object & param, SQInteger value)
 | 
			
		||||
    {
 | 
			
		||||
        Parameter(SQMOD_GET_CREATED(*this), param).SetInt8(value);
 | 
			
		||||
        // Allow chaining of operations
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind an unsigned 8 bit integer value at the specified parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & SetUint8(const Object & param, SQInteger value)
 | 
			
		||||
    {
 | 
			
		||||
        Parameter(SQMOD_GET_CREATED(*this), param).SetUint8(value);
 | 
			
		||||
        // Allow chaining of operations
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a signed 16 bit integer value at the specified parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & SetInt16(const Object & param, SQInteger value)
 | 
			
		||||
    {
 | 
			
		||||
        Parameter(SQMOD_GET_CREATED(*this), param).SetInt16(value);
 | 
			
		||||
        // Allow chaining of operations
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind an unsigned 16 bit integer value at the specified parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & SetUint16(const Object & param, SQInteger value)
 | 
			
		||||
    {
 | 
			
		||||
        Parameter(SQMOD_GET_CREATED(*this), param).SetUint16(value);
 | 
			
		||||
        // Allow chaining of operations
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a signed 32 bit integer value at the specified parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & SetInt32(const Object & param, SQInteger value)
 | 
			
		||||
    {
 | 
			
		||||
        Parameter(SQMOD_GET_CREATED(*this), param).SetInt32(value);
 | 
			
		||||
        // Allow chaining of operations
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind an unsigned 32 bit integer value at the specified parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & SetUint32(const Object & param, SQInteger value)
 | 
			
		||||
    {
 | 
			
		||||
        Parameter(SQMOD_GET_CREATED(*this), param).SetUint32(value);
 | 
			
		||||
        // Allow chaining of operations
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a signed 64 bit integer value at the specified parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & SetInt64(const Object & param, const Object & value)
 | 
			
		||||
    {
 | 
			
		||||
        Parameter(SQMOD_GET_CREATED(*this), param).SetInt64(value);
 | 
			
		||||
        // Allow chaining of operations
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind an unsigned 64 bit integer value at the specified parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & SetUint64(const Object & param, const Object & value)
 | 
			
		||||
    {
 | 
			
		||||
        Parameter(SQMOD_GET_CREATED(*this), param).SetUint64(value);
 | 
			
		||||
        // Allow chaining of operations
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a native floating point value at the specified parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & SetFloat(const Object & param, SQFloat value)
 | 
			
		||||
    {
 | 
			
		||||
        Parameter(SQMOD_GET_CREATED(*this), param).SetFloat(value);
 | 
			
		||||
        // Allow chaining of operations
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a 32 bit floating point value at the specified parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & SetFloat32(const Object & param, SQFloat value)
 | 
			
		||||
    {
 | 
			
		||||
        Parameter(SQMOD_GET_CREATED(*this), param).SetFloat32(value);
 | 
			
		||||
        // Allow chaining of operations
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a 64 bit floating point value at the specified parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & SetFloat64(const Object & param, SQFloat value)
 | 
			
		||||
    {
 | 
			
		||||
        Parameter(SQMOD_GET_CREATED(*this), param).SetFloat64(value);
 | 
			
		||||
        // Allow chaining of operations
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a string value at the specified parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & SetString(const Object & param, StackStrF & value)
 | 
			
		||||
    {
 | 
			
		||||
        Parameter(SQMOD_GET_CREATED(*this), param).SetString(value);
 | 
			
		||||
        // Allow chaining of operations
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a zeroed blob value at the specified parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & SetZeroBlob(const Object & param, SQInteger size)
 | 
			
		||||
    {
 | 
			
		||||
        Parameter(SQMOD_GET_CREATED(*this), param).SetZeroBlob(size);
 | 
			
		||||
        // Allow chaining of operations
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a blob value at the specified parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & SetBlob(const Object & param, const Object & value)
 | 
			
		||||
    {
 | 
			
		||||
        Parameter(SQMOD_GET_CREATED(*this), param).SetBlob(value);
 | 
			
		||||
        // Allow chaining of operations
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a buffer value at the specified parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & SetData(const Object & param, const Object & value)
 | 
			
		||||
    {
 | 
			
		||||
        Parameter(SQMOD_GET_CREATED(*this), param).SetData(value.Cast< const SqBuffer & >());
 | 
			
		||||
        // Allow chaining of operations
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a date value at the specified parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & SetDate(const Object & param, const Object & value)
 | 
			
		||||
    {
 | 
			
		||||
        Parameter(SQMOD_GET_CREATED(*this), param).SetDate(value.Cast< const Date & >());
 | 
			
		||||
        // Allow chaining of operations
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a date value at the specified parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & SetDateEx(const Object & param, SQInteger year, SQInteger month, SQInteger day)
 | 
			
		||||
    {
 | 
			
		||||
        Parameter(SQMOD_GET_CREATED(*this), param).SetDateEx(year, month, day);
 | 
			
		||||
        // Allow chaining of operations
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a time value at the specified parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & SetTime(const Object & param, const Object & value)
 | 
			
		||||
    {
 | 
			
		||||
        Parameter(SQMOD_GET_CREATED(*this), param).SetTime(value.Cast< const Time & >());
 | 
			
		||||
        // Allow chaining of operations
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a time value at the specified parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & SetTimeEx(const Object & param, SQInteger hour, SQInteger minute, SQInteger second)
 | 
			
		||||
    {
 | 
			
		||||
        Parameter(SQMOD_GET_CREATED(*this), param).SetTimeEx(hour, minute, second);
 | 
			
		||||
        // Allow chaining of operations
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a date-time value at the specified parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & SetDatetime(const Object & param, const Object & value)
 | 
			
		||||
    {
 | 
			
		||||
        Parameter(SQMOD_GET_CREATED(*this), param).SetDatetime(value.Cast< const Datetime & >());
 | 
			
		||||
        // Allow chaining of operations
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a date-time value at the specified parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & SetDatetimeEx(const Object & param, SQInteger year, SQInteger month, SQInteger day,
 | 
			
		||||
                                    SQInteger hour, SQInteger minute, SQInteger second)
 | 
			
		||||
    {
 | 
			
		||||
        Parameter(SQMOD_GET_CREATED(*this), param).SetDatetimeEx(year, month, day, hour, minute, second);
 | 
			
		||||
        // Allow chaining of operations
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind the current timestamp at the specified parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & SetNow(const Object & param)
 | 
			
		||||
    {
 | 
			
		||||
        Parameter(SQMOD_GET_CREATED(*this), param).SetNow();
 | 
			
		||||
        // Allow chaining of operations
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind a null value at the specified parameter index.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & SetNull(const Object & param)
 | 
			
		||||
    {
 | 
			
		||||
        Parameter(SQMOD_GET_CREATED(*this), param).SetNull();
 | 
			
		||||
        // Allow chaining of operations
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind the values from an array starting at the specified index.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & SetArray(Int32 idx, const Array & arr);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to bind the values from an associative container.
 | 
			
		||||
    */
 | 
			
		||||
    Statement & SetTable(const Table & tbl);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the column with the specified name or index.
 | 
			
		||||
    */
 | 
			
		||||
    Object GetColumn(const Object & column) const
 | 
			
		||||
    {
 | 
			
		||||
        return Object(new Column(m_Handle, column));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value inside the referenced column as a dynamic type.
 | 
			
		||||
    */
 | 
			
		||||
    Object GetValue(const Object & column) const
 | 
			
		||||
    {
 | 
			
		||||
        return Column(SQMOD_GET_CREATED(*this), column).GetValue();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value inside the referenced column as a numeric type.
 | 
			
		||||
    */
 | 
			
		||||
    Object GetNumber(const Object & column) const
 | 
			
		||||
    {
 | 
			
		||||
        return Column(SQMOD_GET_CREATED(*this), column).GetNumber();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value inside the referenced column as a native script integer.
 | 
			
		||||
    */
 | 
			
		||||
    SQInteger GetInteger(const Object & column) const
 | 
			
		||||
    {
 | 
			
		||||
        return Column(SQMOD_GET_CREATED(*this), column).GetInteger();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value inside the referenced column as a native script floating point.
 | 
			
		||||
    */
 | 
			
		||||
    SQFloat GetFloat(const Object & column) const
 | 
			
		||||
    {
 | 
			
		||||
        return Column(SQMOD_GET_CREATED(*this), column).GetFloat();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value inside the referenced column as a long integer.
 | 
			
		||||
    */
 | 
			
		||||
    Object GetLong(const Object & column) const
 | 
			
		||||
    {
 | 
			
		||||
        return Column(SQMOD_GET_CREATED(*this), column).GetLong();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value inside the referenced column as a string.
 | 
			
		||||
    */
 | 
			
		||||
    Object GetString(const Object & column) const
 | 
			
		||||
    {
 | 
			
		||||
        return Column(SQMOD_GET_CREATED(*this), column).GetString();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value inside the referenced column as a boolean.
 | 
			
		||||
    */
 | 
			
		||||
    bool GetBoolean(const Object & column) const
 | 
			
		||||
    {
 | 
			
		||||
        return Column(SQMOD_GET_CREATED(*this), column).GetBoolean();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value inside the referenced column as a character.
 | 
			
		||||
    */
 | 
			
		||||
    SQChar GetChar(const Object & column) const
 | 
			
		||||
    {
 | 
			
		||||
        return Column(SQMOD_GET_CREATED(*this), column).GetChar();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value inside the referenced column as a memory buffer.
 | 
			
		||||
    */
 | 
			
		||||
    Object GetBuffer(const Object & column) const
 | 
			
		||||
    {
 | 
			
		||||
        return Column(SQMOD_GET_CREATED(*this), column).GetBuffer();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the value inside the referenced column as a memory blob.
 | 
			
		||||
    */
 | 
			
		||||
    Object GetBlob(const Object & column) const
 | 
			
		||||
    {
 | 
			
		||||
        return Column(SQMOD_GET_CREATED(*this), column).GetBlob();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the row as an array container.
 | 
			
		||||
    */
 | 
			
		||||
    Array GetArray() const
 | 
			
		||||
    {
 | 
			
		||||
        return GetArray(0, SQMOD_GET_CREATED(*this)->mColumns);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the row as an array container.
 | 
			
		||||
    */
 | 
			
		||||
    Array GetArray(Int32 min) const
 | 
			
		||||
    {
 | 
			
		||||
        return GetArray(min, SQMOD_GET_CREATED(*this)->mColumns);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the row as an array container.
 | 
			
		||||
    */
 | 
			
		||||
    Array GetArray(Int32 min, Int32 max) const;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the row as an associative container.
 | 
			
		||||
    */
 | 
			
		||||
    Table GetTable() const
 | 
			
		||||
    {
 | 
			
		||||
        // Is there something to return?
 | 
			
		||||
        if (SQMOD_GET_CREATED(*this)->mColumns > 0)
 | 
			
		||||
        {
 | 
			
		||||
            return GetTable(0, m_Handle->mColumns - 1);
 | 
			
		||||
        }
 | 
			
		||||
        // Fallback to empty table
 | 
			
		||||
        return NullTable();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the row as an associative container.
 | 
			
		||||
    */
 | 
			
		||||
    Table GetTable(Int32 min) const
 | 
			
		||||
    {
 | 
			
		||||
        // Is there something to return?
 | 
			
		||||
        if (SQMOD_GET_CREATED(*this)->mColumns > 0)
 | 
			
		||||
        {
 | 
			
		||||
            return GetTable(min, m_Handle->mColumns - 1);
 | 
			
		||||
        }
 | 
			
		||||
        // Fallback to empty table
 | 
			
		||||
        return NullTable();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the row as an associative container.
 | 
			
		||||
    */
 | 
			
		||||
    Table GetTable(Int32 min, Int32 max) const;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
							
								
								
									
										102
									
								
								module/Library/SQLite/Transaction.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								module/Library/SQLite/Transaction.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,102 @@
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Library/SQLite/Transaction.hpp"
 | 
			
		||||
 | 
			
		||||
#include <utility>
 | 
			
		||||
#include "Library/SQLite/Connection.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
SQMODE_DECL_TYPENAME(Typename, _SC("SqLiteTransaction"))
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Transaction::Transaction(const Connection & db)
 | 
			
		||||
    : Transaction(db.GetHandle())
 | 
			
		||||
{
 | 
			
		||||
    /* ... */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Transaction::Transaction(ConnRef  db)
 | 
			
		||||
    : m_Handle(std::move(db)), m_Committed(false)
 | 
			
		||||
{
 | 
			
		||||
    // Was the specified database connection valid?
 | 
			
		||||
    if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Invalid connection handle");
 | 
			
		||||
    }
 | 
			
		||||
    // Attempt to begin transaction
 | 
			
		||||
    m_Handle->mStatus = sqlite3_exec(m_Handle->mPtr, "BEGIN", nullptr, nullptr, nullptr);
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Unable to begin transaction [%s]", m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
Transaction::~Transaction()
 | 
			
		||||
{
 | 
			
		||||
    // Was this transaction successfully committed?
 | 
			
		||||
    if (m_Committed)
 | 
			
		||||
    {
 | 
			
		||||
        return; // We're done here!
 | 
			
		||||
    }
 | 
			
		||||
    // Attempt to roll back changes because this failed to commit
 | 
			
		||||
    m_Handle->mStatus = sqlite3_exec(m_Handle->mPtr, "ROLLBACK", nullptr, nullptr, nullptr);
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        // We cannot throw exceptions in destructor
 | 
			
		||||
        LogErr("Unable to rollback transaction [%s]", m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
bool Transaction::Commit()
 | 
			
		||||
{
 | 
			
		||||
    // We shouldn't even be here if there wasn't a valid connection but let's be sure
 | 
			
		||||
    if (!m_Handle)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Invalid database connection");
 | 
			
		||||
    }
 | 
			
		||||
    // Was this transaction already committed?
 | 
			
		||||
    else if (m_Committed)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Transaction was already committed");
 | 
			
		||||
    }
 | 
			
		||||
    // Attempt to commit the change during this transaction
 | 
			
		||||
    m_Handle->mStatus = sqlite3_exec(m_Handle->mPtr, "COMMIT", nullptr, nullptr, nullptr);
 | 
			
		||||
    // Validate the result
 | 
			
		||||
    if (m_Handle->mStatus != SQLITE_OK)
 | 
			
		||||
    {
 | 
			
		||||
        STHROWF("Unable to commit transaction [%s]", m_Handle->ErrMsg());
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
        m_Committed = true; // Everything was committed successfully
 | 
			
		||||
    }
 | 
			
		||||
    // Return the result
 | 
			
		||||
    return m_Committed;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ================================================================================================
 | 
			
		||||
void Register_Transaction(Table & sqlns)
 | 
			
		||||
{
 | 
			
		||||
    sqlns.Bind(_SC("Transaction"),
 | 
			
		||||
        Class< Transaction, NoCopy< Transaction > >(sqlns.GetVM(), Typename::Str)
 | 
			
		||||
        // Constructors
 | 
			
		||||
        .Ctor< const Connection & >()
 | 
			
		||||
        // Meta-methods
 | 
			
		||||
        .SquirrelFunc(_SC("_typename"), &Typename::Fn)
 | 
			
		||||
        .Func(_SC("_tostring"), &Transaction::ToString)
 | 
			
		||||
        // Properties
 | 
			
		||||
        .Prop(_SC("IsValid"), &Transaction::IsValid)
 | 
			
		||||
        .Prop(_SC("Committed"), &Transaction::Commited)
 | 
			
		||||
        // Member Methods
 | 
			
		||||
        .Func(_SC("Commit"), &Transaction::Commit)
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
							
								
								
									
										95
									
								
								module/Library/SQLite/Transaction.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								module/Library/SQLite/Transaction.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,95 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
#include "Library/SQLite/Handle.hpp"
 | 
			
		||||
 | 
			
		||||
// ------------------------------------------------------------------------------------------------
 | 
			
		||||
namespace SqMod {
 | 
			
		||||
 | 
			
		||||
/* ------------------------------------------------------------------------------------------------
 | 
			
		||||
 * Implements the RAII pattern for database transactions.
 | 
			
		||||
*/
 | 
			
		||||
class Transaction
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Construct by taking the handle from a connection.
 | 
			
		||||
    */
 | 
			
		||||
    Transaction(const Connection & db);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Construct using the direct connection handle.
 | 
			
		||||
    */
 | 
			
		||||
    Transaction(ConnRef  db);
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy constructor. (disabled)
 | 
			
		||||
    */
 | 
			
		||||
    Transaction(const Transaction & o) = delete;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Move constructor. (disabled)
 | 
			
		||||
    */
 | 
			
		||||
    Transaction(Transaction && o) = delete;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Destructor.
 | 
			
		||||
    */
 | 
			
		||||
    ~Transaction();
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Copy assignment operator. (disabled)
 | 
			
		||||
    */
 | 
			
		||||
    Transaction & operator = (const Transaction & o) = delete;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Move assignment operator. (disabled)
 | 
			
		||||
    */
 | 
			
		||||
    Transaction & operator = (Transaction && o) = delete;
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Used by the script engine to convert an instance of this type to a string.
 | 
			
		||||
    */
 | 
			
		||||
    const String & ToString() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Handle ? m_Handle->mName : NullString();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Retrieve the associated statement handle.
 | 
			
		||||
    */
 | 
			
		||||
    const ConnRef & GetHandle() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Handle;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * See whether the managed handle is valid.
 | 
			
		||||
    */
 | 
			
		||||
    bool IsValid() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Handle;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * Attempt to commit changes to the database.
 | 
			
		||||
    */
 | 
			
		||||
    bool Commit();
 | 
			
		||||
 | 
			
		||||
    /* --------------------------------------------------------------------------------------------
 | 
			
		||||
     * See whether the change during this transaction were successfully committed.
 | 
			
		||||
    */
 | 
			
		||||
    bool Commited() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_Committed;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    // --------------------------------------------------------------------------------------------
 | 
			
		||||
    ConnRef     m_Handle; // The database connection handle where the transaction began.
 | 
			
		||||
    bool        m_Committed; // Whether changes were successfully committed to the database.
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // Namespace:: SqMod
 | 
			
		||||
@@ -39,6 +39,7 @@ extern void Register_Chrono(HSQUIRRELVM vm);
 | 
			
		||||
extern void Register_Crypt(HSQUIRRELVM vm);
 | 
			
		||||
extern void Register_IO(HSQUIRRELVM vm);
 | 
			
		||||
extern void Register_Numeric(HSQUIRRELVM vm);
 | 
			
		||||
extern void Register_SQLite(HSQUIRRELVM vm);
 | 
			
		||||
extern void Register_String(HSQUIRRELVM vm);
 | 
			
		||||
extern void Register_System(HSQUIRRELVM vm);
 | 
			
		||||
extern void Register_Utils(HSQUIRRELVM vm);
 | 
			
		||||
@@ -84,6 +85,7 @@ bool RegisterAPI(HSQUIRRELVM vm)
 | 
			
		||||
    Register_Crypt(vm);
 | 
			
		||||
    Register_IO(vm);
 | 
			
		||||
    Register_Numeric(vm);
 | 
			
		||||
    Register_SQLite(vm);
 | 
			
		||||
    Register_String(vm);
 | 
			
		||||
    Register_System(vm);
 | 
			
		||||
    Register_Utils(vm);
 | 
			
		||||
 
 | 
			
		||||
@@ -34,7 +34,7 @@
 | 
			
		||||
    #include <squirrelex.h>
 | 
			
		||||
#endif // SQMOD_PLUGIN_API
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <cstring>
 | 
			
		||||
 | 
			
		||||
#include "sqratAllocator.h"
 | 
			
		||||
#include "sqratTypes.h"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user