MySQL in C++ Seg Fault - c++

I'm implementing mySQL in C++ and ran into an issue. I'm getting a seg fault. And I'm not sure why.
Was hoping someone would know what is going on.
The seg fault seems to be happening somewhere after the MYSQL_ROW productList; line, I haven't been able to pin point where though.
void Receiving::getProduct(const string productToReturn) {
MYSQL *connect, mysql; //Pointers to MySQL
connect = mysql_init(&mysql); // Initialize the connections
int totalRows = 0;
connect = mysql_real_connect(connect,SERVER,USER,PASSWORD,DATABASE,0,NULL,0); //Connect to database
if(connect) { //If connection successful
string sqlQuery; //will hold query
MYSQL_RES *resSetProduct; //define product result set
MYSQL_ROW productList; //define row for product
sqlQuery = "SELECT * FROM Inventory WHERE item_id = \' "; //Create query with desired product id
sqlQuery += productToReturn;
sqlQuery += " \'";
mysql_query(connect, sqlQuery.c_str()); // Send query to the database
resSetProduct = mysql_store_result(connect); // Receive the result and store it in resSetProduct
totalRows = mysql_num_rows(resSetProduct); // count of stored rows
if(totalRows == 0){ //nothing found
cout << "Sorry! No inventory found for that product!" << endl;
}
else {
cout << "Product Id In Stock" << endl;
while( (productList = mysql_fetch_row(resSetProduct)) != NULL ) { //printout the products
cout << productList[0] << " " << productList[1] << endl;
}
}
mysql_free_result(resSetProduct);
}
else //Failed to connect
cerr << "Failed To Connect!";
mysql_close(connect);
}

You should check if mysql_query returns zero. If it does not, mysql_store_result will return NULL and mysql_num_rows might fail with a segfault.
If mysql_query returns non-zero you can check the error codes according to the mysql documentation, eg. here: MySQL mysql_query
As soon as those errors are cleared, mysql_num_rows should not segfault anymore.

Related

SQLite3 Insert statement error, but error message blank?

I'm working on a basic program to learn how to use SQLite3; a user gives input on a song they'd like to add to a SQLite database, and it is inserted. As far as I can seen, the insert statement I'm generating- while not pretty- is a valid statement, but once it reaches my queryDatabase() function it enters the error clause. It prints "Error in execution: ", but when it moves on to errmsg, it seems to enter into a state where nothing happens/no actual error message is printed until I enter .quit. I've tried altering the print line like cout << "ERROR EXECUTING SQL: " << errmsg << "End";, and "End" never prints.
Here is the section of code that calls the queryDatabase() function/passes the command string. args refers to a vector that contains the user input:
string sqlq;
sqlq = "INSERT INTO songs (sid, title, composer) VALUES(";
sqlq.append(args[2]); sqlq.append(", "); sqlq.append("\'"); sqlq.append(args[3]); sqlq.append("\'"); sqlq.append(", "); sqlq.append("\'"); sqlq.append(args[4]); sqlq.append("\'"); sqlq.append(");");
data.queryDatabase(sqlq);
and here is the queryDatabase() function:
sqlite3 *db;
char * errmsg = 0;
int rc;
void Data::queryDatabase(string queryString){
if(queryString.empty()) return;
const char * sqlQuery = queryString.c_str();
rc = sqlite3_exec(db, sqlQuery, callback, (void *) data, &errmsg);
if( rc != SQLITE_OK) {
cout << "Error in execution: " << errmsg;
} else {
cout << "\nSQL QUERY SUCCEEDED\n";
}
}
Both queryString and sqlQuery print INSERT INTO songs (sid, title, composer) VALUES(1905, 'Anti-rage', 'Emperor X'); which as far as I know is a valid command, as copy and pasting this when working direct in the database from terminal results in the song being added. Why might this not be inserting correctly, and why am I not being given an error message?
MODIFIED FOR MORE INFO:
Here's the callback
static int callback(
void * data, //pass through data provided to sqlite3_exec() [4th argument]
int argc, //# of cols in table row
char ** argv, //array of strings representing table row values
char ** azColName //array of strings representing column names
){
for (int i=0; i<argc; i++){
cout << argv[i] << ", ";
}
cout << "\n";
return 0;
}

