propagate status from childs in Model::insert, Model::update, Model::remove and Model::save

This commit is contained in:
Tomasz Sowa 2022-05-24 23:27:07 +02:00
parent 1ad4cb4fbd
commit 12232bf722
3 changed files with 103 additions and 84 deletions

View File

@ -494,12 +494,11 @@ bool Model::insert(ModelData * model_data, bool insert_whole_tree)
model_env = &model_env_local; model_env = &model_env_local;
model_env->model_data = model_data; model_env->model_data = model_data;
model_env->model = this; model_env->model = this;
bool status = false;
try try
{ {
table(); table();
status = insert_tree(insert_whole_tree); insert_tree(insert_whole_tree);
} }
catch(...) catch(...)
{ {
@ -508,30 +507,27 @@ bool Model::insert(ModelData * model_data, bool insert_whole_tree)
} }
model_env = nullptr; model_env = nullptr;
return status; return model_env_local.status;
} }
// has ModelEnv set void Model::insert_tree(bool insert_whole_tree)
// 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::insert_tree(bool insert_whole_tree)
{ {
bool result = false;
model_env->has_primary_key_set = has_primary_key_set; model_env->has_primary_key_set = has_primary_key_set;
if( insert_whole_tree ) if( model_env->status && insert_whole_tree )
{ {
model_env->model_work_mode = MORM_MODEL_WORK_MODE_ITERATE_THROUGH_CHILDS_WITH_FOREIGN_KEY; model_env->model_work_mode = MORM_MODEL_WORK_MODE_ITERATE_THROUGH_CHILDS_WITH_FOREIGN_KEY;
model_env->model_work_submode = MORM_MODEL_WORK_SUBMODE_INSERT; model_env->model_work_submode = MORM_MODEL_WORK_SUBMODE_INSERT;
fields(); fields();
} }
if( model_connector ) if( model_env->status && model_connector )
{ {
model_env->model_work_mode = MORM_MODEL_WORK_MODE_GENERATING_DB_SQL; model_env->model_work_mode = MORM_MODEL_WORK_MODE_GENERATING_DB_SQL;
DbConnector * db_connector = model_connector->get_db_connector(); DbConnector * db_connector = model_connector->get_db_connector();
// CHECK ME what if the stream is being used by something other? // CHECK ME what if the stream is being used by someone else?
pt::TextStream * out_stream = model_connector->get_stream(); pt::TextStream * out_stream = model_connector->get_stream();
if( db_connector && out_stream ) if( db_connector && out_stream )
@ -539,9 +535,9 @@ bool Model::insert_tree(bool insert_whole_tree)
before_insert(); before_insert();
out_stream->clear(); out_stream->clear();
result = db_connector->insert(*out_stream, *this); model_env->status = db_connector->insert(*out_stream, *this);
if( result ) if( model_env->status )
{ {
/* /*
* after_insert() should read the new primary key and set has_primary_key_set flag if the key was read correctly * after_insert() should read the new primary key and set has_primary_key_set flag if the key was read correctly
@ -564,16 +560,22 @@ bool Model::insert_tree(bool insert_whole_tree)
after_insert_failure(); after_insert_failure();
} }
} }
else
{
model_env->status = false;
}
}
else
{
model_env->status = false;
} }
if( insert_whole_tree ) if( model_env->status && insert_whole_tree )
{ {
model_env->model_work_mode = MORM_MODEL_WORK_MODE_ITERATE_THROUGH_CHILDS_WITHOUT_FOREIGN_KEY; model_env->model_work_mode = MORM_MODEL_WORK_MODE_ITERATE_THROUGH_CHILDS_WITHOUT_FOREIGN_KEY;
model_env->model_work_submode = MORM_MODEL_WORK_SUBMODE_INSERT; model_env->model_work_submode = MORM_MODEL_WORK_SUBMODE_INSERT;
fields(); fields();
} }
return result;
} }
@ -621,12 +623,11 @@ bool Model::update(ModelData * model_data, bool update_whole_tree)
model_env = &model_env_local; model_env = &model_env_local;
model_env->model_data = model_data; model_env->model_data = model_data;
model_env->model = this; model_env->model = this;
bool status = false;
try try
{ {
table(); table();
status = update_tree(update_whole_tree); update_tree(update_whole_tree);
} }
catch(...) catch(...)
{ {
@ -635,30 +636,28 @@ bool Model::update(ModelData * model_data, bool update_whole_tree)
} }
model_env = nullptr; model_env = nullptr;
return status; return model_env_local.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 void Model::update_tree(bool update_whole_tree)
bool Model::update_tree(bool update_whole_tree)
{ {
bool result = false;
model_env->has_primary_key_set = has_primary_key_set; model_env->has_primary_key_set = has_primary_key_set;
if( !has_primary_key_set ) if( !has_primary_key_set )
{ {
put_to_log(L"Morm: call update but model doesn't have a primary key set"); put_to_log(L"Morm: call update but model doesn't have a primary key set");
return result; model_env->status = false;
} }
if( update_whole_tree ) if( model_env->status && update_whole_tree )
{ {
model_env->model_work_mode = MORM_MODEL_WORK_MODE_ITERATE_THROUGH_CHILDS_WITH_FOREIGN_KEY; model_env->model_work_mode = MORM_MODEL_WORK_MODE_ITERATE_THROUGH_CHILDS_WITH_FOREIGN_KEY;
model_env->model_work_submode = MORM_MODEL_WORK_SUBMODE_UPDATE; model_env->model_work_submode = MORM_MODEL_WORK_SUBMODE_UPDATE;
fields(); fields();
} }
if( model_connector ) if( model_env->status && model_connector )
{ {
model_env->model_work_mode = MORM_MODEL_WORK_MODE_GENERATING_DB_SQL; model_env->model_work_mode = MORM_MODEL_WORK_MODE_GENERATING_DB_SQL;
DbConnector * db_connector = model_connector->get_db_connector(); DbConnector * db_connector = model_connector->get_db_connector();
@ -670,23 +669,29 @@ bool Model::update_tree(bool update_whole_tree)
{ {
before_update(); before_update();
out_stream->clear(); out_stream->clear();
result = db_connector->update(*out_stream, *this); model_env->status = db_connector->update(*out_stream, *this);
if( result ) if( model_env->status )
after_update(); after_update();
else else
after_update_failure(); after_update_failure();
} }
else
{
model_env->status = false;
}
}
else
{
model_env->status = false;
} }
if( update_whole_tree ) if( model_env->status && update_whole_tree )
{ {
model_env->model_work_mode = MORM_MODEL_WORK_MODE_ITERATE_THROUGH_CHILDS_WITHOUT_FOREIGN_KEY; model_env->model_work_mode = MORM_MODEL_WORK_MODE_ITERATE_THROUGH_CHILDS_WITHOUT_FOREIGN_KEY;
model_env->model_work_submode = MORM_MODEL_WORK_SUBMODE_UPDATE; model_env->model_work_submode = MORM_MODEL_WORK_SUBMODE_UPDATE;
fields(); fields();
} }
return result;
} }
@ -734,12 +739,11 @@ bool Model::remove(ModelData * model_data, bool remove_whole_tree)
model_env = &model_env_local; model_env = &model_env_local;
model_env->model_data = model_data; model_env->model_data = model_data;
model_env->model = this; model_env->model = this;
bool status = false;
try try
{ {
table(); table();
status = remove_tree(remove_whole_tree); remove_tree(remove_whole_tree);
} }
catch(...) catch(...)
{ {
@ -748,44 +752,42 @@ bool Model::remove(ModelData * model_data, bool remove_whole_tree)
} }
model_env = nullptr; model_env = nullptr;
return status; return model_env_local.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 void Model::remove_tree(bool remove_whole_tree)
bool Model::remove_tree(bool remove_whole_tree)
{ {
bool result = false;
model_env->has_primary_key_set = has_primary_key_set; model_env->has_primary_key_set = has_primary_key_set;
if( !has_primary_key_set ) if( !has_primary_key_set )
{ {
put_to_log(L"Morm: call remove but model doesn't have a primary key set"); put_to_log(L"Morm: call remove but model doesn't have a primary key set");
return result; model_env->status = false;
} }
if( remove_whole_tree ) if( model_env->status && remove_whole_tree )
{ {
model_env->model_work_mode = MORM_MODEL_WORK_MODE_ITERATE_THROUGH_CHILDS_WITHOUT_FOREIGN_KEY; model_env->model_work_mode = MORM_MODEL_WORK_MODE_ITERATE_THROUGH_CHILDS_WITHOUT_FOREIGN_KEY;
model_env->model_work_submode = MORM_MODEL_WORK_SUBMODE_REMOVE; model_env->model_work_submode = MORM_MODEL_WORK_SUBMODE_REMOVE;
fields(); fields();
} }
if( model_connector ) if( model_env->status && model_connector )
{ {
model_env->model_work_mode = MORM_MODEL_WORK_MODE_GENERATING_DB_SQL; model_env->model_work_mode = MORM_MODEL_WORK_MODE_GENERATING_DB_SQL;
DbConnector * db_connector = model_connector->get_db_connector(); DbConnector * db_connector = model_connector->get_db_connector();
// CHECK ME what if the stream is being used by something other? // CHECK ME what if the stream is being used by someone else?
pt::TextStream * out_stream = model_connector->get_stream(); pt::TextStream * out_stream = model_connector->get_stream();
if( db_connector && out_stream ) if( db_connector && out_stream )
{ {
before_remove(); before_remove();
out_stream->clear(); out_stream->clear();
result = db_connector->remove(*out_stream, *this); model_env->status = db_connector->remove(*out_stream, *this);
if( result ) if( model_env->status )
{ {
save_mode = DO_NOTHING_ON_SAVE; save_mode = DO_NOTHING_ON_SAVE;
has_primary_key_set = false; has_primary_key_set = false;
@ -797,16 +799,22 @@ bool Model::remove_tree(bool remove_whole_tree)
after_remove_failure(); after_remove_failure();
} }
} }
else
{
model_env->status = false;
}
}
else
{
model_env->status = false;
} }
if( remove_whole_tree ) if( model_env->status && remove_whole_tree )
{ {
model_env->model_work_mode = MORM_MODEL_WORK_MODE_ITERATE_THROUGH_CHILDS_WITH_FOREIGN_KEY; model_env->model_work_mode = MORM_MODEL_WORK_MODE_ITERATE_THROUGH_CHILDS_WITH_FOREIGN_KEY;
model_env->model_work_submode = MORM_MODEL_WORK_SUBMODE_REMOVE; model_env->model_work_submode = MORM_MODEL_WORK_SUBMODE_REMOVE;
fields(); fields();
} }
return result;
} }
@ -830,12 +838,11 @@ bool Model::save(ModelData * model_data, bool save_whole_tree)
model_env = &model_env_local; model_env = &model_env_local;
model_env->model_data = model_data; model_env->model_data = model_data;
model_env->model = this; model_env->model = this;
bool status = false;
try try
{ {
table(); table();
status = save_tree(save_whole_tree); save_tree(save_whole_tree);
} }
catch(...) catch(...)
{ {
@ -844,17 +851,15 @@ bool Model::save(ModelData * model_data, bool save_whole_tree)
} }
model_env = nullptr; model_env = nullptr;
return status; return model_env_local.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 void Model::save_tree(bool save_whole_tree)
bool Model::save_tree(bool save_whole_tree)
{ {
bool result = false;
model_env->has_primary_key_set = has_primary_key_set; model_env->has_primary_key_set = has_primary_key_set;
if( save_whole_tree ) if( model_env->status && save_whole_tree )
{ {
if( save_mode == DO_DELETE_ON_SAVE ) if( save_mode == DO_DELETE_ON_SAVE )
model_env->model_work_mode = MORM_MODEL_WORK_MODE_ITERATE_THROUGH_CHILDS_WITHOUT_FOREIGN_KEY; model_env->model_work_mode = MORM_MODEL_WORK_MODE_ITERATE_THROUGH_CHILDS_WITHOUT_FOREIGN_KEY;
@ -865,30 +870,32 @@ bool Model::save_tree(bool save_whole_tree)
fields(); fields();
} }
ModelEnv * old_model_env = model_env; // remove, insert or update will set model_env to nullptr if( model_env->status )
switch( save_mode )
{ {
case DO_DELETE_ON_SAVE: ModelEnv * old_model_env = model_env; // remove, insert or update will set model_env to nullptr
result = remove_tree(false);
break;
case DO_INSERT_ON_SAVE: switch( save_mode )
result = insert_tree(false); {
break; case DO_DELETE_ON_SAVE:
remove_tree(false);
break;
case DO_UPDATE_ON_SAVE: case DO_INSERT_ON_SAVE:
result = update_tree(false); insert_tree(false);
break; break;
case DO_NOTHING_ON_SAVE: case DO_UPDATE_ON_SAVE:
result = true; update_tree(false);
break; break;
case DO_NOTHING_ON_SAVE:
break;
}
model_env = old_model_env;
} }
model_env = old_model_env; if( model_env->status && save_whole_tree )
if( save_whole_tree )
{ {
if( save_mode == DO_DELETE_ON_SAVE ) if( save_mode == DO_DELETE_ON_SAVE )
model_env->model_work_mode = MORM_MODEL_WORK_MODE_ITERATE_THROUGH_CHILDS_WITH_FOREIGN_KEY; model_env->model_work_mode = MORM_MODEL_WORK_MODE_ITERATE_THROUGH_CHILDS_WITH_FOREIGN_KEY;
@ -898,8 +905,6 @@ bool Model::save_tree(bool save_whole_tree)
model_env->model_work_submode = MORM_MODEL_WORK_SUBMODE_SAVE; model_env->model_work_submode = MORM_MODEL_WORK_SUBMODE_SAVE;
fields(); fields();
} }
return result;
} }
@ -1599,6 +1604,9 @@ void Model::field_model(const wchar_t * db_field_name, const wchar_t * flat_fiel
} }
field_model.model_env = nullptr; field_model.model_env = nullptr;
if( !model_env_local.status )
model_env->status = false;
} }
} }

View File

@ -344,10 +344,10 @@ protected:
virtual ModelData * get_model_data(); virtual ModelData * get_model_data();
virtual bool insert_tree(bool insert_whole_tree); virtual void insert_tree(bool insert_whole_tree);
virtual bool update_tree(bool update_whole_tree); virtual void update_tree(bool update_whole_tree);
virtual bool remove_tree(bool remove_whole_tree); virtual void remove_tree(bool remove_whole_tree);
virtual bool save_tree(bool save_whole_tree); virtual void save_tree(bool save_whole_tree);
virtual void map_values_from_query(); virtual void map_values_from_query();
@ -1146,18 +1146,24 @@ protected:
template<typename ModelContainerType> template<typename ModelContainerType>
void field_list_iterate_through_childs(ModelContainerType & child_model, const FT & field_type) void field_list_iterate_through_childs(ModelContainerType & child_model, const FT & field_type)
{ {
ModelEnv model_env_local; if( model_env->status )
model_env_local.copy_global_objects(*model_env); {
model_env_local.model = &child_model; ModelEnv model_env_local;
model_env_local.copy_global_objects(*model_env);
model_env_local.model = &child_model;
child_model.model_env = &model_env_local; child_model.model_env = &model_env_local;
child_model.model_env->has_primary_key_set = child_model.has_primary_key_set; child_model.model_env->has_primary_key_set = child_model.has_primary_key_set;
child_model.set_connector(model_connector); child_model.set_connector(model_connector);
child_model.table(); child_model.table();
field_model_iterate_through_childs(child_model, field_type); field_model_iterate_through_childs(child_model, field_type);
child_model.model_env = nullptr; if( !model_env_local.status )
model_env->status = false;
child_model.model_env = nullptr;
}
} }

View File

@ -105,6 +105,9 @@ public:
const std::type_info * ezc_fun_info_typeinfo; const std::type_info * ezc_fun_info_typeinfo;
#endif #endif
bool status;
ModelEnv() ModelEnv()
{ {
clear(); clear();
@ -138,6 +141,7 @@ public:
stream = e.stream; stream = e.stream;
was_field_found = e.was_field_found; was_field_found = e.was_field_found;
wrapper = e.wrapper; wrapper = e.wrapper;
status = e.status;
#ifdef MORM_HAS_EZC_LIBRARY #ifdef MORM_HAS_EZC_LIBRARY
ezc_fun_info = e.ezc_fun_info; ezc_fun_info = e.ezc_fun_info;
@ -189,6 +193,7 @@ public:
stream = nullptr; stream = nullptr;
was_field_found = false; was_field_found = false;
wrapper.clear(); wrapper.clear();
status = true;
#ifdef MORM_HAS_EZC_LIBRARY #ifdef MORM_HAS_EZC_LIBRARY
ezc_fun_info = nullptr; ezc_fun_info = nullptr;