Connection to Postgres Database using libpqxx - c++

I am using libpqxx to connect to a postgres database by creating a class.
class databaseConnection
{
public:
pqxx::connection* conn;
void SetConnection(){
conn=new pqxx::connection(
"username=temp "
"host=db.corral.tacc.utexas.edu "
"password=timelione "
"dbname=temp");
}
void Disconnect(){
conn->disconnect();
}
pqxx::result query(std::string strSQL){
//SetConnection();
pqxx::work trans(*conn,"trans");
pqxx::result res=trans.exec(strSQL);
trans.commit();
return res;
}
};
int main()
{
databaseConnection* pdatabase;
pdatabase->SetConnection();
return 0;
}
I am getting error that says
terminate called after throwing an instance of 'pqxx::broken_connection'
what(): invalid connection option "database"
Can anyone help me out?
Thanks

pgxx::connection(const PGSTD::string&) is basically a wrapper around libpq's PQconnectdb() function, so the supported connection parameter keywords are the same as for libpq.
The parameter key word for the PostgreSQL user name to connect as is user, not username. Perhaps correcting that will fix the problem.
Also, in your sample code, pdatabase is an uninitialized pointer. You could either allocate a databaseConnection object on the stack with:
databaseConnection database;
database.SetConnection();
or use new to heap-allocate a databaseConnection object:
databaseConnection* pdatabase = new databaseConnection();
pdatabase->SetConnection();
But you need to pick one.

if you try like this
try
{
conn = new pqxx::connection(
"username=temp "
"host=db.corral.tacc.utexas.edu "
"password=timelione "
"dbname=temp");
}
catch (const std::exception &e)
{
std::cerr << e.what() << std::endl;
}
it catches the exception about connection string:
invalid connection option "username"

You might also need to add port=5432 to your connection string.

Related

C++ Legacy Driver mongoDB Replicaset in Class of a DLL

I have built a dll which includes a class implementing the mongoDB replicaset operations. Here is a summary of the class.
#include "mongo/client/dbclient.h"
mongoimp::mongoimp() {
mongo::client::initialize();
}
mongoimp::~mongoimp() {
mongo::client::shutdown();
}
int mongoimp::queryTRecords() {
string errmsg;
vector<mongo::HostAndPort> hosts = { mongo::HostAndPort("xx-a0.yyyy.com:xxxxx"), mongo::HostAndPort("xx-a1.yyyy.com:xxxxx") };
static mongo::DBClientReplicaSet con("xx", hosts, 0);
con.connect();
con.auth("dbname", "username", "password", errmsg);
auto_ptr<DBClientCursor> cursor = con.query("dbname.t", BSONObj());
BSONObj response;
con.logout("xx", response);
if (cursor->more()) {
BSONObj recordnm = cursor->nextSafe();
return(recordnm.getIntField("lastid"));
} else return(-1);
}
The above code is working. But here are my questions:
1) With the above setting, I can do normal mongoDB operations with the dll but since my application needs to constantly update mongoDB data (close to real-time, up to hundreds a second), I am getting error (No valid replicaset instance servers found) when updating data.
2) Only the server needs to talk to the mongoDB database. So basically I just need one connection to the database. So I want to declare the mongo::DBClientReplicaSet con as a static global variable and connect to it in the class construct function. But it seemed I cannot do it. My application cannot run at all. With that, I constantly get the following error.
Assertion failed: px != 0, file C:\Boost\include\boost-1_62\boost/smart_ptr/scoped_ptr.hpp, line 105
Does anybody know how to solve the problem?
Below is the code I tried:
static mongo::DBClientReplicaSet con("xx", { mongo::HostAndPort("xx-a0.yyyy.com:xxxxx"), mongo::HostAndPort("xx-a1.yyyy.com:xxxxx") }, 0);
mongoimp::mongoimp() {
mongo::client::initialize();
string errmsg;
con.connect();
con.auth("dbname", "username", "password", errmsg);
}
mongoimp::~mongoimp() {
BSONObj response;
con.logout("xx", response);
mongo::client::shutdown();
}
int mongoimp::queryTRecords() {
auto_ptr<DBClientCursor> cursor = con.query("dbname.t", BSONObj());
if (cursor->more()) {
BSONObj recordnm = cursor->nextSafe();
return(recordnm.getIntField("lastid"));
} else return(-1);
}
3) Last question, I noticed there is mongo/client/dbclient_rs.h" file for replicaset. But it seemed I cannot use it. With that, I am getting error for initialize() and auto_ptr cursor. How can I use the file and take full advantage of replicaset features? How can I initialize the relica set if I can use "dbclient_rs.h"? How do I do query and fetch data in that case?
Thanks a lot in advance!
For question No. 2, I remembered the reason for the error:
You need to call mongo::client::initialize before you construct any driver objects, or BSON for that matter.
But how to make that global definition possible, I still need a solution.

