From 2ad6c8c258ac8e9818d2bfc9d174ffdaae6fdf0c Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Thu, 13 May 2021 02:32:03 +0200 Subject: [PATCH] changed the way how to quote schemas, tables and field names, added escaping table names in insert/update/remove removed methods from BaseExpression: virtual void before_short_field_name(); virtual void after_short_field_name(); virtual void before_first_part_long_field_name(); virtual void after_first_part_long_field_name(); virtual void before_second_part_long_field_name(); virtual void after_second_part_long_field_name(); added methods to BaseExpression: virtual void schema_table_separator(); virtual void table_field_separator(); virtual void before_schema_name(); virtual void after_schema_name(); virtual void before_table_name(); virtual void after_table_name(); virtual void before_field_name(); virtual void after_field_name(); --- src/baseexpression.cpp | 117 +++++++++++++++++++++++------------ src/baseexpression.h | 27 ++++---- src/dbconnector.cpp | 12 ++-- src/dbexpression.cpp | 48 ++++++++++++++ src/dbexpression.h | 12 ++++ src/jsonexpression.cpp | 21 +------ src/jsonexpression.h | 8 +-- src/model.cpp | 94 +++++++++++++++------------- src/model.h | 17 +++-- src/postgresqlexpression.cpp | 37 ----------- src/postgresqlexpression.h | 6 -- 11 files changed, 222 insertions(+), 177 deletions(-) diff --git a/src/baseexpression.cpp b/src/baseexpression.cpp index d022615..2e2ff62 100644 --- a/src/baseexpression.cpp +++ b/src/baseexpression.cpp @@ -192,11 +192,9 @@ void BaseExpression::put_field_name(const wchar_t * field_name, const FT & field } else { - // !!!!!!!!!!!!!!!!!!! - // there are too many methods: before... after... - before_short_field_name(); + before_field_name(); esc(field_name, *out_stream); - after_short_field_name(); + after_field_name(); } } @@ -219,36 +217,47 @@ void BaseExpression::save_foreign_key(const wchar_t * field_name, const FT & fie } -void BaseExpression::before_short_field_name() + +void BaseExpression::schema_table_separator() { } -void BaseExpression::after_short_field_name() +void BaseExpression::table_field_separator() { } -void BaseExpression::before_first_part_long_field_name() + +void BaseExpression::before_schema_name() { } -void BaseExpression::after_first_part_long_field_name() +void BaseExpression::after_schema_name() { } -void BaseExpression::before_second_part_long_field_name() +void BaseExpression::before_table_name() { } -void BaseExpression::after_second_part_long_field_name() +void BaseExpression::after_table_name() { } +void BaseExpression::before_field_name() +{ +} + + +void BaseExpression::after_field_name() +{ +} + void BaseExpression::before_field_value(const std::wstring &, const FT & field_type) { @@ -690,36 +699,63 @@ void BaseExpression::after_field_value_string(const FT & field_type) } +/* + * schema_name can be a null pointer or just pointing to an empty string + * in such a case we do not put the schema name + */ void BaseExpression::put_schema_table(const wchar_t * schema_name, const wchar_t * table_name) { if( out_stream ) { - before_first_part_long_field_name(); - esc(schema_name, *out_stream); - after_first_part_long_field_name(); + bool has_schema = false; - (*out_stream) << '.'; + if( !is_empty_field(schema_name) ) + { + has_schema = true; + before_schema_name(); + esc(schema_name, *out_stream); + after_schema_name(); + } - before_second_part_long_field_name(); - esc(table_name, *out_stream); - after_second_part_long_field_name(); + if( !is_empty_field(table_name) ) + { + if( has_schema ) + schema_table_separator(); + + before_table_name(); + esc(table_name, *out_stream); + after_table_name(); + } } } +/* + * schema_name can be empty - in such a case we do not put the schema name + */ void BaseExpression::put_schema_table(const PT::WTextStream & schema_name, const PT::WTextStream & table_name) { if( out_stream ) { - before_first_part_long_field_name(); - esc(schema_name, *out_stream); - after_first_part_long_field_name(); + bool has_schema = false; - (*out_stream) << '.'; + if( !schema_name.empty() ) + { + has_schema = true; + before_schema_name(); + esc(schema_name, *out_stream); + after_schema_name(); + } - before_second_part_long_field_name(); - esc(table_name, *out_stream); - after_second_part_long_field_name(); + if( !table_name.empty() ) + { + if( has_schema ) + schema_table_separator(); + + before_table_name(); + esc(table_name, *out_stream); + after_table_name(); + } } } @@ -728,9 +764,9 @@ void BaseExpression::put_table(const wchar_t * table_name) { if( out_stream ) { - before_short_field_name(); + before_table_name(); esc(table_name, *out_stream); - after_short_field_name(); + after_table_name(); } } @@ -739,9 +775,9 @@ void BaseExpression::put_table(const PT::WTextStream & table_name) { if( out_stream ) { - before_short_field_name(); + before_table_name(); esc(table_name, *out_stream); - after_short_field_name(); + after_table_name(); } } @@ -750,7 +786,7 @@ void BaseExpression::put_table_with_index(const wchar_t * table_name, int index) { if( out_stream ) { - before_short_field_name(); + before_table_name(); esc(table_name, *out_stream); if( index > 1 ) @@ -758,7 +794,7 @@ void BaseExpression::put_table_with_index(const wchar_t * table_name, int index) (*out_stream) << index; } - after_short_field_name(); + after_table_name(); } } @@ -767,7 +803,7 @@ void BaseExpression::put_table_with_index(const PT::WTextStream & table_name, in { if( out_stream ) { - before_short_field_name(); + before_table_name(); esc(table_name, *out_stream); if( index > 1 ) @@ -775,7 +811,7 @@ void BaseExpression::put_table_with_index(const PT::WTextStream & table_name, in (*out_stream) << index; } - after_short_field_name(); + after_table_name(); } } @@ -785,10 +821,7 @@ void BaseExpression::put_table_with_index_and_field(const wchar_t * table_name, if( out_stream ) { put_table_with_index(table_name, index); - (*out_stream) << '.'; - - // IMPROVE ME - // put_field_name seems to be too complicated, it is needed to check there whether field_name is long or short? + table_field_separator(); put_field_name(field_name, field_type, nullptr); } } @@ -798,7 +831,7 @@ void BaseExpression::put_table_with_index_and_field(const PT::WTextStream & tabl if( out_stream ) { put_table_with_index(table_name, index); - (*out_stream) << '.'; + table_field_separator(); put_field_name(field_name, field_type, nullptr); } } @@ -809,7 +842,7 @@ void BaseExpression::put_table_and_field(const wchar_t * table_name, const wchar if( out_stream ) { put_table(table_name); - (*out_stream) << '.'; + table_field_separator(); put_field_name(field_name, field_type, nullptr); } } @@ -819,7 +852,7 @@ void BaseExpression::put_table_and_field(const PT::WTextStream & table_name, con if( out_stream ) { put_table(table_name); - (*out_stream) << '.'; + table_field_separator(); put_field_name(field_name, field_type, nullptr); } } @@ -907,5 +940,11 @@ void BaseExpression::table_and_field_to_stream(PT::TextStream & stream, const PT +bool BaseExpression::is_empty_field(const wchar_t * value) +{ + return (!value || *value == '\0'); +} + + } diff --git a/src/baseexpression.h b/src/baseexpression.h index 1d42d64..d29f2d8 100644 --- a/src/baseexpression.h +++ b/src/baseexpression.h @@ -614,22 +614,18 @@ protected: } - /* - * escaping column names in a case when using short form - just only column_name - * [before_short_field_name]column_name[after_short_field_name] - */ - virtual void before_short_field_name(); - virtual void after_short_field_name(); + virtual void schema_table_separator(); + virtual void table_field_separator(); + + virtual void before_schema_name(); + virtual void after_schema_name(); + + virtual void before_table_name(); + virtual void after_table_name(); + + virtual void before_field_name(); + virtual void after_field_name(); - /* - * escaping column names in a case when using long form: table_name.column_name - * [before_first_part_long_field_name]table_name[after_first_part_long_field_name].[before_second_part_long_field_name]column_name[after_second_part_long_field_name] - * - */ - virtual void before_first_part_long_field_name(); - virtual void after_first_part_long_field_name(); - virtual void before_second_part_long_field_name(); - virtual void after_second_part_long_field_name(); virtual void before_field_value(const std::wstring &, const FT & field_type); virtual void after_field_value(const std::wstring &, const FT & field_type); @@ -721,6 +717,7 @@ protected: void esc(const wchar_t * val, bool has_known_length, size_t len, PT::TextStream & stream, const FT & field_type = FT::default_type); + bool is_empty_field(const wchar_t * value); }; } diff --git a/src/dbconnector.cpp b/src/dbconnector.cpp index 6ec2cab..8c74396 100644 --- a/src/dbconnector.cpp +++ b/src/dbconnector.cpp @@ -183,8 +183,8 @@ void DbConnector::generate_insert_query(PT::TextStream & stream, Model & model) db_expression->clear(); db_expression->allow_to_use_prefix(false); - // IMPROVEME escape table_name - stream << "insert into " << model.get_table_name(); + stream << "insert into "; + db_expression->schema_table_to_stream(stream, model.model_env->schema_name, model.model_env->table_name); stream << " ("; db_expression->set_work_mode(MORM_WORK_MODE_MODEL_FIELDS); @@ -208,8 +208,8 @@ void DbConnector::generate_update_query(PT::TextStream & stream, Model & model) db_expression->clear(); db_expression->allow_to_use_prefix(false); - // IMPROVEME escape table_name - stream << "update " << model.get_table_name(); + stream << "update "; + db_expression->schema_table_to_stream(stream, model.model_env->schema_name, model.model_env->table_name); stream << " set "; db_expression->set_work_mode(MORM_WORK_MODE_MODEL_FIELDS_VALUES); @@ -233,8 +233,8 @@ void DbConnector::generate_remove_query(PT::TextStream & stream, Model & model) db_expression->clear(); db_expression->allow_to_use_prefix(false); - // IMPROVEME escape table_name - stream << "delete from " << model.get_table_name(); + stream << "delete from "; + db_expression->schema_table_to_stream(stream, model.model_env->schema_name, model.model_env->table_name); stream << " where "; db_expression->set_work_mode(MORM_WORK_MODE_MODEL_FIELDS_VALUES); diff --git a/src/dbexpression.cpp b/src/dbexpression.cpp index 913d321..c7b08db 100644 --- a/src/dbexpression.cpp +++ b/src/dbexpression.cpp @@ -182,6 +182,54 @@ void DbExpression::put_name_value_separator() } +void DbExpression::schema_table_separator() +{ + (*out_stream) << '.'; +} + + +void DbExpression::table_field_separator() +{ + (*out_stream) << '.'; +} + + +void DbExpression::before_schema_name() +{ + (*out_stream) << '"'; +} + + +void DbExpression::after_schema_name() +{ + (*out_stream) << '"'; +} + + +void DbExpression::before_table_name() +{ + (*out_stream) << '"'; +} + + +void DbExpression::after_table_name() +{ + (*out_stream) << '"'; +} + + +void DbExpression::before_field_name() +{ + (*out_stream) << '"'; +} + + +void DbExpression::after_field_name() +{ + (*out_stream) << '"'; +} + + void DbExpression::before_field_value_string(const FT & field_type) { diff --git a/src/dbexpression.h b/src/dbexpression.h index c09d579..81b1636 100644 --- a/src/dbexpression.h +++ b/src/dbexpression.h @@ -85,6 +85,18 @@ protected: void field_before(); void put_name_value_separator(); + void schema_table_separator(); + void table_field_separator(); + + void before_schema_name(); + void after_schema_name(); + + void before_table_name(); + void after_table_name(); + + void before_field_name(); + void after_field_name(); + private: diff --git a/src/jsonexpression.cpp b/src/jsonexpression.cpp index bb15a4f..6648df0 100644 --- a/src/jsonexpression.cpp +++ b/src/jsonexpression.cpp @@ -76,33 +76,16 @@ void JSONExpression::field_before() -void JSONExpression::before_short_field_name() +void JSONExpression::before_field_name() { (*out_stream) << "\""; } -void JSONExpression::after_short_field_name() +void JSONExpression::after_field_name() { (*out_stream) << "\""; } -void JSONExpression::before_first_part_long_field_name() -{ - (*out_stream) << "\""; -} - -void JSONExpression::after_first_part_long_field_name() -{ -} - -void JSONExpression::before_second_part_long_field_name() -{ -} - -void JSONExpression::after_second_part_long_field_name() -{ - (*out_stream) << "\""; -} void JSONExpression::before_field_value_string(const FT & field_type) diff --git a/src/jsonexpression.h b/src/jsonexpression.h index ebe7352..3ef6ab8 100644 --- a/src/jsonexpression.h +++ b/src/jsonexpression.h @@ -54,12 +54,8 @@ protected: void field_before(); - void before_short_field_name(); - void after_short_field_name(); - void before_first_part_long_field_name(); - void after_first_part_long_field_name(); - void before_second_part_long_field_name(); - void after_second_part_long_field_name(); + void before_field_name(); + void after_field_name(); void put_name_value_separator(); diff --git a/src/model.cpp b/src/model.cpp index efe3f58..6bca2d6 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -907,56 +907,54 @@ bool Model::is_the_same_field(const wchar_t * field1, const wchar_t * field2) -PT::WTextStream Model::get_table_name(bool put_schema_name) +void Model::log_table_name(bool put_schema_name) { - PT::WTextStream str; - - if( model_env ) + if( model_connector && model_env ) { - if( put_schema_name && !model_env->schema_name.empty() ) + PT::Log * plog = model_connector->get_logger(); + + if( plog ) { - str << model_env->schema_name; + if( put_schema_name && !model_env->schema_name.empty() ) + { + (*plog) << model_env->schema_name; - // IMPROVEME make a virtual method in dbexpression to put such a dot - str << '.'; + // although in BaseExpression there is schema_table_separator() method + // but for logging purposes we can use just a dot here + (*plog) << '.'; + } + + (*plog) << model_env->table_name; } - - str << model_env->table_name; } - - return str; } -PT::WTextStream Model::get_table_name_with_field(const wchar_t * db_field_name, bool put_schema_name) +void Model::log_table_name_with_field(const wchar_t * db_field_name, bool put_schema_name) { - PT::WTextStream str; - bool is_empty_field_name = is_empty_field(db_field_name); - - if( model_env ) + if( model_connector && model_env ) { - if( put_schema_name && !model_env->schema_name.empty() ) + PT::Log * plog = model_connector->get_logger(); + + if( plog ) { - str << model_env->schema_name; + bool is_empty_field_name = is_empty_field(db_field_name); - // IMPROVEME make a virtual method in dbexpression to put such a dot - str << '.'; - } + if( put_schema_name && !model_env->schema_name.empty() ) + { + (*plog) << model_env->schema_name; + (*plog) << '.'; + } - str << model_env->table_name; + (*plog) << model_env->table_name; - if( !is_empty_field_name ) - { - str << '.'; // IMPROVEME get a virtual method from dbexpression + if( !is_empty_field_name ) + { + (*plog) << '.'; + (*plog) << db_field_name; + } } } - - if( !is_empty_field_name ) - { - str << db_field_name; - } - - return str; } @@ -1099,7 +1097,9 @@ void Model::field_model_save_key(const wchar_t * db_field_name) if( model_env->field_value_helper_tab->empty() && plog ) { - (*plog) << PT::Log::log1 << "Morm: I cannot find a primary key in " << get_table_name() << PT::Log::logend; + (*plog) << PT::Log::log1 << "Morm: I cannot find a primary key in "; + log_table_name(); + (*plog) << PT::Log::logend; } } } @@ -1139,14 +1139,19 @@ void Model::field_model_set_parent_key_in_child(const wchar_t * db_field_name, M { if( field_model.model_env->field_index == 0 ) { - (*log) << PT::Log::log1 << "Morm: there is no a foreign key in " << field_model.get_table_name() - << " called " << db_field_name << " pointing to " << get_table_name() << PT::Log::logend; + (*log) << PT::Log::log1 << "Morm: there is no a foreign key in "; + field_model.log_table_name(); + (*log) << " called " << db_field_name << " pointing to "; + log_table_name(); + (*log) << PT::Log::logend; } else { - (*log) << PT::Log::log1 << "Morm: primary key in " << get_table_name() << " consists of " << model_env->field_index << " column(s)" - << " but foreign key in " << field_model.get_table_name() << " consists of " - << field_model.model_env->field_index << " column(s)" << PT::Log::logend; + (*log) << PT::Log::log1 << "Morm: primary key in "; + log_table_name(); + (*log) << " consists of " << model_env->field_index << " column(s) but foreign key in "; + field_model.log_table_name(); + (*log) << " consists of " << field_model.model_env->field_index << " column(s)" << PT::Log::logend; } } @@ -1155,8 +1160,10 @@ void Model::field_model_set_parent_key_in_child(const wchar_t * db_field_name, M else if( log ) { - (*log) << PT::Log::log1 << "Morm: primary key in " << get_table_name() << " consists of incorrect number of columns" - << ", expected " << helper_tab.size() << " column(s) but got " << model_env->field_index << PT::Log::logend; + (*log) << PT::Log::log1 << "Morm: primary key in "; + log_table_name(); + (*log) << " consists of incorrect number of columns, expected " << helper_tab.size() + << " column(s) but got " << model_env->field_index << PT::Log::logend; } } } @@ -1368,8 +1375,9 @@ void Model::field_model(const wchar_t * db_field_name, const wchar_t * flat_fiel if( plog ) { - (*plog) << PT::Log::log1 << "Morm: error in " << get_table_name_with_field(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; + (*plog) << PT::Log::log1 << "Morm: error in "; + log_table_name_with_field(db_field_name); + (*plog) << " field, you should set FT::is_foreign_key or FT::is_foreign_key_in_child flag for a model child object" << PT::Log::logend; } } } diff --git a/src/model.h b/src/model.h index bd7472e..9a5dadd 100644 --- a/src/model.h +++ b/src/model.h @@ -484,7 +484,9 @@ protected: { if( log ) { - (*log) << PT::Log::log1 << "Morm: incorrect type of a field in " << get_table_name() << ", "; + (*log) << PT::Log::log1 << "Morm: incorrect type of a field in "; + log_table_name(); + (*log) << ", "; put_fields_to_log(*log, db_field_name, flat_field_name); (*log) << ", type expected " << typeid(field_value).name() << " got " << helper.value_type_info->name() << PT::Log::logend; @@ -778,7 +780,9 @@ protected: { if( plog ) { - (*plog) << PT::Log::log1 << "Morm: ignoring " << get_table_name_with_field(db_field_name) << " as this is not a container with Model objects" << PT::Log::logend; + (*plog) << PT::Log::log1 << "Morm: ignoring "; + log_table_name_with_field(db_field_name); + (*plog) << " as this is not a container with Model objects" << PT::Log::logend; } } } @@ -786,8 +790,9 @@ protected: { if( plog ) { - (*plog) << PT::Log::log1 << "Morm: error in " << get_table_name_with_field(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; + (*plog) << PT::Log::log1 << "Morm: error in "; + log_table_name_with_field(db_field_name); + (*plog) << " 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; } } } @@ -969,8 +974,8 @@ protected: 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); - virtual PT::WTextStream get_table_name(bool put_schema_name = true); - virtual PT::WTextStream get_table_name_with_field(const wchar_t * db_field_name = nullptr, bool put_schema_name = true); + virtual void log_table_name(bool put_schema_name = true); + virtual void log_table_name_with_field(const wchar_t * db_field_name = nullptr, bool put_schema_name = true); template friend class Finder; template friend class Cursor; diff --git a/src/postgresqlexpression.cpp b/src/postgresqlexpression.cpp index 90b9cf8..4aaa3f7 100644 --- a/src/postgresqlexpression.cpp +++ b/src/postgresqlexpression.cpp @@ -39,43 +39,6 @@ namespace morm { -void PostgreSQLExpression::before_short_field_name() -{ - (*out_stream) << '"'; -} - -void PostgreSQLExpression::after_short_field_name() -{ - (*out_stream) << '"'; -} - - - -void PostgreSQLExpression::before_first_part_long_field_name() -{ - (*out_stream) << '"'; -} - - -void PostgreSQLExpression::after_first_part_long_field_name() -{ - (*out_stream) << '"'; -} - - -void PostgreSQLExpression::before_second_part_long_field_name() -{ - (*out_stream) << '"'; -} - - -void PostgreSQLExpression::after_second_part_long_field_name() -{ - (*out_stream) << '"'; -} - - - void PostgreSQLExpression::before_field_value_string(const FT & field_type) { diff --git a/src/postgresqlexpression.h b/src/postgresqlexpression.h index fc76a1a..0001171 100644 --- a/src/postgresqlexpression.h +++ b/src/postgresqlexpression.h @@ -53,13 +53,7 @@ public: protected: - virtual void before_short_field_name(); - virtual void after_short_field_name(); - virtual void before_first_part_long_field_name(); - virtual void after_first_part_long_field_name(); - virtual void before_second_part_long_field_name(); - virtual void after_second_part_long_field_name(); private: