added Cursor class
git-svn-id: svn://ttmath.org/publicrep/morm/trunk@1140 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
parent
011d8f96e8
commit
1f9e4ee70a
|
@ -12,8 +12,9 @@ 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 clearer.h dbconnector.h
|
||||
baseexpression.o: ../../pikotools/logger/logger.h flatconnector.h
|
||||
baseexpression.o: dbexpression.h flatexpression.h ../../pikotools/utf8/utf8.h
|
||||
baseexpression.o: ../../pikotools/logger/logger.h queryresult.h
|
||||
baseexpression.o: flatconnector.h dbexpression.h flatexpression.h
|
||||
baseexpression.o: ../../pikotools/utf8/utf8.h
|
||||
clearer.o: clearer.h ../../pikotools/date/date.h
|
||||
clearer.o: ../../pikotools/convert/convert.h
|
||||
clearer.o: ../../pikotools/convert/inttostr.h
|
||||
|
@ -23,8 +24,8 @@ clearer.o: ../../pikotools/textstream/textstream.h
|
|||
clearer.o: ../../pikotools/space/space.h ../../pikotools/textstream/types.h
|
||||
clearer.o: ../../pikotools/membuffer/membuffer.h
|
||||
clearer.o: ../../pikotools/textstream/types.h modelconnector.h dbconnector.h
|
||||
clearer.o: ../../pikotools/logger/logger.h flatconnector.h dbexpression.h
|
||||
clearer.o: baseexpression.h morm_types.h flatexpression.h
|
||||
clearer.o: ../../pikotools/logger/logger.h queryresult.h flatconnector.h
|
||||
clearer.o: dbexpression.h baseexpression.h morm_types.h flatexpression.h
|
||||
dbconnector.o: dbconnector.h ../../pikotools/textstream/textstream.h
|
||||
dbconnector.o: ../../pikotools/space/space.h
|
||||
dbconnector.o: ../../pikotools/textstream/types.h ../../pikotools/date/date.h
|
||||
|
@ -34,7 +35,7 @@ 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
|
||||
dbconnector.o: ../../pikotools/logger/logger.h dbexpression.h
|
||||
dbconnector.o: ../../pikotools/logger/logger.h queryresult.h dbexpression.h
|
||||
dbconnector.o: baseexpression.h morm_types.h model.h modelconnector.h
|
||||
dbconnector.o: clearer.h flatconnector.h flatexpression.h
|
||||
dbconnector.o: ../../pikotools/utf8/utf8.h
|
||||
|
@ -86,7 +87,7 @@ flatconnector.o: ../../pikotools/membuffer/membuffer.h
|
|||
flatconnector.o: ../../pikotools/textstream/types.h flatexpression.h
|
||||
flatconnector.o: baseexpression.h morm_types.h model.h modelconnector.h
|
||||
flatconnector.o: clearer.h dbconnector.h ../../pikotools/logger/logger.h
|
||||
flatconnector.o: dbexpression.h
|
||||
flatconnector.o: queryresult.h dbexpression.h
|
||||
flatexpression.o: flatexpression.h baseexpression.h
|
||||
flatexpression.o: ../../pikotools/textstream/textstream.h
|
||||
flatexpression.o: ../../pikotools/space/space.h
|
||||
|
@ -131,8 +132,9 @@ 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 clearer.h
|
||||
model.o: dbconnector.h ../../pikotools/logger/logger.h flatconnector.h
|
||||
model.o: dbexpression.h baseexpression.h morm_types.h flatexpression.h
|
||||
model.o: dbconnector.h ../../pikotools/logger/logger.h queryresult.h
|
||||
model.o: flatconnector.h dbexpression.h baseexpression.h morm_types.h
|
||||
model.o: flatexpression.h
|
||||
modelconnector.o: modelconnector.h clearer.h ../../pikotools/date/date.h
|
||||
modelconnector.o: ../../pikotools/convert/convert.h
|
||||
modelconnector.o: ../../pikotools/convert/inttostr.h
|
||||
|
@ -144,7 +146,8 @@ modelconnector.o: ../../pikotools/space/space.h
|
|||
modelconnector.o: ../../pikotools/textstream/types.h
|
||||
modelconnector.o: ../../pikotools/membuffer/membuffer.h
|
||||
modelconnector.o: ../../pikotools/textstream/types.h
|
||||
modelconnector.o: ../../pikotools/logger/logger.h flatconnector.h
|
||||
modelconnector.o: ../../pikotools/logger/logger.h queryresult.h
|
||||
modelconnector.o: flatconnector.h
|
||||
postgresqlconnector.o: postgresqlconnector.h dbconnector.h
|
||||
postgresqlconnector.o: ../../pikotools/textstream/textstream.h
|
||||
postgresqlconnector.o: ../../pikotools/space/space.h
|
||||
|
@ -157,10 +160,10 @@ postgresqlconnector.o: ../../pikotools/convert/text.h
|
|||
postgresqlconnector.o: ../../pikotools/convert/misc.h
|
||||
postgresqlconnector.o: ../../pikotools/membuffer/membuffer.h
|
||||
postgresqlconnector.o: ../../pikotools/textstream/types.h
|
||||
postgresqlconnector.o: ../../pikotools/logger/logger.h
|
||||
postgresqlconnector.o: ../../pikotools/utf8/utf8.h postgresqlexpression.h
|
||||
postgresqlconnector.o: dbexpression.h baseexpression.h morm_types.h
|
||||
postgresqlconnector.o: ../../pikotools/convert/strtoint.h
|
||||
postgresqlconnector.o: ../../pikotools/logger/logger.h queryresult.h
|
||||
postgresqlconnector.o: postgresqlqueryresult.h ../../pikotools/utf8/utf8.h
|
||||
postgresqlconnector.o: postgresqlexpression.h dbexpression.h baseexpression.h
|
||||
postgresqlconnector.o: morm_types.h ../../pikotools/convert/strtoint.h
|
||||
postgresqlexpression.o: postgresqlexpression.h dbexpression.h
|
||||
postgresqlexpression.o: baseexpression.h
|
||||
postgresqlexpression.o: ../../pikotools/textstream/textstream.h
|
||||
|
@ -174,3 +177,5 @@ postgresqlexpression.o: ../../pikotools/convert/text.h
|
|||
postgresqlexpression.o: ../../pikotools/convert/misc.h
|
||||
postgresqlexpression.o: ../../pikotools/membuffer/membuffer.h
|
||||
postgresqlexpression.o: ../../pikotools/textstream/types.h morm_types.h
|
||||
postgresqlqueryresult.o: postgresqlqueryresult.h queryresult.h
|
||||
queryresult.o: queryresult.h ../../pikotools/utf8/utf8.h
|
||||
|
|
|
@ -1 +1 @@
|
|||
o = baseexpression.o clearer.o dbconnector.o dbexpression.o dochtmlconnector.o dochtmlexpression.o flatconnector.o flatexpression.o jsonconnector.o jsonexpression.o model.o modelconnector.o postgresqlconnector.o postgresqlexpression.o
|
||||
o = baseexpression.o clearer.o dbconnector.o dbexpression.o dochtmlconnector.o dochtmlexpression.o flatconnector.o flatexpression.o jsonconnector.o jsonexpression.o model.o modelconnector.o postgresqlconnector.o postgresqlexpression.o postgresqlqueryresult.o queryresult.o
|
|
@ -0,0 +1,312 @@
|
|||
/*
|
||||
* This file is a part of morm
|
||||
* and is distributed under the 2-Clause BSD licence.
|
||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef headerfile_morm_cursor
|
||||
#define headerfile_morm_cursor
|
||||
|
||||
#include "queryresult.h"
|
||||
#include "modelconnector.h"
|
||||
|
||||
|
||||
namespace morm
|
||||
{
|
||||
|
||||
template<typename ModelClass>
|
||||
class Cursor
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
|
||||
Cursor()
|
||||
{
|
||||
set_default_values();
|
||||
}
|
||||
|
||||
|
||||
Cursor(const Cursor & c)
|
||||
{
|
||||
model_connector = c.model_connector;
|
||||
model_data = c.model_data;
|
||||
query_result = c.query_result;
|
||||
select_status = c.select_status;
|
||||
|
||||
if( query_result )
|
||||
{
|
||||
query_result->references_count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Cursor & operator=(const Cursor & c) = delete;
|
||||
|
||||
|
||||
virtual ~Cursor()
|
||||
{
|
||||
if( query_result && query_result->references_count > 0 )
|
||||
{
|
||||
query_result->references_count -= 1;
|
||||
}
|
||||
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
virtual void clear()
|
||||
{
|
||||
if( query_result && query_result->references_count == 0 )
|
||||
{
|
||||
query_result->clear();
|
||||
delete query_result;
|
||||
}
|
||||
|
||||
set_default_values();
|
||||
}
|
||||
|
||||
|
||||
virtual void set_model_connector(ModelConnector * model_connector)
|
||||
{
|
||||
this->model_connector = model_connector;
|
||||
}
|
||||
|
||||
|
||||
virtual void set_model_data(Model::ModelData * model_data)
|
||||
{
|
||||
this->model_data = model_data;
|
||||
}
|
||||
|
||||
|
||||
virtual void set_query_result(QueryResult * query_result)
|
||||
{
|
||||
this->query_result = query_result;
|
||||
}
|
||||
|
||||
|
||||
virtual void set_select_status(bool select_status)
|
||||
{
|
||||
this->select_status = select_status;
|
||||
}
|
||||
|
||||
|
||||
virtual QueryResult * get_query_result()
|
||||
{
|
||||
return query_result;
|
||||
}
|
||||
|
||||
|
||||
virtual bool has_next()
|
||||
{
|
||||
bool has = false;
|
||||
|
||||
if( model_connector && query_result && query_result->has_db_result() && select_status )
|
||||
{
|
||||
has = query_result->cur_row < query_result->result_rows;
|
||||
}
|
||||
|
||||
return has;
|
||||
}
|
||||
|
||||
|
||||
virtual bool get(ModelClass & result)
|
||||
{
|
||||
bool res = false;
|
||||
result.set_connector(model_connector);
|
||||
result.clear();
|
||||
|
||||
if( model_connector && query_result && query_result->has_db_result() )
|
||||
{
|
||||
DbConnector * db_connector = model_connector->get_db_connector();
|
||||
|
||||
if( db_connector )
|
||||
{
|
||||
try
|
||||
{
|
||||
result.model_data = model_data;
|
||||
result.before_select();
|
||||
res = select_status;
|
||||
|
||||
if( res )
|
||||
{
|
||||
if( query_result->cur_row < query_result->result_rows )
|
||||
{
|
||||
result.set_save_mode(Model::DO_UPDATE_ON_SAVE); // IMPROVE ME check if there is a primary key
|
||||
result.map_values_from_query(query_result);
|
||||
result.after_select();
|
||||
query_result->cur_row += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = false;
|
||||
// log some error or throw an exception?
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.after_select_failure();
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
res = false;
|
||||
// throw something?
|
||||
}
|
||||
|
||||
result.model_data = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
virtual ModelClass get()
|
||||
{
|
||||
ModelClass model;
|
||||
|
||||
get(model);
|
||||
return std::move(model);
|
||||
}
|
||||
|
||||
|
||||
virtual bool get_list(std::list<ModelClass> & result, bool clear_list = true)
|
||||
{
|
||||
bool res = false;
|
||||
|
||||
if( clear_list )
|
||||
{
|
||||
result.clear();
|
||||
}
|
||||
|
||||
if( model_connector && query_result && query_result->has_db_result() )
|
||||
{
|
||||
DbConnector * db_connector = model_connector->get_db_connector();
|
||||
|
||||
if( db_connector )
|
||||
{
|
||||
res = select_status;
|
||||
|
||||
try
|
||||
{
|
||||
if( res )
|
||||
{
|
||||
res = add_models_to_list(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
// add log
|
||||
|
||||
// if there was a failure we do not call after_select_failure()
|
||||
// because there are no any objects in the list
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
res = false;
|
||||
// throw or something?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
virtual std::list<ModelClass> get_list()
|
||||
{
|
||||
std::list<ModelClass> result;
|
||||
|
||||
get_list(result, false);
|
||||
return std::move(result);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
ModelConnector * model_connector;
|
||||
Model::ModelData * model_data;
|
||||
QueryResult * query_result;
|
||||
bool select_status;
|
||||
|
||||
|
||||
virtual void set_default_values()
|
||||
{
|
||||
model_connector = nullptr;
|
||||
model_data = nullptr;
|
||||
query_result = nullptr;
|
||||
select_status = false;
|
||||
}
|
||||
|
||||
|
||||
template<typename ContainerType>
|
||||
bool add_models_to_list(ContainerType & result)
|
||||
{
|
||||
bool res = true;
|
||||
|
||||
for(query_result->cur_row = 0 ; query_result->cur_row < query_result->result_rows ; query_result->cur_row += 1)
|
||||
{
|
||||
result.emplace_back(); // it returns a reference from c++17
|
||||
ModelClass & added_model = result.back();
|
||||
|
||||
try
|
||||
{
|
||||
added_model.set_connector(model_connector);
|
||||
added_model.clear();
|
||||
added_model.set_save_mode(Model::DO_UPDATE_ON_SAVE); // IMPROVE ME check if there is a primary key
|
||||
added_model.model_data = model_data;
|
||||
added_model.before_select();
|
||||
added_model.map_values_from_query(query_result);
|
||||
added_model.after_select();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
res = false;
|
||||
// throw or something?
|
||||
}
|
||||
|
||||
added_model.model_data = nullptr;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
|
@ -33,6 +33,7 @@
|
|||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include "dbconnector.h"
|
||||
#include "dbexpression.h"
|
||||
#include "model.h"
|
||||
|
@ -75,36 +76,22 @@ void DbConnector::set_logger(PT::Logger & logger)
|
|||
|
||||
|
||||
|
||||
void DbConnector::clear_last_query_result()
|
||||
bool DbConnector::query(const PT::TextStream & stream, QueryResult & query_result)
|
||||
{
|
||||
std::string query_str;
|
||||
stream.to_string(query_str);
|
||||
|
||||
return query(query_str, query_result);
|
||||
}
|
||||
|
||||
|
||||
bool DbConnector::query(const PT::TextStream & stream)
|
||||
bool DbConnector::query(const std::string & query_str, QueryResult & query_result)
|
||||
{
|
||||
return false;
|
||||
return query(query_str.c_str(), query_result);
|
||||
}
|
||||
|
||||
|
||||
//bool DbConnector::query(const std::wstring & query)
|
||||
//{
|
||||
// return false;
|
||||
//}
|
||||
|
||||
|
||||
bool DbConnector::query(const std::string & query_str)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//bool DbConnector::query(const wchar_t * query)
|
||||
//{
|
||||
// return false;
|
||||
//}
|
||||
|
||||
|
||||
bool DbConnector::query(const char * query_str)
|
||||
bool DbConnector::query(const char * query_str, QueryResult & query_result)
|
||||
{
|
||||
// do query
|
||||
return false;
|
||||
|
@ -112,55 +99,48 @@ bool DbConnector::query(const char * query_str)
|
|||
|
||||
|
||||
|
||||
bool DbConnector::query_select(const PT::TextStream & stream)
|
||||
bool DbConnector::query_select(const char * query_str, QueryResult & query_result)
|
||||
{
|
||||
return false;
|
||||
return query(query_str, query_result);
|
||||
}
|
||||
|
||||
bool DbConnector::query_update(const PT::TextStream & stream)
|
||||
bool DbConnector::query_update(const char * query_str, QueryResult & query_result)
|
||||
{
|
||||
return false;
|
||||
return query(query_str, query_result);
|
||||
}
|
||||
|
||||
bool DbConnector::query_insert(const PT::TextStream & stream)
|
||||
bool DbConnector::query_insert(const char * query_str, QueryResult & query_result)
|
||||
{
|
||||
return false;
|
||||
return query(query_str, query_result);
|
||||
}
|
||||
|
||||
bool DbConnector::query_remove(const PT::TextStream & stream)
|
||||
bool DbConnector::query_remove(const char * query_str, QueryResult & query_result)
|
||||
{
|
||||
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;
|
||||
return query(query_str, query_result);
|
||||
}
|
||||
|
||||
|
||||
void DbConnector::set_current_row_at_beginning()
|
||||
|
||||
bool DbConnector::query_select(const PT::TextStream & stream, QueryResult & query_result)
|
||||
{
|
||||
return query(stream, query_result);
|
||||
}
|
||||
|
||||
void DbConnector::advance_current_row()
|
||||
bool DbConnector::query_update(const PT::TextStream & stream, QueryResult & query_result)
|
||||
{
|
||||
return query(stream, query_result);
|
||||
}
|
||||
|
||||
bool DbConnector::query_insert(const PT::TextStream & stream, QueryResult & query_result)
|
||||
{
|
||||
return query(stream, query_result);
|
||||
}
|
||||
|
||||
bool DbConnector::query_remove(const PT::TextStream & stream, QueryResult & query_result)
|
||||
{
|
||||
return query(stream, query_result);
|
||||
}
|
||||
|
||||
//void DbConnector::map_values_from_query(Model & model)
|
||||
//{
|
||||
// model.clear();
|
||||
//}
|
||||
|
||||
|
||||
DbExpression * DbConnector::get_expression()
|
||||
|
@ -249,22 +229,28 @@ void DbConnector::generate_remove_query(PT::TextStream & stream, Model & model)
|
|||
|
||||
bool DbConnector::insert(PT::TextStream & stream, Model & model)
|
||||
{
|
||||
std::unique_ptr<QueryResult> query_result_ptr(create_query_result());
|
||||
|
||||
generate_insert_query(stream, model);
|
||||
return query_insert(stream);
|
||||
return query_insert(stream, *query_result_ptr);
|
||||
}
|
||||
|
||||
|
||||
bool DbConnector::update(PT::TextStream & stream, Model & model)
|
||||
{
|
||||
std::unique_ptr<QueryResult> query_result_ptr(create_query_result());
|
||||
|
||||
generate_update_query(stream, model);
|
||||
return query_update(stream);
|
||||
return query_update(stream, *query_result_ptr);
|
||||
}
|
||||
|
||||
|
||||
bool DbConnector::remove(PT::TextStream & stream, Model & model)
|
||||
{
|
||||
std::unique_ptr<QueryResult> query_result_ptr(create_query_result());
|
||||
|
||||
generate_remove_query(stream, model);
|
||||
return query_remove(stream);
|
||||
return query_remove(stream, *query_result_ptr);
|
||||
}
|
||||
|
||||
|
||||
|
@ -288,15 +274,6 @@ void DbConnector::allocate_default_expression_if_needed()
|
|||
}
|
||||
}
|
||||
|
||||
const char * DbConnector::get_field_string_value(const char * field_name)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char * DbConnector::get_field_string_value(const wchar_t * field_name)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
#include "textstream/textstream.h"
|
||||
#include "logger/logger.h"
|
||||
#include "queryresult.h"
|
||||
|
||||
|
||||
namespace morm
|
||||
|
@ -58,7 +59,7 @@ public:
|
|||
|
||||
DbExpression * get_expression();
|
||||
|
||||
virtual void clear_last_query_result();
|
||||
//virtual void clear_last_query_result();
|
||||
|
||||
virtual void generate_select_columns(PT::TextStream & stream, Model & model, const std::wstring & column_prefix);
|
||||
virtual void generate_insert_query(PT::TextStream & stream, Model & model);
|
||||
|
@ -71,27 +72,21 @@ public:
|
|||
|
||||
//void ModelConnector::get_values_from_db(Model & model)
|
||||
|
||||
virtual QueryResult * create_query_result() = 0;
|
||||
|
||||
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(const PT::TextStream & stream, QueryResult & query_result);
|
||||
virtual bool query(const std::string & query_str, QueryResult & query_result);
|
||||
virtual bool query(const char * query_str, QueryResult & query_result);
|
||||
|
||||
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 bool query_select(const char * query_str, QueryResult & query_result);
|
||||
virtual bool query_update(const char * query_str, QueryResult & query_result);
|
||||
virtual bool query_insert(const char * query_str, QueryResult & query_result);
|
||||
virtual bool query_remove(const char * query_str, QueryResult & query_result);
|
||||
|
||||
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();
|
||||
virtual void advance_current_row();
|
||||
|
||||
//virtual void map_values_from_query(Model & model);
|
||||
virtual bool query_select(const PT::TextStream & stream, QueryResult & query_result);
|
||||
virtual bool query_update(const PT::TextStream & stream, QueryResult & query_result);
|
||||
virtual bool query_insert(const PT::TextStream & stream, QueryResult & query_result);
|
||||
virtual bool query_remove(const PT::TextStream & stream, QueryResult & query_result);
|
||||
|
||||
virtual void get_value(const char * value_str, char & field_value);
|
||||
virtual void get_value(const char * value_str, unsigned char & field_value);
|
||||
|
@ -112,18 +107,6 @@ public:
|
|||
virtual void get_value(const char * value_str, PT::Date & 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)
|
||||
{
|
||||
|
@ -140,7 +123,6 @@ protected:
|
|||
|
||||
DbExpression * db_expression;
|
||||
bool expression_allocated;
|
||||
std::wstring last_query_error_msg;
|
||||
PT::Logger * logger;
|
||||
|
||||
|
||||
|
@ -148,9 +130,6 @@ protected:
|
|||
virtual void allocate_default_expression_if_needed();
|
||||
virtual void deallocate_expression();
|
||||
|
||||
virtual const char * get_field_string_value(const char * field_name);
|
||||
virtual const char * get_field_string_value(const wchar_t * field_name);
|
||||
|
||||
virtual const char * query_last_sequence(const wchar_t * sequence_table_name);
|
||||
|
||||
|
||||
|
|
132
src/finder.h
132
src/finder.h
|
@ -42,6 +42,7 @@
|
|||
#include "textstream/textstream.h"
|
||||
#include "dbconnector.h"
|
||||
#include "modelconnector.h"
|
||||
#include "cursor.h"
|
||||
|
||||
|
||||
namespace morm
|
||||
|
@ -431,61 +432,42 @@ public:
|
|||
}
|
||||
|
||||
|
||||
bool get(ModelClass & result)
|
||||
Cursor<ModelClass> get_cursor()
|
||||
{
|
||||
bool res = false;
|
||||
result.set_connector(model_connector);
|
||||
result.clear();
|
||||
Cursor<ModelClass> cursor;
|
||||
cursor.set_model_data(model_data);
|
||||
|
||||
if( model_connector && out_stream )
|
||||
{
|
||||
cursor.set_model_connector(model_connector);
|
||||
DbConnector * db_connector = model_connector->get_db_connector();
|
||||
|
||||
if( db_connector )
|
||||
{
|
||||
try
|
||||
{
|
||||
result.model_data = model_data;
|
||||
result.before_select();
|
||||
res = db_connector->query_select(*out_stream);
|
||||
QueryResult * query_result = db_connector->create_query_result();
|
||||
cursor.set_query_result(query_result);
|
||||
query_result->references_count = 1;
|
||||
|
||||
if( res )
|
||||
{
|
||||
if( db_connector->last_select_size() == 1 )
|
||||
{
|
||||
result.set_save_mode(Model::DO_UPDATE_ON_SAVE); // IMPROVE ME check if there is a primary key
|
||||
result.map_values_from_query();
|
||||
result.after_select();
|
||||
}
|
||||
else
|
||||
{
|
||||
res = false;
|
||||
// log some error or throw an exception if there are more items than one?
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.after_select_failure();
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
res = false;
|
||||
// throw something?
|
||||
// if yes then make sure to call db_connector->clear_last_query_result();
|
||||
}
|
||||
|
||||
result.model_data = nullptr;
|
||||
db_connector->clear_last_query_result();
|
||||
bool status = db_connector->query_select(*out_stream, *query_result);
|
||||
cursor.set_select_status(status);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
return cursor;
|
||||
}
|
||||
|
||||
|
||||
bool get(ModelClass & result)
|
||||
{
|
||||
Cursor<ModelClass> cursor = get_cursor();
|
||||
return cursor.get(result);
|
||||
}
|
||||
|
||||
|
||||
ModelClass get()
|
||||
{
|
||||
ModelClass model;
|
||||
|
||||
get(model);
|
||||
return model;
|
||||
}
|
||||
|
@ -493,84 +475,22 @@ public:
|
|||
|
||||
bool get_list(std::list<ModelClass> & result, bool clear_list = true)
|
||||
{
|
||||
bool res = false;
|
||||
|
||||
if( clear_list )
|
||||
{
|
||||
result.clear();
|
||||
}
|
||||
|
||||
if( model_connector && out_stream )
|
||||
{
|
||||
DbConnector * db_connector = model_connector->get_db_connector();
|
||||
|
||||
if( db_connector )
|
||||
{
|
||||
res = db_connector->query_select(*out_stream);
|
||||
|
||||
try
|
||||
{
|
||||
if( res )
|
||||
{
|
||||
size_t len = db_connector->last_select_size();
|
||||
db_connector->set_current_row_at_beginning();
|
||||
|
||||
for(size_t i = 0 ; i < len ; ++i)
|
||||
{
|
||||
result.emplace_back(); // it returns a reference from c++17
|
||||
ModelClass & added_model = result.back();
|
||||
|
||||
try
|
||||
{
|
||||
added_model.set_connector(model_connector);
|
||||
added_model.clear();
|
||||
added_model.set_save_mode(Model::DO_UPDATE_ON_SAVE); // IMPROVE ME check if there is a primary key
|
||||
added_model.model_data = model_data;
|
||||
added_model.before_select();
|
||||
added_model.map_values_from_query();
|
||||
added_model.after_select();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
res = false;
|
||||
// throw or something?
|
||||
// make sure to call db_connector->clear_last_query_result()
|
||||
}
|
||||
|
||||
added_model.model_data = nullptr;
|
||||
db_connector->advance_current_row();
|
||||
}
|
||||
|
||||
// if there was a failure we do not call after_select_failure()
|
||||
// because there are no any objects in the list
|
||||
}
|
||||
else
|
||||
{
|
||||
// log
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
res = false;
|
||||
// throw or something?
|
||||
// make sure to call db_connector->clear_last_query_result()
|
||||
}
|
||||
|
||||
db_connector->clear_last_query_result();
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
Cursor<ModelClass> cursor = get_cursor();
|
||||
return cursor.get_list(result, clear_list);
|
||||
}
|
||||
|
||||
|
||||
std::list<ModelClass> get_list()
|
||||
{
|
||||
std::list<ModelClass> result;
|
||||
|
||||
get_list(result, false);
|
||||
return std::move(result);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
|
|
|
@ -45,8 +45,22 @@ Model::Model()
|
|||
doc_field_pointer = nullptr;
|
||||
save_mode = DO_INSERT_ON_SAVE;
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
query_result = nullptr;
|
||||
}
|
||||
|
||||
|
||||
Model::Model(const Model & m)
|
||||
{
|
||||
model_connector = m.model_connector;
|
||||
save_mode = m.save_mode;
|
||||
|
||||
model_data = nullptr;
|
||||
doc_field_pointer = nullptr; // does it need to be copied?
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
query_result = nullptr;
|
||||
}
|
||||
|
||||
|
||||
Model::~Model()
|
||||
{
|
||||
}
|
||||
|
@ -85,28 +99,6 @@ void Model::mark_to_update()
|
|||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -472,11 +464,15 @@ void Model::generate_doc_for_db(PT::TextStream & stream, bool clear_stream)
|
|||
}
|
||||
|
||||
|
||||
void Model::map_values_from_query()
|
||||
void Model::map_values_from_query(QueryResult * query_result)
|
||||
{
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_READING_VALUE_FROM_DB_RESULTSET;
|
||||
this->query_result = query_result;
|
||||
|
||||
map_fields();
|
||||
|
||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
||||
this->query_result = nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
|
38
src/model.h
38
src/model.h
|
@ -41,6 +41,7 @@
|
|||
#include "modelconnector.h"
|
||||
#include "dbexpression.h"
|
||||
#include "flatexpression.h"
|
||||
#include "queryresult.h"
|
||||
|
||||
|
||||
|
||||
|
@ -92,10 +93,6 @@ public:
|
|||
virtual bool found();
|
||||
|
||||
|
||||
virtual bool was_db_error();
|
||||
virtual std::wstring get_db_error();
|
||||
|
||||
|
||||
void set_connector(ModelConnector & connector);
|
||||
void set_connector(ModelConnector * connector);
|
||||
|
||||
|
@ -155,8 +152,11 @@ protected:
|
|||
ModelData * model_data;
|
||||
const void * doc_field_pointer;
|
||||
int model_connector_mode;
|
||||
QueryResult * query_result;
|
||||
|
||||
|
||||
Model();
|
||||
Model(const Model & m);
|
||||
virtual ~Model();
|
||||
|
||||
virtual void before_select();
|
||||
|
@ -176,8 +176,8 @@ protected:
|
|||
|
||||
virtual int get_connector_mode();
|
||||
|
||||
// used by Finder
|
||||
virtual void map_values_from_query();
|
||||
// used by Cursor
|
||||
virtual void map_values_from_query(QueryResult * query_result);
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
|
@ -684,7 +684,7 @@ protected:
|
|||
if( db_connector )
|
||||
{
|
||||
if( !is_empty_field(db_field_name) )
|
||||
db_connector->get_value_by_field_name(db_field_name, field_value);
|
||||
get_value_by_field_name(db_field_name, field_value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -825,6 +825,27 @@ protected:
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename FieldValue>
|
||||
void get_value_by_field_name(const wchar_t * field_name, FieldValue & field_value)
|
||||
{
|
||||
if( query_result )
|
||||
{
|
||||
const char * val_str = query_result->get_field_string_value(field_name);
|
||||
|
||||
if( val_str )
|
||||
{
|
||||
DbConnector * db_connector = model_connector->get_db_connector();
|
||||
|
||||
if( db_connector )
|
||||
{
|
||||
db_connector->get_value(val_str, field_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////
|
||||
template<typename FieldValue>
|
||||
void doc_field_generic(const wchar_t * db_field_name, const wchar_t * flat_field_name, FieldValue & field_value)
|
||||
|
@ -966,7 +987,8 @@ protected:
|
|||
virtual bool is_empty_field(const wchar_t * value);
|
||||
|
||||
|
||||
template<typename ModelClass> friend class Finder;
|
||||
// template<typename ModelClass> friend class Finder;
|
||||
template<typename ModelClass> friend class Cursor;
|
||||
friend class BaseExpression;
|
||||
|
||||
};
|
||||
|
|
|
@ -197,28 +197,5 @@ Clearer * ModelConnector::get_clearer()
|
|||
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -56,17 +56,12 @@ class ModelConnector
|
|||
public:
|
||||
|
||||
ModelConnector();
|
||||
ModelConnector(const ModelConnector &) = delete;
|
||||
virtual ~ModelConnector();
|
||||
|
||||
virtual void set_logger(PT::Logger * logger);
|
||||
virtual void set_logger(PT::Logger & logger);
|
||||
|
||||
// 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();
|
||||
|
|
|
@ -61,149 +61,12 @@ void PostgreSQLConnector::close()
|
|||
{
|
||||
if( pg_conn )
|
||||
{
|
||||
clear_all_query_results();
|
||||
PQfinish(pg_conn);
|
||||
pg_conn = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PostgreSQLConnector::clear_all_query_results()
|
||||
{
|
||||
while( !query_results.empty() )
|
||||
{
|
||||
clear_last_query_result();
|
||||
}
|
||||
}
|
||||
|
||||
void PostgreSQLConnector::clear_last_query_result()
|
||||
{
|
||||
if( !query_results.empty() )
|
||||
{
|
||||
QueryResult & res = query_results.back();
|
||||
|
||||
if( res.result )
|
||||
{
|
||||
PQclear(res.result);
|
||||
}
|
||||
|
||||
res.result = nullptr;
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// to nie tylko dla selectow moze byc uzywane
|
||||
size_t PostgreSQLConnector::last_select_size()
|
||||
{
|
||||
if( !query_results.empty() )
|
||||
{
|
||||
return query_results.back().result_rows;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ExecStatusType PostgreSQLConnector::last_query_status()
|
||||
{
|
||||
if( !query_results.empty() )
|
||||
{
|
||||
return query_results.back().status;
|
||||
}
|
||||
|
||||
return PGRES_EMPTY_QUERY;
|
||||
}
|
||||
|
||||
|
||||
bool PostgreSQLConnector::is_last_result(ExecStatusType t)
|
||||
{
|
||||
if( !query_results.empty() )
|
||||
{
|
||||
QueryResult & res = query_results.back();
|
||||
return (res.result && PQresultStatus(res.result) == t);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
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()
|
||||
{
|
||||
if( pg_conn )
|
||||
{
|
||||
set_last_query_error_msg(PQerrorMessage(pg_conn));
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
query_results.back().error_msg.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
query_results.back().error_msg.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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()
|
||||
{
|
||||
|
@ -220,76 +83,106 @@ void PostgreSQLConnector::set_log_queries(bool log_queries)
|
|||
}
|
||||
|
||||
|
||||
bool PostgreSQLConnector::query(const char * query_str)
|
||||
QueryResult * PostgreSQLConnector::create_query_result()
|
||||
{
|
||||
if( pg_conn )
|
||||
return new PostgreSQLQueryResult();
|
||||
}
|
||||
|
||||
|
||||
bool PostgreSQLConnector::do_query(const char * query_str, PostgreSQLQueryResult * psql_result)
|
||||
{
|
||||
if( pg_conn && psql_result )
|
||||
{
|
||||
if( log_queries && logger )
|
||||
{
|
||||
(*logger) << PT::Logger::log1 << "Db: executing query: " << query_str << PT::Logger::logend << PT::Logger::logsave;
|
||||
}
|
||||
|
||||
query_results.push_back(QueryResult());
|
||||
QueryResult & last_res = query_results.back();
|
||||
psql_result->result = PQexec(pg_conn, query_str);
|
||||
|
||||
last_res.result = PQexec(pg_conn, query_str);
|
||||
|
||||
if( !last_res.result )
|
||||
if( !psql_result->result )
|
||||
{
|
||||
if( PQstatus(pg_conn) != CONNECTION_OK )
|
||||
{
|
||||
assert_connection();
|
||||
last_res.result = PQexec(pg_conn, query_str);
|
||||
psql_result->result = PQexec(pg_conn, query_str);
|
||||
}
|
||||
}
|
||||
|
||||
if( last_res.result )
|
||||
if( psql_result->result )
|
||||
{
|
||||
last_res.status = PQresultStatus(last_res.result);
|
||||
last_res.result_rows = static_cast<size_t>(PQntuples(last_res.result));
|
||||
psql_result->status = PQresultStatus(psql_result->result);
|
||||
psql_result->result_rows = static_cast<size_t>(PQntuples(psql_result->result));
|
||||
}
|
||||
|
||||
if( !last_res.result || last_res.status == PGRES_FATAL_ERROR )
|
||||
if( !psql_result->result || psql_result->status == PGRES_FATAL_ERROR )
|
||||
{
|
||||
psql_result->was_error = true;
|
||||
const char * err_msg = PQerrorMessage(pg_conn);
|
||||
|
||||
if( err_msg )
|
||||
{
|
||||
PT::UTF8ToWide(err_msg, psql_result->error_msg);
|
||||
}
|
||||
|
||||
if( logger )
|
||||
{
|
||||
(*logger) << PT::Logger::log1 << "Db: Problem with this query: \"" << query_str << '\"' << PT::Logger::logend << PT::Logger::logsave;
|
||||
(*logger) << PT::Logger::log1 << "Db: " << PQerrorMessage(pg_conn) << PT::Logger::logend << PT::Logger::logsave;
|
||||
|
||||
if( err_msg )
|
||||
(*logger) << PT::Logger::log1 << "Db: " << err_msg << PT::Logger::logend << PT::Logger::logsave;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (!query_results.empty() && query_results.back().result != nullptr);
|
||||
return (psql_result && psql_result->result != nullptr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool PostgreSQLConnector::query(const char * query_str, QueryResult & query_result)
|
||||
{
|
||||
PostgreSQLQueryResult * psql_result = dynamic_cast<PostgreSQLQueryResult*>(&query_result);
|
||||
return do_query(query_str, psql_result);
|
||||
}
|
||||
|
||||
|
||||
const char * PostgreSQLConnector::query_last_sequence(const wchar_t * sequence_table_name)
|
||||
{
|
||||
allocate_default_expression_if_needed();
|
||||
|
||||
if( db_expression )
|
||||
{
|
||||
PostgreSQLQueryResult psql_result;
|
||||
|
||||
stream.clear();
|
||||
stream << "select currval(E'";
|
||||
db_expression->esc(sequence_table_name, stream);
|
||||
stream << "');";
|
||||
|
||||
if( query_select(stream) )
|
||||
if( query_select(stream, psql_result) )
|
||||
{
|
||||
if( last_select_size() == 1 )
|
||||
if( psql_result.result_rows == 1 )
|
||||
{
|
||||
return get_value_from_result(0, 0);
|
||||
return psql_result.get_value_from_result(0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( pg_conn && logger )
|
||||
if( logger )
|
||||
{
|
||||
(*logger) << PT::Logger::log1 << "Db: error (currval) for table: " << sequence_table_name << ", "
|
||||
<< PQerrorMessage(pg_conn) << PT::Logger::logend << PT::Logger::logsave;
|
||||
(*logger) << PT::Logger::log1 << "Db: expected only one row in sequence result, has: " << psql_result.result_rows
|
||||
<< PT::Logger::logend << PT::Logger::logsave;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( pg_conn && logger )
|
||||
{
|
||||
(*logger) << PT::Logger::log1 << "Db: error (currval) for table: " << sequence_table_name << ", "
|
||||
<< PQerrorMessage(pg_conn) << PT::Logger::logend << PT::Logger::logsave;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
@ -297,323 +190,108 @@ const char * PostgreSQLConnector::query_last_sequence(const wchar_t * sequence_t
|
|||
|
||||
|
||||
|
||||
bool PostgreSQLConnector::query(const PT::TextStream & stream)
|
||||
bool PostgreSQLConnector::query(const PT::TextStream & stream, QueryResult & query_result)
|
||||
{
|
||||
stream.to_string(query_str);
|
||||
return query(query_str.c_str());
|
||||
return query(query_str.c_str(), query_result);
|
||||
}
|
||||
|
||||
|
||||
bool PostgreSQLConnector::query(const std::string & query_str)
|
||||
bool PostgreSQLConnector::query(const std::string & query_str, QueryResult & query_result)
|
||||
{
|
||||
return query(query_str.c_str());
|
||||
return query(query_str.c_str(), query_result);
|
||||
}
|
||||
|
||||
|
||||
bool PostgreSQLConnector::query_select(const char * query_str)
|
||||
bool PostgreSQLConnector::query_select(const char * query_str, QueryResult & query_result)
|
||||
{
|
||||
bool result = (query(query_str) && last_query_status() == PGRES_TUPLES_OK);
|
||||
PostgreSQLQueryResult * psql_result = dynamic_cast<PostgreSQLQueryResult*>(&query_result);
|
||||
bool result = false;
|
||||
|
||||
if( !result )
|
||||
if( psql_result )
|
||||
{
|
||||
set_was_error_in_last_query(true);
|
||||
set_last_query_error_msg();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool PostgreSQLConnector::query_update(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();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool PostgreSQLConnector::query_insert(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();
|
||||
}
|
||||
|
||||
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();
|
||||
result = (do_query(query_str, psql_result) && psql_result->status == PGRES_TUPLES_OK);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool PostgreSQLConnector::query_select(const PT::TextStream & stream)
|
||||
bool PostgreSQLConnector::query_update(const char * query_str, QueryResult & query_result)
|
||||
{
|
||||
PostgreSQLQueryResult * psql_result = dynamic_cast<PostgreSQLQueryResult*>(&query_result);
|
||||
bool result = false;
|
||||
|
||||
if( psql_result )
|
||||
{
|
||||
result = (do_query(query_str, psql_result) && psql_result->status == PGRES_COMMAND_OK);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool PostgreSQLConnector::query_insert(const char * query_str, QueryResult & query_result)
|
||||
{
|
||||
PostgreSQLQueryResult * psql_result = dynamic_cast<PostgreSQLQueryResult*>(&query_result);
|
||||
bool result = false;
|
||||
|
||||
if( psql_result )
|
||||
{
|
||||
result = (do_query(query_str, psql_result) && psql_result->status == PGRES_COMMAND_OK);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool PostgreSQLConnector::query_remove(const char * query_str, QueryResult & query_result)
|
||||
{
|
||||
PostgreSQLQueryResult * psql_result = dynamic_cast<PostgreSQLQueryResult*>(&query_result);
|
||||
bool result = false;
|
||||
|
||||
if( psql_result )
|
||||
{
|
||||
result = (do_query(query_str, psql_result) && psql_result->status == PGRES_COMMAND_OK);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool PostgreSQLConnector::query_select(const PT::TextStream & stream, QueryResult & query_result)
|
||||
{
|
||||
stream.to_string(query_str);
|
||||
return query_select(query_str.c_str());
|
||||
return query_select(query_str.c_str(), query_result);
|
||||
}
|
||||
|
||||
bool PostgreSQLConnector::query_update(const PT::TextStream & stream)
|
||||
bool PostgreSQLConnector::query_update(const PT::TextStream & stream, QueryResult & query_result)
|
||||
{
|
||||
stream.to_string(query_str);
|
||||
return query_update(query_str.c_str());
|
||||
return query_update(query_str.c_str(), query_result);
|
||||
}
|
||||
|
||||
bool PostgreSQLConnector::query_insert(const PT::TextStream & stream)
|
||||
bool PostgreSQLConnector::query_insert(const PT::TextStream & stream, QueryResult & query_result)
|
||||
{
|
||||
stream.to_string(query_str);
|
||||
return query_insert(query_str.c_str());
|
||||
return query_insert(query_str.c_str(), query_result);
|
||||
}
|
||||
|
||||
bool PostgreSQLConnector::query_remove(const PT::TextStream & stream)
|
||||
bool PostgreSQLConnector::query_remove(const PT::TextStream & stream, QueryResult & query_result)
|
||||
{
|
||||
stream.to_string(query_str);
|
||||
return query_remove(query_str.c_str());
|
||||
return query_remove(query_str.c_str(), query_result);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//int PostgreSQLConnector::Rows(PGresult * r)
|
||||
//{
|
||||
// // PQntuples - Returns the number of rows (tuples) in the query result. Because it returns
|
||||
// // an integer result, large result sets might overflow the return value on 32-bit operating systems.
|
||||
// return PQntuples(r);
|
||||
//}
|
||||
|
||||
|
||||
//int PostgreSQLConnector::Cols(PGresult * r)
|
||||
//{
|
||||
// // PQnfields - Returns the number of columns (fields) in each row of the query result.
|
||||
// return PQnfields(r);
|
||||
//}
|
||||
|
||||
//long PostgreSQLConnector::AffectedRows(PGresult * r)
|
||||
//{
|
||||
// // PQcmdTuples - This function returns a string containing the number of rows affected by the SQL
|
||||
// // statement that generated the PGresult. This function can only be used following the execution
|
||||
// // of an INSERT, UPDATE, DELETE, MOVE, FETCH, or COPY statement, or [...]
|
||||
// char * rows_str = PQcmdTuples(r); // can be an empty string
|
||||
// long rows = 0;
|
||||
//
|
||||
// if( rows_str )
|
||||
// {
|
||||
// rows = strtol(rows_str, 0, 10);
|
||||
// // strtol - If an overflow or underflow occurs, errno is set to ERANGE
|
||||
// // and the function return value is clamped according to the following table:
|
||||
// // Function underflow overflow
|
||||
// // strtol() LONG_MIN LONG_MAX
|
||||
//
|
||||
// if( rows < 0 )
|
||||
// rows = 0;
|
||||
// }
|
||||
//
|
||||
//return rows;
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
void PostgreSQLConnector::set_current_row_at_beginning()
|
||||
{
|
||||
if( !query_results.empty() )
|
||||
{
|
||||
query_results.back().cur_row = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PostgreSQLConnector::advance_current_row()
|
||||
{
|
||||
if( !query_results.empty() )
|
||||
{
|
||||
query_results.back().cur_row += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int PostgreSQLConnector::get_column_index(const char * column_name)
|
||||
{
|
||||
int col_index = -1;
|
||||
|
||||
if( !query_results.empty() )
|
||||
{
|
||||
QueryResult & res = query_results.back();
|
||||
|
||||
if( res.result )
|
||||
{
|
||||
col_index = PQfnumber(res.result, column_name);
|
||||
// returns -1 if there is no such a column
|
||||
}
|
||||
}
|
||||
|
||||
return col_index;
|
||||
}
|
||||
|
||||
|
||||
int PostgreSQLConnector::get_column_index(const wchar_t * column_name)
|
||||
{
|
||||
PT::WideToUTF8(column_name, temp_column_name);
|
||||
return get_column_index(temp_column_name.c_str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
//const char * PostgreSQLConnector::get_field_string_value(const wchar_t * field_name)
|
||||
const char * PostgreSQLConnector::get_field_string_value(const char * column_name)
|
||||
{
|
||||
const char * value_str = nullptr;
|
||||
|
||||
if( !query_results.empty() )
|
||||
{
|
||||
QueryResult & res = query_results.back();
|
||||
|
||||
if( res.result )
|
||||
{
|
||||
int col_index = PQfnumber(res.result, column_name);
|
||||
|
||||
if( col_index != -1 )
|
||||
{
|
||||
if( res.cur_row < res.result_rows )
|
||||
{
|
||||
value_str = PQgetvalue(res.result, res.cur_row, col_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return value_str;
|
||||
}
|
||||
|
||||
|
||||
const char * PostgreSQLConnector::get_field_string_value(const wchar_t * column_name)
|
||||
{
|
||||
PT::WideToUTF8(column_name, temp_column_name);
|
||||
return get_field_string_value(temp_column_name.c_str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char * PostgreSQLConnector::get_value_from_result(int row, int col)
|
||||
{
|
||||
const char * value_str = nullptr;
|
||||
|
||||
if( !query_results.empty() )
|
||||
{
|
||||
QueryResult & res = query_results.back();
|
||||
|
||||
if( res.result )
|
||||
{
|
||||
value_str = PQgetvalue(res.result, row, col);
|
||||
// can return a null pointer if there is no such an item in the last result
|
||||
}
|
||||
}
|
||||
|
||||
return value_str;
|
||||
}
|
||||
|
||||
|
||||
int PostgreSQLConnector::get_value_length(int row, int col)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
if( !query_results.empty() )
|
||||
{
|
||||
QueryResult & res = query_results.back();
|
||||
|
||||
if( res.result )
|
||||
{
|
||||
len = PQgetlength(res.result, row, col);
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//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);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
//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;
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool PostgreSQLConnector::is_null(int row, int col)
|
||||
{
|
||||
bool is_null = false;
|
||||
|
||||
if( !query_results.empty() )
|
||||
{
|
||||
QueryResult & res = query_results.back();
|
||||
|
||||
if( res.result )
|
||||
{
|
||||
is_null = (PQgetisnull(res.result, row, col) == 1);
|
||||
}
|
||||
}
|
||||
|
||||
return is_null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -35,9 +35,10 @@
|
|||
#ifndef headerfile_morm_postgresqlconnector
|
||||
#define headerfile_morm_postgresqlconnector
|
||||
|
||||
#include "dbconnector.h"
|
||||
#include <libpq-fe.h>
|
||||
#include <string>
|
||||
#include "dbconnector.h"
|
||||
#include "postgresqlqueryresult.h"
|
||||
|
||||
|
||||
|
||||
|
@ -49,85 +50,42 @@ class PostgreSQLConnector : public DbConnector
|
|||
public:
|
||||
|
||||
PostgreSQLConnector();
|
||||
PostgreSQLConnector(const PostgreSQLConnector &) = delete;
|
||||
|
||||
virtual ~PostgreSQLConnector();
|
||||
|
||||
void clear_all_query_results();
|
||||
void clear_last_query_result();
|
||||
virtual void set_log_queries(bool log_queries);
|
||||
|
||||
// give me a better names
|
||||
virtual size_t last_select_size();
|
||||
virtual ExecStatusType last_query_status();
|
||||
virtual bool is_last_result(ExecStatusType t); // was: is_last_result
|
||||
bool query(const PT::TextStream & stream, QueryResult & query_result);
|
||||
bool query(const char * query_str, QueryResult & query_result);
|
||||
bool query(const std::string & query_str, QueryResult & query_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);
|
||||
bool query_select(const char * query_str, QueryResult & query_result);
|
||||
bool query_update(const char * query_str, QueryResult & query_result);
|
||||
bool query_insert(const char * query_str, QueryResult & query_result);
|
||||
bool query_remove(const char * query_str, QueryResult & query_result);
|
||||
|
||||
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);
|
||||
|
||||
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_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);
|
||||
bool query_select(const PT::TextStream & stream, QueryResult & query_result);
|
||||
bool query_update(const PT::TextStream & stream, QueryResult & query_result);
|
||||
bool query_insert(const PT::TextStream & stream, QueryResult & query_result);
|
||||
bool query_remove(const PT::TextStream & stream, QueryResult & query_result);
|
||||
|
||||
|
||||
// give me a better name
|
||||
virtual void set_current_row_at_beginning();
|
||||
virtual void advance_current_row();
|
||||
virtual void set_conn_param(const std::wstring & database, const std::wstring & user, const std::wstring & pass);
|
||||
virtual void connect();
|
||||
virtual void wait_for_connection();
|
||||
virtual void close();
|
||||
//virtual bool assert_connection(bool put_log = true, bool throw_if_no_connection = true);
|
||||
virtual bool assert_connection(bool put_log = true);
|
||||
virtual void set_db_parameters();
|
||||
virtual void log_connection_socket();
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* get column index from the last query (select)
|
||||
* returns -1 if there is no such a column
|
||||
*
|
||||
*/
|
||||
int get_column_index(const char * column_name);
|
||||
int get_column_index(const wchar_t * column_name);
|
||||
|
||||
bool is_null(int row, int col);
|
||||
|
||||
/*
|
||||
* return an item from the last query
|
||||
* can return a null pointer if there is no such an item in the last result
|
||||
*
|
||||
*/
|
||||
const char * get_value_from_result(int row, int col);
|
||||
int get_value_length(int row, int col);
|
||||
|
||||
|
||||
|
||||
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);
|
||||
bool assert_connection(bool put_log = true);
|
||||
void set_db_parameters();
|
||||
void log_connection_socket();
|
||||
|
||||
//PGconn * GetPgConn();
|
||||
|
||||
|
||||
|
||||
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;
|
||||
|
@ -137,35 +95,13 @@ protected:
|
|||
std::wstring db_user;
|
||||
std::wstring db_pass;
|
||||
|
||||
struct QueryResult
|
||||
{
|
||||
PGresult * result; // can be null
|
||||
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()
|
||||
{
|
||||
result = nullptr;
|
||||
result_rows = 0;
|
||||
status = PGRES_EMPTY_QUERY;
|
||||
cur_row = 0;
|
||||
was_error = false;
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<QueryResult> query_results;
|
||||
virtual bool do_query(const char * query_str, PostgreSQLQueryResult * psql_result);
|
||||
virtual void allocate_default_expression();
|
||||
virtual void overwrite(PT::TextStream & stream);
|
||||
virtual const char * query_last_sequence(const wchar_t * sequence_table_name);
|
||||
virtual QueryResult * create_query_result();
|
||||
|
||||
|
||||
void allocate_default_expression();
|
||||
|
||||
void overwrite(PT::TextStream & stream);
|
||||
virtual const char * get_field_string_value(const char * column_name);
|
||||
virtual const char * get_field_string_value(const wchar_t * field_name);
|
||||
virtual void set_last_query_error_msg();
|
||||
const char * query_last_sequence(const wchar_t * sequence_table_name);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,234 @@
|
|||
/*
|
||||
* This file is a part of morm
|
||||
* and is distributed under the 2-Clause BSD licence.
|
||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 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 "postgresqlqueryresult.h"
|
||||
|
||||
|
||||
|
||||
namespace morm
|
||||
{
|
||||
|
||||
|
||||
PostgreSQLQueryResult::PostgreSQLQueryResult()
|
||||
{
|
||||
result = nullptr;
|
||||
status = PGRES_EMPTY_QUERY;
|
||||
}
|
||||
|
||||
|
||||
void PostgreSQLQueryResult::clear()
|
||||
{
|
||||
if( result )
|
||||
{
|
||||
PQclear(result);
|
||||
}
|
||||
|
||||
result = nullptr;
|
||||
status = PGRES_EMPTY_QUERY;
|
||||
|
||||
QueryResult::clear();
|
||||
}
|
||||
|
||||
|
||||
bool PostgreSQLQueryResult::has_db_result()
|
||||
{
|
||||
return result != nullptr;
|
||||
}
|
||||
|
||||
|
||||
const char * PostgreSQLQueryResult::get_field_string_value(const char * column_name)
|
||||
{
|
||||
const char * value_str = nullptr;
|
||||
|
||||
if( result )
|
||||
{
|
||||
int col_index = PQfnumber(result, column_name);
|
||||
|
||||
if( col_index != -1 )
|
||||
{
|
||||
if( cur_row < result_rows )
|
||||
{
|
||||
value_str = PQgetvalue(result, cur_row, col_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return value_str;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int PostgreSQLQueryResult::get_column_index(const char * column_name)
|
||||
{
|
||||
int col_index = -1;
|
||||
|
||||
if( result )
|
||||
{
|
||||
col_index = PQfnumber(result, column_name);
|
||||
// returns -1 if there is no such a column
|
||||
}
|
||||
|
||||
return col_index;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char * PostgreSQLQueryResult::get_value_from_result(int row, int col)
|
||||
{
|
||||
const char * value_str = nullptr;
|
||||
|
||||
if( result )
|
||||
{
|
||||
value_str = PQgetvalue(result, row, col);
|
||||
// can return a null pointer if there is no such an item in the last result
|
||||
}
|
||||
|
||||
return value_str;
|
||||
}
|
||||
|
||||
|
||||
int PostgreSQLQueryResult::get_value_length(int row, int col)
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
if( result )
|
||||
{
|
||||
len = PQgetlength(result, row, col);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
bool PostgreSQLQueryResult::is_null(int row, int col)
|
||||
{
|
||||
bool is_null = false;
|
||||
|
||||
if( result )
|
||||
{
|
||||
is_null = (PQgetisnull(result, row, col) == 1);
|
||||
}
|
||||
|
||||
return is_null;
|
||||
}
|
||||
|
||||
|
||||
//int PostgreSQLQueryResult::Rows(PGresult * r)
|
||||
//{
|
||||
// // PQntuples - Returns the number of rows (tuples) in the query result. Because it returns
|
||||
// // an integer result, large result sets might overflow the return value on 32-bit operating systems.
|
||||
// return PQntuples(r);
|
||||
//}
|
||||
|
||||
|
||||
//int PostgreSQLQueryResult::Cols(PGresult * r)
|
||||
//{
|
||||
// // PQnfields - Returns the number of columns (fields) in each row of the query result.
|
||||
// return PQnfields(r);
|
||||
//}
|
||||
|
||||
//long PostgreSQLQueryResult::AffectedRows(PGresult * r)
|
||||
//{
|
||||
// // PQcmdTuples - This function returns a string containing the number of rows affected by the SQL
|
||||
// // statement that generated the PGresult. This function can only be used following the execution
|
||||
// // of an INSERT, UPDATE, DELETE, MOVE, FETCH, or COPY statement, or [...]
|
||||
// char * rows_str = PQcmdTuples(r); // can be an empty string
|
||||
// long rows = 0;
|
||||
//
|
||||
// if( rows_str )
|
||||
// {
|
||||
// rows = strtol(rows_str, 0, 10);
|
||||
// // strtol - If an overflow or underflow occurs, errno is set to ERANGE
|
||||
// // and the function return value is clamped according to the following table:
|
||||
// // Function underflow overflow
|
||||
// // strtol() LONG_MIN LONG_MAX
|
||||
//
|
||||
// if( rows < 0 )
|
||||
// rows = 0;
|
||||
// }
|
||||
//
|
||||
//return rows;
|
||||
//}
|
||||
|
||||
|
||||
//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);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
//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;
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* This file is a part of morm
|
||||
* and is distributed under the 2-Clause BSD licence.
|
||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef headerfile_morm_postgresqlqueryresult
|
||||
#define headerfile_morm_postgresqlqueryresult
|
||||
|
||||
#include "queryresult.h"
|
||||
#include <libpq-fe.h>
|
||||
|
||||
|
||||
|
||||
namespace morm
|
||||
{
|
||||
|
||||
|
||||
struct PostgreSQLQueryResult : public QueryResult
|
||||
{
|
||||
PGresult * result; // can be null
|
||||
ExecStatusType status;
|
||||
|
||||
|
||||
PostgreSQLQueryResult();
|
||||
|
||||
|
||||
virtual void clear();
|
||||
|
||||
virtual bool has_db_result();
|
||||
|
||||
const char * get_field_string_value(const char * column_name);
|
||||
int get_column_index(const char * column_name);
|
||||
|
||||
const char * get_value_from_result(int row, int col);
|
||||
int get_value_length(int row, int col);
|
||||
|
||||
bool is_null(int row, int col);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* This file is a part of morm
|
||||
* and is distributed under the 2-Clause BSD licence.
|
||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 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 "queryresult.h"
|
||||
#include "utf8/utf8.h"
|
||||
|
||||
|
||||
|
||||
namespace morm
|
||||
{
|
||||
|
||||
QueryResult::QueryResult()
|
||||
{
|
||||
clear();
|
||||
references_count = 0;
|
||||
}
|
||||
|
||||
|
||||
QueryResult::~QueryResult()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
void QueryResult::clear()
|
||||
{
|
||||
result_rows = 0;
|
||||
cur_row = 0;
|
||||
was_error = false;
|
||||
error_msg.clear();
|
||||
|
||||
temp_column_name.clear();
|
||||
}
|
||||
|
||||
|
||||
bool QueryResult::has_db_result()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const char * QueryResult::get_field_string_value(const char * column_name)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
const char * QueryResult::get_field_string_value(const wchar_t * column_name)
|
||||
{
|
||||
PT::WideToUTF8(column_name, temp_column_name);
|
||||
return get_field_string_value(temp_column_name.c_str());
|
||||
}
|
||||
|
||||
|
||||
int QueryResult::get_column_index(const char * column_name)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int QueryResult::get_column_index(const wchar_t * column_name)
|
||||
{
|
||||
PT::WideToUTF8(column_name, temp_column_name);
|
||||
return get_column_index(temp_column_name.c_str());
|
||||
}
|
||||
|
||||
|
||||
const char * QueryResult::get_value_from_result(int row, int col)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int QueryResult::get_value_length(int row, int col)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool QueryResult::is_null(int row, int col)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* This file is a part of morm
|
||||
* and is distributed under the 2-Clause BSD licence.
|
||||
* Author: Tomasz Sowa <t.sowa@ttmath.org>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef headerfile_morm_queryresult
|
||||
#define headerfile_morm_queryresult
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace morm
|
||||
{
|
||||
|
||||
struct QueryResult
|
||||
{
|
||||
size_t result_rows; // how many rows in the result query
|
||||
size_t cur_row; // used for reading
|
||||
bool was_error;
|
||||
std::wstring error_msg;
|
||||
|
||||
std::string temp_column_name;
|
||||
size_t references_count;
|
||||
|
||||
QueryResult();
|
||||
virtual ~QueryResult();
|
||||
|
||||
virtual void clear();
|
||||
virtual bool has_db_result();
|
||||
|
||||
virtual const char * get_field_string_value(const char * column_name);
|
||||
virtual const char * get_field_string_value(const wchar_t * field_name);
|
||||
|
||||
/*
|
||||
* returns -1 if there is no such a column
|
||||
*
|
||||
*/
|
||||
virtual int get_column_index(const char * column_name);
|
||||
virtual int get_column_index(const wchar_t * column_name);
|
||||
|
||||
// may it should be changed to size_t?
|
||||
virtual const char * get_value_from_result(int row, int col);
|
||||
virtual int get_value_length(int row, int col);
|
||||
virtual bool is_null(int row, int col);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue