/* * This file is a part of morm * and is distributed under the 2-Clause BSD licence. * Author: Tomasz Sowa */ /* * 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