- added support for calling member functions (setters/getters) from Models

those functions can be used with databases and flat files
- removed support for calling static function
- if MORM_HAS_EZC_LIBRARY macro is defined then we can call a function
  which has a first argument Ezc::FunInfo<>& object
  (only for generating flat files)
This commit is contained in:
2021-06-01 19:34:34 +02:00
parent 515e806a50
commit dd01fafa40
9 changed files with 444 additions and 108 deletions

View File

@@ -240,6 +240,43 @@ void Model::get_table_name(std::string & str, bool with_schema_name, ModelData *
}
Model * Model::get_field_model(const wchar_t * db_field_name, const wchar_t * flat_field_name)
{
ModelEnv model_env_local;
model_env = &model_env_local;
model_env->model_work_mode = MORM_MODEL_WORK_MODE_GET_FIELD_MODEL;
model_env->flat_field_name = flat_field_name;
model_env->model = this;
Model * model = nullptr;
try
{
fields();
model = model_env->child_model;
}
catch(...)
{
model_env = nullptr;
throw;
}
if( !model_env->model && model_connector )
{
pt::Log * plog = model_connector->get_logger();
if( plog )
{
(*plog) << pt::Log::log1 << "Morm: I cannot find such a property: ";
put_fields_to_log(*plog, db_field_name, flat_field_name);
(*plog) << pt::Log::logend;
}
}
model_env = nullptr;
return model;
}
void Model::put_field_value(const wchar_t * flat_field_name, pt::TextStream & stream, bool clear_stream)
{
put_field_value(flat_field_name, nullptr, stream, clear_stream);
@@ -255,10 +292,10 @@ void Model::put_field_value(const wchar_t * flat_field_name, ModelData * model_d
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->model_data = model_data;
model_env->model = this;
if( model_connector )
{
@@ -295,11 +332,11 @@ 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;
model_env->model = this;
if( model_connector )
{
@@ -389,6 +426,7 @@ void Model::generate_insert_query(pt::TextStream & stream, ModelData * model_dat
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;
model_env->model = this;
if( model_connector )
{
@@ -429,8 +467,8 @@ bool Model::insert(ModelData * model_data, bool insert_whole_tree)
{
ModelEnv model_env_local;
model_env = &model_env_local;
model_env->model_data = model_data;
model_env->model = this;
bool status = false;
try
@@ -522,6 +560,7 @@ void Model::generate_update_query(pt::TextStream & stream, ModelData * model_dat
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;
model_env->model = this;
if( model_connector )
{
@@ -555,8 +594,8 @@ bool Model::update(ModelData * model_data, bool update_whole_tree)
{
ModelEnv model_env_local;
model_env = &model_env_local;
model_env->model_data = model_data;
model_env->model = this;
bool status = false;
try
@@ -633,6 +672,7 @@ void Model::generate_remove_query(pt::TextStream & stream, ModelData * model_dat
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;
model_env->model = this;
if( model_connector )
{
@@ -667,8 +707,8 @@ 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;
model_env->model = this;
bool status = false;
try
@@ -763,8 +803,8 @@ bool Model::save(ModelData * model_data, bool save_whole_tree)
{
ModelEnv model_env_local;
model_env = &model_env_local;
model_env->model_data = model_data;
model_env->model = this;
bool status = false;
try
@@ -885,8 +925,8 @@ void Model::clear()
{
ModelEnv model_env_local;
model_env = &model_env_local;
model_env->model_work_mode = MORM_MODEL_WORK_MODE_CLEARING_VALUE;
model_env->model = this;
try
{
@@ -1002,20 +1042,7 @@ bool Model::is_the_same_field(const wchar_t * field1, const wchar_t * field2)
if( is_empty_field(field1) || is_empty_field(field2) )
return false;
bool the_same = false;
while( *field1 && *field2 )
{
field1 += 1;
field2 += 1;
}
if( *field1 == 0 && *field2 == 0 )
{
the_same = true;
}
return the_same;
return pt::is_equal(field1, field2);
}
@@ -1243,9 +1270,10 @@ void Model::field_model_set_parent_key_in_child(const wchar_t * db_field_name, M
model_env_local.model_work_mode = MORM_MODEL_WORK_MODE_SET_FIELD_VALUE;
model_env_local.field_value_helper_tab = &helper_tab;
model_env_local.field_index = 0;
model_env_local.model = &field_model;
field_model.model_env = &model_env_local;
field_model.table();
field_model.fields();
if( (size_t)field_model.model_env->field_index != helper_tab.size() && log )
@@ -1477,6 +1505,7 @@ void Model::field_model(const wchar_t * db_field_name, const wchar_t * flat_fiel
{
ModelEnv model_env_local;
model_env_local.copy_global_objects(*model_env);
model_env_local.model = &field_model;
field_model.model_env = &model_env_local;
field_model.model_env->has_primary_key_set = field_model.has_primary_key_set;
@@ -1519,10 +1548,9 @@ void Model::field_model(const wchar_t * db_field_name, const wchar_t * flat_fiel
if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_GET_FIELD_MODEL )
{
//if( pt::is_equal(db_field_name, model_env->db_field_model) && pt::is_equal(flat_field_name, model_env->flat_field_name) )
if( flat_field_name && model_env->flat_field_name && pt::is_equal(flat_field_name, model_env->flat_field_name) )
model_env->model = &field_model;
model_env->child_model = &field_model;
}
field_model.model_env = nullptr;
@@ -1623,5 +1651,180 @@ bool Model::db_query(const pt::TextStream & raw_sql)
void Model::field_member_set_field_value(
const wchar_t * db_field_name,
const wchar_t * flat_field_name,
void (Model::*setter_method)(const char * input_str))
{
if( model_env->field_value_helper_tab )
{
if( model_env->field_index >= 0 && (size_t)model_env->field_index < model_env->field_value_helper_tab->size() )
{
FieldValueHelper & helper = (*model_env->field_value_helper_tab)[model_env->field_index];
pt::Log * log = model_connector->get_logger();
if( (!helper.compare_db_field_name || is_the_same_field(db_field_name, helper.db_field_name)) &&
(!helper.compare_flat_field_name || is_the_same_field(flat_field_name, helper.flat_field_name)) )
{
if( helper.value_object && helper.value_type_info )
{
const char * p_const_char_type;
if( typeid(p_const_char_type) == *helper.value_type_info )
{
const char * const * p_str = reinterpret_cast<const char * const *>(helper.value_object);
(model_env->model->*setter_method)(*p_str);
}
else
{
if( log )
{
(*log) << pt::Log::log1 << "Morm: incorrect type of a field in ";
log_table_name();
(*log) << ", ";
put_fields_to_log(*log, db_field_name, flat_field_name);
(*log) << ", type expected " << typeid(p_const_char_type).name()
<< " got " << helper.value_type_info->name() << pt::Log::logend;
}
}
}
helper.found = true;
model_env->field_index += 1;
}
}
}
}
void Model::field_member_generate_flat_string(
const wchar_t * flat_field_name,
void (Model::*getter_method)(pt::TextStream &),
const FT & field_type)
{
FlatConnector * flat_connector = model_connector->get_flat_connector();
if( flat_connector )
{
FlatExpression * flat_expression = flat_connector->get_expression();
if( flat_expression && !is_empty_field(flat_field_name) )
{
flat_expression->field(flat_field_name, getter_method, field_type, model_env);
}
}
}
void Model::field_member_generate_db_sql(
const wchar_t * db_field_name,
void (Model::*getter_method)(pt::TextStream &),
const FT & field_type)
{
DbConnector * db_connector = model_connector->get_db_connector();
if( db_connector )
{
DbExpression * db_expression = db_connector->get_expression();
if( db_expression && !is_empty_field(db_field_name) )
{
// dodac do FT raw_value
// jest raw_value jest zdefiniowane to nie wykonujemy eskejpowania
// (jesli nie zdefiniowane to zrobic tymczasowy strumien ktory zostanie dostarczony
// do getter_method i pozniej z tego strumienia wykopiowac z eskejpowaniem i wstawic do normalnego strumienia)
db_expression->field(db_field_name, getter_method, field_type, model_env);
}
}
}
void Model::field_member_read_value_from_db_resultset(
const wchar_t * db_field_name,
void (Model::*setter_method)(const char * input_str),
const FT & field_type)
{
if( model_env && model_env->model )
{
if( field_type.is_binary() || field_type.is_hexadecimal() )
{
std::string db_value;
field_generic_read_value_from_db_resultset(db_field_name, db_value, field_type);
(model_env->model->*setter_method)(db_value.c_str());
}
else
{
std::string_view db_value;
field_generic_read_value_from_db_resultset(db_field_name, db_value, field_type);
if( db_value.data() != nullptr )
{
// the string is already null terminated (by the database)
(model_env->model->*setter_method)(db_value.data());
}
}
}
}
void Model::field_member_clear_value(
void (Model::*setter_method)(const char * input_str),
const FT & field_type)
{
char buffer[1] = {0};
(model_env->model->*setter_method)(buffer);
}
void Model::field_member(
const wchar_t * db_field_name,
const wchar_t * flat_field_name,
void (Model::*getter_method)(pt::TextStream &),
void (Model::*setter_method)(const char * input_str),
const FT & field_type)
{
if( model_connector && model_env && model_env->model )
{
if( field_type.is_primary_key() )
{
pt::Log * plog = model_connector->get_logger();
if( plog )
{
(*plog) << pt::Log::log1 << "Morm:: getters and setters cannot be used as a primary key" << pt::Log::logend;
}
}
if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_SET_FIELD_VALUE )
{
field_member_set_field_value(db_field_name, flat_field_name, setter_method);
}
if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_GENERATING_FLAT_STRING )
{
field_member_generate_flat_string(flat_field_name, getter_method, field_type);
}
if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_GENERATING_DB_SQL )
{
field_member_generate_db_sql(db_field_name, getter_method, field_type);
}
if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_READING_VALUE_FROM_DB_RESULTSET )
{
field_member_read_value_from_db_resultset(db_field_name, setter_method, field_type);
}
if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_CLEARING_VALUE )
{
field_member_clear_value(setter_method, field_type);
}
}
}
} // namespace