mirror of
https://github.com/brazilofmux/tinymux
synced 2026-08-13 00:23:11 -04:00
tonumber can return int or float; claiming TY_INT always used CALL_INT and post-entry declined on float results. Drop it from the int-return claim so CALL_VAL preserves the typed stack value. EXEC pins "3.5"/"3.0"/"17". Standalone tests/db never saw LBUF_SIZE (no alloc.h). Define it in the Makefile to match alloc.h, and include <cstring> in sqlite_backend for the same TINYMUX_TYPES_DEFINED compile path.
162 lines
4 KiB
C++
162 lines
4 KiB
C++
/*! \file sqlite_backend.cpp
|
|
* \brief SQLite implementation of IStorageBackend.
|
|
*
|
|
*/
|
|
|
|
#if !defined(TINYMUX_TYPES_DEFINED)
|
|
#include "copyright.h"
|
|
#include "autoconf.h"
|
|
#include "config.h"
|
|
#include "externs.h"
|
|
#endif
|
|
|
|
#include "sqlite_backend.h"
|
|
#include <cstring>
|
|
|
|
CSQLiteBackend::CSQLiteBackend()
|
|
{
|
|
}
|
|
|
|
CSQLiteBackend::~CSQLiteBackend()
|
|
{
|
|
Close();
|
|
}
|
|
|
|
bool CSQLiteBackend::Open(const char *path)
|
|
{
|
|
return m_db.Open(path);
|
|
}
|
|
|
|
void CSQLiteBackend::Close()
|
|
{
|
|
m_db.Close();
|
|
}
|
|
|
|
bool CSQLiteBackend::IsOpen() const
|
|
{
|
|
return m_db.IsOpen();
|
|
}
|
|
|
|
bool CSQLiteBackend::Get(unsigned int object, unsigned int attrnum,
|
|
UTF8 *buf, size_t buflen, size_t *pLen,
|
|
int *owner, int *flags)
|
|
{
|
|
dbref db_owner;
|
|
int db_flags;
|
|
bool rc = m_db.GetAttribute(static_cast<dbref>(object), static_cast<int>(attrnum),
|
|
buf, buflen, pLen, &db_owner, &db_flags);
|
|
if (rc)
|
|
{
|
|
if (owner) *owner = static_cast<int>(db_owner);
|
|
if (flags) *flags = db_flags;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
bool CSQLiteBackend::Put(unsigned int object, unsigned int attrnum,
|
|
const UTF8 *value, size_t len,
|
|
int owner, int flags)
|
|
{
|
|
return m_db.PutAttribute(static_cast<dbref>(object), static_cast<int>(attrnum),
|
|
value, len, static_cast<dbref>(owner), flags);
|
|
}
|
|
|
|
bool CSQLiteBackend::Del(unsigned int object, unsigned int attrnum)
|
|
{
|
|
return m_db.DelAttribute(static_cast<dbref>(object), static_cast<int>(attrnum));
|
|
}
|
|
|
|
bool CSQLiteBackend::DelAll(unsigned int object)
|
|
{
|
|
return m_db.DelAllAttributes(static_cast<dbref>(object));
|
|
}
|
|
|
|
bool CSQLiteBackend::GetAll(unsigned int object, AttrCallback cb)
|
|
{
|
|
return m_db.GetAllAttributes(static_cast<dbref>(object),
|
|
[&cb](int attrnum, const UTF8 *value, size_t len, dbref owner, int flags)
|
|
{
|
|
cb(static_cast<unsigned int>(attrnum), value, len,
|
|
static_cast<int>(owner), flags);
|
|
});
|
|
}
|
|
|
|
bool CSQLiteBackend::GetBuiltin(unsigned int object, AttrCallback cb)
|
|
{
|
|
return m_db.GetBuiltinAttributes(static_cast<dbref>(object),
|
|
[&cb](int attrnum, const UTF8 *value, size_t len, dbref owner, int flags)
|
|
{
|
|
cb(static_cast<unsigned int>(attrnum), value, len,
|
|
static_cast<int>(owner), flags);
|
|
});
|
|
}
|
|
|
|
int CSQLiteBackend::Count(unsigned int object)
|
|
{
|
|
return m_db.CountAttributes(static_cast<dbref>(object));
|
|
}
|
|
|
|
uint32_t CSQLiteBackend::GetModCount(unsigned int object, unsigned int attrnum)
|
|
{
|
|
return m_db.GetAttrModCount(static_cast<dbref>(object),
|
|
static_cast<int>(attrnum));
|
|
}
|
|
|
|
bool CSQLiteBackend::GetAllModCounts(unsigned int object, ModCountCallback cb)
|
|
{
|
|
m_db.GetAllAttrModCounts(static_cast<dbref>(object),
|
|
[&cb](int attrnum, uint32_t mc)
|
|
{
|
|
cb(static_cast<unsigned int>(attrnum), mc);
|
|
});
|
|
return true;
|
|
}
|
|
|
|
void CSQLiteBackend::Sync()
|
|
{
|
|
m_db.Checkpoint();
|
|
}
|
|
|
|
void CSQLiteBackend::Tick()
|
|
{
|
|
// Write-through means SQLite is always up to date.
|
|
// Periodic optimize is light maintenance.
|
|
//
|
|
m_db.Optimize();
|
|
}
|
|
|
|
bool derive_sqlite_path(char *buf, size_t buflen, const UTF8 *indb)
|
|
{
|
|
if ( nullptr == buf
|
|
|| 0 == buflen
|
|
|| nullptr == indb)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
static const char suffix[] = ".sqlite";
|
|
const size_t nSuffix = sizeof(suffix) - 1;
|
|
|
|
const char *pIn = reinterpret_cast<const char *>(indb);
|
|
size_t nIn = strlen(pIn);
|
|
|
|
// A trailing ".db" is replaced rather than appended to, so the base is
|
|
// shorter than the input in that case. Note this still grows the path:
|
|
// three characters out, seven in.
|
|
//
|
|
size_t nBase = nIn;
|
|
if ( 3 < nIn
|
|
&& 0 == strcmp(pIn + nIn - 3, ".db"))
|
|
{
|
|
nBase = nIn - 3;
|
|
}
|
|
|
|
if (buflen < nBase + nSuffix + 1)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
memcpy(buf, pIn, nBase);
|
|
memcpy(buf + nBase, suffix, nSuffix + 1);
|
|
return true;
|
|
}
|