diff --git a/src/Makefile.dep b/src/Makefile.dep index 492efda..8217419 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep @@ -6,11 +6,11 @@ baseexpression.o: ../../pikotools/textstream/types.h baseexpression.o: ../../pikotools/date/date.h baseexpression.o: ../../pikotools/convert/inttostr.h baseexpression.o: ../../pikotools/membuffer/membuffer.h -baseexpression.o: ../../pikotools/textstream/types.h morm_types.h model.h -baseexpression.o: modelconnector.h clearer.h dbconnector.h +baseexpression.o: ../../pikotools/textstream/types.h morm_types.h modeldata.h +baseexpression.o: model.h modelconnector.h clearer.h dbconnector.h baseexpression.o: ../../pikotools/log/log.h ../../pikotools/log/filelog.h baseexpression.o: queryresult.h flatconnector.h dbexpression.h -baseexpression.o: flatexpression.h modeldata.h ../../pikotools/utf8/utf8.h +baseexpression.o: flatexpression.h ../../pikotools/utf8/utf8.h clearer.o: clearer.h ../../pikotools/date/date.h clearer.o: ../../pikotools/convert/inttostr.h model.h clearer.o: ../../pikotools/textstream/textstream.h @@ -19,7 +19,7 @@ clearer.o: ../../pikotools/membuffer/membuffer.h clearer.o: ../../pikotools/textstream/types.h modelconnector.h dbconnector.h clearer.o: ../../pikotools/log/log.h ../../pikotools/log/filelog.h clearer.o: queryresult.h flatconnector.h dbexpression.h baseexpression.h -clearer.o: morm_types.h flatexpression.h modeldata.h +clearer.o: morm_types.h modeldata.h flatexpression.h dbconnector.o: dbconnector.h ../../pikotools/textstream/textstream.h dbconnector.o: ../../pikotools/space/space.h dbconnector.o: ../../pikotools/textstream/types.h ../../pikotools/date/date.h @@ -27,8 +27,8 @@ dbconnector.o: ../../pikotools/convert/inttostr.h dbconnector.o: ../../pikotools/membuffer/membuffer.h dbconnector.o: ../../pikotools/textstream/types.h ../../pikotools/log/log.h dbconnector.o: ../../pikotools/log/filelog.h queryresult.h dbexpression.h -dbconnector.o: baseexpression.h morm_types.h model.h modelconnector.h -dbconnector.o: clearer.h flatconnector.h flatexpression.h modeldata.h +dbconnector.o: baseexpression.h morm_types.h modeldata.h model.h +dbconnector.o: modelconnector.h clearer.h flatconnector.h flatexpression.h dbconnector.o: ../../pikotools/utf8/utf8.h ../../pikotools/convert/convert.h dbconnector.o: ../../pikotools/convert/inttostr.h dbconnector.o: ../../pikotools/convert/patternreplacer.h @@ -41,7 +41,7 @@ dbexpression.o: ../../pikotools/textstream/types.h dbexpression.o: ../../pikotools/date/date.h dbexpression.o: ../../pikotools/convert/inttostr.h dbexpression.o: ../../pikotools/membuffer/membuffer.h -dbexpression.o: ../../pikotools/textstream/types.h morm_types.h +dbexpression.o: ../../pikotools/textstream/types.h morm_types.h modeldata.h dochtmlconnector.o: dochtmlconnector.h flatconnector.h dochtmlconnector.o: ../../pikotools/textstream/textstream.h dochtmlconnector.o: ../../pikotools/space/space.h @@ -51,6 +51,7 @@ dochtmlconnector.o: ../../pikotools/convert/inttostr.h dochtmlconnector.o: ../../pikotools/membuffer/membuffer.h dochtmlconnector.o: ../../pikotools/textstream/types.h dochtmlexpression.h dochtmlconnector.o: flatexpression.h baseexpression.h morm_types.h +dochtmlconnector.o: modeldata.h dochtmlexpression.o: dochtmlexpression.h flatexpression.h baseexpression.h dochtmlexpression.o: ../../pikotools/textstream/textstream.h dochtmlexpression.o: ../../pikotools/space/space.h @@ -59,6 +60,7 @@ dochtmlexpression.o: ../../pikotools/date/date.h dochtmlexpression.o: ../../pikotools/convert/inttostr.h dochtmlexpression.o: ../../pikotools/membuffer/membuffer.h dochtmlexpression.o: ../../pikotools/textstream/types.h morm_types.h +dochtmlexpression.o: modeldata.h flatconnector.o: flatconnector.h ../../pikotools/textstream/textstream.h flatconnector.o: ../../pikotools/space/space.h flatconnector.o: ../../pikotools/textstream/types.h @@ -66,10 +68,10 @@ flatconnector.o: ../../pikotools/date/date.h flatconnector.o: ../../pikotools/convert/inttostr.h flatconnector.o: ../../pikotools/membuffer/membuffer.h flatconnector.o: ../../pikotools/textstream/types.h flatexpression.h -flatconnector.o: baseexpression.h morm_types.h model.h modelconnector.h -flatconnector.o: clearer.h dbconnector.h ../../pikotools/log/log.h -flatconnector.o: ../../pikotools/log/filelog.h queryresult.h dbexpression.h -flatconnector.o: modeldata.h +flatconnector.o: baseexpression.h morm_types.h modeldata.h model.h +flatconnector.o: modelconnector.h clearer.h dbconnector.h +flatconnector.o: ../../pikotools/log/log.h ../../pikotools/log/filelog.h +flatconnector.o: queryresult.h dbexpression.h flatexpression.o: flatexpression.h baseexpression.h flatexpression.o: ../../pikotools/textstream/textstream.h flatexpression.o: ../../pikotools/space/space.h @@ -77,7 +79,7 @@ flatexpression.o: ../../pikotools/textstream/types.h flatexpression.o: ../../pikotools/date/date.h flatexpression.o: ../../pikotools/convert/inttostr.h flatexpression.o: ../../pikotools/membuffer/membuffer.h -flatexpression.o: ../../pikotools/textstream/types.h morm_types.h +flatexpression.o: ../../pikotools/textstream/types.h morm_types.h modeldata.h jsonconnector.o: jsonconnector.h flatconnector.h jsonconnector.o: ../../pikotools/textstream/textstream.h jsonconnector.o: ../../pikotools/space/space.h @@ -86,7 +88,7 @@ jsonconnector.o: ../../pikotools/date/date.h jsonconnector.o: ../../pikotools/convert/inttostr.h jsonconnector.o: ../../pikotools/membuffer/membuffer.h jsonconnector.o: ../../pikotools/textstream/types.h jsonexpression.h -jsonconnector.o: flatexpression.h baseexpression.h morm_types.h +jsonconnector.o: flatexpression.h baseexpression.h morm_types.h modeldata.h jsonexpression.o: jsonexpression.h flatexpression.h baseexpression.h jsonexpression.o: ../../pikotools/textstream/textstream.h jsonexpression.o: ../../pikotools/space/space.h @@ -94,7 +96,7 @@ jsonexpression.o: ../../pikotools/textstream/types.h jsonexpression.o: ../../pikotools/date/date.h jsonexpression.o: ../../pikotools/convert/inttostr.h jsonexpression.o: ../../pikotools/membuffer/membuffer.h -jsonexpression.o: ../../pikotools/textstream/types.h morm_types.h +jsonexpression.o: ../../pikotools/textstream/types.h morm_types.h modeldata.h model.o: model.h ../../pikotools/textstream/textstream.h model.o: ../../pikotools/space/space.h ../../pikotools/textstream/types.h model.o: ../../pikotools/date/date.h ../../pikotools/convert/inttostr.h @@ -102,8 +104,8 @@ model.o: ../../pikotools/membuffer/membuffer.h model.o: ../../pikotools/textstream/types.h modelconnector.h clearer.h model.o: dbconnector.h ../../pikotools/log/log.h model.o: ../../pikotools/log/filelog.h queryresult.h flatconnector.h -model.o: dbexpression.h baseexpression.h morm_types.h flatexpression.h -model.o: modeldata.h +model.o: dbexpression.h baseexpression.h morm_types.h modeldata.h +model.o: flatexpression.h modelconnector.o: modelconnector.h clearer.h ../../pikotools/date/date.h modelconnector.o: ../../pikotools/convert/inttostr.h dbconnector.h modelconnector.o: ../../pikotools/textstream/textstream.h @@ -125,7 +127,8 @@ postgresqlconnector.o: ../../pikotools/log/log.h postgresqlconnector.o: ../../pikotools/log/filelog.h queryresult.h postgresqlconnector.o: postgresqlqueryresult.h ../../pikotools/utf8/utf8.h postgresqlconnector.o: postgresqlexpression.h dbexpression.h baseexpression.h -postgresqlconnector.o: morm_types.h ../../pikotools/convert/strtoint.h +postgresqlconnector.o: morm_types.h modeldata.h +postgresqlconnector.o: ../../pikotools/convert/strtoint.h postgresqlconnector.o: ../../pikotools/convert/text.h postgresqlconnector.o: ../../pikotools/convert/misc.h postgresqlexpression.o: postgresqlexpression.h dbexpression.h @@ -137,6 +140,7 @@ postgresqlexpression.o: ../../pikotools/date/date.h postgresqlexpression.o: ../../pikotools/convert/inttostr.h postgresqlexpression.o: ../../pikotools/membuffer/membuffer.h postgresqlexpression.o: ../../pikotools/textstream/types.h morm_types.h +postgresqlexpression.o: modeldata.h postgresqlqueryresult.o: postgresqlqueryresult.h queryresult.h queryresult.o: queryresult.h ../../pikotools/utf8/utf8.h queryresult.o: ../../pikotools/textstream/textstream.h diff --git a/src/baseexpression.cpp b/src/baseexpression.cpp index e396399..57857f6 100644 --- a/src/baseexpression.cpp +++ b/src/baseexpression.cpp @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018, Tomasz Sowa + * Copyright (c) 2018-2019, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -60,6 +60,12 @@ void BaseExpression::set_work_mode(int work_mode) } +int BaseExpression::get_work_mode() +{ + return work_mode; +} + + void BaseExpression::prepare_to_new_expression() { column_prefix.clear(); @@ -144,10 +150,16 @@ void BaseExpression::field_after() } -void BaseExpression::put_field_name(const wchar_t * field_name, bool add_column_prefix) + +void BaseExpression::put_field_name(int table_index, const wchar_t * field_name, bool add_column_prefix) { before_field_name(); + if( table_index >= 0 ) + { + (*out_stream) << 't' << table_index << '.'; + } + if( add_column_prefix && !column_prefix.empty() ) { esc(column_prefix, *out_stream); @@ -159,6 +171,11 @@ void BaseExpression::put_field_name(const wchar_t * field_name, bool add_column_ } +void BaseExpression::put_field_name(const wchar_t * field_name, bool add_column_prefix) +{ + put_field_name(-1, field_name, add_column_prefix); +} + void BaseExpression::put_field_doc(Model & model, const void * field_pointer, bool insertable, bool updatable, bool is_primary_key, ModelData * model_data) diff --git a/src/baseexpression.h b/src/baseexpression.h index 879d25f..7773aaa 100644 --- a/src/baseexpression.h +++ b/src/baseexpression.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018, Tomasz Sowa + * Copyright (c) 2018-2019, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,14 +38,15 @@ #include #include #include "textstream/textstream.h" -#include "morm_types.h" #include "date/date.h" +#include "morm_types.h" +#include "modeldata.h" + namespace morm { class Model; -class ModelData; class ModelConnector; @@ -57,6 +58,8 @@ public: virtual ~BaseExpression(); virtual void set_work_mode(int work_mode); + virtual int get_work_mode(); + virtual void prepare_to_new_expression(); virtual void set_column_prefix(const std::wstring & prefix); @@ -71,7 +74,7 @@ public: template - void field(const wchar_t * field_name, const FieldValue & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false, bool add_column_prefix = true) + void field(int table_index, const wchar_t * field_name, const FieldValue & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false, bool add_column_prefix = true, ModelData * model_data = nullptr) { if( out_stream && can_field_be_generated(insertable, updatable, is_primary_key) ) { @@ -79,7 +82,24 @@ public: if( work_mode == MORM_WORK_MODE_MODEL_FIELDS ) { - put_field_name(field_name, add_column_prefix); + put_field_name(table_index, field_name, add_column_prefix); + } + else + if( work_mode == MORM_WORK_MODE_MODEL_SAVE_FIELDS ) + { + PT::TextStream str; + PT::TextStream * old_out_stream = out_stream; + + out_stream = &str; + put_field_name(table_index, field_name, add_column_prefix); + out_stream = old_out_stream; + + if( model_data ) + { + model_data->morm_foreign_keys.emplace_back(); + std::string & key_str = model_data->morm_foreign_keys.back(); + str.to_string(key_str, false); + } } else if( work_mode == MORM_WORK_MODE_MODEL_VALUES ) @@ -89,15 +109,18 @@ public: else if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES ) { - put_field_name(field_name); + put_field_name(table_index, field_name); put_name_value_separator(); put_field_value(field_value); } + field_after(); } } + + template void field_doc(Model & model, const wchar_t * field_name, const FieldValue & field_value, bool insertable = true, bool updatable = true, @@ -158,6 +181,11 @@ public: { 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); @@ -201,7 +229,7 @@ public: void field_to_stream(PT::TextStream & stream, const wchar_t * field_name, const FieldValue & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { this->out_stream = &stream; - field(field_name, field_value, insertable, updatable, is_primary_key); + field(-1, field_name, field_value, insertable, updatable, is_primary_key); this->out_stream = nullptr; } @@ -260,6 +288,7 @@ protected: //void field(const wchar_t * field_name, Model & field, bool insertable = true, bool updatable = true); + virtual void put_field_name(int table_index, const wchar_t * field_name, bool add_column_prefix = true); virtual void put_field_name(const wchar_t * field_name, bool add_column_prefix = true); template diff --git a/src/dbexpression.cpp b/src/dbexpression.cpp index f7ba295..43f098b 100644 --- a/src/dbexpression.cpp +++ b/src/dbexpression.cpp @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018, Tomasz Sowa + * Copyright (c) 2018-2019, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -56,6 +56,12 @@ void DbExpression::set_output_type(int output_type) } +int DbExpression::get_output_type() +{ + return output_type; +} + + bool DbExpression::can_field_be_generated(bool insertable, bool updatable, bool is_primary_key) { if( output_type == MORM_OUTPUT_TYPE_DB_INSERT ) @@ -68,7 +74,7 @@ bool DbExpression::can_field_be_generated(bool insertable, bool updatable, bool return updatable; } else - if( output_type == MORM_OUTPUT_TYPE_DB_PRIMARY_KEY ) + if( output_type == MORM_OUTPUT_TYPE_DB_PRIMARY_KEY || output_type == MORM_OUTPUT_TYPE_JOIN_TABLES ) { return is_primary_key; } diff --git a/src/dbexpression.h b/src/dbexpression.h index b48b989..13e1f63 100644 --- a/src/dbexpression.h +++ b/src/dbexpression.h @@ -51,6 +51,7 @@ public: virtual ~DbExpression(); virtual void set_output_type(int output_type); + virtual int get_output_type(); virtual void prepare_to_where_clause(); @@ -61,7 +62,6 @@ public: virtual DbExpression & page(PT::TextStream & stream, size_t page_number, size_t page_size); - template void add_field_for_select(const wchar_t * new_column_expression, const wchar_t * new_column_name, FieldValue & field_value) { @@ -71,7 +71,7 @@ public: column_expression += L" as "; column_expression += new_column_name; - field(column_expression.c_str(), field_value, false, false, false, false); + field(-1, column_expression.c_str(), field_value, false, false, false, false); } diff --git a/src/finder.h b/src/finder.h index 0fdb3a3..e02dd97 100644 --- a/src/finder.h +++ b/src/finder.h @@ -175,6 +175,7 @@ public: last_query_error.clear(); model_data = nullptr; column_prefix.clear(); + model.clear_table_index(); // will be changed if( model_connector ) { @@ -242,17 +243,32 @@ public: prepare_to_select(); } + if( !model_data ) + { + model_data = &model_data_generic; + } + + model_data->morm_current_max_column = 0; + if( model_connector && out_stream ) { (*out_stream) << "SELECT "; - model.generate_select_columns(*out_stream, column_prefix); + model.generate_select_columns(*out_stream, column_prefix, model_data); (*out_stream) << " FROM "; model.table_name(*out_stream); if( !column_prefix.empty() ) + { (*out_stream) << " AS " << column_prefix; // what about escaping? + } + else + { + (*out_stream) << " AS t0"; + } (*out_stream) << " "; + + (*out_stream) << model_data->morm_finder_join_tables; } return *this; @@ -557,6 +573,7 @@ private: ModelConnector * model_connector; DbExpression * db_expression; ModelClass model; + ModelData model_data_generic; bool was_query_error; std::wstring last_query_error; ModelData * model_data; diff --git a/src/model.cpp b/src/model.cpp index ba899fa..38bfea2 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018, Tomasz Sowa + * Copyright (c) 2018-2019, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -426,10 +426,11 @@ bool Model::save(ModelData & model_data) } -void Model::generate_select_columns(PT::TextStream & stream, const std::wstring & column_prefix) +void Model::generate_select_columns(PT::TextStream & stream, const std::wstring & column_prefix, ModelData * model_data) { if( model_connector ) { + this->model_data = model_data; model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL; DbConnector * db_connector = model_connector->get_db_connector(); @@ -439,6 +440,7 @@ void Model::generate_select_columns(PT::TextStream & stream, const std::wstring } model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; + this->model_data = nullptr; } } diff --git a/src/model.h b/src/model.h index 730af48..8055bff 100644 --- a/src/model.h +++ b/src/model.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018, Tomasz Sowa + * Copyright (c) 2018-2019, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -97,33 +97,33 @@ public: */ virtual void table_name(PT::TextStream & stream); - virtual void to_text(PT::TextStream & stream, ModelData * model_data = nullptr, 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, 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 = nullptr, 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, 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); + 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); + 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); + 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::wstring & column_prefix); + virtual void generate_select_columns(PT::TextStream & stream, const std::wstring & 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); @@ -132,6 +132,12 @@ public: virtual void clear(); + // will be changed + void clear_table_index() + { + table_index = 0; + } + protected: ModelConnector * model_connector; @@ -140,6 +146,7 @@ protected: const void * doc_field_pointer; int model_connector_mode; QueryResult * query_result; + int table_index; Model(); @@ -269,15 +276,16 @@ protected: 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, bool is_primary_key = false) + 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, is_primary_key); + 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, bool is_primary_key = false) + void field(const wchar_t * field_name, std::list & field_value, bool insertable = true, bool updatable = true) { - field_list(field_name, field_name, field_value, insertable, updatable, is_primary_key); + ModelClass * list_model_null_pointer = nullptr; + field_list(field_name, field_name, field_value, list_model_null_pointer, insertable, updatable); } @@ -384,15 +392,16 @@ protected: } - void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, Model & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) + 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, is_primary_key); + 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, bool is_primary_key = false) + void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::list & field_value, bool insertable = true, bool updatable = true) { - field_list(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); + ModelClass * list_model_null_pointer = nullptr; + field_list(db_field_name, flat_field_name, field_value, list_model_null_pointer, insertable, updatable); } ////////////////////// @@ -644,7 +653,7 @@ protected: 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); + flat_expression->field(-1, flat_field_name, field_value, insertable, updatable, is_primary_key, true, model_data); } } } @@ -659,7 +668,7 @@ protected: if( db_expression && !is_empty_field(db_field_name) ) { - db_expression->field(db_field_name, field_value, insertable, updatable, is_primary_key); + db_expression->field(table_index, db_field_name, field_value, insertable, updatable, is_primary_key, true, model_data); } } } @@ -705,14 +714,64 @@ protected: } - void field_model(const wchar_t * db_field_name, const wchar_t * flat_field_name, Model & field_model, bool insertable, bool updatable, bool 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_data ) + { + 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); + + 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); + + 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 << " = "; + + if( !model_data->morm_foreign_keys.empty() ) + { + model_data->morm_finder_join_tables << model_data->morm_foreign_keys.front(); + } + } + else + { + map_fields(); + + model_data->morm_finder_join_tables << " ON "; + + 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 << ' '; + db_expression->set_work_mode(expr_work_mode); + db_expression->set_output_type(expr_output_type); + } + } + + + 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 ) { field_model.set_connector(model_connector); field_model.model_data = model_data; - // IMPLEMENTME what about db? if( model_connector_mode == MORM_MODEL_CONNECTOR_MODE_GENERATING_FLAT_STRING ) { FlatConnector * flat_connector = model_connector->get_flat_connector(); @@ -724,7 +783,36 @@ protected: if( flat_expression && !is_empty_field(flat_field_name) ) { field_model.model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_FLAT_STRING; - flat_expression->field_model(flat_field_name, field_model, insertable, updatable, is_primary_key); + flat_expression->field_model(flat_field_name, field_model, insertable, updatable, false); + field_model.model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; + } + } + } + + if( 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) ) + { + field_model.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 ) + { + field_model.model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL; + field_model.map_fields(); + field_model.model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; + } + field_model.model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; } } @@ -752,7 +840,7 @@ protected: 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, is_primary_key); + doc_expression->field_doc(*this, flat_field_name, field_model, insertable, updatable, false); } } } @@ -762,10 +850,9 @@ protected: } - template - void field_list(const wchar_t * db_field_name, const wchar_t * flat_field_name, ModelContainer & field_container, bool insertable, bool updatable, bool is_primary_key) + 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) { - // IMPLEMENTME what about db? if( model_connector ) { if( model_connector_mode == MORM_MODEL_CONNECTOR_MODE_GENERATING_FLAT_STRING ) @@ -781,11 +868,31 @@ protected: // 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, is_primary_key, model_connector, model_connector_mode, model_data); + flat_expression->field_list(flat_field_name, field_container, insertable, updatable, false, model_connector, model_connector_mode, model_data); } } } + if( 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 ) + { + ModelContainerType model_type; + + model_type.model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL; + field_model(db_field_name, flat_field_name, model_type, insertable, updatable, false); + model_type.model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; + } + } + } + + if( model_connector_mode == MORM_MODEL_CONNECTOR_MODE_CLEARING_VALUE ) { Clearer * clearer = model_connector->get_clearer(); @@ -808,7 +915,7 @@ protected: 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, is_primary_key, model_data); + doc_expression->field_doc(*this, flat_field_name, field_container, insertable, updatable, false, model_data); } } } diff --git a/src/modeldata.h b/src/modeldata.h index 327cddb..273a190 100644 --- a/src/modeldata.h +++ b/src/modeldata.h @@ -43,8 +43,19 @@ class ModelData { public: - ModelData() {} - virtual ~ModelData() {} + ModelData() + { + morm_current_max_column = 0; + } + + virtual ~ModelData() + { + } + + PT::TextStream morm_finder_join_tables; + std::list morm_foreign_keys; + int morm_current_max_column; + /* * may to add: diff --git a/src/morm_types.h b/src/morm_types.h index 379412e..5b3f801 100644 --- a/src/morm_types.h +++ b/src/morm_types.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018, Tomasz Sowa + * Copyright (c) 2018-2019, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,6 +53,7 @@ #define MORM_WORK_MODE_MODEL_VALUES 2 #define MORM_WORK_MODE_MODEL_FIELDS_VALUES 3 +#define MORM_WORK_MODE_MODEL_SAVE_FIELDS 4 // IMPROVE ME give me a better name @@ -68,12 +69,14 @@ //#define MORM_OUTPUT_TYPE_WHERE_CUSTOM 5 #define MORM_OUTPUT_TYPE_SELECT_COLUMNS 6 -#define MORM_OUTPUT_TYPE_WHERE_EQ 7 -#define MORM_OUTPUT_TYPE_WHERE_LT 8 -#define MORM_OUTPUT_TYPE_WHERE_GT 9 -#define MORM_OUTPUT_TYPE_WHERE_LE 10 -#define MORM_OUTPUT_TYPE_WHERE_GE 11 -#define MORM_OUTPUT_TYPE_WHERE_IN 12 +#define MORM_OUTPUT_TYPE_JOIN_TABLES 7 + +#define MORM_OUTPUT_TYPE_WHERE_EQ 10 +#define MORM_OUTPUT_TYPE_WHERE_LT 11 +#define MORM_OUTPUT_TYPE_WHERE_GT 12 +#define MORM_OUTPUT_TYPE_WHERE_LE 13 +#define MORM_OUTPUT_TYPE_WHERE_GE 14 +#define MORM_OUTPUT_TYPE_WHERE_IN 15 #define MORM_CONJUNCTION_AND 1