serialize a model to flat string even when a DO_NOTHING_ON_SAVE flag is set

while here:
- add FT::serialize_to_null_if_null and FT::do_not_serialize_if_null flags
This commit is contained in:
Tomasz Sowa 2023-02-26 18:28:16 +01:00
parent d1c86c84cf
commit 0fbd988eda
Signed by: tomasz.sowa
GPG Key ID: 662CC1438638588B
7 changed files with 114 additions and 42 deletions

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2018-2022, Tomasz Sowa * Copyright (c) 2018-2023, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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) 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; this->out_stream = &stream;
generate_from_model(model); generate_from_model(model, field_type);
this->out_stream = nullptr; 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 ) if( out_stream )
{ {
before_generate_from_model(); if( should_field_model_be_generated_as_null(model.get_has_primary_key_set(), field_type) )
dump_additional_info(model); {
model.fields(); put_null_value();
add_additional_columns(model); }
after_generate_from_model(); 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() void BaseExpression::field_before()
{ {
if( !is_first_field ) if( !is_first_field )

View File

@ -75,6 +75,7 @@ public:
virtual void clear(); virtual void clear();
virtual void generate_from_model(pt::TextStream & stream, Model & model); 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(); 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_field_name_and_table_if_needed(field_name, field_type, model_env);
put_name_value_separator(); 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 else
if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES_FIELDS ) if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES_FIELDS )
@ -240,7 +241,7 @@ public:
(*out_stream) << '\n'; (*out_stream) << '\n';
put_field_name_and_table_if_needed(field_name, field_type, model_env); put_field_name_and_table_if_needed(field_name, field_type, model_env);
put_name_value_separator(); 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(); put_name_value_separator();
/* /*
* IMPROVEME currently only used in XML serializer so we put / directly here * IMPROVEME currently only used in XML serializer so we put / directly here
@ -267,7 +268,7 @@ public:
template<typename ModelClass> template<typename ModelClass>
void field_model(const wchar_t * field_name, ModelClass & field_model, const FT & field_type, ModelEnv * model_env) 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(); field_before();
@ -278,14 +279,14 @@ public:
else else
if( work_mode == MORM_WORK_MODE_MODEL_VALUES ) 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 else
if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES ) if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES )
{ {
put_field_name_and_table_if_needed(field_name, field_type, model_env); put_field_name_and_table_if_needed(field_name, field_type, model_env);
put_name_value_separator(); put_name_value_separator();
generate_from_model(field_model); generate_from_model(field_model, field_type);
} }
else else
if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES_FIELDS ) if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES_FIELDS )
@ -293,7 +294,7 @@ public:
(*out_stream) << '\n'; (*out_stream) << '\n';
put_field_name_and_table_if_needed(field_name, field_type, model_env); put_field_name_and_table_if_needed(field_name, field_type, model_env);
put_name_value_separator(); put_name_value_separator();
generate_from_model(field_model); generate_from_model(field_model, field_type);
put_name_value_separator(); put_name_value_separator();
/* /*
* IMPROVEME currently only used in XML serializer so we put / directly here * 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_local;
pt::TextStream * scratch_buffer; 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 before_generate_from_model();
virtual void after_generate_from_model(); virtual void after_generate_from_model();
virtual bool can_field_be_generated(const FT &); 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_before();
virtual void field_after(); virtual void field_after();
@ -527,18 +532,18 @@ protected:
template<typename ModelContainer, typename ModelContainerType, typename IsContainerByValueRenameMe> template<typename ModelContainer, typename ModelContainerType, typename IsContainerByValueRenameMe>
void put_field_value_list(ModelContainer & field_value, ModelContainerType * model_container_type, ModelConnector * model_connector, void put_field_value_list(ModelContainer & field_value, ModelContainerType * model_container_type, const FT & field_type,
ModelEnv * model_env, IsContainerByValueRenameMe * foo) ModelConnector * model_connector, ModelEnv * model_env, IsContainerByValueRenameMe * foo)
{ {
if constexpr (std::is_base_of<Model, ModelContainerType>()) if constexpr (std::is_base_of<Model, ModelContainerType>())
{ {
if constexpr (std::is_base_of<Model, IsContainerByValueRenameMe>()) if constexpr (std::is_base_of<Model, IsContainerByValueRenameMe>())
{ {
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 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 else
@ -549,8 +554,8 @@ protected:
template<typename ModelContainer, typename ModelContainerType> template<typename ModelContainer, typename ModelContainerType>
void put_field_value_list_model_by_value(ModelContainer & field_value, ModelContainerType * model_container_type, ModelConnector * model_connector, void put_field_value_list_model_by_value(ModelContainer & field_value, ModelContainerType * model_container_type, const FT & field_type,
ModelEnv * model_env) ModelConnector * model_connector, ModelEnv * model_env)
{ {
if( model_connector && model_env && out_stream ) if( model_connector && model_env && out_stream )
{ {
@ -559,13 +564,16 @@ protected:
for(auto & child_model_item : field_value) 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); put_field_value_list_model(child_model_item, model_connector, model_env);
is_first = false; is_first = false;
}
} }
after_field_value_list(); after_field_value_list();
@ -574,8 +582,8 @@ protected:
template<typename ModelContainer, typename ModelContainerType> template<typename ModelContainer, typename ModelContainerType>
void put_field_value_list_model_by_pointer(ModelContainer & field_value, ModelContainerType * model_container_type, ModelConnector * model_connector, void put_field_value_list_model_by_pointer(ModelContainer & field_value, ModelContainerType * model_container_type, const FT & field_type,
ModelEnv * model_env) ModelConnector * model_connector, ModelEnv * model_env)
{ {
if( model_connector && model_env && out_stream ) if( model_connector && model_env && out_stream )
{ {
@ -584,13 +592,16 @@ protected:
for(auto * child_model_item : field_value) 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); put_field_value_list_model(*child_model_item, model_connector, model_env);
is_first = false; is_first = false;
}
} }
after_field_value_list(); after_field_value_list();
@ -607,7 +618,8 @@ protected:
child_model.model_env->model = &child_model; child_model.model_env->model = &child_model;
child_model.set_connector(model_connector); 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; child_model.model_env = nullptr;
} }

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2018-2022, Tomasz Sowa * Copyright (c) 2018-2023, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -39,6 +39,18 @@
namespace morm 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();
}
} }

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2018-2022, Tomasz Sowa * Copyright (c) 2018-2023, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -46,6 +46,10 @@ class FlatExpression : public BaseExpression
public: 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);
}; };

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2021-2022, Tomasz Sowa * Copyright (c) 2021-2023, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 */ 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 */ 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 */ 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); 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);
}
}; };
} }

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2018-2022, Tomasz Sowa * Copyright (c) 2018-2023, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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; 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( 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; 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); flat_expression->field_model(flat_field_name, field_model, field_type, model_env);

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2018-2022, Tomasz Sowa * Copyright (c) 2018-2023, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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_save_mode2(SaveMode save_mode, bool update_whole_tree = true);
virtual void set_has_primary_key_set(bool has_primary_key); 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_delete();
virtual void mark_to_remove(); virtual void mark_to_remove();