morm/src/model.h

1668 lines
57 KiB
C++

/*
* This file is a part of morm
* and is distributed under the 2-Clause BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2018-2023, 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_src_model
#define headerfile_morm_src_model
#include <string>
#include <list>
#include <vector>
#include <typeinfo>
#include <type_traits>
#include "textstream/textstream.h"
#include "space/space.h"
#include "modelconnector.h"
#include "dbexpression.h"
#include "flatexpression.h"
#include "modelenv.h"
#include "ft.h"
#include "wrapper.h"
#ifdef MORM_HAS_EZC_LIBRARY
#include "funinfo.h"
#endif
#define MORM_MODEL_MEMBER_FIELD(ClassName) \
void field(const wchar_t * field_name, \
void (ClassName::*getter_method)(pt::Stream &), \
void (ClassName::*setter_method)(const char * input_str), \
const morm::FT & field_type = morm::FT::default_type) \
{ \
field(field_name, field_name, getter_method, setter_method, field_type); \
}\
void field(const wchar_t * db_field_name, \
const wchar_t * flat_field_name, \
void (ClassName::*getter_method)(pt::Stream &), \
void (ClassName::*setter_method)(const char * input_str), \
const morm::FT & field_type = morm::FT::default_type) \
{ \
typedef void (Model::*ModelGetterMethod)(pt::Stream &); \
typedef void (Model::*ModelSetterMethod)(const char * input_str); \
ModelGetterMethod model_getter_method = static_cast<ModelGetterMethod>(getter_method); \
ModelSetterMethod model_setter_method = static_cast<ModelSetterMethod>(setter_method); \
field_member(db_field_name, flat_field_name, model_getter_method, model_setter_method, field_type); \
}\
using Model::field;
#ifdef MORM_HAS_EZC_LIBRARY
#define MORM_MODEL_MEMBER_FIELD_EZC(ClassName) \
template<typename FunInfoStreamType> \
void field(const wchar_t * field_name, void (ClassName::*method)(Ezc::FunInfo<FunInfoStreamType> &), const morm::FT & field_type = morm::FT::default_type) \
{ \
field(field_name, field_name, method, field_type); \
} \
template<typename FunInfoStreamType> \
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, void (ClassName::*method)(Ezc::FunInfo<FunInfoStreamType> &), const morm::FT & field_type = morm::FT::default_type) \
{ \
typedef void (Model::*ModelMember)(Ezc::FunInfo<FunInfoStreamType> &); \
ModelMember model_member = static_cast<ModelMember>(method); \
field_member_ezc(db_field_name, flat_field_name, model_member, field_type); \
} \
void field(const wchar_t * field_name, bool (ClassName::*method)(), const morm::FT & field_type = morm::FT::default_type) \
{ \
field(field_name, field_name, method, field_type); \
} \
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, bool (ClassName::*method)(), const morm::FT & field_type = morm::FT::default_type) \
{ \
typedef bool (Model::*ModelMember)(); \
ModelMember model_member = static_cast<ModelMember>(method); \
field_member_ezc(db_field_name, flat_field_name, model_member, field_type); \
} \
void field(const wchar_t * field_name, bool (ClassName::*method)() const, const morm::FT & field_type = morm::FT::default_type) \
{ \
field(field_name, field_name, method, field_type); \
} \
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, bool (ClassName::*method)() const, const morm::FT & field_type = morm::FT::default_type) \
{ \
typedef bool (Model::*ModelMember)() const; \
ModelMember model_member = static_cast<ModelMember>(method); \
field_member_ezc(db_field_name, flat_field_name, model_member, field_type); \
} \
void field(const wchar_t * field_name, void (ClassName::*method)(morm::Wrapper &), const morm::FT & field_type = morm::FT::default_type) \
{ \
field(field_name, field_name, method, field_type); \
} \
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, void (ClassName::*method)(morm::Wrapper &), const morm::FT & field_type = morm::FT::default_type) \
{ \
typedef void (Model::*ModelMember)(morm::Wrapper &); \
ModelMember model_member = static_cast<ModelMember>(method); \
field_member_ezc(db_field_name, flat_field_name, model_member, field_type); \
}
#endif
#ifdef MORM_HAS_EZC_LIBRARY
#define MORM_MEMBER_FIELD(ClassName) MORM_MODEL_MEMBER_FIELD(ClassName) MORM_MODEL_MEMBER_FIELD_EZC(ClassName)
#else
#define MORM_MEMBER_FIELD(ClassName) MORM_MODEL_MEMBER_FIELD(ClassName)
#endif
namespace morm
{
class Model
{
public:
enum SaveMode
{
DO_INSERT_ON_SAVE = 0,
DO_UPDATE_ON_SAVE,
DO_DELETE_ON_SAVE,
DO_NOTHING_ON_SAVE,
};
virtual void set_save_mode(SaveMode save_mode);
virtual SaveMode get_save_mode();
// set_save_mode() will be changed to set_save_mode2() in the future
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() const;
virtual void mark_to_delete();
virtual void mark_to_remove();
virtual void mark_to_insert();
virtual void mark_to_update();
virtual bool object_exists();
virtual bool found();
void set_connector(ModelConnector & connector);
void set_connector(ModelConnector * connector);
ModelConnector * get_connector();
virtual void get_table_name(pt::WTextStream & stream, bool with_schema_name = true, ModelData * model_data = nullptr, bool clear_stream = true);
virtual void get_table_name(std::wstring & str, bool with_schema_name = true, ModelData * model_data = nullptr, bool clear_string = true);
virtual void get_table_name(std::string & str, bool with_schema_name = true, ModelData * model_data = nullptr, bool clear_string = true);
virtual void to_text(pt::TextStream & stream, ModelData * model_data, Export exp = Export::default_type);
virtual void to_text(pt::TextStream & stream, ModelData & model_data, Export exp = Export::default_type);
virtual void to_text(pt::TextStream & stream, Export exp = Export::default_type);
virtual void to_text(pt::TextStream & stream, ModelData * model_data, bool clear_stream, bool dump_mode);
virtual void to_text(pt::TextStream & stream, ModelData & model_data, bool clear_stream, bool dump_mode);
virtual void to_text(pt::TextStream & stream, bool clear_stream, bool dump_mode);
virtual void to_text(std::string & str, ModelData * model_data, bool clear_string = true, bool dump_mode = false);
virtual void to_text(std::string & str, ModelData & model_data, bool clear_string = true, bool dump_mode = false);
virtual void to_text(std::string & str, bool clear_string = true, bool dump_mode = false);
virtual std::string to_text();
virtual std::string to_string();
virtual void generate_insert_query(pt::TextStream & stream, ModelData * model_data = nullptr);
virtual bool insert(ModelData * model_data, bool insert_whole_tree = true);
virtual bool insert(ModelData & model_data, bool insert_whole_tree = true);
virtual bool insert(bool insert_whole_tree = true);
virtual void generate_update_query(pt::TextStream & stream, ModelData * model_data = nullptr);
virtual bool update(ModelData * model_data, bool update_whole_tree = true);
virtual bool update(ModelData & model_data, bool update_whole_tree = true);
virtual bool update(bool update_whole_tree = true);
virtual void generate_remove_query(pt::TextStream & stream, ModelData * model_data = nullptr);
virtual bool remove(ModelData * model_data, bool remove_whole_tree = true);
virtual bool remove(ModelData & model_data, bool remove_whole_tree = true);
virtual bool remove(bool remove_whole_tree = true);
virtual bool save(ModelData * model_data, bool save_whole_tree = true);
virtual bool save(ModelData & model_data, bool save_whole_tree = true);
virtual bool save(bool save_whole_tree = true);
virtual void generate_select_columns(pt::TextStream & stream);
// set object to default values
virtual void clear();
virtual bool do_migration(int & current_table_version);
// IMPROVE ME this will be protected
// add set_field_value() functions for each POD type
template<typename FieldValue>
void set_field_value_generic(const wchar_t * db_field_name, const wchar_t * flat_field_name, const FieldValue & field_value)
{
ModelEnv model_env_local;
model_env = &model_env_local;
model_env->model_work_mode = MORM_MODEL_WORK_MODE_SET_FIELD_VALUE;
model_env->model = this;
FieldValueHelper field_value_helper;
field_value_helper.db_field_name = db_field_name;
field_value_helper.flat_field_name = flat_field_name;
field_value_helper.value_object = &field_value;
field_value_helper.value_type_info = &typeid(field_value);
std::vector<FieldValueHelper> helper_tab;
helper_tab.push_back(field_value_helper);
model_env->field_value_helper_tab = &helper_tab;
fields();
if( !helper_tab.back().found && 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;
}
}
// what if an exception was thrown?
model_env = nullptr;
}
Model * get_model(const wchar_t * db_field_name, const wchar_t * flat_field_name);
Wrapper get_wrapper(const wchar_t * db_field_name, const wchar_t * flat_field_name);
bool get_raw_value(const wchar_t * db_field_name, const wchar_t * flat_field_name, pt::Stream & stream, bool clear_stream = true);
bool get_raw_value(const wchar_t * db_field_name, const wchar_t * flat_field_name, ModelData * model_data, pt::Stream & stream, bool clear_stream = true);
#ifdef MORM_HAS_EZC_LIBRARY
template<typename FunInfoStreamType>
bool get_raw_value(const wchar_t * db_field_name, const wchar_t * flat_field_name, ModelData * model_data,
Ezc::FunInfo<FunInfoStreamType> & fun_info, pt::Stream & stream, bool clear_stream = true)
{
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_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;
try
{
fields();
fun_info.res = model_env->ezc_fun_result;
}
catch(...)
{
model_env = nullptr;
throw;
}
model_env = nullptr;
return model_env_local.was_field_found;
}
#endif
protected:
ModelConnector * model_connector;
ModelEnv * model_env;
SaveMode save_mode;
bool has_primary_key_set;
Model();
Model(const Model & m);
virtual ~Model();
/*
* the main method of mapping between fields and database resultsets
*/
virtual void fields() = 0;
virtual void table();
virtual void table_name(const wchar_t * table_name);
virtual void table_name(const wchar_t * schema_name, const wchar_t * table_name);
virtual void before_select();
virtual void before_insert();
virtual void before_update();
virtual void before_remove();
virtual void after_select();
virtual void after_insert();
virtual void after_update();
virtual void after_remove();
virtual void after_select_failure();
virtual void after_insert_failure();
virtual void after_update_failure();
virtual void after_remove_failure();
virtual int get_work_mode();
virtual ModelData * get_model_data();
virtual void insert_tree(bool insert_whole_tree);
virtual void update_tree(bool update_whole_tree);
virtual void remove_tree(bool remove_whole_tree);
virtual void save_tree(bool save_whole_tree);
virtual void map_values_from_query();
virtual void map_additional_columns_from_query();
virtual void map_rows_counter_from_query();
virtual bool db_query(const char * raw_sql);
virtual bool db_query(const std::string & raw_sql);
virtual bool db_query(const pt::TextStream & raw_sql);
virtual bool db_query(const char ** raw_sql, size_t len);
/////////////////////////////////
/*
* IMPLEMENT ME
* field methods for such field_values: signed char, char16_t, char32_t, std::u16string, std::u32string
*
*/
void field(const wchar_t * field_name, char & field_value, const FT & field_type = FT::default_type)
{
field_generic(field_name, field_name, field_value, field_type);
}
void field(const wchar_t * field_name, unsigned char & field_value, const FT & field_type = FT::default_type)
{
field_generic(field_name, field_name, field_value, field_type);
}
void field(const wchar_t * field_name, wchar_t & field_value, const FT & field_type = FT::default_type)
{
field_generic(field_name, field_name, field_value, field_type);
}
void field(const wchar_t * field_name, std::wstring & field_value, const FT & field_type = FT::default_type)
{
field_generic(field_name, field_name, field_value, field_type);
}
void field(const wchar_t * field_name, std::string & field_value, const FT & field_type = FT::default_type)
{
field_generic(field_name, field_name, field_value, field_type);
}
void field(const wchar_t * field_name, bool & field_value, const FT & field_type = FT::default_type)
{
field_generic(field_name, field_name, field_value, field_type);
}
void field(const wchar_t * field_name, short & field_value, const FT & field_type = FT::default_type)
{
field_generic(field_name, field_name, field_value, field_type);
}
void field(const wchar_t * field_name, unsigned short & field_value, const FT & field_type = FT::default_type)
{
field_generic(field_name, field_name, field_value, field_type);
}
void field(const wchar_t * field_name, int & field_value, const FT & field_type = FT::default_type)
{
field_generic(field_name, field_name, field_value, field_type);
}
void field(const wchar_t * field_name, unsigned int & field_value, const FT & field_type = FT::default_type)
{
field_generic(field_name, field_name, field_value, field_type);
}
void field(const wchar_t * field_name, long & field_value, const FT & field_type = FT::default_type)
{
field_generic(field_name, field_name, field_value, field_type);
}
void field(const wchar_t * field_name, unsigned long & field_value, const FT & field_type = FT::default_type)
{
field_generic(field_name, field_name, field_value, field_type);
}
void field(const wchar_t * field_name, long long & field_value, const FT & field_type = FT::default_type)
{
field_generic(field_name, field_name, field_value, field_type);
}
void field(const wchar_t * field_name, unsigned long long & field_value, const FT & field_type = FT::default_type)
{
field_generic(field_name, field_name, field_value, field_type);
}
void field(const wchar_t * field_name, float & field_value, const FT & field_type = FT::default_type)
{
field_generic(field_name, field_name, field_value, field_type);
}
void field(const wchar_t * field_name, double & field_value, const FT & field_type = FT::default_type)
{
field_generic(field_name, field_name, field_value, field_type);
}
void field(const wchar_t * field_name, long double & field_value, const FT & field_type = FT::default_type)
{
field_generic(field_name, field_name, field_value, field_type);
}
void field(const wchar_t * field_name, pt::Date & field_value, const FT & field_type = FT::default_type)
{
field_date(field_name, field_name, field_value, field_type);
}
void field(const wchar_t * field_name, pt::Space & field_value, const FT & field_type = FT::default_type)
{
field_space(field_name, field_name, field_value, field_type);
}
void field(const wchar_t * field_name, Model & field_value, const FT & field_type = FT::default_type)
{
field_model(field_name, field_name, field_value, field_type);
}
template<typename ContainerItemType>
void field(const wchar_t * field_name, std::list<ContainerItemType> & field_value, const FT & field_type = FT::default_type)
{
field_list(field_name, field_name, field_value, field_type);
}
template<typename ContainerItemType>
void field(const wchar_t * field_name, std::vector<ContainerItemType> & field_value, const FT & field_type = FT::default_type)
{
field_vector(field_name, field_name, field_value, field_type);
}
template<typename ContainerItemType>
void field(const wchar_t * field_name, std::list<ContainerItemType*> & field_value, const FT & field_type = FT::default_type)
{
field_list(field_name, field_name, field_value, field_type);
}
template<typename ContainerItemType>
void field(const wchar_t * field_name, std::vector<ContainerItemType*> & field_value, const FT & field_type = FT::default_type)
{
field_vector(field_name, field_name, field_value, field_type);
}
/*
* field methods which take two names: db_field_name and flat_field_name
*/
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, char & field_value, const FT & field_type = FT::default_type)
{
field_generic(db_field_name, flat_field_name, field_value, field_type);
}
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, unsigned char & field_value, const FT & field_type = FT::default_type)
{
field_generic(db_field_name, flat_field_name, field_value, field_type);
}
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, wchar_t & field_value, const FT & field_type = FT::default_type)
{
field_generic(db_field_name, flat_field_name, field_value, field_type);
}
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::wstring & field_value, const FT & field_type = FT::default_type)
{
field_generic(db_field_name, flat_field_name, field_value, field_type);
}
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::string & field_value, const FT & field_type = FT::default_type)
{
field_generic(db_field_name, flat_field_name, field_value, field_type);
}
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, bool & field_value, const FT & field_type = FT::default_type)
{
field_generic(db_field_name, flat_field_name, field_value, field_type);
}
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, short & field_value, const FT & field_type = FT::default_type)
{
field_generic(db_field_name, flat_field_name, field_value, field_type);
}
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, unsigned short & field_value, const FT & field_type = FT::default_type)
{
field_generic(db_field_name, flat_field_name, field_value, field_type);
}
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, int & field_value, const FT & field_type = FT::default_type)
{
field_generic(db_field_name, flat_field_name, field_value, field_type);
}
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, unsigned int & field_value, const FT & field_type = FT::default_type)
{
field_generic(db_field_name, flat_field_name, field_value, field_type);
}
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, long & field_value, const FT & field_type = FT::default_type)
{
field_generic(db_field_name, flat_field_name, field_value, field_type);
}
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, unsigned long & field_value, const FT & field_type = FT::default_type)
{
field_generic(db_field_name, flat_field_name, field_value, field_type);
}
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, long long & field_value, const FT & field_type = FT::default_type)
{
field_generic(db_field_name, flat_field_name, field_value, field_type);
}
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, unsigned long long & field_value, const FT & field_type = FT::default_type)
{
field_generic(db_field_name, flat_field_name, field_value, field_type);
}
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, float & field_value, const FT & field_type = FT::default_type)
{
field_generic(db_field_name, flat_field_name, field_value, field_type);
}
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, double & field_value, const FT & field_type = FT::default_type)
{
field_generic(db_field_name, flat_field_name, field_value, field_type);
}
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, long double & field_value, const FT & field_type = FT::default_type)
{
field_generic(db_field_name, flat_field_name, field_value, field_type);
}
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, pt::Date & field_value, const FT & field_type = FT::default_type)
{
field_date(db_field_name, flat_field_name, field_value, field_type);
}
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, pt::Space & field_value, const FT & field_type = FT::default_type)
{
field_space(db_field_name, flat_field_name, field_value, field_type);
}
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, Model & field_value, const FT & field_type = FT::default_type)
{
field_model(db_field_name, flat_field_name, field_value, field_type);
}
template<typename ContainerItemType>
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::list<ContainerItemType> & field_value, const FT & field_type = FT::default_type)
{
field_list(db_field_name, flat_field_name, field_value, field_type);
}
template<typename ContainerItemType>
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::vector<ContainerItemType> & field_value, const FT & field_type = FT::default_type)
{
field_vector(db_field_name, flat_field_name, field_value, field_type);
}
// FIXME we need to correct handle such pointerns, cctor, dtor etc.
template<typename ContainerItemType>
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::list<ContainerItemType*> & field_value, const FT & field_type = FT::default_type)
{
field_list(db_field_name, flat_field_name, field_value, field_type);
}
// FIXME we need to correct handle such pointerns, cctor, dtor etc.
template<typename ContainerItemType>
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::vector<ContainerItemType*> & field_value, const FT & field_type = FT::default_type)
{
field_vector(db_field_name, flat_field_name, field_value, field_type);
}
protected:
template<typename FieldValue>
void field_generic_set_field_value(const wchar_t * db_field_name, const wchar_t * flat_field_name, FieldValue & field_value)
{
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 )
{
if( typeid(field_value) == *helper.value_type_info )
{
field_value = *(FieldValue*)helper.value_object;
}
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(field_value).name()
<< " got " << helper.value_type_info->name() << pt::Log::logend;
}
}
}
helper.found = true;
model_env->field_index += 1;
}
}
}
}
template<typename FieldValue>
void field_generic_iterate_primary_key_values(const wchar_t * db_field_name, const wchar_t * flat_field_name, FieldValue & field_value, const FT & field_type)
{
if( field_type.is_primary_key() )
{
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];
helper.value_object = &field_value;
helper.value_type_info = &typeid(field_value);
}
}
model_env->field_index += 1;
}
}
template<typename FieldValue>
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();
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, field_value, field_type, model_env);
}
}
}
template<typename FieldValue>
void field_generic_generate_db_sql(const wchar_t * db_field_name, FieldValue & field_value, 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) )
{
db_expression->field(db_field_name, field_value, field_type, model_env);
}
}
}
template<typename FieldValue>
void field_generic_read_value_from_db_resultset(const wchar_t * db_field_name, FieldValue & field_value, const FT & field_type)
{
DbConnector * db_connector = model_connector->get_db_connector();
if( db_connector )
{
if( !is_empty_field(db_field_name) )
{
if( model_env->cursor_helper && model_env->cursor_helper->has_autogenerated_select )
{
get_value_by_field_index(model_env->cursor_helper->current_column, field_value, field_type);
model_env->cursor_helper->current_column += 1;
}
else
{
get_value_by_field_name(db_field_name, field_value, field_type);
}
}
}
}
template<typename FieldValue>
void field_generic_clear_value(FieldValue & field_value, const FT & field_type)
{
Clearer * clearer = model_connector->get_clearer();
if( clearer )
{
clearer->clear_value(field_value, field_type);
}
}
template<typename FieldValue>
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)) )
{
model_env->was_field_found = true;
if( model_env->stream )
{
(*model_env->stream) << field_value;
}
#ifdef MORM_HAS_EZC_LIBRARY
model_env->ezc_fun_result = convert_to_bool(field_value);
#endif
}
}
template<typename FieldValue>
void field_generic(const wchar_t * db_field_name, const wchar_t * flat_field_name, FieldValue & field_value, 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_SET_FIELD_VALUE )
{
field_generic_set_field_value(db_field_name, flat_field_name, field_value);
}
if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_ITERATE_PRIMARY_KEY_VALUES )
{
field_generic_iterate_primary_key_values(db_field_name, flat_field_name, field_value, field_type);
}
if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_GENERATING_FLAT_STRING )
{
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 )
{
field_generic_generate_db_sql(db_field_name, field_value, field_type);
}
if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_READING_VALUE_FROM_DB_RESULTSET )
{
field_generic_read_value_from_db_resultset(db_field_name, field_value, field_type);
}
if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_CLEARING_VALUE )
{
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);
}
}
}
void field_date(const wchar_t * db_field_name, const wchar_t * flat_field_name, pt::Date & field_value, const FT & field_type)
{
if( model_connector && model_env )
{
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->wrapper.date )
{
model_env->wrapper.date = &field_value;
}
}
else
{
field_generic(db_field_name, flat_field_name, field_value, field_type);
}
}
}
void field_space(const wchar_t * db_field_name, const wchar_t * flat_field_name, pt::Space & field_value, const FT & field_type)
{
if( model_connector && model_env )
{
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->wrapper.space_wrapper )
{
model_env->wrapper.space_wrapper = new SpaceWrapper(&field_value);
}
}
else
{
field_generic(db_field_name, flat_field_name, field_value, field_type);
}
}
}
void 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));
void field_member_generate_flat_string(
const wchar_t * flat_field_name,
void (Model::*getter_method)(pt::Stream &),
const FT & field_type);
void field_member_generate_db_sql(
const wchar_t * db_field_name,
void (Model::*getter_method)(pt::Stream &),
const FT & field_type);
void 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);
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::Stream &),
const FT & field_type);
void field_member_clear_value(
void (Model::*setter_method)(const char * input_str),
const FT & field_type);
void field_member(
const wchar_t * db_field_name,
const wchar_t * flat_field_name,
void (Model::*getter_method)(pt::Stream &),
void (Model::*setter_method)(const char * input_str),
const FT & field_type);
#ifdef MORM_HAS_EZC_LIBRARY
template<typename FunInfoStreamType>
void field_member_ezc(const wchar_t * db_field_name, const wchar_t * flat_field_name, void (Model::*method)(Ezc::FunInfo<FunInfoStreamType> &), const FT & field_type)
{
if( model_connector && model_env && model_env->ezc_fun_info && model_env->ezc_fun_info_typeinfo && model_env->model )
{
if( field_type.is_primary_key() )
{
pt::Log * plog = model_connector->get_logger();
if( plog )
{
(*plog) << pt::Log::log1 << "Morm:: an ezc method 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<typename FunInfoStreamType>
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<FunInfoStreamType> &), 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)) )
{
model_env->was_field_found = true;
if( typeid(Ezc::FunInfo<FunInfoStreamType>) == *model_env->ezc_fun_info_typeinfo )
{
Ezc::FunInfo<FunInfoStreamType> * ezc_fun_info = reinterpret_cast<Ezc::FunInfo<FunInfoStreamType>*>(model_env->ezc_fun_info);
(model_env->model->*method)(*ezc_fun_info);
model_env->ezc_fun_result = ezc_fun_info->res; // ezc_fun_info->res is overwritten in get_raw_value() after fields() method call so we have to remember it in model_env
}
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;
}
}
}
}
void field_member_ezc(const wchar_t * db_field_name, const wchar_t * flat_field_name, bool (Model::*method)(), 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:: an ezc method 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 )
{
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->was_field_found = true;
model_env->ezc_fun_result = (model_env->model->*method)();
}
}
}
}
void field_member_ezc(const wchar_t * db_field_name, const wchar_t * flat_field_name, bool (Model::*method)() const, 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:: an ezc method 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 )
{
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->was_field_found = true;
model_env->ezc_fun_result = (model_env->model->*method)();
}
}
}
}
void field_member_ezc(const wchar_t * db_field_name, const wchar_t * flat_field_name, void (Model::*method)(Wrapper & wrapper), 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:: an ezc method cannot be used as a primary key" << pt::Log::logend;
}
}
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->*method)(model_env->wrapper);
}
}
}
}
#endif
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);
void field_model_set_parent_key(const wchar_t * db_field_name, Model & field_model);
void field_model_iterate_through_childs(Model & field_model, const FT & field_type);
void field_model_generate_flat_string(const wchar_t * flat_field_name, Model & field_model, const FT & field_type);
void field_model_generate_db_sql(const wchar_t * db_field_name, Model & field_model, const FT & field_type);
void field_model_clear_values(Model & field_model, const FT & field_type);
void field_model_read_values_from_queryresult(const wchar_t * db_field_name, Model & field_model, const FT & field_type);
void field_model(const wchar_t * db_field_name, const wchar_t * flat_field_name, Model & field_model, const FT & field_type);
void field_model(const wchar_t * db_field_name, const wchar_t * flat_field_name, Model * field_model, const FT & field_type);
void field_model_for_db(const wchar_t * db_field_name, Model & field_model, const FT & field_type);
template<typename ModelContainer, typename ModelContainerType, typename IsContainerByValueRenameMe>
void field_list_set_parent_key(const wchar_t * db_field_name, ModelContainer & field_container, ModelContainerType * model_container_type, IsContainerByValueRenameMe * foo)
{
FieldValueHelper helper;
helper.db_field_name = db_field_name;
helper.flat_field_name = nullptr;
helper.compare_flat_field_name = false;
std::vector<FieldValueHelper> helper_tab;
helper_tab.push_back(helper);
// only one column at the moment, in the future we can have a primary key from more than one column
model_env->field_value_helper_tab = &helper_tab;
field_model_save_key(db_field_name);
if constexpr (std::is_base_of<Model, IsContainerByValueRenameMe>())
{
field_list_set_parent_key_by_value<ModelContainer, ModelContainerType>(db_field_name, field_container);
}
else
{
field_list_set_parent_key_by_pointer<ModelContainer, ModelContainerType>(db_field_name, field_container);
}
model_env->field_value_helper_tab = nullptr;
}
template<typename ModelContainer, typename ModelContainerType>
void field_list_set_parent_key_by_value(const wchar_t * db_field_name, ModelContainer & field_container)
{
for(ModelContainerType & child_model : field_container)
{
child_model.set_connector(model_connector);
field_model_set_parent_key_in_child(db_field_name, child_model);
}
}
template<typename ModelContainer, typename ModelContainerType>
void field_list_set_parent_key_by_pointer(const wchar_t * db_field_name, ModelContainer & field_container)
{
for(ModelContainerType * child_model : field_container)
{
child_model->set_connector(model_connector);
field_model_set_parent_key_in_child(db_field_name, *child_model);
}
}
template<typename ModelContainer, typename ModelContainerType, typename IsContainerByValueRenameMe>
void field_list_iterate_through_childs(ModelContainer & field_container, ModelContainerType * model_container_type, const FT & field_type, IsContainerByValueRenameMe * foo)
{
if constexpr (std::is_base_of<Model, IsContainerByValueRenameMe>())
{
field_list_iterate_through_childs_by_value(field_container, model_container_type, field_type);
}
else
{
field_list_iterate_through_childs_by_pointer(field_container, model_container_type, field_type);
}
}
template<typename ModelContainer, typename ModelContainerType>
void field_list_iterate_through_childs_by_value(ModelContainer & field_container, ModelContainerType * model_container_type, const FT & field_type)
{
for(ModelContainerType & child_model : field_container)
{
field_list_iterate_through_childs(child_model, field_type);
}
}
template<typename ModelContainer, typename ModelContainerType>
void field_list_iterate_through_childs_by_pointer(ModelContainer & field_container, ModelContainerType * model_container_type, const FT & field_type)
{
for(ModelContainerType * child_model : field_container)
{
field_list_iterate_through_childs(*child_model, field_type);
}
}
template<typename ModelContainerType>
void field_list_iterate_through_childs(ModelContainerType & child_model, const FT & field_type)
{
if( model_env->status )
{
ModelEnv model_env_local;
model_env_local.copy_global_objects(*model_env);
model_env_local.model = &child_model;
child_model.model_env = &model_env_local;
child_model.model_env->has_primary_key_set = child_model.has_primary_key_set;
child_model.set_connector(model_connector);
child_model.table();
field_model_iterate_through_childs(child_model, field_type);
if( !model_env_local.status )
model_env->status = false;
child_model.model_env = nullptr;
}
}
template<typename ModelContainer, typename ModelContainerType, typename IsContainerByValueRenameMe>
void field_list_generate_flat_string(const wchar_t * flat_field_name, ModelContainer & field_container, ModelContainerType * model_container_type,
const FT & field_type, IsContainerByValueRenameMe * foo)
{
FlatConnector * flat_connector = model_connector->get_flat_connector();
if( flat_connector )
{
FlatExpression * flat_expression = flat_connector->get_expression();
if( flat_expression )
{
flat_expression->field_list(flat_field_name, field_container, model_container_type, field_type, model_connector, model_env, foo);
}
}
}
template<typename ModelContainer, typename ModelContainerType, typename IsContainerByValueRenameMe>
void field_list_clearing_values(ModelContainer & field_container, ModelContainerType * model_container_type, IsContainerByValueRenameMe * foo, const FT & field_type)
{
Clearer * clearer = model_connector->get_clearer();
if( clearer )
{
clearer->clear_container(field_container, model_container_type, foo, field_type);
}
}
template<typename ModelContainer, typename ModelContainerType, typename IsContainerByValueRenameMe>
void field_list_propagate_save_status(ModelContainer & field_container, ModelContainerType * model_container_type, IsContainerByValueRenameMe * foo)
{
if constexpr (std::is_base_of<Model, ModelContainerType>())
{
if constexpr (std::is_base_of<Model, IsContainerByValueRenameMe>())
{
field_list_propagate_save_status_in_container_by_value(field_container, model_container_type);
}
else
{
field_list_propagate_save_status_in_container_by_pointer(field_container, model_container_type);
}
}
}
template<typename ModelContainer, typename ModelContainerType>
void field_list_propagate_save_status_in_container_by_value(ModelContainer & field_container, ModelContainerType * model_container_type)
{
for(ModelContainerType & item : field_container)
{
item.set_connector(model_connector);
item.set_save_mode2(save_mode, true);
}
}
template<typename ModelContainer, typename ModelContainerType>
void field_list_propagate_save_status_in_container_by_pointer(ModelContainer & field_container, ModelContainerType * model_container_type)
{
for(ModelContainerType * item : field_container)
{
item->set_connector(model_connector);
item->set_save_mode2(save_mode, true);
}
}
template<typename ContainerItemType>
void field_vector(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::vector<ContainerItemType> & field_value, const FT & field_type)
{
ContainerItemType * item_type_null_pointer = nullptr;
if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_GET_MODEL_WRAPPER )
{
if constexpr (std::is_base_of<Model, ContainerItemType>())
{
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->wrapper.model_container_wrapper )
{
model_env->wrapper.model_container_wrapper = new ModelWrapperVector(&field_value);
}
}
}
else
{
ContainerItemType * pointer = nullptr;
field_list_generic(db_field_name, flat_field_name, field_value, item_type_null_pointer, field_type, pointer);
}
}
template<typename ContainerItemType>
void field_list(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::list<ContainerItemType> & field_value, const FT & field_type)
{
ContainerItemType * item_type_null_pointer = nullptr;
if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_GET_MODEL_WRAPPER )
{
if constexpr (std::is_base_of<Model, ContainerItemType>())
{
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->wrapper.model_container_wrapper )
{
model_env->wrapper.model_container_wrapper = new ModelWrapperList(&field_value);
}
}
}
else
{
ContainerItemType * pointer = nullptr;
field_list_generic(db_field_name, flat_field_name, field_value, item_type_null_pointer, field_type, pointer);
}
}
template<typename ContainerItemType>
void field_vector(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::vector<ContainerItemType*> & field_value, const FT & field_type)
{
ContainerItemType * item_type_null_pointer = nullptr;
if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_GET_MODEL_WRAPPER )
{
if constexpr (std::is_base_of<Model, ContainerItemType>())
{
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->wrapper.model_container_wrapper )
{
model_env->wrapper.model_container_wrapper = new ModelWrapperVectorPointer(&field_value);
}
}
}
else
{
void * pointer = nullptr;
field_list_generic(db_field_name, flat_field_name, field_value, item_type_null_pointer, field_type, pointer);
}
}
template<typename ContainerItemType>
void field_list(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::list<ContainerItemType*> & field_value, const FT & field_type)
{
ContainerItemType * item_type_null_pointer = nullptr;
if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_GET_MODEL_WRAPPER )
{
if constexpr (std::is_base_of<Model, ContainerItemType>())
{
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->wrapper.model_container_wrapper )
{
model_env->wrapper.model_container_wrapper = new ModelWrapperListPointer(&field_value);
}
}
}
else
{
void * pointer = nullptr;
field_list_generic(db_field_name, flat_field_name, field_value, item_type_null_pointer, field_type, pointer);
}
}
template<typename ModelContainer, typename ModelContainerType, typename IsContainerByValueRenameMe>
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, IsContainerByValueRenameMe * foo)
{
if( model_connector && model_env )
{
pt::Log * plog = model_connector->get_logger();
if( !is_empty_field(db_field_name) )
{
/*
* IMPROVEME
* field_type.is_foreign_key() is not implemented for lists yet
* (in such a case parent will point only to one object (or none) so the list will consists of only one object (or none))
*/
if( field_type.is_foreign_key() )
{
if( plog )
{
(*plog) << pt::Log::log1 << "Morm: error: FT::is_foreign_key is not implemented for a list/vector yet" << pt::Log::logend;
return;
}
}
if constexpr (std::is_base_of<Model, ModelContainerType>())
{
bool print_need_foreign_key_option = false;
if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_SET_PARENT_ID )
{
if( field_type.is_foreign_key() || field_type.is_foreign_key_in_child() )
{
field_list_set_parent_key(db_field_name, field_container, model_container_type, foo);
}
else
{
print_need_foreign_key_option = true;
}
}
if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_ITERATE_THROUGH_CHILDS_WITHOUT_FOREIGN_KEY )
{
if( field_type.is_foreign_key() || field_type.is_foreign_key_in_child() )
{
// IMPROVEME it would be good to make some optimisation before going through all items
// such as: if UPDATE is called then we check if field_type allows to make update
field_list_iterate_through_childs(field_container, model_container_type, field_type, foo);
}
else
{
print_need_foreign_key_option = true;
}
}
if( print_need_foreign_key_option && plog )
{
(*plog) << pt::Log::log1 << "Morm: error in ";
log_table_name_with_field(db_field_name);
(*plog) << " field, you should set FT::is_foreign_key or FT::is_foreign_key_in_child flag for a list of child objects" << pt::Log::logend;
}
}
else
{
if( plog )
{
(*plog) << pt::Log::log1 << "Morm: ignoring ";
log_table_name_with_field(db_field_name);
(*plog) << " as this is not a container with Model objects" << pt::Log::logend;
}
}
}
if( !is_empty_field(flat_field_name) )
{
if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_GENERATING_FLAT_STRING )
{
field_list_generate_flat_string(flat_field_name, field_container, model_container_type, field_type, foo);
}
}
if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_CLEARING_VALUE )
{
field_list_clearing_values(field_container, model_container_type, foo, field_type);
}
if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_PROPAGATE_SAVE_STATUS )
{
field_list_propagate_save_status(field_container, model_container_type, foo);
}
}
}
template<typename FieldValue>
void get_value_by_field_index(int field_index, FieldValue & field_value, const FT & field_type)
{
DbConnector * db_connector = model_connector->get_db_connector();
if( db_connector && model_env->cursor_helper && model_env->cursor_helper->query_result )
{
if( !model_env->cursor_helper->query_result->is_null(field_index) )
{
const char * val_str = model_env->cursor_helper->query_result->get_field_string_value(field_index);
if( val_str )
{
db_connector->get_value(val_str, field_value, field_type);
}
}
else
{
if( field_type.is_primary_key() )
{
model_env->has_primary_key_set = false;
}
}
}
}
template<typename FieldValue>
void get_value_by_field_name(const wchar_t * field_name, FieldValue & field_value, const FT & field_type)
{
DbConnector * db_connector = model_connector->get_db_connector();
if( db_connector && model_env->cursor_helper && model_env->cursor_helper->query_result )
{
int column_index = -1;
if( model_env->cursor_helper->use_table_prefix_for_fetching_values && model_env->finder_helper )
{
DbExpression * db_expression = db_connector->get_expression();
if( db_expression )
{
pt::TextStream table_field_name_str;
db_expression->alias_to_stream(table_field_name_str, model_env->table_name, model_env->table_index, field_name);
if( table_field_name_str.size() < 256 )
{
wchar_t alias_name[256];
if( table_field_name_str.to_str(alias_name, sizeof(alias_name) / sizeof(wchar_t)) )
{
column_index = model_env->cursor_helper->query_result->get_column_index(alias_name);
}
}
}
}
else
{
column_index = model_env->cursor_helper->query_result->get_column_index(field_name);
}
if( column_index != -1 && !model_env->cursor_helper->query_result->is_null(column_index) )
{
const char * val_str = model_env->cursor_helper->query_result->get_field_string_value(column_index);
if( val_str )
{
db_connector->get_value(val_str, field_value, field_type);
}
}
else
{
if( field_type.is_primary_key() )
{
model_env->has_primary_key_set = false;
}
}
}
}
virtual void set_parent_key_in_childs();
public:
template<typename FieldValue>
bool get_last_sequence(const wchar_t * sequence_table_name, FieldValue & field_value)
{
if( model_connector )
{
DbConnector * db_connector = model_connector->get_db_connector();
if( db_connector && !is_empty_field(sequence_table_name) )
{
return db_connector->get_last_sequence(sequence_table_name, field_value);
}
}
return false;
}
template<typename FieldValue>
bool get_last_sequence_for_primary_key(const wchar_t * sequence_table_name, FieldValue & field_value)
{
has_primary_key_set = get_last_sequence(sequence_table_name, field_value);
return has_primary_key_set;
}
template<typename FieldValue>
void add_field_for_select(const wchar_t * new_column_expression, const wchar_t * new_column_name, const wchar_t * flat_field_name, FieldValue & field_value)
{
FT field_type = FT::no_insertable | FT::no_updatable | FT::raw_field_name;
if( model_connector && model_env )
{
if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_GENERATING_DB_SQL )
{
DbConnector * db_connector = model_connector->get_db_connector();
if( db_connector )
{
DbExpression * db_expression = db_connector->get_expression();
if( db_expression && !is_empty_field(new_column_expression) )
{
db_expression->add_field_for_select(new_column_expression, new_column_name, field_value, field_type, model_env);
}
}
}
else
if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_GENERATING_FLAT_STRING )
{
field_generic(L"", flat_field_name, field_value, field_type);
}
else
if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_READING_VALUE_FROM_DB_RESULTSET )
{
field_generic(new_column_name, L"", field_value, field_type);
}
else
if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_CLEARING_VALUE )
{
field_generic(L"", L"", field_value, field_type); // the names don't matter here
}
}
}
// RENAME ME to something like select_field() or field_select()
template<typename FieldValue>
void add_field_for_select(const wchar_t * new_column_expression, const wchar_t * new_column_name, FieldValue & field_value)
{
add_field_for_select(new_column_expression, new_column_name, new_column_name, field_value);
}
protected:
virtual bool is_empty_field(const wchar_t * value);
virtual bool is_the_same_field(const wchar_t * field1, const wchar_t * field2);
virtual pt::Log * get_logger();
virtual void put_to_log(const wchar_t * str);
virtual void put_fields_to_log(pt::Log & log, const wchar_t * db_field_name, const wchar_t * flat_field_name);
virtual void log_table_name(bool put_schema_name = true);
virtual void log_table_name_with_field(const wchar_t * db_field_name = nullptr, bool put_schema_name = true);
template<typename ModelObject>
bool do_migration(int & current_table_version, int destination_table_version, ModelObject * model_object, bool (ModelObject::*migration_function)())
{
bool status = true;
if( current_table_version < destination_table_version )
{
if( (model_object->*migration_function)() )
{
current_table_version = destination_table_version;
}
else
{
status = false;
}
}
return status;
}
// those methods are used when converting fields to bool for Ezc library
virtual bool convert_to_bool(char v);
virtual bool convert_to_bool(unsigned char v);
virtual bool convert_to_bool(wchar_t v);
virtual bool convert_to_bool(const std::wstring & str);
virtual bool convert_to_bool(const wchar_t * str);
virtual bool convert_to_bool(const std::string & str);
virtual bool convert_to_bool(const char * str);
virtual bool convert_to_bool(bool v);
virtual bool convert_to_bool(short v);
virtual bool convert_to_bool(unsigned short v);
virtual bool convert_to_bool(int v);
virtual bool convert_to_bool(unsigned int v);
virtual bool convert_to_bool(long v);
virtual bool convert_to_bool(unsigned long v);
virtual bool convert_to_bool(long long v);
virtual bool convert_to_bool(unsigned long long v);
virtual bool convert_to_bool(float v);
virtual bool convert_to_bool(double v);
virtual bool convert_to_bool(long double v);
virtual bool convert_to_bool(const pt::Date & date);
virtual bool convert_to_bool(const pt::TextStream & val);
virtual bool convert_to_bool(const pt::WTextStream & val);
virtual bool convert_to_bool(const pt::Space & space);
template<typename ModelClass> friend class Finder;
template<typename ModelClass> friend class Cursor;
friend class BaseExpression;
friend class DbExpression;
friend class DbConnector;
friend class FlatConnector;
};
} // namespace
#endif