Get bigint from Microsoft SQL Server with SOCI - c++

I am trying to get a bigint value (named "NUM" in my example) that comes from my database (Microsoft SQL Server). In the following code, I am trying to get it as an int even if I know that an int is smaller than a bigint but the cast always fails. I also tried to get it as a long long int and as some other types of variable but I am always getting the same problem at runtime as shown below.
try
{
session sql(odbc, "...");
rowset<row> rs = (sql.prepare << "SELECT MAX(NUM) AS MAX_NUM FROM T1");
for (rowset<row>::const_iterator it = rs.begin(); it != rs.end(); ++it)
{
row const& row = *it;
cout << "MAX_NUM: " << row.get<int>("MAX_NUM") << endl;
}
}
catch (exception const &e)
{
cerr << "Error: " << e.what() << '\n';
}
I have also tried the following getters:
cout << "MAX_NUM: " << row.get<long>("MAX_NUM") << endl;
cout << "MAX_NUM: " << row.get<long long>("MAX_NUM") << endl;
cout << "MAX_NUM: " << row.get<long long int>("MAX_NUM") << endl;
All my tests print the same error when I run my application:
Error: std::bad_cast
My question is : What is the correct way to get this value ?

I don't know if it is the best solution but it is the only one I found that works:
cout << "MAX_NUM: " << row.get<double>("MAX_NUM") << endl;

Related

Class private member wont change in function

