Added flag has_primary_key_set to Model
Now we know whether the primary key is defined or not and we do not allow to make update/remove if the key is not defined. And when doing insert/update we can put NULL if child models don't have the primary key set (fields with has_foreign_key set to true). Now in after_select() we should also set has_primary_key_set flag or just call get_last_sequence_for_primary_key instead of get_last_sequence. fixed: added prefix +00 when serializing PT::Date to PostgreSQL (time zone) (for a column with a time zone there was a wrong value saved)
This commit is contained in:
178
src/model.cpp
178
src/model.cpp
@@ -43,6 +43,7 @@ Model::Model()
|
||||
model_connector = nullptr;
|
||||
model_env = nullptr;
|
||||
save_mode = DO_INSERT_ON_SAVE;
|
||||
has_primary_key_set = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +51,8 @@ Model::Model(const Model & m)
|
||||
{
|
||||
model_connector = m.model_connector;
|
||||
save_mode = m.save_mode;
|
||||
model_env = m.model_env; // or just set to null?
|
||||
model_env = nullptr;
|
||||
has_primary_key_set = m.has_primary_key_set;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +73,19 @@ Model::SaveMode Model::get_save_mode()
|
||||
}
|
||||
|
||||
|
||||
void Model::set_has_primary_key_set(bool has_primary_key)
|
||||
{
|
||||
this->has_primary_key_set = has_primary_key;
|
||||
}
|
||||
|
||||
|
||||
bool Model::get_has_primary_key_set()
|
||||
{
|
||||
return this->has_primary_key_set;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Model::mark_to_delete()
|
||||
{
|
||||
save_mode = DO_DELETE_ON_SAVE;
|
||||
@@ -140,8 +155,10 @@ void Model::to_text(PT::TextStream & stream, ModelData * model_data, bool clear_
|
||||
ModelEnv model_env_local;
|
||||
model_env = &model_env_local;
|
||||
|
||||
model_env->has_primary_key_set = has_primary_key_set;
|
||||
model_env->model_work_mode = MORM_MODEL_WORK_MODE_GENERATING_FLAT_STRING;
|
||||
model_env->dump_mode = dump_mode;
|
||||
model_env->model_data = model_data;
|
||||
|
||||
if( model_connector )
|
||||
{
|
||||
@@ -149,13 +166,18 @@ void Model::to_text(PT::TextStream & stream, ModelData * model_data, bool clear_
|
||||
|
||||
if( flat_connector )
|
||||
{
|
||||
model_env->model_data = model_data;
|
||||
flat_connector->to_text(stream, *this);
|
||||
model_env->model_data = nullptr;
|
||||
try
|
||||
{
|
||||
flat_connector->to_text(stream, *this);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
model_env = nullptr;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// what about if an exception was thrown? this pointer will not be null
|
||||
model_env = nullptr;
|
||||
}
|
||||
|
||||
@@ -221,6 +243,7 @@ void Model::generate_insert_query(PT::TextStream & stream, ModelData * model_dat
|
||||
{
|
||||
ModelEnv model_env_local;
|
||||
model_env = &model_env_local;
|
||||
model_env->has_primary_key_set = has_primary_key_set;
|
||||
model_env->model_data = model_data;
|
||||
model_env->model_work_mode = MORM_MODEL_WORK_MODE_GENERATING_DB_SQL;
|
||||
|
||||
@@ -230,11 +253,18 @@ void Model::generate_insert_query(PT::TextStream & stream, ModelData * model_dat
|
||||
|
||||
if( db_connector )
|
||||
{
|
||||
db_connector->generate_insert_query(stream, *this);
|
||||
try
|
||||
{
|
||||
db_connector->generate_insert_query(stream, *this);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
model_env = nullptr;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// what about if an exception was thrown? this pointer will not be null
|
||||
model_env = nullptr;
|
||||
}
|
||||
|
||||
@@ -257,11 +287,19 @@ bool Model::insert(ModelData * model_data, bool insert_whole_tree)
|
||||
model_env = &model_env_local;
|
||||
|
||||
model_env->model_data = model_data;
|
||||
bool status = insert_tree(insert_whole_tree);
|
||||
bool status = false;
|
||||
|
||||
try
|
||||
{
|
||||
status = insert_tree(insert_whole_tree);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
model_env = nullptr;
|
||||
throw;
|
||||
}
|
||||
|
||||
// what about if an exception was thrown? this pointer will not be null
|
||||
model_env = nullptr;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -271,6 +309,8 @@ bool Model::insert(ModelData * model_data, bool insert_whole_tree)
|
||||
bool Model::insert_tree(bool insert_whole_tree)
|
||||
{
|
||||
bool result = false;
|
||||
has_primary_key_set = false; // the key will be overwritten (the database will create a new key)
|
||||
model_env->has_primary_key_set = false;
|
||||
|
||||
if( insert_whole_tree )
|
||||
{
|
||||
@@ -296,9 +336,21 @@ bool Model::insert_tree(bool insert_whole_tree)
|
||||
|
||||
if( result )
|
||||
{
|
||||
save_mode = DO_UPDATE_ON_SAVE; // IMPROVE ME check if there is a primary key
|
||||
/*
|
||||
* after_insert() should read the new primary key and set has_primary_key_set flag if the key was read correctly
|
||||
*/
|
||||
after_insert();
|
||||
set_parent_key_in_childs();
|
||||
model_env->has_primary_key_set = has_primary_key_set;
|
||||
|
||||
if( has_primary_key_set )
|
||||
{
|
||||
save_mode = DO_UPDATE_ON_SAVE;
|
||||
set_parent_key_in_childs(); // may it would be better to set it even if we do not have a primary key? set it to zero or something?
|
||||
}
|
||||
else
|
||||
{
|
||||
save_mode = DO_NOTHING_ON_SAVE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -323,6 +375,7 @@ void Model::generate_update_query(PT::TextStream & stream, ModelData * model_dat
|
||||
{
|
||||
ModelEnv model_env_local;
|
||||
model_env = &model_env_local;
|
||||
model_env->has_primary_key_set = has_primary_key_set;
|
||||
model_env->model_data = model_data;
|
||||
model_env->model_work_mode = MORM_MODEL_WORK_MODE_GENERATING_DB_SQL;
|
||||
|
||||
@@ -359,11 +412,19 @@ bool Model::update(ModelData * model_data, bool update_whole_tree)
|
||||
model_env = &model_env_local;
|
||||
|
||||
model_env->model_data = model_data;
|
||||
bool status = update_tree(update_whole_tree);
|
||||
bool status = false;
|
||||
|
||||
try
|
||||
{
|
||||
status = update_tree(update_whole_tree);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
model_env = nullptr;
|
||||
throw;
|
||||
}
|
||||
|
||||
// what about if an exception was thrown? this pointer will not be null
|
||||
model_env = nullptr;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -372,6 +433,13 @@ bool Model::update(ModelData * model_data, 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;
|
||||
|
||||
if( !has_primary_key_set )
|
||||
{
|
||||
put_to_log(L"Morm: call update but model doesn't have a primary key set");
|
||||
return result;
|
||||
}
|
||||
|
||||
if( update_whole_tree )
|
||||
{
|
||||
@@ -416,6 +484,7 @@ void Model::generate_remove_query(PT::TextStream & stream, ModelData * model_dat
|
||||
{
|
||||
ModelEnv model_env_local;
|
||||
model_env = &model_env_local;
|
||||
model_env->has_primary_key_set = has_primary_key_set;
|
||||
model_env->model_data = model_data;
|
||||
model_env->model_work_mode = MORM_MODEL_WORK_MODE_GENERATING_DB_SQL;
|
||||
|
||||
@@ -453,11 +522,19 @@ bool Model::remove(ModelData * model_data, bool remove_whole_tree)
|
||||
model_env = &model_env_local;
|
||||
|
||||
model_env->model_data = model_data;
|
||||
bool status = remove_tree(remove_whole_tree);
|
||||
bool status = false;
|
||||
|
||||
try
|
||||
{
|
||||
status = remove_tree(remove_whole_tree);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
model_env = nullptr;
|
||||
throw;
|
||||
}
|
||||
|
||||
// what about if an exception was thrown? this pointer will not be null
|
||||
model_env = nullptr;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -466,6 +543,13 @@ bool Model::remove(ModelData * model_data, 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;
|
||||
|
||||
if( !has_primary_key_set )
|
||||
{
|
||||
put_to_log(L"Morm: call remove but model doesn't have a primary key set");
|
||||
return result;
|
||||
}
|
||||
|
||||
if( remove_whole_tree )
|
||||
{
|
||||
@@ -490,7 +574,9 @@ bool Model::remove_tree(bool remove_whole_tree)
|
||||
|
||||
if( result )
|
||||
{
|
||||
save_mode = DO_INSERT_ON_SAVE; // CHECKME may it would be better to set DO_NOTHING_ON_SAVE?
|
||||
save_mode = DO_NOTHING_ON_SAVE;
|
||||
has_primary_key_set = false;
|
||||
model_env->has_primary_key_set = false;
|
||||
after_remove();
|
||||
}
|
||||
else
|
||||
@@ -531,11 +617,19 @@ bool Model::save(ModelData * model_data, bool save_whole_tree)
|
||||
model_env = &model_env_local;
|
||||
|
||||
model_env->model_data = model_data;
|
||||
bool status = save_tree(save_whole_tree);
|
||||
bool status = false;
|
||||
|
||||
try
|
||||
{
|
||||
status = save_tree(save_whole_tree);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
model_env = nullptr;
|
||||
throw;
|
||||
}
|
||||
|
||||
// what about if an exception was thrown? this pointer will not be null
|
||||
model_env = nullptr;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -544,6 +638,7 @@ bool Model::save(ModelData * model_data, 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;
|
||||
|
||||
if( save_whole_tree )
|
||||
{
|
||||
@@ -617,17 +712,20 @@ void Model::map_values_from_query()
|
||||
if( model_env )
|
||||
{
|
||||
model_env->model_work_mode = MORM_MODEL_WORK_MODE_READING_VALUE_FROM_DB_RESULTSET;
|
||||
model_env->all_fields_are_null = true;
|
||||
model_env->was_primary_key_read = false; // whether or not there was at least one column with primary_key flag
|
||||
model_env->has_primary_key_set = true; // whether all primary_columns were different than null
|
||||
map_fields();
|
||||
model_env->model_work_mode = MORM_MODEL_WORK_MODE_NONE;
|
||||
|
||||
if( model_env->all_fields_are_null )
|
||||
if( model_env->was_primary_key_read && model_env->has_primary_key_set )
|
||||
{
|
||||
save_mode = DO_NOTHING_ON_SAVE;
|
||||
has_primary_key_set = true;
|
||||
save_mode = DO_UPDATE_ON_SAVE;
|
||||
}
|
||||
else
|
||||
{
|
||||
save_mode = DO_UPDATE_ON_SAVE;
|
||||
has_primary_key_set = false;
|
||||
save_mode = DO_NOTHING_ON_SAVE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -640,10 +738,20 @@ void Model::clear()
|
||||
model_env = &model_env_local;
|
||||
|
||||
model_env->model_work_mode = MORM_MODEL_WORK_MODE_CLEARING_VALUE;
|
||||
map_fields();
|
||||
model_env = nullptr;
|
||||
|
||||
try
|
||||
{
|
||||
map_fields();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
model_env = nullptr;
|
||||
throw;
|
||||
}
|
||||
|
||||
model_env = nullptr;
|
||||
save_mode = DO_INSERT_ON_SAVE;
|
||||
has_primary_key_set = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -794,6 +902,20 @@ void Model::put_table_name_with_index(PT::TextStream & str)
|
||||
}
|
||||
|
||||
|
||||
void Model::put_to_log(const wchar_t * str)
|
||||
{
|
||||
if( model_connector )
|
||||
{
|
||||
PT::Log * log = model_connector->get_logger();
|
||||
|
||||
if( log )
|
||||
{
|
||||
(*log) << str << PT::Log::logend;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Model::put_fields_to_log(PT::Log & log, const wchar_t * db_field_name, const wchar_t * flat_field_name)
|
||||
{
|
||||
bool was_db_field_put = false;
|
||||
|
Reference in New Issue
Block a user