StormByte-Database 2.0.0
C++26 database module of the StormByte suite
 
Loading...
Searching...
No Matches
StormByte-Database

Platform C++26 CMake License: LGPL v3 or commercial CI Sponsor

This repository is StormByte Database: the C++26 SQL layer of the StormByte suite.

It depends on StormByte-Logger 2.0.0 or newer, which vendors StormByte-String and StormByte Base. Public headers live under StormByte/database/.

One API covers SQLite, PostgreSQL and MariaDB. You do not construct those backends as generic objects. They are base classes: derive your schema, call the backend constructor, prepare statements and hook connect/disconnect there.

The suite is split on purpose. Base, Buffer, Config, Crypto, Logger, Multimedia, Network, String and System are other repositories. This repository does not implement them.

What this module does

  • One connection type — StormByte::Database::Database with Connect / Disconnect, Query / SilentQuery, named prepared statements and RAII transactions.
  • Inheritance first — SQLite3, MariaDB and Postgres constructors are protected. Your application database is a subclass.
  • Values — type-erased Value (NULL, integers, double, text, blob, bool) with safe numeric Get<T>().
  • Rows — ordered columns, lookup by name (ColumnNotFound / OutOfBounds).
  • Prepared statements — bind by position (0-based), nullptr is SQL NULL, ExpectedRows on execute.
  • Transactions — BeginTransaction(IsolationLevel) returns Expected<Transaction, TransactionError>; failed starts are reported as a value, and an uncommitted transaction rolls back on destruction.
  • Telemetry — GetTelemetry() returns a thread-safe, cumulative StormByte::Shared handle with operation counts, outcomes, rows and latency min/mean/max. SQLite, PostgreSQL and MariaDB provide derived telemetry with backend-specific error counters; retained handles remain readable after disconnect/destruction.
  • TLS — SslMode for MariaDB and PostgreSQL. SQLite ignores it.
  • Concurrent access — operations on one connection are serialized; separate connections can run concurrently. A transaction reserves its connection until commit or rollback and must remain on the thread that created it. Custom backend implementations must lock the shared connection mutex in public operations.

The rest of the suite

Module Role API
Base Exceptions, Expected, serialization, strings, UUID, concepts /StormByte
Buffer FIFO, SharedFIFO, Ring, Producer/Consumer and multi-stage pipelines /StormByte-Buffer
Config Human-readable text and versioned binary documents (groups, lists, raw bytes) /StormByte-Config
Crypto Hash, compress, encrypt, sign and key agreement — Crypto++ never leaves the private tree /StormByte-Crypto
Database This repository /StormByte-Database
Logger Stream logger with levels, headers, human-readable sizes and redaction (ThreadedLog) /StormByte-Logger
Multimedia Decode, encode and containers without raw FFmpeg types; codecs enabled only if present /StormByte-Multimedia
Network Framed packets, Client/Server, IPv4/IPv6 TCP and Buffer pipelines (compress/encrypt) /StormByte-Network
String Owned UTF-8 / wide text that can cross a DLL boundary /StormByte-String
System Processes, pipes and environment variables across Linux, Windows and macOS /StormByte-System

Table of Contents

Installation

Needs a C++26 compiler, CMake 3.28 or newer, and StormByte-Logger 2.0.0 or newer. Logger supplies the bundled StormByte-String and StormByte Base dependencies used by Database. Enable the backends you want (WITH_SQLITE, WITH_POSTGRES, WITH_MARIADB: OFF, SYSTEM or BUNDLED); SYSTEM discovers installed connectors and BUNDLED builds them.

git clone --recurse-submodules https://github.com/StormBytePP/StormByte-Database.git
cd StormByte-Database
cmake -S . -B build
cmake --build build

Shared vs static follows CMake BUILD_SHARED_LIBS (default ON). -DBUILD_SHARED_LIBS=OFF builds a static archive. In static mode BuildMaster flattens private vendor dependencies into the consumer link closure; users do not need to repack vendor archives. The shared library keeps Database replaceable as its own DLL/shared object.