using namespace std;
class map
{
private:
float result= 0;
public:
void func_1();
void setres(float counter);
float getres();
};
void map::setres(float counter)
{
result= counter;
}
float map::getres()
{
return result;
}
void map::func_1()
{
float num_0=0, num_1=0, sum=0, i;
map run;
cout << run.getres() << " Result." << endl;
if(result != 0)
cout << "We already have a result saved and it's: " << run.getres() << endl;
else
{
cout << "Give me first number: ", cin >> num_0;
cout << "Give me second number: ", cin >> num_1;
sum= num_0+num_1;
cout << "Result is: " << sum << endl;
}
cout << "The program will save the result." << endl;
run.setres(sum);
cout << "The saved result is: " << run.getres() << "\nPress 1 to repeat the function and check\nif the result is saved." << endl;
cin >> i;
if(i==1)
run.func_1();
}
int main()
{
map go;
go.func_1();
return 0;
}
I don't know why the private variable result is not saved. And how can i make it work.
Then i start compiling it works fine, private result is changing, but then i reopen the function, the result is back to 0 and i wanted it ro be the last result.
Example:
I put 4
I put 7
Sum is 11
And saved result is 11
Then i press 1 to go to the start the result is 0 again, but i wanted it to be 11 not 0.
Within the function you are creating a local variable of the type map
map run;
the data member result of which is changed. That is the function does not change the data member result of the object for which the function is called.
Moreover for example in this code snippet
cout << run.getres() << " Result." << endl;
if(result != 0)
you are accessing the data member result of two different object. In the first statement
cout << run.getres() << " Result." << endl;
you are accessing the data member of the local object run while in the next statement
if(result != 0)
you are accessing the data member result of the object (the object go declared in main) for which the member function is called.
So remove the declaration in the function
map run;
and instead of expressions like for example run.getres() use either just getres() or this->getres().
The issue is that your function is not using members of the object the method is called on. Instead you create a new instance inside the function:
void map::func_1()
{
float num_0=0, num_1=0, sum=0, i;
map run; // <---------- here
//...
Thats why every time you call the function you get a new fresh object. You do not need to create that instance. You already create one in main and inside the member functions you can access its members. As a fix you can remove all run. from the code. Eg
cout << run.getres() << " Result." << endl;
->
cout << getres() << " Result." << endl;
or if you prefer
cout << this->getres() << " Result." << endl;
The value is saved to run, and run.func_1() is called for checking, but then run.getres() is called there. This run is new map object and differ from the run in which the data is saved.
You checked result != 0, but you used run.getres() to print the result. Inconsisitency here.
Instead of
cout << run.getres() << " Result." << endl;
if(result != 0)
cout << "We already have a result saved and it's: " << run.getres() << endl;
You should do
cout << result << " Result." << endl;
if(result != 0)
cout << "We already have a result saved and it's: " << result << endl;
or
cout << getres() << " Result." << endl;
if(getres() != 0)
cout << "We already have a result saved and it's: " << getres() << endl;

C++ program freezes with 100% CPU in the middle of cout statement

I'm writing a simple graph generator that stores the graphs in a MySQL database.
Here's the output:
Connecting to database...Success!
Checking for unfinished vertices...Completed last n = 7
Creating n8 table...Success!
Notice it doesn't print "Generating..." which is part of the same statement. It freezes just like this with 100% CPU. The table does actually get created in the database.
Also, If I start from n = 1, it runs until n7 and then freezes.
Here's the code (not the entire thing, just this part):
int main()
{
int n = 0;
if (initialize(n)) {
int limit = 8;
if (limit >= n) {
for (; n <= limit; n++) {
stringstream qs;
qs << "CREATE TABLE n" << n << " (idbin TEXT("
<< getLengthOfBinaryByN(n) << ") NOT NULL,vertices INT NOT NULL)";
cout << "Creating n" << n << " table...";
if (runQuery(qs.str())) {
cout << "Success!" << endl
<< "Generating all graphs on " << n << " vertices";
generateGraphs(n);
} else {
cout << "Failed!" << endl;
}
}
} else {
cout << "ERROR: Must be greater than or equal to " << n << endl;
return 1;
}
}
return 0;
}
After some research I found that a "deadlock" may be occurring, but I have no idea how to fix that. Any ideas?
Here's the runQuery function if that helps:
/*
runQuery: runs the sql query, assumes that database connected successfully
Parameters: query
returns a bool
*/
bool runQuery(string query)
{
try {
stmt = con->createStatement();
res = stmt->executeQuery(query);
delete stmt;
} catch (sql::SQLException &e) {
if (e.getErrorCode() != 0 && e.getErrorCode() != 1050) {
cout << "# ERR: SQLException in " << __FILE__
<< "(" << __FUNCTION__ << ") on line " << __LINE__ << endl
<< "# ERR: " << e.what()
<< " (MySQL error code: " << e.getErrorCode()
<< ", SQLState: " << e.getSQLState() << " )" << endl;
return false;
}
return true;
}
return true;
}

Accessing array pointer in Header file?

By attempting to access the TCPSocket inside my "clientArray" I get a Access Violation error. How would I access it properly?
My header file holds the TCPSocket *clientArray.
public:
TCPsocket *clientArray;
SDLNet_SocketSet aSocketSet;
bool serverOn;
It is defined within my constructor:
clientArray = new TCPsocket[maxsockets];
aSocketSet = SDLNet_AllocSocketSet(maxsockets);
It is accessible within another function of mine (it works here without issue):
void ServerSocket::waitingForConnection() {
std::cout << '\r' << flush << "Players connected: " << playersConnected << ". Listening for connection... ";
TCPsocket newsocket = SDLNet_TCP_Accept(serverSocket);
SDL_Delay(1000);
if (!newsocket){
//std::cout << '\r' << flush << "Listening for connection. ";
//std::cout << SDLNet_GetError() << std::endl;
}
else{
std::cout << '\r' << flush << "Socket (client " << slotnum + 1 << ") created successfully. " << std::endl;
clientArray[slotnum] = newsocket;
int n = SDLNet_TCP_AddSocket(aSocketSet, newsocket);
if (n < 0){
std::cout << "Client " << slotnum + 1 << " failed to connect. " << std::endl;
}
else{
char text[10];
std::cout << "Client " << slotnum + 1 << " added to client array successfully." << std::endl;
serverMessage(slotnum, "2 You are successfully connected to the server.");
std::cout << "Sent connection validation to Client " << slotnum + 1 << "." << endl;
std::cout << "Allocating player " << slotnum + 1 << " with player number ." << endl;
serverData(slotnum, '5', slotnum+1);
//ACCESSING IT HERE WITHOUT ISSUE
SDLNet_TCP_Recv(clientArray[slotnum], text, 10);
std::cout << "received text = " << text << endl;
interpretData(text);
slotnum++;
}
//SDLNet_TCP_Close(newsocket);
//SDLNet_TCP_Close(serverSocket);
//code here
}
}
However later on when I try to access it via another function, I get an Access Violation Error :
Unhandled exception at 0x00AED839 in Server.exe: 0xC0000005: Access violation reading location 0x0000000C.
I am calling the problematic function from my Game's Update function as following:
void Game::Update(){
while (g_playersConnected == 2)
{
printGrid();
serverSocket->waitForPlayer((playerTurn-1));
changeTurn();
system("pause");
}
//cout << "Game's Update is running" << endl;
};
This is my other function that is attempting to access the array :
void ServerSocket::waitForPlayer(int playerNum)
{
cout << "Waiting for player " << playerNum + 1 << " (In array : " << playerNum << ")." << endl;
char text[10];
SDLNet_TCP_Recv(clientArray[playerNum], text, 10);
std::cout << "received text = " << text << endl;
interpretData(text);
}
I have not set up Copy constructors or assignment operators and my destructors are just empty blocks at the moment.
ServerSocket::~ServerSocket(){}
Which direction should I go towards solving this issue?
All the best

Mongodb C++ driver, failure at cleanup

I have a small program that tries to connect to mongodb and check how many objects it would receive if I could hope to receive objects. In the event, I can't even get a count of objects, and I segfault on cleanup even if I do nothing but connect.
I'm using the GlobalInstance object to maintain my connection and clean up for me at exit. This function I call from main. The program doesn't really do anything else yet.
Any suggestions on what I'm doing wrong that I segfault? Presumably this is related to not being able to call connection->count()?
Many thanks for any pointers.
int foo() {
mongo::client::Options options;
options.setSSLMode(mongo::client::Options::kSSLRequired);
mongo::client::GlobalInstance mongo_connection(options);
mongo::DBClientBase* connection;
if (!mongo_connection.status().isOK()) {
cout << "Mongo connection not established: "
<< mongo_connection.status() << endl;
}
try {
mongo::DBClientConnection c(true);
string error;
ostringstream mongo_url;
mongo_url << "mongodb://" << db_username << ":" << db_password << "#"
<< db_host << ":" << db_port << "/" << db_name;
const mongo::ConnectionString conn_string =
mongo::ConnectionString::parse(mongo_url.str(), error);
if (!conn_string.isValid()) {
cout << "Bad connection string: " << error << endl;
}
// Reality check. Passes.
cout << "user=" << conn_string.getUser() << endl;
cout << "pass=" << conn_string.getPassword() << endl;
cout << "db= " << conn_string.getDatabase() << endl;
const auto servers = conn_string.getServers();
for (const auto& server : servers) {
cout << "serv=" << server << endl;
}
cout << "type=" << conn_string.type() << endl;
// End reality check.
connection = conn_string.connect(error);
cout << "error says: " << error << endl; // Is empty.
cout << "conn=" << connection << endl; // Not zero.
std::cout << "connected ok" << std::endl;
cout << connection->getConnectionId() << endl; // Prints "1".
// This returns an error 13, not authorized, if I included it.
//cout << "count: " << connection->count("focus_groups") << endl;
} catch( const mongo::DBException &e ) {
std::cout << "caught " << e.what() << std::endl;
}
cout << "----------------------------------------------------------------------" << endl;
return 0;
}
/*
Note that I can do this in the mongo shell with no problem:
jeff#siegfried:~ $ mongo my_host:27017/my_db --ssl -u my_user -p
MongoDB shell version: 2.6.3
Enter password:
connecting to: my_host:27017/my_db
> db.focus_groups.count()
26
>
*/
I am running on 64 bit ubuntu 15.04 and compiling with clang 3.6.0. Boost is 1.55 installed via apt-get. The legacy mongo C++ driver I compiled and installed from git at HEAD (861699d116627d63e1c914384a66e4e3ea7c23bc) with ssl support.
This turned out to be a confluence of several things, but at least these two:
When I compiled the legacy driver, the default mode is C++03, which is not binary compatible with C++11 or C++14.
The driver is sensitive to differences in the version of boost with which it and the client using it are compiled.
An extensive thread appears here.

How can I delete a element from a vector?

I'm developing a simple console based email application.
In my app, messages are stored in std::vector, and I want to add possibility to delete messages.
How can I delete a element from a vector?
Here's my code:
//MAIN MENU OPTION 1 SELECTED:
// print list of all messages to the console
void viewInbox() {
vector<Message> inbox{
Message("jayleno#hotmail.com", "Knife you tonight", "Hey Sam, what kind of suit do you wanna be buried in?!"),
Message("paypalservices#hotmail.com", "Urgent from paypal.com", "Dear paypal user, someone has hacked your account. Give us your password now so we change it!"),
};
cout << "You have " << inbox.size() << " new messages.\n";
cout << "Index Subject" << '\n';
for (int i = 0; i < inbox.size(); ++i)
std::cout << "Message " << i << ": " << inbox[i].getSubject() << '\n';
cout << "Please enter number of message you would like to view\n";
int read;
cin >> read;
cout << "From: " << inbox[read].getAddress() << '\n';
cout << "Subject: " << inbox[read].getSubject() << '\n';
cout << inbox[read].getMessageText() << '\n';
cout << "To erase this message press 1\n";
//Code here for deleting a message...
}//end of viewInbox()
To erase a message from the vector use vector::erase which takes an iterator.
The easiest way to get an iterator to a particular message is to use inbox.begin() + message_number.
I have refactored your code into smaller functions to make the code easier to work with:
void viewMessage(vector<Message>& messages, size_t message_number) {
vector<Message>::iterator message = messages.begin() + message_number;
cout << "From: " << message->getAddress() << endl;
cout << "Subject: " << message->getSubject() << endl;
cout << message->getMessageText() << endl;
cout << "To erase this message press 1\n";
int erase;
cin >> erase;
// Maybe do some error checking on cin...
if (erase == 1) {
messages.erase(message);
}
}
void viewMessages(vector<Message>& messages){
auto inbox_size = messages.size();
cout << "You have " << inbox_size << " new messages.\n";
cout << "Index Subject" << '\n';
for (size_t i = 0u; i != inbox_size; ++i) {
std::cout << "Message " << i << ": " << messages[i].getSubject() << '\n';
}
cout << "Please enter number of message you would like to view\n";
size_t message_number;
cin >> message_number;
// Maybe do some error checking on cin...
// And some bounds checking of message_number...
viewMessage(messages, message_number);
}
void viewInbox() {
vector<Message> inbox{
Message{ "jayleno#hotmail.com", "Knife you tonight", "Hey Sam, what kind of suit do you wanna be buried in?!" },
Message{"paypalservices#hotmail.com", "Urgent from paypal.com", "Dear paypal user, someone has hacked your account. Give us your password now so we change it!"},
};
viewMessages(inbox);
// Maybe call viewMessages again to see results of erase...
}
As I have commented, watch out for error checking on your input.