morm/src/postgresqlqueryresult.cpp

289 lines
6.3 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-2019, 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()
{
psql_result = nullptr;
psql_status = PGRES_EMPTY_QUERY;
}
void PostgreSQLQueryResult::clear()
{
if( psql_result )
{
PQclear(psql_result);
}
psql_result = nullptr;
psql_status = PGRES_EMPTY_QUERY;
QueryResult::clear();
}
bool PostgreSQLQueryResult::has_db_result()
{
return psql_result != nullptr;
}
const char * PostgreSQLQueryResult::get_field_string_value(int column_index)
{
const char * value_str = nullptr;
if( psql_result && column_index >= 0 && (size_t)column_index < result_cols )
{
if( cur_row < result_rows )
{
value_str = PQgetvalue(psql_result, cur_row, column_index);
}
}
return value_str;
}
const char * PostgreSQLQueryResult::get_field_string_value(const char * column_name)
{
const char * value_str = nullptr;
if( psql_result )
{
int col_index = PQfnumber(psql_result, column_name);
if( col_index != -1 )
{
if( cur_row < result_rows )
{
value_str = PQgetvalue(psql_result, cur_row, col_index);
}
}
}
return value_str;
}
int PostgreSQLQueryResult::get_column_index(const char * column_name)
{
int col_index = -1;
if( psql_result )
{
col_index = PQfnumber(psql_result, column_name);
// returns -1 if there is no such a column
}
return col_index;
}
bool PostgreSQLQueryResult::is_null(int column_index)
{
bool res = false;
if( column_index >= 0 && (size_t)column_index < result_cols )
{
if( cur_row < result_rows )
{
res = is_null(cur_row, column_index);
}
}
return res;
}
/*
* in the future we can use single row mode:
* https://www.postgresql.org/docs/10/libpq-single-row-mode.html
*
* or just cursors from database:
* https://www.postgresql.org/docs/current/sql-fetch.html
*
*/
const char * PostgreSQLQueryResult::get_value_from_result(int row, int col)
{
const char * value_str = nullptr;
if( psql_result )
{
value_str = PQgetvalue(psql_result, row, col);
// can return a null pointer if there is no such an item in the last psql_result
}
return value_str;
}
int PostgreSQLQueryResult::get_value_length(int row, int col)
{
int len = 0;
if( psql_result )
{
len = PQgetlength(psql_result, row, col);
}
return len;
}
bool PostgreSQLQueryResult::is_null(int row, int col)
{
bool is_null = false;
if( psql_result )
{
is_null = (PQgetisnull(psql_result, row, col) == 1);
}
return is_null;
}
void PostgreSQLQueryResult::dump_column_names(pt::Log & log)
{
if( psql_result )
{
int cols = PQnfields(psql_result);
for(int i = 0 ; i < cols ; ++i)
{
log << i << ' ' << PQfname(psql_result, i) << pt::Log::logend;
}
}
}
//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 << "Morm: 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