From 0be9feda44770c69247acdb8faf775917c23b0bd Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Thu, 5 Sep 2019 16:32:35 +0000 Subject: [PATCH] added support in Model for removing the whole tree (without lists/vectors at the moment yet) git-svn-id: svn://ttmath.org/publicrep/morm/trunk@1206 e52654a7-88a9-db11-a3e9-0013d4bc506e --- samples/main.cpp | 20 ++++++------ samples/sample01.h | 15 +++++---- src/model.cpp | 67 ++++++++++++++++++++++++++++----------- src/model.h | 63 ++++++++++++++++++++---------------- src/modelconnector.cpp | 5 +++ src/modelconnector.h | 1 + src/morm_types.h | 9 ++++-- src/setfieldvaluehelper.h | 5 +++ 8 files changed, 118 insertions(+), 67 deletions(-) diff --git a/samples/main.cpp b/samples/main.cpp index 2c7d512..413aa3b 100644 --- a/samples/main.cpp +++ b/samples/main.cpp @@ -101,13 +101,6 @@ args_options.Add(L"config", 1); * create database morm_test owner morm_test; * */ - - postgresql_connector.set_conn_param(db_name, db_user, db_pass); - postgresql_connector.wait_for_connection(); - - model_connector.set_flat_connector(json_connector); - model_connector.set_db_connector(postgresql_connector); - PT::Log log; PT::FileLog file_log; PT::WTextStream log_buffer; @@ -116,12 +109,17 @@ args_options.Add(L"config", 1); log.SetLogBuffer(&log_buffer); log.SetFileLog(&file_log); + + + postgresql_connector.set_conn_param(db_name, db_user, db_pass); + postgresql_connector.set_logger(log); + postgresql_connector.set_log_queries(true); + postgresql_connector.wait_for_connection(); + + model_connector.set_flat_connector(json_connector); + model_connector.set_db_connector(postgresql_connector); model_connector.set_logger(log); - postgresql_connector.set_log_queries(true); - - // CHECK ME may it would be better if postgresql_connector could take the logger from model_connector? - postgresql_connector.set_logger(log); morm::samples::Sample01 sample_01; sample_01.set_connector(model_connector); diff --git a/samples/sample01.h b/samples/sample01.h index 713ab2c..2926bb7 100644 --- a/samples/sample01.h +++ b/samples/sample01.h @@ -57,9 +57,10 @@ void make() std::wstring sss = L"cosik"; person.set_field_value_generic(L"email", L"email", sss); - //person.insert(); + person.insert(); //person.update(); - person.save(); + //person.save(); + //person.remove(); } @@ -73,14 +74,14 @@ private: static void load_defaults(Person & person) { - person.id = 200; + person.id = 60; person.first_name = L"MyFirstName"; person.last_name = L"MyLastName"; person.email = L"myemail@mydomain.ltd"; person.set_save_mode(Model::DO_INSERT_ON_SAVE); //person.set_save_mode(Model::DO_UPDATE_ON_SAVE); - person.language.id = 100; + person.language.id = 85; person.language.english_name = L"english"; person.language.local_name = L"polish"; person.language.code_str = L"en"; @@ -90,8 +91,8 @@ private: std::time_t t = std::time(0); - person.attachment.id = 300; - person.attachment.person_id = 200; + person.attachment.id = 40; + person.attachment.person_id = 60; person.attachment.created_date.FromTime(t); person.attachment.name = L"attachment name"; person.attachment.content = "long binary content"; @@ -99,7 +100,7 @@ private: person.attachment.set_save_mode(Model::DO_INSERT_ON_SAVE); //person.attachment.set_save_mode(Model::DO_UPDATE_ON_SAVE); - person.attachment.language.id = 110; + person.attachment.language.id = 86; person.attachment.language.english_name = L"attachment language"; person.attachment.language.local_name = L"attachment local name"; person.attachment.language.code_str = L"loen"; diff --git a/src/model.cpp b/src/model.cpp index 583e9d1..259dffb 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -411,16 +411,41 @@ void Model::generate_remove_query(PT::TextStream & stream, ModelData * model_dat } -bool Model::remove(ModelData * model_data) + +bool Model::remove(ModelData & model_data, bool remove_whole_tree) +{ + return remove(&model_data); +} + + +bool Model::remove(ModelData * model_data, bool remove_whole_tree) +{ + ModelEnv model_env_local; + model_env = &model_env_local; + + model_env->model_data = model_data; + bool status = remove_tree(remove_whole_tree); + + // what about if an exception was thrown? this pointer will not be null + model_env = nullptr; + + return status; +} + + +// FIX ME we need to propagage the status from the whole tree, if there is an error somewhere then we should return error from the parent +bool Model::remove_tree(bool remove_whole_tree) { bool result = false; + if( remove_whole_tree ) + { + model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_ITERATE_THROUGH_CHILDS_WITHOUT_FOREIGN_KEY_AND_REMOVE; + map_fields(); + } + if( model_connector ) { - ModelEnv model_env_local; - model_env = &model_env_local; - - model_env->model_data = model_data; model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL; DbConnector * db_connector = model_connector->get_db_connector(); @@ -435,7 +460,7 @@ bool Model::remove(ModelData * model_data) if( result ) { - save_mode = DO_INSERT_ON_SAVE; + save_mode = DO_INSERT_ON_SAVE; // CHECKME may it would be better to set DO_NOTHING_ON_SAVE? after_remove(); } else @@ -443,20 +468,18 @@ bool Model::remove(ModelData * model_data) after_remove_failure(); } } + } - // what about if an exception was thrown? this pointer will not be null - model_env = nullptr; + if( remove_whole_tree ) + { + model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_ITERATE_THROUGH_CHILDS_WITH_FOREIGN_KEY_AND_REMOVE; + map_fields(); } return result; } -bool Model::remove(ModelData & model_data) -{ - return remove(&model_data); -} - bool Model::save(ModelData & model_data, bool save_whole_tree) @@ -486,7 +509,11 @@ bool Model::save_tree(bool save_whole_tree) if( save_whole_tree ) { - model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_ITERATE_THROUGH_CHILDS_WITH_FOREIGN_KEY_AND_SAVE; + if( save_mode == DO_DELETE_ON_SAVE ) + model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_ITERATE_THROUGH_CHILDS_WITHOUT_FOREIGN_KEY_AND_SAVE; + else + model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_ITERATE_THROUGH_CHILDS_WITH_FOREIGN_KEY_AND_SAVE; + map_fields(); } @@ -495,15 +522,15 @@ bool Model::save_tree(bool save_whole_tree) switch( save_mode ) { case DO_DELETE_ON_SAVE: - result = remove(model_env->model_data);// without the whole tree + result = remove_tree(false); break; case DO_INSERT_ON_SAVE: - result = insert(model_env->model_data, false); + result = insert_tree(false); break; case DO_UPDATE_ON_SAVE: - result = update(model_env->model_data, false); + result = update_tree(false); break; case DO_NOTHING_ON_SAVE: @@ -515,7 +542,11 @@ bool Model::save_tree(bool save_whole_tree) if( save_whole_tree ) { - model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_ITERATE_THROUGH_CHILDS_WITHOUT_FOREIGN_KEY_AND_SAVE; + if( save_mode == DO_DELETE_ON_SAVE ) + model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_ITERATE_THROUGH_CHILDS_WITH_FOREIGN_KEY_AND_SAVE; + else + model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_ITERATE_THROUGH_CHILDS_WITHOUT_FOREIGN_KEY_AND_SAVE; + map_fields(); } diff --git a/src/model.h b/src/model.h index f42a60e..c2ea58c 100644 --- a/src/model.h +++ b/src/model.h @@ -118,8 +118,8 @@ public: virtual bool update(ModelData & model_data, bool update_whole_tree = true); virtual void generate_remove_query(PT::TextStream & stream, ModelData * model_data = nullptr); - virtual bool remove(ModelData * model_data = nullptr); - virtual bool remove(ModelData & model_data); + virtual bool remove(ModelData * model_data = nullptr, bool remove_whole_tree = true); + virtual bool remove(ModelData & model_data, bool remove_whole_tree = true); virtual bool save(ModelData * model_data = nullptr, bool save_whole_tree = true); virtual bool save(ModelData & model_data, bool save_whole_tree = true); @@ -188,6 +188,7 @@ protected: virtual bool insert_tree(bool insert_whole_tree); virtual bool update_tree(bool update_whole_tree); + virtual bool remove_tree(bool remove_whole_tree); virtual bool save_tree(bool save_whole_tree); virtual void map_values_from_query(); @@ -672,6 +673,8 @@ protected: template void field_generic(const wchar_t * db_field_name, const wchar_t * flat_field_name, FieldValue & field_value, bool insertable, bool updatable, bool is_primary_key) { + PT::Log * log = model_connector->get_logger(); + if( model_connector && model_env ) { if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_SET_FIELD_VALUE ) @@ -689,8 +692,13 @@ protected: } else { - // IMPROVE ME - // put some log here + // the log has to be generated by a parent call + // it should compare model_env->field_index with the number of keys +// if( log ) +// { +// // IMPROVE ME a better log message is required +// (*log) << PT::Log::log1 << "Morm: incorrect number of keys found in model objects" << PT::Log::logend; +// } } } } @@ -706,8 +714,12 @@ protected: } else { - // IMPROVE ME - // put some log here + if( log ) + { + // IMPROVE ME a better log message is required + // the log can be generated by a parent call + (*log) << PT::Log::log1 << "Morm: incorrect number of keys found in model objects" << PT::Log::logend; + } } } @@ -1052,49 +1064,44 @@ protected: field_model_set_parent_key(db_field_name, flat_field_name, field_model); } - if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_ITERATE_THROUGH_CHILDS_WITH_FOREIGN_KEY_AND_INSERT && has_foreign_key ) + if( !is_empty_field(db_field_name) ) { - if( !is_empty_field(db_field_name) ) + if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_ITERATE_THROUGH_CHILDS_WITH_FOREIGN_KEY_AND_INSERT && has_foreign_key ) { field_model.insert_tree(true); } - } - if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_ITERATE_THROUGH_CHILDS_WITHOUT_FOREIGN_KEY_AND_INSERT && !has_foreign_key ) - { - if( !is_empty_field(db_field_name) ) + if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_ITERATE_THROUGH_CHILDS_WITHOUT_FOREIGN_KEY_AND_INSERT && !has_foreign_key ) { field_model.insert_tree(true); } - } - if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_ITERATE_THROUGH_CHILDS_WITH_FOREIGN_KEY_AND_UPDATE && has_foreign_key ) - { - if( !is_empty_field(db_field_name) ) + if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_ITERATE_THROUGH_CHILDS_WITH_FOREIGN_KEY_AND_UPDATE && has_foreign_key ) { field_model.update_tree(true); } - } - if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_ITERATE_THROUGH_CHILDS_WITHOUT_FOREIGN_KEY_AND_UPDATE && !has_foreign_key ) - { - if( !is_empty_field(db_field_name) ) + if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_ITERATE_THROUGH_CHILDS_WITHOUT_FOREIGN_KEY_AND_UPDATE && !has_foreign_key ) { field_model.update_tree(true); } - } - if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_ITERATE_THROUGH_CHILDS_WITH_FOREIGN_KEY_AND_SAVE && has_foreign_key ) - { - if( !is_empty_field(db_field_name) ) + if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_ITERATE_THROUGH_CHILDS_WITH_FOREIGN_KEY_AND_REMOVE && has_foreign_key ) + { + field_model.remove_tree(true); + } + + if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_ITERATE_THROUGH_CHILDS_WITHOUT_FOREIGN_KEY_AND_REMOVE && !has_foreign_key ) + { + field_model.remove_tree(true); + } + + if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_ITERATE_THROUGH_CHILDS_WITH_FOREIGN_KEY_AND_SAVE && has_foreign_key ) { field_model.save_tree(true); } - } - if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_ITERATE_THROUGH_CHILDS_WITHOUT_FOREIGN_KEY_AND_SAVE && !has_foreign_key ) - { - if( !is_empty_field(db_field_name) ) + if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_ITERATE_THROUGH_CHILDS_WITHOUT_FOREIGN_KEY_AND_SAVE && !has_foreign_key ) { field_model.save_tree(true); } diff --git a/src/modelconnector.cpp b/src/modelconnector.cpp index f73899f..9a6b45f 100644 --- a/src/modelconnector.cpp +++ b/src/modelconnector.cpp @@ -71,6 +71,11 @@ void ModelConnector::set_logger(PT::Log & log) this->log = &log; } +PT::Log * ModelConnector::get_logger() +{ + return log; +} + void ModelConnector::deallocate_stream() diff --git a/src/modelconnector.h b/src/modelconnector.h index 37dc15f..da9b4a6 100644 --- a/src/modelconnector.h +++ b/src/modelconnector.h @@ -62,6 +62,7 @@ public: virtual void set_logger(PT::Log * log); virtual void set_logger(PT::Log & log); + virtual PT::Log * get_logger(); virtual void set_stream(PT::TextStream & stream); virtual PT::TextStream * get_stream(); diff --git a/src/morm_types.h b/src/morm_types.h index ce2884f..050f693 100644 --- a/src/morm_types.h +++ b/src/morm_types.h @@ -57,11 +57,14 @@ #define MORM_MODEL_CONNECTOR_MODE_ITERATE_THROUGH_CHILDS_WITH_FOREIGN_KEY_AND_SAVE 12 #define MORM_MODEL_CONNECTOR_MODE_ITERATE_THROUGH_CHILDS_WITHOUT_FOREIGN_KEY_AND_SAVE 13 -#define MORM_MODEL_CONNECTOR_MODE_SET_PARENT_ID 14 +#define MORM_MODEL_CONNECTOR_MODE_ITERATE_THROUGH_CHILDS_WITH_FOREIGN_KEY_AND_REMOVE 14 +#define MORM_MODEL_CONNECTOR_MODE_ITERATE_THROUGH_CHILDS_WITHOUT_FOREIGN_KEY_AND_REMOVE 15 -#define MORM_MODEL_CONNECTOR_MODE_ITERATE_PRIMARY_KEY_VALUES 15 +#define MORM_MODEL_CONNECTOR_MODE_SET_PARENT_ID 16 -#define MORM_MODEL_CONNECTOR_MODE_SET_FIELD_VALUE 16 +#define MORM_MODEL_CONNECTOR_MODE_ITERATE_PRIMARY_KEY_VALUES 17 + +#define MORM_MODEL_CONNECTOR_MODE_SET_FIELD_VALUE 18 diff --git a/src/setfieldvaluehelper.h b/src/setfieldvaluehelper.h index 40c2222..b8490ae 100644 --- a/src/setfieldvaluehelper.h +++ b/src/setfieldvaluehelper.h @@ -90,7 +90,11 @@ public: { const wchar_t * db_field_name; const wchar_t * flat_field_name; + + // IMPROVE ME + // instead of FieldValueBase can we have only a pointer to void (to the value object) and a pointer to std::type_info? FieldValueBase * field_value_base; + bool auto_remove_field_value_object; Item() @@ -106,6 +110,7 @@ public: } }; + std::vector item_tab;