2016-12-26 16:06:55 +01:00
# include " PgsqlConn.h "
# include <stdexcept>
using namespace Pgsql ;
2016-12-29 13:48:35 +01:00
namespace {
void set_stdstring_with_charptr ( std : : string & s , const char * p )
{
if ( p ) {
s = p ;
}
else {
s . clear ( ) ;
}
}
} // einde unnamed namespace
ErrorDetails ErrorDetails : : createErrorDetailsFromPGresult ( const PGresult * result )
{
2017-01-21 08:09:12 +01:00
2016-12-29 13:48:35 +01:00
ErrorDetails r ;
2017-01-21 08:09:12 +01:00
set_stdstring_with_charptr ( r . errorMessage , PQresultErrorMessage ( result ) ) ;
2016-12-29 13:48:35 +01:00
set_stdstring_with_charptr ( r . state , PQresultErrorField ( result , PG_DIAG_SQLSTATE ) ) ; ///< PG_DIAG_SQLSTATE Error code as listed in https://www.postgresql.org/docs/9.5/static/errcodes-appendix.html
set_stdstring_with_charptr ( r . severity , PQresultErrorField ( result , PG_DIAG_SEVERITY ) ) ;
set_stdstring_with_charptr ( r . messagePrimary , PQresultErrorField ( result , PG_DIAG_MESSAGE_PRIMARY ) ) ;
set_stdstring_with_charptr ( r . messageDetail , PQresultErrorField ( result , PG_DIAG_MESSAGE_DETAIL ) ) ;
set_stdstring_with_charptr ( r . messageHint , PQresultErrorField ( result , PG_DIAG_MESSAGE_HINT ) ) ;
const char * p = PQresultErrorField ( result , PG_DIAG_STATEMENT_POSITION ) ;
r . statementPosition = p ! = nullptr ? atoi ( p ) : - 1 ; ///< First character is one, measured in characters not bytes!
p = PQresultErrorField ( result , PG_DIAG_INTERNAL_POSITION ) ;
r . internalPosition = p ! = nullptr ? atoi ( p ) : - 1 ;
set_stdstring_with_charptr ( r . internalQuery , PQresultErrorField ( result , PG_DIAG_INTERNAL_QUERY ) ) ;
set_stdstring_with_charptr ( r . context , PQresultErrorField ( result , PG_DIAG_CONTEXT ) ) ;
set_stdstring_with_charptr ( r . schemaName , PQresultErrorField ( result , PG_DIAG_SCHEMA_NAME ) ) ;
set_stdstring_with_charptr ( r . tableName , PQresultErrorField ( result , PG_DIAG_TABLE_NAME ) ) ;
set_stdstring_with_charptr ( r . columnName , PQresultErrorField ( result , PG_DIAG_COLUMN_NAME ) ) ;
set_stdstring_with_charptr ( r . datatypeName , PQresultErrorField ( result , PG_DIAG_DATATYPE_NAME ) ) ;
set_stdstring_with_charptr ( r . constraintName , PQresultErrorField ( result , PG_DIAG_CONSTRAINT_NAME ) ) ;
set_stdstring_with_charptr ( r . sourceFile , PQresultErrorField ( result , PG_DIAG_SOURCE_FILE ) ) ;
set_stdstring_with_charptr ( r . sourceLine , PQresultErrorField ( result , PG_DIAG_SOURCE_LINE ) ) ;
set_stdstring_with_charptr ( r . sourceFunction , PQresultErrorField ( result , PG_DIAG_SOURCE_FUNCTION ) ) ;
return r ;
}
2016-12-26 16:06:55 +01:00
2017-01-25 06:50:57 +01:00
2017-02-04 11:52:42 +01:00
Params : : Params ( )
{ }
Params : : Params ( const Params & rhs )
: m_paramTypes ( rhs . m_paramTypes )
, m_paramLengths ( rhs . m_paramLengths )
, m_paramFormats ( rhs . m_paramFormats )
{
//std::vector<const char *> m_paramValues;
copyValues ( rhs . m_paramValues ) ;
}
Params & Params : : operator = ( const Params & rhs )
{
if ( & rhs ! = this ) {
m_paramTypes = rhs . m_paramTypes ;
m_paramLengths = rhs . m_paramLengths ;
m_paramFormats = rhs . m_paramFormats ;
copyValues ( rhs . m_paramValues ) ;
}
return * this ;
}
Params : : Params ( const Params & & rhs )
: m_paramTypes ( std : : move ( rhs . m_paramTypes ) )
, m_paramValues ( std : : move ( rhs . m_paramValues ) )
, m_paramLengths ( std : : move ( rhs . m_paramLengths ) )
, m_paramFormats ( std : : move ( rhs . m_paramFormats ) )
{ }
Params : : ~ Params ( )
{
deleteValues ( ) ;
}
void Params : : addText ( const char * data , Oid oid )
{
m_paramTypes . push_back ( oid ) ;
m_paramValues . push_back ( data ) ;
m_paramLengths . push_back ( data ? strlen ( data ) + 1 : 0 ) ;
m_paramFormats . push_back ( 0 ) ;
}
void Params : : add ( const QString & s , Oid oid )
{
auto ba = s . toUtf8 ( ) ;
const int len = ba . size ( ) ;
char * p = new char [ len ] ;
std : : memcpy ( p , ba . data ( ) , len ) ;
addText ( p , oid_varchar ) ;
}
void Params : : addBinary ( const char * data , int length , Oid oid )
{
m_paramTypes . push_back ( oid ) ;
m_paramValues . push_back ( data ) ;
m_paramLengths . push_back ( length ) ;
m_paramFormats . push_back ( 1 ) ;
}
void Params : : clear ( )
{
m_paramTypes . clear ( ) ;
deleteValues ( ) ;
m_paramValues . clear ( ) ;
m_paramLengths . clear ( ) ;
m_paramFormats . clear ( ) ;
}
2017-01-25 06:50:57 +01:00
bool Row : : next ( )
{
if ( m_row < m_result . getRows ( ) ) {
+ + m_row ;
return true ;
}
return false ;
}
2017-02-04 11:52:42 +01:00
void Params : : copyValues ( const t_paramValues & r )
{
const int n = m_paramTypes . size ( ) ;
m_paramValues . reserve ( n ) ;
for ( int i = 0 ; i < n ; + + i ) {
const int len = m_paramLengths [ i ] ;
char * p = new char [ len ] ;
std : : memcpy ( p , r [ i ] , len ) ;
m_paramValues . push_back ( p ) ;
}
}
2017-01-25 06:50:57 +01:00
Value Row : : get ( int col ) const
{
return m_result . get ( col , m_row ) ;
}
//Value Row::get(const char *colname) const
//{
//}
2016-12-26 16:06:55 +01:00
Result : : Result ( PGresult * res )
: result ( res )
{
if ( res = = nullptr ) {
throw std : : runtime_error ( " Passing nullptr to Result::Result is not allowed " ) ;
}
}
Result : : ~ Result ( )
{
PQclear ( result ) ;
}
Result : : Result ( Result & & rhs )
: result ( rhs . result )
{
rhs . result = nullptr ;
}
Result & Result : : operator = ( Result & & rhs )
{
if ( result ) {
PQclear ( result ) ;
}
result = rhs . result ;
rhs . result = nullptr ;
return * this ;
}
Result : : operator bool ( ) const
{
return result ! = nullptr ;
}
2016-12-27 21:22:49 +01:00
ExecStatusType Result : : resultStatus ( )
2016-12-26 16:06:55 +01:00
{
return PQresultStatus ( result ) ;
}
std : : string Result : : getResStatus ( )
{
// return PQresStatus(result);
return " " ;
}
2016-12-29 13:48:35 +01:00
std : : string Result : : diagSqlState ( )
{
std : : string s ( PQresultErrorField ( result , PG_DIAG_SQLSTATE ) ) ;
return s ;
}
ErrorDetails Result : : diagDetails ( )
{
// ErrorDetails r;
// r.state = PQresultErrorField(result, PG_DIAG_SQLSTATE); ///< PG_DIAG_SQLSTATE Error code as listed in https://www.postgresql.org/docs/9.5/static/errcodes-appendix.html
// r.severity = PQresultErrorField(result, PG_DIAG_SEVERITY);
// r.messagePrimary = PQresultErrorField(result, PG_DIAG_MESSAGE_PRIMARY);
// r.messageDetail = PQresultErrorField(result, PG_DIAG_MESSAGE_DETAIL);
// r.messageHint = PQresultErrorField(result, PG_DIAG_MESSAGE_HINT);
// r.statementPosition = atoi(PQresultErrorField(result, PG_DIAG_STATEMENT_POSITION)); ///< First character is one, measured in characters not bytes!
// r.internalPosition = atoi(PQresultErrorField(result, PG_DIAG_INTERNAL_POSITION));
// r.internalQuery = PQresultErrorField(result, PG_DIAG_INTERNAL_QUERY);
// r.context = PQresultErrorField(result, PG_DIAG_CONTEXT);
// r.schemaName = PQresultErrorField(result, PG_DIAG_SCHEMA_NAME);
// r.tableName = PQresultErrorField(result, PG_DIAG_TABLE_NAME);
// r.columnName = PQresultErrorField(result, PG_DIAG_COLUMN_NAME);
// r.datatypeName = PQresultErrorField(result, PG_DIAG_DATATYPE_NAME);
// r.constraintName = PQresultErrorField(result, PG_DIAG_CONSTRAINT_NAME);
// r.sourceFile = PQresultErrorField(result, PG_DIAG_SOURCE_FILE);
// r.sourceLine = PQresultErrorField(result, PG_DIAG_SOURCE_LINE);
// r.sourceFunction = PQresultErrorField(result, PG_DIAG_SOURCE_FUNCTION);
// return r;
return ErrorDetails : : createErrorDetailsFromPGresult ( result ) ;
}
2017-01-16 18:56:07 +01:00
int Result : : tuplesAffected ( ) const
{
int i ;
char * res = PQcmdTuples ( result ) ;
if ( res ) {
try {
i = std : : stoi ( res ) ;
}
catch ( std : : invalid_argument & ) {
i = - 1 ;
}
catch ( std : : out_of_range & ) {
i = - 1 ;
}
}
else {
i = - 1 ;
}
return i ;
}
2016-12-29 13:48:35 +01:00
2016-12-26 16:06:55 +01:00
int Result : : getRows ( ) const
{
return PQntuples ( result ) ;
}
int Result : : getCols ( ) const
{
return PQnfields ( result ) ;
}
const char * const Result : : getColName ( int idx ) const
{
return PQfname ( result , idx ) ;
}
const char * Result : : getVal ( int col , int row ) const
{
return PQgetvalue ( result , row , col ) ;
}
2017-01-25 06:50:57 +01:00
Value Result : : get ( int col , int row ) const
{
return Value (
PQgetvalue ( result , row , col ) ,
PQftype ( result , col )
) ;
}
2017-01-18 20:50:53 +01:00
Oid Result : : type ( int col ) const
{
return PQftype ( result , col ) ;
}
bool Result : : null ( int col , int row ) const
{
return PQgetisnull ( result , row , col ) ;
}
2016-12-26 16:06:55 +01:00
2016-12-29 13:48:35 +01:00
Canceller : : Canceller ( PGcancel * c )
: m_cancel ( c )
{ }
Canceller : : Canceller ( Canceller & & rhs )
: m_cancel ( rhs . m_cancel )
{
rhs . m_cancel = nullptr ;
}
Canceller & Canceller : : operator = ( Canceller & & rhs )
{
if ( m_cancel ) {
PQfreeCancel ( m_cancel ) ;
}
m_cancel = rhs . m_cancel ;
rhs . m_cancel = nullptr ;
return * this ;
}
Canceller : : ~ Canceller ( )
{
if ( m_cancel ) {
PQfreeCancel ( m_cancel ) ;
}
}
2017-01-08 09:58:34 +01:00
bool Canceller : : cancel ( std : : string * error )
2016-12-29 13:48:35 +01:00
{
const int errbuf_size = 256 ;
char errbuf [ errbuf_size ] ;
2017-01-08 09:58:34 +01:00
bool res = PQcancel ( m_cancel , errbuf , errbuf_size ) ;
if ( ! res & & error ) {
* error = errbuf ;
}
return res ;
2016-12-29 13:48:35 +01:00
}
2016-12-26 16:06:55 +01:00
Connection : : Connection ( ) = default ;
Connection : : ~ Connection ( )
{
close ( ) ;
}
Connection : : Connection ( Connection & & rhs )
: conn ( rhs . conn )
{
rhs . conn = nullptr ;
}
Connection & Connection : : operator = ( Connection & & rhs )
{
close ( ) ;
conn = rhs . conn ;
rhs . conn = nullptr ;
return * this ;
}
void Connection : : close ( )
{
if ( conn ) {
PQfinish ( conn ) ;
conn = nullptr ;
}
}
2016-12-29 13:48:35 +01:00
Canceller Connection : : getCancel ( )
{
Canceller c ( PQgetCancel ( conn ) ) ;
return c ;
}
2016-12-26 16:06:55 +01:00
bool Connection : : connect ( const char * params )
{
bool result = false ;
conn = PQconnectdb ( params ) ;
if ( conn ) {
ConnStatusType status = PQstatus ( conn ) ;
result = ( status = = CONNECTION_OK ) ;
}
return result ;
}
2017-02-04 11:52:42 +01:00
bool Connection : : connect ( const char * const * keywords , const char * const * values , int expand_dbname )
{
bool result = false ;
conn = PQconnectdbParams ( keywords , values , expand_dbname ) ;
if ( conn ) {
ConnStatusType status = PQstatus ( conn ) ;
result = ( status = = CONNECTION_OK ) ;
}
return result ;
}
2016-12-27 15:41:11 +01:00
bool Connection : : connectStart ( const char * params )
{
conn = PQconnectStart ( params ) ;
return conn ! = nullptr ;
}
2017-01-15 21:01:40 +01:00
bool Connection : : connectStart ( const char * const * keywords ,
const char * const * values )
{
conn = PQconnectStartParams ( keywords , values , 0 ) ;
return conn ! = nullptr ;
}
2016-12-27 15:41:11 +01:00
PostgresPollingStatusType Connection : : connectPoll ( )
{
return PQconnectPoll ( conn ) ;
}
ConnStatusType Connection : : status ( )
{
return PQstatus ( conn ) ;
}
int Connection : : socket ( )
{
return PQsocket ( conn ) ;
}
2016-12-26 16:06:55 +01:00
std : : string Connection : : getErrorMessage ( ) const
{
std : : string result ;
if ( conn ) {
result = PQerrorMessage ( conn ) ;
}
else {
result = " no connection " ;
}
return result ;
}
2016-12-27 15:41:11 +01:00
Result Connection : : query ( const char * command )
2016-12-26 16:06:55 +01:00
{
2016-12-27 15:41:11 +01:00
PGresult * result = PQexec ( conn , command ) ;
2016-12-29 13:48:35 +01:00
return Result ( result ) ;
2016-12-26 16:06:55 +01:00
}
2016-12-27 15:41:11 +01:00
bool Connection : : sendQuery ( const char * query )
{
int res = PQsendQuery ( conn , query ) ;
return res = = 1 ;
}
2017-01-08 09:58:34 +01:00
std : : shared_ptr < Result > Connection : : getResult ( )
2016-12-27 15:41:11 +01:00
{
PGresult * r = PQgetResult ( conn ) ;
if ( r ) {
2017-01-08 09:58:34 +01:00
return std : : make_shared < Result > ( r ) ;
2016-12-27 15:41:11 +01:00
}
else {
return nullptr ;
}
}
2016-12-27 21:22:49 +01:00
bool Connection : : consumeInput ( )
{
int res = PQconsumeInput ( conn ) ;
return res = = 1 ;
}
bool Connection : : isBusy ( )
{
int res = PQisBusy ( conn ) ;
return res = = 1 ;
}
2016-12-29 13:48:35 +01:00
void Connection : : setNoticeReceiver ( std : : function < void ( const PGresult * ) > callback )
{
notifyReceiver = callback ;
PQsetNoticeReceiver ( conn ,
Connection : : notifyReceiveFunc
, reinterpret_cast < void * > ( this ) ) ;
}
void Connection : : notifyReceiveFunc ( void * arg , const PGresult * result )
{
Connection * c = reinterpret_cast < Connection * > ( arg ) ;
c - > notifyReceiver ( result ) ;
}