Proper error handling for OCCI C++ library - c++

I want to understand how should I correctly handle exceptions in OCCI C++ library (https://docs.oracle.com/database/121/LNCPP/relational.htm#LNCPP003).
Below is simple example of creating connection, statement and executing statement.
Environment *env = Environment::createEnvironment();
Connection *conn = env->createConnection(
userName, password, connectString);
Statement *stmt = conn->createStatement(
"SELECT blobcol FROM mytable");
try {
stmt->execute();
} catch (oracle::occi::SQLException &ex) {
// what to do here?
}
My questions are:
Is there a standardized way to handle occi::SQLException? In perfect world I want to know on which exceptions I can safely just retry my stmt->execute and have a possibility to get successful result. I figured out that occi::SQLException has a member is SQLException::isRecoverable(), does it mean I can just retry on all these recoverables errors without reconnect etc.? Is there a documented list of this recoverable errors?
How to know if connection lost? Is there a known list of sql codes for lost connection case?
If connection lost what is the correct way to recover? Should I get rid of old Connection object and create new connection with env->createConnection and hence I have to recreate all statements using new connection? Or maybe I should just retry executing my statements and connection with automatically recover inside OCCI driver library?

Related

Failed to establish connection to MySQL database in C++

I have recently tried to make a connection to my SQL database in C++ using QSqlDatabase. Here is a small part of my code.
void guimain::on_pushbutton_clicked(){
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
db.setHostName("tcp://127.0.0.1:3306");
db.setDatabaseName("MyDatbase");
db.setUserName("username");
db.setPassword("password");
bool connected = db.open();
cout<< connected\n;
}
everytime i run the program it prints connected as 0 meaning it has not connected to the database. I have double checked the correctness of the password, username, database and everything else. What else could be the problem?
Perhaps you're suppressing errors?
cout<< connected\n;
should be
cout<< "connected\n";
or, if you meant to output the string "connected" if a connection has been made:
cout<< connected ? "connected\n" : "failed to connect\n";
And putting the former should have resulted in an error being outputted.
Also you put the name as "MyDatbase" which seems like you misspelt "MyDatabase".
Edit: Not sure why I'm getting downvoted. You told us that you got no errors but I see a clear syntax error, so either you're not being truthful or you're suppressing errors. Suppressing errors is bad practice - avoid it. As for why it actually fails to connect, it seems like you've misspelt the database name, as I said above.

Implementing a client connection function that waits for the server in capnproto

I'm trying to implement in capnproto something like boost's connect function which blocks and retries until the server is up, or basic_socket::async_connect that lets me implement a callback with which to try connecting once more.
For example, running this code:
auto ioContext = kj::setupAsyncIo();
auto address = ioContext.provider->getNetwork()
.parseAddress("localhost:7500").wait(ioContext.waitScope);
auto connection = address->connect().wait(ioContext.waitScope);
Would obviously throw an exception if the server is down.
So my questions are:
Is there a way to register a callback that will handle
connection/failure to connect?
Is there a built in mechanism in capnproto that already enables automatic
reconnection?
There isn't anything built-in for this, but you could implement it fairly easily like so:
kj::Promise<kj::AsyncIoStream> keepTryingConnect(kj::NetworkAddress& addr) {
return addr.connect().catch_(
[&addr](kj::Exception&& e) -> kj::Promise<kj::Own<kj::AsyncIoStream>> {
if (e.getType() == kj::Exception::Type::DISCONNECTED) {
// Try again.
return keepTryingConnect(addr);
} else {
// Propagate error.
return kj::mv(e);
}
});
}
Note that the DISCONNECTED exception type is a catch-all for any type of transient network error, and is explicitly intended for this kind of purpose.
As for reconnecting on disconnect: The system cannot do this automatically, because Cap'n Proto won't know whether it's safe to retry in-flight requests and won't know how to rebuild any capabilities that were present on the connection. What you need to do is find places in your application where it makes sense to catch the DISCONNECTED exception type and then retry, much like in the code above.

Mysql Connector connect() issues

I have a small C++ project and need to access a mySQL DB from it, so i have setup mySQL Connector for C++.
This is done on OS X 10.10, and i got no problems with the compilation/linking.
I have written a class for all the mysql stuff, and in the constructor i want to setup the connection to the db. However, this seems to be kinda hard.
Here is the relevant part from the class:
class mysql{
public:
mysql(std::string server, std::string user, std::string password);
private:
sql::mysql::MySQL_Driver *driver;
sql::Connection *con;
std::string last_error = "";
};
And here the implementation:
mysql::mysql(std::string server, std::string user, std::string password){
driver = sql::mysql::get_mysql_driver_instance();
try{
con = driver->connect(server, user, password);
last_error = "";
}
catch(sql::SQLException &e){
last_error = e.what();
}
}
However, when i create an object of that class like this:
mysql db("tcp://127.0.0.1:3306", "root", "secretsecret");
I then have this in my last_error string:
Unknown MySQL server host '???' (0)
The "host" sometimes differs even tho i dont change it in code. This seems like internally a different memory location is read out as it should be.
But even if i pass the connect() variables directly when i call it, i get this error. Same when saving those three variables internally in the mysql class and use those to call connect().
Anyone has an idea what could cause this? I have a similar implementation in a different project where this does work fine so im kinda confused :/
Here is a post that matches to your circumstances (The C++ connector works on linux and fails on OSX).
With using mysql logging/tracing or running it in debugger, you may be able to gather more information to report to mysql developers. You may have better luck.
After a long time of googeling i found this the most useful link: https://apple.stackexchange.com/questions/251290/weird-behaviour-of-mysql-connector-c-in-osx
Following the hints there, i recompiled the myscl c connector and then the mysql c++ connector (version 1.1.6 cause 1.1.7 caused a json error while compiling).
I also saw in the cmake logs of the c++ connector that Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ was used to compile the library.
So i used that one too for my compilation. It could be that this would work, tho im also including wxwisgeds in my project resulting in this error:
/usr/local/include/wx-3.0/wx/strvararg.h:30:18: fatal error: 'tr1/type_traits' file not found
#include <tr1/type_traits>
I found some hints for that one but they all just produced a massiv amount of new errors, so i stopped digging deeper here.
My best options would be to create two seperate programs, on to communicate with mysql and one to provide the gui and let them both communicate with each other either via sockets or files providing a very inefficient access to a mysql db.
Good luck to anyone who runs into the same thing..

How to close the ADO connection if the database connection fails while inside a transaction

I am using ADO via C++, and let's suppose that I have begun a transaction via ADO when the connection drops out.
I wish to abandon my database changes and close my ADO database connection object, in order to return to another code module which can display an error message (without leaving this module in a dodgy state).
The problem is:
1) I cannot close the database connection because the error adErrInTransaction (0x800a0cae) is thrown (connection object cannot be explicitly closed while in a transaction)
2) I cannot rollback the transaction because the error 0x8000ffff is thrown (catastrophic failure, .... connection failure)
This appears to be a catch 22 situation. Had it been that the transaction was not started then calling Close on the ADO connection succeeds, but unfortunately with the transaction open I appear to be stuck!
Is the only solution to record the fact that it's failed within a transaction, so that when the database connection is restored, I can complete the rollback before attempting anything else?
This was tested with SQLServer 2008 if it's relevant, though I don't really want a SQLServer-specific solution.
Well, didnt do this in a long time but:
1) you have to start your transaction with db.BeginTransaction(); and not with BEGIN TRANSACTION ( http://support.microsoft.com/kb/198024/en-us )
2) simply kill the transaction when you notice your connection went down
via:
SqlConnection db = new SqlConnection("ado...");
SqlTransaction transaction;
db.Open();
transaction = db.BeginTransaction();
//..........
// stuff here
//..........
if ( connGone ) {
transaction.rollback();
db.close(); }

disconnecting from mongoDb with C++ driver

i'm sure this must be really simple or i'm missing the point, but how do you disconnect from Mongo using the C++ driver and DBClientConnection? DBClient has a public member of 'connect' but no disconnect/kill/drop etc that I can find.
There is some talk (in stack overflow and on the web) of using ScopedDBConnection which does seem to be able to allow me to drop my connection - but there are very few examples of how it would be used - or info on when I should use that class over the DBClientConnection class.
Any ideas?
If you're using a DBClientConnection, it has one connection, and you aren't supposed to disconnect/reconnect. I guess it kills the connection when it calls the destructors. You can set it up to automatically reconnect so you can keep using it if it loses its connection.
If you want to have connection pooling and multiple connections, you want to use ScopedDBConnection. You can see some examples here: https://github.com/mongodb/mongo/blob/master/src/mongo/client/model.cpp
Here's the gist:
ScopedDbConnection conn("localhost");
mongo::BSONObjBuilder obj;
obj.append( "name" , "asd" );
conn->insert("test.test", obj);
conn.done();
Basically, you can do anything with conn that you can do with a DBClientConnection, but when you're done you call done().