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_data = model_data;
model_env->model = this;
bool status = false;
try
{
table();
status = insert_tree(insert_whole_tree);
insert_tree(insert_whole_tree);
}
catch(...)
{
@ -508,30 +507,27 @@ bool Model::insert(ModelData * model_data, bool insert_whole_tree)
}
model_env = nullptr;
return status;
return model_env_local.status;
}
// has ModelEnv set
// 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)
void Model::insert_tree(bool insert_whole_tree)
{
bool result = false;
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_submode = MORM_MODEL_WORK_SUBMODE_INSERT;
fields();
}
if( model_connector )
if( model_env->status && model_connector )
{
model_env->model_work_mode = MORM_MODEL_WORK_MODE_GENERATING_DB_SQL;
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();
if( db_connector && out_stream )
@ -539,9 +535,9 @@ bool Model::insert_tree(bool insert_whole_tree)
before_insert();
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
@ -564,16 +560,22 @@ bool Model::insert_tree(bool insert_whole_tree)
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_submode = MORM_MODEL_WORK_SUBMODE_INSERT;
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_data = model_data;
model_env->model = this;
bool status = false;
try
{
table();
status = update_tree(update_whole_tree);
update_tree(update_whole_tree);
}
catch(...)
{
@ -635,30 +636,28 @@ bool Model::update(ModelData * model_data, bool update_whole_tree)
}
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
bool Model::update_tree(bool update_whole_tree)
void Model::update_tree(bool update_whole_tree)
{
bool result = false;
model_env->has_primary_key_set = 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");
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_submode = MORM_MODEL_WORK_SUBMODE_UPDATE;
fields();
}
if( model_connector )
if( model_env->status && model_connector )
{
model_env->model_work_mode = MORM_MODEL_WORK_MODE_GENERATING_DB_SQL;
DbConnector * db_connector = model_connector->get_db_connector();
@ -670,23 +669,29 @@ bool Model::update_tree(bool update_whole_tree)
{
before_update();
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();
else
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_submode = MORM_MODEL_WORK_SUBMODE_UPDATE;
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_data = model_data;
model_env->model = this;
bool status = false;
try
{
table();
status = remove_tree(remove_whole_tree);
remove_tree(remove_whole_tree);
}
catch(...)
{
@ -748,44 +752,42 @@ bool Model::remove(ModelData * model_data, bool remove_whole_tree)
}
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
bool Model::remove_tree(bool remove_whole_tree)
void Model::remove_tree(bool remove_whole_tree)
{
bool result = false;
model_env->has_primary_key_set = 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");
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_submode = MORM_MODEL_WORK_SUBMODE_REMOVE;
fields();
}
if( model_connector )
if( model_env->status && model_connector )
{
model_env->model_work_mode = MORM_MODEL_WORK_MODE_GENERATING_DB_SQL;
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();
if( db_connector && out_stream )
{
before_remove();
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;
has_primary_key_set = false;
@ -797,16 +799,22 @@ bool Model::remove_tree(bool remove_whole_tree)
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_submode = MORM_MODEL_WORK_SUBMODE_REMOVE;
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_data = model_data;
model_env->model = this;
bool status = false;
try
{
table();
status = save_tree(save_whole_tree);
save_tree(save_whole_tree);
}
catch(...)
{
@ -844,17 +851,15 @@ bool Model::save(ModelData * model_data, bool save_whole_tree)
}
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
bool Model::save_tree(bool save_whole_tree)
void Model::save_tree(bool save_whole_tree)
{
bool result = false;
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 )
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();
}
ModelEnv * old_model_env = model_env; // remove, insert or update will set model_env to nullptr
switch( save_mode )
if( model_env->status )
{
case DO_DELETE_ON_SAVE:
result = remove_tree(false);
break;
ModelEnv * old_model_env = model_env; // remove, insert or update will set model_env to nullptr
case DO_INSERT_ON_SAVE:
result = insert_tree(false);
break;
switch( save_mode )
{
case DO_DELETE_ON_SAVE:
remove_tree(false);
break;
case DO_UPDATE_ON_SAVE:
result = update_tree(false);
break;
case DO_INSERT_ON_SAVE:
insert_tree(false);
break;
case DO_NOTHING_ON_SAVE:
result = true;
break;
case DO_UPDATE_ON_SAVE:
update_tree(false);
break;
case DO_NOTHING_ON_SAVE:
break;
}
model_env = old_model_env;
}
model_env = old_model_env;
if( save_whole_tree )
if( model_env->status && save_whole_tree )
{
if( save_mode == DO_DELETE_ON_SAVE )
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;
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;
if( !model_env_local.status )
model_env->status = false;
}
}

View File

@ -344,10 +344,10 @@ protected:
virtual ModelData * get_model_data();
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 insert_tree(bool insert_whole_tree);
virtual void update_tree(bool update_whole_tree);
virtual void remove_tree(bool remove_whole_tree);
virtual void save_tree(bool save_whole_tree);
virtual void map_values_from_query();
@ -1146,18 +1146,24 @@ protected:
template<typename ModelContainerType>
void field_list_iterate_through_childs(ModelContainerType & child_model, const FT & field_type)
{
ModelEnv model_env_local;
model_env_local.copy_global_objects(*model_env);
model_env_local.model = &child_model;
if( model_env->status )
{
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->has_primary_key_set = child_model.has_primary_key_set;
child_model.set_connector(model_connector);
child_model.table();
child_model.model_env = &model_env_local;
child_model.model_env->has_primary_key_set = child_model.has_primary_key_set;
child_model.set_connector(model_connector);
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;
#endif
bool status;
ModelEnv()
{
clear();
@ -138,6 +141,7 @@ public:
stream = e.stream;
was_field_found = e.was_field_found;
wrapper = e.wrapper;
status = e.status;
#ifdef MORM_HAS_EZC_LIBRARY
ezc_fun_info = e.ezc_fun_info;
@ -189,6 +193,7 @@ public:
stream = nullptr;
was_field_found = false;
wrapper.clear();
status = true;
#ifdef MORM_HAS_EZC_LIBRARY
ezc_fun_info = nullptr;