874 lines
16 KiB
C++
874 lines
16 KiB
C++
/*
|
|
* 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.
|
|
*
|
|
*/
|
|
|
|
// for sleep()
|
|
#include <unistd.h>
|
|
|
|
#include "postgresqlconnector.h"
|
|
#include "utf8/utf8.h"
|
|
#include "postgresqlexpression.h"
|
|
#include "convert/strtoint.h"
|
|
|
|
|
|
namespace morm
|
|
{
|
|
|
|
PostgreSQLConnector::PostgreSQLConnector()
|
|
{
|
|
pg_conn = nullptr;
|
|
log_queries = false;
|
|
}
|
|
|
|
|
|
PostgreSQLConnector::~PostgreSQLConnector()
|
|
{
|
|
close();
|
|
}
|
|
|
|
|
|
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;
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
|
|
|
|
void PostgreSQLConnector::allocate_default_expression()
|
|
{
|
|
deallocate_expression();
|
|
db_expression = new PostgreSQLExpression();
|
|
expression_allocated = true;
|
|
}
|
|
|
|
|
|
|
|
void PostgreSQLConnector::set_log_queries(bool log_queries)
|
|
{
|
|
this->log_queries = log_queries;
|
|
}
|
|
|
|
|
|
bool PostgreSQLConnector::query(const char * query_str)
|
|
{
|
|
// if( pg_conn )
|
|
{
|
|
// if( log_queries )
|
|
// {
|
|
// log << log1 << "Db: executing query: " << q << logend;
|
|
// }
|
|
|
|
query_results.push_back(QueryResult());
|
|
QueryResult & last_res = query_results.back();
|
|
|
|
last_res.result = PQexec(pg_conn, query_str);
|
|
|
|
if( !last_res.result )
|
|
{
|
|
if( PQstatus(pg_conn) != CONNECTION_OK )
|
|
{
|
|
assert_connection();
|
|
last_res.result = PQexec(pg_conn, query_str);
|
|
}
|
|
}
|
|
|
|
if( last_res.result )
|
|
{
|
|
last_res.status = PQresultStatus(last_res.result);
|
|
last_res.result_rows = static_cast<size_t>(PQntuples(last_res.result));
|
|
}
|
|
else
|
|
{
|
|
// log << log1 << "Db: Problem with this query: \"" << q << '\"' << logend;
|
|
// log << log1 << "Db: " << PQerrorMessage(pg_conn) << logend;
|
|
}
|
|
}
|
|
|
|
return (!query_results.empty() && query_results.back().result != nullptr);
|
|
}
|
|
|
|
|
|
|
|
const char * PostgreSQLConnector::query_last_sequence(const wchar_t * sequence_table_name)
|
|
{
|
|
allocate_default_expression_if_needed();
|
|
|
|
if( db_expression )
|
|
{
|
|
stream.clear();
|
|
stream << "select currval(E'";
|
|
db_expression->esc(sequence_table_name, stream);
|
|
stream << "');";
|
|
|
|
if( query_select(stream) )
|
|
{
|
|
if( last_select_size() == 1 )
|
|
{
|
|
return get_value_from_result(0, 0);
|
|
}
|
|
else
|
|
{
|
|
//log << log1 << "Db: error (currval) for table: " << table << ", " << PQerrorMessage(db_conn->GetPgConn()) << logend;
|
|
}
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
|
|
|
|
bool PostgreSQLConnector::query(const PT::TextStream & stream)
|
|
{
|
|
stream.to_string(query_str);
|
|
return query(query_str.c_str());
|
|
}
|
|
|
|
|
|
bool PostgreSQLConnector::query(const std::string & query_str)
|
|
{
|
|
return query(query_str.c_str());
|
|
}
|
|
|
|
|
|
bool PostgreSQLConnector::query_select(const char * query_str)
|
|
{
|
|
return (query(query_str) && last_query_status() == PGRES_TUPLES_OK);
|
|
}
|
|
|
|
bool PostgreSQLConnector::query_update(const char * query_str)
|
|
{
|
|
return (query(query_str) && last_query_status() == PGRES_COMMAND_OK);
|
|
}
|
|
|
|
bool PostgreSQLConnector::query_insert(const char * query_str)
|
|
{
|
|
return (query(query_str) && last_query_status() == PGRES_COMMAND_OK);
|
|
}
|
|
|
|
|
|
|
|
bool PostgreSQLConnector::query_select(const PT::TextStream & stream)
|
|
{
|
|
stream.to_string(query_str);
|
|
return query_select(query_str.c_str());
|
|
}
|
|
|
|
bool PostgreSQLConnector::query_update(const PT::TextStream & stream)
|
|
{
|
|
stream.to_string(query_str);
|
|
return query_update(query_str.c_str());
|
|
}
|
|
|
|
bool PostgreSQLConnector::query_insert(const PT::TextStream & stream)
|
|
{
|
|
stream.to_string(query_str);
|
|
return query_insert(query_str.c_str());
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//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;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//void PostgreSQLConnector::CreateIdList(const std::vector<long> & id_tab, std::wstring & list, bool add_parentheses)
|
|
//{
|
|
//wchar_t buffer[50];
|
|
//size_t buffer_len = sizeof(buffer) / sizeof(wchar_t);
|
|
//
|
|
// list.clear();
|
|
//
|
|
// if( add_parentheses )
|
|
// list += '(';
|
|
//
|
|
// for(size_t i=0 ; i<id_tab.size() ; ++i)
|
|
// {
|
|
// Toa((unsigned long)id_tab[i], buffer, buffer_len);
|
|
// list += buffer;
|
|
//
|
|
// if( i+1 < id_tab.size() )
|
|
// list += ',';
|
|
// }
|
|
//
|
|
// if( add_parentheses )
|
|
// list += ')';
|
|
//}
|
|
|
|
|
|
|
|
|
|
//Error PostgreSQLConnector::BeginTrans()
|
|
//{
|
|
// return DoCommand("BEGIN;");
|
|
//}
|
|
//
|
|
//
|
|
//
|
|
//Error PostgreSQLConnector::RollbackTrans()
|
|
//{
|
|
// return DoCommand("ROLLBACK;");
|
|
//}
|
|
//
|
|
//
|
|
//
|
|
//Error PostgreSQLConnector::CommitTrans()
|
|
//{
|
|
// return DoCommand("COMMIT;");
|
|
//}
|
|
//
|
|
//
|
|
//
|
|
//bool PostgreSQLConnector::EndTrans(bool everything_ok)
|
|
//{
|
|
//bool result;
|
|
//
|
|
// if( everything_ok )
|
|
// {
|
|
// result = (CommitTrans() == WINIX_ERR_OK);
|
|
// }
|
|
// else
|
|
// {
|
|
// RollbackTrans();
|
|
// // we return the old err code
|
|
// result = false;
|
|
// }
|
|
//
|
|
//return result;
|
|
//}
|
|
//
|
|
//
|
|
//Error PostgreSQLConnector::EndTrans(Error err)
|
|
//{
|
|
// if( err == WINIX_ERR_OK )
|
|
// {
|
|
// err = CommitTrans();
|
|
// }
|
|
// else
|
|
// {
|
|
// // we return the old err code
|
|
// RollbackTrans();
|
|
// }
|
|
//
|
|
//return err;
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
converting from a bytea
|
|
the old way (escape format)
|
|
*/
|
|
/*
|
|
int PostgreSQLConnector::CharToInt(char c)
|
|
{
|
|
return (int)(unsigned char)(c-'0');
|
|
}
|
|
|
|
bool PostgreSQLConnector::IsCorrectOctalDigit(char c)
|
|
{
|
|
return c>='0' && c<='7';
|
|
}
|
|
|
|
// moves 'i' at least once
|
|
// return -1 if there is en error
|
|
int PostgreSQLConnector::UnescapeBin(const char * str, size_t & i, size_t len)
|
|
{
|
|
if( str[i] != '\\' )
|
|
return str[i++];
|
|
|
|
i += 1;
|
|
|
|
if( i >= len )
|
|
return -1;
|
|
|
|
if( str[i] == '\\' )
|
|
return str[i++];
|
|
|
|
if( i+2 >= len )
|
|
{
|
|
i = len;
|
|
return -1;
|
|
}
|
|
|
|
if( !IsCorrectOctalDigit(str[i]) ||
|
|
!IsCorrectOctalDigit(str[i+1]) ||
|
|
!IsCorrectOctalDigit(str[i+2]) )
|
|
{
|
|
i += 3;
|
|
return -1;
|
|
}
|
|
|
|
int c = 8*8*CharToInt(str[i]) + 8*CharToInt(str[i+1]) + CharToInt(str[i+2]);
|
|
|
|
i += 3;
|
|
|
|
if( c<0 || c>255 )
|
|
return -1;
|
|
|
|
return c;
|
|
}
|
|
|
|
void PostgreSQLConnector::UnescapeBin(const char * str, size_t len, std::string & out, bool clear_out)
|
|
{
|
|
int c;
|
|
size_t i = 0;
|
|
|
|
if( clear_out )
|
|
out.clear();
|
|
|
|
while( i < len )
|
|
{
|
|
c = UnescapeBin(str, i, len);
|
|
|
|
if( c != -1 )
|
|
out += c;
|
|
}
|
|
}
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
converting from a bytea
|
|
the new way (hex format)
|
|
*/
|
|
|
|
|
|
//char PostgreSQLConnector::UnescapeBinHexToDigit(char hex)
|
|
//{
|
|
// if( hex>='0' && hex<='9' )
|
|
// return hex - '0';
|
|
//
|
|
// if( hex>='a' && hex<='z' )
|
|
// return hex - 'a' + 10;
|
|
//
|
|
// if( hex>='A' && hex<='Z' )
|
|
// return hex - 'A' + 10;
|
|
//
|
|
//return 0;
|
|
//}
|
|
//
|
|
//
|
|
//void PostgreSQLConnector::UnescapeBin(const char * str, size_t len, std::string & out, bool clear_out)
|
|
//{
|
|
// if( clear_out )
|
|
// out.clear();
|
|
//
|
|
// if( len < 2 || str[0]!='\\' || str[1]!='x' )
|
|
// {
|
|
// log << log1 << "Db: unsupported binary format (skipping)" << logend;
|
|
// return;
|
|
// }
|
|
//
|
|
// for(size_t i=2 ; i + 1 < len ; i+=2 )
|
|
// {
|
|
// int c1 = UnescapeBinHexToDigit(str[i]);
|
|
// int c2 = UnescapeBinHexToDigit(str[i+1]);
|
|
//
|
|
// out += ((c1 << 4) | c2);
|
|
// }
|
|
//}
|
|
|
|
|
|
|
|
void PostgreSQLConnector::set_conn_param(const std::wstring & database_name, const std::wstring & user, const std::wstring & pass)
|
|
{
|
|
db_database = database_name;
|
|
db_user = user;
|
|
db_pass = pass;
|
|
}
|
|
|
|
|
|
void PostgreSQLConnector::overwrite(PT::TextStream & stream)
|
|
{
|
|
PT::TextStream::iterator i = stream.begin();
|
|
|
|
for( ; i != stream.end() ; ++i)
|
|
{
|
|
*i = 0;
|
|
}
|
|
|
|
stream.clear();
|
|
}
|
|
|
|
|
|
|
|
|
|
void PostgreSQLConnector::connect()
|
|
{
|
|
// IMPROVEME
|
|
// what about if reconnecting is made in the midle of queries?
|
|
// e.g. in after_select? (the whole stack query_results will be cleared)
|
|
close();
|
|
|
|
allocate_default_expression_if_needed();
|
|
|
|
if( db_expression )
|
|
{
|
|
stream.clear();
|
|
stream << "dbname='";
|
|
db_expression->esc(db_database, stream);
|
|
|
|
stream << "' user='";
|
|
db_expression->esc(db_user, stream);
|
|
|
|
stream << "' password='";
|
|
db_expression->esc(db_pass, stream);
|
|
stream << "'";
|
|
|
|
std::string str;
|
|
stream.to_string(str);
|
|
pg_conn = PQconnectdb(str.c_str());
|
|
|
|
overwrite(stream);
|
|
}
|
|
// warning! pg_conn can be not null but there cannnot be a connection established
|
|
// use PQstatus(pg_conn) to check whether the connection works fine
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
void PostgreSQLConnector::log_connection_socket()
|
|
{
|
|
if( pg_conn )
|
|
{
|
|
//log << log2 << "Db: connection to the database works fine" << logend;
|
|
//log << log3 << "Db: connection socket: " << PQsocket(pg_conn) << logend;
|
|
|
|
//std::cout << "Db: connection to the database works fine" << std::endl;
|
|
//std::cout << "Db: connection socket: " << PQsocket(pg_conn) << std::endl;
|
|
}
|
|
}
|
|
|
|
void PostgreSQLConnector::wait_for_connection()
|
|
{
|
|
if( !pg_conn || PQstatus(pg_conn) != CONNECTION_OK )
|
|
{
|
|
//log << log3 << "Db: waiting for the db to be ready...." << logend << logsave;
|
|
//std::cout << "Db: waiting for the db to be ready...." << std::endl;
|
|
|
|
while( !assert_connection(false) )
|
|
{
|
|
sleep(5);
|
|
}
|
|
|
|
//LogConnectionSocket();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
// IMPROVE ME what about the exception now?
|
|
bool PostgreSQLConnector::assert_connection(bool put_log)
|
|
{
|
|
bool was_connection = true;
|
|
|
|
|
|
if( !pg_conn )
|
|
{
|
|
was_connection = false;
|
|
connect();
|
|
}
|
|
else
|
|
if( PQstatus(pg_conn) != CONNECTION_OK )
|
|
{
|
|
if( put_log )
|
|
{
|
|
//log << log2 << "Db: connection to the database is lost, trying to recover" << logend;
|
|
//std::cout << "Db: connection to the database is lost, trying to recover" << std::endl;
|
|
}
|
|
|
|
was_connection = false;
|
|
PQreset(pg_conn);
|
|
}
|
|
|
|
|
|
if( pg_conn && PQstatus(pg_conn) == CONNECTION_OK )
|
|
{
|
|
if( !was_connection )
|
|
{
|
|
// if( put_log )
|
|
// LogConnectionSocket();
|
|
|
|
set_db_parameters();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
if( put_log )
|
|
{
|
|
//log << log1 << "Db: connection to db server cannot be established" << logend;
|
|
//std::cout << "Db: connection to db server cannot be established" << std::endl;
|
|
}
|
|
|
|
// if( throw_if_no_connection )
|
|
// {
|
|
// //throw Error(WINIX_ERR_DB_FATAL_ERROR_DURING_CONNECTING);
|
|
// throw int(10);
|
|
// }
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void PostgreSQLConnector::set_db_parameters()
|
|
{
|
|
if( PQsetClientEncoding(pg_conn, "UTF8") == -1 )
|
|
{
|
|
//log << log1 << "Db: Can't set the proper client encoding" << logend;
|
|
//std::cout << "Db: Can't set the proper client encoding" << std::endl;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|