Error:"Parameter count mismatch" in QSQLite [duplicate]

I am using quite a lot of parameterized queries in my code for performance reasons. In short, some of them work, some don't.
I initialize the query during construction of my database wrapper like this:
QString querystring = QString("SELECT somevalue FROM sometable "
"WHERE one_feature = :one_feature AND other_feature = :other_feature ");
myquery = QSqlQuery(db);
myquery.setForwardOnly(true);
myquery.prepare(querystring);
myquery is a QSqlQuery member variable of my database wrapper. Later on, in the function that wants to use this query, I do something like
int db_wrapper::fetch_some_value (int arg1, int arg2) {
myquery.clear();
myquery.bindValue(":one_feature", arg1);
myquery.bindValue(":other_feature", arg2);
qDebug() << "Bound values: " << myquery.boundValues();
bool OK = myquery.exec();
if (!OK) {
int number = myquery.lastError().number();
qDebug() << "db error " << number;
qDebug() << "db error " << myquery.lastError().text();
#ifdef USE_EXCEPTIONS
throw "Could not fetch some_value!";
#endif
}
// process data...
}
I always get the same error message/output:
Bound values: QMap((":one_feature", QVariant(int, 1) ) ( ":other_feature" , QVariant(int, 1) ) )
db error -1
db error " Parameter count mismatch"
terminate called after throwing an instance of 'char const*'
The exception is not surprising, but the parameter count mismatch is. The call to boundValues actually shows the right values and all, still I get this error message. I have similar queries that work just fine.
I tried substituting positional bind values, renamed the placeholders, used ? and positional bind values, all to no avail. Does anyone have an idea what the problem might be?
I use Qt 4.7.3 and SQLite 3.7.4-2
Usually this error means that the SELECT/UPDATE query itself is incorrect. You did not give the schema of the database so it's not possible to pinpoint which one. So one or more of somevalue, sometable, one_feature, or second_feature is not in the database/table.

Why Isn't find_one working in MongoDB C++?

I have a MongoDB 3.0.7 database, created with the mongo shell. The following works fine:
% mongo test
> vs = db.myCollection.findOne({"somefield.subfield": "somevalue"})
but when I do this in C++:
mongocxx::instance inst{};
mongocxx::client conn{};
auto db = conn["test"];
bsoncxx::stdx::optional< bsoncxx::document::value> docObj;
try {
docObj =
db["myCollection"]
.find_one(document{} <<
"somefield.subfield" << "someValue" <<
bsoncxx::builder::stream::finalize);
} catch (mongocxx::exception::operation e) {
std::cerr << "Retrieval failed (and exception thrown)";
}
if (docObj == bsoncxx::stdx::nullopt)
std::cerr << "Failed to find object";
I get "Failed to find object". What am I missing here?
Update: 11/23/2015, 10:00
I've installed the latest cxx driver (0.3.0), and made the following changes:
mongocxx::instance inst{};
mongocxx::client *connPtr;
bsoncxx::stdx::string_view connectionString("mongodb://localhost");
connPtr = new mongocxx::client(mongocxx::uri(connectionString));
auto db = connPtr->database("test");;
bsoncxx::stdx::optional< bsoncxx::document::value> docObj;
try {
docObj =
db["myCollection"]
.find_one(document{} <<
"somefield.subfield" << "someValue" <<
bsoncxx::builder::stream::finalize);
} catch (mongocxx::exception::operation e) {
std::cerr << "Retrieval failed (and exception thrown)";
}
if (docObj == bsoncxx::stdx::nullopt)
std::cerr << "Failed to find object";
I'm back to exactly the same thing. Calling db.list_collections(document{}) retrieves no results.
The bsoncxx library has two document types, views and values. A document::value contains the actual document data, and a document::view is just a reference to some underlying value. Values must outlive the views that use them.
There's a bug in the new c++11 driver with how document::values are passed around. This code produces a document::value :
document{} << "someField" << "someValue" << finalize;
The collection.find_one() method takes a document::view, and document::values convert implicitly to document::views. Unfortunately, this means if you dynamically build a document in your call to find_one(), as above, you can shoot yourself in the foot:
collection.find_one(document{} << "someField" << "someValue" << finalize);
finalize makes a temporary document::value, then find_one converts that to a document::view. The temporary value is dropped on the floor, leaving your view value-less, like a dangling pointer.
A workaround is to make your value in a separate call, and keep it around:
document::value doc = document{} << "someField" << "someValue" << finalize;
collection.find_one(doc.view());
I suspect this is what's causing your queries to fail; if not, it's something to make your code resilient to nonetheless!
You can track this ticket for the real fix for this problem.

