From fcf1d28b185f61ff460c6f2c1aba7376abc5efbb Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Wed, 10 Mar 2021 16:20:11 +0100 Subject: [PATCH] added FT class which is used in Model::field() methods FT class has following types: enum FieldType { default_type = 0, primary_key = 1, foreign_key = 2, foreign_key_in_child = 4, no_insertable = 8, no_updatable = 16, no_fetchable = 32, /* not supported yet */ }; an object of FT class are now used in Model::field() methods instead of insertable/updatable/is_primary_key/... boolean flags changed the semantic of has_foreign_key (which was a bool) flag in child Models: now on Models and list/vector of Models you should use either FT::foreign_key or FT::foreign_key_in_child 1. FT::foreign_key means that field with this flag is a foreign key and is pointing to the child object (it was the case when has_foreign_key was equal to true beforehand) 2. FT::foreign_key_in child means that the foreign key is in the child object and is pointing to the parent object --- samples/Makefile.dep | 10 +- samples/attachment.h | 6 +- samples/attachment2.h | 8 +- samples/language.h | 2 +- samples/person.h | 18 +- samples/sample01.h | 2 +- samples/type.h | 2 +- src/Makefile.dep | 27 +- src/baseexpression.cpp | 6 +- src/baseexpression.h | 34 +-- src/dbexpression.cpp | 10 +- src/dbexpression.h | 4 +- src/finder.h | 12 +- src/ft.h | 138 +++++++++ src/model.cpp | 20 ++ src/model.h | 661 +++++++++++++++++++++-------------------- src/modelenv.h | 2 + 17 files changed, 571 insertions(+), 391 deletions(-) create mode 100644 src/ft.h diff --git a/samples/Makefile.dep b/samples/Makefile.dep index 3bdaf52..1155a2c 100644 --- a/samples/Makefile.dep +++ b/samples/Makefile.dep @@ -14,10 +14,10 @@ main.o: ../../morm/src/queryresult.h ../../morm/src/flatconnector.h main.o: ../../morm/src/dbexpression.h ../../morm/src/baseexpression.h main.o: ../../morm/src/modelenv.h ../../morm/src/modeldata.h main.o: ../../morm/src/cursorhelper.h ../../morm/src/finderhelper.h -main.o: ../../morm/src/fieldvaluehelper.h ../../morm/src/flatexpression.h -main.o: ../../morm/src/finder.h ../../pikotools/utf8/utf8.h -main.o: ../../morm/src/cursor.h ../../morm/src/jsonexpression.h -main.o: ../../morm/src/postgresqlexpression.h ../../morm/src/jsonconnector.h -main.o: ../../morm/src/postgresqlconnector.h +main.o: ../../morm/src/fieldvaluehelper.h ../../morm/src/ft.h +main.o: ../../morm/src/flatexpression.h ../../morm/src/finder.h +main.o: ../../pikotools/utf8/utf8.h ../../morm/src/cursor.h +main.o: ../../morm/src/jsonexpression.h ../../morm/src/postgresqlexpression.h +main.o: ../../morm/src/jsonconnector.h ../../morm/src/postgresqlconnector.h main.o: ../../morm/src/postgresqlqueryresult.h person.h language.h main.o: attachment.h type.h attachment2.h diff --git a/samples/attachment.h b/samples/attachment.h index 50bc389..4b2146d 100644 --- a/samples/attachment.h +++ b/samples/attachment.h @@ -77,14 +77,14 @@ public: void map_fields() { - field(L"id", id, false, false, true); + field(L"id", id, FT::no_insertable | FT::no_updatable | FT::primary_key); field(L"person_id", person_id); field(L"name", name); field(L"content", content); - field(L"attachment_id", L"types", types); + field(L"attachment_id", L"types", types, FT::foreign_key_in_child); field(L"some_flags", some_flags); field(L"created_date", created_date); - field(L"language_id", L"language", language); + field(L"language_id", L"language", language, FT::foreign_key); } void table_name(PT::TextStream & stream) diff --git a/samples/attachment2.h b/samples/attachment2.h index 3b654e8..e384d2f 100644 --- a/samples/attachment2.h +++ b/samples/attachment2.h @@ -77,14 +77,14 @@ public: void map_fields() { - field(L"id", id, false, false, true); - field(L"person_id", person_id); + field(L"id", id, FT::no_insertable | FT::no_updatable | FT::primary_key); + //field(L"person_id", person_id); field(L"name", name); field(L"content", content); - field(L"attachment_id", L"types", types); + field(L"attachment_id", L"types", types, FT::foreign_key_in_child); field(L"some_flags", some_flags); field(L"created_date", created_date); - field(L"language_id", L"language", language); + field(L"language_id", L"language", language, FT::foreign_key); } void table_name(PT::TextStream & stream) diff --git a/samples/language.h b/samples/language.h index fa60363..d1e0e3e 100644 --- a/samples/language.h +++ b/samples/language.h @@ -70,7 +70,7 @@ public: void map_fields() { - field(L"id", id, false, false, true); + field(L"id", id, FT::no_insertable | FT::no_updatable | FT::primary_key); field(L"english_name", english_name); field(L"local_name", local_name); field(L"code_str", code_str); diff --git a/samples/person.h b/samples/person.h index d70fb03..a0a5a88 100644 --- a/samples/person.h +++ b/samples/person.h @@ -77,29 +77,23 @@ public: void map_fields() { - field(L"id", id, false, false, true); - field(L"language_id", L"language", language); - + field(L"id", id, FT::no_insertable | FT::no_updatable | FT::primary_key); + field(L"language_id", L"language", language, FT::foreign_key); field(L"first_name", first_name); field(L"last_name", last_name); field(L"email", email); - - field(L"person_id", L"attachments", attachments); - - field(L"person_id", L"attachment2", attachment2, true, true, false); - - - //field(L"id", id, f::no_insertable | f::no_updatable | f::primary_key); - //field(L"person_id", attachment, f::insertable | f::updatable | f::foreign_key); - //field(L"person_id", attachment, f::insertable, f::updatable, f::foreign_key); + field(L"person_id", L"attachments", attachments, FT::foreign_key_in_child); + field(L"person_id", L"attachment2", attachment2, FT::foreign_key_in_child | FT::no_insertable | FT::no_updatable); } + void table_name(PT::TextStream & stream) { // schema.table_name or just table_name stream << "public.person"; } + void after_select() { if( has_primary_key_set ) diff --git a/samples/sample01.h b/samples/sample01.h index 87f6db3..a9d46a4 100644 --- a/samples/sample01.h +++ b/samples/sample01.h @@ -75,7 +75,7 @@ void make() morm::Finder finder(model_connector); - Person p = finder.select().where().eq(L"id", 191).get(); + Person p = finder.select().where().eq(L"id", 207).get(); p.to_text(str, true, true); diff --git a/samples/type.h b/samples/type.h index 05ec7fd..b34e50d 100644 --- a/samples/type.h +++ b/samples/type.h @@ -65,7 +65,7 @@ public: void map_fields() { - field(L"id", id, false, false, true); + field(L"id", id, FT::no_insertable | FT::no_updatable | FT::primary_key); field(L"attachment_id", attachment_id); field(L"name", name); } diff --git a/src/Makefile.dep b/src/Makefile.dep index c7b9f44..e0eb565 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep @@ -9,9 +9,9 @@ baseexpression.o: ../../pikotools/membuffer/membuffer.h baseexpression.o: ../../pikotools/textstream/types.h morm_types.h modelenv.h baseexpression.o: modeldata.h cursorhelper.h queryresult.h baseexpression.o: ../../pikotools/log/log.h ../../pikotools/log/filelog.h -baseexpression.o: finderhelper.h fieldvaluehelper.h model.h modelconnector.h -baseexpression.o: clearer.h dbconnector.h flatconnector.h dbexpression.h -baseexpression.o: flatexpression.h ../../pikotools/utf8/utf8.h +baseexpression.o: finderhelper.h fieldvaluehelper.h ft.h model.h +baseexpression.o: modelconnector.h clearer.h dbconnector.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 @@ -21,7 +21,7 @@ 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 cursorhelper.h finderhelper.h -clearer.o: fieldvaluehelper.h flatexpression.h +clearer.o: fieldvaluehelper.h ft.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 @@ -30,7 +30,7 @@ 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 -dbconnector.o: cursorhelper.h finderhelper.h fieldvaluehelper.h model.h +dbconnector.o: cursorhelper.h finderhelper.h fieldvaluehelper.h ft.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 @@ -47,7 +47,7 @@ dbexpression.o: ../../pikotools/membuffer/membuffer.h dbexpression.o: ../../pikotools/textstream/types.h morm_types.h modelenv.h dbexpression.o: modeldata.h cursorhelper.h queryresult.h dbexpression.o: ../../pikotools/log/log.h ../../pikotools/log/filelog.h -dbexpression.o: finderhelper.h fieldvaluehelper.h +dbexpression.o: finderhelper.h fieldvaluehelper.h ft.h flatconnector.o: flatconnector.h ../../pikotools/textstream/textstream.h flatconnector.o: ../../pikotools/space/space.h flatconnector.o: ../../pikotools/textstream/types.h @@ -58,7 +58,7 @@ flatconnector.o: ../../pikotools/textstream/types.h flatexpression.h flatconnector.o: baseexpression.h morm_types.h modelenv.h modeldata.h flatconnector.o: cursorhelper.h queryresult.h ../../pikotools/log/log.h flatconnector.o: ../../pikotools/log/filelog.h finderhelper.h -flatconnector.o: fieldvaluehelper.h model.h modelconnector.h clearer.h +flatconnector.o: fieldvaluehelper.h ft.h model.h modelconnector.h clearer.h flatconnector.o: dbconnector.h dbexpression.h flatexpression.o: flatexpression.h baseexpression.h flatexpression.o: ../../pikotools/textstream/textstream.h @@ -70,7 +70,7 @@ flatexpression.o: ../../pikotools/membuffer/membuffer.h flatexpression.o: ../../pikotools/textstream/types.h morm_types.h modelenv.h flatexpression.o: modeldata.h cursorhelper.h queryresult.h flatexpression.o: ../../pikotools/log/log.h ../../pikotools/log/filelog.h -flatexpression.o: finderhelper.h fieldvaluehelper.h +flatexpression.o: finderhelper.h fieldvaluehelper.h ft.h jsonconnector.o: jsonconnector.h flatconnector.h jsonconnector.o: ../../pikotools/textstream/textstream.h jsonconnector.o: ../../pikotools/space/space.h @@ -82,7 +82,7 @@ jsonconnector.o: ../../pikotools/textstream/types.h jsonexpression.h jsonconnector.o: flatexpression.h baseexpression.h morm_types.h modelenv.h jsonconnector.o: modeldata.h cursorhelper.h queryresult.h jsonconnector.o: ../../pikotools/log/log.h ../../pikotools/log/filelog.h -jsonconnector.o: finderhelper.h fieldvaluehelper.h +jsonconnector.o: finderhelper.h fieldvaluehelper.h ft.h jsonexpression.o: jsonexpression.h flatexpression.h baseexpression.h jsonexpression.o: ../../pikotools/textstream/textstream.h jsonexpression.o: ../../pikotools/space/space.h @@ -93,7 +93,7 @@ jsonexpression.o: ../../pikotools/membuffer/membuffer.h jsonexpression.o: ../../pikotools/textstream/types.h morm_types.h modelenv.h jsonexpression.o: modeldata.h cursorhelper.h queryresult.h jsonexpression.o: ../../pikotools/log/log.h ../../pikotools/log/filelog.h -jsonexpression.o: finderhelper.h fieldvaluehelper.h +jsonexpression.o: finderhelper.h fieldvaluehelper.h ft.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,7 +102,8 @@ 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: cursorhelper.h finderhelper.h fieldvaluehelper.h flatexpression.h +model.o: cursorhelper.h finderhelper.h fieldvaluehelper.h ft.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 +126,7 @@ 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 cursorhelper.h -postgresqlconnector.o: finderhelper.h fieldvaluehelper.h +postgresqlconnector.o: finderhelper.h fieldvaluehelper.h ft.h postgresqlconnector.o: ../../pikotools/convert/strtoint.h postgresqlconnector.o: ../../pikotools/convert/text.h postgresqlconnector.o: ../../pikotools/convert/misc.h @@ -141,7 +142,7 @@ postgresqlexpression.o: ../../pikotools/textstream/types.h morm_types.h postgresqlexpression.o: modelenv.h modeldata.h cursorhelper.h queryresult.h postgresqlexpression.o: ../../pikotools/log/log.h postgresqlexpression.o: ../../pikotools/log/filelog.h finderhelper.h -postgresqlexpression.o: fieldvaluehelper.h +postgresqlexpression.o: fieldvaluehelper.h ft.h postgresqlqueryresult.o: postgresqlqueryresult.h queryresult.h postgresqlqueryresult.o: ../../pikotools/log/log.h postgresqlqueryresult.o: ../../pikotools/textstream/textstream.h diff --git a/src/baseexpression.cpp b/src/baseexpression.cpp index 59e4931..f26df0b 100644 --- a/src/baseexpression.cpp +++ b/src/baseexpression.cpp @@ -117,8 +117,8 @@ void BaseExpression::dump_additional_info(Model & model) { if( model.model_env && model.model_env->dump_mode ) { - field(L"model_save_mode", model.save_mode, false, false, false, model.model_env); - field(L"has_primary_key_set", model.has_primary_key_set, false, false, false, model.model_env); + field(L"model_save_mode", model.save_mode, FT::no_insertable | FT::no_updatable | FT::no_fetchable, model.model_env); + field(L"has_primary_key_set", model.has_primary_key_set, FT::no_insertable | FT::no_updatable | FT::no_fetchable, model.model_env); } } @@ -134,7 +134,7 @@ void BaseExpression::after_generate_from_model() } -bool BaseExpression::can_field_be_generated(bool insertable, bool updatable, bool is_primary_key) +bool BaseExpression::can_field_be_generated(FT) { return true; } diff --git a/src/baseexpression.h b/src/baseexpression.h index 05c06e4..2f6b23a 100644 --- a/src/baseexpression.h +++ b/src/baseexpression.h @@ -41,7 +41,7 @@ #include "date/date.h" #include "morm_types.h" #include "modelenv.h" - +#include "ft.h" namespace morm @@ -73,9 +73,9 @@ public: template - void field(const wchar_t * field_name, const FieldValue & field_value, bool insertable, bool updatable, bool is_primary_key, ModelEnv * model_env) + void field(const wchar_t * field_name, const FieldValue & field_value, FT field_type, ModelEnv * model_env) { - if( out_stream && can_field_be_generated(insertable, updatable, is_primary_key) ) + if( out_stream && can_field_be_generated(field_type) ) { field_before(); @@ -91,7 +91,7 @@ public: else if( work_mode == MORM_WORK_MODE_MODEL_VALUES ) { - put_field_value_or_null(field_value, is_primary_key, model_env); + put_field_value_or_null(field_value, field_type, model_env); } else if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES ) @@ -102,7 +102,7 @@ public: { put_field_name((*model_env->set_field_name_helper)[model_env->field_index], model_env); put_name_value_separator(); - put_field_value_or_null(field_value, is_primary_key, model_env); + put_field_value_or_null(field_value, field_type, model_env); } model_env->field_index += 1; @@ -111,7 +111,7 @@ public: { put_field_name(field_name, model_env); put_name_value_separator(); - put_field_value_or_null(field_value, is_primary_key, model_env); + put_field_value_or_null(field_value, field_type, model_env); } } @@ -122,9 +122,9 @@ public: template - void put_field_value_or_null(const FieldValue & field_value, bool is_primary_key, ModelEnv * model_env) + void put_field_value_or_null(const FieldValue & field_value, FT field_type, ModelEnv * model_env) { - if( is_primary_key ) + if( field_type.is_primary_key() ) { if( model_env && model_env->has_primary_key_set ) put_field_value(field_value); @@ -159,10 +159,9 @@ public: 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) + void field_list(const wchar_t * field_name, ModelContainer & field_value, FT field_type, ModelConnector * model_connector, ModelEnv * model_env) { - if( out_stream && can_field_be_generated(insertable, updatable, is_primary_key) ) + if( out_stream && can_field_be_generated(field_type) ) { field_before(); @@ -183,9 +182,9 @@ public: } template - void field_model(const wchar_t * field_name, ModelClass & field_model, bool insertable, bool updatable, bool is_primary_key, ModelEnv * model_env) + void field_model(const wchar_t * field_name, ModelClass & field_model, FT field_type, ModelEnv * model_env) { - if( out_stream && can_field_be_generated(insertable, updatable, is_primary_key) ) + if( out_stream && can_field_be_generated(field_type) ) { field_before(); @@ -211,11 +210,10 @@ public: } template - void field_to_stream(PT::TextStream & stream, const wchar_t * field_name, const FieldValue & field_value, bool insertable, bool updatable, bool is_primary_key, - ModelEnv * model_env) + void field_to_stream(PT::TextStream & stream, const wchar_t * field_name, const FieldValue & field_value, FT field_type, ModelEnv * model_env) { this->out_stream = &stream; - field(field_name, field_value, insertable, updatable, is_primary_key, model_env); + field(field_name, field_value, field_type, model_env); this->out_stream = nullptr; } @@ -274,12 +272,10 @@ protected: virtual void before_generate_from_model(); virtual void after_generate_from_model(); - virtual bool can_field_be_generated(bool insertable, bool updatable, bool is_primary_key); + virtual bool can_field_be_generated(FT); virtual void field_before(); virtual void field_after(); - //void field(const wchar_t * field_name, Model & field, bool insertable = true, bool updatable = true); - virtual void put_field_name(const wchar_t * field_name, ModelEnv * model_env); virtual void save_foreign_key(const wchar_t * field_name, ModelEnv * model_env); diff --git a/src/dbexpression.cpp b/src/dbexpression.cpp index d496f2d..0036359 100644 --- a/src/dbexpression.cpp +++ b/src/dbexpression.cpp @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018-2019, Tomasz Sowa + * Copyright (c) 2018-2021, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -62,23 +62,23 @@ int DbExpression::get_output_type() } -bool DbExpression::can_field_be_generated(bool insertable, bool updatable, bool is_primary_key) +bool DbExpression::can_field_be_generated(FT field_type) { if( output_type == MORM_OUTPUT_TYPE_DB_INSERT ) { - return insertable; + return field_type.is_insertable(); } else if( output_type == MORM_OUTPUT_TYPE_DB_UPDATE ) { - return updatable; + return field_type.is_updatable(); } else if( output_type == MORM_OUTPUT_TYPE_DB_PRIMARY_KEY || output_type == MORM_OUTPUT_TYPE_JOIN_TABLES || output_type == MORM_OUTPUT_TYPE_DB_INSERT_PRIMARY_KEY ) { - return is_primary_key; + return field_type.is_primary_key(); } else { diff --git a/src/dbexpression.h b/src/dbexpression.h index 53d2dba..ab6d549 100644 --- a/src/dbexpression.h +++ b/src/dbexpression.h @@ -5,7 +5,7 @@ */ /* - * Copyright (c) 2018, Tomasz Sowa + * Copyright (c) 2018-2021, Tomasz Sowa * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -86,7 +86,7 @@ protected: std::vector conjunctions; - bool can_field_be_generated(bool insertable, bool updatable, bool is_primary_key); + bool can_field_be_generated(FT field_type); void field_before(); diff --git a/src/finder.h b/src/finder.h index 1bc7466..3407b9d 100644 --- a/src/finder.h +++ b/src/finder.h @@ -333,7 +333,7 @@ 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, &model_env); + db_expression->field_to_stream(*out_stream, field_name, field_value, FT::default_type, &model_env); } return *this; @@ -346,7 +346,7 @@ public: 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); + db_expression->field_to_stream(*out_stream, field_name, field_value, FT::default_type, &model_env); } return *this; @@ -358,7 +358,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, &model_env); + db_expression->field_to_stream(*out_stream, field_name, field_value, FT::default_type, &model_env); } return *this; @@ -371,7 +371,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, &model_env); + db_expression->field_to_stream(*out_stream, field_name, field_value, FT::default_type, &model_env); } return *this; @@ -384,7 +384,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, &model_env); + db_expression->field_to_stream(*out_stream, field_name, field_value, FT::default_type, &model_env); } return *this; @@ -397,7 +397,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, &model_env); + db_expression->field_to_stream(*out_stream, field_name, field_value, FT::default_type, &model_env); } return *this; diff --git a/src/ft.h b/src/ft.h new file mode 100644 index 0000000..581f9d3 --- /dev/null +++ b/src/ft.h @@ -0,0 +1,138 @@ +/* + * This file is a part of morm + * and is distributed under the 2-Clause BSD licence. + * Author: Tomasz Sowa + */ + +/* + * Copyright (c) 2021, Tomasz Sowa + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef headerfile_morm_ft +#define headerfile_morm_ft + +namespace morm +{ + + + +/* + * field types + */ +class FT +{ +public: + + enum FieldType + { + default_type = 0, + primary_key = 1, + foreign_key = 2, + foreign_key_in_child = 4, + no_insertable = 8, + no_updatable = 16, + no_fetchable = 32, /* not supported yet */ + }; + + /* + * type can be a superposition from FieldType values + */ + int type; + + + + FT() + { + type = 0; + } + + FT(const FT & field_type) + { + type = field_type.type; + } + + FT(FieldType type) + { + this->type = static_cast(type); + } + + FT(int type) + { + this->type = type; + } + + FT & operator=(const FT & field_type) + { + type = field_type.type; + return *this; + } + + bool is_flag_set(int flag_mask) const + { + return (type & flag_mask) != 0; + } + + + bool is_primary_key() const + { + return is_flag_set(primary_key); + } + + + bool is_foreign_key() const + { + return is_flag_set(foreign_key); + } + + bool is_foreign_key_in_child() const + { + return is_flag_set(foreign_key_in_child); + } + + bool is_insertable() const + { + return !is_flag_set(no_insertable); + } + + + bool is_updatable() const + { + return !is_flag_set(no_updatable); + } + + + bool is_fetchable() const + { + return !is_flag_set(no_fetchable); + } + +}; + +} + +#endif + diff --git a/src/model.cpp b/src/model.cpp index ce588fc..416f778 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -943,5 +943,25 @@ void Model::put_fields_to_log(PT::Log & log, const wchar_t * db_field_name, cons } +PT::TextStream Model::log_table_name() +{ + PT::TextStream buf; + table_name(buf); + + return buf; +} + + +PT::TextStream Model::log_table_name(const wchar_t * db_field_name) +{ + PT::TextStream buf; + table_name(buf); + buf << '.' << db_field_name; + + return buf; +} + + + } // namespace diff --git a/src/model.h b/src/model.h index b8f3535..8588c20 100644 --- a/src/model.h +++ b/src/model.h @@ -46,6 +46,7 @@ #include "dbexpression.h" #include "flatexpression.h" #include "modelenv.h" +#include "ft.h" namespace morm @@ -222,246 +223,220 @@ protected: * field methods for such field_values: signed char, wchar_t, char16_t, char32_t, std::u16string, std::u32string * */ - - void field(const wchar_t * field_name, char & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) + void field(const wchar_t * field_name, char & field_value, FT field_type = FT::default_type) { - field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); + field_generic(field_name, field_name, field_value, field_type); } - void field(const wchar_t * field_name, unsigned char & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) + void field(const wchar_t * field_name, unsigned char & field_value, FT field_type = FT::default_type) { - field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); + field_generic(field_name, field_name, field_value, field_type); } - void field(const wchar_t * field_name, std::wstring & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) + void field(const wchar_t * field_name, std::wstring & field_value, FT field_type = FT::default_type) { - field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); + field_generic(field_name, field_name, field_value, field_type); } -// void field(const wchar_t * field_name, wchar_t * field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) -// { -// field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); -// } - - void field(const wchar_t * field_name, std::string & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) + void field(const wchar_t * field_name, std::string & field_value, FT field_type = FT::default_type) { - field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); + field_generic(field_name, field_name, field_value, field_type); } -// void field(const wchar_t * field_name, char * field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) -// { -// field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); -// } - - void field(const wchar_t * field_name, bool & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) + void field(const wchar_t * field_name, bool & field_value, FT field_type = FT::default_type) { - field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); + field_generic(field_name, field_name, field_value, field_type); } - void field(const wchar_t * field_name, short & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) + void field(const wchar_t * field_name, short & field_value, FT field_type = FT::default_type) { - field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); + field_generic(field_name, field_name, field_value, field_type); } - void field(const wchar_t * field_name, unsigned short & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) + void field(const wchar_t * field_name, unsigned short & field_value, FT field_type = FT::default_type) { - field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); + field_generic(field_name, field_name, field_value, field_type); } - void field(const wchar_t * field_name, int & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) + void field(const wchar_t * field_name, int & field_value, FT field_type = FT::default_type) { - field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); + field_generic(field_name, field_name, field_value, field_type); } - void field(const wchar_t * field_name, unsigned int & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) + void field(const wchar_t * field_name, unsigned int & field_value, FT field_type = FT::default_type) { - field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); + field_generic(field_name, field_name, field_value, field_type); } - void field(const wchar_t * field_name, long & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) + void field(const wchar_t * field_name, long & field_value, FT field_type = FT::default_type) { - field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); + field_generic(field_name, field_name, field_value, field_type); } - void field(const wchar_t * field_name, unsigned long & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) + void field(const wchar_t * field_name, unsigned long & field_value, FT field_type = FT::default_type) { - field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); + field_generic(field_name, field_name, field_value, field_type); } - void field(const wchar_t * field_name, long long & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) + void field(const wchar_t * field_name, long long & field_value, FT field_type = FT::default_type) { - field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); + field_generic(field_name, field_name, field_value, field_type); } - void field(const wchar_t * field_name, unsigned long long & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) + void field(const wchar_t * field_name, unsigned long long & field_value, FT field_type = FT::default_type) { - field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); + field_generic(field_name, field_name, field_value, field_type); } - void field(const wchar_t * field_name, float & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) + void field(const wchar_t * field_name, float & field_value, FT field_type = FT::default_type) { - field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); + field_generic(field_name, field_name, field_value, field_type); } - void field(const wchar_t * field_name, double & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) + void field(const wchar_t * field_name, double & field_value, FT field_type = FT::default_type) { - field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); + field_generic(field_name, field_name, field_value, field_type); } - void field(const wchar_t * field_name, long double & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) + void field(const wchar_t * field_name, long double & field_value, FT field_type = FT::default_type) { - field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); + field_generic(field_name, field_name, field_value, field_type); } -// void field(const wchar_t * field_name, void * field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) -// { -// field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); -// } - - void field(const wchar_t * field_name, PT::Date & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) + void field(const wchar_t * field_name, PT::Date & field_value, FT field_type = FT::default_type) { - field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key); + field_generic(field_name, field_name, field_value, field_type); } - void field(const wchar_t * field_name, Model & field_value, bool insertable = true, bool updatable = true, bool has_foreign_key = true) + void field(const wchar_t * field_name, Model & field_value, FT field_type = FT::default_type) { - field_model(field_name, field_name, field_value, insertable, updatable, has_foreign_key); + // has_foreign_key was here + field_model(field_name, field_name, field_value, field_type); } template - void field(const wchar_t * field_name, std::list & field_value, bool insertable = true, bool updatable = true) + void field(const wchar_t * field_name, std::list & field_value, FT field_type = FT::default_type) { ModelClass * list_model_null_pointer = nullptr; - field_list(field_name, field_name, field_value, list_model_null_pointer, insertable, updatable); + field_list(field_name, field_name, field_value, list_model_null_pointer, field_type); } template - void field(const wchar_t * field_name, std::vector & field_value, bool insertable = true, bool updatable = true) + void field(const wchar_t * field_name, std::vector & field_value, FT field_type = FT::default_type) { ModelClass * list_model_null_pointer = nullptr; - field_list(field_name, field_name, field_value, list_model_null_pointer, insertable, updatable); - } - -////////////////////// - - void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, char & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) - { - field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); - } - - void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, unsigned char & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) - { - field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); - } - - void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::wstring & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) - { - field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); - } - -// void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, wchar_t * field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) -// { -// field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); -// } - - void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::string & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) - { - field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); - } - -// void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, char * field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) -// { -// field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); -// } - - void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, bool & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) - { - field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); - } - - void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, short & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) - { - field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); - } - - void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, unsigned short & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) - { - field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); - } - - void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, int & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) - { - field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); - } - - void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, unsigned int & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) - { - field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); - } - - void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, long & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) - { - field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); - } - - void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, unsigned long & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) - { - field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); - } - - void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, long long & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) - { - field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); - } - - void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, unsigned long long & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) - { - field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); - } - - void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, float & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) - { - field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); - } - - void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, double & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) - { - field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); - } - - void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, long double & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) - { - field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); - } - -// void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, void * field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) -// { -// field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); -// } - - void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, PT::Date & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) - { - field_generic(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); + field_list(field_name, field_name, field_value, list_model_null_pointer, field_type); } - void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, Model & field_value, bool insertable = true, bool updatable = true, bool has_foreign_key = true) + /* + * field methods which take two names: db_field_name and flat_field_name + */ + + void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, char & field_value, FT field_type = FT::default_type) { - field_model(db_field_name, flat_field_name, field_value, insertable, updatable, has_foreign_key); + field_generic(db_field_name, flat_field_name, field_value, field_type); + } + + void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, unsigned char & field_value, FT field_type = FT::default_type) + { + field_generic(db_field_name, flat_field_name, field_value, field_type); + } + + void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::wstring & field_value, FT field_type = FT::default_type) + { + field_generic(db_field_name, flat_field_name, field_value, field_type); + } + + void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::string & field_value, FT field_type = FT::default_type) + { + field_generic(db_field_name, flat_field_name, field_value, field_type); + } + + void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, bool & field_value, FT field_type = FT::default_type) + { + field_generic(db_field_name, flat_field_name, field_value, field_type); + } + + void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, short & field_value, FT field_type = FT::default_type) + { + field_generic(db_field_name, flat_field_name, field_value, field_type); + } + + void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, unsigned short & field_value, FT field_type = FT::default_type) + { + field_generic(db_field_name, flat_field_name, field_value, field_type); + } + + void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, int & field_value, FT field_type = FT::default_type) + { + field_generic(db_field_name, flat_field_name, field_value, field_type); + } + + void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, unsigned int & field_value, FT field_type = FT::default_type) + { + field_generic(db_field_name, flat_field_name, field_value, field_type); + } + + void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, long & field_value, FT field_type = FT::default_type) + { + field_generic(db_field_name, flat_field_name, field_value, field_type); + } + + void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, unsigned long & field_value, FT field_type = FT::default_type) + { + field_generic(db_field_name, flat_field_name, field_value, field_type); + } + + void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, long long & field_value, FT field_type = FT::default_type) + { + field_generic(db_field_name, flat_field_name, field_value, field_type); + } + + void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, unsigned long long & field_value, FT field_type = FT::default_type) + { + field_generic(db_field_name, flat_field_name, field_value, field_type); + } + + void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, float & field_value, FT field_type = FT::default_type) + { + field_generic(db_field_name, flat_field_name, field_value, field_type); + } + + void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, double & field_value, FT field_type = FT::default_type) + { + field_generic(db_field_name, flat_field_name, field_value, field_type); + } + + void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, long double & field_value, FT field_type = FT::default_type) + { + field_generic(db_field_name, flat_field_name, field_value, field_type); + } + + void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, PT::Date & field_value, FT field_type = FT::default_type) + { + field_generic(db_field_name, flat_field_name, field_value, field_type); + } + + + void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, Model & field_value, FT field_type = FT::default_type) + { + // has_foreign_key was here + field_model(db_field_name, flat_field_name, field_value, field_type); } 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) + void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::list & field_value, FT field_type = FT::default_type) { ModelClass * list_model_null_pointer = nullptr; - field_list(db_field_name, flat_field_name, field_value, list_model_null_pointer, insertable, updatable); + field_list(db_field_name, flat_field_name, field_value, list_model_null_pointer, field_type); } template - void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::vector & field_value, bool insertable = true, bool updatable = true) + void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::vector & field_value, FT field_type = FT::default_type) { ModelClass * list_model_null_pointer = nullptr; - field_list(db_field_name, flat_field_name, field_value, list_model_null_pointer, insertable, updatable); + field_list(db_field_name, flat_field_name, field_value, list_model_null_pointer, field_type); } @@ -470,7 +445,7 @@ protected: template - void field_generic_set_field_value(const wchar_t * db_field_name, const wchar_t * flat_field_name, FieldValue & field_value, bool insertable, bool updatable, bool is_primary_key) + void field_generic_set_field_value(const wchar_t * db_field_name, const wchar_t * flat_field_name, FieldValue & field_value) { if( model_env->field_value_helper_tab ) { @@ -510,9 +485,9 @@ protected: } template - void field_generic_iterate_primary_key_values(const wchar_t * db_field_name, const wchar_t * flat_field_name, FieldValue & field_value, bool insertable, bool updatable, bool is_primary_key) + void field_generic_iterate_primary_key_values(const wchar_t * db_field_name, const wchar_t * flat_field_name, FieldValue & field_value, FT field_type) { - if( is_primary_key ) + if( field_type.is_primary_key() ) { if( model_env->field_value_helper_tab ) { @@ -529,7 +504,7 @@ protected: } template - void field_generic_generate_flat_string(const wchar_t * db_field_name, const wchar_t * flat_field_name, FieldValue & field_value, bool insertable, bool updatable, bool is_primary_key) + void field_generic_generate_flat_string(const wchar_t * db_field_name, const wchar_t * flat_field_name, FieldValue & field_value, FT field_type) { FlatConnector * flat_connector = model_connector->get_flat_connector(); @@ -539,14 +514,13 @@ 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, model_env); + flat_expression->field(flat_field_name, field_value, field_type, model_env); } } } template - void field_generic_generate_db_sql(const wchar_t * db_field_name, const wchar_t * flat_field_name, FieldValue & field_value, bool insertable, bool updatable, bool is_primary_key) + void field_generic_generate_db_sql(const wchar_t * db_field_name, const wchar_t * flat_field_name, FieldValue & field_value, FT field_type) { DbConnector * db_connector = model_connector->get_db_connector(); @@ -556,13 +530,13 @@ protected: if( db_expression && !is_empty_field(db_field_name) ) { - db_expression->field(db_field_name, field_value, insertable, updatable, is_primary_key, model_env); + db_expression->field(db_field_name, field_value, field_type, model_env); } } } template - void field_generic_read_value_from_db_resultset(const wchar_t * db_field_name, const wchar_t * flat_field_name, FieldValue & field_value, bool insertable, bool updatable, bool is_primary_key) + void field_generic_read_value_from_db_resultset(const wchar_t * db_field_name, const wchar_t * flat_field_name, FieldValue & field_value, FT field_type) { DbConnector * db_connector = model_connector->get_db_connector(); @@ -572,19 +546,19 @@ protected: { if( model_env->cursor_helper && model_env->cursor_helper->has_autogenerated_select ) { - get_value_by_field_index(model_env->cursor_helper->current_column, field_value, is_primary_key); + get_value_by_field_index(model_env->cursor_helper->current_column, field_value, field_type); model_env->cursor_helper->current_column += 1; } else { - get_value_by_field_name(db_field_name, field_value, is_primary_key); + get_value_by_field_name(db_field_name, field_value, field_type); } } } } template - void field_generic_clear_value(const wchar_t * db_field_name, const wchar_t * flat_field_name, FieldValue & field_value, bool insertable, bool updatable, bool is_primary_key) + void field_generic_clear_value(const wchar_t * db_field_name, const wchar_t * flat_field_name, FieldValue & field_value, FT field_type) { Clearer * clearer = model_connector->get_clearer(); @@ -596,43 +570,43 @@ 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) + void field_generic(const wchar_t * db_field_name, const wchar_t * flat_field_name, FieldValue & field_value, FT field_type) { if( model_connector && model_env ) { - if( is_primary_key ) + if( field_type.is_primary_key() ) { model_env->was_primary_key_read = true; } if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_SET_FIELD_VALUE ) { - field_generic_set_field_value(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); + field_generic_set_field_value(db_field_name, flat_field_name, field_value); } if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_ITERATE_PRIMARY_KEY_VALUES ) { - field_generic_iterate_primary_key_values(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); + field_generic_iterate_primary_key_values(db_field_name, flat_field_name, field_value, field_type); } if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_GENERATING_FLAT_STRING ) { - field_generic_generate_flat_string(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); + field_generic_generate_flat_string(db_field_name, flat_field_name, field_value, field_type); } if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_GENERATING_DB_SQL ) { - field_generic_generate_db_sql(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); + field_generic_generate_db_sql(db_field_name, flat_field_name, field_value, field_type); } if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_READING_VALUE_FROM_DB_RESULTSET ) { - field_generic_read_value_from_db_resultset(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); + field_generic_read_value_from_db_resultset(db_field_name, flat_field_name, field_value, field_type); } if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_CLEARING_VALUE ) { - field_generic_clear_value(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key); + field_generic_clear_value(db_field_name, flat_field_name, field_value, field_type); } } } @@ -643,7 +617,7 @@ protected: * this is only in a case when has_foreign_key is false, may it can be ignored? we can use unique index in such a case * */ - 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) + void field_model_left_join(const wchar_t * db_field_name, Model & field_model, FT field_type, DbExpression * db_expression) { if( model_env && field_model.model_env && model_env->finder_helper ) { @@ -662,7 +636,7 @@ protected: db_expression->set_output_type(MORM_OUTPUT_TYPE_JOIN_TABLES); db_expression->allow_to_use_prefix(false); - if( has_foreign_key ) + if( field_type.is_foreign_key() ) { field_model.map_fields(); @@ -773,9 +747,17 @@ protected: if( field_model.model_env->table_name.empty() ) field_model.table_name(field_model.model_env->table_name); - (*log) << PT::Log::log1 << "Morm: primary key in " << model_env->table_name << " consists of " << model_env->field_index << " column(s)" - << " but in " << field_model.model_env->table_name << " there are only " - << field_model.model_env->field_index << " matching column(s)" << PT::Log::logend; + if( field_model.model_env->field_index == 0 ) + { + (*log) << PT::Log::log1 << "Morm: there is no a foreign key in " << field_model.model_env->table_name + << " called " << db_field_name << " pointing to " << model_env->table_name << PT::Log::logend; + } + else + { + (*log) << PT::Log::log1 << "Morm: primary key in " << model_env->table_name << " consists of " << model_env->field_index << " column(s)" + << " but foreign key in " << field_model.model_env->table_name << " consists of " + << field_model.model_env->field_index << " column(s)" << PT::Log::logend; + } } field_model.model_env = nullptr; @@ -815,33 +797,30 @@ protected: void field_model_iterate_through_childs(const wchar_t * db_field_name, Model & field_model) { - if( !is_empty_field(db_field_name) ) + if( model_env->model_work_submode == MORM_MODEL_WORK_SUBMODE_INSERT ) { - if( model_env->model_work_submode == MORM_MODEL_WORK_SUBMODE_INSERT ) - { - field_model.insert_tree(true); - } + field_model.insert_tree(true); + } - if( model_env->model_work_submode == MORM_MODEL_WORK_SUBMODE_UPDATE ) - { - field_model.update_tree(true); - } + if( model_env->model_work_submode == MORM_MODEL_WORK_SUBMODE_UPDATE ) + { + field_model.update_tree(true); + } - if( model_env->model_work_submode == MORM_MODEL_WORK_SUBMODE_REMOVE ) - { - field_model.remove_tree(true); - } + if( model_env->model_work_submode == MORM_MODEL_WORK_SUBMODE_REMOVE ) + { + field_model.remove_tree(true); + } - if( model_env->model_work_submode == MORM_MODEL_WORK_SUBMODE_SAVE ) - { - field_model.save_tree(true); - } + if( model_env->model_work_submode == MORM_MODEL_WORK_SUBMODE_SAVE ) + { + field_model.save_tree(true); } } - void field_model_generate_flat_string(const wchar_t * db_field_name, const wchar_t * flat_field_name, Model & field_model, bool insertable, bool updatable) + void field_model_generate_flat_string(const wchar_t * flat_field_name, Model & field_model, FT field_type) { FlatConnector * flat_connector = model_connector->get_flat_connector(); @@ -849,19 +828,19 @@ protected: { FlatExpression * flat_expression = flat_connector->get_expression(); - if( flat_expression && !is_empty_field(flat_field_name) ) + if( flat_expression ) { if( model_env->dump_mode || field_model.save_mode == DO_INSERT_ON_SAVE || field_model.save_mode == DO_UPDATE_ON_SAVE ) { field_model.model_env->model_work_mode = MORM_MODEL_WORK_MODE_GENERATING_FLAT_STRING; - flat_expression->field_model(flat_field_name, field_model, insertable, updatable, false, model_env); + flat_expression->field_model(flat_field_name, field_model, field_type, model_env); } } } } - 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) + void field_model_generate_db_sql(const wchar_t * db_field_name, Model & field_model, FT field_type) { DbConnector * db_connector = model_connector->get_db_connector(); @@ -878,23 +857,23 @@ protected: 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); + field_model_left_join(db_field_name, field_model, field_type, db_expression); } - if( has_foreign_key ) + if( field_type.is_foreign_key() ) { if( db_expression->get_work_mode() == MORM_WORK_MODE_MODEL_FIELDS && db_expression->get_output_type() == MORM_OUTPUT_TYPE_DB_INSERT ) { - if( insertable ) + if( field_type.is_insertable() ) { int not_used_object = 0; - db_expression->field(db_field_name, not_used_object, insertable, updatable, false, model_env); + db_expression->field(db_field_name, not_used_object, field_type, model_env); } } if( db_expression->get_work_mode() == MORM_WORK_MODE_MODEL_VALUES && db_expression->get_output_type() == MORM_OUTPUT_TYPE_DB_INSERT ) { - if( insertable ) + if( field_type.is_insertable() ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_DB_INSERT_PRIMARY_KEY); field_model.map_fields(); @@ -904,7 +883,7 @@ protected: if( db_expression->get_work_mode() == MORM_WORK_MODE_MODEL_FIELDS_VALUES && db_expression->get_output_type() == MORM_OUTPUT_TYPE_DB_UPDATE ) { - if( updatable ) + if( field_type.is_updatable() ) { std::vector key_fields; key_fields.push_back(db_field_name); // at the moment only one key @@ -939,7 +918,7 @@ protected: } - 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) + void field_model_clear_values(Model & field_model) { Clearer * clearer = model_connector->get_clearer(); @@ -950,38 +929,36 @@ protected: } - 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) + void field_model_read_values_from_queryresult(const wchar_t * db_field_name, Model & field_model, FT field_type) { DbConnector * db_connector = model_connector->get_db_connector(); if( db_connector ) { - if( !is_empty_field(db_field_name) ) + DbExpression * db_expression = db_connector->get_expression(); + + if( db_expression ) { - DbExpression * db_expression = db_connector->get_expression(); - - if( db_expression ) + if( model_env->cursor_helper && + !model_env->cursor_helper->has_autogenerated_select && + model_env->cursor_helper->use_table_prefix_for_fetching_values ) { - if( model_env->cursor_helper && - !model_env->cursor_helper->has_autogenerated_select && - model_env->cursor_helper->use_table_prefix_for_fetching_values ) - { - field_model.prepare_table_names(); - } + field_model.prepare_table_names(); + } - field_model.before_select(); - field_model.map_values_from_query(); + field_model.before_select(); + field_model.map_values_from_query(); - if( field_model.found() ) - { - field_model.after_select(); - } + if( field_model.found() ) + { + 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) + + void field_model(const wchar_t * db_field_name, const wchar_t * flat_field_name, Model & field_model, FT field_type) { if( model_connector && model_env ) { @@ -992,48 +969,35 @@ protected: field_model.model_env->has_primary_key_set = field_model.has_primary_key_set; field_model.set_connector(model_connector); - if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_SET_PARENT_ID ) + if( !is_empty_field(db_field_name) ) { - if( !has_foreign_key ) + if( field_type.is_foreign_key() || field_type.is_foreign_key_in_child() ) { - field_model_set_parent_key(db_field_name, field_model); + field_model_for_db(db_field_name, field_model, field_type); + } + else + { + PT::Log * plog = model_connector->get_logger(); + + if( plog ) + { + (*plog) << "Morm: error in " << log_table_name(db_field_name) + << " field, you should set FT::is_foreign_key or FT::is_foreign_key_in_child flag for a model child object" << PT::Log::logend; + } } } - if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_ITERATE_THROUGH_CHILDS_WITH_FOREIGN_KEY ) + if( !is_empty_field(flat_field_name) ) { - if( has_foreign_key ) + if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_GENERATING_FLAT_STRING ) { - field_model_iterate_through_childs(db_field_name, field_model); + field_model_generate_flat_string(flat_field_name, field_model, field_type); } } - if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_ITERATE_THROUGH_CHILDS_WITHOUT_FOREIGN_KEY ) - { - if( !has_foreign_key ) - { - field_model_iterate_through_childs(db_field_name, field_model); - } - } - - if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_GENERATING_FLAT_STRING ) - { - field_model_generate_flat_string(db_field_name, flat_field_name, field_model, insertable, updatable); - } - - if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_GENERATING_DB_SQL ) - { - field_model_generate_db_sql(db_field_name, flat_field_name, field_model, insertable, updatable, has_foreign_key); - } - if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_CLEARING_VALUE ) { - field_model_clear_values(db_field_name, flat_field_name, field_model, insertable, updatable, has_foreign_key); - } - - if( model_env->model_work_mode == MORM_MODEL_WORK_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_clear_values(field_model); } field_model.model_env = nullptr; @@ -1041,6 +1005,45 @@ protected: } + void field_model_for_db(const wchar_t * db_field_name, Model & field_model, FT field_type) + { + if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_SET_PARENT_ID ) + { + if( field_type.is_foreign_key_in_child() ) + { + field_model_set_parent_key(db_field_name, field_model); + } + } + + if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_ITERATE_THROUGH_CHILDS_WITH_FOREIGN_KEY ) + { + if( field_type.is_foreign_key() ) + { + field_model_iterate_through_childs(db_field_name, field_model); + } + } + + if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_ITERATE_THROUGH_CHILDS_WITHOUT_FOREIGN_KEY ) + { + if( field_type.is_foreign_key_in_child() ) + { + field_model_iterate_through_childs(db_field_name, field_model); + } + } + + if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_GENERATING_DB_SQL ) + { + field_model_generate_db_sql(db_field_name, field_model, field_type); + } + + + if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_READING_VALUE_FROM_DB_RESULTSET ) + { + field_model_read_values_from_queryresult(db_field_name, field_model, field_type); + } + } + + template void field_list_set_parent_key(const wchar_t * db_field_name, ModelContainer & field_container, ModelContainerType * model_container_type) { @@ -1069,46 +1072,42 @@ protected: template void field_list_iterate_through_childs(const wchar_t * db_field_name, ModelContainer & field_container, ModelContainerType * model_container_type) { - if( !is_empty_field(db_field_name) ) + for(ModelContainerType & child_model : field_container) { - for(ModelContainerType & child_model : field_container) + ModelEnv model_env_local; + model_env_local.copy_global_objects(*model_env); + + child_model.model_env = &model_env_local; + child_model.model_env->has_primary_key_set = child_model.has_primary_key_set; + child_model.set_connector(model_connector); + + if( model_env->model_work_submode == MORM_MODEL_WORK_SUBMODE_INSERT ) { - ModelEnv model_env_local; - model_env_local.copy_global_objects(*model_env); - - child_model.model_env = &model_env_local; - child_model.model_env->has_primary_key_set = child_model.has_primary_key_set; - child_model.set_connector(model_connector); - - if( model_env->model_work_submode == MORM_MODEL_WORK_SUBMODE_INSERT ) - { - child_model.insert_tree(true); - } - - if( model_env->model_work_submode == MORM_MODEL_WORK_SUBMODE_UPDATE ) - { - child_model.update_tree(true); - } - - if( model_env->model_work_submode == MORM_MODEL_WORK_SUBMODE_REMOVE ) - { - child_model.remove_tree(true); - } - - if( model_env->model_work_submode == MORM_MODEL_WORK_SUBMODE_SAVE ) - { - child_model.save_tree(true); - } - - child_model.model_env = nullptr; + child_model.insert_tree(true); } - } + if( model_env->model_work_submode == MORM_MODEL_WORK_SUBMODE_UPDATE ) + { + child_model.update_tree(true); + } + + if( model_env->model_work_submode == MORM_MODEL_WORK_SUBMODE_REMOVE ) + { + child_model.remove_tree(true); + } + + if( model_env->model_work_submode == MORM_MODEL_WORK_SUBMODE_SAVE ) + { + child_model.save_tree(true); + } + + child_model.model_env = nullptr; + } } template - void field_list_generate_flat_string(const wchar_t * flat_field_name, ModelContainer & field_container, bool insertable, bool updatable) + void field_list_generate_flat_string(const wchar_t * flat_field_name, ModelContainer & field_container, FT field_type) { FlatConnector * flat_connector = model_connector->get_flat_connector(); @@ -1116,10 +1115,9 @@ protected: { FlatExpression * flat_expression = flat_connector->get_expression(); - if( flat_expression && !is_empty_field(flat_field_name) ) + if( flat_expression ) { - // insertable and updatable will be ignored there - flat_expression->field_list(flat_field_name, field_container, insertable, updatable, false, model_connector, model_env); + flat_expression->field_list(flat_field_name, field_container, field_type, model_connector, model_env); } } } @@ -1138,38 +1136,66 @@ 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) + void field_list(const wchar_t * db_field_name, const wchar_t * flat_field_name, ModelContainer & field_container, ModelContainerType * model_container_type, FT field_type) { if( model_connector && model_env ) { + PT::Log * plog = model_connector->get_logger(); + if( !is_empty_field(db_field_name) ) { - if constexpr (std::is_base_of()) + /* + * IMPROVEME + * field_type.is_foreign_key() is not implemented for lists yet + * (in such a case parent will point only to one object (or none) so the list will consists of only one object (or none)) + */ + if( field_type.is_foreign_key() ) { - if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_SET_PARENT_ID ) + if( plog ) { - field_list_set_parent_key(db_field_name, field_container, model_container_type); + (*plog) << "Morm: error: FT::is_foreign_key is not implemented for a list/vector yet" << PT::Log::logend; + return; } + } - if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_ITERATE_THROUGH_CHILDS_WITHOUT_FOREIGN_KEY ) + if( field_type.is_foreign_key() || field_type.is_foreign_key_in_child() ) + { + if constexpr (std::is_base_of()) { - field_list_iterate_through_childs(db_field_name, field_container, model_container_type); + if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_SET_PARENT_ID ) + { + field_list_set_parent_key(db_field_name, field_container, model_container_type); + } + + if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_ITERATE_THROUGH_CHILDS_WITHOUT_FOREIGN_KEY ) + { + field_list_iterate_through_childs(db_field_name, field_container, model_container_type); + } + } + else + { + if( plog ) + { + (*plog) << "Morm: ignoring " << log_table_name(db_field_name) << " as this is not a container with Model objects" << PT::Log::logend; + } } } else { - PT::Log * plog = model_connector->get_logger(); - if( plog ) { - (*plog) << "Morm: ignoring " << db_field_name << " as this is not a container with Model objects" << PT::Log::logend; + (*plog) << "Morm: error in " << log_table_name(db_field_name) + << " field, you should set FT::is_foreign_key or FT::is_foreign_key_in_child flag for a list of child objects" << PT::Log::logend; } } } - if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_GENERATING_FLAT_STRING ) + if( !is_empty_field(flat_field_name) ) { - field_list_generate_flat_string(flat_field_name, field_container, insertable, updatable); + if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_GENERATING_FLAT_STRING ) + { + field_list_generate_flat_string(flat_field_name, field_container, field_type); + } } if( model_env->model_work_mode == MORM_MODEL_WORK_MODE_CLEARING_VALUE ) @@ -1181,7 +1207,7 @@ protected: template - void get_value_by_field_index(int field_index, FieldValue & field_value, bool is_primary_key) + void get_value_by_field_index(int field_index, FieldValue & field_value, FT field_type) { DbConnector * db_connector = model_connector->get_db_connector(); @@ -1198,7 +1224,7 @@ protected: } else { - if( is_primary_key ) + if( field_type.is_primary_key() ) { model_env->has_primary_key_set = false; } @@ -1208,7 +1234,7 @@ protected: template - void get_value_by_field_name(const wchar_t * field_name, FieldValue & field_value, bool is_primary_key) + void get_value_by_field_name(const wchar_t * field_name, FieldValue & field_value, FT field_type) { DbConnector * db_connector = model_connector->get_db_connector(); @@ -1245,7 +1271,7 @@ protected: } else { - if( is_primary_key ) + if( field_type.is_primary_key() ) { model_env->has_primary_key_set = false; } @@ -1345,10 +1371,13 @@ protected: virtual void prepare_table_names(bool prepare_table_index = true); virtual void put_table_name_with_index(PT::TextStream & str); - virtual void put_to_log(const wchar_t * str); virtual void put_fields_to_log(PT::Log & log, const wchar_t * db_field_name, const wchar_t * flat_field_name); + PT::TextStream log_table_name(); + PT::TextStream log_table_name(const wchar_t * db_field_name); + + template friend class Finder; template friend class Cursor; friend class BaseExpression; diff --git a/src/modelenv.h b/src/modelenv.h index 9cdca98..8b5945d 100644 --- a/src/modelenv.h +++ b/src/modelenv.h @@ -46,6 +46,8 @@ namespace morm { + + class ModelEnv { public: