diff --git a/src/baseexpression.h b/src/baseexpression.h index c702422..18d4323 100644 --- a/src/baseexpression.h +++ b/src/baseexpression.h @@ -42,6 +42,10 @@ #include "morm_types.h" #include "modelenv.h" #include "ft.h" +#include "convert/text.h" + +// put some macro +#include "funinfo.h" namespace morm @@ -117,13 +121,70 @@ 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(); } } + template + void field(const wchar_t * field_name, void (*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(); + } + } + template @@ -142,6 +203,23 @@ public: } } + + // not finished yet + template + void put_field_value(void (*fun)(Ezc::FunInfo&), const FT & field_type, ModelEnv * model_env) + { + if( model_env && model_env->ezc_fun_info && model_env->ezc_fun_info_typeinfo ) + { + if( typeid(Ezc::FunInfo) == *model_env->ezc_fun_info_typeinfo ) + { + fun(*reinterpret_cast*>(model_env->ezc_fun_info)); + } + + //put_field_value(info.out, field_type); + } + } + + 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 2a0d2b8..67375e5 100644 --- a/src/flatconnector.cpp +++ b/src/flatconnector.cpp @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018, Tomasz Sowa + * Copyright (c) 2018-2021, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -83,6 +83,23 @@ 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() { if( expression_allocated ) diff --git a/src/flatconnector.h b/src/flatconnector.h index a762b13..1cd3f87 100644 --- a/src/flatconnector.h +++ b/src/flatconnector.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018, Tomasz Sowa + * Copyright (c) 2018-2021, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -52,6 +52,7 @@ 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 9b1db1b..94a9a58 100644 --- a/src/jsonexpression.cpp +++ b/src/jsonexpression.cpp @@ -68,7 +68,7 @@ void JSONExpression::field_before() { BaseExpression::field_before(); - if( !is_first_field ) + if( !is_first_field && work_mode != MORM_WORK_MODE_GET_SPECIFIC_FIELD_VALUE ) { (*out_stream) << ","; } @@ -90,12 +90,14 @@ void JSONExpression::after_field_name() void JSONExpression::before_field_value_string(const FT & field_type) { - (*out_stream) << "\""; + if( work_mode != MORM_WORK_MODE_GET_SPECIFIC_FIELD_VALUE ) + (*out_stream) << "\""; } void JSONExpression::after_field_value_string(const FT & field_type) { - (*out_stream) << "\""; + if( work_mode != MORM_WORK_MODE_GET_SPECIFIC_FIELD_VALUE ) + (*out_stream) << "\""; } diff --git a/src/model.cpp b/src/model.cpp index 56bb39b..9993799 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -240,6 +240,52 @@ void Model::get_table_name(std::string & str, bool with_schema_name, ModelData * } +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); +} + + +void Model::put_field_value(const wchar_t * flat_field_name, ModelData * model_data, pt::TextStream & stream, bool clear_stream) +{ + if( clear_stream ) + { + stream.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->model_data = model_data; + + if( model_connector ) + { + 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; + } + } + } + + model_env = nullptr; +} + + + + + + void Model::to_text(pt::TextStream & stream, ModelData * model_data, bool clear_stream, bool dump_mode) { if( clear_stream ) @@ -1471,6 +1517,14 @@ void Model::field_model(const wchar_t * db_field_name, const wchar_t * flat_fiel field_model_clear_values(field_model); } + 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; + } + field_model.model_env = nullptr; } } diff --git a/src/model.h b/src/model.h index c7596b9..eb68a3b 100644 --- a/src/model.h +++ b/src/model.h @@ -50,6 +50,11 @@ #include "ft.h" +// use a macro +#include "funinfo.h" +//////////////////// + + namespace morm { @@ -137,7 +142,6 @@ public: ModelEnv model_env_local; model_env = &model_env_local; model_env->model_work_mode = MORM_MODEL_WORK_MODE_SET_FIELD_VALUE; - model_env->field_index = 0; table(); // CHECK ME it is needed to set table name? FieldValueHelper field_value_helper; @@ -169,6 +173,86 @@ public: } + 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 * model = nullptr; + + try + { + fields(); + model = model_env->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 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); + + // put in macro + template + void put_field_value(const wchar_t * flat_field_name, ModelData * model_data, Ezc::FunInfo & fun_info, pt::TextStream & stream, bool clear_stream) + { + if( clear_stream ) + { + stream.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->model_data = model_data; + model_env->ezc_fun_info = &fun_info; + model_env->ezc_fun_info_typeinfo = &typeid(fun_info); + + if( model_connector ) + { + 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; + } + } + } + + model_env = nullptr; + } + + + protected: ModelConnector * model_connector; @@ -341,6 +425,12 @@ protected: field_list(field_name, field_name, field_value, list_model_null_pointer, field_type); } + template + void field(const wchar_t * field_name, void (*fun)(Ezc::FunInfo &), const FT & field_type = FT::default_type) + { + field_fun(field_name, field_name, fun, field_type); + } + /* * field methods which take two names: db_field_name and flat_field_name @@ -461,6 +551,11 @@ protected: field_list(db_field_name, flat_field_name, field_value, list_model_null_pointer, field_type); } + template + void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, void (*fun)(Ezc::FunInfo &), const FT & field_type = FT::default_type) + { + field_fun(db_field_name, flat_field_name, fun, field_type); + } protected: @@ -528,7 +623,7 @@ protected: template - void field_generic_generate_flat_string(const wchar_t * db_field_name, const wchar_t * flat_field_name, FieldValue & field_value, const FT & field_type) + void field_generic_generate_flat_string(const wchar_t * flat_field_name, FieldValue & field_value, const FT & field_type) { FlatConnector * flat_connector = model_connector->get_flat_connector(); @@ -618,7 +713,7 @@ protected: if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_GENERATING_FLAT_STRING ) { - field_generic_generate_flat_string(db_field_name, flat_field_name, field_value, field_type); + field_generic_generate_flat_string(flat_field_name, field_value, field_type); } if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_GENERATING_DB_SQL ) @@ -639,6 +734,47 @@ protected: } + template + void field_fun(const wchar_t * db_field_name, const wchar_t * flat_field_name, void (*fun)(Ezc::FunInfo &), const FT & field_type) + { + if( model_connector && model_env ) + { + if( field_type.is_primary_key() ) + { + model_env->was_primary_key_read = true; + } + + if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_GENERATING_FLAT_STRING ) + { + field_fun_generate_flat_string(flat_field_name, fun, field_type); + } + +// if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_GENERATING_DB_SQL ) +// { +// field_generic_generate_db_sql(db_field_name, flat_field_name, field_value, field_type); +// } + } + } + + + template + void field_fun_generate_flat_string(const wchar_t * flat_field_name, void (*fun)(Ezc::FunInfo &), 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, fun, field_type, model_env); + } + } + } + + + void field_model_left_join(const wchar_t * db_field_name, Model & field_model, const FT & field_type, DbExpression * db_expression); void field_model_save_key(const wchar_t * db_field_name); void field_model_set_parent_key_in_child(const wchar_t * db_field_name, Model & field_model); @@ -1008,6 +1144,7 @@ protected: template friend class Cursor; friend class BaseExpression; friend class DbConnector; + friend class FlatConnector; }; diff --git a/src/modelenv.h b/src/modelenv.h index 7b72405..038c1cc 100644 --- a/src/modelenv.h +++ b/src/modelenv.h @@ -41,10 +41,13 @@ #include "fieldvaluehelper.h" #include "morm_types.h" +// put some macro +#include "funinfo.h" + namespace morm { - +class Model; @@ -81,6 +84,15 @@ public: std::vector * set_field_name_helper; std::vector * field_value_helper_tab; + /* + * used when putting a specific field's value to a stream + */ + const wchar_t * flat_field_name; + Model * model; + + void * ezc_fun_info; + const std::type_info * ezc_fun_info_typeinfo; + ModelEnv() { @@ -103,6 +115,10 @@ public: field_index = e.field_index; was_primary_key_read = e.was_primary_key_read; has_primary_key_set = e.has_primary_key_set; + 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; // schema_name and table_name don't have to be copied table2_name = nullptr; @@ -139,6 +155,10 @@ public: field_index = 0; was_primary_key_read = false; has_primary_key_set = false; + flat_field_name = nullptr; + model = nullptr; + ezc_fun_info = nullptr; + ezc_fun_info_typeinfo = nullptr; } diff --git a/src/morm_types.h b/src/morm_types.h index c175085..71b7445 100644 --- a/src/morm_types.h +++ b/src/morm_types.h @@ -45,6 +45,7 @@ #define MORM_MODEL_WORK_MODE_SET_PARENT_ID 7 #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 // submodes used in some cases @@ -60,8 +61,8 @@ #define MORM_WORK_MODE_MODEL_FIELDS 1 #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