mirror of
https://github.com/latentPrion/cppbessot.git
synced 2026-06-23 15:18:37 +00:00
Add migration commands for SQLite; not PGSql
This commit is contained in:
@@ -9,6 +9,9 @@ if(NOT DEFINED DB_SCHEMA_DIR_TO_GENERATE OR "${DB_SCHEMA_DIR_TO_GENERATE}" STREQ
|
|||||||
"Set DB_SCHEMA_DIR_TO_GENERATE to the exact schema directory basename to test, for example -DDB_SCHEMA_DIR_TO_GENERATE=v1.2.")
|
"Set DB_SCHEMA_DIR_TO_GENERATE to the exact schema directory basename to test, for example -DDB_SCHEMA_DIR_TO_GENERATE=v1.2.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/dbDependencyCheck.cmake")
|
||||||
|
cppbessot_check_dependencies()
|
||||||
|
|
||||||
set(CPPBESSOT_ODB_TEST_SQLITE_CONNSTR "" CACHE STRING
|
set(CPPBESSOT_ODB_TEST_SQLITE_CONNSTR "" CACHE STRING
|
||||||
"Optional SQLite connection string for ODB runtime tests")
|
"Optional SQLite connection string for ODB runtime tests")
|
||||||
set(CPPBESSOT_ODB_TEST_PGSQL_CONNSTR "" CACHE STRING
|
set(CPPBESSOT_ODB_TEST_PGSQL_CONNSTR "" CACHE STRING
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ include("${CMAKE_CURRENT_LIST_DIR}/dbGenCpp.cmake")
|
|||||||
include("${CMAKE_CURRENT_LIST_DIR}/dbGenODB.cmake")
|
include("${CMAKE_CURRENT_LIST_DIR}/dbGenODB.cmake")
|
||||||
include("${CMAKE_CURRENT_LIST_DIR}/dbGenSqlDDL.cmake")
|
include("${CMAKE_CURRENT_LIST_DIR}/dbGenSqlDDL.cmake")
|
||||||
include("${CMAKE_CURRENT_LIST_DIR}/dbGenMigrations.cmake")
|
include("${CMAKE_CURRENT_LIST_DIR}/dbGenMigrations.cmake")
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/dbActionCommon.cmake")
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/dbActionCreateFrom.cmake")
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/dbActionMigrate.cmake")
|
||||||
|
|
||||||
if(NOT DEFINED CPPBESSOT_WORKDIR)
|
if(NOT DEFINED CPPBESSOT_WORKDIR)
|
||||||
set(CPPBESSOT_WORKDIR "db" CACHE STRING "CppBeSSOT schema root folder")
|
set(CPPBESSOT_WORKDIR "db" CACHE STRING "CppBeSSOT schema root folder")
|
||||||
@@ -32,6 +35,41 @@ if(NOT DEFINED DB_SCHEMA_CHANGES_ARE_ERROR)
|
|||||||
option(DB_SCHEMA_CHANGES_ARE_ERROR "Treat dirty schema changes as hard CMake error" OFF)
|
option(DB_SCHEMA_CHANGES_ARE_ERROR "Treat dirty schema changes as hard CMake error" OFF)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED DB_TARGET)
|
||||||
|
set(DB_TARGET "dev" CACHE STRING "Live DB target to act on: prod, proddev, or dev")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED DB_CREATEFROM_SCHEMA_DIR)
|
||||||
|
set(DB_CREATEFROM_SCHEMA_DIR "${DB_SCHEMA_DIR_TO_GENERATE}" CACHE STRING
|
||||||
|
"Schema directory basename under CPPBESSOT_WORKDIR to create a live DB from")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED DB_MIGRATE_WITH)
|
||||||
|
set(DB_MIGRATE_WITH "" CACHE STRING
|
||||||
|
"Migration directory basename under CPPBESSOT_WORKDIR/migrations to apply to the selected DB target")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED DB_MIGRATE_PRODDEV_USE_STALE)
|
||||||
|
option(DB_MIGRATE_PRODDEV_USE_STALE "Reuse an existing stale proddev clone instead of recloning from prod" OFF)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CPPBESSOT_DB_SQLITE_PROD_PATH "${CPPBESSOT_DB_SQLITE_PROD_PATH}" CACHE STRING
|
||||||
|
"Parent-supplied SQLite DB path for DB_TARGET=prod")
|
||||||
|
set(CPPBESSOT_DB_SQLITE_DEV_PATH "${CPPBESSOT_DB_SQLITE_DEV_PATH}" CACHE STRING
|
||||||
|
"Parent-supplied SQLite DB path for DB_TARGET=dev")
|
||||||
|
set(CPPBESSOT_DB_SQLITE_PRODDEV_PATH "${CPPBESSOT_DB_SQLITE_PRODDEV_PATH}" CACHE STRING
|
||||||
|
"Parent-supplied SQLite DB path for DB_TARGET=proddev")
|
||||||
|
set(CPPBESSOT_DB_PGSQL_PROD_CONNSTR "${CPPBESSOT_DB_PGSQL_PROD_CONNSTR}" CACHE STRING
|
||||||
|
"Parent-supplied PostgreSQL connection string for DB_TARGET=prod")
|
||||||
|
set(CPPBESSOT_DB_PGSQL_DEV_CONNSTR "${CPPBESSOT_DB_PGSQL_DEV_CONNSTR}" CACHE STRING
|
||||||
|
"Parent-supplied PostgreSQL connection string for DB_TARGET=dev")
|
||||||
|
set(CPPBESSOT_DB_PGSQL_PRODDEV_CONNSTR "${CPPBESSOT_DB_PGSQL_PRODDEV_CONNSTR}" CACHE STRING
|
||||||
|
"Parent-supplied PostgreSQL connection string for DB_TARGET=proddev")
|
||||||
|
set(CPPBESSOT_DB_SQLITE_CLONE_PROD_TO_PRODDEV_COMMAND "${CPPBESSOT_DB_SQLITE_CLONE_PROD_TO_PRODDEV_COMMAND}" CACHE STRING
|
||||||
|
"Parent-supplied command string that clones the prod SQLite DB into proddev")
|
||||||
|
set(CPPBESSOT_DB_PGSQL_CLONE_PROD_TO_PRODDEV_COMMAND "${CPPBESSOT_DB_PGSQL_CLONE_PROD_TO_PRODDEV_COMMAND}" CACHE STRING
|
||||||
|
"Parent-supplied command string that clones the prod PostgreSQL DB into proddev")
|
||||||
|
|
||||||
if(NOT DEFINED CPPBESSOT_AUTO_ENABLE)
|
if(NOT DEFINED CPPBESSOT_AUTO_ENABLE)
|
||||||
option(CPPBESSOT_AUTO_ENABLE "Auto-register CppBeSSOT targets when this file is included" ON)
|
option(CPPBESSOT_AUTO_ENABLE "Auto-register CppBeSSOT targets when this file is included" ON)
|
||||||
endif()
|
endif()
|
||||||
@@ -218,6 +256,8 @@ function(cppbessot_enable)
|
|||||||
# - db_gen_sql_ddl
|
# - db_gen_sql_ddl
|
||||||
# - db_gen_migrations
|
# - db_gen_migrations
|
||||||
# - db_gen_orm_serdes_and_zod
|
# - db_gen_orm_serdes_and_zod
|
||||||
|
# - db_createfrom
|
||||||
|
# - db_migrate
|
||||||
# - Generated library targets for selected schema version.
|
# - Generated library targets for selected schema version.
|
||||||
cppbessot_initialize_paths()
|
cppbessot_initialize_paths()
|
||||||
|
|
||||||
@@ -261,6 +301,8 @@ VERBATIM
|
|||||||
db_gen_sql_ddl)
|
db_gen_sql_ddl)
|
||||||
set_target_properties(db_gen_orm_serdes_and_zod PROPERTIES EXCLUDE_FROM_ALL TRUE)
|
set_target_properties(db_gen_orm_serdes_and_zod PROPERTIES EXCLUDE_FROM_ALL TRUE)
|
||||||
|
|
||||||
|
cppbessot_add_db_createfrom_target()
|
||||||
|
cppbessot_add_db_migrate_target()
|
||||||
cppbessot_add_generated_libraries()
|
cppbessot_add_generated_libraries()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
include_guard(GLOBAL)
|
||||||
|
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/dbGenerationCommon.cmake")
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/dbActionShared.cmake")
|
||||||
|
|
||||||
|
function(cppbessot_validate_db_target db_target)
|
||||||
|
_cppbessot_db_action_validate_db_target_impl("${db_target}")
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_validate_migration_dir_name migration_dir)
|
||||||
|
_cppbessot_db_action_validate_basename(
|
||||||
|
"${migration_dir}"
|
||||||
|
"Migration directory name"
|
||||||
|
"CPPBESSOT_WORKDIR/migrations")
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_get_migration_dir_path out_var migration_dir)
|
||||||
|
cppbessot_validate_migration_dir_name("${migration_dir}")
|
||||||
|
cppbessot_abs_path(_workdir "${CPPBESSOT_WORKDIR}")
|
||||||
|
set(${out_var} "${_workdir}/migrations/${migration_dir}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_assert_migration_dir_exists migration_dir)
|
||||||
|
cppbessot_get_migration_dir_path(_migration_dir_path "${migration_dir}")
|
||||||
|
if(NOT IS_DIRECTORY "${_migration_dir_path}")
|
||||||
|
message(FATAL_ERROR "Migration directory does not exist: ${_migration_dir_path}")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(_cppbessot_db_action_common_cache_args out_var)
|
||||||
|
set(_args
|
||||||
|
"-DCPPBESSOT_PROJECT_SOURCE_DIR=${PROJECT_SOURCE_DIR}"
|
||||||
|
"-DCPPBESSOT_WORKDIR=${CPPBESSOT_WORKDIR}"
|
||||||
|
"-DDB_SCHEMA_DIR_TO_GENERATE=${DB_SCHEMA_DIR_TO_GENERATE}"
|
||||||
|
"-DDB_CREATEFROM_SCHEMA_DIR=${DB_CREATEFROM_SCHEMA_DIR}"
|
||||||
|
"-DDB_TARGET=${DB_TARGET}"
|
||||||
|
"-DCPPBESSOT_DB_SQLITE_PROD_PATH=${CPPBESSOT_DB_SQLITE_PROD_PATH}"
|
||||||
|
"-DCPPBESSOT_DB_SQLITE_DEV_PATH=${CPPBESSOT_DB_SQLITE_DEV_PATH}"
|
||||||
|
"-DCPPBESSOT_DB_SQLITE_PRODDEV_PATH=${CPPBESSOT_DB_SQLITE_PRODDEV_PATH}"
|
||||||
|
"-DCPPBESSOT_DB_PGSQL_PROD_CONNSTR=${CPPBESSOT_DB_PGSQL_PROD_CONNSTR}"
|
||||||
|
"-DCPPBESSOT_DB_PGSQL_DEV_CONNSTR=${CPPBESSOT_DB_PGSQL_DEV_CONNSTR}"
|
||||||
|
"-DCPPBESSOT_DB_PGSQL_PRODDEV_CONNSTR=${CPPBESSOT_DB_PGSQL_PRODDEV_CONNSTR}")
|
||||||
|
set(${out_var} "${_args}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(_cppbessot_add_db_action_target target_name script_path comment_text)
|
||||||
|
add_custom_target(${target_name}
|
||||||
|
COMMAND "${CMAKE_COMMAND}" ${ARGN} -P "${script_path}"
|
||||||
|
COMMENT "${comment_text}"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
set_target_properties(${target_name} PROPERTIES EXCLUDE_FROM_ALL TRUE)
|
||||||
|
endfunction()
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
include_guard(GLOBAL)
|
||||||
|
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/dbActionCommon.cmake")
|
||||||
|
set(_CPPBESSOT_DB_ACTION_CREATEFROM_DIR "${CMAKE_CURRENT_LIST_DIR}")
|
||||||
|
|
||||||
|
function(cppbessot_add_db_createfrom_target)
|
||||||
|
_cppbessot_db_action_common_cache_args(_common_args)
|
||||||
|
_cppbessot_add_db_action_target(
|
||||||
|
db_createfrom
|
||||||
|
"${_CPPBESSOT_DB_ACTION_CREATEFROM_DIR}/scripts/run_db_createfrom.cmake"
|
||||||
|
"Creating live DB target `${DB_TARGET}` from schema `${DB_CREATEFROM_SCHEMA_DIR}`"
|
||||||
|
${_common_args})
|
||||||
|
endfunction()
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
include_guard(GLOBAL)
|
||||||
|
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/dbActionCommon.cmake")
|
||||||
|
set(_CPPBESSOT_DB_ACTION_MIGRATE_DIR "${CMAKE_CURRENT_LIST_DIR}")
|
||||||
|
|
||||||
|
function(cppbessot_add_db_migrate_target)
|
||||||
|
_cppbessot_db_action_common_cache_args(_common_args)
|
||||||
|
_cppbessot_add_db_action_target(
|
||||||
|
db_migrate
|
||||||
|
"${_CPPBESSOT_DB_ACTION_MIGRATE_DIR}/scripts/run_db_migrate.cmake"
|
||||||
|
"Migrating live DB target `${DB_TARGET}` using migration `${DB_MIGRATE_WITH}`"
|
||||||
|
${_common_args}
|
||||||
|
"-DDB_MIGRATE_WITH=${DB_MIGRATE_WITH}"
|
||||||
|
"-DDB_MIGRATE_PRODDEV_USE_STALE=${DB_MIGRATE_PRODDEV_USE_STALE}"
|
||||||
|
"-DCPPBESSOT_DB_SQLITE_CLONE_PROD_TO_PRODDEV_COMMAND=${CPPBESSOT_DB_SQLITE_CLONE_PROD_TO_PRODDEV_COMMAND}"
|
||||||
|
"-DCPPBESSOT_DB_PGSQL_CLONE_PROD_TO_PRODDEV_COMMAND=${CPPBESSOT_DB_PGSQL_CLONE_PROD_TO_PRODDEV_COMMAND}")
|
||||||
|
endfunction()
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
include_guard(GLOBAL)
|
||||||
|
|
||||||
|
function(_cppbessot_db_action_validate_basename value kind relative_root)
|
||||||
|
if("${value}" STREQUAL "")
|
||||||
|
message(FATAL_ERROR "${kind} must not be empty.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if("${value}" MATCHES "[/\\\\]")
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"${kind} `${value}` must be a basename under ${relative_root}, not a path.")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(_cppbessot_db_action_validate_db_target_impl db_target)
|
||||||
|
if(NOT "${db_target}" STREQUAL "prod"
|
||||||
|
AND NOT "${db_target}" STREQUAL "proddev"
|
||||||
|
AND NOT "${db_target}" STREQUAL "dev")
|
||||||
|
message(FATAL_ERROR "DB_TARGET must be one of: prod, proddev, dev.")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
@@ -4,6 +4,24 @@ include("${CMAKE_CURRENT_LIST_DIR}/dbGenerationCommon.cmake")
|
|||||||
include(CheckIncludeFileCXX)
|
include(CheckIncludeFileCXX)
|
||||||
include(CMakePushCheckState)
|
include(CMakePushCheckState)
|
||||||
|
|
||||||
|
function(_cppbessot_publish_dependency_outputs)
|
||||||
|
set(CPPBESSOT_ODB_EXECUTABLE "${CPPBESSOT_ODB_EXECUTABLE}" PARENT_SCOPE)
|
||||||
|
set(CPPBESSOT_NPX_EXECUTABLE "${CPPBESSOT_NPX_EXECUTABLE}" PARENT_SCOPE)
|
||||||
|
set(CPPBESSOT_NPM_EXECUTABLE "${CPPBESSOT_NPM_EXECUTABLE}" PARENT_SCOPE)
|
||||||
|
set(CPPBESSOT_JAVA_EXECUTABLE "${CPPBESSOT_JAVA_EXECUTABLE}" PARENT_SCOPE)
|
||||||
|
set(CPPBESSOT_GIT_EXECUTABLE "${CPPBESSOT_GIT_EXECUTABLE}" PARENT_SCOPE)
|
||||||
|
set(CPPBESSOT_SQLITE3_EXECUTABLE "${CPPBESSOT_SQLITE3_EXECUTABLE}" PARENT_SCOPE)
|
||||||
|
set(CPPBESSOT_PSQL_EXECUTABLE "${CPPBESSOT_PSQL_EXECUTABLE}" PARENT_SCOPE)
|
||||||
|
set(CPPBESSOT_ODB_RUNTIME_LIB "${CPPBESSOT_ODB_RUNTIME_LIB}" PARENT_SCOPE)
|
||||||
|
set(CPPBESSOT_ODB_SQLITE_RUNTIME_LIB "${CPPBESSOT_ODB_SQLITE_RUNTIME_LIB}" PARENT_SCOPE)
|
||||||
|
set(CPPBESSOT_ODB_PGSQL_RUNTIME_LIB "${CPPBESSOT_ODB_PGSQL_RUNTIME_LIB}" PARENT_SCOPE)
|
||||||
|
set(CPPBESSOT_SQLITE_INCLUDE_DIR "${CPPBESSOT_SQLITE_INCLUDE_DIR}" PARENT_SCOPE)
|
||||||
|
set(CPPBESSOT_PGSQL_INCLUDE_DIR "${CPPBESSOT_PGSQL_INCLUDE_DIR}" PARENT_SCOPE)
|
||||||
|
set(CPPBESSOT_SQLITE_CLIENT_LIB "${CPPBESSOT_SQLITE_CLIENT_LIB}" PARENT_SCOPE)
|
||||||
|
set(CPPBESSOT_PGSQL_CLIENT_LIB "${CPPBESSOT_PGSQL_CLIENT_LIB}" PARENT_SCOPE)
|
||||||
|
set(CPPBESSOT_OPENAPI_ZOD_AVAILABLE TRUE PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
function(_cppbessot_require_program var_name program_name hint)
|
function(_cppbessot_require_program var_name program_name hint)
|
||||||
# Purpose: Locate an executable and fail with a clear install hint if missing.
|
# Purpose: Locate an executable and fail with a clear install hint if missing.
|
||||||
# Inputs:
|
# Inputs:
|
||||||
@@ -64,6 +82,7 @@ function(_cppbessot_require_npx_package_executable npx_executable package_execut
|
|||||||
# - No return value; raises FATAL_ERROR if execution fails.
|
# - No return value; raises FATAL_ERROR if execution fails.
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND "${npx_executable}" --no-install "${package_executable}" --help
|
COMMAND "${npx_executable}" --no-install "${package_executable}" --help
|
||||||
|
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
|
||||||
RESULT_VARIABLE _help_result
|
RESULT_VARIABLE _help_result
|
||||||
OUTPUT_QUIET
|
OUTPUT_QUIET
|
||||||
ERROR_VARIABLE _help_stderr
|
ERROR_VARIABLE _help_stderr
|
||||||
@@ -76,6 +95,7 @@ function(_cppbessot_require_npx_package_executable npx_executable package_execut
|
|||||||
# Some CLIs return non-zero for --help; verify with version as fallback.
|
# Some CLIs return non-zero for --help; verify with version as fallback.
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND "${npx_executable}" --no-install "${package_executable}" version
|
COMMAND "${npx_executable}" --no-install "${package_executable}" version
|
||||||
|
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
|
||||||
RESULT_VARIABLE _version_result
|
RESULT_VARIABLE _version_result
|
||||||
OUTPUT_QUIET
|
OUTPUT_QUIET
|
||||||
ERROR_VARIABLE _version_stderr
|
ERROR_VARIABLE _version_stderr
|
||||||
@@ -101,6 +121,12 @@ function(cppbessot_check_dependencies)
|
|||||||
# - CPPBESSOT_GIT_EXECUTABLE (PARENT_SCOPE)
|
# - CPPBESSOT_GIT_EXECUTABLE (PARENT_SCOPE)
|
||||||
# - CPPBESSOT_OPENAPI_ZOD_AVAILABLE (PARENT_SCOPE)
|
# - CPPBESSOT_OPENAPI_ZOD_AVAILABLE (PARENT_SCOPE)
|
||||||
# - No return value; raises FATAL_ERROR on missing dependencies.
|
# - No return value; raises FATAL_ERROR on missing dependencies.
|
||||||
|
get_property(_cppbessot_dependencies_checked GLOBAL PROPERTY CPPBESSOT_DEPENDENCIES_CHECKED)
|
||||||
|
if(_cppbessot_dependencies_checked)
|
||||||
|
_cppbessot_publish_dependency_outputs()
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
_cppbessot_require_program(CPPBESSOT_ODB_EXECUTABLE odb
|
_cppbessot_require_program(CPPBESSOT_ODB_EXECUTABLE odb
|
||||||
"Install ODB compiler and ensure `odb` is in PATH.")
|
"Install ODB compiler and ensure `odb` is in PATH.")
|
||||||
_cppbessot_require_program(CPPBESSOT_NPX_EXECUTABLE npx
|
_cppbessot_require_program(CPPBESSOT_NPX_EXECUTABLE npx
|
||||||
@@ -111,6 +137,10 @@ function(cppbessot_check_dependencies)
|
|||||||
"Install a Java runtime (OpenAPI generator uses Java).")
|
"Install a Java runtime (OpenAPI generator uses Java).")
|
||||||
_cppbessot_require_program(CPPBESSOT_GIT_EXECUTABLE git
|
_cppbessot_require_program(CPPBESSOT_GIT_EXECUTABLE git
|
||||||
"Install Git and ensure it is available in PATH.")
|
"Install Git and ensure it is available in PATH.")
|
||||||
|
_cppbessot_require_program(CPPBESSOT_SQLITE3_EXECUTABLE sqlite3
|
||||||
|
"Install the SQLite CLI so live SQLite DB actions can apply SQL files.")
|
||||||
|
_cppbessot_require_program(CPPBESSOT_PSQL_EXECUTABLE psql
|
||||||
|
"Install the PostgreSQL client CLI so live PostgreSQL DB actions can run.")
|
||||||
|
|
||||||
_cppbessot_require_npm_package("${CPPBESSOT_NPM_EXECUTABLE}" "@openapitools/openapi-generator-cli")
|
_cppbessot_require_npm_package("${CPPBESSOT_NPM_EXECUTABLE}" "@openapitools/openapi-generator-cli")
|
||||||
_cppbessot_require_npx_package_executable("${CPPBESSOT_NPX_EXECUTABLE}" "@openapitools/openapi-generator-cli")
|
_cppbessot_require_npx_package_executable("${CPPBESSOT_NPX_EXECUTABLE}" "@openapitools/openapi-generator-cli")
|
||||||
@@ -187,17 +217,6 @@ function(cppbessot_check_dependencies)
|
|||||||
"PostgreSQL client library was not found. On Ubuntu/Debian install package `libpq-dev`.")
|
"PostgreSQL client library was not found. On Ubuntu/Debian install package `libpq-dev`.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(CPPBESSOT_ODB_EXECUTABLE "${CPPBESSOT_ODB_EXECUTABLE}" PARENT_SCOPE)
|
set_property(GLOBAL PROPERTY CPPBESSOT_DEPENDENCIES_CHECKED TRUE)
|
||||||
set(CPPBESSOT_NPX_EXECUTABLE "${CPPBESSOT_NPX_EXECUTABLE}" PARENT_SCOPE)
|
_cppbessot_publish_dependency_outputs()
|
||||||
set(CPPBESSOT_NPM_EXECUTABLE "${CPPBESSOT_NPM_EXECUTABLE}" PARENT_SCOPE)
|
|
||||||
set(CPPBESSOT_JAVA_EXECUTABLE "${CPPBESSOT_JAVA_EXECUTABLE}" PARENT_SCOPE)
|
|
||||||
set(CPPBESSOT_GIT_EXECUTABLE "${CPPBESSOT_GIT_EXECUTABLE}" PARENT_SCOPE)
|
|
||||||
set(CPPBESSOT_ODB_RUNTIME_LIB "${CPPBESSOT_ODB_RUNTIME_LIB}" PARENT_SCOPE)
|
|
||||||
set(CPPBESSOT_ODB_SQLITE_RUNTIME_LIB "${CPPBESSOT_ODB_SQLITE_RUNTIME_LIB}" PARENT_SCOPE)
|
|
||||||
set(CPPBESSOT_ODB_PGSQL_RUNTIME_LIB "${CPPBESSOT_ODB_PGSQL_RUNTIME_LIB}" PARENT_SCOPE)
|
|
||||||
set(CPPBESSOT_SQLITE_INCLUDE_DIR "${CPPBESSOT_SQLITE_INCLUDE_DIR}" PARENT_SCOPE)
|
|
||||||
set(CPPBESSOT_PGSQL_INCLUDE_DIR "${CPPBESSOT_PGSQL_INCLUDE_DIR}" PARENT_SCOPE)
|
|
||||||
set(CPPBESSOT_SQLITE_CLIENT_LIB "${CPPBESSOT_SQLITE_CLIENT_LIB}" PARENT_SCOPE)
|
|
||||||
set(CPPBESSOT_PGSQL_CLIENT_LIB "${CPPBESSOT_PGSQL_CLIENT_LIB}" PARENT_SCOPE)
|
|
||||||
set(CPPBESSOT_OPENAPI_ZOD_AVAILABLE TRUE PARENT_SCOPE)
|
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
function(cppbessot_db_action_get_hook_path out_var migration_dir hook_name)
|
||||||
|
set(_hook_path "${migration_dir}/${hook_name}")
|
||||||
|
if(EXISTS "${_hook_path}")
|
||||||
|
set(${out_var} "${_hook_path}" PARENT_SCOPE)
|
||||||
|
else()
|
||||||
|
set(${out_var} "" PARENT_SCOPE)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_db_action_run_hook
|
||||||
|
hook_path
|
||||||
|
db_target
|
||||||
|
backend
|
||||||
|
migration_dir
|
||||||
|
migrate_with
|
||||||
|
schema_dir_to_generate
|
||||||
|
createfrom_schema_dir
|
||||||
|
sqlite_path
|
||||||
|
pgsql_connstr)
|
||||||
|
if("${hook_path}" STREQUAL "")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(_env_args
|
||||||
|
"CPPBESSOT_DB_TARGET=${db_target}"
|
||||||
|
"CPPBESSOT_DB_BACKEND=${backend}"
|
||||||
|
"CPPBESSOT_DB_MIGRATION_DIR=${migration_dir}"
|
||||||
|
"CPPBESSOT_DB_MIGRATE_WITH=${migrate_with}"
|
||||||
|
"CPPBESSOT_DB_SCHEMA_DIR_TO_GENERATE=${schema_dir_to_generate}"
|
||||||
|
"CPPBESSOT_DB_CREATEFROM_SCHEMA_DIR=${createfrom_schema_dir}"
|
||||||
|
"CPPBESSOT_DB_SQLITE_PATH=${sqlite_path}"
|
||||||
|
"CPPBESSOT_DB_PGSQL_CONNSTR=${pgsql_connstr}")
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E env ${_env_args} sh "${hook_path}"
|
||||||
|
WORKING_DIRECTORY "${migration_dir}"
|
||||||
|
RESULT_VARIABLE _result
|
||||||
|
OUTPUT_VARIABLE _stdout
|
||||||
|
ERROR_VARIABLE _stderr
|
||||||
|
)
|
||||||
|
|
||||||
|
if(NOT _result EQUAL 0)
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"Backfill hook failed: ${hook_path}\n${_stdout}\n${_stderr}")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
function(cppbessot_db_action_target_exists out_var backend sqlite_path pgsql_connstr)
|
||||||
|
if("${backend}" STREQUAL "sqlite")
|
||||||
|
if(EXISTS "${sqlite_path}")
|
||||||
|
set(${out_var} TRUE PARENT_SCOPE)
|
||||||
|
else()
|
||||||
|
set(${out_var} FALSE PARENT_SCOPE)
|
||||||
|
endif()
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
cppbessot_db_action_find_program_or_fail(_psql psql
|
||||||
|
"PostgreSQL live actions require `psql` to be available in PATH.")
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${_psql}" "${pgsql_connstr}" -v ON_ERROR_STOP=1 -c "SELECT 1;"
|
||||||
|
RESULT_VARIABLE _result
|
||||||
|
OUTPUT_QUIET
|
||||||
|
ERROR_QUIET
|
||||||
|
)
|
||||||
|
if(_result EQUAL 0)
|
||||||
|
set(${out_var} TRUE PARENT_SCOPE)
|
||||||
|
else()
|
||||||
|
set(${out_var} FALSE PARENT_SCOPE)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_db_action_get_clone_command out_var backend)
|
||||||
|
if("${backend}" STREQUAL "sqlite")
|
||||||
|
set(_command "${CPPBESSOT_DB_SQLITE_CLONE_PROD_TO_PRODDEV_COMMAND}")
|
||||||
|
else()
|
||||||
|
set(_command "${CPPBESSOT_DB_PGSQL_CLONE_PROD_TO_PRODDEV_COMMAND}")
|
||||||
|
endif()
|
||||||
|
set(${out_var} "${_command}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_db_action_invoke_clone_hook backend)
|
||||||
|
cppbessot_db_action_get_clone_command(_clone_command "${backend}")
|
||||||
|
if("${_clone_command}" STREQUAL "")
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"No clone command is configured for backend `${backend}` while preparing proddev.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND sh -c "${_clone_command}"
|
||||||
|
RESULT_VARIABLE _result
|
||||||
|
OUTPUT_VARIABLE _stdout
|
||||||
|
ERROR_VARIABLE _stderr
|
||||||
|
)
|
||||||
|
|
||||||
|
if(NOT _result EQUAL 0)
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"Proddev clone command failed for backend `${backend}`.\n${_stdout}\n${_stderr}")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_db_action_prepare_proddev target backend use_stale sqlite_path pgsql_connstr)
|
||||||
|
if(NOT "${target}" STREQUAL "proddev")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(use_stale)
|
||||||
|
cppbessot_db_action_target_exists(_exists "${backend}" "${sqlite_path}" "${pgsql_connstr}")
|
||||||
|
if(NOT _exists)
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"DB_MIGRATE_PRODDEV_USE_STALE is ON, but no current stale proddev target exists.")
|
||||||
|
endif()
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
cppbessot_db_action_invoke_clone_hook("${backend}")
|
||||||
|
cppbessot_db_action_target_exists(_exists "${backend}" "${sqlite_path}" "${pgsql_connstr}")
|
||||||
|
if(NOT _exists)
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"Proddev clone command completed, but the proddev target still does not appear to exist.")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/../dbActionShared.cmake")
|
||||||
|
|
||||||
|
function(cppbessot_db_action_require_var var_name)
|
||||||
|
if(NOT DEFINED ${var_name} OR "${${var_name}}" STREQUAL "")
|
||||||
|
message(FATAL_ERROR "Required variable `${var_name}` is missing.")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_db_action_resolve_project_path out_var input_path)
|
||||||
|
cppbessot_db_action_require_var(CPPBESSOT_PROJECT_SOURCE_DIR)
|
||||||
|
if(IS_ABSOLUTE "${input_path}")
|
||||||
|
set(_resolved "${input_path}")
|
||||||
|
else()
|
||||||
|
set(_resolved "${CPPBESSOT_PROJECT_SOURCE_DIR}/${input_path}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
get_filename_component(_resolved "${_resolved}" ABSOLUTE)
|
||||||
|
set(${out_var} "${_resolved}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_db_action_validate_schema_dir_name schema_dir)
|
||||||
|
_cppbessot_db_action_validate_basename(
|
||||||
|
"${schema_dir}"
|
||||||
|
"Schema directory name"
|
||||||
|
"CPPBESSOT_WORKDIR")
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_db_action_get_schema_dir_path out_var schema_dir)
|
||||||
|
cppbessot_db_action_validate_schema_dir_name("${schema_dir}")
|
||||||
|
cppbessot_db_action_resolve_project_path(_workdir "${CPPBESSOT_WORKDIR}")
|
||||||
|
set(${out_var} "${_workdir}/${schema_dir}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_db_action_assert_schema_dir_ready schema_dir)
|
||||||
|
cppbessot_db_action_get_schema_dir_path(_schema_dir_path "${schema_dir}")
|
||||||
|
if(NOT IS_DIRECTORY "${_schema_dir_path}")
|
||||||
|
message(FATAL_ERROR "Schema directory does not exist: ${_schema_dir_path}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(_openapi_file "${_schema_dir_path}/openapi/openapi.yaml")
|
||||||
|
if(NOT EXISTS "${_openapi_file}")
|
||||||
|
message(FATAL_ERROR "OpenAPI file does not exist: ${_openapi_file}")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_db_action_validate_migration_dir_name migration_dir)
|
||||||
|
_cppbessot_db_action_validate_basename(
|
||||||
|
"${migration_dir}"
|
||||||
|
"Migration directory name"
|
||||||
|
"CPPBESSOT_WORKDIR/migrations")
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_db_action_get_migration_dir_path out_var migration_dir)
|
||||||
|
cppbessot_db_action_validate_migration_dir_name("${migration_dir}")
|
||||||
|
cppbessot_db_action_resolve_project_path(_workdir "${CPPBESSOT_WORKDIR}")
|
||||||
|
set(${out_var} "${_workdir}/migrations/${migration_dir}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_db_action_assert_migration_dir_exists migration_dir)
|
||||||
|
cppbessot_db_action_get_migration_dir_path(_migration_dir_path "${migration_dir}")
|
||||||
|
if(NOT IS_DIRECTORY "${_migration_dir_path}")
|
||||||
|
message(FATAL_ERROR "Migration directory does not exist: ${_migration_dir_path}")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_db_action_validate_db_target db_target)
|
||||||
|
_cppbessot_db_action_validate_db_target_impl("${db_target}")
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_db_action_backend_subdir out_var backend)
|
||||||
|
if("${backend}" STREQUAL "sqlite")
|
||||||
|
set(${out_var} "sqlite" PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if("${backend}" STREQUAL "postgre")
|
||||||
|
set(${out_var} "postgre" PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(FATAL_ERROR "Unsupported backend `${backend}`.")
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_db_action_collect_nonempty_sql_files out_var sql_dir)
|
||||||
|
if(NOT IS_DIRECTORY "${sql_dir}")
|
||||||
|
set(${out_var} "" PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
file(GLOB _candidate_files "${sql_dir}/*.sql")
|
||||||
|
list(SORT _candidate_files)
|
||||||
|
|
||||||
|
set(_sql_files)
|
||||||
|
foreach(_candidate IN LISTS _candidate_files)
|
||||||
|
file(READ "${_candidate}" _contents)
|
||||||
|
string(STRIP "${_contents}" _trimmed)
|
||||||
|
if(NOT "${_trimmed}" STREQUAL "")
|
||||||
|
list(APPEND _sql_files "${_candidate}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
set(${out_var} "${_sql_files}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_db_action_require_nonempty_sql_dir sql_dir failure_prefix)
|
||||||
|
cppbessot_db_action_collect_nonempty_sql_files(_sql_files "${sql_dir}")
|
||||||
|
if(NOT _sql_files)
|
||||||
|
message(FATAL_ERROR "${failure_prefix}: no non-empty SQL files found under ${sql_dir}")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_db_action_find_program_or_fail out_var program_name hint)
|
||||||
|
find_program(_program "${program_name}")
|
||||||
|
if(NOT _program)
|
||||||
|
message(FATAL_ERROR "Missing required program `${program_name}`. ${hint}")
|
||||||
|
endif()
|
||||||
|
set(${out_var} "${_program}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
function(cppbessot_db_action_reset_sqlite_db sqlite_path)
|
||||||
|
if(EXISTS "${sqlite_path}")
|
||||||
|
file(REMOVE "${sqlite_path}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
get_filename_component(_sqlite_parent "${sqlite_path}" DIRECTORY)
|
||||||
|
if(NOT "${_sqlite_parent}" STREQUAL "")
|
||||||
|
file(MAKE_DIRECTORY "${_sqlite_parent}")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_db_action_apply_sqlite_files sqlite_path)
|
||||||
|
set(_sql_files "${ARGN}")
|
||||||
|
if(NOT _sql_files)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
cppbessot_db_action_find_program_or_fail(_sqlite3 sqlite3
|
||||||
|
"SQLite live actions require the `sqlite3` CLI to be available in PATH.")
|
||||||
|
|
||||||
|
foreach(_sql_file IN LISTS _sql_files)
|
||||||
|
string(REPLACE "\"" "\\\"" _sqlite_read_file "${_sql_file}")
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${_sqlite3}" "${sqlite_path}" ".read \"${_sqlite_read_file}\""
|
||||||
|
RESULT_VARIABLE _result
|
||||||
|
OUTPUT_VARIABLE _stdout
|
||||||
|
ERROR_VARIABLE _stderr
|
||||||
|
)
|
||||||
|
|
||||||
|
if(NOT _result EQUAL 0)
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"SQLite SQL apply failed for `${_sql_file}` against `${sqlite_path}`.\n${_stdout}\n${_stderr}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_db_action_reset_pgsql_schema pgsql_connstr)
|
||||||
|
cppbessot_db_action_find_program_or_fail(_psql psql
|
||||||
|
"PostgreSQL live actions require `psql` to be available in PATH.")
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${_psql}" "${pgsql_connstr}" -v ON_ERROR_STOP=1
|
||||||
|
-c "DROP SCHEMA IF EXISTS public CASCADE; CREATE SCHEMA public;"
|
||||||
|
RESULT_VARIABLE _result
|
||||||
|
OUTPUT_VARIABLE _stdout
|
||||||
|
ERROR_VARIABLE _stderr
|
||||||
|
)
|
||||||
|
|
||||||
|
if(NOT _result EQUAL 0)
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"PostgreSQL schema reset failed.\n${_stdout}\n${_stderr}")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_db_action_apply_pgsql_files pgsql_connstr)
|
||||||
|
set(_sql_files "${ARGN}")
|
||||||
|
if(NOT _sql_files)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
cppbessot_db_action_find_program_or_fail(_psql psql
|
||||||
|
"PostgreSQL live actions require `psql` to be available in PATH.")
|
||||||
|
|
||||||
|
foreach(_sql_file IN LISTS _sql_files)
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${_psql}" "${pgsql_connstr}" -v ON_ERROR_STOP=1 -f "${_sql_file}"
|
||||||
|
RESULT_VARIABLE _result
|
||||||
|
OUTPUT_VARIABLE _stdout
|
||||||
|
ERROR_VARIABLE _stderr
|
||||||
|
)
|
||||||
|
|
||||||
|
if(NOT _result EQUAL 0)
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"PostgreSQL SQL apply failed for `${_sql_file}`.\n${_stdout}\n${_stderr}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endfunction()
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
function(cppbessot_db_action_target_upper out_var db_target)
|
||||||
|
string(TOUPPER "${db_target}" _upper)
|
||||||
|
set(${out_var} "${_upper}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_db_action_resolve_backend_for_target
|
||||||
|
out_backend
|
||||||
|
out_sqlite_path
|
||||||
|
out_pgsql_connstr
|
||||||
|
db_target)
|
||||||
|
cppbessot_db_action_validate_db_target("${db_target}")
|
||||||
|
cppbessot_db_action_target_upper(_target_upper "${db_target}")
|
||||||
|
|
||||||
|
set(_sqlite_var "CPPBESSOT_DB_SQLITE_${_target_upper}_PATH")
|
||||||
|
set(_pgsql_var "CPPBESSOT_DB_PGSQL_${_target_upper}_CONNSTR")
|
||||||
|
|
||||||
|
set(_has_sqlite FALSE)
|
||||||
|
set(_has_pgsql FALSE)
|
||||||
|
|
||||||
|
if(DEFINED ${_sqlite_var} AND NOT "${${_sqlite_var}}" STREQUAL "")
|
||||||
|
set(_has_sqlite TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(DEFINED ${_pgsql_var} AND NOT "${${_pgsql_var}}" STREQUAL "")
|
||||||
|
set(_has_pgsql TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(_has_sqlite AND _has_pgsql)
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"DB target `${db_target}` is ambiguous: both `${_sqlite_var}` and `${_pgsql_var}` are set.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT _has_sqlite AND NOT _has_pgsql)
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"DB target `${db_target}` is not mapped: set exactly one of `${_sqlite_var}` or `${_pgsql_var}`.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(_has_sqlite)
|
||||||
|
set(${out_backend} "sqlite" PARENT_SCOPE)
|
||||||
|
set(${out_sqlite_path} "${${_sqlite_var}}" PARENT_SCOPE)
|
||||||
|
set(${out_pgsql_connstr} "" PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(${out_backend} "postgre" PARENT_SCOPE)
|
||||||
|
set(${out_sqlite_path} "" PARENT_SCOPE)
|
||||||
|
set(${out_pgsql_connstr} "${${_pgsql_var}}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/cppbessotDbActionCommon.cmake")
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/cppbessotDbActionTargetResolution.cmake")
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/cppbessotDbActionSqlApply.cmake")
|
||||||
|
|
||||||
|
cppbessot_db_action_require_var(CPPBESSOT_PROJECT_SOURCE_DIR)
|
||||||
|
cppbessot_db_action_require_var(CPPBESSOT_WORKDIR)
|
||||||
|
cppbessot_db_action_require_var(DB_CREATEFROM_SCHEMA_DIR)
|
||||||
|
cppbessot_db_action_require_var(DB_TARGET)
|
||||||
|
|
||||||
|
cppbessot_db_action_validate_db_target("${DB_TARGET}")
|
||||||
|
if("${DB_TARGET}" STREQUAL "proddev")
|
||||||
|
message(FATAL_ERROR "db_createfrom does not support DB_TARGET=proddev.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
cppbessot_db_action_assert_schema_dir_ready("${DB_CREATEFROM_SCHEMA_DIR}")
|
||||||
|
cppbessot_db_action_resolve_backend_for_target(
|
||||||
|
_backend
|
||||||
|
_sqlite_path
|
||||||
|
_pgsql_connstr
|
||||||
|
"${DB_TARGET}")
|
||||||
|
cppbessot_db_action_backend_subdir(_backend_subdir "${_backend}")
|
||||||
|
cppbessot_db_action_get_schema_dir_path(_schema_dir "${DB_CREATEFROM_SCHEMA_DIR}")
|
||||||
|
set(_ddl_dir "${_schema_dir}/generated-sql-ddl/${_backend_subdir}")
|
||||||
|
cppbessot_db_action_require_nonempty_sql_dir(
|
||||||
|
"${_ddl_dir}"
|
||||||
|
"db_createfrom cannot continue")
|
||||||
|
cppbessot_db_action_collect_nonempty_sql_files(_sql_files "${_ddl_dir}")
|
||||||
|
|
||||||
|
if("${_backend}" STREQUAL "sqlite")
|
||||||
|
cppbessot_db_action_reset_sqlite_db("${_sqlite_path}")
|
||||||
|
cppbessot_db_action_apply_sqlite_files("${_sqlite_path}" ${_sql_files})
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
cppbessot_db_action_reset_pgsql_schema("${_pgsql_connstr}")
|
||||||
|
cppbessot_db_action_apply_pgsql_files("${_pgsql_connstr}" ${_sql_files})
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/cppbessotDbActionCommon.cmake")
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/cppbessotDbActionTargetResolution.cmake")
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/cppbessotDbActionBackfill.cmake")
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/cppbessotDbActionSqlApply.cmake")
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/cppbessotDbActionClone.cmake")
|
||||||
|
|
||||||
|
cppbessot_db_action_require_var(CPPBESSOT_PROJECT_SOURCE_DIR)
|
||||||
|
cppbessot_db_action_require_var(CPPBESSOT_WORKDIR)
|
||||||
|
cppbessot_db_action_require_var(DB_MIGRATE_WITH)
|
||||||
|
cppbessot_db_action_require_var(DB_TARGET)
|
||||||
|
cppbessot_db_action_require_var(DB_SCHEMA_DIR_TO_GENERATE)
|
||||||
|
cppbessot_db_action_require_var(DB_CREATEFROM_SCHEMA_DIR)
|
||||||
|
|
||||||
|
cppbessot_db_action_validate_db_target("${DB_TARGET}")
|
||||||
|
cppbessot_db_action_assert_migration_dir_exists("${DB_MIGRATE_WITH}")
|
||||||
|
cppbessot_db_action_resolve_backend_for_target(
|
||||||
|
_backend
|
||||||
|
_sqlite_path
|
||||||
|
_pgsql_connstr
|
||||||
|
"${DB_TARGET}")
|
||||||
|
cppbessot_db_action_prepare_proddev(
|
||||||
|
"${DB_TARGET}"
|
||||||
|
"${_backend}"
|
||||||
|
"${DB_MIGRATE_PRODDEV_USE_STALE}"
|
||||||
|
"${_sqlite_path}"
|
||||||
|
"${_pgsql_connstr}")
|
||||||
|
cppbessot_db_action_backend_subdir(_backend_subdir "${_backend}")
|
||||||
|
cppbessot_db_action_get_migration_dir_path(_migration_dir "${DB_MIGRATE_WITH}")
|
||||||
|
set(_sql_dir "${_migration_dir}/${_backend_subdir}")
|
||||||
|
cppbessot_db_action_collect_nonempty_sql_files(_sql_files "${_sql_dir}")
|
||||||
|
cppbessot_db_action_get_hook_path(_pre_hook "${_migration_dir}" "pre-structural-backfill.sh")
|
||||||
|
cppbessot_db_action_get_hook_path(_post_hook "${_migration_dir}" "post-structural-backfill.sh")
|
||||||
|
|
||||||
|
cppbessot_db_action_run_hook(
|
||||||
|
"${_pre_hook}"
|
||||||
|
"${DB_TARGET}"
|
||||||
|
"${_backend}"
|
||||||
|
"${_migration_dir}"
|
||||||
|
"${DB_MIGRATE_WITH}"
|
||||||
|
"${DB_SCHEMA_DIR_TO_GENERATE}"
|
||||||
|
"${DB_CREATEFROM_SCHEMA_DIR}"
|
||||||
|
"${_sqlite_path}"
|
||||||
|
"${_pgsql_connstr}")
|
||||||
|
|
||||||
|
if(_sql_files)
|
||||||
|
if("${_backend}" STREQUAL "sqlite")
|
||||||
|
cppbessot_db_action_apply_sqlite_files("${_sqlite_path}" ${_sql_files})
|
||||||
|
else()
|
||||||
|
cppbessot_db_action_apply_pgsql_files("${_pgsql_connstr}" ${_sql_files})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
cppbessot_db_action_run_hook(
|
||||||
|
"${_post_hook}"
|
||||||
|
"${DB_TARGET}"
|
||||||
|
"${_backend}"
|
||||||
|
"${_migration_dir}"
|
||||||
|
"${DB_MIGRATE_WITH}"
|
||||||
|
"${DB_SCHEMA_DIR_TO_GENERATE}"
|
||||||
|
"${DB_CREATEFROM_SCHEMA_DIR}"
|
||||||
|
"${_sqlite_path}"
|
||||||
|
"${_pgsql_connstr}")
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
Ok. Now we need to add the concept of migration action targets. Add new vars: these control the global migration action target. These don't determine the generated source oas, or the target dir to generate that oas into. Rather, they determine the target DB to apply the current DB_SCHEMA_DIR_TO_GENERATE schema against.
|
||||||
|
|
||||||
|
The new var name is: DB_TARGET=<prod|proddev|dev>.
|
||||||
|
It's expected by the parent source dir that DB_TARGET either already is already migrated to DB_SCHEMA_DIR_TO_GENERATE; or DB_TARGET will be migrated to DB_SCHEMA_DIR_TO_GENERATE before the application is compiled and executed. It is in fact the parent application that sets DB_SCHEMA_DIR_TO_GENERATE, after all.
|
||||||
|
|
||||||
|
Prod and dev are self-sufficient targets. Migration actions applied to them are applied to them qua independent, persistent db.
|
||||||
|
* Action: target db_createfrom. Accepts option DB_CREATEFROM_SCHEMA_DIR=<schema dir>. Respects and uses CPPBESSOT_WORKDIR. Will use the pre-generated sql_ddl artifacts in <schema dir> to idempotently create a new db with the name prod or dev, depending on the value of DB_TARGET. Default ON_TARGET=dev. Default value of DB_CREATEFROM_SCHEMA_DIR is DB_SCHEMA_DIR_TO_GENERATE. Obv a non-existent DB_CREATEFROM_SCHEMA_DIR or one whose oas spec doesn't exist, will result in an abort.
|
||||||
|
|
||||||
|
Proddev is copied from prod. It is a sandbox target used to apply migrations against a clone of prod.
|
||||||
|
* Proddev does not support the db_createfrom target. It is always cloned from prod.
|
||||||
|
* Action: target db_migrate with DB_TARGET=proddev will always automatically and idempotently clone prod to a copy called "proddev", unless the DB_MIGRATE_PRODDEV_USE_STALE=ON flag is set. This flag simply means "Don't clone. Re-run the current target action against the most recent, stale cloned proddev, which is itself a prior clone of prod". Specifying DB_TARGET=proddev and running db_createfrom is illegal and should abort. Speciying DB_MIGRATE_PRODDEV_USE_STALE=ON and running target db_migrate when no current stale prod DB exists results in an abort.
|
||||||
|
|
||||||
|
Action: Target db_migrate: Option DB_TARGET=<prod|proddev|dev>. Option DB_MIGRATE_WITH=<migration from-to-dir>. If the <migration from-to-dir> doesn't exist, this aborts.
|
||||||
|
|
||||||
|
Each DB migration from-to-dir may have two shell scripts: pre-structural-backfill.sh and post-structural-backfill.sh. The db_migrate target should check to see if these scripts exist, and if the pre-structural-backfill.sh script exists, it should be executed before the structural migrations, if any. If the structural migrations generated by the db_gen_migrations have content, then they should be applied next. Then if the post-structural-backfill.sh script exists, it should be run last.
|
||||||
|
|
||||||
|
Think of as many tests as you can to give coverage of all of these new commands as well as the sqlite and pgsql variants' behaviour and write them first before implementing this plan.
|
||||||
|
|
||||||
|
Be very aggressive about splitting and isolating code into common subfunctions and modules, and reusing wherever possible. Don't duplicate code. No long-scrolling functions.
|
||||||
|
|
||||||
|
----
|
||||||
|
That sqlite_apply.py script: can it be done as a bash script instead?
|
||||||
|
I'd prefer to add the sqlite3 cli to the project's CMake find_* targets, than to add python unnecessarily.
|
||||||
|
|
||||||
@@ -6,3 +6,4 @@ endif()
|
|||||||
add_subdirectory(googletest)
|
add_subdirectory(googletest)
|
||||||
add_subdirectory(cpp-serdes)
|
add_subdirectory(cpp-serdes)
|
||||||
add_subdirectory(odb-orm)
|
add_subdirectory(odb-orm)
|
||||||
|
add_subdirectory(db-actions)
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
function(cppbessot_add_db_action_test test_name script_name)
|
||||||
|
add_test(
|
||||||
|
NAME ${test_name}
|
||||||
|
COMMAND "${CMAKE_COMMAND}"
|
||||||
|
"-DCPPBESSOT_TEST_NAME=${test_name}"
|
||||||
|
"-DCPPBESSOT_TEST_BINARY_DIR=${CMAKE_CURRENT_BINARY_DIR}"
|
||||||
|
"-DCPPBESSOT_TEST_MODULE_SOURCE_DIR=${PROJECT_SOURCE_DIR}"
|
||||||
|
-P "${CMAKE_CURRENT_SOURCE_DIR}/scripts/${script_name}")
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
cppbessot_add_db_action_test(cppbessot_db_action_invalid_target invalid_target.cmake)
|
||||||
|
cppbessot_add_db_action_test(cppbessot_db_action_missing_mapping missing_mapping.cmake)
|
||||||
|
cppbessot_add_db_action_test(cppbessot_db_action_ambiguous_mapping ambiguous_mapping.cmake)
|
||||||
|
cppbessot_add_db_action_test(cppbessot_db_action_missing_migrate_with missing_migrate_with.cmake)
|
||||||
|
cppbessot_add_db_action_test(cppbessot_db_action_missing_migration_dir missing_migration_dir.cmake)
|
||||||
|
cppbessot_add_db_action_test(cppbessot_db_action_proddev_createfrom_illegal proddev_createfrom_illegal.cmake)
|
||||||
|
cppbessot_add_db_action_test(cppbessot_db_action_sqlite_createfrom sqlite_createfrom.cmake)
|
||||||
|
cppbessot_add_db_action_test(cppbessot_db_action_sqlite_invalid_sql sqlite_invalid_sql.cmake)
|
||||||
|
cppbessot_add_db_action_test(cppbessot_db_action_sqlite_migrate sqlite_migrate.cmake)
|
||||||
|
cppbessot_add_db_action_test(cppbessot_db_action_sqlite_proddev_stale sqlite_proddev_stale.cmake)
|
||||||
|
cppbessot_add_db_action_test(cppbessot_db_action_sqlite_proddev_clone sqlite_proddev_clone.cmake)
|
||||||
|
cppbessot_add_db_action_test(cppbessot_db_action_pgsql_createfrom_mock pgsql_createfrom_mock.cmake)
|
||||||
|
cppbessot_add_db_action_test(cppbessot_db_action_pgsql_migrate_order pgsql_migrate_order.cmake)
|
||||||
|
cppbessot_add_db_action_test(cppbessot_db_action_pgsql_stale_abort pgsql_stale_abort.cmake)
|
||||||
|
cppbessot_add_db_action_test(cppbessot_db_action_backfill_env_no_structural backfill_env_no_structural.cmake)
|
||||||
|
cppbessot_add_db_action_test(cppbessot_db_action_regression regression_targets.cmake)
|
||||||
@@ -0,0 +1,244 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
function(cppbessot_test_require_var var_name)
|
||||||
|
if(NOT DEFINED ${var_name} OR "${${var_name}}" STREQUAL "")
|
||||||
|
message(FATAL_ERROR "Missing required test variable `${var_name}`.")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_test_reset_dir path)
|
||||||
|
file(REMOVE_RECURSE "${path}")
|
||||||
|
file(MAKE_DIRECTORY "${path}")
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_test_write_file path)
|
||||||
|
get_filename_component(_parent "${path}" DIRECTORY)
|
||||||
|
if(NOT "${_parent}" STREQUAL "")
|
||||||
|
file(MAKE_DIRECTORY "${_parent}")
|
||||||
|
endif()
|
||||||
|
string(JOIN "" _content ${ARGN})
|
||||||
|
file(WRITE "${path}" "${_content}")
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_test_write_shell_script path)
|
||||||
|
cppbessot_test_write_file("${path}" ${ARGN})
|
||||||
|
execute_process(COMMAND chmod +x "${path}")
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_test_case_dir out_var)
|
||||||
|
cppbessot_test_require_var(CPPBESSOT_TEST_BINARY_DIR)
|
||||||
|
cppbessot_test_require_var(CPPBESSOT_TEST_NAME)
|
||||||
|
set(_case_dir "${CPPBESSOT_TEST_BINARY_DIR}/cases/${CPPBESSOT_TEST_NAME}")
|
||||||
|
cppbessot_test_reset_dir("${_case_dir}")
|
||||||
|
set(${out_var} "${_case_dir}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_test_write_project root_dir settings_text)
|
||||||
|
cppbessot_test_require_var(CPPBESSOT_TEST_MODULE_SOURCE_DIR)
|
||||||
|
string(REPLACE "\\" "\\\\" _module_dir "${CPPBESSOT_TEST_MODULE_SOURCE_DIR}")
|
||||||
|
set(_settings_parts "${settings_text}" ${ARGN})
|
||||||
|
set(_post_include_text
|
||||||
|
"cppbessot_add_db_createfrom_target()\n"
|
||||||
|
"cppbessot_add_db_migrate_target()\n")
|
||||||
|
list(LENGTH _settings_parts _settings_len)
|
||||||
|
if(_settings_len GREATER 0)
|
||||||
|
math(EXPR _last_index "${_settings_len} - 1")
|
||||||
|
list(GET _settings_parts "${_last_index}" _last_part)
|
||||||
|
if("${_last_part}" STREQUAL "FULL_ENABLE")
|
||||||
|
list(REMOVE_AT _settings_parts "${_last_index}")
|
||||||
|
set(_post_include_text "cppbessot_enable()\n")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
string(JOIN "" _settings_text ${_settings_parts})
|
||||||
|
cppbessot_test_write_file(
|
||||||
|
"${root_dir}/CMakeLists.txt"
|
||||||
|
"cmake_minimum_required(VERSION 3.20)\n"
|
||||||
|
"project(cppbessot_db_action_fixture LANGUAGES CXX)\n"
|
||||||
|
"set(CPPBESSOT_WORKDIR \"db\" CACHE STRING \"\")\n"
|
||||||
|
"set(DB_SCHEMA_DIR_TO_GENERATE \"v1.1\" CACHE STRING \"\")\n"
|
||||||
|
"set(CPPBESSOT_AUTO_ENABLE OFF CACHE BOOL \"\")\n"
|
||||||
|
"${_settings_text}\n"
|
||||||
|
"include(\"${_module_dir}/cmake/CppBeSSOT.cmake\")\n"
|
||||||
|
"${_post_include_text}")
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_test_add_schema root_dir schema_dir)
|
||||||
|
cppbessot_test_write_file(
|
||||||
|
"${root_dir}/db/${schema_dir}/openapi/openapi.yaml"
|
||||||
|
"openapi: 3.0.0\n"
|
||||||
|
"info:\n"
|
||||||
|
" title: test-${schema_dir}\n"
|
||||||
|
" version: 1.0.0\n"
|
||||||
|
"paths: {}\n"
|
||||||
|
"components:\n"
|
||||||
|
" schemas:\n"
|
||||||
|
" Agent:\n"
|
||||||
|
" type: object\n"
|
||||||
|
" properties:\n"
|
||||||
|
" id:\n"
|
||||||
|
" type: string\n")
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_test_add_sql_file path content)
|
||||||
|
cppbessot_test_write_file("${path}" "${content}")
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_test_configure_project root_dir build_dir result_var stdout_var stderr_var)
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -S "${root_dir}" -B "${build_dir}"
|
||||||
|
RESULT_VARIABLE _result
|
||||||
|
OUTPUT_VARIABLE _stdout
|
||||||
|
ERROR_VARIABLE _stderr
|
||||||
|
)
|
||||||
|
set(${result_var} "${_result}" PARENT_SCOPE)
|
||||||
|
set(${stdout_var} "${_stdout}" PARENT_SCOPE)
|
||||||
|
set(${stderr_var} "${_stderr}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_test_build_target build_dir target_name result_var stdout_var stderr_var)
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${CMAKE_COMMAND}" --build "${build_dir}" --target "${target_name}"
|
||||||
|
RESULT_VARIABLE _result
|
||||||
|
OUTPUT_VARIABLE _stdout
|
||||||
|
ERROR_VARIABLE _stderr
|
||||||
|
)
|
||||||
|
set(${result_var} "${_result}" PARENT_SCOPE)
|
||||||
|
set(${stdout_var} "${_stdout}" PARENT_SCOPE)
|
||||||
|
set(${stderr_var} "${_stderr}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_test_build_target_dry_run build_dir target_name result_var stdout_var stderr_var)
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${CMAKE_COMMAND}" --build "${build_dir}" --target "${target_name}" -- -n
|
||||||
|
RESULT_VARIABLE _result
|
||||||
|
OUTPUT_VARIABLE _stdout
|
||||||
|
ERROR_VARIABLE _stderr
|
||||||
|
)
|
||||||
|
set(${result_var} "${_result}" PARENT_SCOPE)
|
||||||
|
set(${stdout_var} "${_stdout}" PARENT_SCOPE)
|
||||||
|
set(${stderr_var} "${_stderr}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_test_assert_success result stderr context)
|
||||||
|
if(NOT "${result}" STREQUAL "0")
|
||||||
|
message(FATAL_ERROR "${context} unexpectedly failed.\n${stderr}")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_test_assert_failure_contains result stderr needle)
|
||||||
|
if("${result}" STREQUAL "0")
|
||||||
|
message(FATAL_ERROR "Expected failure containing `${needle}`, but command succeeded.")
|
||||||
|
endif()
|
||||||
|
string(FIND "${stderr}" "${needle}" _match_index)
|
||||||
|
if(_match_index EQUAL -1)
|
||||||
|
message(FATAL_ERROR "Expected failure containing `${needle}`.\nActual stderr:\n${stderr}")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_test_assert_contains haystack needle context)
|
||||||
|
string(FIND "${haystack}" "${needle}" _match_index)
|
||||||
|
if(_match_index EQUAL -1)
|
||||||
|
message(FATAL_ERROR "${context}: expected to find `${needle}` in:\n${haystack}")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_test_assert_file_exists path)
|
||||||
|
if(NOT EXISTS "${path}")
|
||||||
|
message(FATAL_ERROR "Expected file to exist: ${path}")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_test_set_path_with_tool_dir tool_dir)
|
||||||
|
if(DEFINED ENV{PATH} AND NOT "$ENV{PATH}" STREQUAL "")
|
||||||
|
set(ENV{PATH} "${tool_dir}:$ENV{PATH}")
|
||||||
|
else()
|
||||||
|
set(ENV{PATH} "${tool_dir}")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_test_sqlite_exec db_path sql_text)
|
||||||
|
find_program(_sqlite3 sqlite3 REQUIRED)
|
||||||
|
get_filename_component(_parent "${db_path}" DIRECTORY)
|
||||||
|
if(NOT "${_parent}" STREQUAL "")
|
||||||
|
file(MAKE_DIRECTORY "${_parent}")
|
||||||
|
endif()
|
||||||
|
set(_sql_file "${CMAKE_CURRENT_BINARY_DIR}/cppbessot-test-sqlite-exec.sql")
|
||||||
|
file(WRITE "${_sql_file}" "${sql_text}")
|
||||||
|
string(REPLACE "\"" "\\\"" _sqlite_read_file "${_sql_file}")
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${_sqlite3}" "${db_path}" ".read \"${_sqlite_read_file}\""
|
||||||
|
RESULT_VARIABLE _result
|
||||||
|
ERROR_VARIABLE _stderr
|
||||||
|
)
|
||||||
|
file(REMOVE "${_sql_file}")
|
||||||
|
if(NOT _result EQUAL 0)
|
||||||
|
message(FATAL_ERROR "Failed to execute SQLite SQL.\n${_stderr}")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_test_sqlite_query_scalar out_var db_path query)
|
||||||
|
find_program(_sqlite3 sqlite3 REQUIRED)
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${_sqlite3}" -batch -noheader "${db_path}" "${query}"
|
||||||
|
RESULT_VARIABLE _result
|
||||||
|
OUTPUT_VARIABLE _stdout
|
||||||
|
ERROR_VARIABLE _stderr
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
if(NOT _result EQUAL 0)
|
||||||
|
message(FATAL_ERROR "Failed SQLite query.\n${_stderr}")
|
||||||
|
endif()
|
||||||
|
set(${out_var} "${_stdout}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_test_write_mock_psql path)
|
||||||
|
cppbessot_test_write_shell_script(
|
||||||
|
"${path}"
|
||||||
|
"#!/bin/sh\n"
|
||||||
|
"set -eu\n"
|
||||||
|
"log_file=\"${CPPBESSOT_TEST_LOG}\"\n"
|
||||||
|
"conn=\"$1\"\n"
|
||||||
|
"shift\n"
|
||||||
|
"printf 'conn:%s\\n' \"$conn\" >> \"$log_file\"\n"
|
||||||
|
"if [ \"\${CPPBESSOT_TEST_PSQL_FAIL_SELECT:-0}\" = \"1\" ]\n"
|
||||||
|
"then\n"
|
||||||
|
" if printf '%s ' \"$@\" | grep -F \"SELECT 1\" >/dev/null 2>&1\n"
|
||||||
|
" then\n"
|
||||||
|
" echo 'simulated select failure' >&2\n"
|
||||||
|
" exit 1\n"
|
||||||
|
" fi\n"
|
||||||
|
"fi\n"
|
||||||
|
"if [ \"\${CPPBESSOT_TEST_PSQL_FAIL_ALL:-0}\" = \"1\" ]\n"
|
||||||
|
"then\n"
|
||||||
|
" echo 'simulated psql failure' >&2\n"
|
||||||
|
" exit 1\n"
|
||||||
|
"fi\n"
|
||||||
|
"while [ \"$#\" -gt 0 ]\n"
|
||||||
|
"do\n"
|
||||||
|
" if [ \"$1\" = \"-c\" ]\n"
|
||||||
|
" then\n"
|
||||||
|
" shift\n"
|
||||||
|
" printf 'sqlcmd:%s\\n' \"$1\" >> \"$log_file\"\n"
|
||||||
|
" elif [ \"$1\" = \"-f\" ]\n"
|
||||||
|
" then\n"
|
||||||
|
" shift\n"
|
||||||
|
" printf 'sqlfile:%s\\n' \"$(basename \"$1\")\" >> \"$log_file\"\n"
|
||||||
|
" fi\n"
|
||||||
|
" shift\n"
|
||||||
|
"done\n")
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(cppbessot_test_assert_log_order log_path)
|
||||||
|
file(READ "${log_path}" _contents)
|
||||||
|
set(_cursor -1)
|
||||||
|
foreach(_needle IN LISTS ARGN)
|
||||||
|
string(FIND "${_contents}" "${_needle}" _index)
|
||||||
|
if(_index EQUAL -1)
|
||||||
|
message(FATAL_ERROR "Missing log entry `${_needle}`.\nLog contents:\n${_contents}")
|
||||||
|
endif()
|
||||||
|
if(_index LESS_EQUAL _cursor)
|
||||||
|
message(FATAL_ERROR "Log entry `${_needle}` appeared out of order.\nLog contents:\n${_contents}")
|
||||||
|
endif()
|
||||||
|
set(_cursor "${_index}")
|
||||||
|
endforeach()
|
||||||
|
endfunction()
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/../cmake/TestCommon.cmake")
|
||||||
|
|
||||||
|
cppbessot_test_case_dir(_case_dir)
|
||||||
|
cppbessot_test_write_project(
|
||||||
|
"${_case_dir}"
|
||||||
|
"set(CPPBESSOT_DB_SQLITE_DEV_PATH \"${_case_dir}/live/dev.sqlite\" CACHE STRING \"\")\n"
|
||||||
|
"set(CPPBESSOT_DB_PGSQL_DEV_CONNSTR \"dbname=test\" CACHE STRING \"\")\n")
|
||||||
|
cppbessot_test_add_schema("${_case_dir}" "v1.1")
|
||||||
|
cppbessot_test_add_sql_file("${_case_dir}/db/v1.1/generated-sql-ddl/sqlite/01-schema.sql"
|
||||||
|
"CREATE TABLE sample(id TEXT);\n")
|
||||||
|
|
||||||
|
cppbessot_test_configure_project("${_case_dir}" "${_case_dir}/build" _cfg_result _cfg_stdout _cfg_stderr)
|
||||||
|
cppbessot_test_assert_success("${_cfg_result}" "${_cfg_stderr}" "fixture configure")
|
||||||
|
cppbessot_test_build_target("${_case_dir}/build" "db_createfrom" _build_result _build_stdout _build_stderr)
|
||||||
|
cppbessot_test_assert_failure_contains("${_build_result}" "${_build_stderr}" "is ambiguous")
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/../cmake/TestCommon.cmake")
|
||||||
|
|
||||||
|
cppbessot_test_case_dir(_case_dir)
|
||||||
|
set(_log_file "${_case_dir}/events.log")
|
||||||
|
cppbessot_test_write_file("${_log_file}" "")
|
||||||
|
|
||||||
|
cppbessot_test_write_project(
|
||||||
|
"${_case_dir}"
|
||||||
|
"set(DB_MIGRATE_WITH \"v1.0-v1.1\" CACHE STRING \"\")\n"
|
||||||
|
"set(CPPBESSOT_DB_SQLITE_DEV_PATH \"${_case_dir}/live/dev.sqlite\" CACHE STRING \"\")\n")
|
||||||
|
cppbessot_test_add_schema("${_case_dir}" "v1.1")
|
||||||
|
cppbessot_test_write_shell_script(
|
||||||
|
"${_case_dir}/db/migrations/v1.0-v1.1/pre-structural-backfill.sh"
|
||||||
|
"#!/bin/sh\n"
|
||||||
|
"set -eu\n"
|
||||||
|
"printf 'pre:%s:%s:%s:%s\\n' \"$CPPBESSOT_DB_TARGET\" \"$CPPBESSOT_DB_BACKEND\" \"$CPPBESSOT_DB_MIGRATE_WITH\" \"$CPPBESSOT_DB_SCHEMA_DIR_TO_GENERATE\" >> \"${_log_file}\"\n"
|
||||||
|
"printf 'sqlite:%s\\n' \"$CPPBESSOT_DB_SQLITE_PATH\" >> \"${_log_file}\"\n")
|
||||||
|
cppbessot_test_write_shell_script(
|
||||||
|
"${_case_dir}/db/migrations/v1.0-v1.1/post-structural-backfill.sh"
|
||||||
|
"#!/bin/sh\n"
|
||||||
|
"set -eu\n"
|
||||||
|
"printf 'post:%s\\n' \"$CPPBESSOT_DB_CREATEFROM_SCHEMA_DIR\" >> \"${_log_file}\"\n")
|
||||||
|
|
||||||
|
cppbessot_test_configure_project("${_case_dir}" "${_case_dir}/build" _cfg_result _cfg_stdout _cfg_stderr)
|
||||||
|
cppbessot_test_assert_success("${_cfg_result}" "${_cfg_stderr}" "fixture configure")
|
||||||
|
cppbessot_test_build_target("${_case_dir}/build" "db_migrate" _build_result _build_stdout _build_stderr)
|
||||||
|
cppbessot_test_assert_success("${_build_result}" "${_build_stderr}" "db_migrate hook-only")
|
||||||
|
cppbessot_test_assert_log_order("${_log_file}" "pre:dev:sqlite:v1.0-v1.1:v1.1" "sqlite:${_case_dir}/live/dev.sqlite" "post:v1.1")
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/../cmake/TestCommon.cmake")
|
||||||
|
|
||||||
|
cppbessot_test_case_dir(_case_dir)
|
||||||
|
cppbessot_test_write_project(
|
||||||
|
"${_case_dir}"
|
||||||
|
"set(DB_TARGET \"bogus\" CACHE STRING \"\")\n"
|
||||||
|
"set(CPPBESSOT_DB_SQLITE_DEV_PATH \"${_case_dir}/live/dev.sqlite\" CACHE STRING \"\")\n")
|
||||||
|
cppbessot_test_add_schema("${_case_dir}" "v1.1")
|
||||||
|
cppbessot_test_add_sql_file("${_case_dir}/db/v1.1/generated-sql-ddl/sqlite/01-schema.sql"
|
||||||
|
"CREATE TABLE sample(id TEXT);\n")
|
||||||
|
|
||||||
|
cppbessot_test_configure_project("${_case_dir}" "${_case_dir}/build" _cfg_result _cfg_stdout _cfg_stderr)
|
||||||
|
cppbessot_test_assert_success("${_cfg_result}" "${_cfg_stderr}" "fixture configure")
|
||||||
|
cppbessot_test_build_target("${_case_dir}/build" "db_createfrom" _build_result _build_stdout _build_stderr)
|
||||||
|
cppbessot_test_assert_failure_contains("${_build_result}" "${_build_stderr}" "DB_TARGET must be one of")
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/../cmake/TestCommon.cmake")
|
||||||
|
|
||||||
|
cppbessot_test_case_dir(_case_dir)
|
||||||
|
cppbessot_test_write_project("${_case_dir}" "")
|
||||||
|
cppbessot_test_add_schema("${_case_dir}" "v1.1")
|
||||||
|
cppbessot_test_add_sql_file("${_case_dir}/db/v1.1/generated-sql-ddl/sqlite/01-schema.sql"
|
||||||
|
"CREATE TABLE sample(id TEXT);\n")
|
||||||
|
|
||||||
|
cppbessot_test_configure_project("${_case_dir}" "${_case_dir}/build" _cfg_result _cfg_stdout _cfg_stderr)
|
||||||
|
cppbessot_test_assert_success("${_cfg_result}" "${_cfg_stderr}" "fixture configure")
|
||||||
|
cppbessot_test_build_target("${_case_dir}/build" "db_createfrom" _build_result _build_stdout _build_stderr)
|
||||||
|
cppbessot_test_assert_failure_contains("${_build_result}" "${_build_stderr}" "is not mapped")
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/../cmake/TestCommon.cmake")
|
||||||
|
|
||||||
|
cppbessot_test_case_dir(_case_dir)
|
||||||
|
cppbessot_test_write_project(
|
||||||
|
"${_case_dir}"
|
||||||
|
"set(CPPBESSOT_DB_SQLITE_DEV_PATH \"${_case_dir}/live/dev.sqlite\" CACHE STRING \"\")\n")
|
||||||
|
cppbessot_test_add_schema("${_case_dir}" "v1.1")
|
||||||
|
|
||||||
|
cppbessot_test_configure_project("${_case_dir}" "${_case_dir}/build" _cfg_result _cfg_stdout _cfg_stderr)
|
||||||
|
cppbessot_test_assert_success("${_cfg_result}" "${_cfg_stderr}" "fixture configure")
|
||||||
|
cppbessot_test_build_target("${_case_dir}/build" "db_migrate" _build_result _build_stdout _build_stderr)
|
||||||
|
cppbessot_test_assert_failure_contains("${_build_result}" "${_build_stderr}" "Required variable `DB_MIGRATE_WITH` is missing")
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/../cmake/TestCommon.cmake")
|
||||||
|
|
||||||
|
cppbessot_test_case_dir(_case_dir)
|
||||||
|
cppbessot_test_write_project(
|
||||||
|
"${_case_dir}"
|
||||||
|
"set(DB_MIGRATE_WITH \"v1.0-v1.1\" CACHE STRING \"\")\n"
|
||||||
|
"set(CPPBESSOT_DB_SQLITE_DEV_PATH \"${_case_dir}/live/dev.sqlite\" CACHE STRING \"\")\n")
|
||||||
|
cppbessot_test_add_schema("${_case_dir}" "v1.1")
|
||||||
|
|
||||||
|
cppbessot_test_configure_project("${_case_dir}" "${_case_dir}/build" _cfg_result _cfg_stdout _cfg_stderr)
|
||||||
|
cppbessot_test_assert_success("${_cfg_result}" "${_cfg_stderr}" "fixture configure")
|
||||||
|
cppbessot_test_build_target("${_case_dir}/build" "db_migrate" _build_result _build_stdout _build_stderr)
|
||||||
|
cppbessot_test_assert_failure_contains("${_build_result}" "${_build_stderr}" "Migration directory does not exist")
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/../cmake/TestCommon.cmake")
|
||||||
|
|
||||||
|
cppbessot_test_case_dir(_case_dir)
|
||||||
|
set(_tool_dir "${_case_dir}/tools")
|
||||||
|
set(_log_file "${_case_dir}/psql.log")
|
||||||
|
set(CPPBESSOT_TEST_LOG "${_log_file}")
|
||||||
|
cppbessot_test_write_file("${_log_file}" "")
|
||||||
|
cppbessot_test_write_mock_psql("${_tool_dir}/psql")
|
||||||
|
cppbessot_test_set_path_with_tool_dir("${_tool_dir}")
|
||||||
|
set(ENV{CPPBESSOT_TEST_LOG} "${_log_file}")
|
||||||
|
set(ENV{CPPBESSOT_TEST_PSQL_FAIL_ALL} "0")
|
||||||
|
set(ENV{CPPBESSOT_TEST_PSQL_FAIL_SELECT} "0")
|
||||||
|
|
||||||
|
cppbessot_test_write_project(
|
||||||
|
"${_case_dir}"
|
||||||
|
"set(CPPBESSOT_DB_PGSQL_DEV_CONNSTR \"dbname=dev_db\" CACHE STRING \"\")\n")
|
||||||
|
cppbessot_test_add_schema("${_case_dir}" "v1.1")
|
||||||
|
cppbessot_test_add_sql_file("${_case_dir}/db/v1.1/generated-sql-ddl/postgre/01-schema.sql"
|
||||||
|
"CREATE TABLE sample(id TEXT PRIMARY KEY);\n")
|
||||||
|
cppbessot_test_add_sql_file("${_case_dir}/db/v1.1/generated-sql-ddl/postgre/02-seed.sql"
|
||||||
|
"INSERT INTO sample(id) VALUES ('row-1');\n")
|
||||||
|
|
||||||
|
cppbessot_test_configure_project("${_case_dir}" "${_case_dir}/build" _cfg_result _cfg_stdout _cfg_stderr)
|
||||||
|
cppbessot_test_assert_success("${_cfg_result}" "${_cfg_stderr}" "fixture configure")
|
||||||
|
cppbessot_test_build_target("${_case_dir}/build" "db_createfrom" _build_result _build_stdout _build_stderr)
|
||||||
|
cppbessot_test_assert_success("${_build_result}" "${_build_stderr}" "db_createfrom pgsql mock")
|
||||||
|
|
||||||
|
file(READ "${_log_file}" _log_contents)
|
||||||
|
cppbessot_test_assert_contains("${_log_contents}" "sqlcmd:DROP SCHEMA IF EXISTS public CASCADE; CREATE SCHEMA public;" "pgsql reset log")
|
||||||
|
cppbessot_test_assert_contains("${_log_contents}" "sqlfile:01-schema.sql" "pgsql schema log")
|
||||||
|
cppbessot_test_assert_contains("${_log_contents}" "sqlfile:02-seed.sql" "pgsql seed log")
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/../cmake/TestCommon.cmake")
|
||||||
|
|
||||||
|
cppbessot_test_case_dir(_case_dir)
|
||||||
|
set(_tool_dir "${_case_dir}/tools")
|
||||||
|
set(_log_file "${_case_dir}/events.log")
|
||||||
|
set(CPPBESSOT_TEST_LOG "${_log_file}")
|
||||||
|
cppbessot_test_write_file("${_log_file}" "")
|
||||||
|
cppbessot_test_write_mock_psql("${_tool_dir}/psql")
|
||||||
|
cppbessot_test_set_path_with_tool_dir("${_tool_dir}")
|
||||||
|
set(ENV{CPPBESSOT_TEST_LOG} "${_log_file}")
|
||||||
|
set(ENV{CPPBESSOT_TEST_PSQL_FAIL_ALL} "0")
|
||||||
|
set(ENV{CPPBESSOT_TEST_PSQL_FAIL_SELECT} "0")
|
||||||
|
|
||||||
|
cppbessot_test_write_project(
|
||||||
|
"${_case_dir}"
|
||||||
|
"set(DB_TARGET \"proddev\" CACHE STRING \"\")\n"
|
||||||
|
"set(DB_MIGRATE_WITH \"v1.0-v1.1\" CACHE STRING \"\")\n"
|
||||||
|
"set(CPPBESSOT_DB_PGSQL_PRODDEV_CONNSTR \"dbname=proddev_db\" CACHE STRING \"\")\n"
|
||||||
|
"set(CPPBESSOT_DB_PGSQL_CLONE_PROD_TO_PRODDEV_COMMAND \"printf 'clone\\\\n' >> '${_log_file}'\" CACHE STRING \"\")\n")
|
||||||
|
cppbessot_test_add_schema("${_case_dir}" "v1.1")
|
||||||
|
cppbessot_test_write_shell_script(
|
||||||
|
"${_case_dir}/db/migrations/v1.0-v1.1/pre-structural-backfill.sh"
|
||||||
|
"#!/bin/sh\nset -eu\nprintf 'pre\\n' >> \"$CPPBESSOT_TEST_LOG\"\n")
|
||||||
|
cppbessot_test_write_shell_script(
|
||||||
|
"${_case_dir}/db/migrations/v1.0-v1.1/post-structural-backfill.sh"
|
||||||
|
"#!/bin/sh\nset -eu\nprintf 'post\\n' >> \"$CPPBESSOT_TEST_LOG\"\n")
|
||||||
|
cppbessot_test_add_sql_file("${_case_dir}/db/migrations/v1.0-v1.1/postgre/01-migrate.sql"
|
||||||
|
"ALTER TABLE sample ADD COLUMN note TEXT;\n")
|
||||||
|
|
||||||
|
cppbessot_test_configure_project("${_case_dir}" "${_case_dir}/build" _cfg_result _cfg_stdout _cfg_stderr)
|
||||||
|
cppbessot_test_assert_success("${_cfg_result}" "${_cfg_stderr}" "fixture configure")
|
||||||
|
cppbessot_test_build_target("${_case_dir}/build" "db_migrate" _build_result _build_stdout _build_stderr)
|
||||||
|
cppbessot_test_assert_success("${_build_result}" "${_build_stderr}" "db_migrate pgsql order")
|
||||||
|
cppbessot_test_assert_log_order("${_log_file}" "clone" "pre" "sqlfile:01-migrate.sql" "post")
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/../cmake/TestCommon.cmake")
|
||||||
|
|
||||||
|
cppbessot_test_case_dir(_case_dir)
|
||||||
|
set(_tool_dir "${_case_dir}/tools")
|
||||||
|
set(_log_file "${_case_dir}/psql.log")
|
||||||
|
set(CPPBESSOT_TEST_LOG "${_log_file}")
|
||||||
|
cppbessot_test_write_file("${_log_file}" "")
|
||||||
|
cppbessot_test_write_mock_psql("${_tool_dir}/psql")
|
||||||
|
cppbessot_test_set_path_with_tool_dir("${_tool_dir}")
|
||||||
|
set(ENV{CPPBESSOT_TEST_LOG} "${_log_file}")
|
||||||
|
set(ENV{CPPBESSOT_TEST_PSQL_FAIL_SELECT} "1")
|
||||||
|
set(ENV{CPPBESSOT_TEST_PSQL_FAIL_ALL} "0")
|
||||||
|
|
||||||
|
cppbessot_test_write_project(
|
||||||
|
"${_case_dir}"
|
||||||
|
"set(DB_TARGET \"proddev\" CACHE STRING \"\")\n"
|
||||||
|
"set(DB_MIGRATE_WITH \"v1.0-v1.1\" CACHE STRING \"\")\n"
|
||||||
|
"set(DB_MIGRATE_PRODDEV_USE_STALE ON CACHE BOOL \"\")\n"
|
||||||
|
"set(CPPBESSOT_DB_PGSQL_PRODDEV_CONNSTR \"dbname=proddev_db\" CACHE STRING \"\")\n")
|
||||||
|
cppbessot_test_add_schema("${_case_dir}" "v1.1")
|
||||||
|
cppbessot_test_add_sql_file("${_case_dir}/db/migrations/v1.0-v1.1/postgre/01-migrate.sql"
|
||||||
|
"ALTER TABLE sample ADD COLUMN note TEXT;\n")
|
||||||
|
|
||||||
|
cppbessot_test_configure_project("${_case_dir}" "${_case_dir}/build" _cfg_result _cfg_stdout _cfg_stderr)
|
||||||
|
cppbessot_test_assert_success("${_cfg_result}" "${_cfg_stderr}" "fixture configure")
|
||||||
|
cppbessot_test_build_target("${_case_dir}/build" "db_migrate" _build_result _build_stdout _build_stderr)
|
||||||
|
cppbessot_test_assert_failure_contains("${_build_result}" "${_build_stderr}" "no current stale proddev target")
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/../cmake/TestCommon.cmake")
|
||||||
|
|
||||||
|
cppbessot_test_case_dir(_case_dir)
|
||||||
|
cppbessot_test_write_project(
|
||||||
|
"${_case_dir}"
|
||||||
|
"set(DB_TARGET \"proddev\" CACHE STRING \"\")\n"
|
||||||
|
"set(CPPBESSOT_DB_SQLITE_PRODDEV_PATH \"${_case_dir}/live/proddev.sqlite\" CACHE STRING \"\")\n")
|
||||||
|
cppbessot_test_add_schema("${_case_dir}" "v1.1")
|
||||||
|
cppbessot_test_add_sql_file("${_case_dir}/db/v1.1/generated-sql-ddl/sqlite/01-schema.sql"
|
||||||
|
"CREATE TABLE sample(id TEXT);\n")
|
||||||
|
|
||||||
|
cppbessot_test_configure_project("${_case_dir}" "${_case_dir}/build" _cfg_result _cfg_stdout _cfg_stderr)
|
||||||
|
cppbessot_test_assert_success("${_cfg_result}" "${_cfg_stderr}" "fixture configure")
|
||||||
|
cppbessot_test_build_target("${_case_dir}/build" "db_createfrom" _build_result _build_stdout _build_stderr)
|
||||||
|
cppbessot_test_assert_failure_contains("${_build_result}" "${_build_stderr}" "does not support DB_TARGET=proddev")
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/../cmake/TestCommon.cmake")
|
||||||
|
|
||||||
|
cppbessot_test_require_var(CPPBESSOT_TEST_BINARY_DIR)
|
||||||
|
cppbessot_test_require_var(CPPBESSOT_TEST_MODULE_SOURCE_DIR)
|
||||||
|
set(_build_dir "${CPPBESSOT_TEST_BINARY_DIR}/regression-build")
|
||||||
|
cppbessot_test_reset_dir("${_build_dir}")
|
||||||
|
get_filename_component(_repo_root "${CPPBESSOT_TEST_MODULE_SOURCE_DIR}/../.." ABSOLUTE)
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${CMAKE_COMMAND}"
|
||||||
|
-S "${_repo_root}"
|
||||||
|
-B "${_build_dir}"
|
||||||
|
-DDB_SCHEMA_DIR_TO_GENERATE=v1.1
|
||||||
|
-DDB_SCHEMA_DIR_MIGRATION_FROM=v1.1
|
||||||
|
-DDB_SCHEMA_DIR_MIGRATION_TO=v1.2
|
||||||
|
-DCPPBESSOT_AUTO_ENABLE=ON
|
||||||
|
RESULT_VARIABLE _cfg_result
|
||||||
|
OUTPUT_VARIABLE _cfg_stdout
|
||||||
|
ERROR_VARIABLE _cfg_stderr
|
||||||
|
)
|
||||||
|
cppbessot_test_assert_success("${_cfg_result}" "${_cfg_stderr}" "fixture configure")
|
||||||
|
cppbessot_test_build_target_dry_run("${_build_dir}" "cppBeSsotOpenAiModelGen" _model_result _model_stdout _model_stderr)
|
||||||
|
cppbessot_test_assert_success("${_model_result}" "${_model_stderr}" "dry-run openai model lib build")
|
||||||
|
cppbessot_test_build_target_dry_run("${_build_dir}" "db_gen_migrations" _mig_result _mig_stdout _mig_stderr)
|
||||||
|
cppbessot_test_assert_success("${_mig_result}" "${_mig_stderr}" "dry-run migration generation build")
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/../cmake/TestCommon.cmake")
|
||||||
|
|
||||||
|
cppbessot_test_case_dir(_case_dir)
|
||||||
|
set(_db_path "${_case_dir}/live/dev.sqlite")
|
||||||
|
cppbessot_test_write_project(
|
||||||
|
"${_case_dir}"
|
||||||
|
"set(CPPBESSOT_DB_SQLITE_DEV_PATH \"${_db_path}\" CACHE STRING \"\")\n")
|
||||||
|
cppbessot_test_add_schema("${_case_dir}" "v1.1")
|
||||||
|
cppbessot_test_add_sql_file("${_case_dir}/db/v1.1/generated-sql-ddl/sqlite/01-schema.sql"
|
||||||
|
"CREATE TABLE sample(id TEXT PRIMARY KEY, note TEXT);\n")
|
||||||
|
cppbessot_test_add_sql_file("${_case_dir}/db/v1.1/generated-sql-ddl/sqlite/02-seed.sql"
|
||||||
|
"INSERT INTO sample(id, note) VALUES ('seed-1', 'created-second');\n")
|
||||||
|
cppbessot_test_sqlite_exec("${_db_path}"
|
||||||
|
"CREATE TABLE old_data(id TEXT); INSERT INTO old_data(id) VALUES ('legacy');")
|
||||||
|
|
||||||
|
cppbessot_test_configure_project("${_case_dir}" "${_case_dir}/build" _cfg_result _cfg_stdout _cfg_stderr)
|
||||||
|
cppbessot_test_assert_success("${_cfg_result}" "${_cfg_stderr}" "fixture configure")
|
||||||
|
cppbessot_test_build_target("${_case_dir}/build" "db_createfrom" _build_result _build_stdout _build_stderr)
|
||||||
|
cppbessot_test_assert_success("${_build_result}" "${_build_stderr}" "db_createfrom sqlite")
|
||||||
|
|
||||||
|
cppbessot_test_sqlite_query_scalar(_row_count "${_db_path}" "SELECT COUNT(*) FROM sample;")
|
||||||
|
if(NOT "${_row_count}" STREQUAL "1")
|
||||||
|
message(FATAL_ERROR "Expected seeded sample row after recreate, got `${_row_count}`.")
|
||||||
|
endif()
|
||||||
|
cppbessot_test_sqlite_query_scalar(_old_table_count "${_db_path}"
|
||||||
|
"SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='old_data';")
|
||||||
|
if(NOT "${_old_table_count}" STREQUAL "0")
|
||||||
|
message(FATAL_ERROR "Expected old_data table to be removed during recreate.")
|
||||||
|
endif()
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/../cmake/TestCommon.cmake")
|
||||||
|
|
||||||
|
cppbessot_test_case_dir(_case_dir)
|
||||||
|
cppbessot_test_write_project(
|
||||||
|
"${_case_dir}"
|
||||||
|
"set(CPPBESSOT_DB_SQLITE_DEV_PATH \"${_case_dir}/live/dev.sqlite\" CACHE STRING \"\")\n")
|
||||||
|
cppbessot_test_add_schema("${_case_dir}" "v1.1")
|
||||||
|
cppbessot_test_add_sql_file("${_case_dir}/db/v1.1/generated-sql-ddl/sqlite/01-schema.sql"
|
||||||
|
"CREATE TABLE sample(id TEXT PRIMARY KEY);\nBROKEN SQL;\n")
|
||||||
|
|
||||||
|
cppbessot_test_configure_project("${_case_dir}" "${_case_dir}/build" _cfg_result _cfg_stdout _cfg_stderr)
|
||||||
|
cppbessot_test_assert_success("${_cfg_result}" "${_cfg_stderr}" "fixture configure")
|
||||||
|
cppbessot_test_build_target("${_case_dir}/build" "db_createfrom" _build_result _build_stdout _build_stderr)
|
||||||
|
cppbessot_test_assert_failure_contains("${_build_result}" "${_build_stderr}" "SQLite SQL apply failed")
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/../cmake/TestCommon.cmake")
|
||||||
|
|
||||||
|
cppbessot_test_case_dir(_case_dir)
|
||||||
|
set(_db_path "${_case_dir}/live/dev.sqlite")
|
||||||
|
cppbessot_test_write_project(
|
||||||
|
"${_case_dir}"
|
||||||
|
"set(DB_MIGRATE_WITH \"v1.0-v1.1\" CACHE STRING \"\")\n"
|
||||||
|
"set(CPPBESSOT_DB_SQLITE_DEV_PATH \"${_db_path}\" CACHE STRING \"\")\n")
|
||||||
|
cppbessot_test_add_schema("${_case_dir}" "v1.1")
|
||||||
|
cppbessot_test_write_file("${_case_dir}/db/migrations/v1.0-v1.1/README.txt" "fixture\n")
|
||||||
|
cppbessot_test_add_sql_file("${_case_dir}/db/migrations/v1.0-v1.1/sqlite/01-migrate.sql"
|
||||||
|
"ALTER TABLE sample ADD COLUMN note TEXT DEFAULT 'migrated';\n")
|
||||||
|
cppbessot_test_sqlite_exec("${_db_path}"
|
||||||
|
"CREATE TABLE sample(id TEXT PRIMARY KEY); INSERT INTO sample(id) VALUES ('row-1');")
|
||||||
|
|
||||||
|
cppbessot_test_configure_project("${_case_dir}" "${_case_dir}/build" _cfg_result _cfg_stdout _cfg_stderr)
|
||||||
|
cppbessot_test_assert_success("${_cfg_result}" "${_cfg_stderr}" "fixture configure")
|
||||||
|
cppbessot_test_build_target("${_case_dir}/build" "db_migrate" _build_result _build_stdout _build_stderr)
|
||||||
|
cppbessot_test_assert_success("${_build_result}" "${_build_stderr}" "db_migrate sqlite")
|
||||||
|
cppbessot_test_sqlite_query_scalar(_note "${_db_path}" "SELECT note FROM sample WHERE id='row-1';")
|
||||||
|
if(NOT "${_note}" STREQUAL "migrated")
|
||||||
|
message(FATAL_ERROR "Expected migration to add note column with default value, got `${_note}`.")
|
||||||
|
endif()
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/../cmake/TestCommon.cmake")
|
||||||
|
|
||||||
|
cppbessot_test_case_dir(_case_dir)
|
||||||
|
set(_prod_db "${_case_dir}/live/prod.sqlite")
|
||||||
|
set(_proddev_db "${_case_dir}/live/proddev.sqlite")
|
||||||
|
set(_log_file "${_case_dir}/clone.log")
|
||||||
|
cppbessot_test_sqlite_exec("${_prod_db}"
|
||||||
|
"CREATE TABLE sample(id TEXT PRIMARY KEY); INSERT INTO sample(id) VALUES ('prod-row');")
|
||||||
|
cppbessot_test_write_project(
|
||||||
|
"${_case_dir}"
|
||||||
|
"set(DB_TARGET \"proddev\" CACHE STRING \"\")\n"
|
||||||
|
"set(DB_MIGRATE_WITH \"v1.0-v1.1\" CACHE STRING \"\")\n"
|
||||||
|
"set(CPPBESSOT_DB_SQLITE_PROD_PATH \"${_prod_db}\" CACHE STRING \"\")\n"
|
||||||
|
"set(CPPBESSOT_DB_SQLITE_PRODDEV_PATH \"${_proddev_db}\" CACHE STRING \"\")\n"
|
||||||
|
"set(CPPBESSOT_DB_SQLITE_CLONE_PROD_TO_PRODDEV_COMMAND \"cp '${_prod_db}' '${_proddev_db}' && printf 'clone\\\\n' >> '${_log_file}'\" CACHE STRING \"\")\n")
|
||||||
|
cppbessot_test_add_schema("${_case_dir}" "v1.1")
|
||||||
|
cppbessot_test_add_sql_file("${_case_dir}/db/migrations/v1.0-v1.1/sqlite/01-migrate.sql"
|
||||||
|
"ALTER TABLE sample ADD COLUMN note TEXT DEFAULT 'cloned';\n")
|
||||||
|
|
||||||
|
cppbessot_test_configure_project("${_case_dir}" "${_case_dir}/build" _cfg_result _cfg_stdout _cfg_stderr)
|
||||||
|
cppbessot_test_assert_success("${_cfg_result}" "${_cfg_stderr}" "fixture configure")
|
||||||
|
cppbessot_test_build_target("${_case_dir}/build" "db_migrate" _build_result _build_stdout _build_stderr)
|
||||||
|
cppbessot_test_assert_success("${_build_result}" "${_build_stderr}" "db_migrate sqlite proddev clone")
|
||||||
|
cppbessot_test_assert_file_exists("${_proddev_db}")
|
||||||
|
cppbessot_test_sqlite_query_scalar(_note "${_proddev_db}" "SELECT note FROM sample WHERE id='prod-row';")
|
||||||
|
if(NOT "${_note}" STREQUAL "cloned")
|
||||||
|
message(FATAL_ERROR "Expected migrated proddev clone to contain note column, got `${_note}`.")
|
||||||
|
endif()
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/../cmake/TestCommon.cmake")
|
||||||
|
|
||||||
|
cppbessot_test_case_dir(_case_dir)
|
||||||
|
set(_proddev_db "${_case_dir}/live/proddev.sqlite")
|
||||||
|
cppbessot_test_write_project(
|
||||||
|
"${_case_dir}"
|
||||||
|
"set(DB_TARGET \"proddev\" CACHE STRING \"\")\n"
|
||||||
|
"set(DB_MIGRATE_WITH \"v1.0-v1.1\" CACHE STRING \"\")\n"
|
||||||
|
"set(DB_MIGRATE_PRODDEV_USE_STALE ON CACHE BOOL \"\")\n"
|
||||||
|
"set(CPPBESSOT_DB_SQLITE_PRODDEV_PATH \"${_proddev_db}\" CACHE STRING \"\")\n")
|
||||||
|
cppbessot_test_add_schema("${_case_dir}" "v1.1")
|
||||||
|
cppbessot_test_add_sql_file("${_case_dir}/db/migrations/v1.0-v1.1/sqlite/01-migrate.sql"
|
||||||
|
"ALTER TABLE sample ADD COLUMN note TEXT DEFAULT 'ok';\n")
|
||||||
|
|
||||||
|
cppbessot_test_configure_project("${_case_dir}" "${_case_dir}/build" _cfg_result _cfg_stdout _cfg_stderr)
|
||||||
|
cppbessot_test_assert_success("${_cfg_result}" "${_cfg_stderr}" "fixture configure")
|
||||||
|
cppbessot_test_build_target("${_case_dir}/build" "db_migrate" _build_result _build_stdout _build_stderr)
|
||||||
|
cppbessot_test_assert_failure_contains("${_build_result}" "${_build_stderr}" "no current stale proddev target")
|
||||||
Reference in New Issue
Block a user