structuring C++ program with mysql connections - c++

I'm trying to create a c++ program that connects to mysql and can perform operations on the database such as add remove and edit.
For each table, I want to be able to add, remove and edit as well as run specific querys to my needs.
So far, I have everything in a single main file as I cannot figure out how to divide up my code to have one connection, and then be able to call other classes to run querys.
I clearly a beginner in C++ and am looking for some input into what I should have in each class
#include <stdlib.h>
#include <iostream>
#include "mysql_connection.h"
#include "cppconn/driver.h"
#include "cppconn/exception.h"
#include "cppconn/resultset.h"
#include "cppconn/statement.h"
using namespace std;
int main(void)
{
cout << endl;
try {
sql::Driver *driver;
sql::Connection *con;
sql::Statement *stmt;
sql::ResultSet *res;
/* Create a connection */
driver = get_driver_instance();
con = driver->connect("tcp://127.0.0.1:3306", "root", "root");
/* Connect to the MySQL test database */
con->setSchema("ParkSmart");
stmt = con->createStatement();
res = stmt->executeQuery("SELECT * FROM user WHERE userID = 9");
while (res->next()) {
cout << res->getString(2) << endl;
// getInt(1) returns the first column
// ... or column names for accessing results.
}
//add person(int personID, string fname, string lname)
try
{
int personID = 9;
string fname = "test";
string lname = "man";
string query = "SELECT * FROM person WHERE personID = " + to_string(personID);
res = stmt->executeQuery(query);
if (res->next()){
cout << "A person with that" << endl;
return 0;
//failure, already exists
}
else {
string query = "INSERT INTO user (personID, fname, lname) VALUES (" + to_string(personID) + ", '" + fname + "', '" + lname + ")" ;
res = stmt->executeQuery(query);
return 1;
//success, user added in to database
}
}
catch (sql::SQLException &e) {
cout << "Exception caught: no query returned" << endl;
//this is when there is no user with that userID, continue
//check for other more specific errors
}
What I am thinking is a main that calls a person class that connects to mysql and for each table there is a class that has its own connection but I'm getting seg faults
The code that I have can connect and edit the database properly, I am just lost on the actual file structures.
Any help or advice is appreciated!

Related

having issues inserting data in Mysql from C++ in Linux

Can anyone help me get through just inserting a record with C++ in Linux using the #include<mysql.h> , i have tried almost everything possible , it works just fine making the columns static but cannot pass variables to them at all , even with a cin statement. tried using cin.get(char &ch): and also cin >> varname, why is this so difficult. ? what am i missing.
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <iomanip>
#include <stdio.h>
#include <time.h>
// For MySQL Connection
#include <mysql.h>
using namespace std;
int trollyid = 88232;
// Defining Constant Variables Future Revisions with be with reading a json File
#define SERVER "localhost"
#define USER "root"
#define PASSWORD "xxxxx"
#define DATABASE "txxxx"
int main()
{
MYSQL *connect;
connect = mysql_init(NULL);
auto time = std::time(nullptr);
int trollyid = 88232;
if (!connect)
{
cout << "Mysql Initialization Failed";
// Write XML log for failure
return 1;
}
connect = mysql_real_connect(connect, SERVER, USER, PASSWORD, DATABASE, 0,NULL,0);
if (connect)
{
cout << "Connection Succeeded\n";
}
else
{
cout << "Connection Failed\n";
}
MYSQL_RES *res_set;
MYSQL_ROW row;
// MySQL query with your query
// -- Need to pass variables into the two field '665566', 'GOOD')
mysql_query (connect,"INSERT INTO `Datalog` (`id`, `datecol`, `timecol`, `trolleyid`,
`status`) VALUES (NULL, NOW(), NOW(), '665566', 'GOOD')");
// update: table Datalog with data VALUES (NULL, NOW(), NOW(), '4444444', 'GOOD')");
res_set=mysql_store_result(connect);
// --------------Just showing tables on testing (Move
along)---------------------------------
// unsigned int numrows = mysql_num_rows(res_set);
// cout << " Tables in " << DATABASE << " database " << endl;
// while (((row=mysql_fetch_row(res_set)) !=NULL))
// {
// cout << row[i] << endl;
//}
std::cout
// ISO 8601: %Y-%m-%d %H:%M:%S, e.g. 2017-07-31 00:42:00+0200.
<< std::put_time(std::gmtime(&time), "%H:%M:%S") << '\n'
// %m/%d/%y, e.g. 07/31/17
<< std::put_time(std::gmtime(&time), "%D");
mysql_close (connect);
return 0;
}
// ** EXAMPLE **
// TEST INPUT to table:
char status[20];
cin >> nValue;
cin >> status;
cin.getline(status, sizeof(name)); //taking string input
// MySQL query with your query
mysql_query (connect,"INSERT INTO `Datalog` (`id`, `datecol`, `timecol`, `trolleyid`, `status`) VALUES (NULL, NOW(), NOW(), 'nValue', 'status')");
so here is the way it works now, can i put these back into an array ?
[code][1]

How can I connect to my SQL Database through C++?

I've seen some similar questions but most are based around PHP, there was one based around C but the only answer was go to the SQLConnect() docs, which I've already done.
https://learn.microsoft.com/en-us/sql/odbc/reference/syntax/sqlconnect-function?redirectedfrom=MSDN&view=sql-server-ver15
Seems to be little content online, also I'm a beginner so excuse any silly issues.
I set up the SQL database using the MYSQL Workbench and it's sitting on my localhost:3306. I was able to connect it to the ODBC Data Source Admin program successfully.
So I believe I'm using the right function and have the right SQL back end set up, I just don't know where to go from here.
The end goal is to be able to 'insert' records into my database with the program and also 'select' from it too.
What am I doing wrong, or what am I missing?
# include <stdio.h>
# include <stdlib.h>
# include <sql.h>
# include <sqlext.h>
# include <cstdio>
# include <cstdint>
using namespace std;
int main(){
SQLHENV henv = NULL;
SQLHDBC hdbc = NULL;
/* Initialize the ODBC environment handle. */
SQLAllocHandle(SQL_HANDLE_ENV, NULL, &henv);
/* Set the ODBC version to version 3 (the highest version) */
SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION,
(void*)SQL_OV_ODBC3, 0);
/* Allocate the connection handle. */
SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
SQLConnectW(hdbc, (SQLWCHAR*)"localhost", (SQLSMALLINT) 9,
(SQLWCHAR*)"root", (SQLSMALLINT)4,
(SQLWCHAR*)"password", (SQLSMALLINT)8);
return(0);
}
I have added the comments inside the code, which will help you to understand the code easily.
Credits: Link
/* Includes Standard C++ */
#include <stdlib.h>
#include <iostream>
/*
Include directly the different
headers from cppconn/ and mysql_driver.h + mysql_util.h
(and mysql_connection.h). This will reduce your build time!
*/
#include "mysql_connection.h"
#include <cppconn/driver.h>
#include <cppconn/exception.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>
using namespace std;
int main(void)
{
cout << endl;
cout << "Running 'SELECT 'Successfull' »
AS _message'..." << endl;
try {
sql::Driver *driver;
sql::Connection *con;
sql::Statement *stmt;
sql::ResultSet *res;
/* Create a connection */
driver = get_driver_instance();
con = driver->connect("tcp://127.0.0.1:3306", "root", "root");
/* Connect to the MySQL test database */
con->setSchema("test");
stmt = con->createStatement();
res = stmt->executeQuery("SELECT 'Successfull' AS _message"); // replace with your statement
while (res->next()) {
cout << "\t... MySQL replies: ";
/* Access column data by alias or column name */
cout << res->getString("_message") << endl;
cout << "\t... MySQL says it again: ";
/* Access column fata by numeric offset, 1 is the first column */
cout << res->getString(1) << endl;
}
delete res;
delete stmt;
delete con;
} catch (sql::SQLException &e) {
cout << "# ERR: SQLException in " << __FILE__;
cout << "(" << __FUNCTION__ << ") on line " »
<< __LINE__ << endl;
cout << "# ERR: " << e.what();
cout << " (MySQL error code: " << e.getErrorCode();
cout << ", SQLState: " << e.getSQLState() << " )" << endl;
}
cout << endl;
return EXIT_SUCCESS;
}

