merge from branches/join_models
(added possibility to fetch Model objects when they are used as a field in a Model class) git-svn-id: svn://ttmath.org/publicrep/morm/trunk@1196 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
commit
0a324a38ce
|
@ -6,11 +6,12 @@ baseexpression.o: ../../pikotools/textstream/types.h
|
|||
baseexpression.o: ../../pikotools/date/date.h
|
||||
baseexpression.o: ../../pikotools/convert/inttostr.h
|
||||
baseexpression.o: ../../pikotools/membuffer/membuffer.h
|
||||
baseexpression.o: ../../pikotools/textstream/types.h morm_types.h model.h
|
||||
baseexpression.o: modelconnector.h clearer.h dbconnector.h
|
||||
baseexpression.o: ../../pikotools/textstream/types.h morm_types.h modelenv.h
|
||||
baseexpression.o: modeldata.h cursorhelper.h queryresult.h finderhelper.h
|
||||
baseexpression.o: model.h modelconnector.h clearer.h dbconnector.h
|
||||
baseexpression.o: ../../pikotools/log/log.h ../../pikotools/log/filelog.h
|
||||
baseexpression.o: queryresult.h flatconnector.h dbexpression.h
|
||||
baseexpression.o: flatexpression.h modeldata.h ../../pikotools/utf8/utf8.h
|
||||
baseexpression.o: flatconnector.h dbexpression.h flatexpression.h
|
||||
baseexpression.o: ../../pikotools/utf8/utf8.h
|
||||
clearer.o: clearer.h ../../pikotools/date/date.h
|
||||
clearer.o: ../../pikotools/convert/inttostr.h model.h
|
||||
clearer.o: ../../pikotools/textstream/textstream.h
|
||||
|
@ -19,7 +20,8 @@ clearer.o: ../../pikotools/membuffer/membuffer.h
|
|||
clearer.o: ../../pikotools/textstream/types.h modelconnector.h dbconnector.h
|
||||
clearer.o: ../../pikotools/log/log.h ../../pikotools/log/filelog.h
|
||||
clearer.o: queryresult.h flatconnector.h dbexpression.h baseexpression.h
|
||||
clearer.o: morm_types.h flatexpression.h modeldata.h
|
||||
clearer.o: morm_types.h modelenv.h modeldata.h cursorhelper.h finderhelper.h
|
||||
clearer.o: flatexpression.h
|
||||
dbconnector.o: dbconnector.h ../../pikotools/textstream/textstream.h
|
||||
dbconnector.o: ../../pikotools/space/space.h
|
||||
dbconnector.o: ../../pikotools/textstream/types.h ../../pikotools/date/date.h
|
||||
|
@ -27,8 +29,9 @@ dbconnector.o: ../../pikotools/convert/inttostr.h
|
|||
dbconnector.o: ../../pikotools/membuffer/membuffer.h
|
||||
dbconnector.o: ../../pikotools/textstream/types.h ../../pikotools/log/log.h
|
||||
dbconnector.o: ../../pikotools/log/filelog.h queryresult.h dbexpression.h
|
||||
dbconnector.o: baseexpression.h morm_types.h model.h modelconnector.h
|
||||
dbconnector.o: clearer.h flatconnector.h flatexpression.h modeldata.h
|
||||
dbconnector.o: baseexpression.h morm_types.h modelenv.h modeldata.h
|
||||
dbconnector.o: cursorhelper.h finderhelper.h model.h modelconnector.h
|
||||
dbconnector.o: clearer.h flatconnector.h flatexpression.h
|
||||
dbconnector.o: ../../pikotools/utf8/utf8.h ../../pikotools/convert/convert.h
|
||||
dbconnector.o: ../../pikotools/convert/inttostr.h
|
||||
dbconnector.o: ../../pikotools/convert/patternreplacer.h
|
||||
|
@ -41,7 +44,8 @@ dbexpression.o: ../../pikotools/textstream/types.h
|
|||
dbexpression.o: ../../pikotools/date/date.h
|
||||
dbexpression.o: ../../pikotools/convert/inttostr.h
|
||||
dbexpression.o: ../../pikotools/membuffer/membuffer.h
|
||||
dbexpression.o: ../../pikotools/textstream/types.h morm_types.h
|
||||
dbexpression.o: ../../pikotools/textstream/types.h morm_types.h modelenv.h
|
||||
dbexpression.o: modeldata.h cursorhelper.h queryresult.h finderhelper.h
|
||||
dochtmlconnector.o: dochtmlconnector.h flatconnector.h
|
||||
dochtmlconnector.o: ../../pikotools/textstream/textstream.h
|
||||
dochtmlconnector.o: ../../pikotools/space/space.h
|
||||
|
@ -50,7 +54,8 @@ dochtmlconnector.o: ../../pikotools/date/date.h
|
|||
dochtmlconnector.o: ../../pikotools/convert/inttostr.h
|
||||
dochtmlconnector.o: ../../pikotools/membuffer/membuffer.h
|
||||
dochtmlconnector.o: ../../pikotools/textstream/types.h dochtmlexpression.h
|
||||
dochtmlconnector.o: flatexpression.h baseexpression.h morm_types.h
|
||||
dochtmlconnector.o: flatexpression.h baseexpression.h morm_types.h modelenv.h
|
||||
dochtmlconnector.o: modeldata.h cursorhelper.h queryresult.h finderhelper.h
|
||||
dochtmlexpression.o: dochtmlexpression.h flatexpression.h baseexpression.h
|
||||
dochtmlexpression.o: ../../pikotools/textstream/textstream.h
|
||||
dochtmlexpression.o: ../../pikotools/space/space.h
|
||||
|
@ -59,6 +64,8 @@ dochtmlexpression.o: ../../pikotools/date/date.h
|
|||
dochtmlexpression.o: ../../pikotools/convert/inttostr.h
|
||||
dochtmlexpression.o: ../../pikotools/membuffer/membuffer.h
|
||||
dochtmlexpression.o: ../../pikotools/textstream/types.h morm_types.h
|
||||
dochtmlexpression.o: modelenv.h modeldata.h cursorhelper.h queryresult.h
|
||||
dochtmlexpression.o: finderhelper.h
|
||||
flatconnector.o: flatconnector.h ../../pikotools/textstream/textstream.h
|
||||
flatconnector.o: ../../pikotools/space/space.h
|
||||
flatconnector.o: ../../pikotools/textstream/types.h
|
||||
|
@ -66,10 +73,11 @@ flatconnector.o: ../../pikotools/date/date.h
|
|||
flatconnector.o: ../../pikotools/convert/inttostr.h
|
||||
flatconnector.o: ../../pikotools/membuffer/membuffer.h
|
||||
flatconnector.o: ../../pikotools/textstream/types.h flatexpression.h
|
||||
flatconnector.o: baseexpression.h morm_types.h model.h modelconnector.h
|
||||
flatconnector.o: clearer.h dbconnector.h ../../pikotools/log/log.h
|
||||
flatconnector.o: ../../pikotools/log/filelog.h queryresult.h dbexpression.h
|
||||
flatconnector.o: modeldata.h
|
||||
flatconnector.o: baseexpression.h morm_types.h modelenv.h modeldata.h
|
||||
flatconnector.o: cursorhelper.h queryresult.h finderhelper.h model.h
|
||||
flatconnector.o: modelconnector.h clearer.h dbconnector.h
|
||||
flatconnector.o: ../../pikotools/log/log.h ../../pikotools/log/filelog.h
|
||||
flatconnector.o: dbexpression.h
|
||||
flatexpression.o: flatexpression.h baseexpression.h
|
||||
flatexpression.o: ../../pikotools/textstream/textstream.h
|
||||
flatexpression.o: ../../pikotools/space/space.h
|
||||
|
@ -77,7 +85,8 @@ flatexpression.o: ../../pikotools/textstream/types.h
|
|||
flatexpression.o: ../../pikotools/date/date.h
|
||||
flatexpression.o: ../../pikotools/convert/inttostr.h
|
||||
flatexpression.o: ../../pikotools/membuffer/membuffer.h
|
||||
flatexpression.o: ../../pikotools/textstream/types.h morm_types.h
|
||||
flatexpression.o: ../../pikotools/textstream/types.h morm_types.h modelenv.h
|
||||
flatexpression.o: modeldata.h cursorhelper.h queryresult.h finderhelper.h
|
||||
jsonconnector.o: jsonconnector.h flatconnector.h
|
||||
jsonconnector.o: ../../pikotools/textstream/textstream.h
|
||||
jsonconnector.o: ../../pikotools/space/space.h
|
||||
|
@ -86,7 +95,8 @@ jsonconnector.o: ../../pikotools/date/date.h
|
|||
jsonconnector.o: ../../pikotools/convert/inttostr.h
|
||||
jsonconnector.o: ../../pikotools/membuffer/membuffer.h
|
||||
jsonconnector.o: ../../pikotools/textstream/types.h jsonexpression.h
|
||||
jsonconnector.o: flatexpression.h baseexpression.h morm_types.h
|
||||
jsonconnector.o: flatexpression.h baseexpression.h morm_types.h modelenv.h
|
||||
jsonconnector.o: modeldata.h cursorhelper.h queryresult.h finderhelper.h
|
||||
jsonexpression.o: jsonexpression.h flatexpression.h baseexpression.h
|
||||
jsonexpression.o: ../../pikotools/textstream/textstream.h
|
||||
jsonexpression.o: ../../pikotools/space/space.h
|
||||
|
@ -94,7 +104,8 @@ jsonexpression.o: ../../pikotools/textstream/types.h
|
|||
jsonexpression.o: ../../pikotools/date/date.h
|
||||
jsonexpression.o: ../../pikotools/convert/inttostr.h
|
||||
jsonexpression.o: ../../pikotools/membuffer/membuffer.h
|
||||
jsonexpression.o: ../../pikotools/textstream/types.h morm_types.h
|
||||
jsonexpression.o: ../../pikotools/textstream/types.h morm_types.h modelenv.h
|
||||
jsonexpression.o: modeldata.h cursorhelper.h queryresult.h finderhelper.h
|
||||
model.o: model.h ../../pikotools/textstream/textstream.h
|
||||
model.o: ../../pikotools/space/space.h ../../pikotools/textstream/types.h
|
||||
model.o: ../../pikotools/date/date.h ../../pikotools/convert/inttostr.h
|
||||
|
@ -102,8 +113,8 @@ model.o: ../../pikotools/membuffer/membuffer.h
|
|||
model.o: ../../pikotools/textstream/types.h modelconnector.h clearer.h
|
||||
model.o: dbconnector.h ../../pikotools/log/log.h
|
||||
model.o: ../../pikotools/log/filelog.h queryresult.h flatconnector.h
|
||||
model.o: dbexpression.h baseexpression.h morm_types.h flatexpression.h
|
||||
model.o: modeldata.h
|
||||
model.o: dbexpression.h baseexpression.h morm_types.h modelenv.h modeldata.h
|
||||
model.o: cursorhelper.h finderhelper.h flatexpression.h
|
||||
modelconnector.o: modelconnector.h clearer.h ../../pikotools/date/date.h
|
||||
modelconnector.o: ../../pikotools/convert/inttostr.h dbconnector.h
|
||||
modelconnector.o: ../../pikotools/textstream/textstream.h
|
||||
|
@ -125,7 +136,8 @@ postgresqlconnector.o: ../../pikotools/log/log.h
|
|||
postgresqlconnector.o: ../../pikotools/log/filelog.h queryresult.h
|
||||
postgresqlconnector.o: postgresqlqueryresult.h ../../pikotools/utf8/utf8.h
|
||||
postgresqlconnector.o: postgresqlexpression.h dbexpression.h baseexpression.h
|
||||
postgresqlconnector.o: morm_types.h ../../pikotools/convert/strtoint.h
|
||||
postgresqlconnector.o: morm_types.h modelenv.h modeldata.h cursorhelper.h
|
||||
postgresqlconnector.o: finderhelper.h ../../pikotools/convert/strtoint.h
|
||||
postgresqlconnector.o: ../../pikotools/convert/text.h
|
||||
postgresqlconnector.o: ../../pikotools/convert/misc.h
|
||||
postgresqlexpression.o: postgresqlexpression.h dbexpression.h
|
||||
|
@ -137,6 +149,8 @@ postgresqlexpression.o: ../../pikotools/date/date.h
|
|||
postgresqlexpression.o: ../../pikotools/convert/inttostr.h
|
||||
postgresqlexpression.o: ../../pikotools/membuffer/membuffer.h
|
||||
postgresqlexpression.o: ../../pikotools/textstream/types.h morm_types.h
|
||||
postgresqlexpression.o: modelenv.h modeldata.h cursorhelper.h queryresult.h
|
||||
postgresqlexpression.o: finderhelper.h
|
||||
postgresqlqueryresult.o: postgresqlqueryresult.h queryresult.h
|
||||
queryresult.o: queryresult.h ../../pikotools/utf8/utf8.h
|
||||
queryresult.o: ../../pikotools/textstream/textstream.h
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018, Tomasz Sowa
|
||||
* Copyright (c) 2018-2019, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -44,9 +44,7 @@ namespace morm
|
|||
|
||||
BaseExpression::BaseExpression()
|
||||
{
|
||||
out_stream = nullptr;
|
||||
is_first_field = false;
|
||||
work_mode = 0;
|
||||
clear();
|
||||
}
|
||||
|
||||
BaseExpression::~BaseExpression()
|
||||
|
@ -54,32 +52,47 @@ BaseExpression::~BaseExpression()
|
|||
}
|
||||
|
||||
|
||||
void BaseExpression::clear()
|
||||
{
|
||||
out_stream = nullptr;
|
||||
is_first_field = false;
|
||||
work_mode = 0;
|
||||
use_prefix = false;
|
||||
}
|
||||
|
||||
|
||||
void BaseExpression::set_work_mode(int work_mode)
|
||||
{
|
||||
this->work_mode = work_mode;
|
||||
}
|
||||
|
||||
|
||||
void BaseExpression::prepare_to_new_expression()
|
||||
int BaseExpression::get_work_mode()
|
||||
{
|
||||
column_prefix.clear();
|
||||
out_stream = nullptr;
|
||||
is_first_field = false;
|
||||
work_mode = 0;
|
||||
return work_mode;
|
||||
}
|
||||
|
||||
|
||||
|
||||
PT::TextStream * BaseExpression::get_current_stream()
|
||||
{
|
||||
return out_stream;
|
||||
}
|
||||
|
||||
|
||||
void BaseExpression::set_column_prefix(const std::wstring & prefix)
|
||||
void BaseExpression::allow_to_use_prefix(bool use_prefix)
|
||||
{
|
||||
column_prefix = prefix;
|
||||
this->use_prefix = use_prefix;
|
||||
}
|
||||
|
||||
|
||||
bool BaseExpression::get_allow_to_use_prefix()
|
||||
{
|
||||
return use_prefix;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void BaseExpression::generate_from_model(PT::TextStream & stream, Model & model)
|
||||
{
|
||||
this->out_stream = &stream;
|
||||
|
@ -144,14 +157,80 @@ void BaseExpression::field_after()
|
|||
}
|
||||
|
||||
|
||||
void BaseExpression::put_field_name(const wchar_t * field_name, bool add_column_prefix)
|
||||
bool BaseExpression::is_long_field_name(const wchar_t * field_name)
|
||||
{
|
||||
bool is_long = false;
|
||||
|
||||
while( *field_name != 0 )
|
||||
{
|
||||
if( *field_name == '.' )
|
||||
{
|
||||
is_long = true;
|
||||
break;
|
||||
}
|
||||
|
||||
field_name += 1;
|
||||
}
|
||||
|
||||
return is_long;
|
||||
}
|
||||
|
||||
|
||||
bool BaseExpression::is_long_field_name(const PT::TextStream & field_name)
|
||||
{
|
||||
PT::TextStream::const_iterator i = field_name.begin();
|
||||
bool is_long = false;
|
||||
|
||||
while( i != field_name.end() )
|
||||
{
|
||||
if( *i == '.' )
|
||||
{
|
||||
is_long = true;
|
||||
break;
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
return is_long;
|
||||
}
|
||||
|
||||
|
||||
bool BaseExpression::is_long_table_name(const wchar_t * table_name)
|
||||
{
|
||||
return is_long_field_name(table_name);
|
||||
}
|
||||
|
||||
bool BaseExpression::is_long_table_name(const PT::TextStream & table_name)
|
||||
{
|
||||
return is_long_field_name(table_name);
|
||||
}
|
||||
|
||||
|
||||
bool BaseExpression::need_to_add_field_prefix(const wchar_t * field_name)
|
||||
{
|
||||
return !is_long_field_name(field_name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void BaseExpression::put_field_name(const wchar_t * field_name, ModelEnv * model_env)
|
||||
{
|
||||
before_field_name();
|
||||
|
||||
if( add_column_prefix && !column_prefix.empty() )
|
||||
if( use_prefix && model_env )
|
||||
{
|
||||
esc(column_prefix, *out_stream);
|
||||
(*out_stream) << '.';
|
||||
if( need_to_add_field_prefix(field_name) )
|
||||
{
|
||||
esc(model_env->table_name_short, *out_stream);
|
||||
|
||||
if( model_env->table_index > 1 )
|
||||
{
|
||||
(*out_stream) << model_env->table_index;
|
||||
}
|
||||
|
||||
(*out_stream) << '.';
|
||||
}
|
||||
}
|
||||
|
||||
esc(field_name, *out_stream);
|
||||
|
@ -159,15 +238,30 @@ void BaseExpression::put_field_name(const wchar_t * field_name, bool add_column_
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void BaseExpression::put_field_doc(Model & model, const void * field_pointer, bool insertable, bool updatable, bool is_primary_key, ModelData * model_data)
|
||||
void BaseExpression::save_foreign_key(const wchar_t * field_name, ModelEnv * model_env)
|
||||
{
|
||||
model.doc_field_pointer = field_pointer;
|
||||
model.model_data = model_data;
|
||||
PT::TextStream str;
|
||||
PT::TextStream * old_out_stream = out_stream;
|
||||
|
||||
out_stream = &str;
|
||||
put_field_name(field_name, model_env);
|
||||
out_stream = old_out_stream;
|
||||
|
||||
if( model_env && model_env->finder_helper )
|
||||
{
|
||||
model_env->finder_helper->foreign_keys.emplace_back();
|
||||
std::string & key_str = model_env->finder_helper->foreign_keys.back();
|
||||
str.to_string(key_str, false);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseExpression::put_field_doc(Model & model, const void * field_pointer, bool insertable, bool updatable, bool is_primary_key, ModelEnv * model_env)
|
||||
{
|
||||
//model.doc_field_pointer = field_pointer;
|
||||
model.model_env = model_env;
|
||||
model.map_doc_fields();
|
||||
model.model_data = nullptr;
|
||||
model.doc_field_pointer = nullptr;
|
||||
model.model_env = nullptr;
|
||||
//model.doc_field_pointer = nullptr;
|
||||
}
|
||||
|
||||
void BaseExpression::before_field_name()
|
||||
|
@ -379,6 +473,16 @@ void BaseExpression::esc(const PT::Date & date, PT::TextStream & stream)
|
|||
stream << date;
|
||||
}
|
||||
|
||||
void BaseExpression::esc(const PT::TextStream & val, PT::TextStream & stream)
|
||||
{
|
||||
PT::TextStream::const_iterator i = val.begin();
|
||||
|
||||
for(; i != val.end() ; ++i)
|
||||
{
|
||||
esc(*i, stream);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BaseExpression::put_type(char val, PT::TextStream & stream)
|
||||
{
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018, Tomasz Sowa
|
||||
* Copyright (c) 2018-2019, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -38,14 +38,15 @@
|
|||
#include <list>
|
||||
#include <set>
|
||||
#include "textstream/textstream.h"
|
||||
#include "morm_types.h"
|
||||
#include "date/date.h"
|
||||
#include "morm_types.h"
|
||||
#include "modelenv.h"
|
||||
|
||||
|
||||
|
||||
namespace morm
|
||||
{
|
||||
class Model;
|
||||
class ModelData;
|
||||
class ModelConnector;
|
||||
|
||||
|
||||
|
@ -57,21 +58,25 @@ public:
|
|||
virtual ~BaseExpression();
|
||||
|
||||
virtual void set_work_mode(int work_mode);
|
||||
virtual void prepare_to_new_expression();
|
||||
virtual void set_column_prefix(const std::wstring & prefix);
|
||||
virtual int get_work_mode();
|
||||
|
||||
virtual void clear();
|
||||
|
||||
virtual void generate_from_model(PT::TextStream & stream, Model & model);
|
||||
|
||||
virtual PT::TextStream * get_current_stream();
|
||||
|
||||
// rename me
|
||||
virtual void allow_to_use_prefix(bool use_prefix);
|
||||
virtual bool get_allow_to_use_prefix();
|
||||
|
||||
// give me a better name
|
||||
virtual void put_field_doc(Model & model, const void * field_pointer, bool insertable, bool updatable, bool is_primary_key, ModelData * model_data);
|
||||
virtual void put_field_doc(Model & model, const void * field_pointer, bool insertable, bool updatable, bool is_primary_key, ModelEnv * model_env);
|
||||
|
||||
|
||||
|
||||
template<typename FieldValue>
|
||||
void field(const wchar_t * field_name, const FieldValue & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false, bool add_column_prefix = true)
|
||||
void field(const wchar_t * field_name, const FieldValue & field_value, bool insertable, bool updatable, bool is_primary_key, ModelEnv * model_env)
|
||||
{
|
||||
if( out_stream && can_field_be_generated(insertable, updatable, is_primary_key) )
|
||||
{
|
||||
|
@ -79,7 +84,12 @@ public:
|
|||
|
||||
if( work_mode == MORM_WORK_MODE_MODEL_FIELDS )
|
||||
{
|
||||
put_field_name(field_name, add_column_prefix);
|
||||
put_field_name(field_name, model_env);
|
||||
}
|
||||
else
|
||||
if( work_mode == MORM_WORK_MODE_MODEL_SAVE_FIELDS )
|
||||
{
|
||||
save_foreign_key(field_name, model_env);
|
||||
}
|
||||
else
|
||||
if( work_mode == MORM_WORK_MODE_MODEL_VALUES )
|
||||
|
@ -89,29 +99,29 @@ public:
|
|||
else
|
||||
if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES )
|
||||
{
|
||||
put_field_name(field_name);
|
||||
put_field_name(field_name, model_env);
|
||||
put_name_value_separator();
|
||||
put_field_value(field_value);
|
||||
}
|
||||
|
||||
|
||||
field_after();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename FieldValue>
|
||||
void field_doc(Model & model, const wchar_t * field_name, const FieldValue & field_value,
|
||||
bool insertable = true, bool updatable = true,
|
||||
bool is_primary_key = false, bool add_column_prefix = true,
|
||||
ModelData * model_data = nullptr)
|
||||
void field_doc(Model & model, const wchar_t * field_name, const FieldValue & field_value, bool insertable, bool updatable, bool is_primary_key, ModelEnv * model_env)
|
||||
{
|
||||
if( out_stream )
|
||||
{
|
||||
field_before();
|
||||
|
||||
put_field_name(field_name, add_column_prefix);
|
||||
put_field_name(field_name, model_env);
|
||||
put_name_value_separator();
|
||||
|
||||
put_field_doc(model, reinterpret_cast<const void*>(&field_value), insertable, updatable, is_primary_key, model_data);
|
||||
put_field_doc(model, reinterpret_cast<const void*>(&field_value), insertable, updatable, is_primary_key, model_env);
|
||||
put_name_value_separator();
|
||||
|
||||
put_type(field_value, *out_stream);
|
||||
|
@ -121,48 +131,45 @@ public:
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
template<typename FieldValue>
|
||||
void field(const PT::TextStream & field_name, const FieldValue & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false, bool add_column_prefix = true)
|
||||
void field_in(PT::TextStream & stream, const wchar_t * field_name, const std::set<FieldValue> & container, ModelEnv * model_env)
|
||||
{
|
||||
std::wstring field_name_str; // field() methods can be called recursively, so don't make it as class object
|
||||
field_name.to_string(field_name_str);
|
||||
|
||||
return field(field_name_str.c_str(), field_value, insertable, updatable, is_primary_key, add_column_prefix);
|
||||
}
|
||||
*/
|
||||
|
||||
template<typename FieldValue>
|
||||
void field_in(PT::TextStream & stream, const wchar_t * field_name, const std::set<FieldValue> & container)
|
||||
{
|
||||
field_in_generic<FieldValue, std::set<FieldValue>>(stream, field_name, container);
|
||||
field_in_generic<FieldValue, std::set<FieldValue>>(stream, field_name, container, model_env);
|
||||
}
|
||||
|
||||
template<typename FieldValue>
|
||||
void field_in(PT::TextStream & stream, const wchar_t * field_name, const std::list<FieldValue> & container)
|
||||
{
|
||||
field_in_generic<FieldValue, std::list<FieldValue>>(stream, field_name, container);
|
||||
}
|
||||
|
||||
template<typename FieldValue>
|
||||
void field_in(PT::TextStream & stream, const wchar_t * field_name, const std::vector<FieldValue> & container)
|
||||
void field_in(PT::TextStream & stream, const wchar_t * field_name, const std::list<FieldValue> & container, ModelEnv * model_env)
|
||||
{
|
||||
field_in_generic<FieldValue, std::vector<FieldValue>>(stream, field_name, container);
|
||||
field_in_generic<FieldValue, std::list<FieldValue>>(stream, field_name, container, model_env);
|
||||
}
|
||||
|
||||
|
||||
template<typename FieldValue>
|
||||
void field_in(PT::TextStream & stream, const wchar_t * field_name, const std::vector<FieldValue> & container, ModelEnv * model_env)
|
||||
{
|
||||
field_in_generic<FieldValue, std::vector<FieldValue>>(stream, field_name, container, model_env);
|
||||
}
|
||||
|
||||
|
||||
template<typename ModelContainer>
|
||||
void field_list(const wchar_t * field_name, ModelContainer & field_value, bool insertable, bool updatable, bool is_primary_key,
|
||||
ModelConnector * model_connector, int model_connector_mode, ModelData * model_data)
|
||||
ModelConnector * model_connector, ModelEnv * model_env)
|
||||
{
|
||||
if( out_stream && can_field_be_generated(insertable, updatable, is_primary_key) )
|
||||
{
|
||||
field_before();
|
||||
|
||||
// if( work_mode == MORM_WORK_MODE_MODEL_FIELDS )
|
||||
// {
|
||||
// put_field_name(field_name);
|
||||
// }
|
||||
// else
|
||||
if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES )
|
||||
{
|
||||
put_field_name(field_name);
|
||||
put_field_name(field_name, model_env);
|
||||
put_name_value_separator();
|
||||
put_field_value_list(field_value, model_connector, model_connector_mode, model_data);
|
||||
put_field_value_list(field_value, model_connector, model_env);
|
||||
}
|
||||
|
||||
field_after();
|
||||
|
@ -170,7 +177,7 @@ public:
|
|||
}
|
||||
|
||||
template<typename ModelClass>
|
||||
void field_model(const wchar_t * field_name, ModelClass & field_model, bool insertable = true, bool updatable = true, bool is_primary_key = false)
|
||||
void field_model(const wchar_t * field_name, ModelClass & field_model, bool insertable, bool updatable, bool is_primary_key, ModelEnv * model_env)
|
||||
{
|
||||
if( out_stream && can_field_be_generated(insertable, updatable, is_primary_key) )
|
||||
{
|
||||
|
@ -178,7 +185,7 @@ public:
|
|||
|
||||
if( work_mode == MORM_WORK_MODE_MODEL_FIELDS )
|
||||
{
|
||||
put_field_name(field_name);
|
||||
put_field_name(field_name, model_env);
|
||||
}
|
||||
else
|
||||
if( work_mode == MORM_WORK_MODE_MODEL_VALUES )
|
||||
|
@ -188,7 +195,7 @@ public:
|
|||
else
|
||||
if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES )
|
||||
{
|
||||
put_field_name(field_name);
|
||||
put_field_name(field_name, model_env);
|
||||
put_name_value_separator();
|
||||
generate_from_model(field_model);
|
||||
}
|
||||
|
@ -198,10 +205,11 @@ public:
|
|||
}
|
||||
|
||||
template<typename FieldValue>
|
||||
void field_to_stream(PT::TextStream & stream, const wchar_t * field_name, const FieldValue & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false)
|
||||
void field_to_stream(PT::TextStream & stream, const wchar_t * field_name, const FieldValue & field_value, bool insertable, bool updatable, bool is_primary_key,
|
||||
ModelEnv * model_env)
|
||||
{
|
||||
this->out_stream = &stream;
|
||||
field(field_name, field_value, insertable, updatable, is_primary_key);
|
||||
field(field_name, field_value, insertable, updatable, is_primary_key, model_env);
|
||||
this->out_stream = nullptr;
|
||||
}
|
||||
|
||||
|
@ -231,7 +239,13 @@ public:
|
|||
//virtual void esc(void* val, PT::TextStream & stream);
|
||||
|
||||
virtual void esc(const PT::Date & date, PT::TextStream & stream);
|
||||
virtual void esc(const PT::TextStream & val,PT::TextStream & stream);
|
||||
|
||||
virtual bool is_long_field_name(const wchar_t * field_name);
|
||||
virtual bool is_long_field_name(const PT::TextStream & table_name);
|
||||
|
||||
virtual bool is_long_table_name(const wchar_t * field_name);
|
||||
virtual bool is_long_table_name(const PT::TextStream & table_name);
|
||||
|
||||
|
||||
|
||||
|
@ -240,15 +254,9 @@ protected:
|
|||
int work_mode; /* what to do: generating fields list, values list or fields-values list */
|
||||
bool is_first_field;
|
||||
|
||||
// niech Stream bedzie jakims interfejsem z operatorami << dla standardowych typow
|
||||
// albo w pikotoolsach dodać klase bazowa (intefejs) dla streamow
|
||||
// i dodatkowo dodac loger ktory dziedziczy po niej i dodaje loglevel i endline
|
||||
// jako metode bazowa dodac format("string", parametry,...)
|
||||
// przyda sie do formatowania doubli
|
||||
PT::TextStream * out_stream;
|
||||
|
||||
|
||||
std::wstring column_prefix;
|
||||
bool use_prefix;
|
||||
|
||||
virtual void generate_from_model(Model & model);
|
||||
|
||||
|
@ -260,7 +268,12 @@ protected:
|
|||
|
||||
//void field(const wchar_t * field_name, Model & field, bool insertable = true, bool updatable = true);
|
||||
|
||||
virtual void put_field_name(const wchar_t * field_name, bool add_column_prefix = true);
|
||||
virtual bool need_to_add_field_prefix(const wchar_t * field_name);
|
||||
|
||||
virtual void put_field_name(const wchar_t * field_name, ModelEnv * model_env);
|
||||
|
||||
virtual void save_foreign_key(const wchar_t * field_name, ModelEnv * model_env);
|
||||
|
||||
|
||||
template<typename FieldValue>
|
||||
void put_field_value(const FieldValue & field_value)
|
||||
|
@ -273,49 +286,66 @@ protected:
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
virtual void before_field_value_list()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual void after_field_value_list()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual void field_value_list_separator()
|
||||
{
|
||||
(*out_stream) << ",";
|
||||
}
|
||||
|
||||
virtual void put_statement_in_starts()
|
||||
{
|
||||
(*out_stream) << "(";
|
||||
}
|
||||
|
||||
virtual void put_statement_in_ends()
|
||||
{
|
||||
(*out_stream) << ") ";
|
||||
}
|
||||
|
||||
// what about lists with a pod types? e.g. list<int>
|
||||
template<typename ModelContainer>
|
||||
void put_field_value_list(ModelContainer & field_value, ModelConnector * model_connector, int model_connector_mode, ModelData * model_data)
|
||||
void put_field_value_list(ModelContainer & field_value, ModelConnector * model_connector, ModelEnv * model_env)
|
||||
{
|
||||
if( out_stream )
|
||||
if( model_connector && model_env && out_stream )
|
||||
{
|
||||
(*out_stream) << "[";// make a virtual method
|
||||
}
|
||||
bool is_first = true;
|
||||
before_field_value_list();
|
||||
|
||||
bool is_first = true;
|
||||
|
||||
for(auto & m : field_value)
|
||||
{
|
||||
if( out_stream )
|
||||
for(auto & m : field_value)
|
||||
{
|
||||
if( !is_first )
|
||||
{
|
||||
if( out_stream )
|
||||
(*out_stream) << ","; // make a virtual method
|
||||
field_value_list_separator();
|
||||
}
|
||||
|
||||
ModelEnv model_env_local(*model_env);
|
||||
m.model_env = &model_env_local;
|
||||
//before_field_value(field_value);
|
||||
m.set_connector(model_connector);
|
||||
m.model_connector_mode = model_connector_mode;
|
||||
m.model_data = model_data;
|
||||
generate_from_model(m);
|
||||
m.model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
m.model_data = nullptr;
|
||||
m.model_env = nullptr;
|
||||
//after_field_value(field_value);
|
||||
is_first = false;
|
||||
}
|
||||
}
|
||||
|
||||
if( out_stream )
|
||||
{
|
||||
(*out_stream) << "]";// make a virtual method
|
||||
after_field_value_list();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// used in 'in()' statements, may should be renamed?
|
||||
template<typename FieldValue, typename Container>
|
||||
void field_in_generic(PT::TextStream & stream, const wchar_t * field_name, const Container & container)
|
||||
void field_in_generic(PT::TextStream & stream, const wchar_t * field_name, const Container & container, ModelEnv * model_env)
|
||||
{
|
||||
// IMPROVE ME
|
||||
// what about if container is empty?
|
||||
|
@ -323,24 +353,24 @@ protected:
|
|||
this->out_stream = &stream;
|
||||
|
||||
field_before();
|
||||
put_field_name(field_name);
|
||||
put_field_name(field_name, model_env);
|
||||
put_name_value_separator();
|
||||
|
||||
bool is_first = true;
|
||||
(*out_stream) << "(";
|
||||
put_statement_in_starts();
|
||||
|
||||
for(const FieldValue & v : container)
|
||||
{
|
||||
if( !is_first )
|
||||
{
|
||||
(*out_stream) << ",";
|
||||
field_value_list_separator();
|
||||
}
|
||||
|
||||
put_field_value(v);
|
||||
is_first = false;
|
||||
}
|
||||
|
||||
(*out_stream) << ") ";
|
||||
put_statement_in_ends();
|
||||
field_after();
|
||||
this->out_stream = nullptr;
|
||||
}
|
||||
|
|
63
src/cursor.h
63
src/cursor.h
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018, Tomasz Sowa
|
||||
* Copyright (c) 2018-2019, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -51,7 +51,8 @@ public:
|
|||
|
||||
Cursor()
|
||||
{
|
||||
set_default_values();
|
||||
query_result = nullptr;
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
|
@ -59,6 +60,7 @@ public:
|
|||
{
|
||||
model_connector = c.model_connector;
|
||||
model_data = c.model_data;
|
||||
has_autogenerated_select = c.has_autogenerated_select;
|
||||
query_result = c.query_result;
|
||||
select_status = c.select_status;
|
||||
|
||||
|
@ -66,6 +68,9 @@ public:
|
|||
{
|
||||
query_result->references_count += 1;
|
||||
}
|
||||
|
||||
// helper doesn't have to be copied
|
||||
cursor_helper.clear();
|
||||
}
|
||||
|
||||
|
||||
|
@ -91,7 +96,13 @@ public:
|
|||
delete query_result;
|
||||
}
|
||||
|
||||
set_default_values();
|
||||
model_connector = nullptr;
|
||||
model_data = nullptr;
|
||||
has_autogenerated_select = false;
|
||||
cursor_helper.clear();
|
||||
query_result = nullptr;
|
||||
select_status = false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -119,6 +130,12 @@ public:
|
|||
}
|
||||
|
||||
|
||||
virtual void set_has_autogenerated_select(bool has_autogenerated_select)
|
||||
{
|
||||
this->has_autogenerated_select = has_autogenerated_select;
|
||||
}
|
||||
|
||||
|
||||
virtual QueryResult * get_query_result()
|
||||
{
|
||||
return query_result;
|
||||
|
@ -150,9 +167,17 @@ public:
|
|||
|
||||
if( db_connector )
|
||||
{
|
||||
ModelEnv model_env_local;
|
||||
result.model_env = &model_env_local;
|
||||
result.model_env->cursor_helper = &cursor_helper;
|
||||
|
||||
try
|
||||
{
|
||||
result.model_data = model_data;
|
||||
cursor_helper.clear();
|
||||
cursor_helper.query_result = query_result;
|
||||
cursor_helper.has_autogenerated_select = has_autogenerated_select;
|
||||
|
||||
result.model_env->model_data = model_data;
|
||||
result.before_select();
|
||||
res = select_status;
|
||||
|
||||
|
@ -161,7 +186,7 @@ public:
|
|||
if( query_result->cur_row < query_result->result_rows )
|
||||
{
|
||||
result.set_save_mode(Model::DO_UPDATE_ON_SAVE); // IMPROVE ME check if there is a primary key
|
||||
result.map_values_from_query(query_result);
|
||||
result.map_values_from_query();
|
||||
result.after_select();
|
||||
query_result->cur_row += 1;
|
||||
}
|
||||
|
@ -182,7 +207,7 @@ public:
|
|||
// throw something?
|
||||
}
|
||||
|
||||
result.model_data = nullptr;
|
||||
result.model_env = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,7 +220,7 @@ public:
|
|||
ModelClass model;
|
||||
|
||||
get(model);
|
||||
return std::move(model);
|
||||
return model;
|
||||
}
|
||||
|
||||
|
||||
|
@ -258,17 +283,12 @@ protected:
|
|||
|
||||
ModelConnector * model_connector;
|
||||
ModelData * model_data;
|
||||
bool has_autogenerated_select;
|
||||
CursorHelper cursor_helper;
|
||||
QueryResult * query_result;
|
||||
bool select_status;
|
||||
|
||||
|
||||
virtual void set_default_values()
|
||||
{
|
||||
model_connector = nullptr;
|
||||
model_data = nullptr;
|
||||
query_result = nullptr;
|
||||
select_status = false;
|
||||
}
|
||||
|
||||
|
||||
template<typename ContainerType>
|
||||
|
@ -281,14 +301,23 @@ protected:
|
|||
result.emplace_back(); // it returns a reference from c++17
|
||||
ModelClass & added_model = result.back();
|
||||
|
||||
ModelEnv model_env_local;
|
||||
|
||||
try
|
||||
{
|
||||
cursor_helper.clear();
|
||||
cursor_helper.query_result = query_result;
|
||||
cursor_helper.has_autogenerated_select = has_autogenerated_select;
|
||||
|
||||
added_model.set_connector(model_connector);
|
||||
added_model.clear();
|
||||
|
||||
added_model.model_env = &model_env_local;
|
||||
added_model.model_env->cursor_helper = &cursor_helper;
|
||||
added_model.set_save_mode(Model::DO_UPDATE_ON_SAVE); // IMPROVE ME check if there is a primary key
|
||||
added_model.model_data = model_data;
|
||||
added_model.model_env->model_data = model_data;
|
||||
added_model.before_select();
|
||||
added_model.map_values_from_query(query_result);
|
||||
added_model.map_values_from_query();
|
||||
added_model.after_select();
|
||||
}
|
||||
catch(...)
|
||||
|
@ -297,7 +326,7 @@ protected:
|
|||
// throw or something?
|
||||
}
|
||||
|
||||
added_model.model_data = nullptr;
|
||||
added_model.model_env = nullptr;
|
||||
}
|
||||
|
||||
return res;
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* This file is a part of morm
|
||||
* and is distributed under the 2-Clause BSD licence.
|
||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2019, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef headerfile_morm_cursorhelper
|
||||
#define headerfile_morm_cursorhelper
|
||||
|
||||
#include "queryresult.h"
|
||||
|
||||
|
||||
namespace morm
|
||||
{
|
||||
|
||||
class CursorHelper
|
||||
{
|
||||
public:
|
||||
|
||||
bool has_autogenerated_select;
|
||||
QueryResult * query_result;
|
||||
int current_column;
|
||||
|
||||
|
||||
|
||||
CursorHelper()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
virtual ~CursorHelper()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual void clear()
|
||||
{
|
||||
has_autogenerated_select = false;
|
||||
query_result = nullptr;
|
||||
current_column = 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018, Tomasz Sowa
|
||||
* Copyright (c) 2018-2019, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -49,6 +49,7 @@ DbConnector::DbConnector()
|
|||
db_expression = nullptr;
|
||||
expression_allocated = false;
|
||||
log = nullptr;
|
||||
log_queries = false;
|
||||
}
|
||||
|
||||
DbConnector::DbConnector(const DbConnector &)
|
||||
|
@ -70,12 +71,18 @@ void DbConnector::set_logger(PT::Log * log)
|
|||
this->log = log;
|
||||
}
|
||||
|
||||
|
||||
void DbConnector::set_logger(PT::Log & log)
|
||||
{
|
||||
this->log = &log;
|
||||
}
|
||||
|
||||
|
||||
void DbConnector::set_log_queries(bool log_queries)
|
||||
{
|
||||
this->log_queries = log_queries;
|
||||
}
|
||||
|
||||
|
||||
bool DbConnector::query(const PT::TextStream & stream, QueryResult & query_result)
|
||||
{
|
||||
|
@ -151,16 +158,16 @@ DbExpression * DbConnector::get_expression()
|
|||
}
|
||||
|
||||
|
||||
void DbConnector::generate_select_columns(PT::TextStream & stream, Model & model, const std::wstring & column_prefix)
|
||||
void DbConnector::generate_select_columns(PT::TextStream & stream, Model & model)
|
||||
{
|
||||
allocate_default_expression_if_needed();
|
||||
|
||||
if( db_expression )
|
||||
{
|
||||
db_expression->prepare_to_new_expression();
|
||||
db_expression->clear();
|
||||
db_expression->set_work_mode(MORM_WORK_MODE_MODEL_FIELDS);
|
||||
db_expression->set_output_type(MORM_OUTPUT_TYPE_SELECT_COLUMNS);
|
||||
db_expression->set_column_prefix(column_prefix);
|
||||
db_expression->allow_to_use_prefix(true);
|
||||
db_expression->generate_from_model(stream, model);
|
||||
}
|
||||
}
|
||||
|
@ -172,7 +179,9 @@ void DbConnector::generate_insert_query(PT::TextStream & stream, Model & model)
|
|||
|
||||
if( db_expression )
|
||||
{
|
||||
db_expression->prepare_to_new_expression();
|
||||
db_expression->clear();
|
||||
db_expression->allow_to_use_prefix(false);
|
||||
|
||||
stream << "insert into ";
|
||||
model.table_name(stream);
|
||||
|
||||
|
@ -195,7 +204,9 @@ void DbConnector::generate_update_query(PT::TextStream & stream, Model & model)
|
|||
|
||||
if( db_expression )
|
||||
{
|
||||
db_expression->prepare_to_new_expression();
|
||||
db_expression->clear();
|
||||
db_expression->allow_to_use_prefix(false);
|
||||
|
||||
stream << "update ";
|
||||
model.table_name(stream);
|
||||
|
||||
|
@ -218,7 +229,9 @@ void DbConnector::generate_remove_query(PT::TextStream & stream, Model & model)
|
|||
|
||||
if( db_expression )
|
||||
{
|
||||
db_expression->prepare_to_new_expression();
|
||||
db_expression->clear();
|
||||
db_expression->allow_to_use_prefix(false);
|
||||
|
||||
stream << "delete from ";
|
||||
model.table_name(stream);
|
||||
stream << " where ";
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018, Tomasz Sowa
|
||||
* Copyright (c) 2018-2019, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -57,11 +57,13 @@ public:
|
|||
virtual void set_logger(PT::Log * log);
|
||||
virtual void set_logger(PT::Log & log);
|
||||
|
||||
virtual void set_log_queries(bool log_queries);
|
||||
|
||||
DbExpression * get_expression();
|
||||
|
||||
//virtual void clear_last_query_result();
|
||||
|
||||
virtual void generate_select_columns(PT::TextStream & stream, Model & model, const std::wstring & column_prefix);
|
||||
virtual void generate_select_columns(PT::TextStream & stream, Model & model);
|
||||
virtual void generate_insert_query(PT::TextStream & stream, Model & model);
|
||||
virtual void generate_update_query(PT::TextStream & stream, Model & model);
|
||||
virtual void generate_remove_query(PT::TextStream & stream, Model & model);
|
||||
|
@ -115,6 +117,11 @@ public:
|
|||
if( val_str )
|
||||
{
|
||||
get_value(val_str, field_value);
|
||||
|
||||
if( log && log_queries )
|
||||
{
|
||||
(*log) << PT::Log::log3 << "Morm: sequence value: " << field_value << PT::Log::logend;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,6 +131,7 @@ protected:
|
|||
DbExpression * db_expression;
|
||||
bool expression_allocated;
|
||||
PT::Log * log;
|
||||
bool log_queries;
|
||||
|
||||
|
||||
virtual void allocate_default_expression() = 0;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018, Tomasz Sowa
|
||||
* Copyright (c) 2018-2019, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -56,6 +56,12 @@ void DbExpression::set_output_type(int output_type)
|
|||
}
|
||||
|
||||
|
||||
int DbExpression::get_output_type()
|
||||
{
|
||||
return output_type;
|
||||
}
|
||||
|
||||
|
||||
bool DbExpression::can_field_be_generated(bool insertable, bool updatable, bool is_primary_key)
|
||||
{
|
||||
if( output_type == MORM_OUTPUT_TYPE_DB_INSERT )
|
||||
|
@ -68,7 +74,7 @@ bool DbExpression::can_field_be_generated(bool insertable, bool updatable, bool
|
|||
return updatable;
|
||||
}
|
||||
else
|
||||
if( output_type == MORM_OUTPUT_TYPE_DB_PRIMARY_KEY )
|
||||
if( output_type == MORM_OUTPUT_TYPE_DB_PRIMARY_KEY || output_type == MORM_OUTPUT_TYPE_JOIN_TABLES )
|
||||
{
|
||||
return is_primary_key;
|
||||
}
|
||||
|
@ -90,7 +96,7 @@ void DbExpression::field_before()
|
|||
output_type == MORM_OUTPUT_TYPE_DB_UPDATE ||
|
||||
output_type == MORM_OUTPUT_TYPE_SELECT_COLUMNS )
|
||||
{
|
||||
(*out_stream) << ",";
|
||||
(*out_stream) << ", ";
|
||||
}
|
||||
else
|
||||
if( output_type == MORM_OUTPUT_TYPE_DB_PRIMARY_KEY )
|
||||
|
@ -131,27 +137,32 @@ void DbExpression::put_name_value_separator()
|
|||
output_type == MORM_OUTPUT_TYPE_WHERE_EQ ||
|
||||
output_type == MORM_OUTPUT_TYPE_DB_UPDATE)
|
||||
{
|
||||
(*out_stream) << " = ";
|
||||
(*out_stream) << "=";
|
||||
}
|
||||
else
|
||||
if( output_type == MORM_OUTPUT_TYPE_WHERE_NOT_EQ )
|
||||
{
|
||||
(*out_stream) << "<>";
|
||||
}
|
||||
else
|
||||
if( output_type == MORM_OUTPUT_TYPE_WHERE_LT )
|
||||
{
|
||||
(*out_stream) << " < ";
|
||||
(*out_stream) << "<";
|
||||
}
|
||||
else
|
||||
if( output_type == MORM_OUTPUT_TYPE_WHERE_GT )
|
||||
{
|
||||
(*out_stream) << " > ";
|
||||
(*out_stream) << ">";
|
||||
}
|
||||
else
|
||||
if( output_type == MORM_OUTPUT_TYPE_WHERE_LE )
|
||||
{
|
||||
(*out_stream) << " <= ";
|
||||
(*out_stream) << "<=";
|
||||
}
|
||||
else
|
||||
if( output_type == MORM_OUTPUT_TYPE_WHERE_GE )
|
||||
{
|
||||
(*out_stream) << " >= ";
|
||||
(*out_stream) << ">=";
|
||||
}
|
||||
else
|
||||
if( output_type == MORM_OUTPUT_TYPE_WHERE_IN )
|
||||
|
@ -290,4 +301,40 @@ DbExpression & DbExpression::page(PT::TextStream & stream, size_t page_number, s
|
|||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void DbExpression::prepare_short_table_name(const PT::TextStream & table_name, PT::TextStream & short_table_name)
|
||||
{
|
||||
short_table_name.clear();
|
||||
|
||||
if( is_long_table_name(table_name) )
|
||||
{
|
||||
PT::TextStream::const_iterator i = table_name.begin();
|
||||
bool was_dot = false;
|
||||
|
||||
while( i != table_name.end() )
|
||||
{
|
||||
if( was_dot )
|
||||
{
|
||||
short_table_name << *i;
|
||||
}
|
||||
else
|
||||
if( *i == '.' )
|
||||
{
|
||||
was_dot = true;
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
if( short_table_name.empty() )
|
||||
{
|
||||
short_table_name = table_name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ public:
|
|||
virtual ~DbExpression();
|
||||
|
||||
virtual void set_output_type(int output_type);
|
||||
virtual int get_output_type();
|
||||
|
||||
|
||||
virtual void prepare_to_where_clause();
|
||||
|
@ -61,7 +62,6 @@ public:
|
|||
|
||||
virtual DbExpression & page(PT::TextStream & stream, size_t page_number, size_t page_size);
|
||||
|
||||
|
||||
template<typename FieldValue>
|
||||
void add_field_for_select(const wchar_t * new_column_expression, const wchar_t * new_column_name, FieldValue & field_value)
|
||||
{
|
||||
|
@ -71,10 +71,15 @@ public:
|
|||
column_expression += L" as ";
|
||||
column_expression += new_column_name;
|
||||
|
||||
field(column_expression.c_str(), field_value, false, false, false, false);
|
||||
// put nullptr to ModelEnv* to not allow to use prefix
|
||||
// or may better remember current value of use_prefix and set it to false for a while?
|
||||
field(column_expression.c_str(), field_value, false, false, false, nullptr);
|
||||
}
|
||||
|
||||
|
||||
virtual void prepare_short_table_name(const PT::TextStream & table_name, PT::TextStream & short_table_name);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
int output_type;
|
||||
|
|
116
src/finder.h
116
src/finder.h
|
@ -39,6 +39,7 @@
|
|||
#include <list>
|
||||
#include <set>
|
||||
#include "model.h"
|
||||
#include "utf8/utf8.h"
|
||||
#include "textstream/textstream.h"
|
||||
#include "dbconnector.h"
|
||||
#include "modelconnector.h"
|
||||
|
@ -115,23 +116,6 @@ public:
|
|||
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
void set_out_stream()
|
||||
{
|
||||
if( model_connector )
|
||||
{
|
||||
this->out_stream = model_connector->get_stream();
|
||||
}
|
||||
else
|
||||
{
|
||||
this->out_stream = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
Finder<ModelClass> & set_out_stream(PT::TextStream * out_stream)
|
||||
{
|
||||
this->out_stream = out_stream;
|
||||
|
@ -156,25 +140,18 @@ public:
|
|||
return was_query_error;
|
||||
}
|
||||
|
||||
|
||||
std::wstring get_error_msg()
|
||||
{
|
||||
return last_query_error;
|
||||
}
|
||||
|
||||
|
||||
Finder<ModelClass> & prefix(const wchar_t * prefix)
|
||||
{
|
||||
column_prefix = prefix;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Finder<ModelClass> & prepare_to_select()
|
||||
{
|
||||
was_query_error = false;
|
||||
last_query_error.clear();
|
||||
model_data = nullptr;
|
||||
column_prefix.clear();
|
||||
has_autogenerated_select = false;
|
||||
|
||||
if( model_connector )
|
||||
{
|
||||
|
@ -182,7 +159,6 @@ public:
|
|||
{
|
||||
set_db_expression();
|
||||
out_stream->clear();
|
||||
model.set_connector(model_connector);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -242,22 +218,36 @@ public:
|
|||
prepare_to_select();
|
||||
}
|
||||
|
||||
if( model_connector && out_stream )
|
||||
model.set_connector(model_connector);
|
||||
|
||||
finder_helper.clear();
|
||||
model_env.clear();
|
||||
|
||||
model.model_env = &model_env;
|
||||
model.model_env->model_data = model_data;
|
||||
model.model_env->finder_helper = &finder_helper;
|
||||
|
||||
has_autogenerated_select = true;
|
||||
|
||||
if( model_connector && out_stream && db_expression )
|
||||
{
|
||||
model.table_name(model.model_env->table_name);
|
||||
db_expression->prepare_short_table_name(model.model_env->table_name, model.model_env->table_name_short);
|
||||
|
||||
model.model_env->table_index = finder_helper.add_join_table(model.model_env->table_name_short);
|
||||
|
||||
(*out_stream) << "SELECT ";
|
||||
model.generate_select_columns(*out_stream, column_prefix);
|
||||
(*out_stream) << " FROM ";
|
||||
model.table_name(*out_stream);
|
||||
|
||||
if( !column_prefix.empty() )
|
||||
(*out_stream) << " AS " << column_prefix; // what about escaping?
|
||||
|
||||
model.generate_select_columns(*out_stream);
|
||||
(*out_stream) << " FROM " << model.model_env->table_name << " AS ";
|
||||
(*out_stream) << model.model_env->table_name_short;
|
||||
(*out_stream) << " ";
|
||||
(*out_stream) << finder_helper.join_tables_str;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Finder<ModelClass> & select(ModelData * model_data, bool call_prepare = true)
|
||||
{
|
||||
if( call_prepare )
|
||||
|
@ -269,6 +259,7 @@ public:
|
|||
return select(false);
|
||||
}
|
||||
|
||||
|
||||
Finder<ModelClass> & select(ModelData & model_data, bool call_prepare = true)
|
||||
{
|
||||
if( call_prepare )
|
||||
|
@ -280,6 +271,7 @@ public:
|
|||
return select(false);
|
||||
}
|
||||
|
||||
|
||||
Finder<ModelClass> & where()
|
||||
{
|
||||
if( out_stream && db_expression )
|
||||
|
@ -333,20 +325,32 @@ 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);
|
||||
db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false, &model_env);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template<typename FieldValue>
|
||||
Finder<ModelClass> & neq(const wchar_t * field_name, const FieldValue & field_value)
|
||||
{
|
||||
if( db_expression )
|
||||
{
|
||||
db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_NOT_EQ);
|
||||
db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false, &model_env);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename FieldValue>
|
||||
Finder<ModelClass> & lt(const wchar_t * field_name, const FieldValue & field_value)
|
||||
{
|
||||
if( db_expression )
|
||||
{
|
||||
db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_LT);
|
||||
db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false);
|
||||
db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false, &model_env);
|
||||
}
|
||||
|
||||
return *this;
|
||||
|
@ -359,7 +363,7 @@ public:
|
|||
if( db_expression )
|
||||
{
|
||||
db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_GT);
|
||||
db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false);
|
||||
db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false, &model_env);
|
||||
}
|
||||
|
||||
return *this;
|
||||
|
@ -372,7 +376,7 @@ public:
|
|||
if( db_expression )
|
||||
{
|
||||
db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_LE);
|
||||
db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false);
|
||||
db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false, &model_env);
|
||||
}
|
||||
|
||||
return *this;
|
||||
|
@ -385,7 +389,7 @@ public:
|
|||
if( db_expression )
|
||||
{
|
||||
db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_GE);
|
||||
db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false);
|
||||
db_expression->field_to_stream(*out_stream, field_name, field_value, false, false, false, &model_env);
|
||||
}
|
||||
|
||||
return *this;
|
||||
|
@ -399,7 +403,7 @@ public:
|
|||
if( db_expression )
|
||||
{
|
||||
db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_IN);
|
||||
db_expression->field_in(*out_stream, field_name, container);
|
||||
db_expression->field_in(*out_stream, field_name, container, &model_env);
|
||||
}
|
||||
|
||||
return *this;
|
||||
|
@ -411,7 +415,7 @@ public:
|
|||
if( db_expression )
|
||||
{
|
||||
db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_IN);
|
||||
db_expression->field_in(*out_stream, field_name, container);
|
||||
db_expression->field_in(*out_stream, field_name, container, &model_env);
|
||||
}
|
||||
|
||||
return *this;
|
||||
|
@ -423,7 +427,7 @@ public:
|
|||
if( db_expression )
|
||||
{
|
||||
db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_IN);
|
||||
db_expression->field_in(*out_stream, field_name, container);
|
||||
db_expression->field_in(*out_stream, field_name, container, &model_env);
|
||||
}
|
||||
|
||||
return *this;
|
||||
|
@ -495,6 +499,7 @@ public:
|
|||
{
|
||||
Cursor<ModelClass> cursor;
|
||||
cursor.set_model_data(model_data);
|
||||
cursor.set_has_autogenerated_select(has_autogenerated_select);
|
||||
|
||||
if( model_connector && out_stream )
|
||||
{
|
||||
|
@ -544,7 +549,23 @@ public:
|
|||
std::list<ModelClass> result;
|
||||
|
||||
get_list(result, false);
|
||||
return std::move(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
void set_out_stream()
|
||||
{
|
||||
if( model_connector )
|
||||
{
|
||||
this->out_stream = model_connector->get_stream();
|
||||
}
|
||||
else
|
||||
{
|
||||
this->out_stream = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -559,9 +580,10 @@ private:
|
|||
ModelClass model;
|
||||
bool was_query_error;
|
||||
std::wstring last_query_error;
|
||||
ModelEnv model_env;
|
||||
FinderHelper finder_helper;
|
||||
ModelData * model_data;
|
||||
std::wstring column_prefix;
|
||||
|
||||
bool has_autogenerated_select;
|
||||
|
||||
|
||||
void set_db_expression()
|
||||
|
@ -578,6 +600,8 @@ private:
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* This file is a part of morm
|
||||
* and is distributed under the 2-Clause BSD licence.
|
||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2019, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef headerfile_morm_finderhelper
|
||||
#define headerfile_morm_finderhelper
|
||||
|
||||
#include "queryresult.h"
|
||||
|
||||
|
||||
namespace morm
|
||||
{
|
||||
|
||||
|
||||
class FinderHelper
|
||||
{
|
||||
public:
|
||||
|
||||
PT::TextStream join_tables_str;
|
||||
|
||||
std::map<std::string, int> join_tables_map;
|
||||
|
||||
std::list<std::string> foreign_keys;
|
||||
|
||||
|
||||
|
||||
FinderHelper()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual ~FinderHelper()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual void clear()
|
||||
{
|
||||
join_tables_str.clear();
|
||||
join_tables_map.clear();
|
||||
foreign_keys.clear();
|
||||
}
|
||||
|
||||
|
||||
virtual int add_join_table(const PT::TextStream & table_name)
|
||||
{
|
||||
std::string table_name_str;
|
||||
table_name.to_string(table_name_str);
|
||||
|
||||
return add_join_table(table_name_str);
|
||||
}
|
||||
|
||||
|
||||
virtual int add_join_table(const std::string & table_name)
|
||||
{
|
||||
auto res = join_tables_map.insert(std::make_pair(table_name, 1));
|
||||
|
||||
if( !res.second )
|
||||
{
|
||||
res.first->second += 1;
|
||||
}
|
||||
|
||||
return res.first->second;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -74,7 +74,9 @@ void FlatConnector::to_text(PT::TextStream & stream, Model & model)
|
|||
|
||||
if( flat_expression )
|
||||
{
|
||||
flat_expression->clear();
|
||||
flat_expression->set_work_mode(MORM_WORK_MODE_MODEL_FIELDS_VALUES);
|
||||
flat_expression->allow_to_use_prefix(false);
|
||||
flat_expression->generate_from_model(stream, model);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -137,6 +137,18 @@ void JSONExpression::put_name_value_separator()
|
|||
}
|
||||
|
||||
|
||||
void JSONExpression::before_field_value_list()
|
||||
{
|
||||
(*out_stream) << "[";
|
||||
}
|
||||
|
||||
|
||||
void JSONExpression::after_field_value_list()
|
||||
{
|
||||
(*out_stream) << "]";
|
||||
}
|
||||
|
||||
|
||||
void JSONExpression::esc(char val, PT::TextStream & stream)
|
||||
{
|
||||
switch( val )
|
||||
|
|
|
@ -64,15 +64,8 @@ protected:
|
|||
void before_field_value(const PT::Date &);
|
||||
void after_field_value(const PT::Date &);
|
||||
|
||||
|
||||
template<typename FieldValue>
|
||||
void print_field_name_value(const wchar_t * field_name, const FieldValue & field_value)
|
||||
{
|
||||
put_field_name(field_name);
|
||||
(*out_stream) << ":";
|
||||
put_field_value(field_value);
|
||||
}
|
||||
|
||||
void before_field_value_list();
|
||||
void after_field_value_list();
|
||||
|
||||
|
||||
void esc(char val, PT::TextStream & stream);
|
||||
|
|
136
src/model.cpp
136
src/model.cpp
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018, Tomasz Sowa
|
||||
* Copyright (c) 2018-2019, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -41,11 +41,8 @@ namespace morm
|
|||
Model::Model()
|
||||
{
|
||||
model_connector = nullptr;
|
||||
model_data = nullptr;
|
||||
doc_field_pointer = nullptr;
|
||||
model_env = nullptr;
|
||||
save_mode = DO_INSERT_ON_SAVE;
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
query_result = nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
@ -53,11 +50,7 @@ Model::Model(const Model & m)
|
|||
{
|
||||
model_connector = m.model_connector;
|
||||
save_mode = m.save_mode;
|
||||
|
||||
model_data = nullptr;
|
||||
doc_field_pointer = nullptr; // does it need to be copied?
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
query_result = nullptr;
|
||||
model_env = m.model_env; // or just set to null?
|
||||
}
|
||||
|
||||
|
||||
|
@ -65,6 +58,7 @@ Model::~Model()
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
void Model::set_save_mode(SaveMode save_mode)
|
||||
{
|
||||
this->save_mode = save_mode;
|
||||
|
@ -105,6 +99,7 @@ void Model::table_name(PT::TextStream & stream)
|
|||
}
|
||||
|
||||
|
||||
|
||||
void Model::set_connector(ModelConnector & connector)
|
||||
{
|
||||
set_connector(&connector);
|
||||
|
@ -136,7 +131,10 @@ void Model::to_text(PT::TextStream & stream, ModelData * model_data, bool clear_
|
|||
stream.clear();
|
||||
}
|
||||
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_FLAT_STRING;
|
||||
ModelEnv model_env_local;
|
||||
model_env = &model_env_local;
|
||||
|
||||
model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_FLAT_STRING;
|
||||
|
||||
if( model_connector )
|
||||
{
|
||||
|
@ -144,13 +142,14 @@ void Model::to_text(PT::TextStream & stream, ModelData * model_data, bool clear_
|
|||
|
||||
if( flat_connector )
|
||||
{
|
||||
this->model_data = model_data;
|
||||
model_env->model_data = model_data;
|
||||
flat_connector->to_text(stream, *this);
|
||||
this->model_data = nullptr;
|
||||
model_env->model_data = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
// what about if an exception was thrown? this pointer will not be null
|
||||
model_env = nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
@ -213,7 +212,7 @@ std::string Model::to_string()
|
|||
|
||||
void Model::generate_insert_query(PT::TextStream & stream)
|
||||
{
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL;
|
||||
model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL;
|
||||
|
||||
if( model_connector )
|
||||
{
|
||||
|
@ -225,7 +224,7 @@ void Model::generate_insert_query(PT::TextStream & stream)
|
|||
}
|
||||
}
|
||||
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -236,8 +235,11 @@ bool Model::insert(ModelData * model_data)
|
|||
|
||||
if( model_connector )
|
||||
{
|
||||
this->model_data = model_data;
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL;
|
||||
ModelEnv model_env_local;
|
||||
model_env = &model_env_local;
|
||||
|
||||
model_env->model_data = model_data;
|
||||
model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL;
|
||||
DbConnector * db_connector = model_connector->get_db_connector();
|
||||
|
||||
// CHECK ME what if the stream is being used by something other?
|
||||
|
@ -260,8 +262,8 @@ bool Model::insert(ModelData * model_data)
|
|||
}
|
||||
}
|
||||
|
||||
this->model_data = nullptr;
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
// what about if an exception was thrown? this pointer will not be null
|
||||
model_env = nullptr;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -277,7 +279,7 @@ bool Model::insert(ModelData & model_data)
|
|||
|
||||
void Model::generate_update_query(PT::TextStream & stream)
|
||||
{
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL;
|
||||
model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL;
|
||||
|
||||
if( model_connector )
|
||||
{
|
||||
|
@ -289,7 +291,7 @@ void Model::generate_update_query(PT::TextStream & stream)
|
|||
}
|
||||
}
|
||||
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -299,8 +301,11 @@ bool Model::update(ModelData * model_data)
|
|||
|
||||
if( model_connector )
|
||||
{
|
||||
this->model_data = model_data;
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL;
|
||||
ModelEnv model_env_local;
|
||||
model_env = &model_env_local;
|
||||
|
||||
model_env->model_data = model_data;
|
||||
model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL;
|
||||
DbConnector * db_connector = model_connector->get_db_connector();
|
||||
|
||||
// CHECK ME what if the stream is being used by something other?
|
||||
|
@ -318,8 +323,8 @@ bool Model::update(ModelData * model_data)
|
|||
after_update_failure();
|
||||
}
|
||||
|
||||
this->model_data = nullptr;
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
// what about if an exception was thrown? this pointer will not be null
|
||||
model_env = nullptr;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -337,14 +342,14 @@ void Model::generate_remove_query(PT::TextStream & stream)
|
|||
if( model_connector )
|
||||
{
|
||||
DbConnector * db_connector = model_connector->get_db_connector();
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL;
|
||||
model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL;
|
||||
|
||||
if( db_connector )
|
||||
{
|
||||
db_connector->generate_remove_query(stream, *this);
|
||||
}
|
||||
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -355,8 +360,11 @@ bool Model::remove(ModelData * model_data)
|
|||
|
||||
if( model_connector )
|
||||
{
|
||||
this->model_data = model_data;
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL;
|
||||
ModelEnv model_env_local;
|
||||
model_env = &model_env_local;
|
||||
|
||||
model_env->model_data = model_data;
|
||||
model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL;
|
||||
DbConnector * db_connector = model_connector->get_db_connector();
|
||||
|
||||
// CHECK ME what if the stream is being used by something other?
|
||||
|
@ -379,8 +387,8 @@ bool Model::remove(ModelData * model_data)
|
|||
}
|
||||
}
|
||||
|
||||
this->model_data = nullptr;
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
// what about if an exception was thrown? this pointer will not be null
|
||||
model_env = nullptr;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -426,19 +434,17 @@ bool Model::save(ModelData & model_data)
|
|||
}
|
||||
|
||||
|
||||
void Model::generate_select_columns(PT::TextStream & stream, const std::wstring & column_prefix)
|
||||
void Model::generate_select_columns(PT::TextStream & stream)
|
||||
{
|
||||
if( model_connector )
|
||||
if( model_connector && model_env )
|
||||
{
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL;
|
||||
model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL;
|
||||
DbConnector * db_connector = model_connector->get_db_connector();
|
||||
|
||||
if( db_connector )
|
||||
{
|
||||
db_connector->generate_select_columns(stream, *this, column_prefix);
|
||||
db_connector->generate_select_columns(stream, *this);
|
||||
}
|
||||
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -451,7 +457,7 @@ void Model::generate_doc_for_flat(PT::TextStream & stream, bool clear_stream)
|
|||
stream.clear();
|
||||
}
|
||||
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DOC_FOR_FLAT;
|
||||
model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DOC_FOR_FLAT;
|
||||
|
||||
if( model_connector )
|
||||
{
|
||||
|
@ -463,7 +469,7 @@ void Model::generate_doc_for_flat(PT::TextStream & stream, bool clear_stream)
|
|||
}
|
||||
}
|
||||
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -474,7 +480,7 @@ void Model::generate_doc_for_db(PT::TextStream & stream, bool clear_stream)
|
|||
stream.clear();
|
||||
}
|
||||
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DOC_FOR_DB;
|
||||
model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DOC_FOR_DB;
|
||||
|
||||
if( model_connector )
|
||||
{
|
||||
|
@ -486,31 +492,32 @@ void Model::generate_doc_for_db(PT::TextStream & stream, bool clear_stream)
|
|||
}
|
||||
}
|
||||
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
}
|
||||
|
||||
|
||||
void Model::map_values_from_query(QueryResult * query_result)
|
||||
void Model::map_values_from_query()
|
||||
{
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_READING_VALUE_FROM_DB_RESULTSET;
|
||||
this->query_result = query_result;
|
||||
|
||||
map_fields();
|
||||
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
this->query_result = nullptr;
|
||||
if( model_env )
|
||||
{
|
||||
model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_READING_VALUE_FROM_DB_RESULTSET;
|
||||
map_fields();
|
||||
model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Model::clear()
|
||||
{
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_CLEARING_VALUE;
|
||||
ModelEnv model_env_local;
|
||||
model_env = &model_env_local;
|
||||
|
||||
model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_CLEARING_VALUE;
|
||||
map_fields();
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
model_env = nullptr;
|
||||
|
||||
save_mode = DO_INSERT_ON_SAVE;
|
||||
model_data = nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
@ -569,9 +576,30 @@ void Model::after_remove_failure()
|
|||
|
||||
int Model::get_connector_mode()
|
||||
{
|
||||
return model_connector_mode;
|
||||
if( model_env )
|
||||
{
|
||||
return model_env->model_connector_mode;
|
||||
}
|
||||
else
|
||||
{
|
||||
return MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ModelData * Model::get_model_data()
|
||||
{
|
||||
if( model_env )
|
||||
{
|
||||
return model_env->model_data;
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Model::is_empty_field(const wchar_t * value)
|
||||
{
|
||||
return (!value || *value == '\0');
|
||||
|
|
366
src/model.h
366
src/model.h
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018, Tomasz Sowa
|
||||
* Copyright (c) 2018-2019, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -41,8 +41,7 @@
|
|||
#include "modelconnector.h"
|
||||
#include "dbexpression.h"
|
||||
#include "flatexpression.h"
|
||||
#include "queryresult.h"
|
||||
#include "modeldata.h"
|
||||
#include "modelenv.h"
|
||||
|
||||
|
||||
|
||||
|
@ -97,33 +96,33 @@ public:
|
|||
*/
|
||||
virtual void table_name(PT::TextStream & stream);
|
||||
|
||||
virtual void to_text(PT::TextStream & stream, ModelData * model_data = nullptr, bool clear_stream = true);
|
||||
virtual void to_text(PT::TextStream & stream, ModelData & model_data, bool clear_stream = true);
|
||||
virtual void to_text(PT::TextStream & stream, ModelData * model_data, bool clear_stream = true);
|
||||
virtual void to_text(PT::TextStream & stream, ModelData & model_data, bool clear_stream = true);
|
||||
virtual void to_text(PT::TextStream & stream, bool clear_stream = true);
|
||||
|
||||
virtual void to_text(std::string & str, ModelData * model_data = nullptr, bool clear_string = true);
|
||||
virtual void to_text(std::string & str, ModelData & model_data, bool clear_string = true);
|
||||
virtual void to_text(std::string & str, ModelData * model_data, bool clear_string = true);
|
||||
virtual void to_text(std::string & str, ModelData & model_data, bool clear_string = true);
|
||||
virtual void to_text(std::string & str, bool clear_string = true);
|
||||
|
||||
virtual std::string to_text();
|
||||
virtual std::string to_string();
|
||||
|
||||
virtual void generate_insert_query(PT::TextStream & stream);
|
||||
virtual void generate_insert_query(PT::TextStream & stream); // FIX ME needed model_data
|
||||
virtual bool insert(ModelData * model_data = nullptr);
|
||||
virtual bool insert(ModelData & model_data);
|
||||
|
||||
virtual void generate_update_query(PT::TextStream & stream);
|
||||
virtual void generate_update_query(PT::TextStream & stream); // FIX ME needed model_data
|
||||
virtual bool update(ModelData * model_data = nullptr);
|
||||
virtual bool update(ModelData & model_data);
|
||||
|
||||
virtual void generate_remove_query(PT::TextStream & stream);
|
||||
virtual void generate_remove_query(PT::TextStream & stream); // FIX ME needed model_data
|
||||
virtual bool remove(ModelData * model_data = nullptr);
|
||||
virtual bool remove(ModelData & model_data);
|
||||
|
||||
virtual bool save(ModelData * model_data = nullptr);
|
||||
virtual bool save(ModelData & model_data);
|
||||
|
||||
virtual void generate_select_columns(PT::TextStream & stream, const std::wstring & column_prefix);
|
||||
virtual void generate_select_columns(PT::TextStream & stream);
|
||||
|
||||
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,14 +131,13 @@ public:
|
|||
virtual void clear();
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
ModelConnector * model_connector;
|
||||
SaveMode save_mode;
|
||||
ModelData * model_data;
|
||||
const void * doc_field_pointer;
|
||||
int model_connector_mode;
|
||||
QueryResult * query_result;
|
||||
ModelEnv * model_env;
|
||||
|
||||
|
||||
|
||||
Model();
|
||||
|
@ -163,8 +161,10 @@ protected:
|
|||
|
||||
virtual int get_connector_mode();
|
||||
|
||||
// used by Cursor
|
||||
virtual void map_values_from_query(QueryResult * query_result);
|
||||
virtual ModelData * get_model_data();
|
||||
|
||||
|
||||
virtual void map_values_from_query();
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
|
@ -269,15 +269,16 @@ protected:
|
|||
field_generic(field_name, field_name, field_value, insertable, updatable, is_primary_key);
|
||||
}
|
||||
|
||||
void field(const wchar_t * field_name, Model & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false)
|
||||
void field(const wchar_t * field_name, Model & field_value, bool insertable = true, bool updatable = true)
|
||||
{
|
||||
field_model(field_name, field_name, field_value, insertable, updatable, is_primary_key);
|
||||
field_model(field_name, field_name, field_value, insertable, updatable, true);
|
||||
}
|
||||
|
||||
template<typename ModelClass>
|
||||
void field(const wchar_t * field_name, std::list<ModelClass> & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false)
|
||||
void field(const wchar_t * field_name, std::list<ModelClass> & field_value, bool insertable = true, bool updatable = true)
|
||||
{
|
||||
field_list(field_name, field_name, field_value, insertable, updatable, is_primary_key);
|
||||
ModelClass * list_model_null_pointer = nullptr;
|
||||
field_list(field_name, field_name, field_value, list_model_null_pointer, insertable, updatable);
|
||||
}
|
||||
|
||||
|
||||
|
@ -384,15 +385,16 @@ protected:
|
|||
}
|
||||
|
||||
|
||||
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, Model & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false)
|
||||
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, Model & field_value, bool insertable = true, bool updatable = true)
|
||||
{
|
||||
field_model(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key);
|
||||
field_model(db_field_name, flat_field_name, field_value, insertable, updatable, true);
|
||||
}
|
||||
|
||||
template<typename ModelClass>
|
||||
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::list<ModelClass> & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false)
|
||||
void field(const wchar_t * db_field_name, const wchar_t * flat_field_name, std::list<ModelClass> & field_value, bool insertable = true, bool updatable = true)
|
||||
{
|
||||
field_list(db_field_name, flat_field_name, field_value, insertable, updatable, is_primary_key);
|
||||
ModelClass * list_model_null_pointer = nullptr;
|
||||
field_list(db_field_name, flat_field_name, field_value, list_model_null_pointer, insertable, updatable);
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
|
@ -631,9 +633,9 @@ protected:
|
|||
template<typename FieldValue>
|
||||
void field_generic(const wchar_t * db_field_name, const wchar_t * flat_field_name, FieldValue & field_value, bool insertable, bool updatable, bool is_primary_key)
|
||||
{
|
||||
if( model_connector )
|
||||
if( model_connector && model_env )
|
||||
{
|
||||
if( model_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();
|
||||
|
||||
|
@ -644,12 +646,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);
|
||||
flat_expression->field(flat_field_name, field_value, insertable, updatable, is_primary_key, model_env);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
|
@ -659,23 +661,33 @@ protected:
|
|||
|
||||
if( db_expression && !is_empty_field(db_field_name) )
|
||||
{
|
||||
db_expression->field(db_field_name, field_value, insertable, updatable, is_primary_key);
|
||||
db_expression->field(db_field_name, field_value, insertable, updatable, is_primary_key, model_env);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
if( db_connector )
|
||||
{
|
||||
if( !is_empty_field(db_field_name) )
|
||||
get_value_by_field_name(db_field_name, field_value);
|
||||
{
|
||||
if( model_env->model_data && model_env->cursor_helper && model_env->cursor_helper->has_autogenerated_select )
|
||||
{
|
||||
get_value_by_field_index(model_env->cursor_helper->current_column, field_value);
|
||||
model_env->cursor_helper->current_column += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
get_value_by_field_name(db_field_name, field_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
|
@ -685,7 +697,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)
|
||||
|
||||
|
@ -697,7 +709,7 @@ protected:
|
|||
if( doc_expression && !is_empty_field(flat_field_name) )
|
||||
{
|
||||
// insertable, updatable and is_primary_key are ignored here
|
||||
doc_expression->field_doc(*this, flat_field_name, field_value, insertable, updatable, is_primary_key);
|
||||
doc_expression->field_doc(*this, flat_field_name, field_value, insertable, updatable, is_primary_key, model_env);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -705,70 +717,205 @@ protected:
|
|||
}
|
||||
|
||||
|
||||
void field_model(const wchar_t * db_field_name, const wchar_t * flat_field_name, Model & field_model, bool insertable, bool updatable, bool is_primary_key)
|
||||
void field_model_left_join(const wchar_t * db_field_name, const wchar_t * flat_field_name, Model & field_model, bool insertable, bool updatable, bool has_foreign_key, DbExpression * db_expression)
|
||||
{
|
||||
if( model_connector )
|
||||
if( model_env && field_model.model_env && model_env->finder_helper )
|
||||
{
|
||||
model_env->finder_helper->foreign_keys.clear();
|
||||
field_model.model_env->table_index = model_env->finder_helper->add_join_table(field_model.model_env->table_name_short);
|
||||
|
||||
model_env->finder_helper->join_tables_str << "LEFT JOIN " << field_model.model_env->table_name
|
||||
<< " AS " << field_model.model_env->table_name_short;
|
||||
|
||||
if( field_model.model_env->table_index > 1 )
|
||||
model_env->finder_helper->join_tables_str << field_model.model_env->table_index;
|
||||
|
||||
int expr_work_mode = db_expression->get_work_mode();
|
||||
int expr_output_type = db_expression->get_output_type();
|
||||
bool expr_allow_prefix = db_expression->get_allow_to_use_prefix();
|
||||
|
||||
db_expression->set_work_mode(MORM_WORK_MODE_MODEL_SAVE_FIELDS);
|
||||
db_expression->set_output_type(MORM_OUTPUT_TYPE_JOIN_TABLES);
|
||||
db_expression->allow_to_use_prefix(false);
|
||||
|
||||
if( has_foreign_key )
|
||||
{
|
||||
field_model.map_fields();
|
||||
|
||||
model_env->finder_helper->join_tables_str << " ON " << model_env->table_name_short << '.'
|
||||
<< db_field_name << " = " << field_model.model_env->table_name_short << '.';
|
||||
|
||||
if( model_env->finder_helper->foreign_keys.size() == 1 )
|
||||
{
|
||||
model_env->finder_helper->join_tables_str << model_env->finder_helper->foreign_keys.front();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
map_fields();
|
||||
|
||||
model_env->finder_helper->join_tables_str << " ON " << model_env->table_name_short << '.';
|
||||
|
||||
if( model_env->finder_helper->foreign_keys.size() == 1 )
|
||||
{
|
||||
model_env->finder_helper->join_tables_str << model_env->finder_helper->foreign_keys.front();
|
||||
}
|
||||
|
||||
model_env->finder_helper->join_tables_str << " = " << field_model.model_env->table_name_short << '.' << db_field_name;
|
||||
}
|
||||
|
||||
model_env->finder_helper->join_tables_str << ' ';
|
||||
|
||||
db_expression->set_work_mode(expr_work_mode);
|
||||
db_expression->set_output_type(expr_output_type);
|
||||
db_expression->allow_to_use_prefix(expr_allow_prefix);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void field_model_generate_flat_string(const wchar_t * db_field_name, const wchar_t * flat_field_name, Model & field_model, bool insertable, bool updatable)
|
||||
{
|
||||
FlatConnector * flat_connector = model_connector->get_flat_connector();
|
||||
|
||||
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, 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)
|
||||
{
|
||||
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;
|
||||
|
||||
field_model.table_name(field_model.model_env->table_name);
|
||||
db_expression->prepare_short_table_name(field_model.model_env->table_name, field_model.model_env->table_name_short);
|
||||
|
||||
if( db_expression->get_output_type() == MORM_OUTPUT_TYPE_SELECT_COLUMNS )
|
||||
{
|
||||
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.map_fields();
|
||||
}
|
||||
|
||||
field_model.model_env->model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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, model_env);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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 && model_env )
|
||||
{
|
||||
ModelEnv model_env_local;
|
||||
model_env_local.copy_global_objects(*model_env);
|
||||
|
||||
field_model.model_env = &model_env_local;
|
||||
field_model.set_connector(model_connector);
|
||||
field_model.model_data = model_data;
|
||||
|
||||
// IMPLEMENTME what about db?
|
||||
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, is_primary_key);
|
||||
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);
|
||||
}
|
||||
|
||||
if( model_connector_mode == MORM_MODEL_CONNECTOR_MODE_CLEARING_VALUE )
|
||||
if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_SQL )
|
||||
{
|
||||
Clearer * clearer = model_connector->get_clearer();
|
||||
|
||||
if( clearer )
|
||||
{
|
||||
clearer->clear_model(field_model);
|
||||
}
|
||||
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_GENERATING_DOC_FOR_FLAT )
|
||||
if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_CLEARING_VALUE )
|
||||
{
|
||||
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, is_primary_key);
|
||||
}
|
||||
}
|
||||
field_model_clear_values(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_GENERATING_DOC_FOR_FLAT )
|
||||
{
|
||||
field_model_generate_doc_flat(db_field_name, flat_field_name, field_model, insertable, updatable, has_foreign_key);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename ModelContainer>
|
||||
void field_list(const wchar_t * db_field_name, const wchar_t * flat_field_name, ModelContainer & field_container, bool insertable, bool updatable, bool is_primary_key)
|
||||
template<typename ModelContainer, typename ModelContainerType>
|
||||
void field_list(const wchar_t * db_field_name, const wchar_t * flat_field_name, ModelContainer & field_container, ModelContainerType * model_container_type, bool insertable, bool updatable)
|
||||
{
|
||||
// IMPLEMENTME what about db?
|
||||
if( model_connector )
|
||||
if( model_connector && model_env )
|
||||
{
|
||||
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();
|
||||
|
||||
|
@ -781,12 +928,30 @@ protected:
|
|||
// IMPROVE ME
|
||||
// what about model_data and save_mode?
|
||||
// may it should be placed inside some structure?
|
||||
flat_expression->field_list(flat_field_name, field_container, insertable, updatable, is_primary_key, model_connector, model_connector_mode, model_data);
|
||||
flat_expression->field_list(flat_field_name, field_container, insertable, updatable, false, model_connector, model_env);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( model_connector_mode == MORM_MODEL_CONNECTOR_MODE_CLEARING_VALUE )
|
||||
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) && db_expression->get_output_type() != MORM_OUTPUT_TYPE_JOIN_TABLES )
|
||||
{
|
||||
// another select will be used (from another Finder)
|
||||
// we need only columns name
|
||||
// but columns are defined in the other model
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( model_env->model_connector_mode == MORM_MODEL_CONNECTOR_MODE_CLEARING_VALUE )
|
||||
{
|
||||
Clearer * clearer = model_connector->get_clearer();
|
||||
|
||||
|
@ -796,7 +961,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)
|
||||
|
||||
|
@ -808,7 +973,7 @@ protected:
|
|||
if( doc_expression && !is_empty_field(flat_field_name) )
|
||||
{
|
||||
// insertable, updatable and is_primary_key are ignored here
|
||||
doc_expression->field_doc(*this, flat_field_name, field_container, insertable, updatable, is_primary_key, model_data);
|
||||
doc_expression->field_doc(*this, flat_field_name, field_container, insertable, updatable, false, model_env);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -816,12 +981,32 @@ protected:
|
|||
}
|
||||
|
||||
|
||||
template<typename FieldValue>
|
||||
void get_value_by_field_index(int field_index, FieldValue & field_value)
|
||||
{
|
||||
if( model_env->cursor_helper && model_env->cursor_helper->query_result )
|
||||
{
|
||||
const char * val_str = model_env->cursor_helper->query_result->get_field_string_value(field_index);
|
||||
|
||||
if( val_str )
|
||||
{
|
||||
DbConnector * db_connector = model_connector->get_db_connector();
|
||||
|
||||
if( db_connector )
|
||||
{
|
||||
db_connector->get_value(val_str, field_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename FieldValue>
|
||||
void get_value_by_field_name(const wchar_t * field_name, FieldValue & field_value)
|
||||
{
|
||||
if( query_result )
|
||||
if( model_env->cursor_helper && model_env->cursor_helper->query_result )
|
||||
{
|
||||
const char * val_str = query_result->get_field_string_value(field_name);
|
||||
const char * val_str = model_env->cursor_helper->query_result->get_field_string_value(field_name);
|
||||
|
||||
if( val_str )
|
||||
{
|
||||
|
@ -840,7 +1025,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();
|
||||
|
||||
|
@ -864,7 +1049,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();
|
||||
|
||||
|
@ -889,7 +1074,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();
|
||||
|
||||
|
@ -976,8 +1161,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;
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#define headerfile_morm_modeldata
|
||||
|
||||
|
||||
|
||||
namespace morm
|
||||
{
|
||||
|
||||
|
@ -43,19 +44,14 @@ class ModelData
|
|||
{
|
||||
public:
|
||||
|
||||
ModelData() {}
|
||||
virtual ~ModelData() {}
|
||||
ModelData()
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~ModelData()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* may to add:
|
||||
* std::set<std::wstring> skip_columns;
|
||||
* and Finder can use this
|
||||
* also update and insert from Model
|
||||
* (but what about the same name of columns through the whole objects-tree?
|
||||
* may we can save the name of the table too?)
|
||||
*
|
||||
*
|
||||
*/
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* This file is a part of morm
|
||||
* and is distributed under the 2-Clause BSD licence.
|
||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2019, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef headerfile_morm_modelenv
|
||||
#define headerfile_morm_modelenv
|
||||
|
||||
#include "modeldata.h"
|
||||
#include "cursorhelper.h"
|
||||
#include "finderhelper.h"
|
||||
#include "morm_types.h"
|
||||
|
||||
|
||||
namespace morm
|
||||
{
|
||||
|
||||
class ModelEnv
|
||||
{
|
||||
public:
|
||||
|
||||
ModelData * model_data;
|
||||
FinderHelper * finder_helper;
|
||||
CursorHelper * cursor_helper;
|
||||
|
||||
int model_connector_mode;
|
||||
const void * doc_field_pointer;
|
||||
|
||||
PT::TextStream table_name;
|
||||
PT::TextStream table_name_short;
|
||||
int table_index;
|
||||
|
||||
|
||||
|
||||
ModelEnv()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
~ModelEnv()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ModelEnv(const ModelEnv & e)
|
||||
{
|
||||
model_data = e.model_data;
|
||||
finder_helper = e.finder_helper;
|
||||
cursor_helper = e.cursor_helper;
|
||||
model_connector_mode = e.model_connector_mode;
|
||||
table_index = e.table_index;
|
||||
doc_field_pointer = e.doc_field_pointer;
|
||||
}
|
||||
|
||||
|
||||
void copy_global_objects(const ModelEnv & e)
|
||||
{
|
||||
model_data = e.model_data;
|
||||
finder_helper = e.finder_helper;
|
||||
cursor_helper = e.cursor_helper;
|
||||
|
||||
model_connector_mode = e.model_connector_mode;
|
||||
|
||||
// what about doc_field_pointer?
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
model_data = nullptr;
|
||||
finder_helper = nullptr;
|
||||
cursor_helper = nullptr;
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
doc_field_pointer = nullptr;
|
||||
table_name.clear();
|
||||
table_name_short.clear();
|
||||
table_index = 0;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018, Tomasz Sowa
|
||||
* Copyright (c) 2018-2019, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -53,6 +53,7 @@
|
|||
#define MORM_WORK_MODE_MODEL_VALUES 2
|
||||
#define MORM_WORK_MODE_MODEL_FIELDS_VALUES 3
|
||||
|
||||
#define MORM_WORK_MODE_MODEL_SAVE_FIELDS 4
|
||||
|
||||
|
||||
// IMPROVE ME give me a better name
|
||||
|
@ -68,12 +69,15 @@
|
|||
//#define MORM_OUTPUT_TYPE_WHERE_CUSTOM 5
|
||||
#define MORM_OUTPUT_TYPE_SELECT_COLUMNS 6
|
||||
|
||||
#define MORM_OUTPUT_TYPE_WHERE_EQ 7
|
||||
#define MORM_OUTPUT_TYPE_WHERE_LT 8
|
||||
#define MORM_OUTPUT_TYPE_WHERE_GT 9
|
||||
#define MORM_OUTPUT_TYPE_WHERE_LE 10
|
||||
#define MORM_OUTPUT_TYPE_WHERE_GE 11
|
||||
#define MORM_OUTPUT_TYPE_WHERE_IN 12
|
||||
#define MORM_OUTPUT_TYPE_JOIN_TABLES 7
|
||||
|
||||
#define MORM_OUTPUT_TYPE_WHERE_EQ 10
|
||||
#define MORM_OUTPUT_TYPE_WHERE_LT 11
|
||||
#define MORM_OUTPUT_TYPE_WHERE_GT 12
|
||||
#define MORM_OUTPUT_TYPE_WHERE_LE 13
|
||||
#define MORM_OUTPUT_TYPE_WHERE_GE 14
|
||||
#define MORM_OUTPUT_TYPE_WHERE_IN 15
|
||||
#define MORM_OUTPUT_TYPE_WHERE_NOT_EQ 16
|
||||
|
||||
|
||||
#define MORM_CONJUNCTION_AND 1
|
||||
|
|
|
@ -47,7 +47,6 @@ namespace morm
|
|||
PostgreSQLConnector::PostgreSQLConnector()
|
||||
{
|
||||
pg_conn = nullptr;
|
||||
log_queries = false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -77,10 +76,6 @@ void PostgreSQLConnector::allocate_default_expression()
|
|||
|
||||
|
||||
|
||||
void PostgreSQLConnector::set_log_queries(bool log_queries)
|
||||
{
|
||||
this->log_queries = log_queries;
|
||||
}
|
||||
|
||||
|
||||
QueryResult * PostgreSQLConnector::create_query_result()
|
||||
|
@ -97,7 +92,7 @@ bool PostgreSQLConnector::do_query(const char * query_str, PostgreSQLQueryResult
|
|||
|
||||
if( log_queries && log )
|
||||
{
|
||||
(*log) << PT::Log::log1 << "Morm: query: " << query_str << PT::Log::logend;
|
||||
(*log) << PT::Log::log3 << "Morm: query: " << query_str << PT::Log::logend;
|
||||
}
|
||||
|
||||
psql_result->psql_result = PQexec(pg_conn, query_str);
|
||||
|
@ -115,6 +110,7 @@ bool PostgreSQLConnector::do_query(const char * query_str, PostgreSQLQueryResult
|
|||
{
|
||||
psql_result->psql_status = PQresultStatus(psql_result->psql_result);
|
||||
psql_result->result_rows = static_cast<size_t>(PQntuples(psql_result->psql_result));
|
||||
psql_result->result_cols = static_cast<size_t>(PQnfields(psql_result->psql_result));
|
||||
}
|
||||
|
||||
if( !psql_result->psql_result || psql_result->psql_status == PGRES_FATAL_ERROR )
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018, Tomasz Sowa
|
||||
* Copyright (c) 2018-2019, Tomasz Sowa
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -54,7 +54,6 @@ public:
|
|||
|
||||
virtual ~PostgreSQLConnector();
|
||||
|
||||
virtual void set_log_queries(bool log_queries);
|
||||
|
||||
bool query(const PT::TextStream & stream, QueryResult & query_result);
|
||||
bool query(const char * query_str, QueryResult & query_result);
|
||||
|
@ -86,10 +85,8 @@ public:
|
|||
protected:
|
||||
|
||||
PGconn * pg_conn;
|
||||
bool log_queries;
|
||||
PT::TextStream stream;
|
||||
std::string query_str;
|
||||
std::string temp_column_name;
|
||||
|
||||
std::wstring db_database;
|
||||
std::wstring db_user;
|
||||
|
|
|
@ -67,6 +67,23 @@ bool PostgreSQLQueryResult::has_db_result()
|
|||
}
|
||||
|
||||
|
||||
const char * PostgreSQLQueryResult::get_field_string_value(int column_index)
|
||||
{
|
||||
const char * value_str = nullptr;
|
||||
|
||||
if( column_index >= 0 && (size_t)column_index < result_cols )
|
||||
{
|
||||
if( cur_row < result_rows )
|
||||
{
|
||||
value_str = PQgetvalue(psql_result, cur_row, column_index);
|
||||
}
|
||||
}
|
||||
|
||||
return value_str;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char * PostgreSQLQueryResult::get_field_string_value(const char * column_name)
|
||||
{
|
||||
const char * value_str = nullptr;
|
||||
|
|
|
@ -57,6 +57,7 @@ struct PostgreSQLQueryResult : public QueryResult
|
|||
|
||||
virtual bool has_db_result();
|
||||
|
||||
const char * get_field_string_value(int column_index);
|
||||
const char * get_field_string_value(const char * column_name);
|
||||
int get_column_index(const char * column_name);
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ QueryResult::~QueryResult()
|
|||
void QueryResult::clear()
|
||||
{
|
||||
result_rows = 0;
|
||||
result_cols = 0;
|
||||
cur_row = 0;
|
||||
status = false;
|
||||
error_msg.clear();
|
||||
|
@ -70,6 +71,12 @@ bool QueryResult::has_db_result()
|
|||
}
|
||||
|
||||
|
||||
const char * QueryResult::get_field_string_value(int column_index)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
const char * QueryResult::get_field_string_value(const char * column_name)
|
||||
{
|
||||
return nullptr;
|
||||
|
|
|
@ -45,6 +45,7 @@ struct QueryResult
|
|||
{
|
||||
bool status;
|
||||
size_t result_rows; // how many rows in the result query
|
||||
size_t result_cols; // how many columns in the result query
|
||||
size_t cur_row; // used for reading
|
||||
std::wstring error_msg;
|
||||
|
||||
|
@ -57,6 +58,7 @@ struct QueryResult
|
|||
virtual void clear();
|
||||
virtual bool has_db_result();
|
||||
|
||||
virtual const char * get_field_string_value(int column_index);
|
||||
virtual const char * get_field_string_value(const char * column_name);
|
||||
virtual const char * get_field_string_value(const wchar_t * field_name);
|
||||
|
||||
|
|
Loading…
Reference in New Issue