Compare commits

...

5 Commits

11 changed files with 146 additions and 15 deletions
+3
View File
@@ -12,6 +12,7 @@ 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")
include("${CMAKE_CURRENT_LIST_DIR}/dbRuntimeEnv.cmake")
if(NOT DEFINED CPPBESSOT_WORKDIR)
set(CPPBESSOT_WORKDIR "db" CACHE STRING "CppBeSSOT schema root folder")
@@ -87,6 +88,8 @@ set(CPPBESSOT_DB_SQLITE_CLONE_PROD_TO_PRODDEV_COMMAND "${CPPBESSOT_DB_SQLITE_CLO
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")
cppbessot_write_runtime_env_file("${CMAKE_BINARY_DIR}/cppbessot.env")
if(NOT DEFINED CPPBESSOT_AUTO_ENABLE)
option(CPPBESSOT_AUTO_ENABLE "Auto-register CppBeSSOT targets when this file is included" ON)
endif()
+5 -3
View File
@@ -56,9 +56,10 @@ function(_cppbessot_require_npm_package npm_executable package_name)
# - package_name: Package name to validate.
# Outputs:
# - No return value; raises FATAL_ERROR when package is not installed.
cppbessot_get_module_root(_module_root)
execute_process(
COMMAND "${npm_executable}" list --depth=0 "${package_name}"
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
WORKING_DIRECTORY "${_module_root}"
RESULT_VARIABLE _local_result
OUTPUT_QUIET
ERROR_QUIET
@@ -90,9 +91,10 @@ function(_cppbessot_require_npx_package_executable npx_executable package_execut
# - package_executable: Executable name exposed by a package.
# Outputs:
# - No return value; raises FATAL_ERROR if execution fails.
cppbessot_get_module_root(_module_root)
execute_process(
COMMAND "${npx_executable}" --no-install "${package_executable}" --help
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
WORKING_DIRECTORY "${_module_root}"
RESULT_VARIABLE _help_result
OUTPUT_QUIET
ERROR_VARIABLE _help_stderr
@@ -105,7 +107,7 @@ function(_cppbessot_require_npx_package_executable npx_executable package_execut
# Some CLIs return non-zero for --help; verify with version as fallback.
execute_process(
COMMAND "${npx_executable}" --no-install "${package_executable}" version
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
WORKING_DIRECTORY "${_module_root}"
RESULT_VARIABLE _version_result
OUTPUT_QUIET
ERROR_VARIABLE _version_stderr
+11 -7
View File
@@ -1,7 +1,6 @@
include_guard(GLOBAL)
include("${CMAKE_CURRENT_LIST_DIR}/dbGenerationCommon.cmake")
set(_CPPBESSOT_DB_GEN_CPP_DIR "${CMAKE_CURRENT_LIST_DIR}")
function(cppbessot_add_db_gen_cpp_target schema_dir)
# Purpose: Register C++ model generation target using checked-in templates.
@@ -13,19 +12,20 @@ function(cppbessot_add_db_gen_cpp_target schema_dir)
# - Files under `<schema_dir>/generated-cpp-source`.
cppbessot_validate_schema_dir_name("${schema_dir}")
cppbessot_get_schema_dir_path(_version_dir "${schema_dir}")
if(DEFINED CPPBESSOT_MODULE_ROOT AND NOT "${CPPBESSOT_MODULE_ROOT}" STREQUAL "")
set(_module_root "${CPPBESSOT_MODULE_ROOT}")
else()
get_filename_component(_module_root "${_CPPBESSOT_DB_GEN_CPP_DIR}/.." ABSOLUTE)
endif()
cppbessot_get_module_root(_module_root)
set(_openapi_file "${_version_dir}/openapi/openapi.yaml")
set(_template_dir "${_module_root}/openapi/templates/cpp-odb-json")
set(_template_config "${_template_dir}/config.yaml")
set(_output_dir "${_version_dir}/generated-cpp-source")
file(GLOB_RECURSE _template_inputs CONFIGURE_DEPENDS "${_template_dir}/*")
cppbessot_get_expected_cpp_model_outputs(
_expected_model_headers
_expected_model_sources
"${schema_dir}")
add_custom_target(db_gen_cpp_headers
add_custom_command(
OUTPUT ${_expected_model_headers} ${_expected_model_sources}
COMMAND ${CMAKE_COMMAND} -E make_directory "${_output_dir}"
COMMAND "${CPPBESSOT_NPX_EXECUTABLE}" @openapitools/openapi-generator-cli generate
-i "${_openapi_file}"
@@ -35,9 +35,13 @@ function(cppbessot_add_db_gen_cpp_target schema_dir)
-o "${_output_dir}"
--global-property models
DEPENDS "${_openapi_file}" ${_template_inputs}
WORKING_DIRECTORY "${_module_root}"
COMMENT "Generating C++ model headers/sources for ${schema_dir}"
VERBATIM
)
add_custom_target(db_gen_cpp_headers
DEPENDS ${_expected_model_headers} ${_expected_model_sources})
set_target_properties(db_gen_cpp_headers PROPERTIES EXCLUDE_FROM_ALL TRUE)
endfunction()
+16 -2
View File
@@ -13,16 +13,30 @@ function(cppbessot_add_db_gen_sql_ddl_target schema_dir)
# - Files under `<schema_dir>/generated-sql-ddl/{sqlite,postgre}`.
cppbessot_validate_schema_dir_name("${schema_dir}")
cppbessot_get_schema_dir_path(_version_dir "${schema_dir}")
cppbessot_get_expected_odb_generation_artifacts(
_expected_model_headers
_expected_odb_sources
"${schema_dir}")
add_custom_target(db_gen_sql_ddl
set(_stamp_dir "${CMAKE_CURRENT_BINARY_DIR}/cppbessot/${schema_dir}")
set(_stamp_file "${_stamp_dir}/db_gen_sql_ddl.stamp")
add_custom_command(
OUTPUT "${_stamp_file}"
COMMAND "${CMAKE_COMMAND}" -E make_directory "${_stamp_dir}"
COMMAND "${CMAKE_COMMAND}"
-DCPPBESSOT_ODB_EXECUTABLE=${CPPBESSOT_ODB_EXECUTABLE}
-DCPPBESSOT_VERSION_DIR=${_version_dir}
-P "${_CPPBESSOT_DB_GEN_SQL_DDL_DIR}/scripts/run_odb_sql_ddl.cmake"
DEPENDS db_gen_cpp_headers
COMMAND "${CMAKE_COMMAND}" -E touch "${_stamp_file}"
DEPENDS db_gen_cpp_headers ${_expected_model_headers}
COMMENT "Generating SQL DDL snapshots for ${schema_dir} (sqlite + postgre)"
VERBATIM
)
add_custom_target(db_gen_sql_ddl
DEPENDS "${_stamp_file}")
add_dependencies(db_gen_sql_ddl db_gen_cpp_headers)
set_target_properties(db_gen_sql_ddl PROPERTIES EXCLUDE_FROM_ALL TRUE)
endfunction()
+2
View File
@@ -12,6 +12,7 @@ function(cppbessot_add_db_gen_ts_target schema_dir)
# - Files under `<schema_dir>/generated-ts-types`.
cppbessot_validate_schema_dir_name("${schema_dir}")
cppbessot_get_schema_dir_path(_version_dir "${schema_dir}")
cppbessot_get_module_root(_module_root)
set(_openapi_file "${_version_dir}/openapi/openapi.yaml")
set(_output_dir "${_version_dir}/generated-ts-types")
@@ -22,6 +23,7 @@ function(cppbessot_add_db_gen_ts_target schema_dir)
-i "${_openapi_file}"
-g typescript-fetch
-o "${_output_dir}"
WORKING_DIRECTORY "${_module_root}"
COMMENT "Generating TypeScript types for ${schema_dir}"
VERBATIM
)
+14
View File
@@ -41,6 +41,20 @@ function(cppbessot_initialize_paths)
set(CPPBESSOT_WORKDIR_ABS "${CPPBESSOT_WORKDIR_ABS}" PARENT_SCOPE)
endfunction()
function(cppbessot_get_module_root out_var)
# Purpose: Resolve the CppBeSSOT module root, respecting parent overrides.
# Inputs:
# - CPPBESSOT_MODULE_ROOT (optional): Parent-provided module root path.
# Outputs:
# - <out_var> (PARENT_SCOPE): Absolute module root path.
if(DEFINED CPPBESSOT_MODULE_ROOT AND NOT "${CPPBESSOT_MODULE_ROOT}" STREQUAL "")
get_filename_component(_module_root "${CPPBESSOT_MODULE_ROOT}" ABSOLUTE)
else()
get_filename_component(_module_root "${_CPPBESSOT_GENERATION_COMMON_DIR}/.." ABSOLUTE)
endif()
set(${out_var} "${_module_root}" PARENT_SCOPE)
endfunction()
function(cppbessot_require_var var_name)
# Purpose: Fail fast if a required CMake variable is missing/empty.
# Inputs:
+41
View File
@@ -0,0 +1,41 @@
include_guard(GLOBAL)
function(_cppbessot_dotenv_escape output_var value)
set(escaped "${value}")
string(REPLACE "\\" "\\\\" escaped "${escaped}")
string(REPLACE "\"" "\\\"" escaped "${escaped}")
string(REPLACE "\n" "\\n" escaped "${escaped}")
string(REPLACE "\r" "\\r" escaped "${escaped}")
string(REPLACE "\t" "\\t" escaped "${escaped}")
set(${output_var} "${escaped}" PARENT_SCOPE)
endfunction()
function(_cppbessot_dotenv_append output_var name value)
_cppbessot_dotenv_escape(escaped_value "${value}")
set(line "${name}=\"${escaped_value}\"\n")
set(${output_var} "${${output_var}}${line}" PARENT_SCOPE)
endfunction()
function(cppbessot_write_runtime_env_file output_path)
set(env_contents
"# Generated by cppbessot during CMake configure. Do not edit.\n")
_cppbessot_dotenv_append(env_contents
"DB_TARGET" "${DB_TARGET}")
_cppbessot_dotenv_append(env_contents
"CPPBESSOT_DB_PGSQL_PROD_CONNSTR" "${CPPBESSOT_DB_PGSQL_PROD_CONNSTR}")
_cppbessot_dotenv_append(env_contents
"CPPBESSOT_DB_PGSQL_DEV_CONNSTR" "${CPPBESSOT_DB_PGSQL_DEV_CONNSTR}")
_cppbessot_dotenv_append(env_contents
"CPPBESSOT_DB_PGSQL_PRODDEV_CONNSTR" "${CPPBESSOT_DB_PGSQL_PRODDEV_CONNSTR}")
_cppbessot_dotenv_append(env_contents
"CPPBESSOT_DB_PGSQL_TESTS_CONNSTR" "${CPPBESSOT_DB_PGSQL_TESTS_CONNSTR}")
_cppbessot_dotenv_append(env_contents
"CPPBESSOT_DB_SQLITE_PROD_PATH" "${CPPBESSOT_DB_SQLITE_PROD_PATH}")
_cppbessot_dotenv_append(env_contents
"CPPBESSOT_DB_SQLITE_DEV_PATH" "${CPPBESSOT_DB_SQLITE_DEV_PATH}")
_cppbessot_dotenv_append(env_contents
"CPPBESSOT_DB_SQLITE_PRODDEV_PATH" "${CPPBESSOT_DB_SQLITE_PRODDEV_PATH}")
_cppbessot_dotenv_append(env_contents
"CPPBESSOT_DB_SQLITE_TESTS_PATH" "${CPPBESSOT_DB_SQLITE_TESTS_PATH}")
file(WRITE "${output_path}" "${env_contents}")
endfunction()
+49 -1
View File
@@ -104,8 +104,56 @@ function(cppbessot_db_action_collect_nonempty_sql_files out_var sql_dir)
set(${out_var} "${_sql_files}" PARENT_SCOPE)
endfunction()
function(cppbessot_db_action_is_migration_sql_file out_var sql_file)
get_filename_component(_filename "${sql_file}" NAME)
if("${_filename}" MATCHES "-[0-9]+-(pre|post)\\.sql$")
set(${out_var} TRUE PARENT_SCOPE)
return()
endif()
set(${out_var} FALSE PARENT_SCOPE)
endfunction()
function(cppbessot_db_action_collect_schema_sql_files out_var sql_dir)
cppbessot_db_action_collect_nonempty_sql_files(_candidate_files "${sql_dir}")
set(_sql_files)
foreach(_candidate IN LISTS _candidate_files)
cppbessot_db_action_is_migration_sql_file(_is_migration_sql "${_candidate}")
if(NOT _is_migration_sql)
list(APPEND _sql_files "${_candidate}")
endif()
endforeach()
set(${out_var} "${_sql_files}" PARENT_SCOPE)
endfunction()
function(cppbessot_db_action_migration_sort_key out_var sql_file)
get_filename_component(_filename "${sql_file}" NAME)
string(REGEX REPLACE "-([0-9]+)-pre\\.sql$" "-\\1-0-pre.sql" _sort_key "${_filename}")
string(REGEX REPLACE "-([0-9]+)-post\\.sql$" "-\\1-1-post.sql" _sort_key "${_sort_key}")
set(${out_var} "${_sort_key}" PARENT_SCOPE)
endfunction()
function(cppbessot_db_action_collect_migration_sql_files out_var sql_dir)
cppbessot_db_action_collect_nonempty_sql_files(_candidate_files "${sql_dir}")
set(_keyed_files)
foreach(_candidate IN LISTS _candidate_files)
cppbessot_db_action_is_migration_sql_file(_is_migration_sql "${_candidate}")
if(_is_migration_sql)
cppbessot_db_action_migration_sort_key(_sort_key "${_candidate}")
list(APPEND _keyed_files "${_sort_key}|${_candidate}")
endif()
endforeach()
list(SORT _keyed_files)
set(_sql_files)
foreach(_keyed_file IN LISTS _keyed_files)
string(REGEX REPLACE "^[^|]+\\|" "" _sql_file "${_keyed_file}")
list(APPEND _sql_files "${_sql_file}")
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}")
cppbessot_db_action_collect_schema_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()
+1 -1
View File
@@ -26,7 +26,7 @@ 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}")
cppbessot_db_action_collect_schema_sql_files(_sql_files "${_ddl_dir}")
if("${_backend}" STREQUAL "sqlite")
cppbessot_db_action_reset_sqlite_db("${_sqlite_path}")
+1 -1
View File
@@ -29,7 +29,7 @@ cppbessot_db_action_prepare_proddev(
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_collect_migration_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")
@@ -49,6 +49,9 @@ public:
{{/vendorExtensions.x-odbAddedIn}}
{{#vendorExtensions.x-cppType}}{{vendorExtensions.x-cppType}}{{/vendorExtensions.x-cppType}}{{^vendorExtensions.x-cppType}}{{#isString}}std::string{{/isString}}{{^isString}}{{#isDateTime}}std::string{{/isDateTime}}{{^isDateTime}}{{#isBoolean}}bool{{/isBoolean}}{{^isBoolean}}{{#isInteger}}int32_t{{/isInteger}}{{^isInteger}}{{#isLong}}int64_t{{/isLong}}{{^isLong}}{{dataType}}{{/isLong}}{{/isInteger}}{{/isBoolean}}{{/isDateTime}}{{/isString}}{{/vendorExtensions.x-cppType}} {{nameInCamelCase}}{};
{{/vars}}
{{#vendorExtensions.x-dataModelUniqueConstraints}}
#pragma db index("{{name}}") unique {{odbMemberSpec}}
{{/vendorExtensions.x-dataModelUniqueConstraints}}
NLOHMANN_DEFINE_TYPE_INTRUSIVE({{classname}}{{#vars}}, {{nameInCamelCase}}{{/vars}})