Error message after inserting to a table in MYSQL db

I have this c++ code that works fine, i can read from the tables and write to the tables:
int main()
{
// 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(); // Specify which connection our SQL statement should be executed on
// Try to query the database
try
{
stmt->execute("USE test"); // Select which database to use. Notice that we use "execute" to perform a command.
res = stmt->executeQuery("INSERT INTO users (fName, lName, age) VALUES ('fname', 'lname', 25)"); // Perform a query and get the results. Notice that we use "executeQuery" to get results back
//res = stmt->executeQuery("SELECT * FROM users");
//return 0;
}
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 there are still results (i.e. rows/records) in our result set...
while (res->next())
{
for (int i = 1; i <= columns; i++) {
cout << res->getString(i) << " | " ;
}
cout << endl;
}
delete res;
delete stmt;
delete dbConn;
//system("pause");
return 0;
}
So, this inserts to the table but then i get this error message
SQL error. Error message: sh: 1: pause: not found
This doesn't happen if i use the "select".
Also i know that this question was already asked here but unfortunately it has no answer so i'm asking again.
Your question looks related to MySQL Query executes but throws exception.
executeQuery() assumes that sql query should return sql::ResultSet but your INSERT INTO query does not. You can use execute() instead, which returns true or false:
try
{
stmt->execute("USE test");
stmt->execute("INSERT INTO users (fName, lName, age) VALUES ('fname', 'lname', 25)");
}
catch (sql::SQLException e)
{
cout << "SQL error. Error message: " << e.what() << endl;
exit(1);
}
An INSERT is not a query. Try using executeUpdate() instead of executeQuery(). Look at the official MySQL example here.
Replace this line
res = stmt->executeQuery("INSERT INTO users (fName, lName, age) VALUES ('fname', 'lname', 25)"); // Perform a query and get the results. Notice that we use "executeQuery" to get results back
with the following lines (you may need a new .h file):
sql::PreparedStatement *pstmt;
pstmt = con->prepareStatement("INSERT INTO users (fName, lName, age)
VALUES ('fname', 'lname', 25)");
res = pstmt->executeUpdate();
delete pstmt;
You may also try using execute(), as shown in this Stackoverflow question. The function execute() is used for generic SQL commands, but may not be as verbose in its return value as more specified functions (it returns a boolean).

how to execute postgresql function with unnest array as parameter using libpqxx c++

I have created a postgresql function,
create or replace function check4(interval_ int[],password_ text[])
returns void as
$$
begin
EXECUTE '
INSERT INTO test(id,password)
SELECT unnest($1),unnest($2)'
USING $1,$2;
end;
$$
language plpgsql;
Then i tried to execute the above procedure from c++ using libpqxx
try
{
connection *conn;
conn = new connection("dbname = test user = postgres password = postgres hostaddr = 127.0.0.1 port = 5432");
if (conn->is_open()) {
cout<<"Opened database successfully:"<<std::endl<<std::flush;
}
else {
cout << "Can't open database" << std::endl << std::flush;
}
int arr_id[2] = { 1,2 };
string arr_pass[2] = { "hi","bye" };
work P(*conn);
conn->prepare("example", "select check4(UNNEST(:$1), UNNEST(:$2));");
for (int i = 0; i < 2; i++)
{
P.prepared("example")(arr_id[i])(arr_pass[i]).exec();
}
P.commit();
cout << "Records created successfully" << endl;
}
catch (const std::exception &e) {
cerr << e.what() << std::endl;
}
In this code, data is inserted one by one but i want the data to be inserted in bulk.I want to create array of 5000 records and insert in one shot.
Please anyone suggest me, How to pass array as parameter to a function?
Any help appreciated.
Thank you.

Delete with PQexec by given ID in C++

I am taking ID from my user and then i want to delete that ID from the database. I am using postgresql. but the query is not running. When i give hard code value like id=5 then it runs but when i give it user's value like id = DeleteId then it doesn't run. Here is the function:
void DeleteValue(PGconn *conn, int DeleteId)
{
PGresult *res = PQexec(conn, "DELETE FROM testData where ID = DeleteId" );
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
cout << "Delete testData record failed." << endl;
PQclear(res);
CloseConn(conn);
}
cout << "\nDelete testData record - OK\n";
PQclear(res);
}
Just solved my own problem.first concatenate it with the help of sprintf and then execute the query. Here is the solution of the problem
sprintf(sql,"DELETE FROM testData WHERE id = %d",DeleteId);
PGresult *res = PQexec(conn, sql );

