diff --git a/src/baseexpression.cpp b/src/baseexpression.cpp index 6e35f74..f4bba3e 100644 --- a/src/baseexpression.cpp +++ b/src/baseexpression.cpp @@ -67,6 +67,8 @@ void BaseExpression::generate_from_model(PT::TextStream & stream, Model & model) before_generate_from_model(); model.map_fields(); after_generate_from_model(); + + this->out_stream = nullptr; } diff --git a/src/baseexpression.h b/src/baseexpression.h index 5b6847d..6a1f166 100644 --- a/src/baseexpression.h +++ b/src/baseexpression.h @@ -60,7 +60,7 @@ public: template void field(const wchar_t * field_name, const FieldValue & field_value, bool insertable = true, bool updatable = true, bool is_primary_key = false) { - if( can_field_be_generated(insertable, updatable, is_primary_key) ) + if( out_stream && can_field_be_generated(insertable, updatable, is_primary_key) ) { field_before(); @@ -86,6 +86,40 @@ public: } + template + 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) + { + this->out_stream = &stream; + field(field_name, field_value, insertable, updatable, is_primary_key); + this->out_stream = nullptr; + } + + + + virtual void esc(char val, PT::TextStream & stream); + virtual void esc(unsigned char val, PT::TextStream & stream); + + virtual void esc(const std::wstring & val, PT::TextStream & stream); + virtual void esc(const wchar_t * val, PT::TextStream & stream); + + virtual void esc(const std::string & val, PT::TextStream & stream); + virtual void esc(const char * val, PT::TextStream & stream); + + virtual void esc(bool val, PT::TextStream & stream); + virtual void esc(short val, PT::TextStream & stream); + virtual void esc(unsigned short val, PT::TextStream & stream); + virtual void esc(int val, PT::TextStream & stream); + virtual void esc(unsigned int val, PT::TextStream & stream); + virtual void esc(long val, PT::TextStream & stream); + virtual void esc(unsigned long val, PT::TextStream & stream); + virtual void esc(long long val, PT::TextStream & stream); + virtual void esc(unsigned long long val, PT::TextStream & stream); + virtual void esc(float val, PT::TextStream & stream); + virtual void esc(double val, PT::TextStream & stream); + virtual void esc(long double val, PT::TextStream & stream); + virtual void esc(void* val, PT::TextStream & stream); + + virtual void esc(const PT::Date & date, PT::TextStream & stream); protected: @@ -226,31 +260,6 @@ protected: */ - virtual void esc(char val, PT::TextStream & stream); - virtual void esc(unsigned char val, PT::TextStream & stream); - - virtual void esc(const std::wstring & val, PT::TextStream & stream); - virtual void esc(const wchar_t * val, PT::TextStream & stream); - - virtual void esc(const std::string & val, PT::TextStream & stream); - virtual void esc(const char * val, PT::TextStream & stream); - - virtual void esc(bool val, PT::TextStream & stream); - virtual void esc(short val, PT::TextStream & stream); - virtual void esc(unsigned short val, PT::TextStream & stream); - virtual void esc(int val, PT::TextStream & stream); - virtual void esc(unsigned int val, PT::TextStream & stream); - virtual void esc(long val, PT::TextStream & stream); - virtual void esc(unsigned long val, PT::TextStream & stream); - virtual void esc(long long val, PT::TextStream & stream); - virtual void esc(unsigned long long val, PT::TextStream & stream); - virtual void esc(float val, PT::TextStream & stream); - virtual void esc(double val, PT::TextStream & stream); - virtual void esc(long double val, PT::TextStream & stream); - virtual void esc(void* val, PT::TextStream & stream); - - virtual void esc(const PT::Date & date, PT::TextStream & stream); - }; } diff --git a/src/dbconnector.cpp b/src/dbconnector.cpp index cca9b13..be0cf75 100644 --- a/src/dbconnector.cpp +++ b/src/dbconnector.cpp @@ -53,31 +53,31 @@ DbConnector::~DbConnector() -bool DbConnector::query(PT::TextStream & stream) +bool DbConnector::query(const PT::TextStream & stream) { return false; } -bool DbConnector::query(const std::wstring & query) +//bool DbConnector::query(const std::wstring & query) +//{ +// return false; +//} + + +bool DbConnector::query(const std::string & query_str) { return false; } -bool DbConnector::query(const std::string & query) -{ - return false; -} +//bool DbConnector::query(const wchar_t * query) +//{ +// return false; +//} -bool DbConnector::query(const wchar_t * query) -{ - return false; -} - - -bool DbConnector::query(const char * query) +bool DbConnector::query(const char * query_str) { // do query return false; @@ -85,6 +85,27 @@ bool DbConnector::query(const char * query) +bool DbConnector::query_select(const PT::TextStream & stream) +{ + return false; +} + +bool DbConnector::query_update(const PT::TextStream & stream) +{ + return false; +} + +bool DbConnector::query_insert(const PT::TextStream & stream) +{ + return false; +} + + +virtual void DbConnector::map_values_from_query(Model & model) +{ + model.clear(); +} + DbExpression * DbConnector::get_expression() { diff --git a/src/dbconnector.h b/src/dbconnector.h index f709897..a95e2de 100644 --- a/src/dbconnector.h +++ b/src/dbconnector.h @@ -61,11 +61,17 @@ public: virtual void insert(PT::TextStream & stream, Model & model); virtual void update(PT::TextStream & stream, Model & model); - virtual bool query(PT::TextStream & stream); - virtual bool query(const std::wstring & query); - virtual bool query(const std::string & query); - virtual bool query(const wchar_t * query); - virtual bool query(const char * query); + virtual bool query(const PT::TextStream & stream); + //virtual bool query(const std::wstring & query); + virtual bool query(const std::string & query_str); + //virtual bool query(const wchar_t * query); + virtual bool query(const char * query_str); + + virtual bool query_select(const PT::TextStream & stream); + virtual bool query_update(const PT::TextStream & stream); + virtual bool query_insert(const PT::TextStream & stream); + + virtual void map_values_from_query(Model & model); protected: diff --git a/src/dbexpression.cpp b/src/dbexpression.cpp index 79f2f58..c1e25ba 100644 --- a/src/dbexpression.cpp +++ b/src/dbexpression.cpp @@ -227,28 +227,34 @@ void DbExpression::prepare_to_where_clause() } -DbExpression & DbExpression::group_or() +DbExpression & DbExpression::group_or(PT::TextStream & stream) { + out_stream = &stream; field_before(); (*out_stream) << "("; is_first_field = true; conjunctions.push_back(MORM_CONJUNCTION_OR); + out_stream = nullptr; return *this; } -DbExpression & DbExpression::group_and() +DbExpression & DbExpression::group_and(PT::TextStream & stream) { + out_stream = &stream; field_before(); (*out_stream) << "("; is_first_field = true; conjunctions.push_back(MORM_CONJUNCTION_AND); + out_stream = nullptr; return *this; } -DbExpression & DbExpression::group_end() +DbExpression & DbExpression::group_end(PT::TextStream & stream) { + out_stream = &stream; + if( !conjunctions.empty() ) { conjunctions.pop_back(); @@ -256,6 +262,7 @@ DbExpression & DbExpression::group_end() field_after(); } + out_stream = nullptr; return *this; } diff --git a/src/dbexpression.h b/src/dbexpression.h index ab3625f..cd058ae 100644 --- a/src/dbexpression.h +++ b/src/dbexpression.h @@ -55,10 +55,9 @@ public: virtual void prepare_to_where_clause(); - // may better names? - virtual DbExpression & group_or(); - virtual DbExpression & group_and(); - virtual DbExpression & group_end(); + virtual DbExpression & group_or(PT::TextStream & stream); + virtual DbExpression & group_and(PT::TextStream & stream); + virtual DbExpression & group_end(PT::TextStream & stream); diff --git a/src/finder.h b/src/finder.h index fa84f40..7721051 100644 --- a/src/finder.h +++ b/src/finder.h @@ -36,6 +36,7 @@ #define headerfile_morm_finder #include +#include #include "model.h" #include "textstream/textstream.h" #include "dbconnector.h" @@ -70,8 +71,8 @@ public: Finder(PT::TextStream & out_stream, ModelConnector & model_connector) { - this->model_connector = &model_connector; this->out_stream = &out_stream; + this->model_connector = &model_connector; db_expression = nullptr; } @@ -91,29 +92,34 @@ public: } + + + + + + Finder & find() { if( model_connector ) { - if( out_stream ) - { - model_connector->set_stream(*out_stream); - } - else + if( !out_stream ) { out_stream = model_connector->get_stream(); } - set_db_expression(); + if( out_stream ) + { + set_db_expression(); - out_stream->clear(); - model.set_connector(*model_connector); - model.clear(); + out_stream->clear(); + model.set_connector(*model_connector); + model.clear(); - (*out_stream) << "SELECT "; - model_connector->generate_select_columns(*out_stream, model); - (*out_stream) << " FROM "; - model.table_name(*out_stream); + (*out_stream) << "SELECT "; + model_connector->generate_select_columns(*out_stream, model); + (*out_stream) << " FROM "; + model.table_name(*out_stream); + } } return *this; @@ -159,9 +165,9 @@ public: // may better names? Finder & group_or() { - if( db_expression ) + if( db_expression && out_stream ) { - db_expression->group_or(); + db_expression->group_or(*out_stream); } return *this; @@ -170,9 +176,9 @@ public: Finder & group_and() { - if( db_expression ) + if( db_expression && out_stream ) { - db_expression->group_and(); + db_expression->group_and(*out_stream); } return *this; @@ -181,9 +187,9 @@ public: Finder & group_end() { - if( db_expression ) + if( db_expression && out_stream ) { - db_expression->group_end(); + db_expression->group_end(*out_stream); } return *this; @@ -198,7 +204,7 @@ public: if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_EQ); - db_expression->field(field_name, field_value, false, false, false); + db_expression->field(*out_stream, field_name, field_value, false, false, false); } return *this; @@ -211,7 +217,7 @@ public: if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_LT); - db_expression->field(field_name, field_value, false, false, false); + db_expression->field(*out_stream, field_name, field_value, false, false, false); } return *this; @@ -224,7 +230,7 @@ public: if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_GT); - db_expression->field(field_name, field_value, false, false, false); + db_expression->field(*out_stream, field_name, field_value, false, false, false); } return *this; @@ -237,7 +243,7 @@ public: if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_LE); - db_expression->field(field_name, field_value, false, false, false); + db_expression->field(*out_stream, field_name, field_value, false, false, false); } return *this; @@ -250,13 +256,55 @@ public: if( db_expression ) { db_expression->set_output_type(MORM_OUTPUT_TYPE_WHERE_GE); - db_expression->field(field_name, field_value, false, false, false); + db_expression->field(*out_stream, field_name, field_value, false, false, false); } return *this; } + void get_list(std::list & result, bool clear_list = true) + { + if( clear_list ) + { + result.clear(); + } + + if( model_connector && out_stream ) + { + DbConnector * db_connector = model_connector->get_db_connector(); + + if( db_connector ) + { + bool res = db_connector->query_select(*out_stream); + + if( res ) + { + //ModelClass model; + //db_connector->map_values_from_query(model); + + } + + if( !res ) + { + // put some log here? + } + + + + + } + } + } + + std::list get_list() + { + std::list result; + get_list(result); + return result; + } + + private: diff --git a/src/morm_types.h b/src/morm_types.h index 2186da6..03fffd4 100644 --- a/src/morm_types.h +++ b/src/morm_types.h @@ -40,6 +40,9 @@ #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_OUTPUT_TYPE_JSON 1 #define MORM_OUTPUT_TYPE_DB_INSERT 2 #define MORM_OUTPUT_TYPE_DB_UPDATE 3 diff --git a/src/postgresqlconnector.cpp b/src/postgresqlconnector.cpp index 4de7d3e..5f64392 100644 --- a/src/postgresqlconnector.cpp +++ b/src/postgresqlconnector.cpp @@ -32,6 +32,9 @@ * */ +// for sleep() +#include + #include "postgresqlconnector.h" #include "utf8/utf8.h" #include "postgresqlexpression.h" @@ -73,14 +76,14 @@ bool PostgreSQLConnector::query(const char * query_str) // if( log_queries ) // log << log1 << "Db: executing query: " << q << logend; - last_status = PGRES_EMPTY_QUERY; + last_status = PGRES_EMPTY_QUERY; // or something else? last_result = PQexec(pg_conn, query_str); if( !last_result ) { if( PQstatus(pg_conn) != CONNECTION_OK ) { - //AssertConnection(); + assert_connection(); last_result = PQexec(pg_conn, query_str); } } @@ -99,6 +102,19 @@ return last_result != nullptr; } +bool PostgreSQLConnector::query(const PT::TextStream & stream) +{ + stream.to_string(query_str); + return query(query_str.c_str()); +} + + +bool PostgreSQLConnector::query(const std::string & query_str) +{ + return query(query_str.c_str()); +} + + bool PostgreSQLConnector::query_select(const char * query_str) { return (query(query_str) && last_status == PGRES_TUPLES_OK); @@ -115,6 +131,27 @@ bool PostgreSQLConnector::query_insert(const char * query_str) } + +bool PostgreSQLConnector::query_select(const PT::TextStream & stream) +{ + stream.to_string(query_str); + return query_select(query_str.c_str()); +} + +bool PostgreSQLConnector::query_update(const PT::TextStream & stream) +{ + stream.to_string(query_str); + return query_update(query_str.c_str()); +} + +bool PostgreSQLConnector::query_insert(const PT::TextStream & stream) +{ + stream.to_string(query_str); + return query_insert(query_str.c_str()); +} + + + //Error PostgreSQLConnector::DoCommand(const char * command) //{ // PGresult * r = 0; @@ -137,7 +174,6 @@ bool PostgreSQLConnector::query_insert(const char * query_str) - bool PostgreSQLConnector::is_last_result(ExecStatusType t) { return (last_result && PQresultStatus(last_result) == t); @@ -145,6 +181,28 @@ bool PostgreSQLConnector::is_last_result(ExecStatusType t) +void PostgreSQLConnector::map_values_from_query(Model & model) +{ + if( db_expression ) + { + db_expression->set_work_mode(MORM_WORK_MODE_MODEL_SELECT_FROM_DB); + //db_expression->set_output_type() + + + + + + + + + } +} + + + + + + int PostgreSQLConnector::get_column_index(const char * column_name) { int c = PQfnumber(last_result, column_name); @@ -580,120 +638,160 @@ size_t i = 0; -//void PostgreSQLConnector::SetConnParam(const std::wstring & database_name, const std::wstring & user, const std::wstring & pass) -//{ -// db_database = database_name; -// db_user = user; -// db_pass = pass; -//} +void PostgreSQLConnector::set_conn_param(const std::wstring & database_name, const std::wstring & user, const std::wstring & pass) +{ + db_database = database_name; + db_user = user; + db_pass = pass; +} + + +void PostgreSQLConnector::overwrite(PT::TextStream & stream) +{ + PT::TextStream::iterator i = stream.begin(); + + for( ; i != stream.end() ; ++i) + { + *i = 0; + } + + stream.clear(); +} + + + + +void PostgreSQLConnector::connect() +{ + close(); + + stream.clear(); + stream << "dbname='"; + db_expression->esc(db_database, stream); + + stream << "' user='"; + db_expression->esc(db_user, stream); + + stream << "' password='"; + db_expression->esc(db_pass, stream); + 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 +} + // // // -//void PostgreSQLConnector::Connect() -//{ -// Close(); -// -// conn_info.Clear(); -// conn_info.SetExtented(false); -// -// conn_info << R("dbname=") << db_database -// << R(" user=") << db_user -// << R(" password=") << db_pass; -// -// pg_conn = PQconnectdb(conn_info.CStr()); -// -// // 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 -//} -// -// -// -//void PostgreSQLConnector::LogConnectionSocket() -//{ -// log << log2 << "Db: connection to the database works fine" << logend; -// log << log3 << "Db: connection socket: " << PQsocket(pg_conn) << logend; -//} -// -// -// -//void PostgreSQLConnector::WaitForConnection() -//{ -// if( !pg_conn || PQstatus(pg_conn) != CONNECTION_OK ) -// { -// log << log3 << "Db: waiting for the db to be ready...." << logend << logsave; -// -// while( !AssertConnection(false, false) ) -// sleep(5); -// -// LogConnectionSocket(); -// } -//} -// -// -// -//void PostgreSQLConnector::Close() -//{ -// if( pg_conn ) -// { -// PQfinish(pg_conn); -// pg_conn = 0; -// } -//} -// -// -// -//bool PostgreSQLConnector::AssertConnection(bool put_log, bool throw_if_no_connection) -//{ -//bool was_connection = true; -// -// -// if( !pg_conn ) -// { -// was_connection = false; -// Connect(); -// } -// else -// if( PQstatus(pg_conn) != CONNECTION_OK ) -// { -// if( put_log ) -// log << log2 << "Db: connection to the database is lost, trying to recover" << logend; -// -// was_connection = false; -// PQreset(pg_conn); -// } -// -// -// if( pg_conn && PQstatus(pg_conn) == CONNECTION_OK ) -// { -// if( !was_connection ) -// { + +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; + } +} + +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; + + while( !assert_connection(false, false) ) + { + sleep(5); + } + + //LogConnectionSocket(); + } +} + + + +void PostgreSQLConnector::close() +{ + if( pg_conn ) + { + PQfinish(pg_conn); + pg_conn = nullptr; + } +} + + +bool PostgreSQLConnector::assert_connection(bool put_log, bool throw_if_no_connection) +{ +bool was_connection = true; + + + if( !pg_conn ) + { + was_connection = false; + connect(); + } + else + if( PQstatus(pg_conn) != CONNECTION_OK ) + { + 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; + } + + was_connection = false; + PQreset(pg_conn); + } + + + if( pg_conn && PQstatus(pg_conn) == CONNECTION_OK ) + { + if( !was_connection ) + { // if( put_log ) // LogConnectionSocket(); -// -// SetDbParameters(); -// } -// -// return true; -// } -// else -// { -// if( put_log ) -// log << log1 << "Db: connection to db server cannot be established" << logend; -// -// if( throw_if_no_connection ) -// throw Error(WINIX_ERR_DB_FATAL_ERROR_DURING_CONNECTING); -// -// return false; -// } -//} -// -// -// -//void PostgreSQLConnector::SetDbParameters() -//{ -// if( PQsetClientEncoding(pg_conn, "UTF8") == -1 ) -// log << log1 << "Db: Can't set the proper client encoding" << logend; -//} + + set_db_parameters(); + } + + return true; + } + else + { + 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; + } + + if( throw_if_no_connection ) + { + //throw Error(WINIX_ERR_DB_FATAL_ERROR_DURING_CONNECTING); + throw int(10); + } + + return false; + } +} + +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; + } +} } diff --git a/src/postgresqlconnector.h b/src/postgresqlconnector.h index 65734bc..856fb6b 100644 --- a/src/postgresqlconnector.h +++ b/src/postgresqlconnector.h @@ -52,11 +52,21 @@ public: void set_log_queries(bool log_queries); + bool query(const PT::TextStream & stream); bool query(const char * query_str); + bool query(const std::string & query_str); + bool query_select(const char * query_str); bool query_update(const char * query_str); bool query_insert(const char * query_str); + bool query_select(const PT::TextStream & stream); + bool query_update(const PT::TextStream & stream); + bool query_insert(const PT::TextStream & stream); + + void map_values_from_query(Model & model); + + bool is_last_result(ExecStatusType t); /* @@ -81,12 +91,14 @@ public: void clear_result(); - //void SetConnParam(const std::wstring & database, const std::wstring & user, const std::wstring & pass); - //void Connect(); - //void WaitForConnection(); - //void Close(); - //bool AssertConnection(bool put_log = true, bool throw_if_no_connection = true); - //void SetDbParameters(); + void set_conn_param(const std::wstring & database, const std::wstring & user, const std::wstring & pass); + void connect(); + void wait_for_connection(); + void close(); + bool assert_connection(bool put_log = true, bool throw_if_no_connection = true); + void set_db_parameters(); + void log_connection_socket(); + //PGconn * GetPgConn(); @@ -96,6 +108,8 @@ protected: PGresult * last_result; // can be null ExecStatusType last_status; bool log_queries; + PT::TextStream stream; + std::string query_str; std::wstring db_database; std::wstring db_user; @@ -104,6 +118,7 @@ protected: void allocate_default_expression(); + void overwrite(PT::TextStream & stream); }; } diff --git a/src/postgresqlexpression.h b/src/postgresqlexpression.h index d34119c..7f9131d 100644 --- a/src/postgresqlexpression.h +++ b/src/postgresqlexpression.h @@ -43,6 +43,9 @@ namespace morm class PostgreSQLExpression : public DbExpression { +public: + + void esc(char val, PT::TextStream & stream); protected: @@ -65,7 +68,6 @@ private: void after_field_value_string(); - void esc(char val, PT::TextStream & stream); };