From ab54a3fc3e0be059c459db458f5377771b380c88 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Tue, 26 Mar 2019 20:35:05 +0000 Subject: [PATCH] some work: we need a different way of naming tables for joins git-svn-id: svn://ttmath.org/publicrep/morm/branches/join_models@1187 e52654a7-88a9-db11-a3e9-0013d4bc506e --- src/baseexpression.cpp | 21 +++++++++--- src/baseexpression.h | 7 ++-- src/dbconnector.cpp | 2 +- src/dbconnector.h | 2 +- src/finder.h | 26 ++++++++++++--- src/model.cpp | 36 ++++++++++++++++++++- src/model.h | 73 ++++++++++++++++++++++++++++++++++++++---- src/modeldata.h | 36 ++++++++++++++++++++- 8 files changed, 181 insertions(+), 22 deletions(-) diff --git a/src/baseexpression.cpp b/src/baseexpression.cpp index 57857f6..a864880 100644 --- a/src/baseexpression.cpp +++ b/src/baseexpression.cpp @@ -81,11 +81,16 @@ PT::TextStream * BaseExpression::get_current_stream() } -void BaseExpression::set_column_prefix(const std::wstring & prefix) +void BaseExpression::set_column_prefix(const std::string & prefix) { column_prefix = prefix; } +std::string BaseExpression::get_column_prefix() +{ + return column_prefix; +} + void BaseExpression::generate_from_model(PT::TextStream & stream, Model & model) { this->out_stream = &stream; @@ -155,10 +160,16 @@ void BaseExpression::put_field_name(int table_index, const wchar_t * field_name, { before_field_name(); - if( table_index >= 0 ) - { - (*out_stream) << 't' << table_index << '.'; - } +// if( !add_column_prefix ) +// { +// +// +// } +// +// if( table_index >= 0 ) +// { +// (*out_stream) << 't' << table_index << '.'; +// } if( add_column_prefix && !column_prefix.empty() ) { diff --git a/src/baseexpression.h b/src/baseexpression.h index 7773aaa..e83d92f 100644 --- a/src/baseexpression.h +++ b/src/baseexpression.h @@ -61,7 +61,8 @@ public: virtual int get_work_mode(); virtual void prepare_to_new_expression(); - virtual void set_column_prefix(const std::wstring & prefix); + virtual void set_column_prefix(const std::string & prefix); + virtual std::string get_column_prefix(); virtual void generate_from_model(PT::TextStream & stream, Model & model); @@ -91,7 +92,7 @@ public: PT::TextStream * old_out_stream = out_stream; out_stream = &str; - put_field_name(table_index, field_name, add_column_prefix); + put_field_name(-1, field_name, add_column_prefix); out_stream = old_out_stream; if( model_data ) @@ -276,7 +277,7 @@ protected: PT::TextStream * out_stream; - std::wstring column_prefix; + std::string column_prefix; virtual void generate_from_model(Model & model); diff --git a/src/dbconnector.cpp b/src/dbconnector.cpp index 1c5bf27..35ba785 100644 --- a/src/dbconnector.cpp +++ b/src/dbconnector.cpp @@ -151,7 +151,7 @@ DbExpression * DbConnector::get_expression() } -void DbConnector::generate_select_columns(PT::TextStream & stream, Model & model, const std::wstring & column_prefix) +void DbConnector::generate_select_columns(PT::TextStream & stream, Model & model, const std::string & column_prefix) { allocate_default_expression_if_needed(); diff --git a/src/dbconnector.h b/src/dbconnector.h index 34b7907..6d37ad6 100644 --- a/src/dbconnector.h +++ b/src/dbconnector.h @@ -61,7 +61,7 @@ public: //virtual void clear_last_query_result(); - virtual void generate_select_columns(PT::TextStream & stream, Model & model, const std::wstring & column_prefix); + virtual void generate_select_columns(PT::TextStream & stream, Model & model, const std::string & column_prefix); virtual void generate_insert_query(PT::TextStream & stream, Model & model); virtual void generate_update_query(PT::TextStream & stream, Model & model); virtual void generate_remove_query(PT::TextStream & stream, Model & model); diff --git a/src/finder.h b/src/finder.h index e02dd97..7cafe50 100644 --- a/src/finder.h +++ b/src/finder.h @@ -39,6 +39,7 @@ #include #include #include "model.h" +#include "utf8/utf8.h" #include "textstream/textstream.h" #include "dbconnector.h" #include "modelconnector.h" @@ -164,7 +165,7 @@ public: Finder & prefix(const wchar_t * prefix) { - column_prefix = prefix; + PT::WideToUTF8(prefix, column_prefix); return *this; } @@ -248,11 +249,21 @@ public: model_data = &model_data_generic; } - model_data->morm_current_max_column = 0; + model_data->prepare_to_new_select(); if( model_connector && out_stream ) { (*out_stream) << "SELECT "; + + if( column_prefix.empty() ) + { + PT::TextStream prefix_stream; + model.table_name_for_join_as(prefix_stream); + + prefix_stream.to_string(column_prefix); + model_data->add_join_table(column_prefix); + } + model.generate_select_columns(*out_stream, column_prefix, model_data); (*out_stream) << " FROM "; model.table_name(*out_stream); @@ -263,7 +274,14 @@ public: } else { - (*out_stream) << " AS t0"; + (*out_stream) << " AS "; + PT::TextStream str_tmp; // improve me + model.table_name_for_join_as(str_tmp); + (*out_stream) << str_tmp; + + std::string str; + str_tmp.to_string(str); + model_data->add_join_table(str); } (*out_stream) << " "; @@ -577,7 +595,7 @@ private: bool was_query_error; std::wstring last_query_error; ModelData * model_data; - std::wstring column_prefix; + std::string column_prefix; diff --git a/src/model.cpp b/src/model.cpp index 38bfea2..82700df 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -105,6 +105,40 @@ void Model::table_name(PT::TextStream & stream) } +// the body can be moved to dbexpression +// the algorithm can be different depending on the database used +void Model::table_name_for_join_as(PT::TextStream & stream) +{ + PT::TextStream str_temp; + table_name(str_temp); + + // temporarily + std::string str; + str_temp.to_string(str); + + size_t i = str.size(); + + while( i-- > 0 ) + { + if( str[i] == '.' ) + { + break; + } + } + + + if( str[i] == '.' ) + { + i += 1; + } + + for( ; i < str.size() ; ++i) + { + stream << str[i]; + } +} + + void Model::set_connector(ModelConnector & connector) { set_connector(&connector); @@ -426,7 +460,7 @@ bool Model::save(ModelData & model_data) } -void Model::generate_select_columns(PT::TextStream & stream, const std::wstring & column_prefix, ModelData * model_data) +void Model::generate_select_columns(PT::TextStream & stream, const std::string & column_prefix, ModelData * model_data) { if( model_connector ) { diff --git a/src/model.h b/src/model.h index 8055bff..29ccba4 100644 --- a/src/model.h +++ b/src/model.h @@ -96,6 +96,7 @@ public: * */ 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); @@ -123,7 +124,7 @@ public: virtual bool save(ModelData * model_data = nullptr); virtual bool save(ModelData & model_data); - virtual void generate_select_columns(PT::TextStream & stream, const std::wstring & column_prefix, ModelData * model_data); + virtual void generate_select_columns(PT::TextStream & stream, const std::string & column_prefix, ModelData * model_data); 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); @@ -720,24 +721,61 @@ protected: { model_data->morm_current_max_column += 1; model_data->morm_foreign_keys.clear(); + field_model.table_index = model_data->morm_current_max_column; model_data->morm_finder_join_tables << "LEFT JOIN "; field_model.table_name(model_data->morm_finder_join_tables); - model_data->morm_finder_join_tables << " AS t" << (model_data->morm_current_max_column); + + model_data->morm_finder_join_tables << " AS "; + + + ////////////// + PT::TextStream join_table_name_this; + table_name_for_join_as(join_table_name_this); + + std::string sss1; // improve me + join_table_name_this.to_string(sss1); + + int this_index = model_data->find_join_table_index(sss1); + + if( this_index > 1 ) + join_table_name_this << this_index; + /////////// + PT::TextStream join_table_name; + field_model.table_name_for_join_as(join_table_name); + + std::string sss; // improve me + join_table_name.to_string(sss); + int table_index = model_data->add_join_table(sss); + + if( table_index > 1 ) + join_table_name << table_index; + ////////// + + + + + + + model_data->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(); + std::string old_prefix = db_expression->get_column_prefix(); db_expression->set_work_mode(MORM_WORK_MODE_MODEL_SAVE_FIELDS); db_expression->set_output_type(MORM_OUTPUT_TYPE_JOIN_TABLES); + std::string empty; + db_expression->set_column_prefix(empty); + if( has_foreign_key ) { field_model.map_fields(); - model_data->morm_finder_join_tables << " ON t" << table_index << '.' << db_field_name; - model_data->morm_finder_join_tables << " = "; + model_data->morm_finder_join_tables << " ON " << join_table_name_this << '.' << db_field_name; // escape? + model_data->morm_finder_join_tables << " = " << join_table_name << '.'; if( !model_data->morm_foreign_keys.empty() ) { @@ -748,19 +786,20 @@ protected: { map_fields(); - model_data->morm_finder_join_tables << " ON "; + model_data->morm_finder_join_tables << " ON " << join_table_name_this << '.'; if( !model_data->morm_foreign_keys.empty() ) { model_data->morm_finder_join_tables << model_data->morm_foreign_keys.front(); } - model_data->morm_finder_join_tables << " = t" << (model_data->morm_current_max_column) << '.' << db_field_name; + model_data->morm_finder_join_tables << " = " << (join_table_name) << '.' << db_field_name; } model_data->morm_finder_join_tables << ' '; db_expression->set_work_mode(expr_work_mode); db_expression->set_output_type(expr_output_type); + db_expression->set_column_prefix(old_prefix); } } @@ -809,7 +848,29 @@ protected: if( db_expression->get_output_type() != MORM_OUTPUT_TYPE_JOIN_TABLES ) { field_model.model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL; + std::string current_prefix = db_expression->get_column_prefix(); + + /////////// + PT::TextStream join_table_name; + field_model.table_name_for_join_as(join_table_name); + + std::string sss; // improve me + join_table_name.to_string(sss); + int table_index = model_data->add_join_table(sss); + + if( table_index > 1 ) + { + join_table_name << table_index; + join_table_name.to_string(sss); + } + + ////////// + db_expression->set_column_prefix(sss); + + + field_model.map_fields(); + db_expression->set_column_prefix(current_prefix); field_model.model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; } diff --git a/src/modeldata.h b/src/modeldata.h index 273a190..fa04d49 100644 --- a/src/modeldata.h +++ b/src/modeldata.h @@ -45,7 +45,7 @@ public: ModelData() { - morm_current_max_column = 0; + morm_current_max_column = 1; } virtual ~ModelData() @@ -55,8 +55,42 @@ public: PT::TextStream morm_finder_join_tables; std::list morm_foreign_keys; int morm_current_max_column; + std::map morm_table_join_map; + virtual void prepare_to_new_select() + { + morm_current_max_column = 1; + morm_finder_join_tables.clear(); + morm_table_join_map.clear(); + morm_foreign_keys.clear(); + } + + + virtual int add_join_table(const std::string & table_name) + { + auto res = morm_table_join_map.insert(std::make_pair(table_name, 1)); + + if( !res.second ) + { + res.first->second += 1; + } + + return res.first->second; + } + + virtual int find_join_table_index(const std::string & table_name) + { + auto iter = morm_table_join_map.find(table_name); + + if( iter != morm_table_join_map.end() ) + { + return iter->second; + } + + return 0; + } + /* * may to add: * std::set skip_columns;