From 440f56e37699d219ee70d82fc2a38f8d2e892ec9 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Tue, 26 Mar 2019 18:22:21 +0000 Subject: [PATCH 01/10] creating branch branches/join_models git-svn-id: svn://ttmath.org/publicrep/morm/branches/join_models@1185 e52654a7-88a9-db11-a3e9-0013d4bc506e From 9c7a0f3d7eaf6ed4b13e6fb882113b06a6accb80 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Tue, 26 Mar 2019 18:34:07 +0000 Subject: [PATCH 02/10] added: support for generating LEFT JOIN statement in Finder (the primary key should consist of only one column at the moment) git-svn-id: svn://ttmath.org/publicrep/morm/branches/join_models@1186 e52654a7-88a9-db11-a3e9-0013d4bc506e --- src/Makefile.dep | 38 +++++----- src/baseexpression.cpp | 21 +++++- src/baseexpression.h | 43 +++++++++-- src/dbexpression.cpp | 10 ++- src/dbexpression.h | 4 +- src/finder.h | 19 ++++- src/model.cpp | 6 +- src/model.h | 163 ++++++++++++++++++++++++++++++++++------- src/modeldata.h | 15 +++- src/morm_types.h | 17 +++-- 10 files changed, 266 insertions(+), 70 deletions(-) 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 From ab54a3fc3e0be059c459db458f5377771b380c88 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Tue, 26 Mar 2019 20:35:05 +0000 Subject: [PATCH 03/10] 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; From 6d9b9045fe53b307eccae6346b7f1e0c88438eed Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Sun, 31 Mar 2019 20:21:12 +0000 Subject: [PATCH 04/10] fixed: generating a correct table names with indices for JOIN statements and column prefixes git-svn-id: svn://ttmath.org/publicrep/morm/branches/join_models@1188 e52654a7-88a9-db11-a3e9-0013d4bc506e --- src/baseexpression.cpp | 46 ++++++++++++--------- src/baseexpression.h | 18 ++++++--- src/dbexpression.h | 2 +- src/finder.h | 4 +- src/model.cpp | 5 +++ src/model.h | 90 ++++++++++++++++++++---------------------- src/modeldata.h | 40 ++++++++++++++----- 7 files changed, 121 insertions(+), 84 deletions(-) diff --git a/src/baseexpression.cpp b/src/baseexpression.cpp index a864880..28570b2 100644 --- a/src/baseexpression.cpp +++ b/src/baseexpression.cpp @@ -69,9 +69,11 @@ int BaseExpression::get_work_mode() void BaseExpression::prepare_to_new_expression() { column_prefix.clear(); + column_prefix_index = 1; out_stream = nullptr; is_first_field = false; work_mode = 0; + use_prefix = true; } @@ -81,16 +83,35 @@ PT::TextStream * BaseExpression::get_current_stream() } +void BaseExpression::allow_to_use_prefix(bool use_prefix) +{ + this->use_prefix = use_prefix; +} + + void BaseExpression::set_column_prefix(const std::string & prefix) { column_prefix = prefix; } +void BaseExpression::set_column_prefix(const std::string & prefix, int index) +{ + column_prefix = prefix; + column_prefix_index = index; +} + std::string BaseExpression::get_column_prefix() { return column_prefix; } +int BaseExpression::get_column_prefix_index() +{ + return column_prefix_index; +} + + + void BaseExpression::generate_from_model(PT::TextStream & stream, Model & model) { this->out_stream = &stream; @@ -156,24 +177,17 @@ void BaseExpression::field_after() -void BaseExpression::put_field_name(int table_index, const wchar_t * field_name, bool add_column_prefix) +void BaseExpression::put_field_name(const wchar_t * field_name, bool add_column_prefix) { before_field_name(); -// if( !add_column_prefix ) -// { -// -// -// } -// -// if( table_index >= 0 ) -// { -// (*out_stream) << 't' << table_index << '.'; -// } - - if( add_column_prefix && !column_prefix.empty() ) + if( use_prefix && add_column_prefix && !column_prefix.empty() ) { esc(column_prefix, *out_stream); + + if( column_prefix_index > 1 ) + (*out_stream) << column_prefix_index; + (*out_stream) << '.'; } @@ -182,12 +196,6 @@ void BaseExpression::put_field_name(int table_index, const wchar_t * field_name, } -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 e83d92f..0350d73 100644 --- a/src/baseexpression.h +++ b/src/baseexpression.h @@ -62,12 +62,17 @@ public: virtual void prepare_to_new_expression(); virtual void set_column_prefix(const std::string & prefix); + virtual void set_column_prefix(const std::string & prefix, int index); + virtual std::string get_column_prefix(); + virtual int get_column_prefix_index(); 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); // give me a better name virtual void put_field_doc(Model & model, const void * field_pointer, bool insertable, bool updatable, bool is_primary_key, ModelData * model_data); @@ -75,7 +80,7 @@ public: template - 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) + 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, ModelData * model_data = nullptr) { if( out_stream && can_field_be_generated(insertable, updatable, is_primary_key) ) { @@ -83,7 +88,7 @@ public: if( work_mode == MORM_WORK_MODE_MODEL_FIELDS ) { - put_field_name(table_index, field_name, add_column_prefix); + put_field_name(field_name, add_column_prefix); } else if( work_mode == MORM_WORK_MODE_MODEL_SAVE_FIELDS ) @@ -92,7 +97,7 @@ public: PT::TextStream * old_out_stream = out_stream; out_stream = &str; - put_field_name(-1, field_name, add_column_prefix); + put_field_name(field_name, add_column_prefix); out_stream = old_out_stream; if( model_data ) @@ -110,7 +115,7 @@ public: else if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES ) { - put_field_name(table_index, field_name); + put_field_name(field_name); put_name_value_separator(); put_field_value(field_value); } @@ -230,7 +235,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(-1, field_name, field_value, insertable, updatable, is_primary_key); + field(field_name, field_value, insertable, updatable, is_primary_key); this->out_stream = nullptr; } @@ -278,6 +283,8 @@ protected: std::string column_prefix; + int column_prefix_index; + bool use_prefix; virtual void generate_from_model(Model & model); @@ -289,7 +296,6 @@ 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.h b/src/dbexpression.h index 13e1f63..b679c36 100644 --- a/src/dbexpression.h +++ b/src/dbexpression.h @@ -71,7 +71,7 @@ public: column_expression += L" as "; column_expression += new_column_name; - field(-1, column_expression.c_str(), field_value, false, false, false, false); + field(column_expression.c_str(), field_value, false, false, false, false); } diff --git a/src/finder.h b/src/finder.h index 7cafe50..375b398 100644 --- a/src/finder.h +++ b/src/finder.h @@ -176,7 +176,7 @@ public: last_query_error.clear(); model_data = nullptr; column_prefix.clear(); - model.clear_table_index(); // will be changed + model.prepare_to_select(); if( model_connector ) { @@ -608,6 +608,8 @@ private: if( db_connector ) { db_expression = db_connector->get_expression(); + db_expression->allow_to_use_prefix(true); + // set prefix maybe there to an empty string? } } } diff --git a/src/model.cpp b/src/model.cpp index 82700df..9190d2b 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -550,6 +550,11 @@ void Model::clear() } +void Model::prepare_to_select() +{ + table_index = 1; +} + diff --git a/src/model.h b/src/model.h index 29ccba4..7c2a404 100644 --- a/src/model.h +++ b/src/model.h @@ -132,12 +132,8 @@ public: // set object to default values virtual void clear(); + virtual void prepare_to_select(); - // will be changed - void clear_table_index() - { - table_index = 0; - } protected: @@ -654,7 +650,7 @@ protected: if( flat_expression && !is_empty_field(flat_field_name) ) { // insertable, updatable and is_primary_key are ignored here - flat_expression->field(-1, flat_field_name, field_value, insertable, updatable, is_primary_key, true, model_data); + flat_expression->field(flat_field_name, field_value, insertable, updatable, is_primary_key, true, model_data); } } } @@ -669,7 +665,12 @@ protected: if( db_expression && !is_empty_field(db_field_name) ) { - db_expression->field(table_index, db_field_name, field_value, insertable, updatable, is_primary_key, true, model_data); + db_expression->field(db_field_name, field_value, insertable, updatable, is_primary_key, true, model_data); + + if( model_data ) + { + model_data->current_column += 1; + } } } } @@ -681,7 +682,14 @@ protected: if( db_connector ) { if( !is_empty_field(db_field_name) ) + { get_value_by_field_name(db_field_name, field_value); + + if( model_data ) + { + model_data->current_column += 1; + } + } } } @@ -722,11 +730,8 @@ 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 "; @@ -734,41 +739,30 @@ protected: 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); + if( table_index > 1 ) + join_table_name_this << table_index; - 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); + field_model.table_index = model_data->add_join_table(join_table_name); - if( table_index > 1 ) - join_table_name << table_index; + if( field_model.table_index > 1 ) + join_table_name << field_model.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); + db_expression->allow_to_use_prefix(false); if( has_foreign_key ) { @@ -797,9 +791,12 @@ protected: } 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); + + db_expression->allow_to_use_prefix(true); + } } @@ -848,33 +845,32 @@ protected: if( db_expression->get_output_type() != MORM_OUTPUT_TYPE_JOIN_TABLES ) { field_model.model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL; + + // 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); + field_model.table_name_for_join_as(join_table_name); // RENAME this method 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); - + db_expression->set_column_prefix(sss, field_model.table_index); field_model.map_fields(); - db_expression->set_column_prefix(current_prefix); + + db_expression->set_column_prefix(current_prefix, current_table_index); field_model.model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; } field_model.model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; + + if( model_data ) + { + model_data->current_column += 1; + } } } } @@ -944,11 +940,9 @@ protected: 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; + // another select will be used (from another Finder) + // we need only columns name + // but columns are defined in the other model } } } @@ -1145,7 +1139,7 @@ protected: virtual bool is_empty_field(const wchar_t * value); -// template friend class Finder; + //template friend class Finder; template friend class Cursor; friend class BaseExpression; diff --git a/src/modeldata.h b/src/modeldata.h index fa04d49..5f435dc 100644 --- a/src/modeldata.h +++ b/src/modeldata.h @@ -46,6 +46,7 @@ public: ModelData() { morm_current_max_column = 1; + current_column = 1; } virtual ~ModelData() @@ -57,6 +58,10 @@ public: int morm_current_max_column; std::map morm_table_join_map; + int current_column; + //std::vector table_index; + + virtual void prepare_to_new_select() { @@ -67,6 +72,14 @@ public: } + virtual int add_join_table(const PT::TextStream & table_name) + { + std::string table_name_str; + table_name.to_string(table_name_str); + + return add_join_table(table_name_str); + } + virtual int add_join_table(const std::string & table_name) { auto res = morm_table_join_map.insert(std::make_pair(table_name, 1)); @@ -79,17 +92,26 @@ public: return res.first->second; } - virtual int find_join_table_index(const std::string & table_name) - { - auto iter = morm_table_join_map.find(table_name); +// 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; +// } - if( iter != morm_table_join_map.end() ) - { - return iter->second; - } +// virtual int get_table_index(int column) +// { +// if( column < (int)table_index.size() ) +// return table_index[column]; +// +// return 0; +// } - return 0; - } /* * may to add: From 34ddf11351868d8ae0e10ce9aaea68c85eec18e8 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Mon, 13 May 2019 03:12:31 +0000 Subject: [PATCH 05/10] some work in branches/join_models git-svn-id: svn://ttmath.org/publicrep/morm/branches/join_models@1190 e52654a7-88a9-db11-a3e9-0013d4bc506e --- src/cursor.h | 6 ++++++ src/finder.h | 1 + src/model.h | 29 ++++++++++++++++++++++++++--- src/modeldata.h | 5 +++++ src/postgresqlconnector.cpp | 1 + src/postgresqlqueryresult.cpp | 17 +++++++++++++++++ src/postgresqlqueryresult.h | 1 + src/queryresult.cpp | 7 +++++++ src/queryresult.h | 2 ++ 9 files changed, 66 insertions(+), 3 deletions(-) diff --git a/src/cursor.h b/src/cursor.h index 9ff9aa5..1d471f4 100644 --- a/src/cursor.h +++ b/src/cursor.h @@ -152,6 +152,9 @@ public: { try { + if( model_data ) + model_data->current_column = 0; + result.model_data = model_data; result.before_select(); res = select_status; @@ -283,6 +286,9 @@ protected: try { + if( model_data ) + model_data->current_column = 0; + added_model.set_connector(model_connector); added_model.clear(); added_model.set_save_mode(Model::DO_UPDATE_ON_SAVE); // IMPROVE ME check if there is a primary key diff --git a/src/finder.h b/src/finder.h index 375b398..161c43d 100644 --- a/src/finder.h +++ b/src/finder.h @@ -250,6 +250,7 @@ public: } model_data->prepare_to_new_select(); + model_data->has_autogenerated_select = true; if( model_connector && out_stream ) { diff --git a/src/model.h b/src/model.h index 7c2a404..527ef39 100644 --- a/src/model.h +++ b/src/model.h @@ -683,12 +683,15 @@ protected: { if( !is_empty_field(db_field_name) ) { - get_value_by_field_name(db_field_name, field_value); - - if( model_data ) + if( model_data && model_data->has_autogenerated_select ) { + get_value_by_field_index(model_data->current_column, field_value); model_data->current_column += 1; } + else + { + get_value_by_field_name(db_field_name, field_value); + } } } } @@ -978,6 +981,26 @@ protected: } + template + void get_value_by_field_index(int field_index, FieldValue & field_value) + { + if( query_result ) + { + const char * val_str = 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) { diff --git a/src/modeldata.h b/src/modeldata.h index 5f435dc..df6ef2d 100644 --- a/src/modeldata.h +++ b/src/modeldata.h @@ -53,6 +53,9 @@ public: { } + bool has_autogenerated_select; + + PT::TextStream morm_finder_join_tables; std::list morm_foreign_keys; int morm_current_max_column; @@ -65,6 +68,8 @@ public: virtual void prepare_to_new_select() { + has_autogenerated_select = false; + morm_current_max_column = 1; morm_finder_join_tables.clear(); morm_table_join_map.clear(); diff --git a/src/postgresqlconnector.cpp b/src/postgresqlconnector.cpp index 39272f4..b3fb529 100644 --- a/src/postgresqlconnector.cpp +++ b/src/postgresqlconnector.cpp @@ -115,6 +115,7 @@ bool PostgreSQLConnector::do_query(const char * query_str, PostgreSQLQueryResult { psql_result->psql_status = PQresultStatus(psql_result->psql_result); psql_result->result_rows = static_cast(PQntuples(psql_result->psql_result)); + psql_result->result_cols = static_cast(PQnfields(psql_result->psql_result)); } if( !psql_result->psql_result || psql_result->psql_status == PGRES_FATAL_ERROR ) diff --git a/src/postgresqlqueryresult.cpp b/src/postgresqlqueryresult.cpp index bcb45d9..a28f240 100644 --- a/src/postgresqlqueryresult.cpp +++ b/src/postgresqlqueryresult.cpp @@ -67,6 +67,23 @@ bool PostgreSQLQueryResult::has_db_result() } +const char * PostgreSQLQueryResult::get_field_string_value(int column_index) +{ + const char * value_str = nullptr; + + if( column_index >= 0 && (size_t)column_index < result_cols ) + { + if( cur_row < result_rows ) + { + value_str = PQgetvalue(psql_result, cur_row, column_index); + } + } + + return value_str; +} + + + const char * PostgreSQLQueryResult::get_field_string_value(const char * column_name) { const char * value_str = nullptr; diff --git a/src/postgresqlqueryresult.h b/src/postgresqlqueryresult.h index 74c4dd5..3efa8f3 100644 --- a/src/postgresqlqueryresult.h +++ b/src/postgresqlqueryresult.h @@ -57,6 +57,7 @@ struct PostgreSQLQueryResult : public QueryResult virtual bool has_db_result(); + const char * get_field_string_value(int column_index); const char * get_field_string_value(const char * column_name); int get_column_index(const char * column_name); diff --git a/src/queryresult.cpp b/src/queryresult.cpp index b5bd092..2e3c16b 100644 --- a/src/queryresult.cpp +++ b/src/queryresult.cpp @@ -56,6 +56,7 @@ QueryResult::~QueryResult() void QueryResult::clear() { result_rows = 0; + result_cols = 0; cur_row = 0; status = false; error_msg.clear(); @@ -70,6 +71,12 @@ bool QueryResult::has_db_result() } +const char * QueryResult::get_field_string_value(int column_index) +{ + return nullptr; +} + + const char * QueryResult::get_field_string_value(const char * column_name) { return nullptr; diff --git a/src/queryresult.h b/src/queryresult.h index 5caef0e..9ca13bb 100644 --- a/src/queryresult.h +++ b/src/queryresult.h @@ -45,6 +45,7 @@ struct QueryResult { bool status; size_t result_rows; // how many rows in the result query + size_t result_cols; // how many columns in the result query size_t cur_row; // used for reading std::wstring error_msg; @@ -57,6 +58,7 @@ struct QueryResult virtual void clear(); virtual bool has_db_result(); + virtual const char * get_field_string_value(int column_index); virtual const char * get_field_string_value(const char * column_name); virtual const char * get_field_string_value(const wchar_t * field_name); From b37a577713a29d80e72d12e038409b6e59352d55 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Mon, 13 May 2019 17:59:28 +0000 Subject: [PATCH 06/10] some work in branches/join_models added: ModelEnv class - now Model has a pointer to ModelEnv and ModelEnv has a pointer to ModelData, model_connector_mode, table_index and doc_field_pointer git-svn-id: svn://ttmath.org/publicrep/morm/branches/join_models@1191 e52654a7-88a9-db11-a3e9-0013d4bc506e --- src/Makefile.dep | 46 +++--- src/baseexpression.cpp | 2 + src/baseexpression.h | 12 +- src/cursor.h | 32 ++-- src/finder.h | 28 +++- src/model.cpp | 130 +++++++++------- src/model.h | 327 +++++++++++++++++++++++------------------ src/modeldata.h | 11 ++ src/modelenv.h | 90 ++++++++++++ 9 files changed, 441 insertions(+), 237 deletions(-) create mode 100644 src/modelenv.h diff --git a/src/Makefile.dep b/src/Makefile.dep index 8217419..e372200 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 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 ../../pikotools/utf8/utf8.h +baseexpression.o: ../../pikotools/textstream/types.h morm_types.h modelenv.h +baseexpression.o: modeldata.h queryresult.h model.h modelconnector.h +baseexpression.o: clearer.h dbconnector.h ../../pikotools/log/log.h +baseexpression.o: ../../pikotools/log/filelog.h flatconnector.h +baseexpression.o: dbexpression.h 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 modeldata.h flatexpression.h +clearer.o: morm_types.h modelenv.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,7 +27,7 @@ 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 modeldata.h model.h +dbconnector.o: baseexpression.h morm_types.h modelenv.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 @@ -41,7 +41,8 @@ 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 modeldata.h +dbexpression.o: ../../pikotools/textstream/types.h morm_types.h modelenv.h +dbexpression.o: modeldata.h queryresult.h dochtmlconnector.o: dochtmlconnector.h flatconnector.h dochtmlconnector.o: ../../pikotools/textstream/textstream.h dochtmlconnector.o: ../../pikotools/space/space.h @@ -50,8 +51,8 @@ dochtmlconnector.o: ../../pikotools/date/date.h 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 +dochtmlconnector.o: flatexpression.h baseexpression.h morm_types.h modelenv.h +dochtmlconnector.o: modeldata.h queryresult.h dochtmlexpression.o: dochtmlexpression.h flatexpression.h baseexpression.h dochtmlexpression.o: ../../pikotools/textstream/textstream.h dochtmlexpression.o: ../../pikotools/space/space.h @@ -60,7 +61,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 +dochtmlexpression.o: modelenv.h modeldata.h queryresult.h flatconnector.o: flatconnector.h ../../pikotools/textstream/textstream.h flatconnector.o: ../../pikotools/space/space.h flatconnector.o: ../../pikotools/textstream/types.h @@ -68,10 +69,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 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 +flatconnector.o: baseexpression.h morm_types.h modelenv.h modeldata.h +flatconnector.o: queryresult.h model.h modelconnector.h clearer.h +flatconnector.o: dbconnector.h ../../pikotools/log/log.h +flatconnector.o: ../../pikotools/log/filelog.h dbexpression.h flatexpression.o: flatexpression.h baseexpression.h flatexpression.o: ../../pikotools/textstream/textstream.h flatexpression.o: ../../pikotools/space/space.h @@ -79,7 +80,8 @@ 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 modeldata.h +flatexpression.o: ../../pikotools/textstream/types.h morm_types.h modelenv.h +flatexpression.o: modeldata.h queryresult.h jsonconnector.o: jsonconnector.h flatconnector.h jsonconnector.o: ../../pikotools/textstream/textstream.h jsonconnector.o: ../../pikotools/space/space.h @@ -88,7 +90,8 @@ 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 modeldata.h +jsonconnector.o: flatexpression.h baseexpression.h morm_types.h modelenv.h +jsonconnector.o: modeldata.h queryresult.h jsonexpression.o: jsonexpression.h flatexpression.h baseexpression.h jsonexpression.o: ../../pikotools/textstream/textstream.h jsonexpression.o: ../../pikotools/space/space.h @@ -96,7 +99,8 @@ 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 modeldata.h +jsonexpression.o: ../../pikotools/textstream/types.h morm_types.h modelenv.h +jsonexpression.o: modeldata.h queryresult.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 @@ -104,7 +108,7 @@ 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 modeldata.h +model.o: dbexpression.h baseexpression.h morm_types.h modelenv.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 @@ -127,7 +131,7 @@ 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 modeldata.h +postgresqlconnector.o: morm_types.h modelenv.h modeldata.h postgresqlconnector.o: ../../pikotools/convert/strtoint.h postgresqlconnector.o: ../../pikotools/convert/text.h postgresqlconnector.o: ../../pikotools/convert/misc.h @@ -140,7 +144,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 +postgresqlexpression.o: modelenv.h modeldata.h queryresult.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 28570b2..554837f 100644 --- a/src/baseexpression.cpp +++ b/src/baseexpression.cpp @@ -199,11 +199,13 @@ void BaseExpression::put_field_name(const wchar_t * field_name, bool add_column_ void BaseExpression::put_field_doc(Model & model, const void * field_pointer, bool insertable, bool updatable, bool is_primary_key, ModelData * model_data) { + /* model.doc_field_pointer = field_pointer; model.model_data = model_data; model.map_doc_fields(); model.model_data = nullptr; model.doc_field_pointer = nullptr; + */ } void BaseExpression::before_field_name() diff --git a/src/baseexpression.h b/src/baseexpression.h index 0350d73..a80ce74 100644 --- a/src/baseexpression.h +++ b/src/baseexpression.h @@ -40,7 +40,7 @@ #include "textstream/textstream.h" #include "date/date.h" #include "morm_types.h" -#include "modeldata.h" +#include "modelenv.h" @@ -330,13 +330,15 @@ protected: (*out_stream) << ","; // make a virtual method } + ModelEnv model_env_local; + m.model_env = &model_env_local; + //before_field_value(field_value); m.set_connector(model_connector); - m.model_connector_mode = model_connector_mode; - m.model_data = model_data; + m.model_env->model_connector_mode = model_connector_mode; + m.model_env->model_data = model_data; generate_from_model(m); - m.model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; - m.model_data = nullptr; + m.model_env = nullptr; //after_field_value(field_value); is_first = false; } diff --git a/src/cursor.h b/src/cursor.h index 1d471f4..6b42474 100644 --- a/src/cursor.h +++ b/src/cursor.h @@ -144,18 +144,21 @@ public: result.set_connector(model_connector); result.clear(); - if( model_connector && query_result && query_result->has_db_result() ) + if( model_connector && query_result && query_result->has_db_result() && model_data ) { DbConnector * db_connector = model_connector->get_db_connector(); if( db_connector ) { + ModelEnv model_env_local; + result.model_env = &model_env_local; + try { - if( model_data ) - model_data->current_column = 0; + model_data->current_column = 0; + model_data->query_result = query_result; - result.model_data = model_data; + result.model_env->model_data = model_data; result.before_select(); res = select_status; @@ -164,7 +167,7 @@ public: if( query_result->cur_row < query_result->result_rows ) { result.set_save_mode(Model::DO_UPDATE_ON_SAVE); // IMPROVE ME check if there is a primary key - result.map_values_from_query(query_result); + result.map_values_from_query(); result.after_select(); query_result->cur_row += 1; } @@ -185,7 +188,7 @@ public: // throw something? } - result.model_data = nullptr; + result.model_env = nullptr; } } @@ -198,7 +201,7 @@ public: ModelClass model; get(model); - return std::move(model); + return model; } @@ -211,7 +214,7 @@ public: result.clear(); } - if( model_connector && query_result && query_result->has_db_result() ) + if( model_connector && query_result && query_result->has_db_result() && model_data ) { DbConnector * db_connector = model_connector->get_db_connector(); @@ -284,17 +287,20 @@ protected: result.emplace_back(); // it returns a reference from c++17 ModelClass & added_model = result.back(); + ModelEnv model_env_local; + added_model.model_env = &model_env_local; + try { - if( model_data ) - model_data->current_column = 0; + model_data->current_column = 0; + model_data->query_result = query_result; added_model.set_connector(model_connector); added_model.clear(); added_model.set_save_mode(Model::DO_UPDATE_ON_SAVE); // IMPROVE ME check if there is a primary key - added_model.model_data = model_data; + added_model.model_env->model_data = model_data; added_model.before_select(); - added_model.map_values_from_query(query_result); + added_model.map_values_from_query(); added_model.after_select(); } catch(...) @@ -303,7 +309,7 @@ protected: // throw or something? } - added_model.model_data = nullptr; + added_model.model_env = nullptr; } return res; diff --git a/src/finder.h b/src/finder.h index 161c43d..6b767fb 100644 --- a/src/finder.h +++ b/src/finder.h @@ -174,8 +174,13 @@ public: { was_query_error = false; last_query_error.clear(); - model_data = nullptr; column_prefix.clear(); + + model.model_env = &model_env; + model.model_env->clear(); + + //model.model_data = nullptr; + // what about model_data in model here? model.prepare_to_select(); if( model_connector ) @@ -198,6 +203,11 @@ public: last_query_error = L"model connector object is required"; } + if( !model_data ) + { + model_data = &model_data_generic; + } + return *this; } @@ -244,11 +254,19 @@ public: prepare_to_select(); } + if( !model.model_env ) + { + model.model_env = &model_env; + model.model_env->clear(); + } + if( !model_data ) { model_data = &model_data_generic; } + model.model_env->model_data = model_data; + model_data->prepare_to_new_select(); model_data->has_autogenerated_select = true; @@ -265,7 +283,7 @@ public: model_data->add_join_table(column_prefix); } - model.generate_select_columns(*out_stream, column_prefix, model_data); + model.generate_select_columns(*out_stream, column_prefix); (*out_stream) << " FROM "; model.table_name(*out_stream); @@ -293,6 +311,7 @@ public: return *this; } + Finder & select(ModelData * model_data, bool call_prepare = true) { if( call_prepare ) @@ -304,6 +323,7 @@ public: return select(false); } + Finder & select(ModelData & model_data, bool call_prepare = true) { if( call_prepare ) @@ -315,6 +335,7 @@ public: return select(false); } + Finder & where() { if( out_stream && db_expression ) @@ -579,7 +600,7 @@ public: std::list result; get_list(result, false); - return std::move(result); + return result; } @@ -597,6 +618,7 @@ private: std::wstring last_query_error; ModelData * model_data; std::string column_prefix; + ModelEnv model_env; diff --git a/src/model.cpp b/src/model.cpp index 9190d2b..5e51fc0 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -41,11 +41,8 @@ namespace morm Model::Model() { model_connector = nullptr; - model_data = nullptr; - doc_field_pointer = nullptr; + model_env = nullptr; save_mode = DO_INSERT_ON_SAVE; - model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; - query_result = nullptr; } @@ -53,11 +50,7 @@ Model::Model(const Model & m) { model_connector = m.model_connector; save_mode = m.save_mode; - - model_data = nullptr; - doc_field_pointer = nullptr; // does it need to be copied? - model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; - query_result = nullptr; + model_env = m.model_env; // or just set to null? } @@ -65,6 +58,7 @@ Model::~Model() { } + void Model::set_save_mode(SaveMode save_mode) { this->save_mode = save_mode; @@ -170,7 +164,10 @@ void Model::to_text(PT::TextStream & stream, ModelData * model_data, bool clear_ stream.clear(); } - model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_FLAT_STRING; + ModelEnv model_env_local; + model_env = &model_env_local; + + model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_FLAT_STRING; if( model_connector ) { @@ -178,13 +175,14 @@ void Model::to_text(PT::TextStream & stream, ModelData * model_data, bool clear_ if( flat_connector ) { - this->model_data = model_data; + this->model_env->model_data = model_data; flat_connector->to_text(stream, *this); - this->model_data = nullptr; + this->model_env->model_data = nullptr; } } - model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; + // what about if an exception was thrown? this pointer will not be null + model_env = nullptr; } @@ -247,7 +245,7 @@ std::string Model::to_string() void Model::generate_insert_query(PT::TextStream & stream) { - model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL; + model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL; if( model_connector ) { @@ -259,7 +257,7 @@ void Model::generate_insert_query(PT::TextStream & stream) } } - model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; + model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; } @@ -270,8 +268,11 @@ bool Model::insert(ModelData * model_data) if( model_connector ) { - this->model_data = model_data; - model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL; + ModelEnv model_env_local; + model_env = &model_env_local; + + model_env->model_data = model_data; + model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL; DbConnector * db_connector = model_connector->get_db_connector(); // CHECK ME what if the stream is being used by something other? @@ -294,8 +295,8 @@ bool Model::insert(ModelData * model_data) } } - this->model_data = nullptr; - model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; + // what about if an exception was thrown? this pointer will not be null + model_env = nullptr; } return result; @@ -311,7 +312,7 @@ bool Model::insert(ModelData & model_data) void Model::generate_update_query(PT::TextStream & stream) { - model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL; + model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL; if( model_connector ) { @@ -323,7 +324,7 @@ void Model::generate_update_query(PT::TextStream & stream) } } - model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; + model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; } @@ -333,8 +334,11 @@ bool Model::update(ModelData * model_data) if( model_connector ) { - this->model_data = model_data; - model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL; + ModelEnv model_env_local; + model_env = &model_env_local; + + model_env->model_data = model_data; + model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL; DbConnector * db_connector = model_connector->get_db_connector(); // CHECK ME what if the stream is being used by something other? @@ -352,8 +356,8 @@ bool Model::update(ModelData * model_data) after_update_failure(); } - this->model_data = nullptr; - model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; + // what about if an exception was thrown? this pointer will not be null + model_env = nullptr; } return result; @@ -371,14 +375,14 @@ void Model::generate_remove_query(PT::TextStream & stream) if( model_connector ) { DbConnector * db_connector = model_connector->get_db_connector(); - model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL; + model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL; if( db_connector ) { db_connector->generate_remove_query(stream, *this); } - model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; + model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; } } @@ -389,8 +393,11 @@ bool Model::remove(ModelData * model_data) if( model_connector ) { - this->model_data = model_data; - model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL; + ModelEnv model_env_local; + model_env = &model_env_local; + + model_env->model_data = model_data; + model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL; DbConnector * db_connector = model_connector->get_db_connector(); // CHECK ME what if the stream is being used by something other? @@ -413,8 +420,8 @@ bool Model::remove(ModelData * model_data) } } - this->model_data = nullptr; - model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; + // what about if an exception was thrown? this pointer will not be null + model_env = nullptr; } return result; @@ -460,21 +467,17 @@ bool Model::save(ModelData & model_data) } -void Model::generate_select_columns(PT::TextStream & stream, const std::string & column_prefix, ModelData * model_data) +void Model::generate_select_columns(PT::TextStream & stream, const std::string & column_prefix) { - if( model_connector ) + if( model_connector && model_env ) { - this->model_data = model_data; - model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL; + model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL; DbConnector * db_connector = model_connector->get_db_connector(); if( db_connector ) { db_connector->generate_select_columns(stream, *this, column_prefix); } - - model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; - this->model_data = nullptr; } } @@ -487,7 +490,7 @@ void Model::generate_doc_for_flat(PT::TextStream & stream, bool clear_stream) stream.clear(); } - model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DOC_FOR_FLAT; + model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DOC_FOR_FLAT; if( model_connector ) { @@ -499,7 +502,7 @@ void Model::generate_doc_for_flat(PT::TextStream & stream, bool clear_stream) } } - model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; + model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; } @@ -510,7 +513,7 @@ void Model::generate_doc_for_db(PT::TextStream & stream, bool clear_stream) stream.clear(); } - model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DOC_FOR_DB; + model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DOC_FOR_DB; if( model_connector ) { @@ -522,37 +525,35 @@ void Model::generate_doc_for_db(PT::TextStream & stream, bool clear_stream) } } - model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; + model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; } -void Model::map_values_from_query(QueryResult * query_result) +void Model::map_values_from_query() { - model_connector_mode = MORM_MODEL_CONNECTOR_MODE_READING_VALUE_FROM_DB_RESULTSET; - this->query_result = query_result; - + model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_READING_VALUE_FROM_DB_RESULTSET; map_fields(); - - model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; - this->query_result = nullptr; + model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; } void Model::clear() { - model_connector_mode = MORM_MODEL_CONNECTOR_MODE_CLEARING_VALUE; + ModelEnv model_env_local; + model_env = &model_env_local; + + model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_CLEARING_VALUE; map_fields(); - model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; + model_env = nullptr; save_mode = DO_INSERT_ON_SAVE; - model_data = nullptr; } void Model::prepare_to_select() { - table_index = 1; + model_env->table_index = 1; } @@ -610,9 +611,30 @@ void Model::after_remove_failure() int Model::get_connector_mode() { - return model_connector_mode; + if( model_env ) + { + return model_env->model_connector_mode; + } + else + { + return MORM_MODEL_CONNECTOR_MODE_NONE; + } } + +ModelData * Model::get_model_data() +{ + if( model_env ) + { + return model_env->model_data; + } + else + { + return nullptr; + } +} + + bool Model::is_empty_field(const wchar_t * value) { return (!value || *value == '\0'); diff --git a/src/model.h b/src/model.h index 527ef39..3cdce56 100644 --- a/src/model.h +++ b/src/model.h @@ -41,8 +41,7 @@ #include "modelconnector.h" #include "dbexpression.h" #include "flatexpression.h" -#include "queryresult.h" -#include "modeldata.h" +#include "modelenv.h" @@ -124,7 +123,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::string & column_prefix, 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); @@ -132,6 +131,7 @@ public: // set object to default values virtual void clear(); + // we need a pointer to ModelData here? virtual void prepare_to_select(); @@ -139,11 +139,8 @@ protected: ModelConnector * model_connector; SaveMode save_mode; - ModelData * model_data; - const void * doc_field_pointer; - int model_connector_mode; - QueryResult * query_result; - int table_index; + ModelEnv * model_env; + Model(); @@ -167,8 +164,10 @@ protected: virtual int get_connector_mode(); + virtual ModelData * get_model_data(); + // used by Cursor - virtual void map_values_from_query(QueryResult * query_result); + virtual void map_values_from_query(); ///////////////////////////////// @@ -639,7 +638,7 @@ protected: { if( model_connector ) { - if( model_connector_mode == MORM_MODEL_CONNECTOR_MODE_GENERATING_FLAT_STRING ) + if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_GENERATING_FLAT_STRING ) { FlatConnector * flat_connector = model_connector->get_flat_connector(); @@ -650,12 +649,12 @@ 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, true, model_data); + flat_expression->field(flat_field_name, field_value, insertable, updatable, is_primary_key, true, model_env->model_data); } } } - if( model_connector_mode == MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL ) + if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL ) { DbConnector * db_connector = model_connector->get_db_connector(); @@ -665,17 +664,17 @@ protected: if( db_expression && !is_empty_field(db_field_name) ) { - db_expression->field(db_field_name, field_value, insertable, updatable, is_primary_key, true, model_data); + db_expression->field(db_field_name, field_value, insertable, updatable, is_primary_key, true, model_env->model_data); - if( model_data ) + if( model_env->model_data ) { - model_data->current_column += 1; + model_env->model_data->current_column += 1; } } } } - if( model_connector_mode == MORM_MODEL_CONNECTOR_MODE_READING_VALUE_FROM_DB_RESULTSET ) + if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_READING_VALUE_FROM_DB_RESULTSET ) { DbConnector * db_connector = model_connector->get_db_connector(); @@ -683,10 +682,10 @@ protected: { if( !is_empty_field(db_field_name) ) { - if( model_data && model_data->has_autogenerated_select ) + if( model_env->model_data && model_env->model_data->has_autogenerated_select ) { - get_value_by_field_index(model_data->current_column, field_value); - model_data->current_column += 1; + get_value_by_field_index(model_env->model_data->current_column, field_value); + model_env->model_data->current_column += 1; } else { @@ -696,7 +695,7 @@ protected: } } - if( model_connector_mode == MORM_MODEL_CONNECTOR_MODE_CLEARING_VALUE ) + if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_CLEARING_VALUE ) { Clearer * clearer = model_connector->get_clearer(); @@ -706,7 +705,7 @@ protected: } } - if( model_connector_mode == MORM_MODEL_CONNECTOR_MODE_GENERATING_DOC_FOR_FLAT ) + 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) @@ -728,36 +727,36 @@ protected: 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 ) + if( model_env->model_data ) { - model_data->morm_current_max_column += 1; - model_data->morm_foreign_keys.clear(); + model_env->model_data->morm_current_max_column += 1; + model_env->model_data->morm_foreign_keys.clear(); - 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 "; + model_env->model_data->morm_finder_join_tables << "LEFT JOIN "; + field_model.table_name(model_env->model_data->morm_finder_join_tables); + model_env->model_data->morm_finder_join_tables << " AS "; ////////////// PT::TextStream join_table_name_this; table_name_for_join_as(join_table_name_this); - if( table_index > 1 ) - join_table_name_this << table_index; + 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.table_index = model_data->add_join_table(join_table_name); + field_model.model_env->table_index = model_env->model_data->add_join_table(join_table_name); - if( field_model.table_index > 1 ) - join_table_name << field_model.table_index; + if( field_model.model_env->table_index > 1 ) + join_table_name << field_model.model_env->table_index; ////////// - model_data->morm_finder_join_tables << join_table_name; + model_env->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(); @@ -771,29 +770,29 @@ protected: { field_model.map_fields(); - model_data->morm_finder_join_tables << " ON " << join_table_name_this << '.' << db_field_name; // escape? - model_data->morm_finder_join_tables << " = " << join_table_name << '.'; + model_env->model_data->morm_finder_join_tables << " ON " << join_table_name_this << '.' << db_field_name; // escape? + model_env->model_data->morm_finder_join_tables << " = " << join_table_name << '.'; - if( !model_data->morm_foreign_keys.empty() ) + if( !model_env->model_data->morm_foreign_keys.empty() ) { - model_data->morm_finder_join_tables << model_data->morm_foreign_keys.front(); + model_env->model_data->morm_finder_join_tables << model_env->model_data->morm_foreign_keys.front(); } } else { map_fields(); - model_data->morm_finder_join_tables << " ON " << join_table_name_this << '.'; + model_env->model_data->morm_finder_join_tables << " ON " << join_table_name_this << '.'; - if( !model_data->morm_foreign_keys.empty() ) + if( !model_env->model_data->morm_foreign_keys.empty() ) { - model_data->morm_finder_join_tables << model_data->morm_foreign_keys.front(); + model_env->model_data->morm_finder_join_tables << model_env->model_data->morm_foreign_keys.front(); } - model_data->morm_finder_join_tables << " = " << (join_table_name) << '.' << db_field_name; + model_env->model_data->morm_finder_join_tables << " = " << (join_table_name) << '.' << db_field_name; } - model_data->morm_finder_join_tables << ' '; + model_env->model_data->morm_finder_join_tables << ' '; db_expression->set_work_mode(expr_work_mode); db_expression->set_output_type(expr_output_type); @@ -804,108 +803,155 @@ protected: } + + 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; + + if( model_env->model_data ) + { + model_env->model_data->current_column += 1; + } + } + } + } + + + 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 ) { + ModelEnv model_env_local(*model_env); + field_model.model_env = &model_env_local; field_model.set_connector(model_connector); - field_model.model_data = model_data; - if( model_connector_mode == MORM_MODEL_CONNECTOR_MODE_GENERATING_FLAT_STRING ) + 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) ) - { - field_model.model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_FLAT_STRING; - flat_expression->field_model(flat_field_name, field_model, insertable, updatable, false); - field_model.model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; - } - } + field_model_generate_flat_string(db_field_name, flat_field_name, field_model, insertable, updatable, has_foreign_key); } - if( model_connector_mode == MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL ) + 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) ) - { - 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; - - // 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); - - db_expression->set_column_prefix(sss, field_model.table_index); - - field_model.map_fields(); - - db_expression->set_column_prefix(current_prefix, current_table_index); - field_model.model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; - } - - field_model.model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; - - if( model_data ) - { - model_data->current_column += 1; - } - } - } + field_model_generate_db_sql(db_field_name, flat_field_name, field_model, insertable, updatable, has_foreign_key); } - if( model_connector_mode == MORM_MODEL_CONNECTOR_MODE_CLEARING_VALUE ) + if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_CLEARING_VALUE ) { - Clearer * clearer = model_connector->get_clearer(); - - if( clearer ) - { - clearer->clear_model(field_model); - } + field_model_clear_values(db_field_name, flat_field_name, field_model, insertable, updatable, has_foreign_key); } - if( model_connector_mode == MORM_MODEL_CONNECTOR_MODE_GENERATING_DOC_FOR_FLAT ) + 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_model, insertable, updatable, false); - } - } + field_model_generate_doc_flat(db_field_name, flat_field_name, field_model, insertable, updatable, has_foreign_key); } - field_model.model_data = nullptr; + 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; } } @@ -915,7 +961,7 @@ protected: { if( model_connector ) { - if( model_connector_mode == MORM_MODEL_CONNECTOR_MODE_GENERATING_FLAT_STRING ) + if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_GENERATING_FLAT_STRING ) { FlatConnector * flat_connector = model_connector->get_flat_connector(); @@ -928,12 +974,12 @@ 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, false, model_connector, model_connector_mode, model_data); + flat_expression->field_list(flat_field_name, field_container, insertable, updatable, false, model_connector, model_env->model_connector_mode, model_env->model_data); } } } - if( model_connector_mode == MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL ) + if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL ) { DbConnector * db_connector = model_connector->get_db_connector(); @@ -951,7 +997,7 @@ protected: } - if( model_connector_mode == MORM_MODEL_CONNECTOR_MODE_CLEARING_VALUE ) + if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_CLEARING_VALUE ) { Clearer * clearer = model_connector->get_clearer(); @@ -961,7 +1007,7 @@ protected: } } - if( model_connector_mode == MORM_MODEL_CONNECTOR_MODE_GENERATING_DOC_FOR_FLAT ) + 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) @@ -973,7 +1019,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, false, model_data); + doc_expression->field_doc(*this, flat_field_name, field_container, insertable, updatable, false, model_env->model_data); } } } @@ -984,9 +1030,9 @@ protected: template void get_value_by_field_index(int field_index, FieldValue & field_value) { - if( query_result ) + if( model_env->model_data && model_env->model_data->query_result ) { - const char * val_str = query_result->get_field_string_value(field_index); + const char * val_str = model_env->model_data->query_result->get_field_string_value(field_index); if( val_str ) { @@ -1004,9 +1050,9 @@ protected: template void get_value_by_field_name(const wchar_t * field_name, FieldValue & field_value) { - if( query_result ) + if( model_env->model_data && model_env->model_data->query_result ) { - const char * val_str = query_result->get_field_string_value(field_name); + const char * val_str = model_env->model_data->query_result->get_field_string_value(field_name); if( val_str ) { @@ -1025,7 +1071,7 @@ protected: 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) == doc_field_pointer && model_connector ) + if( reinterpret_cast(&field_value) == model_env->doc_field_pointer && model_connector ) { FlatConnector * doc_connector = model_connector->get_doc_connector(); @@ -1049,7 +1095,7 @@ protected: void doc_field_model(const wchar_t * db_field_name, const wchar_t * flat_field_name, Model & field_model) { - if( reinterpret_cast(&field_model) == doc_field_pointer && model_connector ) + if( reinterpret_cast(&field_model) == model_env->doc_field_pointer && model_connector ) { FlatConnector * doc_connector = model_connector->get_doc_connector(); @@ -1074,7 +1120,7 @@ protected: 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) == doc_field_pointer && model_connector ) + if( reinterpret_cast(&field_container) == model_env->doc_field_pointer && model_connector ) { FlatConnector * doc_connector = model_connector->get_doc_connector(); @@ -1161,8 +1207,7 @@ protected: virtual bool is_empty_field(const wchar_t * value); - - //template friend class Finder; + template friend class Finder; template friend class Cursor; friend class BaseExpression; diff --git a/src/modeldata.h b/src/modeldata.h index df6ef2d..8781181 100644 --- a/src/modeldata.h +++ b/src/modeldata.h @@ -35,6 +35,8 @@ #ifndef headerfile_morm_modeldata #define headerfile_morm_modeldata +#include "queryresult.h" + namespace morm { @@ -47,6 +49,7 @@ public: { morm_current_max_column = 1; current_column = 1; + query_result = nullptr; } virtual ~ModelData() @@ -55,7 +58,12 @@ public: bool has_autogenerated_select; + QueryResult * query_result; +// int table_index; + + // can be moved to another struct? + // let ModelData be only for user stuff PT::TextStream morm_finder_join_tables; std::list morm_foreign_keys; int morm_current_max_column; @@ -69,6 +77,9 @@ public: virtual void prepare_to_new_select() { has_autogenerated_select = false; + query_result = nullptr; + +// table_index = 1; morm_current_max_column = 1; morm_finder_join_tables.clear(); diff --git a/src/modelenv.h b/src/modelenv.h new file mode 100644 index 0000000..5c34e14 --- /dev/null +++ b/src/modelenv.h @@ -0,0 +1,90 @@ +/* + * This file is a part of morm + * and is distributed under the 2-Clause BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 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_modelenv +#define headerfile_morm_modelenv + +#include "modeldata.h" +#include "morm_types.h" + + +namespace morm +{ + +// rename me? +class ModelEnv +{ +public: + + ModelData * model_data; + int model_connector_mode; + int table_index; + const void * doc_field_pointer; + + + ModelEnv() + { + clear(); + } + + + ~ModelEnv() + { + } + + + ModelEnv(const ModelEnv & e) + { + model_data = e.model_data; + model_connector_mode = e.model_connector_mode; + table_index = e.table_index; + doc_field_pointer = e.doc_field_pointer; + } + + + void clear() + { + model_data = nullptr; + model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; + table_index = 0; + doc_field_pointer = nullptr; + } + + +}; + +} + + +#endif From 958e89fb022b735b63b58c1747728558a6031b19 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Tue, 21 May 2019 15:51:13 +0000 Subject: [PATCH 07/10] some work in branches/join_models - added FinderHelper class - used as a global object for the whole model tree in Finder (some fields moved from ModelData) - added CursorHelper class - used as a global object for the whole model tree in Cursor (some fields moved from ModelData) git-svn-id: svn://ttmath.org/publicrep/morm/branches/join_models@1192 e52654a7-88a9-db11-a3e9-0013d4bc506e --- src/Makefile.dep | 46 +++++++++++--------- src/baseexpression.cpp | 12 +++--- src/baseexpression.h | 63 +++++++++++++++------------ src/cursor.h | 48 ++++++++++++++------- src/cursorhelper.h | 76 ++++++++++++++++++++++++++++++++ src/finder.h | 51 +++++++--------------- src/finderhelper.h | 98 ++++++++++++++++++++++++++++++++++++++++++ src/jsonexpression.cpp | 12 ++++++ src/jsonexpression.h | 3 ++ src/model.cpp | 9 ++-- src/model.h | 72 +++++++++++++------------------ src/modeldata.h | 87 ------------------------------------- src/modelenv.h | 10 ++++- 13 files changed, 349 insertions(+), 238 deletions(-) create mode 100644 src/cursorhelper.h create mode 100644 src/finderhelper.h diff --git a/src/Makefile.dep b/src/Makefile.dep index e372200..4a4f46e 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep @@ -7,10 +7,11 @@ 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 modelenv.h -baseexpression.o: modeldata.h queryresult.h model.h modelconnector.h -baseexpression.o: clearer.h dbconnector.h ../../pikotools/log/log.h -baseexpression.o: ../../pikotools/log/filelog.h flatconnector.h -baseexpression.o: dbexpression.h flatexpression.h ../../pikotools/utf8/utf8.h +baseexpression.o: modeldata.h cursorhelper.h queryresult.h finderhelper.h +baseexpression.o: model.h modelconnector.h clearer.h dbconnector.h +baseexpression.o: ../../pikotools/log/log.h ../../pikotools/log/filelog.h +baseexpression.o: flatconnector.h dbexpression.h flatexpression.h +baseexpression.o: ../../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 +20,8 @@ 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 modelenv.h modeldata.h flatexpression.h +clearer.o: morm_types.h modelenv.h modeldata.h cursorhelper.h finderhelper.h +clearer.o: 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 +29,9 @@ 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 modelenv.h modeldata.h model.h -dbconnector.o: modelconnector.h clearer.h flatconnector.h flatexpression.h +dbconnector.o: baseexpression.h morm_types.h modelenv.h modeldata.h +dbconnector.o: cursorhelper.h finderhelper.h model.h modelconnector.h +dbconnector.o: 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 @@ -42,7 +45,7 @@ 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 modelenv.h -dbexpression.o: modeldata.h queryresult.h +dbexpression.o: modeldata.h cursorhelper.h queryresult.h finderhelper.h dochtmlconnector.o: dochtmlconnector.h flatconnector.h dochtmlconnector.o: ../../pikotools/textstream/textstream.h dochtmlconnector.o: ../../pikotools/space/space.h @@ -52,7 +55,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 modelenv.h -dochtmlconnector.o: modeldata.h queryresult.h +dochtmlconnector.o: modeldata.h cursorhelper.h queryresult.h finderhelper.h dochtmlexpression.o: dochtmlexpression.h flatexpression.h baseexpression.h dochtmlexpression.o: ../../pikotools/textstream/textstream.h dochtmlexpression.o: ../../pikotools/space/space.h @@ -61,7 +64,8 @@ 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: modelenv.h modeldata.h queryresult.h +dochtmlexpression.o: modelenv.h modeldata.h cursorhelper.h queryresult.h +dochtmlexpression.o: finderhelper.h flatconnector.o: flatconnector.h ../../pikotools/textstream/textstream.h flatconnector.o: ../../pikotools/space/space.h flatconnector.o: ../../pikotools/textstream/types.h @@ -70,9 +74,10 @@ 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 modelenv.h modeldata.h -flatconnector.o: queryresult.h model.h modelconnector.h clearer.h -flatconnector.o: dbconnector.h ../../pikotools/log/log.h -flatconnector.o: ../../pikotools/log/filelog.h dbexpression.h +flatconnector.o: cursorhelper.h queryresult.h finderhelper.h model.h +flatconnector.o: modelconnector.h clearer.h dbconnector.h +flatconnector.o: ../../pikotools/log/log.h ../../pikotools/log/filelog.h +flatconnector.o: dbexpression.h flatexpression.o: flatexpression.h baseexpression.h flatexpression.o: ../../pikotools/textstream/textstream.h flatexpression.o: ../../pikotools/space/space.h @@ -81,7 +86,7 @@ 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 modelenv.h -flatexpression.o: modeldata.h queryresult.h +flatexpression.o: modeldata.h cursorhelper.h queryresult.h finderhelper.h jsonconnector.o: jsonconnector.h flatconnector.h jsonconnector.o: ../../pikotools/textstream/textstream.h jsonconnector.o: ../../pikotools/space/space.h @@ -91,7 +96,7 @@ 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 modelenv.h -jsonconnector.o: modeldata.h queryresult.h +jsonconnector.o: modeldata.h cursorhelper.h queryresult.h finderhelper.h jsonexpression.o: jsonexpression.h flatexpression.h baseexpression.h jsonexpression.o: ../../pikotools/textstream/textstream.h jsonexpression.o: ../../pikotools/space/space.h @@ -100,7 +105,7 @@ 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 modelenv.h -jsonexpression.o: modeldata.h queryresult.h +jsonexpression.o: modeldata.h cursorhelper.h queryresult.h finderhelper.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 @@ -109,7 +114,7 @@ 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 modelenv.h modeldata.h -model.o: flatexpression.h +model.o: cursorhelper.h finderhelper.h 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 @@ -131,8 +136,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 modelenv.h modeldata.h -postgresqlconnector.o: ../../pikotools/convert/strtoint.h +postgresqlconnector.o: morm_types.h modelenv.h modeldata.h cursorhelper.h +postgresqlconnector.o: finderhelper.h ../../pikotools/convert/strtoint.h postgresqlconnector.o: ../../pikotools/convert/text.h postgresqlconnector.o: ../../pikotools/convert/misc.h postgresqlexpression.o: postgresqlexpression.h dbexpression.h @@ -144,7 +149,8 @@ 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: modelenv.h modeldata.h queryresult.h +postgresqlexpression.o: modelenv.h modeldata.h cursorhelper.h queryresult.h +postgresqlexpression.o: finderhelper.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 554837f..6f826ae 100644 --- a/src/baseexpression.cpp +++ b/src/baseexpression.cpp @@ -197,15 +197,13 @@ void BaseExpression::put_field_name(const wchar_t * field_name, bool add_column_ -void BaseExpression::put_field_doc(Model & model, const void * field_pointer, bool insertable, bool updatable, bool is_primary_key, ModelData * model_data) +void BaseExpression::put_field_doc(Model & model, const void * field_pointer, bool insertable, bool updatable, bool is_primary_key, ModelEnv * model_env) { - /* - model.doc_field_pointer = field_pointer; - model.model_data = model_data; + //model.doc_field_pointer = field_pointer; + model.model_env = model_env; model.map_doc_fields(); - model.model_data = nullptr; - model.doc_field_pointer = nullptr; - */ + model.model_env = nullptr; + //model.doc_field_pointer = nullptr; } void BaseExpression::before_field_name() diff --git a/src/baseexpression.h b/src/baseexpression.h index a80ce74..58edf80 100644 --- a/src/baseexpression.h +++ b/src/baseexpression.h @@ -75,12 +75,13 @@ public: virtual void allow_to_use_prefix(bool use_prefix); // give me a better name - virtual void put_field_doc(Model & model, const void * field_pointer, bool insertable, bool updatable, bool is_primary_key, ModelData * model_data); + virtual void put_field_doc(Model & model, const void * field_pointer, bool insertable, bool updatable, bool is_primary_key, ModelEnv * model_env); 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, ModelData * model_data = nullptr) + 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, ModelEnv * model_env = nullptr) { if( out_stream && can_field_be_generated(insertable, updatable, is_primary_key) ) { @@ -100,10 +101,10 @@ public: put_field_name(field_name, add_column_prefix); out_stream = old_out_stream; - if( model_data ) + if( model_env && model_env->finder_helper ) { - model_data->morm_foreign_keys.emplace_back(); - std::string & key_str = model_data->morm_foreign_keys.back(); + model_env->finder_helper->morm_foreign_keys.emplace_back(); + std::string & key_str = model_env->finder_helper->morm_foreign_keys.back(); str.to_string(key_str, false); } } @@ -131,7 +132,7 @@ public: void field_doc(Model & model, 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) + ModelEnv * model_env = nullptr) { if( out_stream ) { @@ -140,7 +141,7 @@ public: put_field_name(field_name, add_column_prefix); put_name_value_separator(); - put_field_doc(model, reinterpret_cast(&field_value), insertable, updatable, is_primary_key, model_data); + put_field_doc(model, reinterpret_cast(&field_value), insertable, updatable, is_primary_key, model_env); put_name_value_separator(); put_type(field_value, *out_stream); @@ -181,7 +182,7 @@ public: template void field_list(const wchar_t * field_name, ModelContainer & field_value, bool insertable, bool updatable, bool is_primary_key, - ModelConnector * model_connector, int model_connector_mode, ModelData * model_data) + ModelConnector * model_connector, ModelEnv * model_env) { if( out_stream && can_field_be_generated(insertable, updatable, is_primary_key) ) { @@ -196,7 +197,7 @@ public: { put_field_name(field_name); put_name_value_separator(); - put_field_value_list(field_value, model_connector, model_connector_mode, model_data); + put_field_value_list(field_value, model_connector, model_env); } field_after(); @@ -309,44 +310,50 @@ protected: } } + + virtual void before_field_value_list() + { + } + + + virtual void after_field_value_list() + { + } + + + virtual void field_value_list_separator() + { + (*out_stream) << ","; + } + + // what about lists with a pod types? e.g. list template - void put_field_value_list(ModelContainer & field_value, ModelConnector * model_connector, int model_connector_mode, ModelData * model_data) + void put_field_value_list(ModelContainer & field_value, ModelConnector * model_connector, ModelEnv * model_env) { - if( out_stream ) + if( model_connector && model_env && out_stream ) { - (*out_stream) << "[";// make a virtual method - } + bool is_first = true; + before_field_value_list(); - bool is_first = true; - - for(auto & m : field_value) - { - if( out_stream ) + for(auto & m : field_value) { if( !is_first ) { - if( out_stream ) - (*out_stream) << ","; // make a virtual method + field_value_list_separator(); } - ModelEnv model_env_local; + ModelEnv model_env_local(*model_env); m.model_env = &model_env_local; - //before_field_value(field_value); m.set_connector(model_connector); - m.model_env->model_connector_mode = model_connector_mode; - m.model_env->model_data = model_data; generate_from_model(m); m.model_env = nullptr; //after_field_value(field_value); is_first = false; } - } - if( out_stream ) - { - (*out_stream) << "]";// make a virtual method + after_field_value_list(); } } diff --git a/src/cursor.h b/src/cursor.h index 6b42474..17c1052 100644 --- a/src/cursor.h +++ b/src/cursor.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 @@ -51,7 +51,8 @@ public: Cursor() { - set_default_values(); + query_result = nullptr; + clear(); } @@ -59,6 +60,7 @@ public: { model_connector = c.model_connector; model_data = c.model_data; + has_autogenerated_select = c.has_autogenerated_select; query_result = c.query_result; select_status = c.select_status; @@ -66,6 +68,9 @@ public: { query_result->references_count += 1; } + + // helper doesn't have to be copied + cursor_helper.clear(); } @@ -91,7 +96,13 @@ public: delete query_result; } - set_default_values(); + model_connector = nullptr; + model_data = nullptr; + has_autogenerated_select = false; + cursor_helper.clear(); + query_result = nullptr; + select_status = false; + } @@ -119,6 +130,12 @@ public: } + virtual void set_has_autogenerated_select(bool has_autogenerated_select) + { + this->has_autogenerated_select = has_autogenerated_select; + } + + virtual QueryResult * get_query_result() { return query_result; @@ -144,7 +161,7 @@ public: result.set_connector(model_connector); result.clear(); - if( model_connector && query_result && query_result->has_db_result() && model_data ) + if( model_connector && query_result && query_result->has_db_result() ) { DbConnector * db_connector = model_connector->get_db_connector(); @@ -152,11 +169,13 @@ public: { ModelEnv model_env_local; result.model_env = &model_env_local; + result.model_env->cursor_helper = &cursor_helper; try { - model_data->current_column = 0; - model_data->query_result = query_result; + cursor_helper.clear(); + cursor_helper.query_result = query_result; + cursor_helper.has_autogenerated_select = has_autogenerated_select; result.model_env->model_data = model_data; result.before_select(); @@ -214,7 +233,7 @@ public: result.clear(); } - if( model_connector && query_result && query_result->has_db_result() && model_data ) + if( model_connector && query_result && query_result->has_db_result() ) { DbConnector * db_connector = model_connector->get_db_connector(); @@ -264,17 +283,12 @@ protected: ModelConnector * model_connector; ModelData * model_data; + bool has_autogenerated_select; + CursorHelper cursor_helper; QueryResult * query_result; bool select_status; - virtual void set_default_values() - { - model_connector = nullptr; - model_data = nullptr; - query_result = nullptr; - select_status = false; - } template @@ -289,11 +303,13 @@ protected: ModelEnv model_env_local; added_model.model_env = &model_env_local; + added_model.model_env->cursor_helper = &cursor_helper; try { - model_data->current_column = 0; - model_data->query_result = query_result; + cursor_helper.clear(); + cursor_helper.query_result = query_result; + cursor_helper.has_autogenerated_select = has_autogenerated_select; added_model.set_connector(model_connector); added_model.clear(); diff --git a/src/cursorhelper.h b/src/cursorhelper.h new file mode 100644 index 0000000..2b469f2 --- /dev/null +++ b/src/cursorhelper.h @@ -0,0 +1,76 @@ +/* + * This file is a part of morm + * and is distributed under the 2-Clause BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 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_cursorhelper +#define headerfile_morm_cursorhelper + +#include "queryresult.h" + + +namespace morm +{ + +class CursorHelper +{ +public: + + bool has_autogenerated_select; + QueryResult * query_result; + int current_column; + + + + CursorHelper() + { + clear(); + } + + + virtual ~CursorHelper() + { + } + + + virtual void clear() + { + has_autogenerated_select = false; + query_result = nullptr; + current_column = 0; + } + +}; + +} + +#endif diff --git a/src/finder.h b/src/finder.h index 6b767fb..7b7d76e 100644 --- a/src/finder.h +++ b/src/finder.h @@ -175,13 +175,7 @@ public: was_query_error = false; last_query_error.clear(); column_prefix.clear(); - - model.model_env = &model_env; - model.model_env->clear(); - - //model.model_data = nullptr; - // what about model_data in model here? - model.prepare_to_select(); + has_autogenerated_select = false; if( model_connector ) { @@ -189,7 +183,6 @@ public: { set_db_expression(); out_stream->clear(); - model.set_connector(model_connector); } else { @@ -203,11 +196,6 @@ public: last_query_error = L"model connector object is required"; } - if( !model_data ) - { - model_data = &model_data_generic; - } - return *this; } @@ -254,21 +242,17 @@ public: prepare_to_select(); } - if( !model.model_env ) - { - model.model_env = &model_env; - model.model_env->clear(); - } + model.set_connector(model_connector); - if( !model_data ) - { - model_data = &model_data_generic; - } + finder_helper.clear(); + model_env.clear(); + model.model_env = &model_env; model.model_env->model_data = model_data; + model.model_env->finder_helper = &finder_helper; + model.prepare_to_select(); - model_data->prepare_to_new_select(); - model_data->has_autogenerated_select = true; + has_autogenerated_select = true; if( model_connector && out_stream ) { @@ -280,7 +264,7 @@ public: model.table_name_for_join_as(prefix_stream); prefix_stream.to_string(column_prefix); - model_data->add_join_table(column_prefix); + finder_helper.add_join_table(column_prefix); } model.generate_select_columns(*out_stream, column_prefix); @@ -294,18 +278,14 @@ public: else { (*out_stream) << " AS "; - PT::TextStream str_tmp; // improve me + PT::TextStream str_tmp; 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); + finder_helper.add_join_table(str_tmp); } (*out_stream) << " "; - - (*out_stream) << model_data->morm_finder_join_tables; + (*out_stream) << finder_helper.morm_finder_join_tables; } return *this; @@ -551,6 +531,7 @@ public: { Cursor cursor; cursor.set_model_data(model_data); + cursor.set_has_autogenerated_select(has_autogenerated_select); if( model_connector && out_stream ) { @@ -613,13 +594,13 @@ 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; std::string column_prefix; ModelEnv model_env; - + FinderHelper finder_helper; + ModelData * model_data; + bool has_autogenerated_select; void set_db_expression() diff --git a/src/finderhelper.h b/src/finderhelper.h new file mode 100644 index 0000000..180eddb --- /dev/null +++ b/src/finderhelper.h @@ -0,0 +1,98 @@ +/* + * This file is a part of morm + * and is distributed under the 2-Clause BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 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_finderhelper +#define headerfile_morm_finderhelper + +#include "queryresult.h" + + +namespace morm +{ + + +class FinderHelper +{ +public: + + PT::TextStream morm_finder_join_tables; + std::map morm_table_join_map; + std::list morm_foreign_keys; + + + FinderHelper() + { + } + + + virtual ~FinderHelper() + { + } + + + virtual void clear() + { + morm_finder_join_tables.clear(); + morm_table_join_map.clear(); + morm_foreign_keys.clear(); + } + + + virtual int add_join_table(const PT::TextStream & table_name) + { + std::string table_name_str; + table_name.to_string(table_name_str); + + return add_join_table(table_name_str); + } + + + 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; + } + + +}; + +} + +#endif diff --git a/src/jsonexpression.cpp b/src/jsonexpression.cpp index 6987460..1212c3f 100644 --- a/src/jsonexpression.cpp +++ b/src/jsonexpression.cpp @@ -137,6 +137,18 @@ void JSONExpression::put_name_value_separator() } +void JSONExpression::before_field_value_list() +{ + (*out_stream) << "["; +} + + +void JSONExpression::after_field_value_list() +{ + (*out_stream) << "]"; +} + + void JSONExpression::esc(char val, PT::TextStream & stream) { switch( val ) diff --git a/src/jsonexpression.h b/src/jsonexpression.h index abbdb24..4a7e5e5 100644 --- a/src/jsonexpression.h +++ b/src/jsonexpression.h @@ -64,6 +64,9 @@ protected: void before_field_value(const PT::Date &); void after_field_value(const PT::Date &); + void before_field_value_list(); + void after_field_value_list(); + template void print_field_name_value(const wchar_t * field_name, const FieldValue & field_value) diff --git a/src/model.cpp b/src/model.cpp index 5e51fc0..a36452b 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -531,9 +531,12 @@ void Model::generate_doc_for_db(PT::TextStream & stream, bool clear_stream) void Model::map_values_from_query() { - model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_READING_VALUE_FROM_DB_RESULTSET; - map_fields(); - model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; + if( model_env ) + { + model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_READING_VALUE_FROM_DB_RESULTSET; + map_fields(); + model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; + } } diff --git a/src/model.h b/src/model.h index 3cdce56..5be9e6d 100644 --- a/src/model.h +++ b/src/model.h @@ -166,7 +166,7 @@ protected: virtual ModelData * get_model_data(); - // used by Cursor + virtual void map_values_from_query(); @@ -636,7 +636,7 @@ 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 ) + if( model_connector && model_env ) { if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_GENERATING_FLAT_STRING ) { @@ -649,7 +649,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, true, model_env->model_data); + flat_expression->field(flat_field_name, field_value, insertable, updatable, is_primary_key, true, model_env); } } } @@ -664,12 +664,7 @@ protected: 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->model_data); - - if( model_env->model_data ) - { - model_env->model_data->current_column += 1; - } + db_expression->field(db_field_name, field_value, insertable, updatable, is_primary_key, true, model_env); } } } @@ -682,10 +677,10 @@ protected: { if( !is_empty_field(db_field_name) ) { - if( model_env->model_data && model_env->model_data->has_autogenerated_select ) + if( model_env->model_data && model_env->cursor_helper && model_env->cursor_helper->has_autogenerated_select ) { - get_value_by_field_index(model_env->model_data->current_column, field_value); - model_env->model_data->current_column += 1; + get_value_by_field_index(model_env->cursor_helper->current_column, field_value); + model_env->cursor_helper->current_column += 1; } else { @@ -727,14 +722,14 @@ protected: 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->model_data ) + if( model_env->finder_helper ) { - model_env->model_data->morm_current_max_column += 1; - model_env->model_data->morm_foreign_keys.clear(); + //model_env->select_helper->morm_current_max_column += 1; + model_env->finder_helper->morm_foreign_keys.clear(); - model_env->model_data->morm_finder_join_tables << "LEFT JOIN "; - field_model.table_name(model_env->model_data->morm_finder_join_tables); - model_env->model_data->morm_finder_join_tables << " AS "; + 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 "; ////////////// @@ -749,14 +744,14 @@ protected: PT::TextStream join_table_name; field_model.table_name_for_join_as(join_table_name); - field_model.model_env->table_index = model_env->model_data->add_join_table(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->model_data->morm_finder_join_tables << join_table_name; + 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(); @@ -770,29 +765,29 @@ protected: { field_model.map_fields(); - model_env->model_data->morm_finder_join_tables << " ON " << join_table_name_this << '.' << db_field_name; // escape? - model_env->model_data->morm_finder_join_tables << " = " << join_table_name << '.'; + 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->model_data->morm_foreign_keys.empty() ) + if( !model_env->finder_helper->morm_foreign_keys.empty() ) { - model_env->model_data->morm_finder_join_tables << model_env->model_data->morm_foreign_keys.front(); + model_env->finder_helper->morm_finder_join_tables << model_env->finder_helper->morm_foreign_keys.front(); } } else { map_fields(); - model_env->model_data->morm_finder_join_tables << " ON " << join_table_name_this << '.'; + model_env->finder_helper->morm_finder_join_tables << " ON " << join_table_name_this << '.'; - if( !model_env->model_data->morm_foreign_keys.empty() ) + if( !model_env->finder_helper->morm_foreign_keys.empty() ) { - model_env->model_data->morm_finder_join_tables << model_env->model_data->morm_foreign_keys.front(); + model_env->finder_helper->morm_finder_join_tables << model_env->finder_helper->morm_foreign_keys.front(); } - model_env->model_data->morm_finder_join_tables << " = " << (join_table_name) << '.' << db_field_name; + model_env->finder_helper->morm_finder_join_tables << " = " << (join_table_name) << '.' << db_field_name; } - model_env->model_data->morm_finder_join_tables << ' '; + model_env->finder_helper->morm_finder_join_tables << ' '; db_expression->set_work_mode(expr_work_mode); db_expression->set_output_type(expr_output_type); @@ -860,11 +855,6 @@ protected: } field_model.model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; - - if( model_env->model_data ) - { - model_env->model_data->current_column += 1; - } } } } @@ -920,7 +910,7 @@ protected: 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 ) + if( model_connector && model_env ) { ModelEnv model_env_local(*model_env); field_model.model_env = &model_env_local; @@ -959,7 +949,7 @@ protected: 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 ) + if( model_connector && model_env ) { if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_GENERATING_FLAT_STRING ) { @@ -974,7 +964,7 @@ 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, false, model_connector, model_env->model_connector_mode, model_env->model_data); + flat_expression->field_list(flat_field_name, field_container, insertable, updatable, false, model_connector, model_env); } } } @@ -1030,9 +1020,9 @@ protected: template void get_value_by_field_index(int field_index, FieldValue & field_value) { - if( model_env->model_data && model_env->model_data->query_result ) + if( model_env->cursor_helper && model_env->cursor_helper->query_result ) { - const char * val_str = model_env->model_data->query_result->get_field_string_value(field_index); + const char * val_str = model_env->cursor_helper->query_result->get_field_string_value(field_index); if( val_str ) { @@ -1050,9 +1040,9 @@ protected: template void get_value_by_field_name(const wchar_t * field_name, FieldValue & field_value) { - if( model_env->model_data && model_env->model_data->query_result ) + if( model_env->cursor_helper && model_env->cursor_helper->query_result ) { - const char * val_str = model_env->model_data->query_result->get_field_string_value(field_name); + const char * val_str = model_env->cursor_helper->query_result->get_field_string_value(field_name); if( val_str ) { diff --git a/src/modeldata.h b/src/modeldata.h index 8781181..472bf69 100644 --- a/src/modeldata.h +++ b/src/modeldata.h @@ -35,7 +35,6 @@ #ifndef headerfile_morm_modeldata #define headerfile_morm_modeldata -#include "queryresult.h" namespace morm @@ -47,98 +46,12 @@ public: ModelData() { - morm_current_max_column = 1; - current_column = 1; - query_result = nullptr; } virtual ~ModelData() { } - bool has_autogenerated_select; - - QueryResult * query_result; -// int table_index; - - - // can be moved to another struct? - // let ModelData be only for user stuff - PT::TextStream morm_finder_join_tables; - std::list morm_foreign_keys; - int morm_current_max_column; - std::map morm_table_join_map; - - int current_column; - //std::vector table_index; - - - - virtual void prepare_to_new_select() - { - has_autogenerated_select = false; - query_result = nullptr; - -// table_index = 1; - - 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 PT::TextStream & table_name) - { - std::string table_name_str; - table_name.to_string(table_name_str); - - return add_join_table(table_name_str); - } - - 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; -// } - -// virtual int get_table_index(int column) -// { -// if( column < (int)table_index.size() ) -// return table_index[column]; -// -// return 0; -// } - - - /* - * may to add: - * std::set skip_columns; - * and Finder can use this - * also update and insert from Model - * (but what about the same name of columns through the whole objects-tree? - * may we can save the name of the table too?) - * - * - */ }; } diff --git a/src/modelenv.h b/src/modelenv.h index 5c34e14..6042d80 100644 --- a/src/modelenv.h +++ b/src/modelenv.h @@ -36,18 +36,22 @@ #define headerfile_morm_modelenv #include "modeldata.h" +#include "cursorhelper.h" +#include "finderhelper.h" #include "morm_types.h" namespace morm { -// rename me? class ModelEnv { public: ModelData * model_data; + FinderHelper * finder_helper; + CursorHelper * cursor_helper; + int model_connector_mode; int table_index; const void * doc_field_pointer; @@ -67,6 +71,8 @@ public: ModelEnv(const ModelEnv & e) { model_data = e.model_data; + finder_helper = e.finder_helper; + cursor_helper = e.cursor_helper; model_connector_mode = e.model_connector_mode; table_index = e.table_index; doc_field_pointer = e.doc_field_pointer; @@ -76,6 +82,8 @@ public: void clear() { model_data = nullptr; + finder_helper = nullptr; + cursor_helper = nullptr; model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; table_index = 0; doc_field_pointer = nullptr; From a1d18735b0334ff3ee1c552b7c024836d0a74aa4 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Tue, 21 May 2019 17:24:12 +0000 Subject: [PATCH 08/10] - removed prefix() method from Finder (this was for a custom prefix) - removed column_prefix and column_prefix_index from BaseExpression now we have a pointer to ModelEnv passed in field() method - to ModelEnv: added table_name, table_name_simple and table_index git-svn-id: svn://ttmath.org/publicrep/morm/branches/join_models@1193 e52654a7-88a9-db11-a3e9-0013d4bc506e --- src/baseexpression.cpp | 44 +++++++++++-------------- src/baseexpression.h | 32 +++++++----------- src/dbconnector.cpp | 3 +- src/dbconnector.h | 2 +- src/finder.h | 62 ++++++++++++----------------------- src/finderhelper.h | 1 + src/model.cpp | 4 +-- src/model.h | 73 ++++++++++++------------------------------ src/modelenv.h | 21 ++++++++++-- 9 files changed, 94 insertions(+), 148 deletions(-) diff --git a/src/baseexpression.cpp b/src/baseexpression.cpp index 6f826ae..e7d1cc3 100644 --- a/src/baseexpression.cpp +++ b/src/baseexpression.cpp @@ -68,8 +68,6 @@ int BaseExpression::get_work_mode() void BaseExpression::prepare_to_new_expression() { - column_prefix.clear(); - column_prefix_index = 1; out_stream = nullptr; is_first_field = false; work_mode = 0; @@ -89,25 +87,9 @@ void BaseExpression::allow_to_use_prefix(bool use_prefix) } -void BaseExpression::set_column_prefix(const std::string & prefix) +bool BaseExpression::get_allow_to_use_prefix() { - column_prefix = prefix; -} - -void BaseExpression::set_column_prefix(const std::string & prefix, int index) -{ - column_prefix = prefix; - column_prefix_index = index; -} - -std::string BaseExpression::get_column_prefix() -{ - return column_prefix; -} - -int BaseExpression::get_column_prefix_index() -{ - return column_prefix_index; + return use_prefix; } @@ -177,16 +159,18 @@ void BaseExpression::field_after() -void BaseExpression::put_field_name(const wchar_t * field_name, bool add_column_prefix) +void BaseExpression::put_field_name(const wchar_t * field_name, bool add_column_prefix, ModelEnv * model_env) { before_field_name(); - if( use_prefix && add_column_prefix && !column_prefix.empty() ) + if( use_prefix && model_env && add_column_prefix ) { - esc(column_prefix, *out_stream); + esc(model_env->table_name_simple, *out_stream); - if( column_prefix_index > 1 ) - (*out_stream) << column_prefix_index; + if( model_env->table_index > 1 ) + { + (*out_stream) << model_env->table_index; + } (*out_stream) << '.'; } @@ -415,6 +399,16 @@ void BaseExpression::esc(const PT::Date & date, PT::TextStream & stream) stream << date; } +void BaseExpression::esc(const PT::TextStream & val, PT::TextStream & stream) +{ + PT::TextStream::const_iterator i = val.begin(); + + for(; i != val.end() ; ++i) + { + esc(*i, stream); + } +} + void BaseExpression::put_type(char val, PT::TextStream & stream) { diff --git a/src/baseexpression.h b/src/baseexpression.h index 58edf80..fd2f56c 100644 --- a/src/baseexpression.h +++ b/src/baseexpression.h @@ -61,11 +61,6 @@ public: virtual int get_work_mode(); virtual void prepare_to_new_expression(); - virtual void set_column_prefix(const std::string & prefix); - virtual void set_column_prefix(const std::string & prefix, int index); - - virtual std::string get_column_prefix(); - virtual int get_column_prefix_index(); virtual void generate_from_model(PT::TextStream & stream, Model & model); @@ -73,6 +68,7 @@ public: // rename me virtual void allow_to_use_prefix(bool use_prefix); + virtual bool get_allow_to_use_prefix(); // give me a better name virtual void put_field_doc(Model & model, const void * field_pointer, bool insertable, bool updatable, bool is_primary_key, ModelEnv * model_env); @@ -89,7 +85,7 @@ public: if( work_mode == MORM_WORK_MODE_MODEL_FIELDS ) { - put_field_name(field_name, add_column_prefix); + put_field_name(field_name, add_column_prefix, model_env); } else if( work_mode == MORM_WORK_MODE_MODEL_SAVE_FIELDS ) @@ -98,7 +94,7 @@ public: PT::TextStream * old_out_stream = out_stream; out_stream = &str; - put_field_name(field_name, add_column_prefix); + put_field_name(field_name, add_column_prefix, model_env); out_stream = old_out_stream; if( model_env && model_env->finder_helper ) @@ -116,7 +112,7 @@ public: else if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES ) { - put_field_name(field_name); + put_field_name(field_name, add_column_prefix, model_env); put_name_value_separator(); put_field_value(field_value); } @@ -138,7 +134,7 @@ public: { field_before(); - put_field_name(field_name, add_column_prefix); + put_field_name(field_name, add_column_prefix, model_env); put_name_value_separator(); put_field_doc(model, reinterpret_cast(&field_value), insertable, updatable, is_primary_key, model_env); @@ -195,7 +191,7 @@ public: // else if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES ) { - put_field_name(field_name); + put_field_name(field_name); // what about model_env? put it here? put_name_value_separator(); put_field_value_list(field_value, model_connector, model_env); } @@ -233,10 +229,11 @@ public: } template - 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) + 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, + bool add_column_prefix = true, ModelEnv * model_env = nullptr) { this->out_stream = &stream; - field(field_name, field_value, insertable, updatable, is_primary_key); + field(field_name, field_value, insertable, updatable, is_primary_key, add_column_prefix, model_env); this->out_stream = nullptr; } @@ -266,6 +263,7 @@ public: //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); @@ -275,16 +273,8 @@ protected: int work_mode; /* what to do: generating fields list, values list or fields-values list */ bool is_first_field; - // niech Stream bedzie jakims interfejsem z operatorami << dla standardowych typow - // albo w pikotoolsach dodać klase bazowa (intefejs) dla streamow - // i dodatkowo dodac loger ktory dziedziczy po niej i dodaje loglevel i endline - // jako metode bazowa dodac format("string", parametry,...) - // przyda sie do formatowania doubli PT::TextStream * out_stream; - - std::string column_prefix; - int column_prefix_index; bool use_prefix; virtual void generate_from_model(Model & model); @@ -297,7 +287,7 @@ protected: //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, bool add_column_prefix = true); + virtual void put_field_name(const wchar_t * field_name, bool add_column_prefix = true, ModelEnv * model_env = nullptr); template void put_field_value(const FieldValue & field_value) diff --git a/src/dbconnector.cpp b/src/dbconnector.cpp index 35ba785..d74d1d2 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::string & column_prefix) +void DbConnector::generate_select_columns(PT::TextStream & stream, Model & model) { allocate_default_expression_if_needed(); @@ -160,7 +160,6 @@ void DbConnector::generate_select_columns(PT::TextStream & stream, Model & model db_expression->prepare_to_new_expression(); db_expression->set_work_mode(MORM_WORK_MODE_MODEL_FIELDS); db_expression->set_output_type(MORM_OUTPUT_TYPE_SELECT_COLUMNS); - db_expression->set_column_prefix(column_prefix); db_expression->generate_from_model(stream, model); } } diff --git a/src/dbconnector.h b/src/dbconnector.h index 6d37ad6..e2f58e1 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::string & column_prefix); + virtual void generate_select_columns(PT::TextStream & stream, Model & model); 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 7b7d76e..cf645f5 100644 --- a/src/finder.h +++ b/src/finder.h @@ -157,24 +157,17 @@ public: return was_query_error; } + std::wstring get_error_msg() { return last_query_error; } - Finder & prefix(const wchar_t * prefix) - { - PT::WideToUTF8(prefix, column_prefix); - return *this; - } - - Finder & prepare_to_select() { was_query_error = false; last_query_error.clear(); - column_prefix.clear(); has_autogenerated_select = false; if( model_connector ) @@ -256,34 +249,14 @@ public: if( model_connector && out_stream ) { + model.table_name(model.model_env->table_name); + model.table_name_for_join_as(model.model_env->table_name_simple); + model.model_env->table_index = finder_helper.add_join_table(model.model_env->table_name_simple); + (*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); - finder_helper.add_join_table(column_prefix); - } - - model.generate_select_columns(*out_stream, column_prefix); - (*out_stream) << " FROM "; - model.table_name(*out_stream); - - if( !column_prefix.empty() ) - { - (*out_stream) << " AS " << column_prefix; // what about escaping? - } - else - { - (*out_stream) << " AS "; - PT::TextStream str_tmp; - model.table_name_for_join_as(str_tmp); - (*out_stream) << str_tmp; - finder_helper.add_join_table(str_tmp); - } - + model.generate_select_columns(*out_stream); + (*out_stream) << " FROM " << model.model_env->table_name << " AS "; + (*out_stream) << model.model_env->table_name_simple; (*out_stream) << " "; (*out_stream) << finder_helper.morm_finder_join_tables; } @@ -369,7 +342,14 @@ public: if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_EQ); - db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false); + + bool put_table_prefix = true; + + // IMPROVE ME + // add check if there is a dot char in field_name? + // or add a second eq() method with an additional parameter -- table name? + + db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false, put_table_prefix, &model_env); } return *this; @@ -382,7 +362,7 @@ public: if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_LT); - db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false); + db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false, true, &model_env); } return *this; @@ -395,7 +375,7 @@ public: if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_GT); - db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false); + db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false, true, &model_env); } return *this; @@ -408,7 +388,7 @@ public: if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_LE); - db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false); + db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false, true, &model_env); } return *this; @@ -421,7 +401,7 @@ public: if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_GE); - db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false); + db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false, true, &model_env); } return *this; @@ -596,7 +576,6 @@ private: ModelClass model; bool was_query_error; std::wstring last_query_error; - std::string column_prefix; ModelEnv model_env; FinderHelper finder_helper; ModelData * model_data; @@ -613,7 +592,6 @@ private: { db_expression = db_connector->get_expression(); db_expression->allow_to_use_prefix(true); - // set prefix maybe there to an empty string? } } } diff --git a/src/finderhelper.h b/src/finderhelper.h index 180eddb..ba1e3a8 100644 --- a/src/finderhelper.h +++ b/src/finderhelper.h @@ -51,6 +51,7 @@ public: std::list morm_foreign_keys; + FinderHelper() { } diff --git a/src/model.cpp b/src/model.cpp index a36452b..8770457 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -467,7 +467,7 @@ bool Model::save(ModelData & model_data) } -void Model::generate_select_columns(PT::TextStream & stream, const std::string & column_prefix) +void Model::generate_select_columns(PT::TextStream & stream) { if( model_connector && model_env ) { @@ -476,7 +476,7 @@ void Model::generate_select_columns(PT::TextStream & stream, const std::string & if( db_connector ) { - db_connector->generate_select_columns(stream, *this, column_prefix); + db_connector->generate_select_columns(stream, *this); } } } diff --git a/src/model.h b/src/model.h index 5be9e6d..7eec1cd 100644 --- a/src/model.h +++ b/src/model.h @@ -123,7 +123,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::string & column_prefix); + virtual void generate_select_columns(PT::TextStream & stream); 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); @@ -722,53 +722,33 @@ protected: 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 ) + if( model_env && field_model.model_env && model_env->finder_helper ) { - //model_env->select_helper->morm_current_max_column += 1; model_env->finder_helper->morm_foreign_keys.clear(); + field_model.model_env->table_index = model_env->finder_helper->add_join_table(field_model.model_env->table_name_simple); - 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); + model_env->finder_helper->morm_finder_join_tables << "LEFT JOIN " << field_model.model_env->table_name + << " AS " << field_model.model_env->table_name_simple; 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; + model_env->finder_helper->morm_finder_join_tables << field_model.model_env->table_index; int expr_work_mode = db_expression->get_work_mode(); int expr_output_type = db_expression->get_output_type(); + bool expr_allow_prefix = db_expression->get_allow_to_use_prefix(); 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 << '.'; + model_env->finder_helper->morm_finder_join_tables << " ON " << model_env->table_name_simple << '.' + << db_field_name << " = " << field_model.model_env->table_name_simple << '.'; - if( !model_env->finder_helper->morm_foreign_keys.empty() ) + if( model_env->finder_helper->morm_foreign_keys.size() == 1 ) { model_env->finder_helper->morm_finder_join_tables << model_env->finder_helper->morm_foreign_keys.front(); } @@ -777,23 +757,21 @@ protected: { map_fields(); - model_env->finder_helper->morm_finder_join_tables << " ON " << join_table_name_this << '.'; + model_env->finder_helper->morm_finder_join_tables << " ON " << model_env->table_name_simple << '.'; - if( !model_env->finder_helper->morm_foreign_keys.empty() ) + if( model_env->finder_helper->morm_foreign_keys.size() == 1 ) { 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 << " = " << field_model.model_env->table_name_simple << '.' << 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); - + db_expression->allow_to_use_prefix(expr_allow_prefix); } } @@ -828,6 +806,9 @@ protected: { field_model.model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL; + field_model.table_name(field_model.model_env->table_name); + field_model.table_name_for_join_as(field_model.model_env->table_name_simple); + 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); @@ -835,23 +816,7 @@ protected: 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; @@ -912,7 +877,9 @@ protected: { if( model_connector && model_env ) { - ModelEnv model_env_local(*model_env); + ModelEnv model_env_local; + model_env_local.copy_global_objects(*model_env); + field_model.model_env = &model_env_local; field_model.set_connector(model_connector); diff --git a/src/modelenv.h b/src/modelenv.h index 6042d80..f6eb01d 100644 --- a/src/modelenv.h +++ b/src/modelenv.h @@ -53,9 +53,13 @@ public: CursorHelper * cursor_helper; int model_connector_mode; - int table_index; const void * doc_field_pointer; + PT::TextStream table_name; + PT::TextStream table_name_simple; + int table_index; + + ModelEnv() { @@ -79,14 +83,27 @@ public: } + void copy_global_objects(const ModelEnv & e) + { + model_data = e.model_data; + finder_helper = e.finder_helper; + cursor_helper = e.cursor_helper; + + model_connector_mode = e.model_connector_mode; + + // what about doc_field_pointer? + } + void clear() { model_data = nullptr; finder_helper = nullptr; cursor_helper = nullptr; model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; - table_index = 0; doc_field_pointer = nullptr; + table_name.clear(); + table_name_simple.clear(); + table_index = 0; } From b6fbe29805f9cd73ba369c51c3b7e4c82ee48ba6 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Fri, 31 May 2019 18:28:09 +0000 Subject: [PATCH 09/10] added BaseExpression::is_long_field_name() added BaseExpression::need_to_add_field_prefix() now the fields() methods don't take add_column_prefix parameter but the field_name (wchar_t*) is tested whether is it a long (with a period) or short name added BaseExpression::save_foreign_key() (code moved from field()) removed some default method arguments from BaseExpression added neq() method for Finder added DbExpression::prepare_short_table_name(const PT::TextStream & table_name, PT::TextStream & short_table_name) git-svn-id: svn://ttmath.org/publicrep/morm/branches/join_models@1194 e52654a7-88a9-db11-a3e9-0013d4bc506e --- src/baseexpression.cpp | 112 ++++++++++++++++++++++++++++++++++------- src/baseexpression.h | 109 +++++++++++++++++++-------------------- src/dbconnector.cpp | 15 ++++-- src/dbexpression.cpp | 41 +++++++++++++++ src/dbexpression.h | 7 ++- src/finder.h | 83 ++++++++++++++++-------------- src/finderhelper.h | 16 +++--- src/flatconnector.cpp | 2 + src/jsonexpression.h | 10 ---- src/model.cpp | 42 +--------------- src/model.h | 49 +++++++++--------- src/modelenv.h | 4 +- src/morm_types.h | 1 + 13 files changed, 286 insertions(+), 205 deletions(-) diff --git a/src/baseexpression.cpp b/src/baseexpression.cpp index e7d1cc3..a108b6b 100644 --- a/src/baseexpression.cpp +++ b/src/baseexpression.cpp @@ -44,9 +44,7 @@ namespace morm BaseExpression::BaseExpression() { - out_stream = nullptr; - is_first_field = false; - work_mode = 0; + clear(); } BaseExpression::~BaseExpression() @@ -54,6 +52,15 @@ BaseExpression::~BaseExpression() } +void BaseExpression::clear() +{ + out_stream = nullptr; + is_first_field = false; + work_mode = 0; + use_prefix = false; +} + + void BaseExpression::set_work_mode(int work_mode) { this->work_mode = work_mode; @@ -66,14 +73,6 @@ int BaseExpression::get_work_mode() } -void BaseExpression::prepare_to_new_expression() -{ - out_stream = nullptr; - is_first_field = false; - work_mode = 0; - use_prefix = true; -} - PT::TextStream * BaseExpression::get_current_stream() { @@ -158,21 +157,80 @@ void BaseExpression::field_after() } +bool BaseExpression::is_long_field_name(const wchar_t * field_name) +{ + bool is_long = false; -void BaseExpression::put_field_name(const wchar_t * field_name, bool add_column_prefix, ModelEnv * model_env) + while( *field_name != 0 ) + { + if( *field_name == '.' ) + { + is_long = true; + break; + } + + field_name += 1; + } + + return is_long; +} + + +bool BaseExpression::is_long_field_name(const PT::TextStream & field_name) +{ + PT::TextStream::const_iterator i = field_name.begin(); + bool is_long = false; + + while( i != field_name.end() ) + { + if( *i == '.' ) + { + is_long = true; + break; + } + + ++i; + } + + return is_long; +} + + +bool BaseExpression::is_long_table_name(const wchar_t * table_name) +{ + return is_long_field_name(table_name); +} + +bool BaseExpression::is_long_table_name(const PT::TextStream & table_name) +{ + return is_long_field_name(table_name); +} + + +bool BaseExpression::need_to_add_field_prefix(const wchar_t * field_name) +{ + return !is_long_field_name(field_name); +} + + + +void BaseExpression::put_field_name(const wchar_t * field_name, ModelEnv * model_env) { before_field_name(); - if( use_prefix && model_env && add_column_prefix ) + if( use_prefix && model_env ) { - esc(model_env->table_name_simple, *out_stream); - - if( model_env->table_index > 1 ) + if( need_to_add_field_prefix(field_name) ) { - (*out_stream) << model_env->table_index; - } + esc(model_env->table_name_short, *out_stream); - (*out_stream) << '.'; + if( model_env->table_index > 1 ) + { + (*out_stream) << model_env->table_index; + } + + (*out_stream) << '.'; + } } esc(field_name, *out_stream); @@ -180,6 +238,22 @@ void BaseExpression::put_field_name(const wchar_t * field_name, bool add_column_ } +void BaseExpression::save_foreign_key(const wchar_t * field_name, ModelEnv * model_env) +{ + PT::TextStream str; + PT::TextStream * old_out_stream = out_stream; + + out_stream = &str; + put_field_name(field_name, model_env); + out_stream = old_out_stream; + + if( model_env && model_env->finder_helper ) + { + model_env->finder_helper->foreign_keys.emplace_back(); + std::string & key_str = model_env->finder_helper->foreign_keys.back(); + str.to_string(key_str, false); + } +} void BaseExpression::put_field_doc(Model & model, const void * field_pointer, bool insertable, bool updatable, bool is_primary_key, ModelEnv * model_env) { diff --git a/src/baseexpression.h b/src/baseexpression.h index fd2f56c..351b8b9 100644 --- a/src/baseexpression.h +++ b/src/baseexpression.h @@ -60,7 +60,7 @@ public: virtual void set_work_mode(int work_mode); virtual int get_work_mode(); - virtual void prepare_to_new_expression(); + virtual void clear(); virtual void generate_from_model(PT::TextStream & stream, Model & model); @@ -76,8 +76,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, ModelEnv * model_env = nullptr) + 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) ) { @@ -85,24 +84,12 @@ public: if( work_mode == MORM_WORK_MODE_MODEL_FIELDS ) { - put_field_name(field_name, add_column_prefix, model_env); + put_field_name(field_name, model_env); } 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(field_name, add_column_prefix, model_env); - out_stream = old_out_stream; - - if( model_env && model_env->finder_helper ) - { - model_env->finder_helper->morm_foreign_keys.emplace_back(); - std::string & key_str = model_env->finder_helper->morm_foreign_keys.back(); - str.to_string(key_str, false); - } + save_foreign_key(field_name, model_env); } else if( work_mode == MORM_WORK_MODE_MODEL_VALUES ) @@ -112,7 +99,7 @@ public: else if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES ) { - put_field_name(field_name, add_column_prefix, model_env); + put_field_name(field_name, model_env); put_name_value_separator(); put_field_value(field_value); } @@ -125,16 +112,13 @@ public: template - void field_doc(Model & model, 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, - ModelEnv * model_env = nullptr) + void field_doc(Model & model, const wchar_t * field_name, const FieldValue & field_value, bool insertable, bool updatable, bool is_primary_key, ModelEnv * model_env) { if( out_stream ) { field_before(); - put_field_name(field_name, add_column_prefix, model_env); + put_field_name(field_name, model_env); put_name_value_separator(); put_field_doc(model, reinterpret_cast(&field_value), insertable, updatable, is_primary_key, model_env); @@ -147,38 +131,30 @@ public: } - /* template - void field(const PT::TextStream & field_name, const FieldValue & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false, bool add_column_prefix = true) + void field_in(PT::TextStream & stream, const wchar_t * field_name, const std::set & container, ModelEnv * model_env) { - std::wstring field_name_str; // field() methods can be called recursively, so don't make it as class object - field_name.to_string(field_name_str); - - return field(field_name_str.c_str(), field_value, insertable, updatable, is_primary_key, add_column_prefix); - } - */ - - template - void field_in(PT::TextStream & stream, const wchar_t * field_name, const std::set & container) - { - field_in_generic>(stream, field_name, container); + 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) - { - field_in_generic>(stream, field_name, container); - } template - void field_in(PT::TextStream & stream, const wchar_t * field_name, const std::vector & container) + 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); + 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) + ModelConnector * model_connector, ModelEnv * model_env) { if( out_stream && can_field_be_generated(insertable, updatable, is_primary_key) ) { @@ -191,7 +167,7 @@ public: // else if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES ) { - put_field_name(field_name); // what about model_env? put it here? + put_field_name(field_name, model_env); put_name_value_separator(); put_field_value_list(field_value, model_connector, model_env); } @@ -201,7 +177,7 @@ public: } template - void field_model(const wchar_t * field_name, ModelClass & field_model, bool insertable = true, bool updatable = true, bool is_primary_key = false) + 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) ) { @@ -209,7 +185,7 @@ public: if( work_mode == MORM_WORK_MODE_MODEL_FIELDS ) { - put_field_name(field_name); + put_field_name(field_name, model_env); } else if( work_mode == MORM_WORK_MODE_MODEL_VALUES ) @@ -219,7 +195,7 @@ public: else if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES ) { - put_field_name(field_name); + put_field_name(field_name, model_env); put_name_value_separator(); generate_from_model(field_model); } @@ -229,11 +205,11 @@ public: } template - 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, - bool add_column_prefix = true, ModelEnv * model_env = nullptr) + 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, add_column_prefix, model_env); + field(field_name, field_value, insertable, updatable, is_primary_key, model_env); this->out_stream = nullptr; } @@ -265,6 +241,11 @@ public: 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); @@ -287,7 +268,12 @@ protected: //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, bool add_column_prefix = true, ModelEnv * model_env = nullptr); + virtual bool need_to_add_field_prefix(const wchar_t * field_name); + + 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); + template void put_field_value(const FieldValue & field_value) @@ -316,6 +302,15 @@ protected: (*out_stream) << ","; } + virtual void put_statement_in_starts() + { + (*out_stream) << "("; + } + + virtual void put_statement_in_ends() + { + (*out_stream) << ") "; + } // what about lists with a pod types? e.g. list template @@ -350,7 +345,7 @@ protected: // used in 'in()' statements, may should be renamed? template - void field_in_generic(PT::TextStream & stream, const wchar_t * field_name, const Container & container) + 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? @@ -358,24 +353,24 @@ protected: this->out_stream = &stream; field_before(); - put_field_name(field_name); + put_field_name(field_name, model_env); put_name_value_separator(); bool is_first = true; - (*out_stream) << "("; + put_statement_in_starts(); for(const FieldValue & v : container) { if( !is_first ) { - (*out_stream) << ","; + field_value_list_separator(); } put_field_value(v); is_first = false; } - (*out_stream) << ") "; + put_statement_in_ends(); field_after(); this->out_stream = nullptr; } diff --git a/src/dbconnector.cpp b/src/dbconnector.cpp index d74d1d2..9654b8a 100644 --- a/src/dbconnector.cpp +++ b/src/dbconnector.cpp @@ -157,9 +157,10 @@ void DbConnector::generate_select_columns(PT::TextStream & stream, Model & model if( db_expression ) { - db_expression->prepare_to_new_expression(); + db_expression->clear(); db_expression->set_work_mode(MORM_WORK_MODE_MODEL_FIELDS); db_expression->set_output_type(MORM_OUTPUT_TYPE_SELECT_COLUMNS); + db_expression->allow_to_use_prefix(true); db_expression->generate_from_model(stream, model); } } @@ -171,7 +172,9 @@ void DbConnector::generate_insert_query(PT::TextStream & stream, Model & model) if( db_expression ) { - db_expression->prepare_to_new_expression(); + db_expression->clear(); + db_expression->allow_to_use_prefix(true); + stream << "insert into "; model.table_name(stream); @@ -194,7 +197,9 @@ void DbConnector::generate_update_query(PT::TextStream & stream, Model & model) if( db_expression ) { - db_expression->prepare_to_new_expression(); + db_expression->clear(); + db_expression->allow_to_use_prefix(true); + stream << "update "; model.table_name(stream); @@ -217,7 +222,9 @@ void DbConnector::generate_remove_query(PT::TextStream & stream, Model & model) if( db_expression ) { - db_expression->prepare_to_new_expression(); + db_expression->clear(); + db_expression->allow_to_use_prefix(true); + stream << "delete from "; model.table_name(stream); stream << " where "; diff --git a/src/dbexpression.cpp b/src/dbexpression.cpp index 43f098b..f65e48e 100644 --- a/src/dbexpression.cpp +++ b/src/dbexpression.cpp @@ -140,6 +140,11 @@ void DbExpression::put_name_value_separator() (*out_stream) << " = "; } else + if( output_type == MORM_OUTPUT_TYPE_WHERE_NOT_EQ ) + { + (*out_stream) << " <> "; + } + else if( output_type == MORM_OUTPUT_TYPE_WHERE_LT ) { (*out_stream) << " < "; @@ -296,4 +301,40 @@ DbExpression & DbExpression::page(PT::TextStream & stream, size_t page_number, s return *this; } + + + + +void DbExpression::prepare_short_table_name(const PT::TextStream & table_name, PT::TextStream & short_table_name) +{ + short_table_name.clear(); + + if( is_long_table_name(table_name) ) + { + PT::TextStream::const_iterator i = table_name.begin(); + bool was_dot = false; + + while( i != table_name.end() ) + { + if( was_dot ) + { + short_table_name << *i; + } + else + if( *i == '.' ) + { + was_dot = true; + } + + ++i; + } + } + + if( short_table_name.empty() ) + { + short_table_name = table_name; + } +} + + } diff --git a/src/dbexpression.h b/src/dbexpression.h index b679c36..53d2dba 100644 --- a/src/dbexpression.h +++ b/src/dbexpression.h @@ -71,10 +71,15 @@ public: column_expression += L" as "; column_expression += new_column_name; - field(column_expression.c_str(), field_value, false, false, false, false); + // put nullptr to ModelEnv* to not allow to use prefix + // or may better remember current value of use_prefix and set it to false for a while? + field(column_expression.c_str(), field_value, false, false, false, nullptr); } + virtual void prepare_short_table_name(const PT::TextStream & table_name, PT::TextStream & short_table_name); + + protected: int output_type; diff --git a/src/finder.h b/src/finder.h index cf645f5..86faf13 100644 --- a/src/finder.h +++ b/src/finder.h @@ -116,23 +116,6 @@ public: -protected: - - void set_out_stream() - { - if( model_connector ) - { - this->out_stream = model_connector->get_stream(); - } - else - { - this->out_stream = nullptr; - } - } - - -public: - Finder & set_out_stream(PT::TextStream * out_stream) { this->out_stream = out_stream; @@ -243,22 +226,22 @@ public: model.model_env = &model_env; model.model_env->model_data = model_data; model.model_env->finder_helper = &finder_helper; - model.prepare_to_select(); has_autogenerated_select = true; - if( model_connector && out_stream ) + if( model_connector && out_stream && db_expression ) { model.table_name(model.model_env->table_name); - model.table_name_for_join_as(model.model_env->table_name_simple); - model.model_env->table_index = finder_helper.add_join_table(model.model_env->table_name_simple); + db_expression->prepare_short_table_name(model.model_env->table_name, model.model_env->table_name_short); + + model.model_env->table_index = finder_helper.add_join_table(model.model_env->table_name_short); (*out_stream) << "SELECT "; model.generate_select_columns(*out_stream); (*out_stream) << " FROM " << model.model_env->table_name << " AS "; - (*out_stream) << model.model_env->table_name_simple; + (*out_stream) << model.model_env->table_name_short; (*out_stream) << " "; - (*out_stream) << finder_helper.morm_finder_join_tables; + (*out_stream) << finder_helper.join_tables_str; } return *this; @@ -342,27 +325,32 @@ public: if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_EQ); - - bool put_table_prefix = true; - - // IMPROVE ME - // add check if there is a dot char in field_name? - // or add a second eq() method with an additional parameter -- table name? - - db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false, put_table_prefix, &model_env); + db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false, &model_env); } return *this; } + template + Finder & neq(const wchar_t * field_name, const FieldValue & field_value) + { + if( db_expression ) + { + db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_NOT_EQ); + db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false, &model_env); + } + + return *this; + } + template Finder & lt(const wchar_t * field_name, const FieldValue & field_value) { if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_LT); - db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false, true, &model_env); + db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false, &model_env); } return *this; @@ -375,7 +363,7 @@ public: if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_GT); - db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false, true, &model_env); + db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false, &model_env); } return *this; @@ -388,7 +376,7 @@ public: if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_LE); - db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false, true, &model_env); + db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false, &model_env); } return *this; @@ -401,7 +389,7 @@ public: if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_GE); - db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false, true, &model_env); + db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false, &model_env); } return *this; @@ -415,7 +403,7 @@ public: if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_IN); - db_expression->field_in(*out_stream, field_name, container); + db_expression->field_in(*out_stream, field_name, container, &model_env); } return *this; @@ -427,7 +415,7 @@ public: if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_IN); - db_expression->field_in(*out_stream, field_name, container); + db_expression->field_in(*out_stream, field_name, container, &model_env); } return *this; @@ -439,7 +427,7 @@ public: if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_IN); - db_expression->field_in(*out_stream, field_name, container); + db_expression->field_in(*out_stream, field_name, container, &model_env); } return *this; @@ -566,6 +554,22 @@ public: +protected: + + void set_out_stream() + { + if( model_connector ) + { + this->out_stream = model_connector->get_stream(); + } + else + { + this->out_stream = nullptr; + } + } + + + private: @@ -591,12 +595,13 @@ private: if( db_connector ) { db_expression = db_connector->get_expression(); - db_expression->allow_to_use_prefix(true); } } } + + }; } // namespace diff --git a/src/finderhelper.h b/src/finderhelper.h index ba1e3a8..4898fe8 100644 --- a/src/finderhelper.h +++ b/src/finderhelper.h @@ -46,9 +46,11 @@ class FinderHelper { public: - PT::TextStream morm_finder_join_tables; - std::map morm_table_join_map; - std::list morm_foreign_keys; + PT::TextStream join_tables_str; + + std::map join_tables_map; + + std::list foreign_keys; @@ -64,9 +66,9 @@ public: virtual void clear() { - morm_finder_join_tables.clear(); - morm_table_join_map.clear(); - morm_foreign_keys.clear(); + join_tables_str.clear(); + join_tables_map.clear(); + foreign_keys.clear(); } @@ -81,7 +83,7 @@ public: virtual int add_join_table(const std::string & table_name) { - auto res = morm_table_join_map.insert(std::make_pair(table_name, 1)); + auto res = join_tables_map.insert(std::make_pair(table_name, 1)); if( !res.second ) { diff --git a/src/flatconnector.cpp b/src/flatconnector.cpp index d686fd5..99bdb7d 100644 --- a/src/flatconnector.cpp +++ b/src/flatconnector.cpp @@ -74,7 +74,9 @@ void FlatConnector::to_text(PT::TextStream & stream, Model & model) if( flat_expression ) { + flat_expression->clear(); flat_expression->set_work_mode(MORM_WORK_MODE_MODEL_FIELDS_VALUES); + flat_expression->allow_to_use_prefix(false); flat_expression->generate_from_model(stream, model); } } diff --git a/src/jsonexpression.h b/src/jsonexpression.h index 4a7e5e5..2d149f5 100644 --- a/src/jsonexpression.h +++ b/src/jsonexpression.h @@ -68,16 +68,6 @@ protected: void after_field_value_list(); - template - void print_field_name_value(const wchar_t * field_name, const FieldValue & field_value) - { - put_field_name(field_name); - (*out_stream) << ":"; - put_field_value(field_value); - } - - - void esc(char val, PT::TextStream & stream); diff --git a/src/model.cpp b/src/model.cpp index 8770457..7ce8d7f 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -99,39 +99,6 @@ 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) { @@ -175,9 +142,9 @@ void Model::to_text(PT::TextStream & stream, ModelData * model_data, bool clear_ if( flat_connector ) { - this->model_env->model_data = model_data; + model_env->model_data = model_data; flat_connector->to_text(stream, *this); - this->model_env->model_data = nullptr; + model_env->model_data = nullptr; } } @@ -554,11 +521,6 @@ void Model::clear() } -void Model::prepare_to_select() -{ - model_env->table_index = 1; -} - diff --git a/src/model.h b/src/model.h index 7eec1cd..e14b616 100644 --- a/src/model.h +++ b/src/model.h @@ -95,7 +95,6 @@ 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); @@ -131,8 +130,6 @@ public: // set object to default values virtual void clear(); - // we need a pointer to ModelData here? - virtual void prepare_to_select(); protected: @@ -649,7 +646,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, true, model_env); + flat_expression->field(flat_field_name, field_value, insertable, updatable, is_primary_key, model_env); } } } @@ -664,7 +661,7 @@ protected: 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); + db_expression->field(db_field_name, field_value, insertable, updatable, is_primary_key, model_env); } } } @@ -712,7 +709,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_value, insertable, updatable, is_primary_key); + doc_expression->field_doc(*this, flat_field_name, field_value, insertable, updatable, is_primary_key, model_env); } } } @@ -724,14 +721,14 @@ protected: { if( model_env && field_model.model_env && model_env->finder_helper ) { - model_env->finder_helper->morm_foreign_keys.clear(); - field_model.model_env->table_index = model_env->finder_helper->add_join_table(field_model.model_env->table_name_simple); + model_env->finder_helper->foreign_keys.clear(); + field_model.model_env->table_index = model_env->finder_helper->add_join_table(field_model.model_env->table_name_short); - model_env->finder_helper->morm_finder_join_tables << "LEFT JOIN " << field_model.model_env->table_name - << " AS " << field_model.model_env->table_name_simple; + model_env->finder_helper->join_tables_str << "LEFT JOIN " << field_model.model_env->table_name + << " AS " << field_model.model_env->table_name_short; if( field_model.model_env->table_index > 1 ) - model_env->finder_helper->morm_finder_join_tables << field_model.model_env->table_index; + model_env->finder_helper->join_tables_str << field_model.model_env->table_index; int expr_work_mode = db_expression->get_work_mode(); int expr_output_type = db_expression->get_output_type(); @@ -745,29 +742,29 @@ protected: { field_model.map_fields(); - model_env->finder_helper->morm_finder_join_tables << " ON " << model_env->table_name_simple << '.' - << db_field_name << " = " << field_model.model_env->table_name_simple << '.'; + model_env->finder_helper->join_tables_str << " ON " << model_env->table_name_short << '.' + << db_field_name << " = " << field_model.model_env->table_name_short << '.'; - if( model_env->finder_helper->morm_foreign_keys.size() == 1 ) + if( model_env->finder_helper->foreign_keys.size() == 1 ) { - model_env->finder_helper->morm_finder_join_tables << model_env->finder_helper->morm_foreign_keys.front(); + model_env->finder_helper->join_tables_str << model_env->finder_helper->foreign_keys.front(); } } else { map_fields(); - model_env->finder_helper->morm_finder_join_tables << " ON " << model_env->table_name_simple << '.'; + model_env->finder_helper->join_tables_str << " ON " << model_env->table_name_short << '.'; - if( model_env->finder_helper->morm_foreign_keys.size() == 1 ) + if( model_env->finder_helper->foreign_keys.size() == 1 ) { - model_env->finder_helper->morm_finder_join_tables << model_env->finder_helper->morm_foreign_keys.front(); + model_env->finder_helper->join_tables_str << model_env->finder_helper->foreign_keys.front(); } - model_env->finder_helper->morm_finder_join_tables << " = " << field_model.model_env->table_name_simple << '.' << db_field_name; + model_env->finder_helper->join_tables_str << " = " << field_model.model_env->table_name_short << '.' << db_field_name; } - model_env->finder_helper->morm_finder_join_tables << ' '; + model_env->finder_helper->join_tables_str << ' '; db_expression->set_work_mode(expr_work_mode); db_expression->set_output_type(expr_output_type); @@ -777,7 +774,7 @@ protected: - 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) + 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) { FlatConnector * flat_connector = model_connector->get_flat_connector(); @@ -788,7 +785,7 @@ protected: 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); + flat_expression->field_model(flat_field_name, field_model, insertable, updatable, false, model_env); } } } @@ -807,7 +804,7 @@ protected: field_model.model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL; field_model.table_name(field_model.model_env->table_name); - field_model.table_name_for_join_as(field_model.model_env->table_name_simple); + db_expression->prepare_short_table_name(field_model.model_env->table_name, field_model.model_env->table_name_short); if( db_expression->get_output_type() == MORM_OUTPUT_TYPE_SELECT_COLUMNS ) { @@ -848,7 +845,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, false); + doc_expression->field_doc(*this, flat_field_name, field_model, insertable, updatable, false, model_env); } } } @@ -885,7 +882,7 @@ protected: 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); + field_model_generate_flat_string(db_field_name, flat_field_name, field_model, insertable, updatable); } if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL ) @@ -976,7 +973,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, false, model_env->model_data); + doc_expression->field_doc(*this, flat_field_name, field_container, insertable, updatable, false, model_env); } } } diff --git a/src/modelenv.h b/src/modelenv.h index f6eb01d..776d439 100644 --- a/src/modelenv.h +++ b/src/modelenv.h @@ -56,7 +56,7 @@ public: const void * doc_field_pointer; PT::TextStream table_name; - PT::TextStream table_name_simple; + PT::TextStream table_name_short; int table_index; @@ -102,7 +102,7 @@ public: model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; doc_field_pointer = nullptr; table_name.clear(); - table_name_simple.clear(); + table_name_short.clear(); table_index = 0; } diff --git a/src/morm_types.h b/src/morm_types.h index 5b3f801..d1a2c61 100644 --- a/src/morm_types.h +++ b/src/morm_types.h @@ -77,6 +77,7 @@ #define MORM_OUTPUT_TYPE_WHERE_LE 13 #define MORM_OUTPUT_TYPE_WHERE_GE 14 #define MORM_OUTPUT_TYPE_WHERE_IN 15 +#define MORM_OUTPUT_TYPE_WHERE_NOT_EQ 16 #define MORM_CONJUNCTION_AND 1 From 2533b18cfdf37dc134863ef6b962b16411876cc7 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Mon, 17 Jun 2019 10:59:39 +0000 Subject: [PATCH 10/10] fixed: in cursor in add_models_to_list(): added_model.model_env should be set after added_model.clear() fixed: when generating: insert, update or remove statements we have used prefixes for columns but the table name was not set in ModelEnv (now we do not use prefixes in such statements) changed: log_queries field moved from PostgreSQLConnector to DbConnector git-svn-id: svn://ttmath.org/publicrep/morm/branches/join_models@1195 e52654a7-88a9-db11-a3e9-0013d4bc506e --- src/cursor.h | 5 +++-- src/dbconnector.cpp | 15 +++++++++++---- src/dbconnector.h | 10 +++++++++- src/dbexpression.cpp | 14 +++++++------- src/postgresqlconnector.cpp | 7 +------ src/postgresqlconnector.h | 5 +---- 6 files changed, 32 insertions(+), 24 deletions(-) diff --git a/src/cursor.h b/src/cursor.h index 17c1052..e167330 100644 --- a/src/cursor.h +++ b/src/cursor.h @@ -302,8 +302,6 @@ protected: ModelClass & added_model = result.back(); ModelEnv model_env_local; - added_model.model_env = &model_env_local; - added_model.model_env->cursor_helper = &cursor_helper; try { @@ -313,6 +311,9 @@ protected: added_model.set_connector(model_connector); added_model.clear(); + + added_model.model_env = &model_env_local; + added_model.model_env->cursor_helper = &cursor_helper; added_model.set_save_mode(Model::DO_UPDATE_ON_SAVE); // IMPROVE ME check if there is a primary key added_model.model_env->model_data = model_data; added_model.before_select(); diff --git a/src/dbconnector.cpp b/src/dbconnector.cpp index 9654b8a..5ec5569 100644 --- a/src/dbconnector.cpp +++ b/src/dbconnector.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 @@ -49,6 +49,7 @@ DbConnector::DbConnector() db_expression = nullptr; expression_allocated = false; log = nullptr; + log_queries = false; } DbConnector::DbConnector(const DbConnector &) @@ -70,12 +71,18 @@ void DbConnector::set_logger(PT::Log * log) this->log = log; } + void DbConnector::set_logger(PT::Log & log) { this->log = &log; } +void DbConnector::set_log_queries(bool log_queries) +{ + this->log_queries = log_queries; +} + bool DbConnector::query(const PT::TextStream & stream, QueryResult & query_result) { @@ -173,7 +180,7 @@ void DbConnector::generate_insert_query(PT::TextStream & stream, Model & model) if( db_expression ) { db_expression->clear(); - db_expression->allow_to_use_prefix(true); + db_expression->allow_to_use_prefix(false); stream << "insert into "; model.table_name(stream); @@ -198,7 +205,7 @@ void DbConnector::generate_update_query(PT::TextStream & stream, Model & model) if( db_expression ) { db_expression->clear(); - db_expression->allow_to_use_prefix(true); + db_expression->allow_to_use_prefix(false); stream << "update "; model.table_name(stream); @@ -223,7 +230,7 @@ void DbConnector::generate_remove_query(PT::TextStream & stream, Model & model) if( db_expression ) { db_expression->clear(); - db_expression->allow_to_use_prefix(true); + db_expression->allow_to_use_prefix(false); stream << "delete from "; model.table_name(stream); diff --git a/src/dbconnector.h b/src/dbconnector.h index e2f58e1..7e2753d 100644 --- a/src/dbconnector.h +++ b/src/dbconnector.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 @@ -57,6 +57,8 @@ public: virtual void set_logger(PT::Log * log); virtual void set_logger(PT::Log & log); + virtual void set_log_queries(bool log_queries); + DbExpression * get_expression(); //virtual void clear_last_query_result(); @@ -115,6 +117,11 @@ public: if( val_str ) { get_value(val_str, field_value); + + if( log && log_queries ) + { + (*log) << PT::Log::log3 << "Morm: sequence value: " << field_value << PT::Log::logend; + } } } @@ -124,6 +131,7 @@ protected: DbExpression * db_expression; bool expression_allocated; PT::Log * log; + bool log_queries; virtual void allocate_default_expression() = 0; diff --git a/src/dbexpression.cpp b/src/dbexpression.cpp index f65e48e..c489b7f 100644 --- a/src/dbexpression.cpp +++ b/src/dbexpression.cpp @@ -96,7 +96,7 @@ void DbExpression::field_before() output_type == MORM_OUTPUT_TYPE_DB_UPDATE || output_type == MORM_OUTPUT_TYPE_SELECT_COLUMNS ) { - (*out_stream) << ","; + (*out_stream) << ", "; } else if( output_type == MORM_OUTPUT_TYPE_DB_PRIMARY_KEY ) @@ -137,32 +137,32 @@ void DbExpression::put_name_value_separator() output_type == MORM_OUTPUT_TYPE_WHERE_EQ || output_type == MORM_OUTPUT_TYPE_DB_UPDATE) { - (*out_stream) << " = "; + (*out_stream) << "="; } else if( output_type == MORM_OUTPUT_TYPE_WHERE_NOT_EQ ) { - (*out_stream) << " <> "; + (*out_stream) << "<>"; } else if( output_type == MORM_OUTPUT_TYPE_WHERE_LT ) { - (*out_stream) << " < "; + (*out_stream) << "<"; } else if( output_type == MORM_OUTPUT_TYPE_WHERE_GT ) { - (*out_stream) << " > "; + (*out_stream) << ">"; } else if( output_type == MORM_OUTPUT_TYPE_WHERE_LE ) { - (*out_stream) << " <= "; + (*out_stream) << "<="; } else if( output_type == MORM_OUTPUT_TYPE_WHERE_GE ) { - (*out_stream) << " >= "; + (*out_stream) << ">="; } else if( output_type == MORM_OUTPUT_TYPE_WHERE_IN ) diff --git a/src/postgresqlconnector.cpp b/src/postgresqlconnector.cpp index b3fb529..bad375d 100644 --- a/src/postgresqlconnector.cpp +++ b/src/postgresqlconnector.cpp @@ -47,7 +47,6 @@ namespace morm PostgreSQLConnector::PostgreSQLConnector() { pg_conn = nullptr; - log_queries = false; } @@ -77,10 +76,6 @@ void PostgreSQLConnector::allocate_default_expression() -void PostgreSQLConnector::set_log_queries(bool log_queries) -{ - this->log_queries = log_queries; -} QueryResult * PostgreSQLConnector::create_query_result() @@ -97,7 +92,7 @@ bool PostgreSQLConnector::do_query(const char * query_str, PostgreSQLQueryResult if( log_queries && log ) { - (*log) << PT::Log::log1 << "Morm: query: " << query_str << PT::Log::logend; + (*log) << PT::Log::log3 << "Morm: query: " << query_str << PT::Log::logend; } psql_result->psql_result = PQexec(pg_conn, query_str); diff --git a/src/postgresqlconnector.h b/src/postgresqlconnector.h index 86561d3..27e4f1a 100644 --- a/src/postgresqlconnector.h +++ b/src/postgresqlconnector.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 @@ -54,7 +54,6 @@ public: virtual ~PostgreSQLConnector(); - virtual void set_log_queries(bool log_queries); bool query(const PT::TextStream & stream, QueryResult & query_result); bool query(const char * query_str, QueryResult & query_result); @@ -86,10 +85,8 @@ public: protected: PGconn * pg_conn; - bool log_queries; PT::TextStream stream; std::string query_str; - std::string temp_column_name; std::wstring db_database; std::wstring db_user;