diff --git a/src/Makefile.dep b/src/Makefile.dep index d940ecb..40fe88f 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep @@ -36,16 +36,6 @@ dbexpression.o: ../../pikotools/convert/strtoint.h dbexpression.o: ../../pikotools/convert/text.h ../../pikotools/convert/misc.h dbexpression.o: ../../pikotools/membuffer/membuffer.h dbexpression.o: ../../pikotools/textstream/types.h morm_types.h -finder.o: finder.h model.h ../../pikotools/textstream/textstream.h -finder.o: ../../pikotools/space/space.h ../../pikotools/textstream/types.h -finder.o: ../../pikotools/date/date.h ../../pikotools/convert/convert.h -finder.o: ../../pikotools/convert/inttostr.h -finder.o: ../../pikotools/convert/strtoint.h ../../pikotools/convert/text.h -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 diff --git a/src/Makefile.o.dep b/src/Makefile.o.dep index 9bea281..c07e46f 100644 --- a/src/Makefile.o.dep +++ b/src/Makefile.o.dep @@ -1 +1 @@ -o = baseexpression.o dbconnector.o dbexpression.o finder.o flatconnector.o flatexpression.o jsonconnector.o jsonexpression.o model.o modelconnector.o postgresqlconnector.o postgresqlexpression.o \ No newline at end of file +o = baseexpression.o dbconnector.o dbexpression.o flatconnector.o flatexpression.o jsonconnector.o jsonexpression.o model.o modelconnector.o postgresqlconnector.o postgresqlexpression.o \ No newline at end of file diff --git a/src/dbconnector.cpp b/src/dbconnector.cpp index 2f8b95d..37d6164 100644 --- a/src/dbconnector.cpp +++ b/src/dbconnector.cpp @@ -112,11 +112,26 @@ bool DbConnector::query_insert(const PT::TextStream & stream) return false; } +bool DbConnector::query_remove(const PT::TextStream & stream) +{ + return false; +} + size_t DbConnector::last_select_size() { return 0; } +std::wstring DbConnector::get_last_query_error_msg() +{ + return std::wstring(); +} + +bool DbConnector::was_error_in_last_query() +{ + return false; +} + void DbConnector::set_current_row_at_beginning() { @@ -159,12 +174,12 @@ void DbConnector::generate_insert_query(PT::TextStream & stream, Model & model) if( db_expression ) { - db_expression->set_output_type(MORM_OUTPUT_TYPE_DB_UPDATE); - stream << "insert into "; model.table_name(stream); + stream << " ("; db_expression->set_work_mode(MORM_WORK_MODE_MODEL_FIELDS); + db_expression->set_output_type(MORM_OUTPUT_TYPE_DB_UPDATE); db_expression->generate_from_model(stream, model); stream << ") values ("; @@ -181,13 +196,12 @@ void DbConnector::generate_update_query(PT::TextStream & stream, Model & model) if( db_expression ) { - db_expression->set_output_type(MORM_OUTPUT_TYPE_DB_UPDATE); - stream << "update "; model.table_name(stream); - stream << " set "; + stream << " set "; db_expression->set_work_mode(MORM_WORK_MODE_MODEL_FIELDS_VALUES); + db_expression->set_output_type(MORM_OUTPUT_TYPE_DB_UPDATE); db_expression->generate_from_model(stream, model); stream << " where "; @@ -198,6 +212,20 @@ void DbConnector::generate_update_query(PT::TextStream & stream, Model & model) } +void DbConnector::generate_remove_query(PT::TextStream & stream, Model & model) +{ + allocate_default_expression_if_needed(); + + if( db_expression ) + { + stream << "delete from "; + model.table_name(stream); + 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); + } +} bool DbConnector::insert(PT::TextStream & stream, Model & model) { @@ -213,6 +241,13 @@ bool DbConnector::update(PT::TextStream & stream, Model & model) } +bool DbConnector::remove(PT::TextStream & stream, Model & model) +{ + generate_remove_query(stream, model); + return query_remove(stream); +} + + void DbConnector::deallocate_expression() { if( expression_allocated ) diff --git a/src/dbconnector.h b/src/dbconnector.h index 24a70c1..ba432d0 100644 --- a/src/dbconnector.h +++ b/src/dbconnector.h @@ -60,9 +60,11 @@ public: 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); virtual bool insert(PT::TextStream & stream, Model & model); virtual bool update(PT::TextStream & stream, Model & model); + virtual bool remove(PT::TextStream & stream, Model & model); //void ModelConnector::get_values_from_db(Model & model) @@ -76,8 +78,11 @@ public: 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 bool query_remove(const PT::TextStream & stream); virtual size_t last_select_size(); + virtual std::wstring get_last_query_error_msg(); + virtual bool was_error_in_last_query(); // give me a better name virtual void set_current_row_at_beginning(); @@ -153,6 +158,7 @@ protected: DbExpression * db_expression; bool expression_allocated; + std::wstring last_query_error_msg; virtual void allocate_default_expression() = 0; virtual void allocate_default_expression_if_needed(); diff --git a/src/finder.cpp b/src/finder.cpp deleted file mode 100644 index 98790b1..0000000 --- a/src/finder.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* - * This file is a part of morm - * and is distributed under the 2-Clause BSD licence. - * Author: Tomasz Sowa - */ - -/* - * Copyright (c) 2018, 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. - * - */ - -#include "finder.h" - - -namespace morm -{ - - - - - - - - - - - - - -} // namespace - diff --git a/src/finder.h b/src/finder.h index 4ed4d19..e221b55 100644 --- a/src/finder.h +++ b/src/finder.h @@ -59,48 +59,94 @@ public: model_connector = nullptr; out_stream = nullptr; db_expression = nullptr; + was_query_error = false; } + Finder(PT::TextStream & out_stream) + { + this->out_stream = &out_stream; + this->model_connector = nullptr; + db_expression = nullptr; + was_query_error = false; + } + Finder(ModelConnector & model_connector) { this->model_connector = &model_connector; out_stream = nullptr; db_expression = nullptr; + was_query_error = false; } + Finder(ModelConnector * model_connector) + { + this->model_connector = model_connector; + out_stream = nullptr; + db_expression = nullptr; + was_query_error = false; + } Finder(PT::TextStream & out_stream, ModelConnector & model_connector) { this->out_stream = &out_stream; this->model_connector = &model_connector; db_expression = nullptr; + was_query_error = false; + } + + Finder(PT::TextStream & out_stream, ModelConnector * model_connector) + { + this->out_stream = &out_stream; + this->model_connector = model_connector; + db_expression = nullptr; + was_query_error = false; } - Finder & find(ModelConnector & model_connector) + bool was_error() + { + return was_query_error; + } + + std::wstring get_error_msg() + { + return last_query_error; + } + + + Finder & select(ModelConnector & model_connector) { this->model_connector = &model_connector; - return find(); + return select(); } + Finder & select(ModelConnector * model_connector) + { + this->model_connector = model_connector; + return select(); + } - Finder & find(PT::TextStream & out_stream, ModelConnector & model_connector) + Finder & select(PT::TextStream & out_stream, ModelConnector & model_connector) { this->out_stream = &out_stream; this->model_connector = &model_connector; - return find(); + return select(); + } + + Finder & select(PT::TextStream & out_stream, ModelConnector * model_connector) + { + this->out_stream = &out_stream; + this->model_connector = model_connector; + return select(); } - - - - - - - Finder & find() + Finder & prepare_to_select() { + was_query_error = false; + last_query_error.clear(); + if( model_connector ) { if( !out_stream ) @@ -113,14 +159,18 @@ public: set_db_expression(); 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); + model.set_connector(model_connector); } + else + { + was_query_error = true; + last_query_error = L"out stream object is required"; + } + } + else + { + was_query_error = true; + last_query_error = L"model connector object is required"; } return *this; @@ -128,27 +178,23 @@ public: - ModelClass find_one() + Finder & select() { - //model.set_object_exists(true); + prepare_to_select(); - // at the end - db_expression = nullptr; - return model; + if( model_connector && out_stream ) + { + (*out_stream) << "SELECT "; + model_connector->generate_select_columns(*out_stream, model); + (*out_stream) << " FROM "; + model.table_name(*out_stream); + (*out_stream) << " "; + } + + return *this; } - std::vector find_many() - { - std::vector res; - - - // at the end - db_expression = nullptr; - - return res; - } - Finder & where() { @@ -162,8 +208,6 @@ public: } - - // may better names? Finder & group_or() { if( db_expression && out_stream ) @@ -315,8 +359,10 @@ public: bool get(ModelClass & result) { bool res = false; - result.clear(); - result.set_object_exists(false); + result.clear(); // here has to be a model connector (it clears all fields) + + // what about setting a model connector for the result? + // it can be a different object if( model_connector && out_stream ) { @@ -324,22 +370,20 @@ public: if( db_connector ) { - res = db_connector->query_select(*out_stream); - try { + result.before_select(); + res = db_connector->query_select(*out_stream); + if( res ) { - result.set_object_exists(true); - result.set_connector(*model_connector); - result.before_select(); + result.set_save_mode(Model::DO_UPDATE_ON_SAVE); model_connector->map_values_from_query(result); result.after_select(); } - - if( !res ) + else { - // put some log here? + result.after_select_failure(); } } catch(...) @@ -389,20 +433,25 @@ public: 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); + result.emplace_back(); // it returns a reference from c++17 + ModelClass & added_model = result.back(); + + added_model.set_connector(model_connector); + added_model.clear(); + added_model.set_save_mode(Model::DO_UPDATE_ON_SAVE); + added_model.before_select(); + model_connector->map_values_from_query(added_model); + added_model.after_select(); + db_connector->advance_current_row(); } - } - if( !res ) + // if there was a failure we do not call after_select_failure() + // because there are no any objects in the list + } + else { - // put some log here? + // log } } catch(...) @@ -422,7 +471,7 @@ public: { std::list result; get_list(result, false); - return result; + return std::move(result); } @@ -433,7 +482,8 @@ private: ModelConnector * model_connector; DbExpression * db_expression; ModelClass model; - + bool was_query_error; + std::wstring last_query_error; void set_db_expression() { diff --git a/src/model.cpp b/src/model.cpp index c80a7a3..3a817a3 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -41,13 +41,70 @@ namespace morm Model::Model() { model_connector = nullptr; - morm_object_exists = false; + save_mode = DO_INSERT_ON_SAVE; } Model::~Model() { } +void Model::set_save_mode(SaveMode save_mode) +{ + this->save_mode = save_mode; +} + + +Model::SaveMode Model::get_save_mode() +{ + return save_mode; +} + + +void Model::mark_to_delete() +{ + save_mode = DO_DELETE_ON_SAVE; +} + +void Model::mark_to_remove() +{ + save_mode = DO_DELETE_ON_SAVE; +} + +void Model::mark_to_insert() +{ + save_mode = DO_INSERT_ON_SAVE; +} + + +void Model::mark_to_update() +{ + save_mode = DO_UPDATE_ON_SAVE; +} + + +bool Model::was_db_error() +{ + if( model_connector ) + { + return model_connector->was_db_error(); + } + + return false; +} + + +std::wstring Model::get_db_error() +{ + if( model_connector ) + { + return model_connector->get_db_error(); + } + + return std::wstring(); +} + + + void Model::table_name(PT::TextStream & stream) { } @@ -58,20 +115,21 @@ void Model::set_connector(ModelConnector & connector) model_connector = &connector; } -void Model::set_object_exists(bool object_exists) +void Model::set_connector(ModelConnector * connector) { - this->morm_object_exists = object_exists; + model_connector = connector; } bool Model::object_exists() { - return morm_object_exists; + return save_mode == DO_UPDATE_ON_SAVE; } + bool Model::found() { - return morm_object_exists; + return save_mode == DO_UPDATE_ON_SAVE; } @@ -107,6 +165,7 @@ std::string Model::to_text() return str; } + std::string Model::to_string() { return to_text(); @@ -126,7 +185,10 @@ void Model::insert() { if( model_connector ) { - model_connector->insert(*this); + if( model_connector->insert(*this) ) + { + save_mode = DO_UPDATE_ON_SAVE; + } } } @@ -149,6 +211,49 @@ void Model::update() } +void Model::generate_remove_query(PT::TextStream & stream) +{ + if( model_connector ) + { + model_connector->generate_remove_query(stream, *this); + } +} + + +void Model::remove() +{ + if( model_connector ) + { + if( model_connector->remove(*this) ) + { + save_mode = DO_INSERT_ON_SAVE; + } + } +} + + +void Model::save() +{ + switch( save_mode ) + { + case DO_DELETE_ON_SAVE: + remove(); + break; + + case DO_INSERT_ON_SAVE: + insert(); + break; + + case DO_UPDATE_ON_SAVE: + update(); + break; + + case DO_NOTHING_ON_SAVE: + break; + } +} + + void Model::clear() { if( model_connector ) @@ -156,7 +261,7 @@ void Model::clear() model_connector->clear_values(*this); } - morm_object_exists = false; + save_mode = DO_INSERT_ON_SAVE; } @@ -172,6 +277,10 @@ void Model::before_update() { } +void Model::before_remove() +{ +} + void Model::after_select() { } @@ -184,6 +293,26 @@ void Model::after_update() { } +void Model::after_remove() +{ +} + +void Model::after_select_failure() +{ +} + +void Model::after_insert_failure() +{ +} + +void Model::after_update_failure() +{ +} + +void Model::after_remove_failure() +{ +} + int Model::get_connector_mode() { if( model_connector ) diff --git a/src/model.h b/src/model.h index 9a3846f..4390a1e 100644 --- a/src/model.h +++ b/src/model.h @@ -51,7 +51,34 @@ class Model { public: + enum SaveMode + { + DO_INSERT_ON_SAVE, + DO_UPDATE_ON_SAVE, + DO_DELETE_ON_SAVE, + DO_NOTHING_ON_SAVE, + }; + + virtual void set_save_mode(SaveMode save_mode); + virtual SaveMode get_save_mode(); + + virtual void mark_to_delete(); + virtual void mark_to_remove(); + + virtual void mark_to_insert(); + virtual void mark_to_update(); + + virtual bool object_exists(); + virtual bool found(); + + + virtual bool was_db_error(); + virtual std::wstring get_db_error(); + + void set_connector(ModelConnector & connector); + void set_connector(ModelConnector * connector); + /* * map fields to names @@ -81,10 +108,11 @@ public: virtual void generate_update_query(PT::TextStream & stream); virtual void update(); - virtual void set_object_exists(bool object_exists); + virtual void generate_remove_query(PT::TextStream & stream); + virtual void remove(); + + virtual void save(); - virtual bool object_exists(); - virtual bool found(); // set object to default values virtual void clear(); @@ -93,7 +121,7 @@ public: protected: ModelConnector * model_connector; - bool morm_object_exists; + SaveMode save_mode; Model(); virtual ~Model(); @@ -101,10 +129,17 @@ protected: virtual void before_select(); virtual void before_insert(); virtual void before_update(); + virtual void before_remove(); virtual void after_select(); virtual void after_insert(); virtual void after_update(); + virtual void after_remove(); + + virtual void after_select_failure(); + virtual void after_insert_failure(); + virtual void after_update_failure(); + virtual void after_remove_failure(); virtual int get_connector_mode(); diff --git a/src/modelconnector.cpp b/src/modelconnector.cpp index cb139fc..3bcb225 100644 --- a/src/modelconnector.cpp +++ b/src/modelconnector.cpp @@ -146,6 +146,30 @@ DbConnector * ModelConnector::get_db_connector() } +bool ModelConnector::was_db_error() +{ + if( db_connector ) + { + return db_connector->was_error_in_last_query(); + } + + return false; +} + + +std::wstring ModelConnector::get_db_error() +{ + if( db_connector ) + { + return db_connector->get_last_query_error_msg(); + } + + return std::wstring(); +} + + + + void ModelConnector::to_text(PT::TextStream & stream, Model & model) { if( flat_connector ) @@ -219,8 +243,23 @@ void ModelConnector::generate_update_query(PT::TextStream & stream, Model & mode } -void ModelConnector::insert(Model & model) +void ModelConnector::generate_remove_query(PT::TextStream & stream, Model & model) { + if( db_connector ) + { + model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_EXPRESSION; + db_connector->generate_remove_query(stream, model); + model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; + } +} + + + + + +bool ModelConnector::insert(Model & model) +{ + bool result = false; allocate_default_stream_if_needed(); if( db_connector && out_stream ) @@ -230,17 +269,24 @@ void ModelConnector::insert(Model & model) model.before_insert(); out_stream->clear(); - db_connector->insert(*out_stream, model); - model.after_insert(); + result = db_connector->insert(*out_stream, model); + + if( result ) + model.after_insert(); + else + model.after_insert_failure(); //db_connector_callback = nullptr; model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; } + + return result; } -void ModelConnector::update(Model & model) +bool ModelConnector::update(Model & model) { + bool result = false; allocate_default_stream_if_needed(); if( db_connector && out_stream ) @@ -250,17 +296,56 @@ void ModelConnector::update(Model & model) model.before_update(); out_stream->clear(); - db_connector->update(*out_stream, model); - model.after_update(); + result = db_connector->update(*out_stream, model); + + if( result ) + model.after_update(); + else + model.after_update_failure(); //db_connector_callback = nullptr; model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; } + + return result; +} + + + + +bool ModelConnector::remove(Model & model) +{ + bool result = false; + allocate_default_stream_if_needed(); + + if( db_connector && out_stream ) + { + model_connector_mode = MORM_MODEL_CONNECTOR_MODE_GENERATING_DB_EXPRESSION; + //db_connector_callback = db_connector; + + model.before_remove(); + out_stream->clear(); + result = db_connector->remove(*out_stream, model); + + if( result ) + model.after_remove(); + else + model.after_remove_failure(); + + //db_connector_callback = nullptr; + model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE; + } + + return result; } void ModelConnector::map_values_from_query(Model & model) { + // CHECK ME + // may we should set model.model_connector() to this? + // the same in other methods which get a model parameter + if( db_connector ) { model_connector_mode = MORM_MODEL_CONNECTOR_MODE_READING_VALUE_FROM_DB; diff --git a/src/modelconnector.h b/src/modelconnector.h index 78f10b3..1673ecc 100644 --- a/src/modelconnector.h +++ b/src/modelconnector.h @@ -63,6 +63,10 @@ public: // FIX ME // add c-copy ctr (allocate a new stream and expression) + virtual bool was_db_error(); + virtual std::wstring get_db_error(); + + virtual void set_stream(PT::TextStream & stream); virtual PT::TextStream * get_stream(); @@ -80,9 +84,11 @@ public: 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); - virtual void insert(Model & model); - virtual void update(Model & model); + virtual bool insert(Model & model); + virtual bool update(Model & model); + virtual bool remove(Model & model); virtual void map_values_from_query(Model & model); diff --git a/src/postgresqlconnector.cpp b/src/postgresqlconnector.cpp index 01ede29..cf89779 100644 --- a/src/postgresqlconnector.cpp +++ b/src/postgresqlconnector.cpp @@ -91,6 +91,8 @@ void PostgreSQLConnector::clear_last_query_result() res.result_rows = 0; res.status = PGRES_EMPTY_QUERY; res.cur_row = 0; + res.error_msg.clear(); // may overwrite it first? + res.was_error = false; query_results.pop_back(); } @@ -132,6 +134,59 @@ bool PostgreSQLConnector::is_last_result(ExecStatusType t) } +std::wstring PostgreSQLConnector::get_last_query_error_msg() +{ + if( !query_results.empty() ) + { + return query_results.back().error_msg; + } + + return std::wstring(); +} + + +void PostgreSQLConnector::set_last_query_error_msg(const char * error_msg) +{ + if( !query_results.empty() ) + { + if( error_msg ) + { + PT::UTF8ToWide(error_msg, query_results.back().error_msg); + } + } +} + + +void PostgreSQLConnector::set_last_query_error_msg(const wchar_t * error_msg) +{ + if( !query_results.empty() ) + { + if( error_msg ) + { + query_results.back().error_msg = error_msg; + } + } +} + + +bool PostgreSQLConnector::was_error_in_last_query() +{ + if( !query_results.empty() ) + { + return query_results.back().was_error; + } + + return false; +} + + +void PostgreSQLConnector::set_was_error_in_last_query(bool was_error) +{ + if( !query_results.empty() ) + { + query_results.back().was_error = was_error; + } +} void PostgreSQLConnector::allocate_default_expression() @@ -233,19 +288,55 @@ bool PostgreSQLConnector::query(const std::string & query_str) bool PostgreSQLConnector::query_select(const char * query_str) { - return (query(query_str) && last_query_status() == PGRES_TUPLES_OK); + bool result = (query(query_str) && last_query_status() == PGRES_TUPLES_OK); + + if( !result ) + { + set_was_error_in_last_query(true); + set_last_query_error_msg(PQerrorMessage(pg_conn)); + } + + return result; } bool PostgreSQLConnector::query_update(const char * query_str) { - return (query(query_str) && last_query_status() == PGRES_COMMAND_OK); + bool result = (query(query_str) && last_query_status() == PGRES_COMMAND_OK); + + if( !result ) + { + set_was_error_in_last_query(true); + set_last_query_error_msg(PQerrorMessage(pg_conn)); + } + + return result; } bool PostgreSQLConnector::query_insert(const char * query_str) { - return (query(query_str) && last_query_status() == PGRES_COMMAND_OK); + bool result = (query(query_str) && last_query_status() == PGRES_COMMAND_OK); + + if( !result ) + { + set_was_error_in_last_query(true); + set_last_query_error_msg(PQerrorMessage(pg_conn)); + } + + return result; } +bool PostgreSQLConnector::query_remove(const char * query_str) +{ + bool result = (query(query_str) && last_query_status() == PGRES_COMMAND_OK); + + if( !result ) + { + set_was_error_in_last_query(true); + set_last_query_error_msg(PQerrorMessage(pg_conn)); + } + + return result; +} bool PostgreSQLConnector::query_select(const PT::TextStream & stream) @@ -266,6 +357,11 @@ bool PostgreSQLConnector::query_insert(const PT::TextStream & stream) return query_insert(query_str.c_str()); } +bool PostgreSQLConnector::query_remove(const PT::TextStream & stream) +{ + stream.to_string(query_str); + return query_remove(query_str.c_str()); +} diff --git a/src/postgresqlconnector.h b/src/postgresqlconnector.h index 856132a..d0ad48f 100644 --- a/src/postgresqlconnector.h +++ b/src/postgresqlconnector.h @@ -47,6 +47,7 @@ namespace morm class PostgreSQLConnector : public DbConnector { public: + PostgreSQLConnector(); virtual ~PostgreSQLConnector(); @@ -54,10 +55,16 @@ public: void clear_last_query_result(); // give me a better names - virtual size_t last_select_size(); // was: last_select_size + virtual size_t last_select_size(); virtual ExecStatusType last_query_status(); virtual bool is_last_result(ExecStatusType t); // was: is_last_result + virtual std::wstring get_last_query_error_msg(); + virtual void set_last_query_error_msg(const char * error_msg); + virtual void set_last_query_error_msg(const wchar_t * error_msg); + + virtual bool was_error_in_last_query(); + virtual void set_was_error_in_last_query(bool was_error); void set_log_queries(bool log_queries); @@ -68,10 +75,12 @@ public: bool query_select(const char * query_str); bool query_update(const char * query_str); bool query_insert(const char * query_str); + bool query_remove(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); + bool query_remove(const PT::TextStream & stream); // give me a better name @@ -134,6 +143,8 @@ protected: size_t result_rows; // how many rows in the result query ExecStatusType status; size_t cur_row; // used for reading + bool was_error; + std::wstring error_msg; QueryResult() { @@ -141,6 +152,7 @@ protected: result_rows = 0; status = PGRES_EMPTY_QUERY; cur_row = 0; + was_error = false; } }; @@ -154,6 +166,7 @@ protected: virtual const char * get_field_string_value(const wchar_t * field_name); + const char * query_last_sequence(const wchar_t * sequence_table_name); };