some work in morm
- support for fetching rows from db - support for inserting/updating rows git-svn-id: svn://ttmath.org/publicrep/morm/trunk@1081 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
parent
09f31b2803
commit
72b2622d08
|
@ -11,7 +11,9 @@ baseexpression.o: ../../pikotools/convert/text.h
|
|||
baseexpression.o: ../../pikotools/convert/misc.h
|
||||
baseexpression.o: ../../pikotools/membuffer/membuffer.h
|
||||
baseexpression.o: ../../pikotools/textstream/types.h morm_types.h model.h
|
||||
baseexpression.o: modelconnector.h ../../pikotools/utf8/utf8.h
|
||||
baseexpression.o: modelconnector.h dbconnector.h dbexpression.h
|
||||
baseexpression.o: flatexpression.h flatconnector.h
|
||||
baseexpression.o: ../../pikotools/utf8/utf8.h
|
||||
dbconnector.o: dbconnector.h dbexpression.h baseexpression.h
|
||||
dbconnector.o: ../../pikotools/textstream/textstream.h
|
||||
dbconnector.o: ../../pikotools/space/space.h
|
||||
|
@ -22,7 +24,8 @@ dbconnector.o: ../../pikotools/convert/strtoint.h
|
|||
dbconnector.o: ../../pikotools/convert/text.h ../../pikotools/convert/misc.h
|
||||
dbconnector.o: ../../pikotools/membuffer/membuffer.h
|
||||
dbconnector.o: ../../pikotools/textstream/types.h morm_types.h model.h
|
||||
dbconnector.o: modelconnector.h
|
||||
dbconnector.o: modelconnector.h flatexpression.h flatconnector.h
|
||||
dbconnector.o: ../../pikotools/utf8/utf8.h
|
||||
dbexpression.o: dbexpression.h baseexpression.h
|
||||
dbexpression.o: ../../pikotools/textstream/textstream.h
|
||||
dbexpression.o: ../../pikotools/space/space.h
|
||||
|
@ -42,6 +45,7 @@ finder.o: ../../pikotools/convert/misc.h
|
|||
finder.o: ../../pikotools/membuffer/membuffer.h
|
||||
finder.o: ../../pikotools/textstream/types.h modelconnector.h
|
||||
finder.o: baseexpression.h morm_types.h dbconnector.h dbexpression.h
|
||||
finder.o: flatexpression.h flatconnector.h
|
||||
flatconnector.o: flatconnector.h flatexpression.h baseexpression.h
|
||||
flatconnector.o: ../../pikotools/textstream/textstream.h
|
||||
flatconnector.o: ../../pikotools/space/space.h
|
||||
|
@ -54,7 +58,7 @@ flatconnector.o: ../../pikotools/convert/text.h
|
|||
flatconnector.o: ../../pikotools/convert/misc.h
|
||||
flatconnector.o: ../../pikotools/membuffer/membuffer.h
|
||||
flatconnector.o: ../../pikotools/textstream/types.h morm_types.h model.h
|
||||
flatconnector.o: modelconnector.h
|
||||
flatconnector.o: modelconnector.h dbconnector.h dbexpression.h
|
||||
flatexpression.o: flatexpression.h baseexpression.h
|
||||
flatexpression.o: ../../pikotools/textstream/textstream.h
|
||||
flatexpression.o: ../../pikotools/space/space.h
|
||||
|
@ -99,7 +103,8 @@ model.o: ../../pikotools/convert/inttostr.h
|
|||
model.o: ../../pikotools/convert/strtoint.h ../../pikotools/convert/text.h
|
||||
model.o: ../../pikotools/convert/misc.h ../../pikotools/membuffer/membuffer.h
|
||||
model.o: ../../pikotools/textstream/types.h modelconnector.h baseexpression.h
|
||||
model.o: morm_types.h
|
||||
model.o: morm_types.h dbconnector.h dbexpression.h flatexpression.h
|
||||
model.o: flatconnector.h
|
||||
modelconnector.o: modelconnector.h baseexpression.h
|
||||
modelconnector.o: ../../pikotools/textstream/textstream.h
|
||||
modelconnector.o: ../../pikotools/space/space.h
|
||||
|
@ -111,9 +116,9 @@ modelconnector.o: ../../pikotools/convert/strtoint.h
|
|||
modelconnector.o: ../../pikotools/convert/text.h
|
||||
modelconnector.o: ../../pikotools/convert/misc.h
|
||||
modelconnector.o: ../../pikotools/membuffer/membuffer.h
|
||||
modelconnector.o: ../../pikotools/textstream/types.h morm_types.h model.h
|
||||
modelconnector.o: flatconnector.h flatexpression.h dbconnector.h
|
||||
modelconnector.o: dbexpression.h
|
||||
modelconnector.o: ../../pikotools/textstream/types.h morm_types.h
|
||||
modelconnector.o: dbconnector.h dbexpression.h flatexpression.h
|
||||
modelconnector.o: flatconnector.h model.h
|
||||
postgresqlconnector.o: postgresqlconnector.h dbconnector.h dbexpression.h
|
||||
postgresqlconnector.o: baseexpression.h
|
||||
postgresqlconnector.o: ../../pikotools/textstream/textstream.h
|
||||
|
@ -128,6 +133,7 @@ postgresqlconnector.o: ../../pikotools/convert/misc.h
|
|||
postgresqlconnector.o: ../../pikotools/membuffer/membuffer.h
|
||||
postgresqlconnector.o: ../../pikotools/textstream/types.h morm_types.h
|
||||
postgresqlconnector.o: ../../pikotools/utf8/utf8.h postgresqlexpression.h
|
||||
postgresqlconnector.o: ../../pikotools/convert/strtoint.h
|
||||
postgresqlexpression.o: postgresqlexpression.h dbexpression.h
|
||||
postgresqlexpression.o: baseexpression.h
|
||||
postgresqlexpression.o: ../../pikotools/textstream/textstream.h
|
||||
|
|
|
@ -63,15 +63,21 @@ void BaseExpression::set_work_mode(int work_mode)
|
|||
void BaseExpression::generate_from_model(PT::TextStream & stream, Model & model)
|
||||
{
|
||||
this->out_stream = &stream;
|
||||
|
||||
before_generate_from_model();
|
||||
model.map_fields();
|
||||
after_generate_from_model();
|
||||
|
||||
generate_from_model(model);
|
||||
this->out_stream = nullptr;
|
||||
}
|
||||
|
||||
|
||||
void BaseExpression::generate_from_model(Model & model)
|
||||
{
|
||||
if( out_stream )
|
||||
{
|
||||
before_generate_from_model();
|
||||
model.map_fields();
|
||||
after_generate_from_model();
|
||||
}
|
||||
}
|
||||
|
||||
void BaseExpression::before_generate_from_model()
|
||||
{
|
||||
is_first_field = true;
|
||||
|
@ -161,6 +167,14 @@ void BaseExpression::after_field_value(const char *)
|
|||
{
|
||||
}
|
||||
|
||||
void BaseExpression::before_field_value(const PT::Date &)
|
||||
{
|
||||
}
|
||||
|
||||
void BaseExpression::after_field_value(const PT::Date &)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
void BaseExpression::put_name_value_separator()
|
||||
|
@ -315,7 +329,7 @@ void BaseExpression::esc(void* val, PT::TextStream & stream)
|
|||
|
||||
void BaseExpression::esc(const PT::Date & date, PT::TextStream & stream)
|
||||
{
|
||||
stream << "'" << date << "'";
|
||||
stream << date;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#ifndef headerfile_morm_baseexpression
|
||||
#define headerfile_morm_baseexpression
|
||||
|
||||
|
||||
#include <list>
|
||||
#include "textstream/textstream.h"
|
||||
#include "morm_types.h"
|
||||
#include "date/date.h"
|
||||
|
@ -86,6 +86,34 @@ public:
|
|||
}
|
||||
|
||||
|
||||
template<typename ModelClass>
|
||||
void field_list(const wchar_t * field_name, const std::list<ModelClass> & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false)
|
||||
{
|
||||
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_VALUES )
|
||||
// {
|
||||
// put_field_value(field_value);
|
||||
// }
|
||||
// else
|
||||
if( work_mode == MORM_WORK_MODE_MODEL_FIELDS_VALUES )
|
||||
{
|
||||
put_field_name(field_name);
|
||||
put_name_value_separator();
|
||||
put_field_value_list(field_value);
|
||||
}
|
||||
|
||||
field_after();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename FieldValue>
|
||||
void field(PT::TextStream & stream, const wchar_t * field_name, const FieldValue & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false)
|
||||
{
|
||||
|
@ -144,6 +172,8 @@ protected:
|
|||
// generate_from_model();
|
||||
// }
|
||||
|
||||
virtual void generate_from_model(Model & model);
|
||||
|
||||
virtual void before_generate_from_model();
|
||||
virtual void after_generate_from_model();
|
||||
virtual bool can_field_be_generated(bool insertable, bool updatable, bool is_primary_key);
|
||||
|
@ -162,6 +192,38 @@ protected:
|
|||
after_field_value(field_value);
|
||||
}
|
||||
|
||||
template<typename ModelClass>
|
||||
void put_field_value_list(const std::list<ModelClass> & field_value)
|
||||
{
|
||||
if( out_stream )
|
||||
{
|
||||
(*out_stream) << "[";// make a virtual method
|
||||
}
|
||||
|
||||
bool is_first = true;
|
||||
|
||||
for(ModelClass m : field_value)
|
||||
{
|
||||
if( out_stream )
|
||||
{
|
||||
if( !is_first )
|
||||
{
|
||||
if( out_stream )
|
||||
(*out_stream) << ","; // make a virtual method
|
||||
}
|
||||
|
||||
//before_field_value(field_value);
|
||||
generate_from_model(m);
|
||||
//after_field_value(field_value);
|
||||
is_first = false;
|
||||
}
|
||||
}
|
||||
|
||||
if( out_stream )
|
||||
{
|
||||
(*out_stream) << "]";// make a virtual method
|
||||
}
|
||||
}
|
||||
|
||||
virtual void before_field_name();
|
||||
virtual void after_field_name();
|
||||
|
@ -178,6 +240,9 @@ protected:
|
|||
virtual void before_field_value(const char *);
|
||||
virtual void after_field_value(const char *);
|
||||
|
||||
virtual void before_field_value(const PT::Date &);
|
||||
virtual void after_field_value(const PT::Date &);
|
||||
|
||||
|
||||
template<typename FieldValue>
|
||||
void before_field_value(const FieldValue &)
|
||||
|
|
|
@ -32,8 +32,10 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include "dbconnector.h"
|
||||
#include "model.h"
|
||||
#include "utf8/utf8.h"
|
||||
|
||||
|
||||
namespace morm
|
||||
|
@ -45,6 +47,12 @@ DbConnector::DbConnector()
|
|||
expression_allocated = false;
|
||||
}
|
||||
|
||||
DbConnector::DbConnector(const DbConnector &)
|
||||
{
|
||||
db_expression = nullptr;
|
||||
expression_allocated = false;
|
||||
}
|
||||
|
||||
|
||||
DbConnector::~DbConnector()
|
||||
{
|
||||
|
@ -100,13 +108,27 @@ bool DbConnector::query_insert(const PT::TextStream & stream)
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
virtual void DbConnector::map_values_from_query(Model & model)
|
||||
size_t DbConnector::last_select_size()
|
||||
{
|
||||
model.clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void DbConnector::set_current_row_at_beginning()
|
||||
{
|
||||
}
|
||||
|
||||
void DbConnector::advance_current_row()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//void DbConnector::map_values_from_query(Model & model)
|
||||
//{
|
||||
// model.clear();
|
||||
//}
|
||||
|
||||
|
||||
DbExpression * DbConnector::get_expression()
|
||||
{
|
||||
allocate_default_expression_if_needed();
|
||||
|
@ -159,15 +181,12 @@ void DbConnector::generate_update_query(PT::TextStream & stream, Model & model)
|
|||
|
||||
stream << "update ";
|
||||
model.table_name(stream);
|
||||
stream << " set (";
|
||||
db_expression->set_work_mode(MORM_WORK_MODE_MODEL_FIELDS);
|
||||
stream << " set ";
|
||||
|
||||
db_expression->set_work_mode(MORM_WORK_MODE_MODEL_FIELDS_VALUES);
|
||||
db_expression->generate_from_model(stream, model);
|
||||
|
||||
stream << ") values (";
|
||||
db_expression->set_work_mode(MORM_WORK_MODE_MODEL_VALUES);
|
||||
db_expression->generate_from_model(stream, model);
|
||||
|
||||
stream << ") where ";
|
||||
stream << " where ";
|
||||
db_expression->set_work_mode(MORM_WORK_MODE_MODEL_FIELDS_VALUES);
|
||||
db_expression->set_output_type(MORM_OUTPUT_TYPE_DB_PRIMARY_KEY);
|
||||
db_expression->generate_from_model(stream, model);
|
||||
|
@ -176,21 +195,17 @@ void DbConnector::generate_update_query(PT::TextStream & stream, Model & model)
|
|||
|
||||
|
||||
|
||||
void DbConnector::insert(PT::TextStream & stream, Model & model)
|
||||
bool DbConnector::insert(PT::TextStream & stream, Model & model)
|
||||
{
|
||||
generate_insert_query(stream, model);
|
||||
// do the real inserting
|
||||
// query(stream);
|
||||
// and get autogenerated columns
|
||||
return query_insert(stream);
|
||||
}
|
||||
|
||||
|
||||
void DbConnector::update(PT::TextStream & stream, Model & model)
|
||||
bool DbConnector::update(PT::TextStream & stream, Model & model)
|
||||
{
|
||||
generate_update_query(stream, model);
|
||||
// do the real updating
|
||||
// query(stream);
|
||||
// and get autogenerated columns
|
||||
return query_update(stream);
|
||||
}
|
||||
|
||||
|
||||
|
@ -214,7 +229,235 @@ void DbConnector::allocate_default_expression_if_needed()
|
|||
}
|
||||
}
|
||||
|
||||
const char * DbConnector::get_field_string_value(const wchar_t * field_name)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DbConnector::clear_value(char & field_value)
|
||||
{
|
||||
field_value = 0;
|
||||
}
|
||||
|
||||
void DbConnector::clear_value(unsigned char & field_value)
|
||||
{
|
||||
field_value = 0;
|
||||
}
|
||||
|
||||
void DbConnector::clear_value(std::wstring & field_value)
|
||||
{
|
||||
field_value.clear();
|
||||
}
|
||||
|
||||
void DbConnector::clear_value(std::string & field_value)
|
||||
{
|
||||
field_value.clear();
|
||||
}
|
||||
|
||||
void DbConnector::clear_value(bool & field_value)
|
||||
{
|
||||
field_value = false;
|
||||
}
|
||||
|
||||
void DbConnector::clear_value(short & field_value)
|
||||
{
|
||||
field_value = 0;
|
||||
}
|
||||
|
||||
void DbConnector::clear_value(unsigned short & field_value)
|
||||
{
|
||||
field_value = 0;
|
||||
}
|
||||
|
||||
void DbConnector::clear_value(int & field_value)
|
||||
{
|
||||
field_value = 0;
|
||||
}
|
||||
|
||||
void DbConnector::clear_value(unsigned int & field_value)
|
||||
{
|
||||
field_value = 0;
|
||||
}
|
||||
|
||||
void DbConnector::clear_value(long & field_value)
|
||||
{
|
||||
field_value = 0;
|
||||
}
|
||||
|
||||
void DbConnector::clear_value(unsigned long & field_value)
|
||||
{
|
||||
field_value = 0;
|
||||
}
|
||||
|
||||
void DbConnector::clear_value(long long & field_value)
|
||||
{
|
||||
field_value = 0;
|
||||
}
|
||||
|
||||
void DbConnector::clear_value(unsigned long long & field_value)
|
||||
{
|
||||
field_value = 0;
|
||||
}
|
||||
|
||||
void DbConnector::clear_value(float & field_value)
|
||||
{
|
||||
field_value = 0.0f;
|
||||
}
|
||||
|
||||
void DbConnector::clear_value(double & field_value)
|
||||
{
|
||||
field_value = 0.0;
|
||||
}
|
||||
|
||||
void DbConnector::clear_value(long double & field_value)
|
||||
{
|
||||
field_value = 0.0;
|
||||
}
|
||||
|
||||
void DbConnector::clear_value(PT::Date & field_value)
|
||||
{
|
||||
field_value.Clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void DbConnector::get_value(const char * value_str, char & field_value)
|
||||
{
|
||||
field_value = *value_str;
|
||||
value_str += 1;
|
||||
|
||||
if( *value_str != 0 )
|
||||
{
|
||||
// value has more than one charater, put some error?
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DbConnector::get_value(const char * value_str, unsigned char & field_value)
|
||||
{
|
||||
field_value = *(const unsigned char*)value_str;
|
||||
value_str += 1;
|
||||
|
||||
if( *value_str != 0 )
|
||||
{
|
||||
// value has more than one charater, put some error?
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DbConnector::get_value(const char * value_str, std::wstring & field_value)
|
||||
{
|
||||
// CHECKME
|
||||
// what about \0 in val_str?
|
||||
// it is escaped somehow?
|
||||
PT::UTF8ToWide(value_str, field_value);
|
||||
}
|
||||
|
||||
|
||||
void DbConnector::get_value(const char * value_str, std::string & field_value)
|
||||
{
|
||||
field_value = value_str;
|
||||
}
|
||||
|
||||
|
||||
void DbConnector::get_value(const char * value_str, bool & field_value)
|
||||
{
|
||||
// IMPROVE ME
|
||||
// this 't' is locale dependent
|
||||
field_value = (value_str[0]=='t' || value_str[0]=='y' || value_str[0]=='1');
|
||||
}
|
||||
|
||||
|
||||
void DbConnector::get_value(const char * value_str, short & field_value)
|
||||
{
|
||||
// IMPROVE ME give some overflow checking
|
||||
field_value = (short)PT::Toi(value_str, 10);
|
||||
}
|
||||
|
||||
|
||||
void DbConnector::get_value(const char * value_str, unsigned short & field_value)
|
||||
{
|
||||
// IMPROVE ME give some overflow checking
|
||||
field_value = (unsigned short)PT::Toui(value_str, 10);
|
||||
}
|
||||
|
||||
|
||||
void DbConnector::get_value(const char * value_str, int & field_value)
|
||||
{
|
||||
// IMPROVE ME give some overflow checking
|
||||
field_value = PT::Toi(value_str, 10);
|
||||
}
|
||||
|
||||
|
||||
void DbConnector::get_value(const char * value_str, unsigned int & field_value)
|
||||
{
|
||||
// IMPROVE ME give some overflow checking
|
||||
field_value = PT::Toui(value_str, 10);
|
||||
}
|
||||
|
||||
|
||||
void DbConnector::get_value(const char * value_str, long & field_value)
|
||||
{
|
||||
// IMPROVE ME give some overflow checking
|
||||
field_value = PT::Tol(value_str, 10);
|
||||
}
|
||||
|
||||
|
||||
void DbConnector::get_value(const char * value_str, unsigned long & field_value)
|
||||
{
|
||||
// IMPROVE ME give some overflow checking
|
||||
field_value = PT::Toul(value_str, 10);
|
||||
}
|
||||
|
||||
|
||||
void DbConnector::get_value(const char * value_str, long long & field_value)
|
||||
{
|
||||
// IMPROVE ME give some overflow checking
|
||||
field_value = PT::Toll(value_str, 10);
|
||||
}
|
||||
|
||||
|
||||
void DbConnector::get_value(const char * value_str, unsigned long long & field_value)
|
||||
{
|
||||
// IMPROVE ME give some overflow checking
|
||||
field_value = PT::Toull(value_str, 10);
|
||||
}
|
||||
|
||||
|
||||
void DbConnector::get_value(const char * value_str, float & field_value)
|
||||
{
|
||||
// IMPROVE ME give some overflow checking
|
||||
field_value = strtof(value_str, 0);
|
||||
}
|
||||
|
||||
|
||||
void DbConnector::get_value(const char * value_str, double & field_value)
|
||||
{
|
||||
// IMPROVE ME give some overflow checking
|
||||
field_value = strtod(value_str, 0);
|
||||
}
|
||||
|
||||
|
||||
void DbConnector::get_value(const char * value_str, long double & field_value)
|
||||
{
|
||||
// IMPROVE ME give some overflow checking
|
||||
field_value = strtold(value_str, 0);
|
||||
}
|
||||
|
||||
|
||||
void DbConnector::get_value(const char * value_str, PT::Date & field_value)
|
||||
{
|
||||
// IMPROVE ME give some log if parsing failed
|
||||
bool res = field_value.Parse(value_str);
|
||||
}
|
||||
|
||||
|
||||
const char * DbConnector::query_last_sequence(const wchar_t * sequence_table_name)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ class DbConnector
|
|||
public:
|
||||
|
||||
DbConnector();
|
||||
DbConnector(const DbConnector &);
|
||||
virtual ~DbConnector();
|
||||
|
||||
DbExpression * get_expression();
|
||||
|
@ -58,8 +59,11 @@ public:
|
|||
virtual void generate_insert_query(PT::TextStream & stream, Model & model);
|
||||
virtual void generate_update_query(PT::TextStream & stream, Model & model);
|
||||
|
||||
virtual void insert(PT::TextStream & stream, Model & model);
|
||||
virtual void update(PT::TextStream & stream, Model & model);
|
||||
virtual bool insert(PT::TextStream & stream, Model & model);
|
||||
virtual bool update(PT::TextStream & stream, Model & model);
|
||||
|
||||
//void ModelConnector::get_values_from_db(Model & model)
|
||||
|
||||
|
||||
virtual bool query(const PT::TextStream & stream);
|
||||
//virtual bool query(const std::wstring & query);
|
||||
|
@ -71,7 +75,76 @@ public:
|
|||
virtual bool query_update(const PT::TextStream & stream);
|
||||
virtual bool query_insert(const PT::TextStream & stream);
|
||||
|
||||
virtual void map_values_from_query(Model & model);
|
||||
virtual size_t last_select_size();
|
||||
|
||||
// give me a better name
|
||||
virtual void set_current_row_at_beginning();
|
||||
virtual void advance_current_row();
|
||||
|
||||
//virtual void map_values_from_query(Model & model);
|
||||
|
||||
// these methods should be somewhere else
|
||||
// flat_parsers (json parser) can use them as well
|
||||
virtual void clear_value(char & field_value);
|
||||
virtual void clear_value(unsigned char & field_value);
|
||||
virtual void clear_value(std::wstring & field_value);
|
||||
virtual void clear_value(std::string & field_value);
|
||||
virtual void clear_value(bool & field_value);
|
||||
virtual void clear_value(short & field_value);
|
||||
virtual void clear_value(unsigned short & field_value);
|
||||
virtual void clear_value(int & field_value);
|
||||
virtual void clear_value(unsigned int & field_value);
|
||||
virtual void clear_value(long & field_value);
|
||||
virtual void clear_value(unsigned long & field_value);
|
||||
virtual void clear_value(long long & field_value);
|
||||
virtual void clear_value(unsigned long long & field_value);
|
||||
virtual void clear_value(float & field_value);
|
||||
virtual void clear_value(double & field_value);
|
||||
virtual void clear_value(long double & field_value);
|
||||
virtual void clear_value(PT::Date & field_value);
|
||||
|
||||
|
||||
virtual void get_value(const char * value_str, char & field_value);
|
||||
virtual void get_value(const char * value_str, unsigned char & field_value);
|
||||
virtual void get_value(const char * value_str, std::wstring & field_value);
|
||||
virtual void get_value(const char * value_str, std::string & field_value);
|
||||
virtual void get_value(const char * value_str, bool & field_value);
|
||||
virtual void get_value(const char * value_str, short & field_value);
|
||||
virtual void get_value(const char * value_str, unsigned short & field_value);
|
||||
virtual void get_value(const char * value_str, int & field_value);
|
||||
virtual void get_value(const char * value_str, unsigned int & field_value);
|
||||
virtual void get_value(const char * value_str, long & field_value);
|
||||
virtual void get_value(const char * value_str, unsigned long & field_value);
|
||||
virtual void get_value(const char * value_str, long long & field_value);
|
||||
virtual void get_value(const char * value_str, unsigned long long & field_value);
|
||||
virtual void get_value(const char * value_str, float & field_value);
|
||||
virtual void get_value(const char * value_str, double & field_value);
|
||||
virtual void get_value(const char * value_str, long double & field_value);
|
||||
virtual void get_value(const char * value_str, PT::Date & field_value);
|
||||
//virtual void get_value(const char * value_str, void* & field_value);
|
||||
|
||||
|
||||
template<typename FieldValue>
|
||||
void get_value_by_field_name(const wchar_t * field_name, FieldValue & field_value)
|
||||
{
|
||||
const char * val_str = get_field_string_value(field_name);
|
||||
|
||||
if( val_str )
|
||||
{
|
||||
get_value(val_str, field_value);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename FieldValue>
|
||||
void get_last_sequence(const wchar_t * sequence_table_name, FieldValue & field_value)
|
||||
{
|
||||
const char * val_str = query_last_sequence(sequence_table_name);
|
||||
|
||||
if( val_str )
|
||||
{
|
||||
get_value(val_str, field_value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
|
@ -82,6 +155,12 @@ protected:
|
|||
virtual void allocate_default_expression() = 0;
|
||||
virtual void allocate_default_expression_if_needed();
|
||||
virtual void deallocate_expression();
|
||||
virtual const char * get_field_string_value(const wchar_t * field_name);
|
||||
|
||||
virtual const char * query_last_sequence(const wchar_t * sequence_table_name);
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -127,7 +127,8 @@ void DbExpression::field_before()
|
|||
void DbExpression::put_name_value_separator()
|
||||
{
|
||||
if( output_type == MORM_OUTPUT_TYPE_DB_PRIMARY_KEY ||
|
||||
output_type == MORM_OUTPUT_TYPE_WHERE_EQ )
|
||||
output_type == MORM_OUTPUT_TYPE_WHERE_EQ ||
|
||||
output_type == MORM_OUTPUT_TYPE_DB_UPDATE)
|
||||
{
|
||||
(*out_stream) << " = ";
|
||||
}
|
||||
|
@ -218,6 +219,16 @@ void DbExpression::after_field_value(const char *)
|
|||
after_field_value_string();
|
||||
}
|
||||
|
||||
void DbExpression::before_field_value(const PT::Date &)
|
||||
{
|
||||
before_field_value_string();
|
||||
}
|
||||
|
||||
void DbExpression::after_field_value(const PT::Date &)
|
||||
{
|
||||
after_field_value_string();
|
||||
}
|
||||
|
||||
|
||||
void DbExpression::prepare_to_where_clause()
|
||||
{
|
||||
|
|
|
@ -83,6 +83,8 @@ protected:
|
|||
void before_field_value(const char *);
|
||||
void after_field_value(const char *);
|
||||
|
||||
void before_field_value(const PT::Date &);
|
||||
void after_field_value(const PT::Date &);
|
||||
|
||||
void put_name_value_separator();
|
||||
|
||||
|
|
70
src/finder.h
70
src/finder.h
|
@ -263,8 +263,51 @@ public:
|
|||
}
|
||||
|
||||
|
||||
void get_list(std::list<ModelClass> & result, bool clear_list = true)
|
||||
bool get(ModelClass & result)
|
||||
{
|
||||
bool res = false;
|
||||
result.clear();
|
||||
result.set_object_exists(false);
|
||||
|
||||
if( model_connector && out_stream )
|
||||
{
|
||||
DbConnector * db_connector = model_connector->get_db_connector();
|
||||
|
||||
if( db_connector )
|
||||
{
|
||||
res = db_connector->query_select(*out_stream);
|
||||
|
||||
if( res )
|
||||
{
|
||||
result.set_object_exists(true);
|
||||
result.set_connector(*model_connector);
|
||||
result.before_select();
|
||||
model_connector->map_values_from_query(result);
|
||||
result.after_select();
|
||||
}
|
||||
|
||||
if( !res )
|
||||
{
|
||||
// put some log here?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
ModelClass get()
|
||||
{
|
||||
get(model);
|
||||
return model;
|
||||
}
|
||||
|
||||
|
||||
bool get_list(std::list<ModelClass> & result, bool clear_list = true)
|
||||
{
|
||||
bool res = false;
|
||||
|
||||
if( clear_list )
|
||||
{
|
||||
result.clear();
|
||||
|
@ -276,31 +319,40 @@ public:
|
|||
|
||||
if( db_connector )
|
||||
{
|
||||
bool res = db_connector->query_select(*out_stream);
|
||||
res = db_connector->query_select(*out_stream);
|
||||
|
||||
if( res )
|
||||
{
|
||||
//ModelClass model;
|
||||
//db_connector->map_values_from_query(model);
|
||||
size_t len = db_connector->last_select_size();
|
||||
db_connector->set_current_row_at_beginning();
|
||||
|
||||
for(size_t i = 0 ; i < len ; ++i)
|
||||
{
|
||||
model.clear();
|
||||
model.set_object_exists(true);
|
||||
model.set_connector(*model_connector);
|
||||
model.before_select();
|
||||
model_connector->map_values_from_query(model);
|
||||
model.after_select();
|
||||
result.push_back(model);
|
||||
db_connector->advance_current_row();
|
||||
}
|
||||
}
|
||||
|
||||
if( !res )
|
||||
{
|
||||
// put some log here?
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
std::list<ModelClass> get_list()
|
||||
{
|
||||
std::list<ModelClass> result;
|
||||
get_list(result);
|
||||
get_list(result, false);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -119,6 +119,17 @@ void JSONExpression::after_field_value(const std::string &)
|
|||
after_field_value_string();
|
||||
}
|
||||
|
||||
void JSONExpression::before_field_value(const PT::Date &)
|
||||
{
|
||||
before_field_value_string();
|
||||
}
|
||||
|
||||
void JSONExpression::after_field_value(const PT::Date &)
|
||||
{
|
||||
after_field_value_string();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void JSONExpression::put_name_value_separator()
|
||||
{
|
||||
|
|
|
@ -61,6 +61,10 @@ protected:
|
|||
void after_field_value(const std::string &);
|
||||
void put_name_value_separator();
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -146,8 +146,40 @@ void Model::update()
|
|||
|
||||
void Model::clear()
|
||||
{
|
||||
if( model_connector )
|
||||
{
|
||||
model_connector->clear_values(*this);
|
||||
}
|
||||
|
||||
morm_object_exists = false;
|
||||
}
|
||||
|
||||
|
||||
void Model::before_select()
|
||||
{
|
||||
}
|
||||
|
||||
void Model::before_insert()
|
||||
{
|
||||
}
|
||||
|
||||
void Model::before_update()
|
||||
{
|
||||
}
|
||||
|
||||
void Model::after_select()
|
||||
{
|
||||
}
|
||||
|
||||
void Model::after_insert()
|
||||
{
|
||||
}
|
||||
|
||||
void Model::after_update()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
|
31
src/model.h
31
src/model.h
|
@ -89,6 +89,7 @@ public:
|
|||
// set object to default values
|
||||
virtual void clear();
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
ModelConnector * model_connector;
|
||||
|
@ -97,9 +98,16 @@ protected:
|
|||
Model();
|
||||
virtual ~Model();
|
||||
|
||||
virtual void before_select();
|
||||
virtual void before_insert();
|
||||
virtual void before_update();
|
||||
|
||||
virtual void after_select();
|
||||
virtual void after_insert();
|
||||
virtual void after_update();
|
||||
|
||||
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)
|
||||
void field(const wchar_t * field_name, FieldValue & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false)
|
||||
{
|
||||
if( model_connector )
|
||||
{
|
||||
|
@ -107,9 +115,28 @@ protected:
|
|||
}
|
||||
}
|
||||
|
||||
template<typename ModelClass>
|
||||
void field_list(const wchar_t * field_name, std::list<ModelClass> & field_list, bool insertable = true, bool updatable = true, bool is_primary_key = false)
|
||||
{
|
||||
if( model_connector )
|
||||
{
|
||||
model_connector->field_list(field_name, field_list, insertable, updatable, is_primary_key);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename FieldValue>
|
||||
void get_last_sequence(const wchar_t * sequence_table_name, FieldValue & field_value)
|
||||
{
|
||||
if( model_connector )
|
||||
{
|
||||
model_connector->get_last_sequence(sequence_table_name, field_value);
|
||||
}
|
||||
}
|
||||
|
||||
//void field(const wchar_t * field_name, Model & field, bool insertable = true, bool updatable = true);
|
||||
|
||||
|
||||
template<typename ModelClass> friend class Finder;
|
||||
friend class ModelConnector;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -43,9 +43,13 @@ namespace morm
|
|||
|
||||
ModelConnector::ModelConnector()
|
||||
{
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
flat_connector = nullptr;
|
||||
db_connector = nullptr;
|
||||
expression_callback = nullptr;
|
||||
|
||||
|
||||
//expression_callback = nullptr;
|
||||
//db_connector_callback = nullptr;
|
||||
|
||||
out_stream = nullptr;
|
||||
out_stream_allocated = false;
|
||||
|
@ -140,14 +144,16 @@ void ModelConnector::to_text(PT::TextStream & stream, Model & model)
|
|||
{
|
||||
if( flat_connector )
|
||||
{
|
||||
expression_callback = flat_connector->get_expression();
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_FLAT_EXPRESSION;
|
||||
//expression_callback = flat_connector->get_expression();
|
||||
|
||||
if( expression_callback )
|
||||
{
|
||||
//if( expression_callback )
|
||||
//{
|
||||
flat_connector->to_text(stream, model);
|
||||
}
|
||||
//}
|
||||
|
||||
expression_callback = nullptr;
|
||||
//expression_callback = nullptr;
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -156,14 +162,16 @@ void ModelConnector::generate_select_columns(PT::TextStream & stream, Model & mo
|
|||
{
|
||||
if( db_connector )
|
||||
{
|
||||
expression_callback = db_connector->get_expression();
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_EXPRESSION;
|
||||
//expression_callback = db_connector->get_expression();
|
||||
|
||||
if( expression_callback )
|
||||
{
|
||||
//if( expression_callback )
|
||||
//{
|
||||
db_connector->generate_select_columns(stream, model);
|
||||
}
|
||||
//}
|
||||
|
||||
expression_callback = nullptr;
|
||||
//expression_callback = nullptr;
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -173,14 +181,16 @@ void ModelConnector::generate_insert_query(PT::TextStream & stream, Model & mode
|
|||
{
|
||||
if( db_connector )
|
||||
{
|
||||
expression_callback = db_connector->get_expression();
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_EXPRESSION;
|
||||
//expression_callback = db_connector->get_expression();
|
||||
|
||||
if( expression_callback )
|
||||
{
|
||||
//if( expression_callback )
|
||||
//{
|
||||
db_connector->generate_insert_query(stream, model);
|
||||
}
|
||||
//}
|
||||
|
||||
expression_callback = nullptr;
|
||||
//expression_callback = nullptr;
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,14 +199,16 @@ void ModelConnector::generate_update_query(PT::TextStream & stream, Model & mode
|
|||
{
|
||||
if( db_connector )
|
||||
{
|
||||
expression_callback = db_connector->get_expression();
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_EXPRESSION;
|
||||
//expression_callback = db_connector->get_expression();
|
||||
|
||||
if( expression_callback )
|
||||
{
|
||||
//if( expression_callback )
|
||||
//{
|
||||
db_connector->generate_update_query(stream, model);
|
||||
}
|
||||
//}
|
||||
|
||||
expression_callback = nullptr;
|
||||
//expression_callback = nullptr;
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -207,8 +219,16 @@ void ModelConnector::insert(Model & model)
|
|||
|
||||
if( db_connector && out_stream )
|
||||
{
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_EXPRESSION;
|
||||
//db_connector_callback = db_connector;
|
||||
|
||||
model.before_insert();
|
||||
out_stream->clear();
|
||||
db_connector->insert(*out_stream, model);
|
||||
model.after_insert();
|
||||
|
||||
//db_connector_callback = nullptr;
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -219,11 +239,44 @@ void ModelConnector::update(Model & model)
|
|||
|
||||
if( db_connector && out_stream )
|
||||
{
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_EXPRESSION;
|
||||
//db_connector_callback = db_connector;
|
||||
|
||||
model.before_update();
|
||||
out_stream->clear();
|
||||
db_connector->update(*out_stream, model);
|
||||
model.after_update();
|
||||
|
||||
//db_connector_callback = nullptr;
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ModelConnector::map_values_from_query(Model & model)
|
||||
{
|
||||
if( db_connector )
|
||||
{
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_READING_VALUE_FROM_DB;
|
||||
//db_connector_callback = db_connector;
|
||||
model.map_fields();
|
||||
//db_connector_callback = nullptr;
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ModelConnector::clear_values(Model & model)
|
||||
{
|
||||
if( db_connector )
|
||||
{
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_CLEARING_VALUE;
|
||||
model.map_fields();
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -36,14 +36,15 @@
|
|||
#define headerfile_morm_modelconnector
|
||||
|
||||
#include "baseexpression.h"
|
||||
//#include "finder.h"
|
||||
#include "dbconnector.h"
|
||||
#include "flatexpression.h"
|
||||
#include "flatconnector.h"
|
||||
|
||||
|
||||
namespace morm
|
||||
{
|
||||
class Model;
|
||||
class FlatConnector;
|
||||
class DbConnector;
|
||||
|
||||
|
||||
template<typename ModelClass>
|
||||
class Finder;
|
||||
|
@ -81,6 +82,10 @@ public:
|
|||
virtual void insert(Model & model);
|
||||
virtual void update(Model & model);
|
||||
|
||||
virtual void map_values_from_query(Model & model);
|
||||
|
||||
virtual void clear_values(Model & model);
|
||||
|
||||
|
||||
// template<typename ModelClass>
|
||||
// Finder<ModelClass> & find()
|
||||
|
@ -92,13 +97,16 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
int model_connector_mode;
|
||||
|
||||
FlatConnector * flat_connector;
|
||||
DbConnector * db_connector;
|
||||
|
||||
PT::TextStream * out_stream; // IMPROVE ME give here an interface to the base stream (implement him)
|
||||
bool out_stream_allocated;
|
||||
|
||||
BaseExpression * expression_callback;
|
||||
//BaseExpression * expression_callback;
|
||||
//DbConnector * db_connector_callback;
|
||||
|
||||
void allocate_default_stream();
|
||||
void allocate_default_stream_if_needed();
|
||||
|
@ -108,12 +116,75 @@ protected:
|
|||
template<typename FieldValue>
|
||||
void field(const wchar_t * field_name, FieldValue & field_value, bool insertable, bool updatable, bool is_primary_key)
|
||||
{
|
||||
if( expression_callback )
|
||||
// may we need only db_connector_callback?
|
||||
|
||||
// if( expression_callback )
|
||||
// {
|
||||
// expression_callback->field(field_name, field_value, insertable, updatable, is_primary_key);
|
||||
// }
|
||||
|
||||
// if( db_connector_callback )
|
||||
// {
|
||||
// db_connector_callback->get_value_by_field_name(field_name, field_value);
|
||||
// }
|
||||
|
||||
if( model_connector_mode == MORM_MODEL_CONNECTOR_MODE_GENERATING_FLAT_EXPRESSION && flat_connector )
|
||||
{
|
||||
expression_callback->field(field_name, field_value, insertable, updatable, is_primary_key);
|
||||
FlatExpression * flat_expression = flat_connector->get_expression();
|
||||
|
||||
if( flat_expression )
|
||||
{
|
||||
flat_expression->field(field_name, field_value, insertable, updatable, is_primary_key);
|
||||
}
|
||||
}
|
||||
|
||||
if( model_connector_mode == MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_EXPRESSION && db_connector )
|
||||
{
|
||||
DbExpression * db_expression = db_connector->get_expression();
|
||||
|
||||
if( db_expression )
|
||||
{
|
||||
db_expression->field(field_name, field_value, insertable, updatable, is_primary_key);
|
||||
}
|
||||
}
|
||||
|
||||
if( model_connector_mode == MORM_MODEL_CONNECTOR_MODE_READING_VALUE_FROM_DB && db_connector )
|
||||
{
|
||||
db_connector->get_value_by_field_name(field_name, field_value);
|
||||
}
|
||||
|
||||
if( model_connector_mode == MORM_MODEL_CONNECTOR_MODE_CLEARING_VALUE && db_connector )
|
||||
{
|
||||
// IMPROVE ME those clearing should be moved to a better place
|
||||
db_connector->clear_value(field_value);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ModelClass>
|
||||
void field_list(const wchar_t * field_name, std::list<ModelClass> & field_list, bool insertable = true, bool updatable = true, bool is_primary_key = false)
|
||||
{
|
||||
if( model_connector_mode == MORM_MODEL_CONNECTOR_MODE_GENERATING_FLAT_EXPRESSION && flat_connector && out_stream )
|
||||
{
|
||||
FlatExpression * flat_expression = flat_connector->get_expression();
|
||||
|
||||
if( flat_expression )
|
||||
{
|
||||
flat_expression->field_list(field_name, field_list, insertable, updatable, is_primary_key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename FieldValue>
|
||||
void get_last_sequence(const wchar_t * sequence_table_name, FieldValue & field_value)
|
||||
{
|
||||
if( db_connector )
|
||||
{
|
||||
db_connector->get_last_sequence(sequence_table_name, field_value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Model is using field() method
|
||||
*/
|
||||
|
|
|
@ -35,13 +35,23 @@
|
|||
#ifndef headerfile_morm_morm_types
|
||||
#define headerfile_morm_morm_types
|
||||
|
||||
#define MORM_MODEL_CONNECTOR_MODE_NONE 0
|
||||
#define MORM_MODEL_CONNECTOR_MODE_GENERATING_FLAT_EXPRESSION 1
|
||||
#define MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_EXPRESSION 2
|
||||
|
||||
// not used at the moment, there are not any flat parsers (json parser)
|
||||
#define MORM_MODEL_CONNECTOR_MODE_READING_VALUE_FROM_FLAT 3
|
||||
|
||||
#define MORM_MODEL_CONNECTOR_MODE_READING_VALUE_FROM_DB 4
|
||||
#define MORM_MODEL_CONNECTOR_MODE_CLEARING_VALUE 5
|
||||
|
||||
|
||||
#define MORM_WORK_MODE_MODEL_FIELDS 1
|
||||
#define MORM_WORK_MODE_MODEL_VALUES 2
|
||||
#define MORM_WORK_MODE_MODEL_FIELDS_VALUES 3
|
||||
|
||||
// IMPROVE ME give me a better name
|
||||
#define MORM_WORK_MODE_MODEL_SELECT_FROM_DB 3
|
||||
//#define MORM_WORK_MODE_MODEL_SELECT_FROM_DB 4
|
||||
|
||||
//#define MORM_OUTPUT_TYPE_JSON 1
|
||||
#define MORM_OUTPUT_TYPE_DB_INSERT 2
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "postgresqlconnector.h"
|
||||
#include "utf8/utf8.h"
|
||||
#include "postgresqlexpression.h"
|
||||
#include "convert/strtoint.h"
|
||||
|
||||
|
||||
namespace morm
|
||||
|
@ -49,6 +50,8 @@ PostgreSQLConnector::PostgreSQLConnector()
|
|||
log_queries = false;
|
||||
last_status = PGRES_EMPTY_QUERY;
|
||||
last_result = nullptr;
|
||||
last_result_rows = 0;
|
||||
cur_row = 0;
|
||||
}
|
||||
|
||||
PostgreSQLConnector::~PostgreSQLConnector()
|
||||
|
@ -77,6 +80,7 @@ bool PostgreSQLConnector::query(const char * query_str)
|
|||
// log << log1 << "Db: executing query: " << q << logend;
|
||||
|
||||
last_status = PGRES_EMPTY_QUERY; // or something else?
|
||||
last_result_rows = 0;
|
||||
last_result = PQexec(pg_conn, query_str);
|
||||
|
||||
if( !last_result )
|
||||
|
@ -91,6 +95,7 @@ bool PostgreSQLConnector::query(const char * query_str)
|
|||
if( last_result )
|
||||
{
|
||||
last_status = PQresultStatus(last_result);
|
||||
last_result_rows = static_cast<size_t>(PQntuples(last_result));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -102,6 +107,36 @@ return last_result != nullptr;
|
|||
}
|
||||
|
||||
|
||||
|
||||
const char * PostgreSQLConnector::query_last_sequence(const wchar_t * sequence_table_name)
|
||||
{
|
||||
allocate_default_expression_if_needed();
|
||||
|
||||
if( db_expression )
|
||||
{
|
||||
stream.clear();
|
||||
stream << "select currval(E'";
|
||||
db_expression->esc(sequence_table_name, stream);
|
||||
stream << "');";
|
||||
|
||||
if( query_select(stream) )
|
||||
{
|
||||
if( last_result_rows == 1 )
|
||||
{
|
||||
return get_value(0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
//log << log1 << "Db: error (currval) for table: " << table << ", " << PQerrorMessage(db_conn->GetPgConn()) << logend;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool PostgreSQLConnector::query(const PT::TextStream & stream)
|
||||
{
|
||||
stream.to_string(query_str);
|
||||
|
@ -152,219 +187,18 @@ bool PostgreSQLConnector::query_insert(const PT::TextStream & stream)
|
|||
|
||||
|
||||
|
||||
//Error PostgreSQLConnector::DoCommand(const char * command)
|
||||
//{
|
||||
// PGresult * r = 0;
|
||||
// Error status = WINIX_ERR_OK;
|
||||
//
|
||||
// try
|
||||
// {
|
||||
// r = AssertQuery(command);
|
||||
// AssertResult(r, PGRES_COMMAND_OK);
|
||||
// }
|
||||
// catch(const Error & e)
|
||||
// {
|
||||
// status = e;
|
||||
// }
|
||||
//
|
||||
// ClearResult(r);
|
||||
//
|
||||
//return status;
|
||||
//}
|
||||
|
||||
|
||||
|
||||
bool PostgreSQLConnector::is_last_result(ExecStatusType t)
|
||||
{
|
||||
return (last_result && PQresultStatus(last_result) == t);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void PostgreSQLConnector::map_values_from_query(Model & model)
|
||||
// to nie tylko dla selectow moze byc uzywane
|
||||
size_t PostgreSQLConnector::last_select_size()
|
||||
{
|
||||
if( db_expression )
|
||||
{
|
||||
db_expression->set_work_mode(MORM_WORK_MODE_MODEL_SELECT_FROM_DB);
|
||||
//db_expression->set_output_type()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
return last_result_rows;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int PostgreSQLConnector::get_column_index(const char * column_name)
|
||||
{
|
||||
int c = PQfnumber(last_result, column_name);
|
||||
// returns -1 if there is no such a column
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char * PostgreSQLConnector::get_value(int row, int col)
|
||||
{
|
||||
const char * res = PQgetvalue(last_result, row, col);
|
||||
// can return a null pointer if there is no such an item in the last result
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
bool PostgreSQLConnector::get_value(int row, int col, std::string & result, bool clear_string)
|
||||
{
|
||||
if( clear_string )
|
||||
result.clear();
|
||||
|
||||
const char * raw_result = get_value(row, col);
|
||||
|
||||
if( raw_result )
|
||||
{
|
||||
result += raw_result;
|
||||
}
|
||||
|
||||
return raw_result != nullptr;
|
||||
}
|
||||
|
||||
|
||||
bool PostgreSQLConnector::get_value(int row, int col, std::wstring & result, bool clear_string)
|
||||
{
|
||||
if( clear_string )
|
||||
result.clear();
|
||||
|
||||
const char * raw_result = get_value(row, col);
|
||||
|
||||
if( raw_result )
|
||||
{
|
||||
PT::UTF8ToWide(raw_result, result);
|
||||
}
|
||||
|
||||
return raw_result != nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//void PostgreSQLConnector::get_value_bin(int row, int col, std::string & result, bool clear_string)
|
||||
//{
|
||||
// if( clear_string )
|
||||
// result.clear();
|
||||
//
|
||||
// const char * raw_result = get_value(row, col);
|
||||
//
|
||||
// if( raw_result )
|
||||
// {
|
||||
// int len = PQgetlength(last_result, row, col);
|
||||
//
|
||||
// if( len > 0 )
|
||||
// {
|
||||
// unescape_bin(raw_result, len, result);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
|
||||
//long PostgreSQLConnector::AssertValueLong(PGresult * r, int row, int col)
|
||||
//{
|
||||
// return strtol( AssertValue(r, row, col), 0, 10 );
|
||||
//}
|
||||
//
|
||||
//
|
||||
//int PostgreSQLConnector::AssertValueInt(PGresult * r, int row, int col)
|
||||
//{
|
||||
// return (int)strtol( AssertValue(r, row, col), 0, 10 );
|
||||
//}
|
||||
//
|
||||
//
|
||||
//bool PostgreSQLConnector::AssertValueBool(PGresult * r, int row, int col)
|
||||
//{
|
||||
// const char * s = AssertValue(r, row, col);
|
||||
// return (s[0]=='t' || s[0]=='y' || s[0]=='1');
|
||||
//}
|
||||
//
|
||||
//
|
||||
//unsigned long PostgreSQLConnector::AssertValueULong(PGresult * r, int row, int col)
|
||||
//{
|
||||
// return strtoul( AssertValue(r, row, col), 0, 10 );
|
||||
//}
|
||||
//
|
||||
//
|
||||
//unsigned int PostgreSQLConnector::AssertValueUInt(PGresult * r, int row, int col)
|
||||
//{
|
||||
// return (unsigned int)strtoul( AssertValue(r, row, col), 0, 10 );
|
||||
//}
|
||||
//
|
||||
//
|
||||
//
|
||||
//PT::Date PostgreSQLConnector::AssertValueDate(PGresult * r, int row, int col)
|
||||
//{
|
||||
// PT::Date date = AssertValue(r, row, col);
|
||||
//
|
||||
//return date;
|
||||
//}
|
||||
//
|
||||
//
|
||||
//bool PostgreSQLConnector::AssertValueSpace(PGresult * r, int row, int col, PT::Space & space)
|
||||
//{
|
||||
// const char * res = AssertValue(r, row, col);
|
||||
//
|
||||
// conf_parser.SetSpace(space);
|
||||
// space.Clear();
|
||||
//
|
||||
// PT::SpaceParser::Status status = conf_parser.ParseString(res);
|
||||
//
|
||||
// if( status != PT::SpaceParser::ok )
|
||||
// {
|
||||
// log << log1 << "Db: a problem with parsing a PT::Space";
|
||||
//
|
||||
// if( status == PT::SpaceParser::syntax_error )
|
||||
// log << ", syntax error at line: " << conf_parser.line;
|
||||
//
|
||||
// log << logend;
|
||||
//
|
||||
// space.Clear();
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
//return true;
|
||||
//}
|
||||
//
|
||||
//
|
||||
|
||||
|
||||
|
||||
void PostgreSQLConnector::clear_result()
|
||||
{
|
||||
if( last_result )
|
||||
{
|
||||
PQclear(last_result);
|
||||
last_result = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool PostgreSQLConnector::is_null(int row, int col)
|
||||
{
|
||||
if( last_result )
|
||||
{
|
||||
return PQgetisnull(last_result, row, col) == 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//int PostgreSQLConnector::Rows(PGresult * r)
|
||||
//{
|
||||
// // PQntuples - Returns the number of rows (tuples) in the query result. Because it returns
|
||||
|
@ -379,7 +213,6 @@ bool PostgreSQLConnector::is_null(int row, int col)
|
|||
// return PQnfields(r);
|
||||
//}
|
||||
|
||||
|
||||
//long PostgreSQLConnector::AffectedRows(PGresult * r)
|
||||
//{
|
||||
// // PQcmdTuples - This function returns a string containing the number of rows affected by the SQL
|
||||
|
@ -404,27 +237,126 @@ bool PostgreSQLConnector::is_null(int row, int col)
|
|||
//}
|
||||
|
||||
|
||||
//long PostgreSQLConnector::AssertCurrval(const char * table)
|
||||
|
||||
|
||||
void PostgreSQLConnector::set_current_row_at_beginning()
|
||||
{
|
||||
cur_row = 0;
|
||||
}
|
||||
|
||||
|
||||
void PostgreSQLConnector::advance_current_row()
|
||||
{
|
||||
cur_row += 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int PostgreSQLConnector::get_column_index(const char * column_name)
|
||||
{
|
||||
int c = PQfnumber(last_result, column_name);
|
||||
// returns -1 if there is no such a column
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
int PostgreSQLConnector::get_column_index(const wchar_t * column_name)
|
||||
{
|
||||
// temporary
|
||||
std::string s; // move me somewhere?
|
||||
PT::WideToUTF8(column_name, s);
|
||||
return get_column_index(s.c_str());
|
||||
}
|
||||
|
||||
|
||||
const char * PostgreSQLConnector::get_value(int row, int col)
|
||||
{
|
||||
const char * res = PQgetvalue(last_result, row, col);
|
||||
// can return a null pointer if there is no such an item in the last result
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int PostgreSQLConnector::get_value_length(int row, int col)
|
||||
{
|
||||
int len = PQgetlength(last_result, row, col);
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//void PostgreSQLConnector::get_value_bin(int row, int col, std::string & result, bool clear_string)
|
||||
//{
|
||||
// PGresult * r;
|
||||
// if( clear_string )
|
||||
// result.clear();
|
||||
//
|
||||
// bquery.Clear();
|
||||
// bquery << R("select currval(")
|
||||
// << table
|
||||
// << R(");");
|
||||
// const char * raw_result = get_value(row, col);
|
||||
//
|
||||
// r = AssertQuery(bquery);
|
||||
// AssertResult(r, PGRES_TUPLES_OK);
|
||||
//
|
||||
// if( Rows(r) != 1 )
|
||||
// if( raw_result )
|
||||
// {
|
||||
// log << log1 << "Db: error (currval) for table: " << table << ", " << PQerrorMessage(db_conn->GetPgConn()) << logend;
|
||||
// throw Error(WINIX_ERR_DB_ERR_CURRVAL);
|
||||
// int len = PQgetlength(last_result, row, col);
|
||||
//
|
||||
// if( len > 0 )
|
||||
// {
|
||||
// unescape_bin(raw_result, len, result);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
//bool PostgreSQLConnector::AssertValueSpace(PGresult * r, int row, int col, PT::Space & space)
|
||||
//{
|
||||
// const char * res = AssertValue(r, row, col);
|
||||
//
|
||||
// conf_parser.SetSpace(space);
|
||||
// space.Clear();
|
||||
//
|
||||
// PT::SpaceParser::Status status = conf_parser.ParseString(res);
|
||||
//
|
||||
// if( status != PT::SpaceParser::ok )
|
||||
// {
|
||||
// log << log1 << "Db: a problem with parsing a PT::Space";
|
||||
//
|
||||
// if( status == PT::SpaceParser::syntax_error )
|
||||
// log << ", syntax error at line: " << conf_parser.line;
|
||||
//
|
||||
// log << logend;
|
||||
//
|
||||
// space.Clear();
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
//return AssertValueLong(r, 0, 0);
|
||||
//return true;
|
||||
//}
|
||||
//
|
||||
|
||||
|
||||
|
||||
void PostgreSQLConnector::clear_result()
|
||||
{
|
||||
if( last_result )
|
||||
{
|
||||
PQclear(last_result);
|
||||
last_result = nullptr;
|
||||
last_result_rows = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool PostgreSQLConnector::is_null(int row, int col)
|
||||
{
|
||||
if( last_result )
|
||||
{
|
||||
return PQgetisnull(last_result, row, col) == 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -665,23 +597,27 @@ void PostgreSQLConnector::connect()
|
|||
{
|
||||
close();
|
||||
|
||||
stream.clear();
|
||||
stream << "dbname='";
|
||||
db_expression->esc(db_database, stream);
|
||||
allocate_default_expression_if_needed();
|
||||
|
||||
stream << "' user='";
|
||||
db_expression->esc(db_user, stream);
|
||||
if( db_expression )
|
||||
{
|
||||
stream.clear();
|
||||
stream << "dbname='";
|
||||
db_expression->esc(db_database, stream);
|
||||
|
||||
stream << "' password='";
|
||||
db_expression->esc(db_pass, stream);
|
||||
stream << "'";
|
||||
stream << "' user='";
|
||||
db_expression->esc(db_user, stream);
|
||||
|
||||
std::string str;
|
||||
stream.to_string(str);
|
||||
pg_conn = PQconnectdb(str.c_str());
|
||||
stream << "' password='";
|
||||
db_expression->esc(db_pass, stream);
|
||||
stream << "'";
|
||||
|
||||
overwrite(stream);
|
||||
std::string str;
|
||||
stream.to_string(str);
|
||||
pg_conn = PQconnectdb(str.c_str());
|
||||
|
||||
overwrite(stream);
|
||||
}
|
||||
// warning! pg_conn can be not null but there cannnot be a connection established
|
||||
// use PQstatus(pg_conn) to check whether the connection works fine
|
||||
}
|
||||
|
@ -692,13 +628,13 @@ void PostgreSQLConnector::connect()
|
|||
|
||||
void PostgreSQLConnector::log_connection_socket()
|
||||
{
|
||||
//log << log2 << "Db: connection to the database works fine" << logend;
|
||||
//log << log3 << "Db: connection socket: " << PQsocket(pg_conn) << logend;
|
||||
|
||||
if( pg_conn )
|
||||
{
|
||||
std::cout << "Db: connection to the database works fine" << std::endl;
|
||||
std::cout << "Db: connection socket: " << PQsocket(pg_conn) << std::endl;
|
||||
//log << log2 << "Db: connection to the database works fine" << logend;
|
||||
//log << log3 << "Db: connection socket: " << PQsocket(pg_conn) << logend;
|
||||
|
||||
//std::cout << "Db: connection to the database works fine" << std::endl;
|
||||
//std::cout << "Db: connection socket: " << PQsocket(pg_conn) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -707,7 +643,7 @@ void PostgreSQLConnector::wait_for_connection()
|
|||
if( !pg_conn || PQstatus(pg_conn) != CONNECTION_OK )
|
||||
{
|
||||
//log << log3 << "Db: waiting for the db to be ready...." << logend << logsave;
|
||||
std::cout << "Db: waiting for the db to be ready...." << std::endl;
|
||||
//std::cout << "Db: waiting for the db to be ready...." << std::endl;
|
||||
|
||||
while( !assert_connection(false, false) )
|
||||
{
|
||||
|
@ -726,6 +662,8 @@ void PostgreSQLConnector::close()
|
|||
{
|
||||
PQfinish(pg_conn);
|
||||
pg_conn = nullptr;
|
||||
last_result = nullptr;
|
||||
last_result_rows = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -746,7 +684,7 @@ bool was_connection = true;
|
|||
if( put_log )
|
||||
{
|
||||
//log << log2 << "Db: connection to the database is lost, trying to recover" << logend;
|
||||
std::cout << "Db: connection to the database is lost, trying to recover" << std::endl;
|
||||
//std::cout << "Db: connection to the database is lost, trying to recover" << std::endl;
|
||||
}
|
||||
|
||||
was_connection = false;
|
||||
|
@ -771,7 +709,7 @@ bool was_connection = true;
|
|||
if( put_log )
|
||||
{
|
||||
//log << log1 << "Db: connection to db server cannot be established" << logend;
|
||||
std::cout << "Db: connection to db server cannot be established" << std::endl;
|
||||
//std::cout << "Db: connection to db server cannot be established" << std::endl;
|
||||
}
|
||||
|
||||
if( throw_if_no_connection )
|
||||
|
@ -789,9 +727,28 @@ void PostgreSQLConnector::set_db_parameters()
|
|||
if( PQsetClientEncoding(pg_conn, "UTF8") == -1 )
|
||||
{
|
||||
//log << log1 << "Db: Can't set the proper client encoding" << logend;
|
||||
std::cout << "Db: Can't set the proper client encoding" << std::endl;
|
||||
//std::cout << "Db: Can't set the proper client encoding" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const char * PostgreSQLConnector::get_field_string_value(const wchar_t * field_name)
|
||||
{
|
||||
int c = get_column_index(field_name);
|
||||
|
||||
if( c != -1 )
|
||||
{
|
||||
if( cur_row < last_result_rows )
|
||||
{
|
||||
return get_value(cur_row, c);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -64,7 +64,12 @@ public:
|
|||
bool query_update(const PT::TextStream & stream);
|
||||
bool query_insert(const PT::TextStream & stream);
|
||||
|
||||
void map_values_from_query(Model & model);
|
||||
// give me a better name
|
||||
virtual size_t last_select_size();
|
||||
|
||||
// give me a better name
|
||||
virtual void set_current_row_at_beginning();
|
||||
virtual void advance_current_row();
|
||||
|
||||
|
||||
bool is_last_result(ExecStatusType t);
|
||||
|
@ -75,6 +80,7 @@ public:
|
|||
*
|
||||
*/
|
||||
int get_column_index(const char * column_name);
|
||||
int get_column_index(const wchar_t * column_name);
|
||||
|
||||
bool is_null(int row, int col);
|
||||
|
||||
|
@ -84,10 +90,8 @@ public:
|
|||
*
|
||||
*/
|
||||
const char * get_value(int row, int col);
|
||||
int get_value_length(int row, int col);
|
||||
|
||||
bool get_value(int row, int col, std::string & result, bool clear_string = true);
|
||||
bool get_value(int row, int col, std::wstring & result, bool clear_string = true);
|
||||
void get_value_bin(int row, int col, std::string & result, bool clear_string = true);
|
||||
|
||||
void clear_result();
|
||||
|
||||
|
@ -106,10 +110,12 @@ protected:
|
|||
|
||||
PGconn * pg_conn;
|
||||
PGresult * last_result; // can be null
|
||||
size_t last_result_rows; // how many rows in the last result query
|
||||
ExecStatusType last_status;
|
||||
bool log_queries;
|
||||
PT::TextStream stream;
|
||||
std::string query_str;
|
||||
size_t cur_row;
|
||||
|
||||
std::wstring db_database;
|
||||
std::wstring db_user;
|
||||
|
@ -119,6 +125,9 @@ protected:
|
|||
void allocate_default_expression();
|
||||
|
||||
void overwrite(PT::TextStream & stream);
|
||||
virtual const char * get_field_string_value(const wchar_t * field_name);
|
||||
|
||||
const char * query_last_sequence(const wchar_t * sequence_table_name);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue