MySQL C++ Connector: How do I get the thread/connection Id? - c++

I'm trying to find out how to obtain the MySQL Connection/thread id using Connector C++.
mysql_thread_id(MYSQL* ) seems to be available for just this, but I'm not sure how to get an instance of MYSQL from the Connector C++.
What I've tried:
int threadId = mysql_thread_id(NULL);
But this just returns zero.
Any ideas?

The function mysql_thread_id() expects a pointer to a connection object created by the native MySQL C API's mysql_connect(...) function. Connector/C++ has buried that object very deep (I looked). The alternative suggested by MySQL's documentation here is to execute query SELECT CONNECTION_ID() and the returned result will be the ID you're looking for.

Related

C++ Poco ODBC Transactions - AutoCommit mode

I am currently attempting to use transactions in my C++ app, but I have a problem with the ODBC's auto commit mode.
I am using the POCO libaries to create a connection to a PostgreSQL database on the same machine. Currently, I can send data to this database as single statements, but I cannot get my head around how to use Poco's transaction libraries to be able to send this data more quickly.
As I have several thousand records to insert, and so continuing to use single insert statements is extrememly slow and inpractical - So I am trying to use Poco's transaction to speed this up a bit (a fair bit).
The error I am encountering is a theoretically a simple one - Poco is throwing the following error:
'Invalid access: Session is in auto commit mode.'
I understand, as a result of this, I should somehow set "auto commit" to false - as it only allows me to commit data to the database line by line, rather than as a single transaction.
The problem is how I set this.
Currently, I have a session created from Session.h, that looks alot like this:
session = new Poco::Data::Session(
"ODBC",
connection_data.str()
);
Where connection data is a simple stringstream with the login information, password, database, server and "Driver={PostgreSQL ANSI};" to tell ODBC to utilize PostgreSQL's driver.
I have tried just setting a property "autocommit" to false through the session's setFeature or setProperty settings, this, of course, was to no avail. (it was more of a ditch attempt at this point).
session->setFeature("AUTOCOMMIT", false);
Looking around, I saw a possible alternative method by creating a ODBC sessionImpl directly from ODBC/session/SessionImpl.h instead of using this generic method above, and then creating a new session object from this.
The benefits of this are that ODBC's sessionImpl has references to autocommit mode in the header, which would suggest it would be able to handle this:
void autoCommit(const std::string&, bool val);
/// Sets autocommit property for the session.
However, having not used sessionImpl before, I cannot garuntee if this will work or if can can get this to work with the limited documentation available.
I am using C++ 03 (Not 11), with Visual Studio 2015
Poco 1.7.5
Boost (Where needed)
Would any one know the correct way of setting this feature (above) or a alternative method to achieving this?
edit: Looking at the source of poco, at:
https://github.com/pocoproject/poco/blob/develop/Data/ODBC/src/SessionImpl.cpp#L153
The property seems be named autoCommit, and looking at
https://github.com/pocoproject/poco/blob/develop/Data/include/Poco/Data/AbstractSessionImpl.h#L120
the case of the property names seem to matter. So, does it help if you use session->setFeature("autoCommit", false);?
Cant you just call session->begin(); and session->end(); on the corresponding Session object?
What is returned by session->canTransact()?
According to the doc begin() will start a new transaction, the doc does not mention any property that needs to be set before or after.
See: https://pocoproject.org/docs/Poco.Data.Session.html
Also faced a similar issue.
First of all before begin() need:
m_ses.setFeature("autoCommit", false);
m_ses.begin();
And the second issue is that this feature stays "autoCommit" in false for all other sessions. So don't forget for the next session call
session.setFeature("autoCommit", true);

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..

SQL Server Table-Valued Parameters in c++ OLEDB client?

I have an c++ application working ith SQL Server via OLEDB.
How to use table-valued parameters in old good unmanaged c++ OLEDB clients?
In NET app it is clear how to :
SqlParameter param = new SqlParameter("#Customers", dataTable);
param.SqlDbType = SqlDbType.Structured;
cmd.Parameters.Add(param);
// Execute the command
SqlDataReader rdr = cmd.ExecuteReader();
How to pass this kind of parameters calling stored procedures in c++ oledb client app?
Here's an example of doing it using ADO, is that what you're looking for? http://msftdpprodsamples.codeplex.com/wikipage?title=SS2008%21Readme_Table-Valued%20Parameters&referringTitle=Home

c++ driver mongodb connection options

It seems that c++ drivers doesn't accept mongodb connection uri format.
There's no documentation on how i should create connection string, any guess?
I need to connect to a replica set with 3 servers, and set readPreference options.
Create a connection to a replica set in MongoDB C++ client
Until the problems explained in #acm's answer are resolved, I have found a workaround to the bad Connection Strings of the C++ driver. You can create a DBClientReplicaSet using a vector of hosts and ports this way:
//First create a vector of hosts
//( you can ignore port numbers if yours are default)
vector<HostAndPort> hosts;
hosts.push_back(mongo::HostAndPort("YourHost1.com:portNumber1"));
hosts.push_back(mongo::HostAndPort("YourHost2.com:portNumber2"));
hosts.push_back(mongo::HostAndPort("YourHost3.com:portNumber3"));
//Then create a Replica Set DB Client:
mongo::DBClientReplicaSet connection("YourReplicaSetName",hosts,0);
//Connect to it now:
connection.connect();
//Authenticate to the database(s) if needed
std::string errmsg;
connection.auth("DB1Name","UserForDB1","pass1",errmsg);
connection.auth("DB2Name","UserForDB2","pass2",errmsg);
Now, you can use insert, update, etc. just as you did with DBClientConnection. For a quick fix, you can replace your references to DBClientConnection with DBClientBase (which is a parent to both DBClientConnection and DBClientReplicaSet)
Last pitfall: if you are using getLastError(), you must use it with the aimed database name like this:
connection.getLastError(std::string("DBName"));
cause otherwise it will always return "command failed: must log in" as described in this JIRA ticket.
Set the read preferences for every request
You have two ways to do that:
SlaveOK option
It lets your read queries be directed to secondary servers.
It takes place in the query options, which are at the end of the parameters of DBClientReplicaSet.query(). The options are listed in Mongo's official documentation
The one you would look for is mongo::QueryOption_SlaveOk, which will allow you to have reads made on secondary instances.
This is how you should call query();
connection.query("Database.Collection",
QUERY("_id" << id),
n,
m,
BSON("SomeField" << 1),
QueryOption_SlaveOk);
where n is the number of documents to return (0 if you don't want any limit), m the number to skip (defaults to 0), the next field is your projection and the last your query option.
To use several query option, you can use bitwise or | like this :
connection.query("Database.Collection",
QUERY("_id" << id),
n,
m,
BSON("SomeField" << 1),
QueryOption_SlaveOk | QueryOption_NoCursorTimeout | QueryOption_Exhaust);
Query::readPref option
The Query object has a readPref method which sets read preferences for a special query. It should be called for each query.
You can pass different arguments for more control. They are listed here.
So here's what you should do (I did not test that one cause I can't right now but it should work just fine)
/* you should pass an array for the tags. Not sure if this is required.
Anyway, let's create an empty array using the builder. */
BSONArrayBuilder bab;
/* if any, add your tags here */
connection.query("Database.Collection",
QUERY("_id" << id).readPref(ReadPreference_SecondaryPreferred, bab.arr()),
n,
m,
BSON("SomeField" << 1),
QueryOption_NoCursorTimeout | QueryOption_Exhaust);
Note: if any readPref option is used, it should override the slaveOk option.
Hope this helped.
Please see the connection string documentation for details on the connection string format.
(code links below are to 2.2.3 files)
To use a connection string with the C++ driver, you should use the ConnectionString class. You first call the ConnectionString::parse static method with a connection string to obtain a ConnectionString object. You then call ConnectionString::connect to obtain a DBClientBase object which you can then use to send queries.
As for read preference, at the moment I do not see a way to set the read preference in the connection string for the C++ driver, which would preclude a per-connection setting.
However, the implementation of DBClientBase returned by calling ConnectionString::parse with a string that identifies a replica set will return you an instance of DBClientReplicaSet. That class honors $readPreference in queries, so you can set your read preference on a per-query basis.
Since the current C++ drivers still do not accept the standard mongodb connection URIs, I've opened a ticket:
https://jira.mongodb.org/browse/CXX-2
Please vote for it to help get this fixed.
it seems like you can set read Preference before send a read request by call "readPref" method of your Query object. I'v not found a way to set read Preference on mongo collection object yet.

How to set "IN" values with mysql cpp connector

How does one to set the "IN" value for the following SQL statement :
UPDATE `test` SET `test`.`status` = 'foo' WHERE `test`.`id` IN (?);
Is that possible ? I looked in the headers and couldn't find anything related nor did I find anything in google nor stackoverflow.
Should I use the setBlob method ?
There is nothing in MySQL Connector API to handle such case.
But it shouldn't be mind blowing to work it around with a very simple for loop.
either you loop for each id and update atomically.
for each (id in your collection){
UPDATE `test` SET `test`.`status` = 'foo' WHERE `test`.`id` = (?);
}
or you call a direct statement that you custom-build (also with a for loop)...