mirror of
https://github.com/latentPrion/cppbessot.git
synced 2026-06-23 15:18:37 +00:00
Support enum headers and other stuff
This commit is contained in:
@@ -31,6 +31,19 @@ if(NOT DEFINED DB_SCHEMA_DIR_MIGRATION_TO)
|
||||
"Optional target schema directory basename for migration generation")
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED CPPBESSOT_GEN_MIGRATION_BACKENDS)
|
||||
if(DEFINED CPPBESSOT_GEN_MIGRATIONS_BACKENDS)
|
||||
set(CPPBESSOT_GEN_MIGRATION_BACKENDS "${CPPBESSOT_GEN_MIGRATIONS_BACKENDS}")
|
||||
else()
|
||||
set(CPPBESSOT_GEN_MIGRATION_BACKENDS "sqlite;pgsql")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CPPBESSOT_GEN_MIGRATION_BACKENDS "${CPPBESSOT_GEN_MIGRATION_BACKENDS}" CACHE STRING
|
||||
"ODB backends for db_gen_migrations; supported values: sqlite, pgsql")
|
||||
set(CPPBESSOT_GEN_MIGRATIONS_BACKENDS "${CPPBESSOT_GEN_MIGRATION_BACKENDS}" CACHE STRING
|
||||
"Compatibility alias for CPPBESSOT_GEN_MIGRATION_BACKENDS" FORCE)
|
||||
|
||||
if(NOT DEFINED DB_SCHEMA_CHANGES_ARE_ERROR)
|
||||
option(DB_SCHEMA_CHANGES_ARE_ERROR "Treat dirty schema changes as hard CMake error" OFF)
|
||||
endif()
|
||||
@@ -249,6 +262,7 @@ function(cppbessot_enable)
|
||||
# - DB_SCHEMA_DIR_TO_GENERATE
|
||||
# - DB_SCHEMA_DIR_MIGRATION_FROM
|
||||
# - DB_SCHEMA_DIR_MIGRATION_TO
|
||||
# - CPPBESSOT_GEN_MIGRATION_BACKENDS
|
||||
# - DB_SCHEMA_CHANGES_ARE_ERROR (optional behavior control)
|
||||
# Outputs:
|
||||
# - Custom targets:
|
||||
|
||||
@@ -9,6 +9,7 @@ function(cppbessot_add_db_gen_migrations_target from_schema_dir to_schema_dir)
|
||||
# - from_schema_dir: Source schema directory basename.
|
||||
# - to_schema_dir: Target schema directory basename.
|
||||
# - CPPBESSOT_ODB_EXECUTABLE: Path to `odb` compiler.
|
||||
# - CPPBESSOT_GEN_MIGRATION_BACKENDS: List of ODB backends to generate.
|
||||
# Outputs:
|
||||
# - CMake target: `db_gen_migrations` (EXCLUDE_FROM_ALL).
|
||||
# - Files under `migrations/<from>-<to>/{sqlite,postgre}`.
|
||||
@@ -26,10 +27,11 @@ function(cppbessot_add_db_gen_migrations_target from_schema_dir to_schema_dir)
|
||||
|
||||
add_custom_target(db_gen_migrations
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
-DCPPBESSOT_ODB_EXECUTABLE=${CPPBESSOT_ODB_EXECUTABLE}
|
||||
-DCPPBESSOT_FROM_VERSION_DIR=${_from_dir}
|
||||
-DCPPBESSOT_TO_VERSION_DIR=${_to_dir}
|
||||
-DCPPBESSOT_MIGRATION_DIR=${_migration_dir}
|
||||
"-DCPPBESSOT_ODB_EXECUTABLE=${CPPBESSOT_ODB_EXECUTABLE}"
|
||||
"-DCPPBESSOT_FROM_VERSION_DIR=${_from_dir}"
|
||||
"-DCPPBESSOT_TO_VERSION_DIR=${_to_dir}"
|
||||
"-DCPPBESSOT_MIGRATION_DIR=${_migration_dir}"
|
||||
"-DCPPBESSOT_GEN_MIGRATION_BACKENDS=${CPPBESSOT_GEN_MIGRATION_BACKENDS}"
|
||||
-P "${_CPPBESSOT_DB_GEN_MIGRATIONS_DIR}/scripts/run_odb_migrations.cmake"
|
||||
COMMENT "Generating DB migrations: ${from_schema_dir} -> ${to_schema_dir}"
|
||||
VERBATIM
|
||||
|
||||
@@ -13,36 +13,130 @@ if(NOT DEFINED CPPBESSOT_MIGRATION_DIR OR CPPBESSOT_MIGRATION_DIR STREQUAL "")
|
||||
message(FATAL_ERROR "CPPBESSOT_MIGRATION_DIR is required")
|
||||
endif()
|
||||
|
||||
function(cppbessot_migration_resolve_backends out_var)
|
||||
if(NOT DEFINED CPPBESSOT_GEN_MIGRATION_BACKENDS OR CPPBESSOT_GEN_MIGRATION_BACKENDS STREQUAL "")
|
||||
if(DEFINED CPPBESSOT_GEN_MIGRATIONS_BACKENDS AND NOT CPPBESSOT_GEN_MIGRATIONS_BACKENDS STREQUAL "")
|
||||
set(_raw_backends "${CPPBESSOT_GEN_MIGRATIONS_BACKENDS}")
|
||||
else()
|
||||
set(_raw_backends "sqlite;pgsql")
|
||||
endif()
|
||||
else()
|
||||
set(_raw_backends "${CPPBESSOT_GEN_MIGRATION_BACKENDS}")
|
||||
endif()
|
||||
|
||||
set(_resolved_backends "")
|
||||
foreach(_backend IN LISTS _raw_backends)
|
||||
string(STRIP "${_backend}" _backend)
|
||||
string(TOLOWER "${_backend}" _backend)
|
||||
|
||||
if(_backend STREQUAL "")
|
||||
message(FATAL_ERROR "CPPBESSOT_GEN_MIGRATION_BACKENDS contains an empty backend name.")
|
||||
endif()
|
||||
|
||||
if(NOT _backend STREQUAL "sqlite" AND NOT _backend STREQUAL "pgsql")
|
||||
message(FATAL_ERROR
|
||||
"Unsupported migration backend `${_backend}`. "
|
||||
"CPPBESSOT_GEN_MIGRATION_BACKENDS supports sqlite and pgsql.")
|
||||
endif()
|
||||
|
||||
if(NOT _backend IN_LIST _resolved_backends)
|
||||
list(APPEND _resolved_backends "${_backend}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(NOT _resolved_backends)
|
||||
message(FATAL_ERROR "CPPBESSOT_GEN_MIGRATION_BACKENDS must name at least one backend.")
|
||||
endif()
|
||||
|
||||
set(${out_var} "${_resolved_backends}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(cppbessot_migration_backend_metadata backend out_subdir out_odb_database out_database_attr)
|
||||
if("${backend}" STREQUAL "sqlite")
|
||||
set(${out_subdir} "sqlite" PARENT_SCOPE)
|
||||
set(${out_odb_database} "sqlite" PARENT_SCOPE)
|
||||
set(${out_database_attr} "sqlite" PARENT_SCOPE)
|
||||
elseif("${backend}" STREQUAL "pgsql")
|
||||
set(${out_subdir} "postgre" PARENT_SCOPE)
|
||||
set(${out_odb_database} "pgsql" PARENT_SCOPE)
|
||||
set(${out_database_attr} "pgsql" PARENT_SCOPE)
|
||||
else()
|
||||
message(FATAL_ERROR "Unsupported migration backend `${backend}`.")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(cppbessot_migration_write_empty_changelog changelog_path database_attr)
|
||||
if(NOT EXISTS "${changelog_path}")
|
||||
file(WRITE "${changelog_path}"
|
||||
"<changelog xmlns=\"http://www.codesynthesis.com/xmlns/odb/changelog\" database=\"${database_attr}\" version=\"1\">\n"
|
||||
" <model version=\"1\">\n"
|
||||
" </model>\n"
|
||||
"</changelog>\n")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(cppbessot_migration_should_retry_sqlite_from_empty out_var backend from_xml empty_changelog stdout stderr)
|
||||
set(_should_retry FALSE)
|
||||
if("${backend}" STREQUAL "sqlite" AND NOT "${from_xml}" STREQUAL "${empty_changelog}")
|
||||
set(_diagnostics "${stdout}\n${stderr}")
|
||||
if(_diagnostics MATCHES "SQLite does not support dropping of columns")
|
||||
set(_should_retry TRUE)
|
||||
endif()
|
||||
endif()
|
||||
set(${out_var} "${_should_retry}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
cppbessot_migration_resolve_backends(_migration_backends)
|
||||
|
||||
set(_to_include_dir "${CPPBESSOT_TO_VERSION_DIR}/generated-cpp-source/include")
|
||||
file(GLOB _to_headers "${_to_include_dir}/*/model/*.h")
|
||||
if(NOT _to_headers)
|
||||
message(FATAL_ERROR "No target-version headers found under ${_to_include_dir}")
|
||||
endif()
|
||||
|
||||
foreach(_backend IN ITEMS sqlite pgsql)
|
||||
if(_backend STREQUAL "sqlite")
|
||||
set(_subdir sqlite)
|
||||
else()
|
||||
set(_subdir postgre)
|
||||
set(_object_headers "")
|
||||
foreach(_header IN LISTS _to_headers)
|
||||
file(READ "${_header}" _header_contents)
|
||||
if(_header_contents MATCHES "#pragma db object")
|
||||
list(APPEND _object_headers "${_header}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(NOT _object_headers)
|
||||
message(FATAL_ERROR "No ODB object headers found under ${_to_include_dir}")
|
||||
endif()
|
||||
|
||||
set(_empty_changelog_dir "${CPPBESSOT_MIGRATION_DIR}/.empty-baseline")
|
||||
file(MAKE_DIRECTORY "${_empty_changelog_dir}")
|
||||
|
||||
foreach(_backend IN LISTS _migration_backends)
|
||||
cppbessot_migration_backend_metadata(
|
||||
"${_backend}"
|
||||
_subdir
|
||||
_odb_database
|
||||
_database_attr)
|
||||
|
||||
set(_empty_changelog "${_empty_changelog_dir}/${_subdir}-empty.xml")
|
||||
cppbessot_migration_write_empty_changelog("${_empty_changelog}" "${_database_attr}")
|
||||
|
||||
set(_migration_backend_dir "${CPPBESSOT_MIGRATION_DIR}/${_subdir}")
|
||||
file(MAKE_DIRECTORY "${_migration_backend_dir}")
|
||||
|
||||
foreach(_header IN LISTS _to_headers)
|
||||
foreach(_header IN LISTS _object_headers)
|
||||
get_filename_component(_name "${_header}" NAME_WE)
|
||||
set(_in_xml "${CPPBESSOT_FROM_VERSION_DIR}/generated-odb-source/${_subdir}/${_name}.xml")
|
||||
set(_out_xml "${CPPBESSOT_TO_VERSION_DIR}/generated-odb-source/${_subdir}/${_name}.xml")
|
||||
|
||||
if(NOT EXISTS "${_in_xml}")
|
||||
message(FATAL_ERROR "Missing changelog input for `${_name}`: ${_in_xml}")
|
||||
set(_from_xml "${_in_xml}")
|
||||
if(NOT EXISTS "${_from_xml}")
|
||||
set(_from_xml "${_empty_changelog}")
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND "${CPPBESSOT_ODB_EXECUTABLE}" -I "${_to_include_dir}" --std c++11 -d "${_backend}"
|
||||
COMMAND "${CPPBESSOT_ODB_EXECUTABLE}" -I "${_to_include_dir}" --std c++11 -d "${_odb_database}"
|
||||
--generate-schema --schema-format sql -q
|
||||
-o "${_migration_backend_dir}"
|
||||
--changelog-in "${_in_xml}"
|
||||
--changelog-in "${_from_xml}"
|
||||
--changelog-out "${_out_xml}"
|
||||
"${_header}"
|
||||
RESULT_VARIABLE _result
|
||||
@@ -50,6 +144,31 @@ foreach(_backend IN ITEMS sqlite pgsql)
|
||||
ERROR_VARIABLE _stderr
|
||||
)
|
||||
|
||||
cppbessot_migration_should_retry_sqlite_from_empty(
|
||||
_retry_from_empty
|
||||
"${_backend}"
|
||||
"${_from_xml}"
|
||||
"${_empty_changelog}"
|
||||
"${_stdout}"
|
||||
"${_stderr}")
|
||||
|
||||
if(NOT _result EQUAL 0 AND _retry_from_empty)
|
||||
message(WARNING
|
||||
"SQLite incremental migration failed for `${_name}`; retrying from empty baseline. "
|
||||
"Generated SQLite migration SQL is a greenfield create for this model.")
|
||||
execute_process(
|
||||
COMMAND "${CPPBESSOT_ODB_EXECUTABLE}" -I "${_to_include_dir}" --std c++11 -d "${_odb_database}"
|
||||
--generate-schema --schema-format sql -q
|
||||
-o "${_migration_backend_dir}"
|
||||
--changelog-in "${_empty_changelog}"
|
||||
--changelog-out "${_out_xml}"
|
||||
"${_header}"
|
||||
RESULT_VARIABLE _result
|
||||
OUTPUT_VARIABLE _stdout
|
||||
ERROR_VARIABLE _stderr
|
||||
)
|
||||
endif()
|
||||
|
||||
if(NOT _result EQUAL 0)
|
||||
message(FATAL_ERROR
|
||||
"Migration generation failed for `${_name}` backend `${_backend}`.\n${_stdout}\n${_stderr}")
|
||||
|
||||
Reference in New Issue
Block a user