How to check if "value does not exists" in sqlite column using C++

I have a table "SiteCode" with following schema :
CREATE TABLE SiteCode(
ID INTEGER PRIMARY KEY,
Code TEXT(3) UNIQUE NOT NULL DEFAULT 0);
Through the following code I can Open a DB & Access the elements of DB and perform the query execution perfectly.
Now I wish to add a small code snippet which could check if the element that a user wish to delete exists .
For example: Suppose table SiteCode have following Entries in Code column : 400, 401, 402 and 403 and user enters 444 as the input to DELETE query then it shall return an error.
At present, if a user enters 444 as input to the query then that query gets executed successfully without checking the Code column and without any Error.
How do i approach this problem. Kindly Help.
void DELETE_Site_Code()
{
int CodeA;
int rc = sqlite3_open("/DBsqlite3/empdbv3.db", &db);
if (rc != SQLITE_OK) {
cerr << "Cannot open database [ " << sqlite3_errmsg(db) << " ]" << endl;
sqlite3_close(db);
}
sql = "DELETE FROM SiteCode WHERE Code= #Code;";
rc = sqlite3_prepare_v2(db, sql, -1, &stmt4, 0);
if(SQLITE_OK != rc) {
cerr << "Failed to PREPARE DELETE statement for SiteCode Table [ " << sqlite3_errmsg(db) << " ]" << endl;
sqlite3_close(db);
exit(1);
}
else{
int Code_x = sqlite3_bind_parameter_index(stmt4, "#Code");
cout<< "Enter the Site Code That you wish to DELETE from table-SiteCode\n"<< endl;
cin>>CodeA;
if(cin.fail()) {
cout<<"\nPlease enter only digits\n"<<endl;
}
else {
if((CodeA >= 000) && (CodeA <= 998)) {
sqlite3_bind_int(stmt4, Code_x, CodeA);
}
else {
cout<< "Valid Site Code Should be between 000 to 998\n" <<endl;
}
} //else loop of (cin.fail) ends here
}
int step = sqlite3_step(stmt4);
if(SQLITE_DONE != step) {
cout<<"\nERROR while inserting into table\n"<< endl;
}
else {
cout<<"\nRecord DELETION completed"<<endl;
}
if(step == SQLITE_ROW){
cout<< sqlite3_column_text(stmt4, 0) << endl;
cout<< sqlite3_column_text(stmt4, 1) << endl;
}
sqlite3_finalize(stmt4);
sqlite3_close(db);
}
Use sqlite3_changes() function to query how many rows were affected by the query executed most recently:
// ...
int step = sqlite3_step(stmt4);
if(SQLITE_DONE != step) {
cout<<"\nERROR while inserting into table\n"<< endl;
}
else if (sqlite3_changes(db) == 0) {
cout<<"\nNo records deleted"<<endl;
}
else {
cout<<"\nRecord DELETION completed"<<endl;
}