/* * This file is a part of morm * and is distributed under the 2-Clause BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2018-2021, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ #ifndef headerfile_morm_baseexpression #define headerfile_morm_baseexpression #include #include #include "textstream/textstream.h" #include "date/date.h" #include "morm_types.h" #include "modelenv.h" namespace morm { class Model; class ModelConnector; class BaseExpression { public: BaseExpression(); virtual ~BaseExpression(); virtual void set_work_mode(int work_mode); virtual int get_work_mode(); virtual void clear(); virtual void generate_from_model(PT::TextStream & stream, Model & model); virtual PT::TextStream * get_current_stream(); // rename me virtual void allow_to_use_prefix(bool use_prefix); virtual bool get_allow_to_use_prefix(); template void field(const wchar_t * field_name, const FieldValue & field_value, bool insertable, bool updatable, bool is_primary_key, ModelEnv * model_env) { if( out_stream && can_field_be_generated(insertable, updatable, is_primary_key) ) { field_before(); if( work_mode == MORM_WORK_MODE_MODEL_FIELDS ) { put_field_name(field_name, model_env); } else if( work_mode == MORM_WORK_MODE_MODEL_SAVE_FIELDS ) { save_foreign_key(field_name, model_env); } else if( work_mode == MORM_WORK_MODE_MODEL_VALUES ) { put_field_value_or_null(field_value, is_primary_key, 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((*model_env->set_field_name_helper)[model_env->field_index], model_env); put_name_value_separator(); put_field_value_or_null(field_value, is_primary_key, model_env); } model_env->field_index += 1; } else { put_field_name(field_name, model_env); put_name_value_separator(); put_field_value_or_null(field_value, is_primary_key, model_env); } } field_after(); } } template void put_field_value_or_null(const FieldValue & field_value, bool is_primary_key, ModelEnv * model_env) { if( is_primary_key ) { if( model_env && model_env->has_primary_key_set ) put_field_value(field_value); else put_null_value(); } else { put_field_value(field_value); } } template void field_in(PT::TextStream & stream, const wchar_t * field_name, const std::set & container, ModelEnv * model_env) { field_in_generic>(stream, field_name, container, model_env); } template void field_in(PT::TextStream & stream, const wchar_t * field_name, const std::list & container, ModelEnv * model_env) { field_in_generic>(stream, field_name, container, model_env); } template void field_in(PT::TextStream & stream, const wchar_t * field_name, const std::vector & container, ModelEnv * model_env) { field_in_generic>(stream, field_name, container, model_env); } template void field_list(const wchar_t * field_name, ModelContainer & field_value, bool insertable, bool updatable, bool is_primary_key, ModelConnector * model_connector, ModelEnv * model_env) { if( out_stream && can_field_be_generated(insertable, updatable, is_primary_key) ) { field_before(); // if( work_mode == MORM_WORK_MODE_MODEL_FIELDS ) // { // put_field_name(field_name); // } // else if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES ) { put_field_name(field_name, model_env); put_name_value_separator(); put_field_value_list(field_value, model_connector, model_env); } field_after(); } } template void field_model(const wchar_t * field_name, ModelClass & field_model, bool insertable, bool updatable, bool is_primary_key, ModelEnv * model_env) { if( out_stream && can_field_be_generated(insertable, updatable, is_primary_key) ) { field_before(); if( work_mode == MORM_WORK_MODE_MODEL_FIELDS ) { put_field_name(field_name, model_env); } else if( work_mode == MORM_WORK_MODE_MODEL_VALUES ) { generate_from_model(field_model); // is it ok as a value? } else if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES ) { put_field_name(field_name, model_env); put_name_value_separator(); generate_from_model(field_model); } field_after(); } } template void field_to_stream(PT::TextStream & stream, const wchar_t * field_name, const FieldValue & field_value, bool insertable, bool updatable, bool is_primary_key, ModelEnv * model_env) { this->out_stream = &stream; field(field_name, field_value, insertable, updatable, is_primary_key, model_env); this->out_stream = nullptr; } /* * IMPLEMENT ME * esc for: signed char, wchar_t, char16_t, char32_t * */ virtual void esc(char val, PT::TextStream & stream); virtual void esc(unsigned char val, PT::TextStream & stream); virtual void esc(wchar_t val, PT::TextStream & stream); virtual void esc(const std::wstring & val, PT::TextStream & stream); virtual void esc(const wchar_t * val, PT::TextStream & stream); virtual void esc(const std::string & val, PT::TextStream & stream); virtual void esc(const char * val, PT::TextStream & stream); virtual void esc(bool val, PT::TextStream & stream); virtual void esc(short val, PT::TextStream & stream); virtual void esc(unsigned short val, PT::TextStream & stream); virtual void esc(int val, PT::TextStream & stream); virtual void esc(unsigned int val, PT::TextStream & stream); virtual void esc(long val, PT::TextStream & stream); virtual void esc(unsigned long val, PT::TextStream & stream); virtual void esc(long long val, PT::TextStream & stream); virtual void esc(unsigned long long val, PT::TextStream & stream); virtual void esc(float val, PT::TextStream & stream); virtual void esc(double val, PT::TextStream & stream); virtual void esc(long double val, PT::TextStream & stream); //virtual void esc(void* val, PT::TextStream & stream); virtual void esc(const PT::Date & date, PT::TextStream & stream); virtual void esc(const PT::TextStream & val,PT::TextStream & stream); virtual bool is_long_field_name(const wchar_t * field_name); virtual bool is_long_field_name(const PT::TextStream & table_name); virtual bool is_long_table_name(const wchar_t * field_name); virtual bool is_long_table_name(const PT::TextStream & table_name); protected: int work_mode; /* what to do: generating fields list, values list or fields-values list */ bool is_first_field; PT::TextStream * out_stream; bool use_prefix; virtual void generate_from_model(Model & model); virtual void before_generate_from_model(); virtual void after_generate_from_model(); virtual bool can_field_be_generated(bool insertable, bool updatable, bool is_primary_key); virtual void field_before(); virtual void field_after(); //void field(const wchar_t * field_name, Model & field, bool insertable = true, bool updatable = true); virtual void put_field_name(const wchar_t * field_name, ModelEnv * model_env); virtual void save_foreign_key(const wchar_t * field_name, ModelEnv * model_env); virtual void dump_additional_info(Model & model); template void put_field_value(const FieldValue & field_value) { if( out_stream ) { before_field_value(field_value); esc(field_value, *out_stream); after_field_value(field_value); } } virtual void put_null_value() { (*out_stream) << "null"; } virtual void before_field_value_list() { } virtual void after_field_value_list() { } virtual void field_value_list_separator() { (*out_stream) << ","; } virtual void put_statement_in_starts() { (*out_stream) << "("; } virtual void put_statement_in_ends() { (*out_stream) << ") "; } template void put_field_value_list_non_model(ModelContainer & field_value, ModelConnector * model_connector) { if( model_connector && out_stream ) { bool is_first = true; before_field_value_list(); for(const auto & m : field_value) { if( !is_first ) { field_value_list_separator(); } //ModelEnv model_env_local(*model_env); //m.model_env = &model_env_local; //before_field_value(field_value); //m.set_connector(model_connector); put_field_value(m); //generate_from_model(m); //m.model_env = nullptr; //after_field_value(field_value); is_first = false; } after_field_value_list(); } } template void put_field_value_list(ModelContainer & field_value, ModelConnector * model_connector, ModelEnv * model_env) { if( model_connector && model_env && out_stream ) { bool is_first = true; before_field_value_list(); for(auto & m : field_value) { if( !is_first ) { field_value_list_separator(); } ModelEnv model_env_local(*model_env); m.model_env = &model_env_local; //before_field_value(field_value); m.set_connector(model_connector); generate_from_model(m); m.model_env = nullptr; //after_field_value(field_value); is_first = false; } after_field_value_list(); } } void put_field_value_list(std::vector & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::vector & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::vector & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::vector & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::vector & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::vector & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::vector & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::vector & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::vector & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::vector & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::vector & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::vector & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::vector & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::vector & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::vector & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::vector & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::vector & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::list & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::list & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::list & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::list & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::list & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::list & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::list & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::list & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::list & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::list & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::list & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::list & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::list & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::list & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::list & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::list & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } void put_field_value_list(std::list & field_value, ModelConnector * model_connector, ModelEnv *) { put_field_value_list_non_model(field_value, model_connector); } // used in 'in()' statements, may should be renamed? template void field_in_generic(PT::TextStream & stream, const wchar_t * field_name, const Container & container, ModelEnv * model_env) { // IMPROVE ME // what about if container is empty? // only 'in()' statement would be generated this->out_stream = &stream; field_before(); put_field_name(field_name, model_env); put_name_value_separator(); bool is_first = true; put_statement_in_starts(); for(const FieldValue & v : container) { if( !is_first ) { field_value_list_separator(); } put_field_value(v); is_first = false; } put_statement_in_ends(); field_after(); this->out_stream = nullptr; } /* * escaping column names in a case when using short form - just only column_name * [before_short_field_name]column_name[after_short_field_name] */ virtual void before_short_field_name(); virtual void after_short_field_name(); /* * escaping column names in a case when using long form: table_name.column_name * [before_first_part_long_field_name]table_name[after_first_part_long_field_name].[before_second_part_long_field_name]column_name[after_second_part_long_field_name] * */ virtual void before_first_part_long_field_name(); virtual void after_first_part_long_field_name(); virtual void before_second_part_long_field_name(); virtual void after_second_part_long_field_name(); virtual const wchar_t * put_long_part_field_name(const wchar_t * field_name); virtual void put_long_field_name(const wchar_t * field_name); virtual void put_short_field_name(const wchar_t * field_name, ModelEnv * model_env); virtual void before_field_value(const std::wstring &); virtual void after_field_value(const std::wstring &); virtual void before_field_value(const std::string &); virtual void after_field_value(const std::string &); virtual void before_field_value(const wchar_t *); virtual void after_field_value(const wchar_t *); virtual void before_field_value(const char *); virtual void after_field_value(const char *); virtual void before_field_value(const PT::Date &); virtual void after_field_value(const PT::Date &); template void before_field_value(const FieldValue &) { } template void after_field_value(const FieldValue &) { } virtual void put_name_value_separator(); /* * IMPLEMENT ME * put_type for: signed char, wchar_t, char16_t, char32_t * */ virtual void put_type(char val, PT::TextStream & stream); virtual void put_type(unsigned char val, PT::TextStream & stream); virtual void put_type(const std::wstring & val, PT::TextStream & stream); virtual void put_type(const wchar_t * val, PT::TextStream & stream); virtual void put_type(const std::string & val, PT::TextStream & stream); virtual void put_type(const char * val, PT::TextStream & stream); virtual void put_type(bool val, PT::TextStream & stream); virtual void put_type(short val, PT::TextStream & stream); virtual void put_type(unsigned short val, PT::TextStream & stream); virtual void put_type(int val, PT::TextStream & stream); virtual void put_type(unsigned int val, PT::TextStream & stream); virtual void put_type(long val, PT::TextStream & stream); virtual void put_type(unsigned long val, PT::TextStream & stream); virtual void put_type(long long val, PT::TextStream & stream); virtual void put_type(unsigned long long val, PT::TextStream & stream); virtual void put_type(float val, PT::TextStream & stream); virtual void put_type(double val, PT::TextStream & stream); virtual void put_type(long double val, PT::TextStream & stream); //virtual void put_type(void* val, PT::TextStream & stream); virtual void put_type(const PT::Date & date, PT::TextStream & stream); virtual void put_type(const Model & model, PT::TextStream & stream); template void put_type(const std::list & model, PT::TextStream & stream) { stream << "table"; // may just use std::list? } template void put_type(const std::vector & model, PT::TextStream & stream) { stream << "table"; // may just just std::vector? } }; } #endif