diff --git a/src/Makefile.dep b/src/Makefile.dep index 6940b12..9345e1c 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep @@ -4,15 +4,16 @@ baseexpression.o: baseexpression.h morm_types.h modelenv.h modeldata.h baseexpression.o: cursorhelper.h queryresult.h finderhelper.h baseexpression.o: fieldvaluehelper.h ft.h model.h modelconnector.h clearer.h baseexpression.o: dbconnector.h flatconnector.h dbexpression.h -baseexpression.o: flatexpression.h +baseexpression.o: flatexpression.h modelwrapper.h clearer.o: clearer.h model.h modelconnector.h dbconnector.h queryresult.h clearer.o: ft.h flatconnector.h dbexpression.h baseexpression.h morm_types.h clearer.o: modelenv.h modeldata.h cursorhelper.h finderhelper.h -clearer.o: fieldvaluehelper.h flatexpression.h +clearer.o: fieldvaluehelper.h flatexpression.h modelwrapper.h dbconnector.o: dbconnector.h queryresult.h ft.h dbexpression.h dbconnector.o: baseexpression.h morm_types.h modelenv.h modeldata.h dbconnector.o: cursorhelper.h finderhelper.h fieldvaluehelper.h model.h dbconnector.o: modelconnector.h clearer.h flatconnector.h flatexpression.h +dbconnector.o: modelwrapper.h dbexpression.o: dbexpression.h baseexpression.h morm_types.h modelenv.h dbexpression.o: modeldata.h cursorhelper.h queryresult.h finderhelper.h dbexpression.o: fieldvaluehelper.h ft.h @@ -20,6 +21,7 @@ flatconnector.o: flatconnector.h flatexpression.h baseexpression.h flatconnector.o: morm_types.h modelenv.h modeldata.h cursorhelper.h flatconnector.o: queryresult.h finderhelper.h fieldvaluehelper.h ft.h model.h flatconnector.o: modelconnector.h clearer.h dbconnector.h dbexpression.h +flatconnector.o: modelwrapper.h flatexpression.o: flatexpression.h baseexpression.h morm_types.h modelenv.h flatexpression.o: modeldata.h cursorhelper.h queryresult.h finderhelper.h flatexpression.o: fieldvaluehelper.h ft.h @@ -33,7 +35,7 @@ jsonexpression.o: queryresult.h finderhelper.h fieldvaluehelper.h ft.h model.o: model.h modelconnector.h clearer.h dbconnector.h queryresult.h ft.h model.o: flatconnector.h dbexpression.h baseexpression.h morm_types.h model.o: modelenv.h modeldata.h cursorhelper.h finderhelper.h -model.o: fieldvaluehelper.h flatexpression.h +model.o: fieldvaluehelper.h flatexpression.h modelwrapper.h modelconnector.o: modelconnector.h clearer.h dbconnector.h queryresult.h ft.h modelconnector.o: flatconnector.h postgresqlconnector.o: postgresqlconnector.h dbconnector.h queryresult.h ft.h diff --git a/src/baseexpression.cpp b/src/baseexpression.cpp index 8b8ac84..ee522f2 100644 --- a/src/baseexpression.cpp +++ b/src/baseexpression.cpp @@ -206,73 +206,6 @@ void BaseExpression::put_field_name(const wchar_t * field_name, const FT & field } -void BaseExpression::field(const wchar_t * field_name, void (Model::*getter_method)(pt::TextStream &), const FT & field_type, ModelEnv * model_env) -{ - if( out_stream && can_field_be_generated(field_type) ) - { - field_before(); - - if( work_mode == MORM_WORK_MODE_MODEL_FIELDS ) - { - put_field_name_and_table_if_needed(field_name, field_type, model_env); - } - else - if( work_mode == MORM_WORK_MODE_MODEL_VALUES ) - { - put_field_value(getter_method, field_type, model_env); - } - else - if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES ) - { - if( model_env && model_env->set_field_name_helper ) - { - if( (size_t)model_env->field_index < model_env->set_field_name_helper->size() ) - { - put_field_name_and_table_if_needed((*model_env->set_field_name_helper)[model_env->field_index], field_type, model_env); - put_name_value_separator(); - put_field_value(getter_method, field_type, model_env); - } - - model_env->field_index += 1; - } - else - { - put_field_name_and_table_if_needed(field_name, field_type, model_env); - put_name_value_separator(); - put_field_value(getter_method, field_type, model_env); - } - } - else - if( work_mode == MORM_WORK_MODE_GET_SPECIFIC_FIELD_VALUE ) - { - if( model_env && model_env->flat_field_name && pt::is_equal(model_env->flat_field_name, field_name) ) - { - put_field_value(getter_method, field_type, model_env); - } - } - - field_after(); - } -} - - -void BaseExpression::put_field_value(void (Model::*getter_method)(pt::TextStream &), const FT & field_type, ModelEnv * model_env) -{ - if( model_env && model_env->model && out_stream ) - { - // IMPROVEME - // if field_type is something like raw_value then don't call before_field_value_string() and after...() - // and don't do escaping - - before_field_value_string(field_type); - - // FIXME add escaping, we need to create a tmp buffer pt::TextStream and this buffer put to getter_method - (model_env->model->*getter_method)(*out_stream); - after_field_value_string(field_type); - } -} - - void BaseExpression::save_foreign_key(const wchar_t * field_name, const FT & field_type, ModelEnv * model_env) { @@ -592,14 +525,13 @@ void BaseExpression::esc(unsigned long val, pt::TextStream & stream, const FT & void BaseExpression::esc(long long val, pt::TextStream & stream, const FT & field_type) { - // not implemented in pt::TextStream yet - //stream << val; + stream << val; } void BaseExpression::esc(unsigned long long val, pt::TextStream & stream, const FT & field_type) { - //stream << val; + stream << val; } @@ -617,8 +549,7 @@ void BaseExpression::esc(double val, pt::TextStream & stream, const FT & field_t void BaseExpression::esc(long double val, pt::TextStream & stream, const FT & field_type) { - // IMPLEMENT ME in pt::TextStream - //stream << val; + stream << val; } @@ -627,6 +558,7 @@ void BaseExpression::esc(const pt::Date & date, pt::TextStream & stream, const F stream << date; } + void BaseExpression::esc(const pt::TextStream & val, pt::TextStream & stream, const FT & field_type) { pt::TextStream::const_iterator i = val.begin(); @@ -637,6 +569,7 @@ void BaseExpression::esc(const pt::TextStream & val, pt::TextStream & stream, co } } + void BaseExpression::esc(const pt::WTextStream & val, pt::TextStream & stream, const FT & field_type) { pt::WTextStream::const_iterator i = val.begin(); @@ -647,6 +580,7 @@ void BaseExpression::esc(const pt::WTextStream & val, pt::TextStream & stream, c } } + void BaseExpression::esc(const pt::Space & space, pt::TextStream & stream, const FT & field_type) { pt::WTextStream tmp_stream; diff --git a/src/baseexpression.h b/src/baseexpression.h index 8bbb01b..9447f68 100644 --- a/src/baseexpression.h +++ b/src/baseexpression.h @@ -122,79 +122,12 @@ public: put_field_value_or_null(field_value, field_type, model_env); } } - else - if( work_mode == MORM_WORK_MODE_GET_SPECIFIC_FIELD_VALUE ) - { - if( model_env && model_env->flat_field_name && pt::is_equal(model_env->flat_field_name, field_name) ) - { - put_field_value_or_null(field_value, field_type, model_env); - } - } field_after(); } } - - virtual void field(const wchar_t * field_name, void (Model::*getter_method)(pt::TextStream &), const FT & field_type, ModelEnv * model_env); - - - -#ifdef MORM_HAS_EZC_LIBRARY - template - void field(const wchar_t * field_name, void (Model::*fun)(Ezc::FunInfo &), const FT & field_type, ModelEnv * model_env) - { - if( out_stream && can_field_be_generated(field_type) ) - { - field_before(); - - if( work_mode == MORM_WORK_MODE_MODEL_FIELDS ) - { - put_field_name_and_table_if_needed(field_name, field_type, model_env); - } - else - if( work_mode == MORM_WORK_MODE_MODEL_VALUES ) - { - put_field_value(fun, field_type, model_env); - } - else - if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES ) - { - if( model_env && model_env->set_field_name_helper ) - { - if( (size_t)model_env->field_index < model_env->set_field_name_helper->size() ) - { - put_field_name_and_table_if_needed((*model_env->set_field_name_helper)[model_env->field_index], field_type, model_env); - put_name_value_separator(); - put_field_value(fun, field_type, model_env); - } - - model_env->field_index += 1; - } - else - { - put_field_name_and_table_if_needed(field_name, field_type, model_env); - put_name_value_separator(); - put_field_value(fun, field_type, model_env); - } - } - else - if( work_mode == MORM_WORK_MODE_GET_SPECIFIC_FIELD_VALUE ) - { - if( model_env && model_env->flat_field_name && pt::is_equal(model_env->flat_field_name, field_name) ) - { - put_field_value(fun, field_type, model_env); - } - } - - field_after(); - } - } -#endif - - - template void put_field_value_or_null(const FieldValue & field_value, const FT & field_type, ModelEnv * model_env) { @@ -212,28 +145,6 @@ public: } - void put_field_value(void (Model::*getter_method)(pt::TextStream &), const FT & field_type, ModelEnv * model_env); - - - -#ifdef MORM_HAS_EZC_LIBRARY - template - void put_field_value(void (Model::*getter_method)(Ezc::FunInfo &), const FT & field_type, ModelEnv * model_env) - { - if( model_env && model_env->model && model_env->ezc_fun_info && model_env->ezc_fun_info_typeinfo ) - { - if( typeid(Ezc::FunInfo) == *model_env->ezc_fun_info_typeinfo ) - { - before_field_value_string(field_type); - (model_env->model->*getter_method)(*reinterpret_cast*>(model_env->ezc_fun_info)); - after_field_value_string(field_type); - } - } - } -#endif - - - template void field_in(pt::TextStream & stream, const wchar_t * field_name, const std::set & container, ModelEnv * model_env) { diff --git a/src/flatconnector.cpp b/src/flatconnector.cpp index 67375e5..a7ea051 100644 --- a/src/flatconnector.cpp +++ b/src/flatconnector.cpp @@ -83,22 +83,6 @@ void FlatConnector::to_text(pt::TextStream & stream, Model & model) -void FlatConnector::to_text(const wchar_t * flat_field_name, pt::TextStream & stream, Model & model) -{ - allocate_default_expression_if_needed(); - - if( flat_expression && model.model_env ) - { - flat_expression->clear(); - flat_expression->set_work_mode(MORM_WORK_MODE_GET_SPECIFIC_FIELD_VALUE); - flat_expression->allow_to_use_prefix(false); - model.model_env->flat_field_name = flat_field_name; - flat_expression->generate_from_model(stream, model); - } -} - - - void FlatConnector::deallocate_expression() { diff --git a/src/flatconnector.h b/src/flatconnector.h index 1cd3f87..cf0587c 100644 --- a/src/flatconnector.h +++ b/src/flatconnector.h @@ -52,7 +52,6 @@ public: virtual ~FlatConnector(); virtual void to_text(pt::TextStream & stream, Model & model); - virtual void to_text(const wchar_t * flat_field_name, pt::TextStream & stream, Model & model); virtual void set_expression(FlatExpression & expression); virtual FlatExpression * get_expression(); diff --git a/src/jsonexpression.cpp b/src/jsonexpression.cpp index 94a9a58..9b1db1b 100644 --- a/src/jsonexpression.cpp +++ b/src/jsonexpression.cpp @@ -68,7 +68,7 @@ void JSONExpression::field_before() { BaseExpression::field_before(); - if( !is_first_field && work_mode != MORM_WORK_MODE_GET_SPECIFIC_FIELD_VALUE ) + if( !is_first_field ) { (*out_stream) << ","; } @@ -90,14 +90,12 @@ void JSONExpression::after_field_name() void JSONExpression::before_field_value_string(const FT & field_type) { - if( work_mode != MORM_WORK_MODE_GET_SPECIFIC_FIELD_VALUE ) - (*out_stream) << "\""; + (*out_stream) << "\""; } void JSONExpression::after_field_value_string(const FT & field_type) { - if( work_mode != MORM_WORK_MODE_GET_SPECIFIC_FIELD_VALUE ) - (*out_stream) << "\""; + (*out_stream) << "\""; } diff --git a/src/model.cpp b/src/model.cpp index 5f75430..3db73a8 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -240,11 +240,12 @@ 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) +Model * Model::get_model(const wchar_t * db_field_name, const wchar_t * flat_field_name, bool put_log_if_not_found) { ModelEnv model_env_local; model_env = &model_env_local; model_env->model_work_mode = MORM_MODEL_WORK_MODE_GET_FIELD_MODEL; + model_env->db_field_name = db_field_name; model_env->flat_field_name = flat_field_name; model_env->model = this; Model * model = nullptr; @@ -260,7 +261,7 @@ Model * Model::get_field_model(const wchar_t * db_field_name, const wchar_t * fl throw; } - if( !model_env->model && model_connector ) + if( !model_env->model && model_connector && put_log_if_not_found ) { pt::Log * plog = model_connector->get_logger(); @@ -277,13 +278,52 @@ Model * Model::get_field_model(const wchar_t * db_field_name, const wchar_t * fl } -void Model::put_field_value(const wchar_t * flat_field_name, pt::TextStream & stream, bool clear_stream) +ModelWrapper * Model::get_model_wrapper(const wchar_t * db_field_name, const wchar_t * flat_field_name, bool put_log_if_not_found) { - put_field_value(flat_field_name, nullptr, stream, clear_stream); + ModelEnv model_env_local; + model_env = &model_env_local; + model_env->model_work_mode = MORM_MODEL_WORK_MODE_GET_MODEL_WRAPPER; + model_env->db_field_name = db_field_name; + model_env->flat_field_name = flat_field_name; + model_env->model = this; + ModelWrapper * models_base = nullptr; + + try + { + fields(); + models_base = model_env->model_wrapper; + } + catch(...) + { + model_env = nullptr; + throw; + } + + if( !model_env->model_wrapper && model_connector && put_log_if_not_found ) + { + 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 models_base; } -void Model::put_field_value(const wchar_t * flat_field_name, ModelData * model_data, pt::TextStream & stream, bool clear_stream) + +void Model::get_raw_value(const wchar_t * db_field_name, const wchar_t * flat_field_name, pt::TextStream & stream, bool clear_stream, bool put_log_if_not_found) +{ + get_raw_value(db_field_name, flat_field_name, nullptr, stream, clear_stream, put_log_if_not_found); +} + + +void Model::get_raw_value(const wchar_t * db_field_name, const wchar_t * flat_field_name, ModelData * model_data, pt::TextStream & stream, bool clear_stream, bool put_log_if_not_found) { if( clear_stream ) { @@ -293,25 +333,32 @@ 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_work_mode = MORM_MODEL_WORK_MODE_PUT_FIELD_RAW_VALUE_TO_STREAM; + model_env->db_field_name = db_field_name; + model_env->flat_field_name = flat_field_name; model_env->model_data = model_data; + model_env->stream = &stream; model_env->model = this; - if( model_connector ) + try { - FlatConnector * flat_connector = model_connector->get_flat_connector(); + fields(); + } + catch(...) + { + model_env = nullptr; + throw; + } - if( flat_connector ) + if( !model_env->model_wrapper && model_connector && put_log_if_not_found ) + { + pt::Log * plog = model_connector->get_logger(); + + if( plog ) { - try - { - flat_connector->to_text(flat_field_name, stream, *this); - } - catch(...) - { - model_env = nullptr; - throw; - } + (*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; } } @@ -1470,6 +1517,7 @@ void Model::field_model_clear_values(Model & field_model) } + void Model::field_model_read_values_from_queryresult(const wchar_t * db_field_name, Model & field_model, const FT & field_type) { DbConnector * db_connector = model_connector->get_db_connector(); @@ -1548,9 +1596,21 @@ 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) ) + if( is_the_same_field(db_field_name, model_env->db_field_name) && + is_the_same_field(flat_field_name, model_env->flat_field_name) ) + { model_env->child_model = &field_model; + } + } + + if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_GET_MODEL_WRAPPER ) + { + if( (is_empty_field(model_env->db_field_name) || is_the_same_field(db_field_name, model_env->db_field_name)) && + (is_empty_field(model_env->flat_field_name) || is_the_same_field(flat_field_name, model_env->flat_field_name)) && + !model_env->model_wrapper ) + { + model_env->model_wrapper = new ModelWrapperModel(&field_model); + } } field_model.model_env = nullptr; @@ -1769,6 +1829,23 @@ void Model::field_member_read_value_from_db_resultset( } +void Model::field_member_put_field_raw_value_to_stream( + const wchar_t * db_field_name, + const wchar_t * flat_field_name, + void (Model::*getter_method)(pt::TextStream &), + const FT & field_type) +{ + if( (is_empty_field(model_env->db_field_name) || is_the_same_field(db_field_name, model_env->db_field_name)) && + (is_empty_field(model_env->flat_field_name) || is_the_same_field(flat_field_name, model_env->flat_field_name)) ) + { + if( model_env->stream ) + { + (model_env->model->*getter_method)(*model_env->stream); + } + } +} + + void Model::field_member_clear_value( void (Model::*setter_method)(const char * input_str), const FT & field_type) @@ -1817,6 +1894,11 @@ void Model::field_member( field_member_read_value_from_db_resultset(db_field_name, setter_method, field_type); } + if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_PUT_FIELD_RAW_VALUE_TO_STREAM ) + { + field_member_put_field_raw_value_to_stream(db_field_name, flat_field_name, getter_method, field_type); + } + if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_CLEARING_VALUE ) { field_member_clear_value(setter_method, field_type); diff --git a/src/model.h b/src/model.h index 2b77b5d..c24e070 100644 --- a/src/model.h +++ b/src/model.h @@ -48,6 +48,7 @@ #include "flatexpression.h" #include "modelenv.h" #include "ft.h" +#include "modelwrapper.h" #ifdef MORM_HAS_EZC_LIBRARY #include "funinfo.h" @@ -81,11 +82,16 @@ #ifdef MORM_HAS_EZC_LIBRARY #define MORM_MODEL_MEMBER_FIELD_EZC(ClassName) \ template \ - void field(const wchar_t * flat_field_name, void (ClassName::*method)(Ezc::FunInfo &), const morm::FT & field_type = morm::FT::default_type) \ + void field(const wchar_t * field_name, void (ClassName::*method)(Ezc::FunInfo &), const morm::FT & field_type = morm::FT::default_type) \ + { \ + field(field_name, field_name, method, field_type); \ + } \ + template \ + void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, void (ClassName::*method)(Ezc::FunInfo &), const morm::FT & field_type = morm::FT::default_type) \ { \ typedef void (Model::*ModelMember)(Ezc::FunInfo &); \ ModelMember model_member = static_cast(method); \ - field_member_ezc(flat_field_name, model_member, field_type); \ + field_member_ezc(db_field_name, flat_field_name, model_member, field_type); \ } #endif @@ -216,16 +222,18 @@ public: } - Model * get_field_model(const wchar_t * db_field_name, const wchar_t * flat_field_name); + Model * get_model(const wchar_t * db_field_name, const wchar_t * flat_field_name, bool put_log_if_not_found = true); + ModelWrapper * get_model_wrapper(const wchar_t * db_field_name, const wchar_t * flat_field_name, bool put_log_if_not_found = true); - void put_field_value(const wchar_t * flat_field_name, pt::TextStream & stream, bool clear_stream = true); - void put_field_value(const wchar_t * flat_field_name, ModelData * model_data, pt::TextStream & stream, bool clear_stream = true); + void get_raw_value(const wchar_t * db_field_name, const wchar_t * flat_field_name, pt::TextStream & stream, bool clear_stream = true, bool put_log_if_not_found = true); + void get_raw_value(const wchar_t * db_field_name, const wchar_t * flat_field_name, ModelData * model_data, pt::TextStream & stream, bool clear_stream = true, bool put_log_if_not_found = true); #ifdef MORM_HAS_EZC_LIBRARY template - void put_field_value(const wchar_t * flat_field_name, ModelData * model_data, Ezc::FunInfo & fun_info, pt::TextStream & stream, bool clear_stream = true) + void get_raw_value(const wchar_t * db_field_name, const wchar_t * flat_field_name, ModelData * model_data, + Ezc::FunInfo & fun_info, pt::TextStream & stream, bool clear_stream = true) { if( clear_stream ) { @@ -236,28 +244,23 @@ public: 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_work_mode = MORM_MODEL_WORK_MODE_PUT_FIELD_RAW_VALUE_TO_STREAM; + model_env->db_field_name = db_field_name; + model_env->flat_field_name = flat_field_name; model_env->model_data = model_data; + model_env->stream = &stream; model_env->ezc_fun_info = &fun_info; model_env->ezc_fun_info_typeinfo = &typeid(fun_info); model_env->model = this; - if( model_connector ) + try { - FlatConnector * flat_connector = model_connector->get_flat_connector(); - - if( flat_connector ) - { - try - { - flat_connector->to_text(flat_field_name, stream, *this); - } - catch(...) - { - model_env = nullptr; - throw; - } - } + fields(); + } + catch(...) + { + model_env = nullptr; + throw; } model_env = nullptr; @@ -433,15 +436,13 @@ protected: template void field(const wchar_t * field_name, std::list & field_value, const FT & field_type = FT::default_type) { - ModelClass * list_model_null_pointer = nullptr; - field_list(field_name, field_name, field_value, list_model_null_pointer, field_type); + field_list(field_name, field_name, field_value, field_type); } template void field(const wchar_t * field_name, std::vector & field_value, const FT & field_type = FT::default_type) { - ModelClass * list_model_null_pointer = nullptr; - field_list(field_name, field_name, field_value, list_model_null_pointer, field_type); + field_vector(field_name, field_name, field_value, field_type); } @@ -555,15 +556,13 @@ protected: template void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::list & field_value, const FT & field_type = FT::default_type) { - ModelClass * list_model_null_pointer = nullptr; - field_list(db_field_name, flat_field_name, field_value, list_model_null_pointer, field_type); + field_list(db_field_name, flat_field_name, field_value, field_type); } template void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::vector & field_value, const FT & field_type = FT::default_type) { - ModelClass * list_model_null_pointer = nullptr; - field_list(db_field_name, flat_field_name, field_value, list_model_null_pointer, field_type); + field_vector(db_field_name, flat_field_name, field_value, field_type); } @@ -702,6 +701,20 @@ protected: } + template + void field_generic_put_raw_value_to_stream(const wchar_t * db_field_name, const wchar_t * flat_field_name, FieldValue & field_value, const FT & field_type) + { + if( (is_empty_field(model_env->db_field_name) || is_the_same_field(db_field_name, model_env->db_field_name)) && + (is_empty_field(model_env->flat_field_name) || is_the_same_field(flat_field_name, model_env->flat_field_name)) ) + { + if( model_env->stream ) + { + (*model_env->stream) << field_value; + } + } + } + + template void field_generic(const wchar_t * db_field_name, const wchar_t * flat_field_name, FieldValue & field_value, const FT & field_type) { @@ -741,6 +754,11 @@ protected: { field_generic_clear_value(field_value, field_type); } + + if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_PUT_FIELD_RAW_VALUE_TO_STREAM ) + { + field_generic_put_raw_value_to_stream(db_field_name, flat_field_name, field_value, field_type); + } } } @@ -766,6 +784,12 @@ protected: void (Model::*setter_method)(const char * input_str), const FT & field_type); + void field_member_put_field_raw_value_to_stream( + const wchar_t * db_field_name, + const wchar_t * flat_field_name, + void (Model::*getter_method)(pt::TextStream &), + const FT & field_type); + void field_member_clear_value( void (Model::*setter_method)(const char * input_str), const FT & field_type); @@ -781,29 +805,46 @@ protected: #ifdef MORM_HAS_EZC_LIBRARY template - void field_member_ezc(const wchar_t * flat_field_name, void (Model::*method)(Ezc::FunInfo &), const FT & field_type) + void field_member_ezc(const wchar_t * db_field_name, const wchar_t * flat_field_name, void (Model::*method)(Ezc::FunInfo &), const FT & field_type) { if( model_connector && model_env && model_env->ezc_fun_info && model_env->ezc_fun_info_typeinfo && model_env->model ) { - if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_GENERATING_FLAT_STRING ) + if( field_type.is_primary_key() ) { - field_fun_generate_flat_string(flat_field_name, method, field_type); + pt::Log * plog = model_connector->get_logger(); + + if( plog ) + { + (*plog) << pt::Log::log1 << "Morm:: ezc methods cannot be used as a primary key" << pt::Log::logend; + } + } + + if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_PUT_FIELD_RAW_VALUE_TO_STREAM ) + { + field_member_ezc_put_field_value_to_stream(db_field_name, flat_field_name, method, field_type); } } } template - void field_fun_generate_flat_string(const wchar_t * flat_field_name, void (Model::*method)(Ezc::FunInfo &), const FT & field_type) + void field_member_ezc_put_field_value_to_stream(const wchar_t * db_field_name, const wchar_t * flat_field_name, void (Model::*method)(Ezc::FunInfo &), const FT & field_type) { - FlatConnector * flat_connector = model_connector->get_flat_connector(); - - if( flat_connector ) + if( (is_empty_field(model_env->db_field_name) || is_the_same_field(db_field_name, model_env->db_field_name)) && + (is_empty_field(model_env->flat_field_name) || is_the_same_field(flat_field_name, model_env->flat_field_name)) ) { - FlatExpression * flat_expression = flat_connector->get_expression(); - - if( flat_expression && !is_empty_field(flat_field_name) ) + if( typeid(Ezc::FunInfo) == *model_env->ezc_fun_info_typeinfo ) { - flat_expression->field(flat_field_name, method, field_type, model_env); + Ezc::FunInfo * ezc_fun_info = reinterpret_cast*>(model_env->ezc_fun_info); + (model_env->model->*method)(*ezc_fun_info); + } + else + { + pt::Log * plog = model_connector->get_logger(); + + if( plog ) + { + (*plog) << pt::Log::log2 << "Morm: incorrect method type for field: " << flat_field_name << pt::Log::logend; + } } } } @@ -918,8 +959,52 @@ protected: } + template + void field_vector(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::vector & field_value, const FT & field_type) + { + ModelClass * list_model_null_pointer = nullptr; + + if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_GET_MODEL_WRAPPER ) + { + if( (is_empty_field(model_env->db_field_name) || is_the_same_field(db_field_name, model_env->db_field_name)) && + (is_empty_field(model_env->flat_field_name) || is_the_same_field(flat_field_name, model_env->flat_field_name)) && + !model_env->model_wrapper ) + { + model_env->model_wrapper = new ModelWrapperVector(&field_value); + } + } + else + { + field_list_generic(db_field_name, flat_field_name, field_value, list_model_null_pointer, field_type); + } + } + + + template + void field_list(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::list & field_value, const FT & field_type) + { + ModelClass * list_model_null_pointer = nullptr; + + if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_GET_MODEL_WRAPPER ) + { + if( (is_empty_field(model_env->db_field_name) || is_the_same_field(db_field_name, model_env->db_field_name)) && + (is_empty_field(model_env->flat_field_name) || is_the_same_field(flat_field_name, model_env->flat_field_name)) && + !model_env->model_wrapper ) + { + model_env->model_wrapper = new ModelWrapperList(&field_value); + } + } + else + { + field_list_generic(db_field_name, flat_field_name, field_value, list_model_null_pointer, field_type); + } + } + + + + template - void field_list(const wchar_t * db_field_name, const wchar_t * flat_field_name, ModelContainer & field_container, ModelContainerType * model_container_type, const FT & field_type) + void field_list_generic(const wchar_t * db_field_name, const wchar_t * flat_field_name, ModelContainer & field_container, ModelContainerType * model_container_type, const FT & field_type) { if( model_connector && model_env ) { diff --git a/src/modelenv.h b/src/modelenv.h index 2908077..92a494e 100644 --- a/src/modelenv.h +++ b/src/modelenv.h @@ -41,14 +41,15 @@ #include "fieldvaluehelper.h" #include "morm_types.h" -// put some macro +#ifdef MORM_HAS_EZC_LIBRARY #include "funinfo.h" +#endif namespace morm { class Model; - +class ModelWrapper; class ModelEnv @@ -87,13 +88,18 @@ public: /* * used when putting a specific field's value to a stream */ + const wchar_t * db_field_name; const wchar_t * flat_field_name; Model * model; + Model * child_model; + ModelWrapper * model_wrapper; + pt::TextStream * stream; + + #ifdef MORM_HAS_EZC_LIBRARY void * ezc_fun_info; const std::type_info * ezc_fun_info_typeinfo; - - Model * child_model; + #endif ModelEnv() { @@ -116,13 +122,17 @@ public: field_index = e.field_index; was_primary_key_read = e.was_primary_key_read; has_primary_key_set = e.has_primary_key_set; + db_field_name = e.db_field_name; flat_field_name = e.flat_field_name; model = e.model; ezc_fun_info = e.ezc_fun_info; ezc_fun_info_typeinfo = e.ezc_fun_info_typeinfo; child_model = e.child_model; + model_wrapper = e.model_wrapper; + stream = e.stream; - // schema_name and table_name don't have to be copied + + // schema_name and table_name don't have to be copied table2_name = nullptr; } @@ -157,11 +167,17 @@ public: field_index = 0; was_primary_key_read = false; has_primary_key_set = false; + db_field_name = nullptr; flat_field_name = nullptr; model = nullptr; + child_model = nullptr; + model_wrapper = nullptr; + stream = nullptr; + + #ifdef MORM_HAS_EZC_LIBRARY ezc_fun_info = nullptr; ezc_fun_info_typeinfo = nullptr; - child_model = nullptr; + #endif } diff --git a/src/modelwrapper.h b/src/modelwrapper.h new file mode 100644 index 0000000..7055579 --- /dev/null +++ b/src/modelwrapper.h @@ -0,0 +1,297 @@ +/* + * This file is a part of morm + * and is distributed under the 2-Clause BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2021, Tomasz Sowa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef headerfile_morm_modelwrapper +#define headerfile_morm_modelwrapper + +#include +#include +#include +#include + + +namespace morm +{ +class Model; + + + +class ModelWrapper +{ +public: + + ModelWrapper() + { + auto_remove = true; + } + + virtual ~ModelWrapper() + { + clear_childs(); + } + + virtual bool should_be_auto_removed() + { + return auto_remove; + } + + virtual Model * get_model() + { + return nullptr; + } + + virtual bool is_container() + { + return false; + } + + virtual bool is_container_empty() + { + return true; + } + + virtual void increment_iterator() + { + } + + virtual bool is_iterator_correct() + { + return false; + } + + virtual void clear_childs() + { + for(auto & map_item : childs_map) + { + if( map_item.second->should_be_auto_removed() ) + { + delete map_item.second; + map_item.second = nullptr; + } + + childs_map.clear(); + } + } + + virtual void add_child(const std::wstring & child_name, ModelWrapper * models_base) + { + childs_map[child_name] = models_base; + } + + virtual ModelWrapper * find_child(const std::wstring & child_name) + { + auto i = childs_map.find(child_name); + + if( i != childs_map.end() ) + { + return i->second; + } + + return nullptr; + } + +protected: + + bool auto_remove; + std::map childs_map; + + +private: + + ModelWrapper(const ModelWrapper &) + { + auto_remove = false; + } + + ModelWrapper & operator=(const ModelWrapper &) + { + return *this; + } + + +}; + + + + + +class ModelWrapperModel : public ModelWrapper +{ +public: + + ModelWrapperModel(Model * model) + { + this->model = model; + } + + Model * get_model() + { + return model; + } + + +protected: + + Model * model; + +}; + + + + + + +template +class ModelWrapperVector : public ModelWrapper +{ +public: + + ModelWrapperVector(std::vector * container) + { + this->container = container; + index = container->size(); + } + + bool is_container() + { + return true; + } + + bool is_container_empty() + { + return container->empty(); + } + + void increment_iterator() + { + if( index >= container->size() ) + { + index = 0; + } + else + { + index += 1; + } + } + + bool is_iterator_correct() + { + return index < container->size(); + } + + Model * get_model() + { + if( index < container->size() ) + { + return &(*container)[index]; + } + + return nullptr; + } + + +protected: + + std::vector * container; + size_t index; + + +}; + + + + + + +template +class ModelWrapperList : public ModelWrapper +{ +public: + + ModelWrapperList(std::list * container) + { + this->container = container; + iterator = container->end(); + } + + bool is_container() + { + return true; + } + + bool is_container_empty() + { + return container->empty(); + } + + void increment_iterator() + { + if( iterator == container->end() ) + { + iterator = container->begin(); + } + else + { + ++iterator; + } + } + + bool is_iterator_correct() + { + return iterator != container->end(); + } + + Model * get_model() + { + if( iterator != container->end() ) + { + return &(*iterator); + } + + return nullptr; + } + + +protected: + + std::list * container; + typename std::list::iterator iterator; + +}; + + + +} + +#endif diff --git a/src/morm_types.h b/src/morm_types.h index 71b7445..4315935 100644 --- a/src/morm_types.h +++ b/src/morm_types.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018-2019, Tomasz Sowa + * Copyright (c) 2018-2021, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,6 +46,9 @@ #define MORM_MODEL_WORK_MODE_ITERATE_PRIMARY_KEY_VALUES 8 #define MORM_MODEL_WORK_MODE_SET_FIELD_VALUE 9 #define MORM_MODEL_WORK_MODE_GET_FIELD_MODEL 10 +#define MORM_MODEL_WORK_MODE_GET_MODEL_WRAPPER 11 +#define MORM_MODEL_WORK_MODE_PUT_FIELD_RAW_VALUE_TO_STREAM 12 + // submodes used in some cases @@ -62,7 +65,7 @@ #define MORM_WORK_MODE_MODEL_VALUES 2 #define MORM_WORK_MODE_MODEL_FIELDS_VALUES 3 #define MORM_WORK_MODE_MODEL_SAVE_FIELDS 4 -#define MORM_WORK_MODE_GET_SPECIFIC_FIELD_VALUE 5 + // IMPROVE ME give me a better name