Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,7 @@
path = modules/cache
url = https://github.com/vixcpp/cache.git
branch = dev
[submodule "modules/db"]
path = modules/db
url = git@github.com:vixcpp/db.git
branch = dev
27 changes: 27 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
---

## [Unreleased]
# Vix.cpp v1.21.0

This release stabilizes the new DB core module, improves CLI runtime output, and fixes several build/link issues across modules.

## Highlights
- DB/ORM separation is now fully aligned: `vix::db` is the low-level core layer, `vix::orm` remains optional sugar on top.
- CLI runtime output and error UX were refined to be clearer and less noisy.
- Improved reliability for MySQL detection/linking in diverse environments.

## CLI (modules/cli)
- Fix: prevent duplicate runtime logs in some failure paths.
- Improve: runtime error detectors and diagnostics formatting.
- Improve: UX cleanup for run/dev flows (clearer output, less noise).

## DB Core (modules/db)
- Fix: CMake/source/linkage issues across DB drivers.
- Fix: MySQL Connector/C++ discovery via fallback alias target (more robust CI/local setups).
- Improve: driver linkage consistency and feature flag reporting.

## Umbrella / Modules
- Introduced `vix::db` as a core module and decoupled ORM tooling/drivers accordingly.
- Synced submodules after DB/ORM compatibility fixes.

## Upgrade notes
- If you enable `ORM`, it automatically implies `DB`.
- If MySQL is enabled, ensure Connector/C++ is available (the fallback alias helps when CMake configs are missing).

## v1.20.1 — Improved CLI Error UX & Build Feedback

### ✨ CLI — Error reporting & diagnostics
Expand Down
97 changes: 85 additions & 12 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,41 @@ cmake_minimum_required(VERSION 3.20)
# cmake --build build -j
# ====================================================================

project(vix VERSION 1.17.1 LANGUAGES CXX)
cmake_minimum_required(VERSION 3.20)

# Resolve umbrella version from git (preferred)
set(_VIX_VERSION_FALLBACK "0.0.0")

