/* * This file is a part of morm * and is distributed under the 2-Clause BSD licence. * Author: Tomasz Sowa */ /* * Copyright (c) 2018-2019, 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_model #define headerfile_morm_model #include #include "textstream/textstream.h" #include "modelconnector.h" #include "dbexpression.h" #include "flatexpression.h" #include "modelenv.h" namespace morm { class Model { public: enum SaveMode { DO_INSERT_ON_SAVE, 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(); 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); /* * map fields to names * * */ virtual void map_fields() = 0; virtual void map_doc_fields() {} ; /* * * we can use the object for a different purpose than database (e.g. json) * so let the table_name be non pure-virtual * */ virtual void table_name(PT::TextStream & stream); virtual void table_name_for_join_as(PT::TextStream & stream); virtual void to_text(PT::TextStream & stream, ModelData * model_data, bool clear_stream = true); virtual void to_text(PT::TextStream & stream, ModelData & model_data, bool clear_stream = true); virtual void to_text(PT::TextStream & stream, bool clear_stream = true); virtual void to_text(std::string & str, ModelData * model_data, bool clear_string = true); virtual void to_text(std::string & str, ModelData & model_data, bool clear_string = true); virtual void to_text(std::string & str, bool clear_string = true); virtual std::string to_text(); virtual std::string to_string(); virtual void generate_insert_query(PT::TextStream & stream); // FIX ME needed model_data virtual bool insert(ModelData * model_data = nullptr); virtual bool insert(ModelData & model_data); virtual void generate_update_query(PT::TextStream & stream); // FIX ME needed model_data virtual bool update(ModelData * model_data = nullptr); virtual bool update(ModelData & model_data); virtual void generate_remove_query(PT::TextStream & stream); // FIX ME needed model_data virtual bool remove(ModelData * model_data = nullptr); virtual bool remove(ModelData & model_data); virtual bool save(ModelData * model_data = nullptr); virtual bool save(ModelData & model_data); virtual void generate_select_columns(PT::TextStream & stream, const std::string & column_prefix); virtual void generate_doc_for_flat(PT::TextStream & stream, bool clear_stream = true); virtual void generate_doc_for_db(PT::TextStream & stream, bool clear_stream = true); // set object to default values virtual void clear(); // we need a pointer to ModelData here? virtual void prepare_to_select(); protected: ModelConnector * model_connector; SaveMode save_mode; ModelEnv * model_env; Model(); Model(const Model & m); virtual ~Model(); 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_connector_mode(); virtual ModelData * get_model_data(); virtual void map_values_from_query(); ///////////////////////////////// void field(const wchar_t * field_name, char & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); } void field(const wchar_t * field_name, unsigned char & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); } void field(const wchar_t * field_name, std::wstring & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); } // void field(const wchar_t * field_name, wchar_t * field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) // { // field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); // } void field(const wchar_t * field_name, std::string & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); } // void field(const wchar_t * field_name, char * field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) // { // field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); // } void field(const wchar_t * field_name, bool & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); } void field(const wchar_t * field_name, short & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); } void field(const wchar_t * field_name, unsigned short & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); } void field(const wchar_t * field_name, int & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); } void field(const wchar_t * field_name, unsigned int & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); } void field(const wchar_t * field_name, long & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); } void field(const wchar_t * field_name, unsigned long & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); } void field(const wchar_t * field_name, long long & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); } void field(const wchar_t * field_name, unsigned long long & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); } void field(const wchar_t * field_name, float & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); } void field(const wchar_t * field_name, double & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); } void field(const wchar_t * field_name, long double & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); } // void field(const wchar_t * field_name, void * field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) // { // field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); // } void field(const wchar_t * field_name, PT::Date & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); } void field(const wchar_t * field_name, Model & field_value, bool insertable = true, bool updatable = true) { field_model(field_name, field_name, field_value, insertable, updatable, true); } template void field(const wchar_t * field_name, std::list & field_value, bool insertable = true, bool updatable = true) { ModelClass * list_model_null_pointer = nullptr; field_list(field_name, field_name, field_value, list_model_null_pointer, insertable, updatable); } ////////////////////// void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, char & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); } void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, unsigned char & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); } void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::wstring & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); } // void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, wchar_t * field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) // { // field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); // } void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::string & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); } // void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, char * field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) // { // field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); // } void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, bool & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); } void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, short & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); } void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, unsigned short & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); } void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, int & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); } void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, unsigned int & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); } void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, long & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); } void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, unsigned long & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); } void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, long long & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); } void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, unsigned long long & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); } void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, float & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); } void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, double & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); } void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, long double & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); } // void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, void * field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) // { // field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); // } void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, PT::Date & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); } void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, Model & field_value, bool insertable = true, bool updatable = true) { field_model(db_field_name, flat_field_name, field_value, insertable, updatable, true); } template void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::list & field_value, bool insertable = true, bool updatable = true) { ModelClass * list_model_null_pointer = nullptr; field_list(db_field_name, flat_field_name, field_value, list_model_null_pointer, insertable, updatable); } ////////////////////// void doc(const wchar_t * field_name, char & field_value) { doc_field_generic(field_name, field_name, field_value); } void doc(const wchar_t * field_name, unsigned char & field_value) { doc_field_generic(field_name, field_name, field_value); } void doc(const wchar_t * field_name, std::wstring & field_value) { doc_field_generic(field_name, field_name, field_value); } // void doc(const wchar_t * field_name, wchar_t * field_value) // { // doc_field_generic(field_name, field_name, field_value); // } void doc(const wchar_t * field_name, std::string & field_value) { doc_field_generic(field_name, field_name, field_value); } // void doc(const wchar_t * field_name, char * field_value) // { // doc_field_generic(field_name, field_name, field_value); // } void doc(const wchar_t * field_name, bool & field_value) { doc_field_generic(field_name, field_name, field_value); } void doc(const wchar_t * field_name, short & field_value) { doc_field_generic(field_name, field_name, field_value); } void doc(const wchar_t * field_name, unsigned short & field_value) { doc_field_generic(field_name, field_name, field_value); } void doc(const wchar_t * field_name, int & field_value) { doc_field_generic(field_name, field_name, field_value); } void doc(const wchar_t * field_name, unsigned int & field_value) { doc_field_generic(field_name, field_name, field_value); } void doc(const wchar_t * field_name, long & field_value) { doc_field_generic(field_name, field_name, field_value); } void doc(const wchar_t * field_name, unsigned long & field_value) { doc_field_generic(field_name, field_name, field_value); } void doc(const wchar_t * field_name, long long & field_value) { doc_field_generic(field_name, field_name, field_value); } void doc(const wchar_t * field_name, unsigned long long & field_value) { doc_field_generic(field_name, field_name, field_value); } void doc(const wchar_t * field_name, float & field_value) { doc_field_generic(field_name, field_name, field_value); } void doc(const wchar_t * field_name, double & field_value) { doc_field_generic(field_name, field_name, field_value); } void doc(const wchar_t * field_name, long double & field_value) { doc_field_generic(field_name, field_name, field_value); } // void doc(const wchar_t * field_name, void * field_value) // { // doc_field_generic(field_name, field_name, field_value); // } void doc(const wchar_t * field_name, PT::Date & field_value) { doc_field_generic(field_name, field_name, field_value); } void doc(const wchar_t * field_name, Model & field_value) { doc_field_model(field_name, field_name, field_value); } template void doc(const wchar_t * field_name, std::list & field_value) { doc_field_list(field_name, field_name, field_value); } ////////////////////// void doc(const wchar_t * db_field_name, const wchar_t * flat_field_name, char & field_value) { doc_field_generic(db_field_name, flat_field_name, field_value); } void doc(const wchar_t * db_field_name, const wchar_t * flat_field_name, unsigned char & field_value) { doc_field_generic(db_field_name, flat_field_name, field_value); } void doc(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::wstring & field_value) { doc_field_generic(db_field_name, flat_field_name, field_value); } // void doc(const wchar_t * db_field_name, const wchar_t * flat_field_name, wchar_t * field_value) // { // doc_field_generic(db_field_name, flat_field_name, field_value); // } void doc(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::string & field_value) { doc_field_generic(db_field_name, flat_field_name, field_value); } // void doc(const wchar_t * db_field_name, const wchar_t * flat_field_name, char * field_value) // { // doc_field_generic(db_field_name, flat_field_name, field_value); // } void doc(const wchar_t * db_field_name, const wchar_t * flat_field_name, bool & field_value) { doc_field_generic(db_field_name, flat_field_name, field_value); } void doc(const wchar_t * db_field_name, const wchar_t * flat_field_name, short & field_value) { doc_field_generic(db_field_name, flat_field_name, field_value); } void doc(const wchar_t * db_field_name, const wchar_t * flat_field_name, unsigned short & field_value) { doc_field_generic(db_field_name, flat_field_name, field_value); } void doc(const wchar_t * db_field_name, const wchar_t * flat_field_name, int & field_value) { doc_field_generic(db_field_name, flat_field_name, field_value); } void doc(const wchar_t * db_field_name, const wchar_t * flat_field_name, unsigned int & field_value) { doc_field_generic(db_field_name, flat_field_name, field_value); } void doc(const wchar_t * db_field_name, const wchar_t * flat_field_name, long & field_value) { doc_field_generic(db_field_name, flat_field_name, field_value); } void doc(const wchar_t * db_field_name, const wchar_t * flat_field_name, unsigned long & field_value) { doc_field_generic(db_field_name, flat_field_name, field_value); } void doc(const wchar_t * db_field_name, const wchar_t * flat_field_name, long long & field_value) { doc_field_generic(db_field_name, flat_field_name, field_value); } void doc(const wchar_t * db_field_name, const wchar_t * flat_field_name, unsigned long long & field_value) { doc_field_generic(db_field_name, flat_field_name, field_value); } void doc(const wchar_t * db_field_name, const wchar_t * flat_field_name, float & field_value) { doc_field_generic(db_field_name, flat_field_name, field_value); } void doc(const wchar_t * db_field_name, const wchar_t * flat_field_name, double & field_value) { doc_field_generic(db_field_name, flat_field_name, field_value); } void doc(const wchar_t * db_field_name, const wchar_t * flat_field_name, long double & field_value) { doc_field_generic(db_field_name, flat_field_name, field_value); } // void doc(const wchar_t * db_field_name, const wchar_t * flat_field_name, void * field_value) // { // doc_field_generic(db_field_name, flat_field_name, field_value); // } void doc(const wchar_t * db_field_name, const wchar_t * flat_field_name, PT::Date & field_value) { doc_field_generic(db_field_name, flat_field_name, field_value); } void doc(const wchar_t * db_field_name, const wchar_t * flat_field_name, Model & field_value) { doc_field_model(db_field_name, flat_field_name, field_value); } template void doc(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::list & field_value) { doc_field_list(db_field_name, flat_field_name, field_value); } ////////////////////// protected: template void field_generic(const wchar_t * db_field_name, const wchar_t * flat_field_name, FieldValue & field_value, bool insertable, bool updatable, bool is_primary_key) { if( model_connector && model_env ) { if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_GENERATING_FLAT_STRING ) { 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) ) { // insertable, updatable and is_primary_key are ignored here flat_expression->field(flat_field_name, field_value, insertable, updatable, is_primary_key, true, model_env); } } } if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_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(db_field_name) ) { db_expression->field(db_field_name, field_value, insertable, updatable, is_primary_key, true, model_env); } } } if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_READING_VALUE_FROM_DB_RESULTSET ) { DbConnector * db_connector = model_connector->get_db_connector(); if( db_connector ) { if( !is_empty_field(db_field_name) ) { if( model_env->model_data && model_env->cursor_helper && model_env->cursor_helper->has_autogenerated_select ) { get_value_by_field_index(model_env->cursor_helper->current_column, field_value); model_env->cursor_helper->current_column += 1; } else { get_value_by_field_name(db_field_name, field_value); } } } } if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_CLEARING_VALUE ) { Clearer * clearer = model_connector->get_clearer(); if( clearer ) { clearer->clear_value(field_value); } } if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_GENERATING_DOC_FOR_FLAT ) { FlatConnector * doc_connector = model_connector->get_doc_connector(); // different connector will be here (doc, flat) if( doc_connector ) { FlatExpression * doc_expression = doc_connector->get_expression(); // potrzebujemy dwa rozne doce, jeden dla flat drugi dla bazy danych if( doc_expression && !is_empty_field(flat_field_name) ) { // insertable, updatable and is_primary_key are ignored here doc_expression->field_doc(*this, flat_field_name, field_value, insertable, updatable, is_primary_key); } } } } } void field_model_left_join(const wchar_t * db_field_name, const wchar_t * flat_field_name, Model & field_model, bool insertable, bool updatable, bool has_foreign_key, DbExpression * db_expression) { if( model_env->finder_helper ) { //model_env->select_helper->morm_current_max_column += 1; model_env->finder_helper->morm_foreign_keys.clear(); model_env->finder_helper->morm_finder_join_tables << "LEFT JOIN "; field_model.table_name(model_env->finder_helper->morm_finder_join_tables); model_env->finder_helper->morm_finder_join_tables << " AS "; ////////////// PT::TextStream join_table_name_this; table_name_for_join_as(join_table_name_this); if( model_env->table_index > 1 ) join_table_name_this << model_env->table_index; /////////// PT::TextStream join_table_name; field_model.table_name_for_join_as(join_table_name); field_model.model_env->table_index = model_env->finder_helper->add_join_table(join_table_name); if( field_model.model_env->table_index > 1 ) join_table_name << field_model.model_env->table_index; ////////// model_env->finder_helper->morm_finder_join_tables << join_table_name; int expr_work_mode = db_expression->get_work_mode(); int expr_output_type = db_expression->get_output_type(); db_expression->set_work_mode(MORM_WORK_MODE_MODEL_SAVE_FIELDS); db_expression->set_output_type(MORM_OUTPUT_TYPE_JOIN_TABLES); db_expression->allow_to_use_prefix(false); if( has_foreign_key ) { field_model.map_fields(); model_env->finder_helper->morm_finder_join_tables << " ON " << join_table_name_this << '.' << db_field_name; // escape? model_env->finder_helper->morm_finder_join_tables << " = " << join_table_name << '.'; if( !model_env->finder_helper->morm_foreign_keys.empty() ) { model_env->finder_helper->morm_finder_join_tables << model_env->finder_helper->morm_foreign_keys.front(); } } else { map_fields(); model_env->finder_helper->morm_finder_join_tables << " ON " << join_table_name_this << '.'; if( !model_env->finder_helper->morm_foreign_keys.empty() ) { model_env->finder_helper->morm_finder_join_tables << model_env->finder_helper->morm_foreign_keys.front(); } model_env->finder_helper->morm_finder_join_tables << " = " << (join_table_name) << '.' << db_field_name; } model_env->finder_helper->morm_finder_join_tables << ' '; db_expression->set_work_mode(expr_work_mode); db_expression->set_output_type(expr_output_type); db_expression->allow_to_use_prefix(true); } } void field_model_generate_flat_string(const wchar_t * db_field_name, const wchar_t * flat_field_name, Model & field_model, bool insertable, bool updatable, bool has_foreign_key) { 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) ) { field_model.model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_FLAT_STRING; flat_expression->field_model(flat_field_name, field_model, insertable, updatable, false); } } } void field_model_generate_db_sql(const wchar_t * db_field_name, const wchar_t * flat_field_name, Model & field_model, bool insertable, bool updatable, bool has_foreign_key) { 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) ) { field_model.model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL; if( db_expression->get_output_type() == MORM_OUTPUT_TYPE_SELECT_COLUMNS ) { field_model_left_join(db_field_name, flat_field_name, field_model, insertable, updatable, has_foreign_key, db_expression); } if( db_expression->get_output_type() != MORM_OUTPUT_TYPE_JOIN_TABLES ) { // they dont have to be copied out, this is the same as current table name and table_index std::string current_prefix = db_expression->get_column_prefix(); int current_table_index = db_expression->get_column_prefix_index(); /////////// PT::TextStream join_table_name; field_model.table_name_for_join_as(join_table_name); // RENAME this method std::string sss; // improve me join_table_name.to_string(sss); // now we dont need set_column_prefix()?, we can pass ModelEnv there somewhat? db_expression->set_column_prefix(sss, field_model.model_env->table_index); field_model.map_fields(); db_expression->set_column_prefix(current_prefix, current_table_index); } field_model.model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; } } } void field_model_clear_values(const wchar_t * db_field_name, const wchar_t * flat_field_name, Model & field_model, bool insertable, bool updatable, bool has_foreign_key) { Clearer * clearer = model_connector->get_clearer(); if( clearer ) { clearer->clear_model(field_model); } } void field_model_generate_doc_flat(const wchar_t * db_field_name, const wchar_t * flat_field_name, Model & field_model, bool insertable, bool updatable, bool has_foreign_key) { FlatConnector * doc_connector = model_connector->get_doc_connector(); // different connector will be here (doc, flat) if( doc_connector ) { FlatExpression * doc_expression = doc_connector->get_expression(); // potrzebujemy dwa rozne doce, jeden dla flat drugi dla bazy danych if( doc_expression && !is_empty_field(flat_field_name) ) { // insertable, updatable and is_primary_key are ignored here doc_expression->field_doc(*this, flat_field_name, field_model, insertable, updatable, false); } } } void field_model_read_values_from_queryresult(const wchar_t * db_field_name, const wchar_t * flat_field_name, Model & field_model, bool insertable, bool updatable, bool has_foreign_key) { DbConnector * db_connector = model_connector->get_db_connector(); if( db_connector ) { if( !is_empty_field(db_field_name) ) { // we need to test if the object is actually defined, test nulls on primary key? field_model.before_select(); field_model.set_save_mode(Model::DO_UPDATE_ON_SAVE); // IMPROVE ME check if there is a primary key field_model.map_values_from_query(); field_model.after_select(); } } } void field_model(const wchar_t * db_field_name, const wchar_t * flat_field_name, Model & field_model, bool insertable, bool updatable, bool has_foreign_key) { if( model_connector && model_env ) { ModelEnv model_env_local(*model_env); field_model.model_env = &model_env_local; field_model.set_connector(model_connector); if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_GENERATING_FLAT_STRING ) { field_model_generate_flat_string(db_field_name, flat_field_name, field_model, insertable, updatable, has_foreign_key); } if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL ) { field_model_generate_db_sql(db_field_name, flat_field_name, field_model, insertable, updatable, has_foreign_key); } if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_CLEARING_VALUE ) { field_model_clear_values(db_field_name, flat_field_name, field_model, insertable, updatable, has_foreign_key); } if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_GENERATING_DOC_FOR_FLAT ) { field_model_generate_doc_flat(db_field_name, flat_field_name, field_model, insertable, updatable, has_foreign_key); } if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_READING_VALUE_FROM_DB_RESULTSET ) { field_model_read_values_from_queryresult(db_field_name, flat_field_name, field_model, insertable, updatable, has_foreign_key); } field_model.model_env = nullptr; } } template void field_list(const wchar_t * db_field_name, const wchar_t * flat_field_name, ModelContainer & field_container, ModelContainerType * model_container_type, bool insertable, bool updatable) { if( model_connector && model_env ) { if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_GENERATING_FLAT_STRING ) { 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) ) { // IMPROVE ME // what about model_data and save_mode? // may it should be placed inside some structure? flat_expression->field_list(flat_field_name, field_container, insertable, updatable, false, model_connector, model_env); } } } if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_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(db_field_name) && db_expression->get_output_type() != MORM_OUTPUT_TYPE_JOIN_TABLES ) { // another select will be used (from another Finder) // we need only columns name // but columns are defined in the other model } } } if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_CLEARING_VALUE ) { Clearer * clearer = model_connector->get_clearer(); if( clearer ) { clearer->clear_container(field_container); } } if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_GENERATING_DOC_FOR_FLAT ) { FlatConnector * doc_connector = model_connector->get_doc_connector(); // different connector will be here (doc, flat) if( doc_connector ) { FlatExpression * doc_expression = doc_connector->get_expression(); // potrzebujemy dwa rozne doce, jeden dla flat drugi dla bazy danych if( doc_expression && !is_empty_field(flat_field_name) ) { // insertable, updatable and is_primary_key are ignored here doc_expression->field_doc(*this, flat_field_name, field_container, insertable, updatable, false, model_env->model_data); } } } } } template void get_value_by_field_index(int field_index, FieldValue & field_value) { if( model_env->cursor_helper && model_env->cursor_helper->query_result ) { const char * val_str = model_env->cursor_helper->query_result->get_field_string_value(field_index); if( val_str ) { DbConnector * db_connector = model_connector->get_db_connector(); if( db_connector ) { db_connector->get_value(val_str, field_value); } } } } template void get_value_by_field_name(const wchar_t * field_name, FieldValue & field_value) { if( model_env->cursor_helper && model_env->cursor_helper->query_result ) { const char * val_str = model_env->cursor_helper->query_result->get_field_string_value(field_name); if( val_str ) { DbConnector * db_connector = model_connector->get_db_connector(); if( db_connector ) { db_connector->get_value(val_str, field_value); } } } } //// template void doc_field_generic(const wchar_t * db_field_name, const wchar_t * flat_field_name, FieldValue & field_value) { if( reinterpret_cast(&field_value) == model_env->doc_field_pointer && model_connector ) { FlatConnector * doc_connector = model_connector->get_doc_connector(); if( doc_connector ) { FlatExpression * doc_expression = doc_connector->get_expression(); if( doc_expression ) { PT::TextStream * out_stream = doc_expression->get_current_stream(); if( out_stream ) { (*out_stream) << flat_field_name; } } } } } void doc_field_model(const wchar_t * db_field_name, const wchar_t * flat_field_name, Model & field_model) { if( reinterpret_cast(&field_model) == model_env->doc_field_pointer && model_connector ) { FlatConnector * doc_connector = model_connector->get_doc_connector(); if( doc_connector ) { FlatExpression * doc_expression = doc_connector->get_expression(); if( doc_expression ) { PT::TextStream * out_stream = doc_expression->get_current_stream(); if( out_stream ) { (*out_stream) << flat_field_name; } } } } } template void doc_field_list(const wchar_t * db_field_name, const wchar_t * flat_field_name, ModelContainer & field_container) { if( reinterpret_cast(&field_container) == model_env->doc_field_pointer && model_connector ) { FlatConnector * doc_connector = model_connector->get_doc_connector(); if( doc_connector ) { FlatExpression * doc_expression = doc_connector->get_expression(); if( doc_expression ) { PT::TextStream * out_stream = doc_expression->get_current_stream(); if( out_stream ) { (*out_stream) << flat_field_name; } } } } } public: template void 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) ) { db_connector->get_last_sequence(sequence_table_name, field_value); } } } template 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) { if( model_connector ) { if( get_connector_mode() == MORM_MODEL_CONNECTOR_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); } } } else if( get_connector_mode() == MORM_MODEL_CONNECTOR_MODE_GENERATING_FLAT_STRING ) { field_generic(L"", flat_field_name, field_value, false, false, false); } else if( get_connector_mode() == MORM_MODEL_CONNECTOR_MODE_READING_VALUE_FROM_DB_RESULTSET ) { field_generic(new_column_name, L"", field_value, false, false, false); } else if( get_connector_mode() == MORM_MODEL_CONNECTOR_MODE_CLEARING_VALUE ) { field_generic(L"", L"", field_value, false, false, false); // the names don't matter here } } } template 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); template friend class Finder; template friend class Cursor; friend class BaseExpression; }; } // namespace #endif