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
This commit is contained in:
2019-05-13 17:59:28 +00:00
parent 34ddf11351
commit b37a577713
9 changed files with 441 additions and 237 deletions

View File

@@ -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<typename FieldValue>
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<typename FieldValue>
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<typename FieldValue>
void doc_field_generic(const wchar_t * db_field_name, const wchar_t * flat_field_name, FieldValue & field_value)
{
if( reinterpret_cast<const void*>(&field_value) == doc_field_pointer && model_connector )
if( reinterpret_cast<const void*>(&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<const void*>(&field_model) == doc_field_pointer && model_connector )
if( reinterpret_cast<const void*>(&field_model) == model_env->doc_field_pointer && model_connector )
{
FlatConnector * doc_connector = model_connector->get_doc_connector();
@@ -1074,7 +1120,7 @@ protected:
template<typename ModelContainer>
void doc_field_list(const wchar_t * db_field_name, const wchar_t * flat_field_name, ModelContainer & field_container)
{
if( reinterpret_cast<const void*>(&field_container) == doc_field_pointer && model_connector )
if( reinterpret_cast<const void*>(&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<typename ModelClass> friend class Finder;
template<typename ModelClass> friend class Finder;
template<typename ModelClass> friend class Cursor;
friend class BaseExpression;