blob: 0e71d5647c251d516492a71139bd59786cdde5e5 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <unistd.h>
#include "psql.h"
#include "command.h"
using std::string;
namespace hawq {
namespace test {
#define PSQL_BASIC_DIFF_OPTS "-w -I NOTICE: -I HINT: -I CONTEXT: -I GP_IGNORE:"
#define PSQL_PRETTY_DIFF_OPTS \
"-w -I NOTICE: -I HINT: -I CONTEXT: -I GP_IGNORE: -C3"
void PSQLQueryResult::setErrorMessage(const string & errmsg) {
this->_errmsg = errmsg;
}
const string& PSQLQueryResult::getErrorMessage() const {
return this->_errmsg;
}
bool PSQLQueryResult::isError() const {
return this->_errmsg.length() > 0;
}
const std::vector<std::vector<string> >& PSQLQueryResult::getRows() const {
return this->_rows;
}
const std::vector<string>& PSQLQueryResult::getFields() const {
return this->_fields;
}
const std::vector<string>& PSQLQueryResult::getRow(int ri) const {
return this->getRows()[ri];
}
const string& PSQLQueryResult::getData(int ri, int ci) const {
return this->getRow(ri)[ci];
}
string PSQLQueryResult::getData(int ri, const string& ck) const {
for (unsigned int ci = 0; ci < this->_fields.size(); ci++) {
if (ck == this->_fields[ci]) {
return this->getData(ri, ci);
}
}
return "";
}
const string& PSQLQueryResult::getFieldName(int ci) const {
return this->_fields[ci];
}
int PSQLQueryResult::rowCount() const {
return this->_rows.size();
}
int PSQLQueryResult::fieldCount() const {
return this->_fields.size();
}
void PSQLQueryResult::savePGResult(const PGresult* res) {
int nfields = PQnfields(res);
for (int i = 0; i < nfields; i++) {
this->_fields.push_back(PQfname(res, i));
}
for (int i = 0; i < PQntuples(res); i++) {
std::vector<string> row;
for (int j = 0; j < nfields; j++) {
row.push_back(PQgetvalue(res, i, j));
}
this->_rows.push_back(row);
}
}
void PSQLQueryResult::reset() {
this->_errmsg.clear();
this->_rows.clear();
this->_fields.clear();
}
PSQL& PSQL::runSQLCommand(const string& sql_cmd) {
hawq::test::Command c(this->_getPSQLQueryCommand(sql_cmd));
c.run();
this->_last_status = c.getResultStatus();
this->_last_result = c.getResultOutput();
return *this;
}
PSQL& PSQL::runSQLFile(const string& sql_file, bool printTupleOnly) {
this->_last_status =
hawq::test::Command::getCommandStatus(this->_getPSQLFileCommand(sql_file, printTupleOnly));
return *this;
}
const PSQLQueryResult& PSQL::getQueryResult(const string& sql) {
PGconn* conn = NULL;
PGresult* res = NULL;
conn = PQconnectdb(this->getConnectionString().c_str());
if (PQstatus(conn) != CONNECTION_OK) {
this->_result.setErrorMessage(PQerrorMessage(conn));
goto done;
}
res = PQexec(conn, sql.c_str());
if (PQresultStatus(res) != PGRES_TUPLES_OK) {
this->_result.setErrorMessage(PQerrorMessage(conn));
goto done;
}
this->_result.reset();
this->_result.savePGResult(res);
done:
if (res) {
PQclear(res);
res = NULL;
}
if (conn) {
PQfinish(conn);
conn = NULL;
}
return this->_result;
}
PSQL& PSQL::setHost(const string& host) {
this->_host = host;
return *this;
}
PSQL& PSQL::setPort(const string& port) {
this->_port = port;
return *this;
}
PSQL& PSQL::setUser(const string& username) {
this->_user = username;
return *this;
}
PSQL& PSQL::setPassword(const string& password) {
this->_password = password;
return *this;
}
PSQL& PSQL::setOutputFile(const string& out) {
this->_output_file = out;
return *this;
}
void PSQL::resetOutput() {
this->_output_file.clear();
}
string PSQL::getConnectionString() const {
// host=localhost port=5432 dbname=mydb
string command;
command.append("host=")
.append(this->_host)
.append(" port=")
.append(this->_port)
.append(" user=")
.append(this->_user)
.append(" dbname=")
.append(this->_dbname);
return command;
}
int PSQL::getLastStatus() const {
return this->_last_status;
}
const string& PSQL::getLastResult() const {
return this->_last_result;
}
const string PSQL::_getPSQLBaseCommand() const {
string command = "psql";
command.append(" -p ").append(this->_port);
command.append(" -h ").append(this->_host);
command.append(" -U ").append(this->_user);
command.append(" -d ").append(this->_dbname);
if (this->_output_file.length() > 0) {
command.append(" > ").append(this->_output_file);
}
return command;
}
const string PSQL::_getPSQLQueryCommand(const string& query) const {
string command = this->_getPSQLBaseCommand();
return command.append(" -c \"").append(query).append("\"");
}
const string PSQL::_getPSQLFileCommand(const string& file, bool printTupleOnly) const {
string command = this->_getPSQLBaseCommand();
if (printTupleOnly) {
return command.append(" -a -A -t -f").append(file);
}
else {
return command.append(" -a -f ").append(file);
}
}
bool PSQL::checkDiff(const string& expect_file,
const string& result_file,
bool save_diff,
const string& global_init_file,
const string& init_file) {
string diff_file = result_file + ".diff";
string command;
command.append("gpdiff.pl -du ")
.append(PSQL_BASIC_DIFF_OPTS);
if (!global_init_file.empty()) {
command.append(" -gpd_init ")
.append(global_init_file);
}
if (!init_file.empty()) {
command.append(" -gpd_init ")
.append(init_file);
}
command.append(" ")
.append(expect_file)
.append(" ")
.append(result_file)
.append(" ")
.append(" >")
.append(diff_file);
if (hawq::test::Command::getCommandStatus(command) == 0) {
unlink(diff_file.c_str());
return false;
} else {
if (!save_diff) {
unlink(diff_file.c_str());
}
return true;
}
}
} // namespace test
} // namespace hawq