diff --git a/src/baseexpression.cpp b/src/baseexpression.cpp index d28bff0..27adbc8 100644 --- a/src/baseexpression.cpp +++ b/src/baseexpression.cpp @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018-2022, Tomasz Sowa + * Copyright (c) 2018-2023, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -112,22 +112,36 @@ bool BaseExpression::get_allow_to_use_prefix() void BaseExpression::generate_from_model(pt::TextStream & stream, Model & model) +{ + FT field_type = FT::default_type; + generate_from_model(stream, model, field_type); +} + + +void BaseExpression::generate_from_model(pt::TextStream & stream, Model & model, const FT & field_type) { this->out_stream = &stream; - generate_from_model(model); + generate_from_model(model, field_type); this->out_stream = nullptr; } -void BaseExpression::generate_from_model(Model & model) +void BaseExpression::generate_from_model(Model & model, const FT & field_type) { if( out_stream ) { - before_generate_from_model(); - dump_additional_info(model); - model.fields(); - add_additional_columns(model); - after_generate_from_model(); + if( should_field_model_be_generated_as_null(model.get_has_primary_key_set(), field_type) ) + { + put_null_value(); + } + else + { + before_generate_from_model(); + dump_additional_info(model); + model.fields(); + add_additional_columns(model); + after_generate_from_model(); + } } } @@ -164,6 +178,17 @@ bool BaseExpression::can_field_be_generated(const FT &) } +bool BaseExpression::can_field_model_be_generated(bool has_model_primary_key, const FT & field_type) +{ + return true; +} + + +bool BaseExpression::should_field_model_be_generated_as_null(bool has_model_primary_key, const FT & field_type) +{ + return false; +} + void BaseExpression::field_before() { if( !is_first_field ) diff --git a/src/baseexpression.h b/src/baseexpression.h index b8043da..0e33ec9 100644 --- a/src/baseexpression.h +++ b/src/baseexpression.h @@ -75,6 +75,7 @@ public: virtual void clear(); virtual void generate_from_model(pt::TextStream & stream, Model & model); + virtual void generate_from_model(pt::TextStream & stream, Model & model, const FT & field_type); virtual pt::TextStream * get_current_stream(); @@ -232,7 +233,7 @@ public: { put_field_name_and_table_if_needed(field_name, field_type, model_env); put_name_value_separator(); - put_field_value_list(field_value, model_container_type, model_connector, model_env, foo); + put_field_value_list(field_value, model_container_type, field_type, model_connector, model_env, foo); } else if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES_FIELDS ) @@ -240,7 +241,7 @@ public: (*out_stream) << '\n'; put_field_name_and_table_if_needed(field_name, field_type, model_env); put_name_value_separator(); - put_field_value_list(field_value, model_container_type, model_connector, model_env, foo); + put_field_value_list(field_value, model_container_type, field_type, model_connector, model_env, foo); put_name_value_separator(); /* * IMPROVEME currently only used in XML serializer so we put / directly here @@ -267,7 +268,7 @@ public: template void field_model(const wchar_t * field_name, ModelClass & field_model, const FT & field_type, ModelEnv * model_env) { - if( out_stream && can_field_be_generated(field_type) ) + if( out_stream && can_field_be_generated(field_type) && can_field_model_be_generated(field_model.get_has_primary_key_set(), field_type) ) { field_before(); @@ -278,14 +279,14 @@ public: else if( work_mode == MORM_WORK_MODE_MODEL_VALUES ) { - generate_from_model(field_model); // is it ok as a value? + generate_from_model(field_model, field_type); // is it ok as a value? } else if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES ) { put_field_name_and_table_if_needed(field_name, field_type, model_env); put_name_value_separator(); - generate_from_model(field_model); + generate_from_model(field_model, field_type); } else if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES_FIELDS ) @@ -293,7 +294,7 @@ public: (*out_stream) << '\n'; put_field_name_and_table_if_needed(field_name, field_type, model_env); put_name_value_separator(); - generate_from_model(field_model); + generate_from_model(field_model, field_type); put_name_value_separator(); /* * IMPROVEME currently only used in XML serializer so we put / directly here @@ -450,11 +451,15 @@ protected: pt::TextStream scratch_buffer_local; pt::TextStream * scratch_buffer; - virtual void generate_from_model(Model & model); + virtual void generate_from_model(Model & model, const FT & field_type); virtual void before_generate_from_model(); virtual void after_generate_from_model(); + virtual bool can_field_be_generated(const FT &); + virtual bool can_field_model_be_generated(bool has_model_primary_key, const FT & field_type); + virtual bool should_field_model_be_generated_as_null(bool has_model_primary_key, const FT & field_type); + virtual void field_before(); virtual void field_after(); @@ -527,18 +532,18 @@ protected: template - void put_field_value_list(ModelContainer & field_value, ModelContainerType * model_container_type, ModelConnector * model_connector, - ModelEnv * model_env, IsContainerByValueRenameMe * foo) + void put_field_value_list(ModelContainer & field_value, ModelContainerType * model_container_type, const FT & field_type, + ModelConnector * model_connector, ModelEnv * model_env, IsContainerByValueRenameMe * foo) { if constexpr (std::is_base_of()) { if constexpr (std::is_base_of()) { - put_field_value_list_model_by_value(field_value, model_container_type, model_connector, model_env); + put_field_value_list_model_by_value(field_value, model_container_type, field_type, model_connector, model_env); } else { - put_field_value_list_model_by_pointer(field_value, model_container_type, model_connector, model_env); + put_field_value_list_model_by_pointer(field_value, model_container_type, field_type, model_connector, model_env); } } else @@ -549,8 +554,8 @@ protected: template - void put_field_value_list_model_by_value(ModelContainer & field_value, ModelContainerType * model_container_type, ModelConnector * model_connector, - ModelEnv * model_env) + void put_field_value_list_model_by_value(ModelContainer & field_value, ModelContainerType * model_container_type, const FT & field_type, + ModelConnector * model_connector, ModelEnv * model_env) { if( model_connector && model_env && out_stream ) { @@ -559,13 +564,16 @@ protected: for(auto & child_model_item : field_value) { - if( !is_first ) + if( can_field_model_be_generated(child_model_item.get_has_primary_key_set(), field_type) ) { - field_value_list_separator(); - } + if( !is_first ) + { + field_value_list_separator(); + } - put_field_value_list_model(child_model_item, model_connector, model_env); - is_first = false; + put_field_value_list_model(child_model_item, model_connector, model_env); + is_first = false; + } } after_field_value_list(); @@ -574,8 +582,8 @@ protected: template - void put_field_value_list_model_by_pointer(ModelContainer & field_value, ModelContainerType * model_container_type, ModelConnector * model_connector, - ModelEnv * model_env) + void put_field_value_list_model_by_pointer(ModelContainer & field_value, ModelContainerType * model_container_type, const FT & field_type, + ModelConnector * model_connector, ModelEnv * model_env) { if( model_connector && model_env && out_stream ) { @@ -584,13 +592,16 @@ protected: for(auto * child_model_item : field_value) { - if( !is_first ) + if( can_field_model_be_generated(child_model_item->get_has_primary_key_set(), field_type) ) { - field_value_list_separator(); - } + if( !is_first ) + { + field_value_list_separator(); + } - put_field_value_list_model(*child_model_item, model_connector, model_env); - is_first = false; + put_field_value_list_model(*child_model_item, model_connector, model_env); + is_first = false; + } } after_field_value_list(); @@ -607,7 +618,8 @@ protected: child_model.model_env->model = &child_model; child_model.set_connector(model_connector); - generate_from_model(child_model); + FT field_type = FT::default_type; + generate_from_model(child_model, field_type); child_model.model_env = nullptr; } diff --git a/src/flatexpression.cpp b/src/flatexpression.cpp index 925a4c6..7fb9d1a 100644 --- a/src/flatexpression.cpp +++ b/src/flatexpression.cpp @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018-2022, Tomasz Sowa + * Copyright (c) 2018-2023, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,6 +39,18 @@ namespace morm { +bool FlatExpression::should_field_model_be_generated_as_null(bool has_model_primary_key, const FT & field_type) +{ + return !has_model_primary_key && field_type.is_serialize_to_null_if_null(); +} + + + +bool FlatExpression::can_field_model_be_generated(bool has_model_primary_key, const FT & field_type) +{ + return has_model_primary_key || !field_type.is_do_not_serialize_if_null(); +} + } diff --git a/src/flatexpression.h b/src/flatexpression.h index 3c8adc0..d6c4691 100644 --- a/src/flatexpression.h +++ b/src/flatexpression.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018-2022, Tomasz Sowa + * Copyright (c) 2018-2023, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,6 +46,10 @@ class FlatExpression : public BaseExpression public: +protected: + + bool should_field_model_be_generated_as_null(bool has_model_primary_key, const FT & field_type); + bool can_field_model_be_generated(bool has_model_primary_key, const FT & field_type); }; diff --git a/src/ft.h b/src/ft.h index 5224f73..32e5541 100644 --- a/src/ft.h +++ b/src/ft.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2021-2022, Tomasz Sowa + * Copyright (c) 2021-2023, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -68,6 +68,15 @@ public: date_only = 32768, /* use only year, month and day from pt::Date, no_time_zone flag is not used here */ time_only = 65536, /* use only hour, min, sec from pt::Date, no_time_zone flag is not used here */ no_time_zone = 131072, /* no time zone, used only with pt::Date */ + + /* + * if this flag is set and a model does not have a primary key set + * then we print only 'null' + * (this is used only with flat strings) + * + */ + serialize_to_null_if_null = 262144, + do_not_serialize_if_null = 524288, /* null objects are completely skipped when serializing to a flat string (test only for Model objects, not lists/vectors with childs models */ }; /* @@ -212,6 +221,16 @@ public: return is_flag_set(no_time_zone); } + bool is_serialize_to_null_if_null() const + { + return is_flag_set(serialize_to_null_if_null); + } + + bool is_do_not_serialize_if_null() const + { + return is_flag_set(do_not_serialize_if_null); + } + }; } diff --git a/src/model.cpp b/src/model.cpp index ffd7069..8516926 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018-2022, Tomasz Sowa + * Copyright (c) 2018-2023, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -95,7 +95,7 @@ void Model::set_has_primary_key_set(bool has_primary_key) } -bool Model::get_has_primary_key_set() +bool Model::get_has_primary_key_set() const { return this->has_primary_key_set; } @@ -1448,7 +1448,7 @@ void Model::field_model_generate_flat_string(const wchar_t * flat_field_name, Mo if( flat_expression ) { - if( model_env->dump_mode || field_model.save_mode == DO_INSERT_ON_SAVE || field_model.save_mode == DO_UPDATE_ON_SAVE ) + if( model_env->dump_mode || field_model.save_mode != DO_DELETE_ON_SAVE ) { field_model.model_env->model_work_mode = MORM_MODEL_WORK_MODE_GENERATING_FLAT_STRING; flat_expression->field_model(flat_field_name, field_model, field_type, model_env); diff --git a/src/model.h b/src/model.h index e0b7980..f67b472 100644 --- a/src/model.h +++ b/src/model.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018-2022, Tomasz Sowa + * Copyright (c) 2018-2023, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -157,7 +157,7 @@ public: virtual void set_save_mode2(SaveMode save_mode, bool update_whole_tree = true); virtual void set_has_primary_key_set(bool has_primary_key); - virtual bool get_has_primary_key_set(); + virtual bool get_has_primary_key_set() const; virtual void mark_to_delete(); virtual void mark_to_remove();