MySQL call procedure with output parameter from C++ mysqlpp

I need help with the C++ mysqlpp driver calling a stored procedure and retrieving its output parameter. The queries seem to pass successfully but trying to get the stored value causes segmentation fault. My current pseudo code is:
mysqlpp::Connection* connection; // the connection type I am bound to use, no createStatement, prepareStatement methods
Query query = connection->query();
Query transactionQuery = connection->query();
query << "CALL sp_get_transactions_count(" << inputId << ", #transactionsCount);";
transactionQuery << "SELECT #transactionsCount as combinations;";
ClearQuerySentry cleanUpQuery(transactionQuery);
query.exec();
mysqlpp::StoreQueryResult transactionsResult = transactionQuery.store();
if (!transactionsResult || transactionsResult.num_rows() == 0)
{
logWarning(....);
}
else
{
const mysqlpp::Row& transactionRecord = result[0];
environment.pairTransactionsCount = verboseLexicalCast<int>(transactionRecord, "combinations"); // segfault on trying to cast static_cast<const char*>(row[fieldName.c_str()]))
}
I am not very experienced with mysqlpp and MySQL as a whole so it is possible my perception of the solution to be wrong. Thanks in advance.

How Can I Call PL/pgSQL Function From C++ Code

I am trying to call a function which is declared in PostgreSQL with PL/pgSQL. For that I write the code below. My function is working but after that I am taking a "PGRES_FATAL_ERROR". Also when I changed "select removestopwords()" with an sql query like "DELETE * FROM TABLE1" it's working successfully.
I am considering, that error can cause some big problem in future even if now working. How can I call a PL/pgSQL function without taking error?
void removeStopWordsDB(PGconn* conn) {
PGresult *res = PQexec(conn, "select removestopwords()");
if (PQresultStatus(res) != PGRES_COMMAND_OK) {
printf("removestopwords failed");
cout<<PQresultStatus(res);
PQclear(res);
exit_nicely(conn);
}
printf("removestopwords - OK\n");
PQclear(res);
}
If you get PGRES_FATAL_ERROR from PQresultStatus you should use PQresultErrorField to get all the error data from the result set to provide a useful error message. This will allow you to determine what the actual error is here (quite likely an error being sent over from the server).
Consider creating a class to hold PostgreSQL error details that can be constructed from q PQresult pointer, e.g.:
PgError(const PGresult *rs)
{
severity = GetErrorField(rs, PG_DIAG_SEVERITY);
sqlstate = GetErrorField(rs, PG_DIAG_SQLSTATE);
primary = GetErrorField(rs, PG_DIAG_MESSAGE_PRIMARY);
// ...
}
static std::string GetErrorField(const PGresult *rs, int fieldCode)
{
const char *message = PQresultErrorField(rs, fieldCode);
if (message == NULL) return "";
return std::string(message);
}
Then you can, for example, encapsulate dumping out the error to a stream in this object to provide details just like psql and friends do (although strictly speaking, you'd need the input SQL as well for all of that)
PostgreSQL API doesn't support some flag like "ignore all errors". If you would to ignore result, then just don't check result in host environment. But it is bad strategy.