connecting to database in c++

In php I create a config file that opens a connection to the database and then I use that file in all my other files in order to open a connection also. But I can't seem to find a way to do the same thing with c++. I can connect to the database but I can't use it as a class because I have a main() inside it and I can't seem to make it work without the main. This is my code:
// Standard C++ includes
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
// Include the Connector/C++ headers
#include "cppconn/driver.h"
#include "cppconn/exception.h"
#include "cppconn/resultset.h"
#include "cppconn/statement.h"
// Link to the Connector/C++ library
#pragma comment(lib, "mysqlcppconn.lib")
// Specify our connection target and credentials
const string server = "localhost";
const string username = "root";
const string password = "";
int main()
{
sql::Driver *driver; // Create a pointer to a MySQL driver object
sql::Connection *dbConn; // Create a pointer to a database connection object
sql::Statement *stmt; // Create a pointer to a Statement object to hold our SQL commands
sql::ResultSet *res; // Create a pointer to a ResultSet object to hold the results of any queries we run
// Try to get a driver to use to connect to our DBMS
try
{
driver = get_driver_instance();
}
catch (sql::SQLException e)
{
cout << "Could not get a database driver. Error message: " << e.what() << endl;
system("pause");
exit(1);
}
// Try to connect to the DBMS server
try
{
dbConn = driver->connect(server, username, password);
}
catch (sql::SQLException e)
{
cout << "Could not connect to database. Error message: " << e.what() << endl;
system("pause");
exit(1);
}
stmt = dbConn->createStatement();
// Try to query the database
try
{
stmt->execute("USE test");
res = stmt->executeQuery("SELECT * FROM users");
}
catch (sql::SQLException e)
{
cout << "SQL error. Error message: " << e.what() << endl;
system("pause");
exit(1);
}
sql::ResultSetMetaData *res_meta = res -> getMetaData();
int columns = res_meta -> getColumnCount();
while (res->next())
{
for (int i = 1; i <= columns; i++) {
cout << res->getString(i) << " | " ;
}
cout << endl;
}
delete res;
delete stmt;
delete dbConn;
return 0;
}
You need to create a class (e.g class DBConnector)and declare functions in header file.
For example this piece of code can go into one function:
sql::Driver* DBConnector::GetDriverInstance()
{
try
{
m_driver = get_driver_instance();
}
catch (sql::SQLException e)
{
cout << "Could not get a database driver. Error message: " << e.what() << endl;
system("pause");
exit(1);
}
return m_driver;
}
Here sql::Driver *m_driver is expected to be declared as a member variable of class in header file. You might need to read more about classes and member functions and variables before actually going ahead with code.
Other than this, you need to take very good care of memory management. I would suggest you read more and use smart pointers like std::shared_ptr.