find_package(Git QUIET)
set(_VIX_GIT_DESCRIBE "")
if(Git_FOUND)
execute_process(
COMMAND "${GIT_EXECUTABLE}" describe --tags --always --dirty
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
OUTPUT_VARIABLE _VIX_GIT_DESCRIBE
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
endif()

# Compute PROJECT_VERSION (must be numeric for CMake packaging)
# If describe returns: v1.20.1-4-gXXXX -> numeric is 1.20.1
set(_VIX_PROJECT_VERSION "${_VIX_VERSION_FALLBACK}")
if(_VIX_GIT_DESCRIBE MATCHES "^v([0-9]+\\.[0-9]+\\.[0-9]+)")
set(_VIX_PROJECT_VERSION "${CMAKE_MATCH_1}")
endif()

project(vix VERSION ${_VIX_PROJECT_VERSION} LANGUAGES CXX)

# Human-friendly version string (can include -N-gHASH[-dirty])
if(_VIX_GIT_DESCRIBE STREQUAL "")
set(VIX_UMBRELLA_VERSION "v${PROJECT_VERSION}")
else()
set(VIX_UMBRELLA_VERSION "${_VIX_GIT_DESCRIBE}")
endif()
set(VIX_UMBRELLA_VERSION "${VIX_UMBRELLA_VERSION}" CACHE STRING "Umbrella version" FORCE)

set(VIX_UMBRELLA_BUILD ON CACHE BOOL "Building Vix from umbrella" FORCE)

# Make find_package honor *_ROOT hints (e.g. MYSQLCPPCONN_ROOT)
if (POLICY CMP0144)
Expand Down Expand Up @@ -72,6 +106,15 @@ option(VIX_BENCH_MODE "Disable heavy security/logging checks for benchmarks" OFF
option(VIX_ENABLE_MIDDLEWARE "Build Vix middleware module" ON)
option(VIX_ENABLE_HTTP_COMPRESSION "Enable HTTP compression middleware deps (zlib/brotli)" ON)

option(VIX_ENABLE_DB "Build Vix DB module (core anti-ORM)" ON)

# DB backends (forwarded to modules/db)
option(VIX_DB_USE_MYSQL "Enable MySQL backend in vix_db" ON)
option(VIX_DB_USE_SQLITE "Enable SQLite backend in vix_db" OFF)
option(VIX_DB_USE_POSTGRES "Enable PostgreSQL backend in vix_db" OFF)
option(VIX_DB_USE_REDIS "Enable Redis backend in vix_db" OFF)


# ----------------------------------------------------
# Tooling / Static analysis
# ----------------------------------------------------
Expand Down Expand Up @@ -341,6 +384,23 @@ if (VIX_BENCH_MODE)
endif()
endif()

# --- DB (optional, required by ORM) ---
set(VIX_HAS_DB OFF)
if (VIX_ENABLE_DB AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/modules/db/CMakeLists.txt")
message(STATUS "Adding 'modules/db'...")
add_subdirectory(modules/db db_build)

if (TARGET vix::db OR TARGET vix_db)
if (TARGET vix_db AND NOT TARGET vix::db)
add_library(vix::db ALIAS vix_db)
endif()
set(VIX_HAS_DB ON)
else()
message(WARNING "DB module added but no vix::db target was exported.")
endif()
else()
message(STATUS "DB: disabled or not present.")
endif()

# --- WebSocket (optional) ---
set(VIX_HAS_WEBSOCKET OFF)
Expand All @@ -358,21 +418,24 @@ endif()
# --- CLI (optional) ---
if (VIX_ENABLE_CLI AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/modules/cli/CMakeLists.txt")
message(STATUS "Adding 'modules/cli'...")
set(VIX_UMBRELLA_VERSION "${PROJECT_VERSION}" CACHE STRING "Umbrella version" FORCE)
add_subdirectory(modules/cli cli_build)
else()
message(STATUS "CLI: disabled or not present.")
endif()

# --- ORM (optional) ---
# Forwarded to modules/orm (users can override via -D flags)
option(VIX_ORM_USE_MYSQL "Enable MySQL backend in vix_orm" ON)
set(VIX_ORM_BUILD_EXAMPLES OFF CACHE BOOL "Build vix_orm examples")
set(VIX_ORM_BUILD_TESTS OFF CACHE BOOL "Build vix_orm tests")

set(VIX_UMBRELLA_BUILD ON CACHE BOOL "Building Vix from umbrella" FORCE)
set(VIX_HAS_ORM OFF)
if (VIX_ENABLE_ORM AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/modules/orm/CMakeLists.txt")

if (NOT VIX_HAS_DB)
message(FATAL_ERROR "ORM requires DB module. Enable it with -DVIX_ENABLE_DB=ON and ensure modules/db exists.")
endif()

message(STATUS "Adding 'modules/orm'...")
set(VIX_ORM_BUILD_EXAMPLES OFF CACHE BOOL "Build vix_orm examples")
set(VIX_ORM_BUILD_TESTS OFF CACHE BOOL "Build vix_orm tests")

add_subdirectory(modules/orm orm_build)

if (TARGET vix::orm OR TARGET vix_orm)
Expand All @@ -396,6 +459,10 @@ target_link_libraries(vix INTERFACE
${JSON_TARGET}
)

if (TARGET vix::db)
target_link_libraries(vix INTERFACE vix::db)
endif()

# Link websocket only if it exists
if (TARGET vix::websocket)
target_link_libraries(vix INTERFACE vix::websocket)
Expand Down Expand Up @@ -463,7 +530,7 @@ if (VIX_BUILD_EXAMPLES)
endif()

# 2) If ORM is ON but MySQL backend is OFF → remove MySQL-based ORM examples
if (VIX_HAS_ORM AND NOT VIX_ORM_USE_MYSQL)
if (VIX_HAS_ORM AND NOT VIX_DB_USE_MYSQL)
foreach(_ex IN LISTS _ORM_MYSQL_EXAMPLES)
list(FILTER VIX_UMBRELLA_EXAMPLES EXCLUDE REGEX ".*/${_ex}\\.cpp$")
list(FILTER VIX_UMBRELLA_EXAMPLES EXCLUDE REGEX ".*\\\\${_ex}\\.cpp$")
Expand Down Expand Up @@ -629,6 +696,11 @@ if (VIX_ENABLE_INSTALL)
FILES_MATCHING PATTERN "*.hpp" PATTERN "*.h")
endif()

if (VIX_HAS_DB AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/modules/db/include")
install(DIRECTORY modules/db/include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILES_MATCHING PATTERN "*.hpp" PATTERN "*.h")
endif()

if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/modules/middleware/include")
install(DIRECTORY modules/middleware/include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILES_MATCHING PATTERN "*.hpp" PATTERN "*.h")
Expand All @@ -654,10 +726,10 @@ if (VIX_ENABLE_INSTALL)
COMPATIBILITY SameMajorVersion
)

set(VIX_HAS_ORM ${VIX_HAS_ORM})
set(VIX_ORM_WITH_MYSQL OFF)
if (VIX_HAS_ORM AND VIX_ORM_USE_MYSQL)
set(VIX_ORM_WITH_MYSQL ON)
set(VIX_HAS_ORM ${VIX_HAS_ORM})
set(VIX_DB_WITH_MYSQL OFF)
if (VIX_HAS_DB AND VIX_DB_USE_MYSQL)
set(VIX_DB_WITH_MYSQL ON)
endif()

configure_package_config_file(
Expand Down Expand Up @@ -696,6 +768,7 @@ message(STATUS "Project version : ${PROJECT_VERSION}")
message(STATUS "JSON backend : ${_VIX_JSON_BACKEND}")
message(STATUS "WebSocket built : ${VIX_HAS_WEBSOCKET}")
message(STATUS "ORM packaged : ${VIX_HAS_ORM}")
message(STATUS "DB built : ${VIX_HAS_DB}")
message(STATUS "Middleware built : ${VIX_HAS_MIDDLEWARE}")
message(STATUS "Examples : ${VIX_BUILD_EXAMPLES}")
message(STATUS "Tests : ${VIX_BUILD_TESTS}")
Expand Down
26 changes: 15 additions & 11 deletions examples/http_crud/batch_insert_tx.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
*
* @file examples/http_crud/batch_insert_tx.cpp
* @file batch_insert_tx.hpp
* @author Gaspard Kirira
*
* Copyright 2025, Gaspard Kirira. All rights reserved.
Expand All @@ -9,28 +9,26 @@
* that can be found in the License file.
*
* Vix.cpp
*
*/

#include <vix/orm/orm.hpp>
#include <vix/orm/ConnectionPool.hpp>
#include <vix/orm/MySQLDriver.hpp>

#include <cstdint>
#include <iostream>
#include <vector>
#include <string>
#include <vector>

using namespace vix::orm;

int main(int argc, char **argv)
{
std::string host = (argc > 1 ? argv[1] : "tcp://127.0.0.1:3306");
std::string user = (argc > 2 ? argv[2] : "root");
std::string pass = (argc > 3 ? argv[3] : "");
std::string db = (argc > 4 ? argv[4] : "vixdb");
const std::string host = (argc > 1 ? argv[1] : "tcp://127.0.0.1:3306");
const std::string user = (argc > 2 ? argv[2] : "root");
const std::string pass = (argc > 3 ? argv[3] : "");
const std::string db = (argc > 4 ? argv[4] : "vixdb");

try
{
// DB factory (MySQL driver)
auto factory = make_mysql_factory(host, user, pass, db);

PoolConfig cfg;
Expand All @@ -40,6 +38,7 @@ int main(int argc, char **argv)
ConnectionPool pool{factory, cfg};
pool.warmup();

// Transaction (RAII rollback if not committed)
Transaction tx(pool);
auto &c = tx.conn();

Expand All @@ -52,7 +51,7 @@ int main(int argc, char **argv)
int age;
};

std::vector<Row> rows = {
const std::vector<Row> rows = {
{"Zoe", "zoe@example.com", 23},
{"Mina", "mina@example.com", 31},
{"Omar", "omar@example.com", 35},
Expand All @@ -71,6 +70,11 @@ int main(int argc, char **argv)
std::cout << "[OK] inserted rows = " << total << "\n";
return 0;
}
catch (const DBError &e)
{
std::cerr << "[DBError] " << e.what() << "\n";
return 1;
}
catch (const std::exception &e)
{
std::cerr << "[ERR] " << e.what() << "\n";
Expand Down
37 changes: 31 additions & 6 deletions examples/http_crud/error_handling.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
*
* @file examples/http_crud/error_handling.cpp
* @file error_handling.hpp
* @author Gaspard Kirira
*
* Copyright 2025, Gaspard Kirira. All rights reserved.
Expand All @@ -9,31 +9,56 @@
* that can be found in the License file.
*
* Vix.cpp
*
*/
#include <vix/orm/orm.hpp>

#include <iostream>
#include <string>

using namespace vix::orm;

int main(int argc, char **argv)
{
(void)argc;
(void)argv;

try
{
// Intentionally wrong DB name to show error
auto raw = make_mysql_factory("tcp://127.0.0.1:3306", "root", "", "db_does_not_exist");
//.....
// Intentionally wrong DB name to show error handling
const std::string host = "tcp://127.0.0.1:3306";
const std::string user = "root";
const std::string pass = "";
const std::string db = "db_does_not_exist";

auto factory = make_mysql_factory(host, user, pass, db);

PoolConfig cfg;
cfg.min = 1;
cfg.max = 8;

ConnectionPool pool{factory, cfg};

// will throw if factory returns invalid connection (recommended after our warmup fix),
// or later when first query fails.
pool.warmup();

UnitOfWork uow{pool};
auto &con = uow.conn();

auto st = con.prepare("SELECT 1");
(void)st->exec();

std::cout << "[INFO] This message may not be reached if connection fails.\n";
return 0;
}
catch (const DBError &e)
{
std::cerr << "[DBError] " << e.what() << "\n";
return 1;
}
catch (const std::exception &e)
{
std::cerr << "[std::exception] " << e.what() << "\n";
return 1;
}
return 0;
}
Loading
Loading