Documentation

Usage

Headers are #include <StormByte/database/….hxx>. Namespace root is StormByte::Database. Moving a connected backend transfers ownership of its connection; the moved-from backend is disconnected.

Derive your database

#include <utility>
public:
: SQLite3(std::filesystem::path{"app.db"}, log) {}
protected:
void DoPostConnect() noexcept override {
PrepareSTMT("user_by_id", "SELECT id, name FROM users WHERE id = ?");
}
};
int main() {
AppDb db(nullptr);
if (!db.Connect())
return 1;
auto rows = db.Query("SELECT 1 AS n");
if (!rows)
return 1;
}
virtual void DoPostConnect() noexcept
Post-connect hook.
Definition database.hxx:262
void PrepareSTMT(std::string_view name, std::string_view query) noexcept
Register a prepared statement under name.
SQLite3 backend.
Definition sqlite3.hxx:76
void EnableForeignKeys()
Enable foreign keys (off by default in SQLite).
STL namespace.

MariaDB / Postgres follow the same pattern: subclass, pass host / user / password / database (and port on MariaDB), optionally SetSslMode before Connect(). PostgreSQL connection parameters are passed separately, so credentials may contain quotes and backslashes.

Values and rows

using namespace StormByte::Database;
Value n(42);
Value empty; // SQL NULL
auto i = n.Get<int>();
if (auto row = /* from Query */) {
const Value& name = (*row)[0]["name"];
}
Type-erased SQL value (NULL, integers, double, text, blob, bool).
Definition value.hxx:68
std::decay_t< T > Get() const
Stored value as T, with safe numeric conversions.
Definition value.hxx:215
Database module of the StormByte suite.

Malformed or out-of-range numeric values returned by a backend are reported through ExpectedRows as query errors.

Queries and statements

auto result = db.ExecuteSTMT("user_by_id", 7);
if (!result)
return 1;
for (const auto& row : *result) {
auto id = row["id"].Get<int>();
}

nullptr binds SQL NULL. Missing statement names raise UnknownSTMT through ExpectedRows.

Transactions

#include <utility>
{
auto tx_result = db.BeginTransaction(IsolationLevel::Serializable);
if (!tx_result)
return 1;
auto tx = std::move(*tx_result);
db.SilentQuery("INSERT INTO users(name) VALUES ('ada')");
tx.Commit();
} // Rollback if Commit was not called

Telemetry

#include <iostream>
#include <string>
auto telemetry = db.GetTelemetry();
const auto query_metrics = telemetry->Metrics(StormByte::Database::Operation::Query);
std::cout << "queries=" << query_metrics.Attempts
<< " failures=" << query_metrics.Failures
<< " mean_ns=" << query_metrics.MeanNanoseconds() << '\n';
if (const auto* sqlite = dynamic_cast<const StormByte::Database::SQLite::Telemetry*>(telemetry.get()))
std::cout << "sqlite_busy=" << sqlite->BusyErrors()
<< " constraints=" << sqlite->ConstraintErrors() << '\n';
std::string snapshot = static_cast<std::string>(*telemetry);
SQLite-specific counters layered on common database telemetry.
Definition telemetry.hxx:17
@ Query
Queries that return rows.

Telemetry records operation attempts, successes/failures, total/minimum/mean/maximum latency, rows returned, and categorized backend events. It does not retain SQL text or bind values. Its getters are safe to call while operations run; snapshots may reflect updates that complete during the read. The Shared handle owns the same cumulative telemetry object and remains valid after the database is disconnected or destroyed.

Contributing

Support

Questions and bugs: GitHub issues on this repository. Sponsorship: github.com/sponsors/StormBytePP.

Issues only on this repository. Fork and open a pull request against master.

License

Dual license: GNU Lesser General Public License v3.0 or later, or a commercial license from the copyright holder. See [LICENSE](LICENSE), COPYING.LGPLv3 and https://www.gnu.org/licenses/lgpl-3.0.html. Third-party trees under thirdparty/ keep their own licenses.