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/membuffer/membuffer.h
|
||||||
baseexpression.o: ../../pikotools/textstream/types.h morm_types.h model.h
|
baseexpression.o: ../../pikotools/textstream/types.h morm_types.h model.h
|
||||||
baseexpression.o: modelconnector.h clearer.h dbconnector.h
|
baseexpression.o: modelconnector.h clearer.h dbconnector.h
|
||||||
baseexpression.o: ../../pikotools/logger/logger.h flatconnector.h
|
baseexpression.o: ../../pikotools/logger/logger.h queryresult.h
|
||||||
baseexpression.o: dbexpression.h flatexpression.h ../../pikotools/utf8/utf8.h
|
baseexpression.o: flatconnector.h dbexpression.h flatexpression.h
|
||||||
|
baseexpression.o: ../../pikotools/utf8/utf8.h
|
||||||
clearer.o: clearer.h ../../pikotools/date/date.h
|
clearer.o: clearer.h ../../pikotools/date/date.h
|
||||||
clearer.o: ../../pikotools/convert/convert.h
|
clearer.o: ../../pikotools/convert/convert.h
|
||||||
clearer.o: ../../pikotools/convert/inttostr.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/space/space.h ../../pikotools/textstream/types.h
|
||||||
clearer.o: ../../pikotools/membuffer/membuffer.h
|
clearer.o: ../../pikotools/membuffer/membuffer.h
|
||||||
clearer.o: ../../pikotools/textstream/types.h modelconnector.h dbconnector.h
|
clearer.o: ../../pikotools/textstream/types.h modelconnector.h dbconnector.h
|
||||||
clearer.o: ../../pikotools/logger/logger.h flatconnector.h dbexpression.h
|
clearer.o: ../../pikotools/logger/logger.h queryresult.h flatconnector.h
|
||||||
clearer.o: baseexpression.h morm_types.h flatexpression.h
|
clearer.o: dbexpression.h baseexpression.h morm_types.h flatexpression.h
|
||||||
dbconnector.o: dbconnector.h ../../pikotools/textstream/textstream.h
|
dbconnector.o: dbconnector.h ../../pikotools/textstream/textstream.h
|
||||||
dbconnector.o: ../../pikotools/space/space.h
|
dbconnector.o: ../../pikotools/space/space.h
|
||||||
dbconnector.o: ../../pikotools/textstream/types.h ../../pikotools/date/date.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/convert/text.h ../../pikotools/convert/misc.h
|
||||||
dbconnector.o: ../../pikotools/membuffer/membuffer.h
|
dbconnector.o: ../../pikotools/membuffer/membuffer.h
|
||||||
dbconnector.o: ../../pikotools/textstream/types.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: baseexpression.h morm_types.h model.h modelconnector.h
|
||||||
dbconnector.o: clearer.h flatconnector.h flatexpression.h
|
dbconnector.o: clearer.h flatconnector.h flatexpression.h
|
||||||
dbconnector.o: ../../pikotools/utf8/utf8.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: ../../pikotools/textstream/types.h flatexpression.h
|
||||||
flatconnector.o: baseexpression.h morm_types.h model.h modelconnector.h
|
flatconnector.o: baseexpression.h morm_types.h model.h modelconnector.h
|
||||||
flatconnector.o: clearer.h dbconnector.h ../../pikotools/logger/logger.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: flatexpression.h baseexpression.h
|
||||||
flatexpression.o: ../../pikotools/textstream/textstream.h
|
flatexpression.o: ../../pikotools/textstream/textstream.h
|
||||||
flatexpression.o: ../../pikotools/space/space.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/strtoint.h ../../pikotools/convert/text.h
|
||||||
model.o: ../../pikotools/convert/misc.h ../../pikotools/membuffer/membuffer.h
|
model.o: ../../pikotools/convert/misc.h ../../pikotools/membuffer/membuffer.h
|
||||||
model.o: ../../pikotools/textstream/types.h modelconnector.h clearer.h
|
model.o: ../../pikotools/textstream/types.h modelconnector.h clearer.h
|
||||||
model.o: dbconnector.h ../../pikotools/logger/logger.h flatconnector.h
|
model.o: dbconnector.h ../../pikotools/logger/logger.h queryresult.h
|
||||||
model.o: dbexpression.h baseexpression.h morm_types.h flatexpression.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: modelconnector.h clearer.h ../../pikotools/date/date.h
|
||||||
modelconnector.o: ../../pikotools/convert/convert.h
|
modelconnector.o: ../../pikotools/convert/convert.h
|
||||||
modelconnector.o: ../../pikotools/convert/inttostr.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/textstream/types.h
|
||||||
modelconnector.o: ../../pikotools/membuffer/membuffer.h
|
modelconnector.o: ../../pikotools/membuffer/membuffer.h
|
||||||
modelconnector.o: ../../pikotools/textstream/types.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: postgresqlconnector.h dbconnector.h
|
||||||
postgresqlconnector.o: ../../pikotools/textstream/textstream.h
|
postgresqlconnector.o: ../../pikotools/textstream/textstream.h
|
||||||
postgresqlconnector.o: ../../pikotools/space/space.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/convert/misc.h
|
||||||
postgresqlconnector.o: ../../pikotools/membuffer/membuffer.h
|
postgresqlconnector.o: ../../pikotools/membuffer/membuffer.h
|
||||||
postgresqlconnector.o: ../../pikotools/textstream/types.h
|
postgresqlconnector.o: ../../pikotools/textstream/types.h
|
||||||
postgresqlconnector.o: ../../pikotools/logger/logger.h
|
postgresqlconnector.o: ../../pikotools/logger/logger.h queryresult.h
|
||||||
postgresqlconnector.o: ../../pikotools/utf8/utf8.h postgresqlexpression.h
|
postgresqlconnector.o: postgresqlqueryresult.h ../../pikotools/utf8/utf8.h
|
||||||
postgresqlconnector.o: dbexpression.h baseexpression.h morm_types.h
|
postgresqlconnector.o: postgresqlexpression.h dbexpression.h baseexpression.h
|
||||||
postgresqlconnector.o: ../../pikotools/convert/strtoint.h
|
postgresqlconnector.o: morm_types.h ../../pikotools/convert/strtoint.h
|
||||||
postgresqlexpression.o: postgresqlexpression.h dbexpression.h
|
postgresqlexpression.o: postgresqlexpression.h dbexpression.h
|
||||||
postgresqlexpression.o: baseexpression.h
|
postgresqlexpression.o: baseexpression.h
|
||||||
postgresqlexpression.o: ../../pikotools/textstream/textstream.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/convert/misc.h
|
||||||
postgresqlexpression.o: ../../pikotools/membuffer/membuffer.h
|
postgresqlexpression.o: ../../pikotools/membuffer/membuffer.h
|
||||||
postgresqlexpression.o: ../../pikotools/textstream/types.h morm_types.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 <cstdlib>
|
||||||
|
#include <memory>
|
||||||
#include "dbconnector.h"
|
#include "dbconnector.h"
|
||||||
#include "dbexpression.h"
|
#include "dbexpression.h"
|
||||||
#include "model.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)
|
bool DbConnector::query(const char * query_str, QueryResult & query_result)
|
||||||
//{
|
|
||||||
// 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)
|
|
||||||
{
|
{
|
||||||
// do query
|
// do query
|
||||||
return false;
|
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;
|
return query(query_str, query_result);
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
|
||||||
|
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()
|
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)
|
bool DbConnector::insert(PT::TextStream & stream, Model & model)
|
||||||
{
|
{
|
||||||
|
std::unique_ptr<QueryResult> query_result_ptr(create_query_result());
|
||||||
|
|
||||||
generate_insert_query(stream, model);
|
generate_insert_query(stream, model);
|
||||||
return query_insert(stream);
|
return query_insert(stream, *query_result_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool DbConnector::update(PT::TextStream & stream, Model & model)
|
bool DbConnector::update(PT::TextStream & stream, Model & model)
|
||||||
{
|
{
|
||||||
|
std::unique_ptr<QueryResult> query_result_ptr(create_query_result());
|
||||||
|
|
||||||
generate_update_query(stream, model);
|
generate_update_query(stream, model);
|
||||||
return query_update(stream);
|
return query_update(stream, *query_result_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool DbConnector::remove(PT::TextStream & stream, Model & model)
|
bool DbConnector::remove(PT::TextStream & stream, Model & model)
|
||||||
{
|
{
|
||||||
|
std::unique_ptr<QueryResult> query_result_ptr(create_query_result());
|
||||||
|
|
||||||
generate_remove_query(stream, model);
|
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 "textstream/textstream.h"
|
||||||
#include "logger/logger.h"
|
#include "logger/logger.h"
|
||||||
|
#include "queryresult.h"
|
||||||
|
|
||||||
|
|
||||||
namespace morm
|
namespace morm
|
||||||
|
@ -58,7 +59,7 @@ public:
|
||||||
|
|
||||||
DbExpression * get_expression();
|
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_select_columns(PT::TextStream & stream, Model & model, const std::wstring & column_prefix);
|
||||||
virtual void generate_insert_query(PT::TextStream & stream, Model & model);
|
virtual void generate_insert_query(PT::TextStream & stream, Model & model);
|
||||||
|
@ -71,27 +72,21 @@ public:
|
||||||
|
|
||||||
//void ModelConnector::get_values_from_db(Model & model)
|
//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 PT::TextStream & stream, QueryResult & query_result);
|
||||||
//virtual bool query(const std::wstring & query);
|
virtual bool query(const std::string & query_str, QueryResult & query_result);
|
||||||
virtual bool query(const std::string & query_str);
|
virtual bool query(const char * query_str, QueryResult & query_result);
|
||||||
//virtual bool query(const wchar_t * query);
|
|
||||||
virtual bool query(const char * query_str);
|
|
||||||
|
|
||||||
virtual bool query_select(const PT::TextStream & stream);
|
virtual bool query_select(const char * query_str, QueryResult & query_result);
|
||||||
virtual bool query_update(const PT::TextStream & stream);
|
virtual bool query_update(const char * query_str, QueryResult & query_result);
|
||||||
virtual bool query_insert(const PT::TextStream & stream);
|
virtual bool query_insert(const char * query_str, QueryResult & query_result);
|
||||||
virtual bool query_remove(const PT::TextStream & stream);
|
virtual bool query_remove(const char * query_str, QueryResult & query_result);
|
||||||
|
|
||||||
virtual size_t last_select_size();
|
virtual bool query_select(const PT::TextStream & stream, QueryResult & query_result);
|
||||||
virtual std::wstring get_last_query_error_msg();
|
virtual bool query_update(const PT::TextStream & stream, QueryResult & query_result);
|
||||||
virtual bool was_error_in_last_query();
|
virtual bool query_insert(const PT::TextStream & stream, QueryResult & query_result);
|
||||||
|
virtual 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 map_values_from_query(Model & model);
|
|
||||||
|
|
||||||
virtual void get_value(const char * value_str, char & field_value);
|
virtual void get_value(const char * value_str, char & field_value);
|
||||||
virtual void get_value(const char * value_str, unsigned char & field_value);
|
virtual void get_value(const char * value_str, unsigned char & field_value);
|
||||||
|
@ -112,18 +107,6 @@ public:
|
||||||
virtual void get_value(const char * value_str, PT::Date & field_value);
|
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>
|
template<typename FieldValue>
|
||||||
void get_last_sequence(const wchar_t * sequence_table_name, FieldValue & field_value)
|
void get_last_sequence(const wchar_t * sequence_table_name, FieldValue & field_value)
|
||||||
{
|
{
|
||||||
|
@ -140,7 +123,6 @@ protected:
|
||||||
|
|
||||||
DbExpression * db_expression;
|
DbExpression * db_expression;
|
||||||
bool expression_allocated;
|
bool expression_allocated;
|
||||||
std::wstring last_query_error_msg;
|
|
||||||
PT::Logger * logger;
|
PT::Logger * logger;
|
||||||
|
|
||||||
|
|
||||||
|
@ -148,9 +130,6 @@ protected:
|
||||||
virtual void allocate_default_expression_if_needed();
|
virtual void allocate_default_expression_if_needed();
|
||||||
virtual void deallocate_expression();
|
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);
|
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 "textstream/textstream.h"
|
||||||
#include "dbconnector.h"
|
#include "dbconnector.h"
|
||||||
#include "modelconnector.h"
|
#include "modelconnector.h"
|
||||||
|
#include "cursor.h"
|
||||||
|
|
||||||
|
|
||||||
namespace morm
|
namespace morm
|
||||||
|
@ -431,61 +432,42 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool get(ModelClass & result)
|
Cursor<ModelClass> get_cursor()
|
||||||
{
|
{
|
||||||
bool res = false;
|
Cursor<ModelClass> cursor;
|
||||||
result.set_connector(model_connector);
|
cursor.set_model_data(model_data);
|
||||||
result.clear();
|
|
||||||
|
|
||||||
if( model_connector && out_stream )
|
if( model_connector && out_stream )
|
||||||
{
|
{
|
||||||
|
cursor.set_model_connector(model_connector);
|
||||||
DbConnector * db_connector = model_connector->get_db_connector();
|
DbConnector * db_connector = model_connector->get_db_connector();
|
||||||
|
|
||||||
if( db_connector )
|
if( db_connector )
|
||||||
{
|
{
|
||||||
try
|
QueryResult * query_result = db_connector->create_query_result();
|
||||||
{
|
cursor.set_query_result(query_result);
|
||||||
result.model_data = model_data;
|
query_result->references_count = 1;
|
||||||
result.before_select();
|
|
||||||
res = db_connector->query_select(*out_stream);
|
|
||||||
|
|
||||||
if( res )
|
bool status = db_connector->query_select(*out_stream, *query_result);
|
||||||
{
|
cursor.set_select_status(status);
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return cursor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool get(ModelClass & result)
|
||||||
|
{
|
||||||
|
Cursor<ModelClass> cursor = get_cursor();
|
||||||
|
return cursor.get(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ModelClass get()
|
ModelClass get()
|
||||||
{
|
{
|
||||||
|
ModelClass model;
|
||||||
|
|
||||||
get(model);
|
get(model);
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
@ -493,84 +475,22 @@ public:
|
||||||
|
|
||||||
bool get_list(std::list<ModelClass> & result, bool clear_list = true)
|
bool get_list(std::list<ModelClass> & result, bool clear_list = true)
|
||||||
{
|
{
|
||||||
bool res = false;
|
Cursor<ModelClass> cursor = get_cursor();
|
||||||
|
return cursor.get_list(result, clear_list);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::list<ModelClass> get_list()
|
std::list<ModelClass> get_list()
|
||||||
{
|
{
|
||||||
std::list<ModelClass> result;
|
std::list<ModelClass> result;
|
||||||
|
|
||||||
get_list(result, false);
|
get_list(result, false);
|
||||||
return std::move(result);
|
return std::move(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -45,8 +45,22 @@ Model::Model()
|
||||||
doc_field_pointer = nullptr;
|
doc_field_pointer = nullptr;
|
||||||
save_mode = DO_INSERT_ON_SAVE;
|
save_mode = DO_INSERT_ON_SAVE;
|
||||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
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()
|
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)
|
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;
|
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_READING_VALUE_FROM_DB_RESULTSET;
|
||||||
|
this->query_result = query_result;
|
||||||
|
|
||||||
map_fields();
|
map_fields();
|
||||||
|
|
||||||
model_connector_mode = MORM_MODEL_CONNECTOR_MODE_NONE;
|
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 "modelconnector.h"
|
||||||
#include "dbexpression.h"
|
#include "dbexpression.h"
|
||||||
#include "flatexpression.h"
|
#include "flatexpression.h"
|
||||||
|
#include "queryresult.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,10 +93,6 @@ public:
|
||||||
virtual bool found();
|
virtual bool found();
|
||||||
|
|
||||||
|
|
||||||
virtual bool was_db_error();
|
|
||||||
virtual std::wstring get_db_error();
|
|
||||||
|
|
||||||
|
|
||||||
void set_connector(ModelConnector & connector);
|
void set_connector(ModelConnector & connector);
|
||||||
void set_connector(ModelConnector * connector);
|
void set_connector(ModelConnector * connector);
|
||||||
|
|
||||||
|
@ -155,8 +152,11 @@ protected:
|
||||||
ModelData * model_data;
|
ModelData * model_data;
|
||||||
const void * doc_field_pointer;
|
const void * doc_field_pointer;
|
||||||
int model_connector_mode;
|
int model_connector_mode;
|
||||||
|
QueryResult * query_result;
|
||||||
|
|
||||||
|
|
||||||
Model();
|
Model();
|
||||||
|
Model(const Model & m);
|
||||||
virtual ~Model();
|
virtual ~Model();
|
||||||
|
|
||||||
virtual void before_select();
|
virtual void before_select();
|
||||||
|
@ -176,8 +176,8 @@ protected:
|
||||||
|
|
||||||
virtual int get_connector_mode();
|
virtual int get_connector_mode();
|
||||||
|
|
||||||
// used by Finder
|
// used by Cursor
|
||||||
virtual void map_values_from_query();
|
virtual void map_values_from_query(QueryResult * query_result);
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
|
@ -684,7 +684,7 @@ protected:
|
||||||
if( db_connector )
|
if( db_connector )
|
||||||
{
|
{
|
||||||
if( !is_empty_field(db_field_name) )
|
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>
|
template<typename FieldValue>
|
||||||
void doc_field_generic(const wchar_t * db_field_name, const wchar_t * flat_field_name, FieldValue & field_value)
|
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);
|
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;
|
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:
|
public:
|
||||||
|
|
||||||
ModelConnector();
|
ModelConnector();
|
||||||
|
ModelConnector(const ModelConnector &) = delete;
|
||||||
virtual ~ModelConnector();
|
virtual ~ModelConnector();
|
||||||
|
|
||||||
virtual void set_logger(PT::Logger * logger);
|
virtual void set_logger(PT::Logger * logger);
|
||||||
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 void set_stream(PT::TextStream & stream);
|
||||||
virtual PT::TextStream * get_stream();
|
virtual PT::TextStream * get_stream();
|
||||||
|
|
|
@ -61,149 +61,12 @@ void PostgreSQLConnector::close()
|
||||||
{
|
{
|
||||||
if( pg_conn )
|
if( pg_conn )
|
||||||
{
|
{
|
||||||
clear_all_query_results();
|
|
||||||
PQfinish(pg_conn);
|
PQfinish(pg_conn);
|
||||||
pg_conn = nullptr;
|
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()
|
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 )
|
if( log_queries && logger )
|
||||||
{
|
{
|
||||||
(*logger) << PT::Logger::log1 << "Db: executing query: " << query_str << PT::Logger::logend << PT::Logger::logsave;
|
(*logger) << PT::Logger::log1 << "Db: executing query: " << query_str << PT::Logger::logend << PT::Logger::logsave;
|
||||||
}
|
}
|
||||||
|
|
||||||
query_results.push_back(QueryResult());
|
psql_result->result = PQexec(pg_conn, query_str);
|
||||||
QueryResult & last_res = query_results.back();
|
|
||||||
|
|
||||||
last_res.result = PQexec(pg_conn, query_str);
|
if( !psql_result->result )
|
||||||
|
|
||||||
if( !last_res.result )
|
|
||||||
{
|
{
|
||||||
if( PQstatus(pg_conn) != CONNECTION_OK )
|
if( PQstatus(pg_conn) != CONNECTION_OK )
|
||||||
{
|
{
|
||||||
assert_connection();
|
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);
|
psql_result->status = PQresultStatus(psql_result->result);
|
||||||
last_res.result_rows = static_cast<size_t>(PQntuples(last_res.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 )
|
if( logger )
|
||||||
{
|
{
|
||||||
(*logger) << PT::Logger::log1 << "Db: Problem with this query: \"" << query_str << '\"' << PT::Logger::logend << PT::Logger::logsave;
|
(*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)
|
const char * PostgreSQLConnector::query_last_sequence(const wchar_t * sequence_table_name)
|
||||||
{
|
{
|
||||||
allocate_default_expression_if_needed();
|
allocate_default_expression_if_needed();
|
||||||
|
|
||||||
if( db_expression )
|
if( db_expression )
|
||||||
{
|
{
|
||||||
|
PostgreSQLQueryResult psql_result;
|
||||||
|
|
||||||
stream.clear();
|
stream.clear();
|
||||||
stream << "select currval(E'";
|
stream << "select currval(E'";
|
||||||
db_expression->esc(sequence_table_name, stream);
|
db_expression->esc(sequence_table_name, stream);
|
||||||
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
|
else
|
||||||
{
|
{
|
||||||
if( pg_conn && logger )
|
if( logger )
|
||||||
{
|
{
|
||||||
(*logger) << PT::Logger::log1 << "Db: error (currval) for table: " << sequence_table_name << ", "
|
(*logger) << PT::Logger::log1 << "Db: expected only one row in sequence result, has: " << psql_result.result_rows
|
||||||
<< PQerrorMessage(pg_conn) << PT::Logger::logend << PT::Logger::logsave;
|
<< 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;
|
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);
|
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);
|
result = (do_query(query_str, psql_result) && psql_result->status == PGRES_TUPLES_OK);
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
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);
|
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);
|
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);
|
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);
|
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
|
#ifndef headerfile_morm_postgresqlconnector
|
||||||
#define headerfile_morm_postgresqlconnector
|
#define headerfile_morm_postgresqlconnector
|
||||||
|
|
||||||
#include "dbconnector.h"
|
|
||||||
#include <libpq-fe.h>
|
#include <libpq-fe.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include "dbconnector.h"
|
||||||
|
#include "postgresqlqueryresult.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -49,85 +50,42 @@ class PostgreSQLConnector : public DbConnector
|
||||||
public:
|
public:
|
||||||
|
|
||||||
PostgreSQLConnector();
|
PostgreSQLConnector();
|
||||||
|
PostgreSQLConnector(const PostgreSQLConnector &) = delete;
|
||||||
|
|
||||||
virtual ~PostgreSQLConnector();
|
virtual ~PostgreSQLConnector();
|
||||||
|
|
||||||
void clear_all_query_results();
|
virtual void set_log_queries(bool log_queries);
|
||||||
void clear_last_query_result();
|
|
||||||
|
|
||||||
// give me a better names
|
bool query(const PT::TextStream & stream, QueryResult & query_result);
|
||||||
virtual size_t last_select_size();
|
bool query(const char * query_str, QueryResult & query_result);
|
||||||
virtual ExecStatusType last_query_status();
|
bool query(const std::string & query_str, QueryResult & query_result);
|
||||||
virtual bool is_last_result(ExecStatusType t); // was: is_last_result
|
|
||||||
|
|
||||||
virtual std::wstring get_last_query_error_msg();
|
bool query_select(const char * query_str, QueryResult & query_result);
|
||||||
virtual void set_last_query_error_msg(const char * error_msg);
|
bool query_update(const char * query_str, QueryResult & query_result);
|
||||||
virtual void set_last_query_error_msg(const wchar_t * error_msg);
|
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();
|
bool query_select(const PT::TextStream & stream, QueryResult & query_result);
|
||||||
virtual void set_was_error_in_last_query(bool was_error);
|
bool query_update(const PT::TextStream & stream, QueryResult & query_result);
|
||||||
|
bool query_insert(const PT::TextStream & stream, QueryResult & query_result);
|
||||||
void set_log_queries(bool log_queries);
|
bool query_remove(const PT::TextStream & stream, QueryResult & query_result);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
|
|
||||||
// give me a better name
|
virtual void set_conn_param(const std::wstring & database, const std::wstring & user, const std::wstring & pass);
|
||||||
virtual void set_current_row_at_beginning();
|
virtual void connect();
|
||||||
virtual void advance_current_row();
|
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:
|
protected:
|
||||||
|
|
||||||
PGconn * pg_conn;
|
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;
|
bool log_queries;
|
||||||
PT::TextStream stream;
|
PT::TextStream stream;
|
||||||
std::string query_str;
|
std::string query_str;
|
||||||
|
@ -137,35 +95,13 @@ protected:
|
||||||
std::wstring db_user;
|
std::wstring db_user;
|
||||||
std::wstring db_pass;
|
std::wstring db_pass;
|
||||||
|
|
||||||
struct QueryResult
|
virtual bool do_query(const char * query_str, PostgreSQLQueryResult * psql_result);
|
||||||
{
|
virtual void allocate_default_expression();
|
||||||
PGresult * result; // can be null
|
virtual void overwrite(PT::TextStream & stream);
|
||||||
size_t result_rows; // how many rows in the result query
|
virtual const char * query_last_sequence(const wchar_t * sequence_table_name);
|
||||||
ExecStatusType status;
|
virtual QueryResult * create_query_result();
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
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