MySQL C++ Connector always outputs the same string

I am trying to write a program to output a row from a MYSQL table and it always outputs the same thing...
The function takes input from another function
C++
try {
sql::Driver *driver;
sql::Connection *con;
sql::Statement *stmt;
sql::ResultSet *res;
/* Create a connection */
driver = get_driver_instance();
con = driver->connect("tcp://127.0.0.1:3306", "root", "TSA!");
/* Connect to the MySQL test database */
con->setSchema("main");
stmt = con->createStatement();
stmt->execute("CALL getData('" + quest1 +"', #ans)");
res = stmt->executeQuery("SELECT #ans AS _message");
while (res->next()) {
cout << "Answer: ";
/* Access column data by alias or column name */
cout << res->getString("_message") << endl;
}
delete res;
delete stmt;
delete con;
}
and then a error statement which is not triggered by this program.
MySQL
CREATE DEFINER=`root`#`localhost` PROCEDURE `getData`(IN info MEDIUMTEXT,
OUT datas MEDIUMTEXT)
BEGIN
SELECT `answer` from `approved` WHERE `Question` = info into datas;
END
The table:
question | answer
test | test
test2 | test2
The program always and only outputs "test"
How do I fix this?
I fixed it by getting a char from the user for input using cin.getline rather than cin to a string.
You can clear the existing buffer with cin which I believe was the problem.

VS Express 2013 C++ with MySQL Connector stmt->executeQuery() error

So I finally got VS 2013 C++ to connect with mySQL using the Connector C and C++ and I know this because I am able to add a table into my DB using the stmt->execute() function.
Now, I am trying to get the rows using the ResultSet to retrieve from function executeQuery, but this error shows up:
Here is my code:
#include <iostream>
#include <string>
#include "mysql_connection.h"
#include "mysql_driver.h"
#include <cppconn/driver.h>
#include <cppconn/exception.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>
#include <cppconn/prepared_statement.h>
#define dbHOST "tcp://127.0.0.1:3306"
#define dbUSER "root"
#define dbPASS "root"
#define dbDB "db_test"
using namespace std;
using namespace sql;
int main()
{
sql::mysql::MySQL_Driver *driver;
sql::Connection *con;
sql::Statement *stmt;
sql::ResultSet *res;
driver = sql::mysql::get_driver_instance();
con = driver->connect(dbHOST, dbUSER, dbPASS);
stmt = con->createStatement();
string query = "SELECT * FROM test";
res = stmt->executeQuery(query.c_str());
while (res->next()) {
cout << "id = " << res->getInt(1);
cout << ", label = '" << res->getString("label") << "'" << endl;
}
delete res;
delete stmt;
delete con;
system("pause");
return 0;
}
Under the output pane, it shows this as well:
First-chance exception at 0x77661D4D in MySQLConnect.exe: Microsoft C++ exception: sql::SQLException at memory location 0x0088FB5C.
Unhandled exception at 0x77661D4D in MySQLConnect.exe: Microsoft C++ exception: sql::SQLException at memory location 0x0088FB5C.
Under the call stack after I hit F5 and it breaks, it shows this:
MySQLConnect.exe!main() Line 35 C++
Line 35 is the line with res = stmt->executeQuery(query.c_str());
Let me know if you need more information on my code / settings.
Thanks in advance!
Silly me, I found out what is the problem.
I have to add in a line:
stmt->execute("USE " dbDB);
before I can do any further query for that database. The snippet is now like this:
stmt = con->createStatement();
stmt->execute("USE " dbDB); // <-- This line, change dbDB to your own
string query = "SELECT * FROM test"; // <- before all of these below
res = stmt->executeQuery(query.c_str());
I hope this helps!