Delete with PQexec by given ID in C++ - 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 );

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.

MySQL in C++ Seg Fault

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.

UPDATE with NULL char in the middle of std::string or char array

We are using Oracle 12c database and CentOS7 with OCCI to connect. We are trying to insert a char array into the database, but this char array has a NUL character in the middle. When we use the statement->setString function the update is successful however once it sees the NUL char it only puts NUL chars there after. See this example code and it's output.
Example Code using setString:
static void Run(const std::string &connectionString, const std::string &user, const std::string &pwd)
{
Environment *env = Environment::createEnvironment();
Connection *conn = env->createConnection(user, pwd, connectionString);
Statement *stmt = conn->createStatement("UPDATE my_customers SET first_name = :1 WHERE customer_id = :2");
stmt->setString(1, std::string("GEO\0RGE ", 20));
stmt->setInt(2, 10);
stmt->setString(1, std::string(adrs_first_name, sizeof(adrs_first_name)));
oracle::occi::Statement::Status status = stmt->execute();
conn->terminateStatement(stmt);
conn->commit();
}
Accessing the Database After the Update:
SELECT first_name FROM my_customers WHERE customer_id = 10;
GEO
SELECT rawtohex(first_name) FROM my_customers WHERE customer_id = 10;
47454F0000000000000000000000000000000000
However I would have expected it to be
47454F0047452032322020202020202020202020
So I tried using oracle::occi::Bytes-- this errors out with
ORA - 12899: value too large for column "MAIN_USER"."MY_CUSTOMERS"."FIRST_NAME" (actual : 40, maximum : 20)
Example Code using setBytes:
static void Run(const std::string &connectionString, const std::string &user, const std::string &pwd)
{
Environment *env = Environment::createEnvironment();
Connection *conn = env->createConnection(user, pwd, connectionString);
Statement *stmt = conn->createStatement("UPDATE my_customers SET first_name = :1 WHERE customer_id = :2");
std::string s("GEO\0RGE ", 20);
oracle::occi::Bytes bytes((unsigned char *)s.c_str(), 20, 0, env);
stmt->setBytes(1, bytes);
stmt->setInt(2, 10);
try
{
oracle::occi::Statement::Status status = stmt->execute();
}
catch (oracle::occi::SQLException &e)
{
std::cout << "Error " << e.getErrorCode() << ": " << e.what() << std::endl;
}
conn->terminateStatement(stmt);
conn->commit();
}
Output:
Error 12899 : ORA - 12899 : value too large for column "MAIN_USER"."MY_CUSTOMERS"."FIRST_NAME" (actual : 40, maximum : 20)
So I tried sending in half the bytes by changing the 2nd parameter of the oracle::occi::Bytes constructor to 10, and it succeeded however after reading the value from the database I realized it is a string representation of the hex value of the chars. So my question at this point is why is Oracle12c putting the hex value as a string when I pass oracle::occi:Bytes.
Example Code using half the actual length and setBytes:
static void Run(const std::string &connectionString, const std::string &user, const std::string &pwd)
{
Environment *env = Environment::createEnvironment();
Connection *conn = env->createConnection(user, pwd, connectionString);
Statement *stmt = conn->createStatement("UPDATE my_customers SET first_name = :1 WHERE customer_id = :2");
std::string s("GEO\0RGE ", 20);
oracle::occi::Bytes bytes((unsigned char *)s.c_str(), 10, 0, env);
stmt->setBytes(1, bytes);
stmt->setInt(2, 10);
try
{
oracle::occi::Statement::Status status = stmt->execute();
}
catch (oracle::occi::SQLException &e)
{
std::cout << "Error " << e.getErrorCode() << ": " << e.what() << std::endl;
}
conn->terminateStatement(stmt);
conn->commit();
}
Accessing the Database After the Update :
SELECT first_name FROM my_customers WHERE customer_id = 10;
47454F00524745202020
NOTE : This query did not wrap with rawtohex-- this is the actual char array value in the database.
Here is the table definition:
DESCRIBE MAIN_USER.MY_CUSTOMERS
Name Null Type
------------------------------ ---- --------------
CUSTOMER_ID NUMBER(10)
FIRST_NAME CHAR(20 CHAR)
Here is our Oracle instance information :
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Advanced Analytics and Real Application Testing options
We are using Oracle occi client 12.1 64bit
For those that may stumble upon this, I ended up talking with Oracle Support and they told me there wasn't a way to do what I wanted (as expected) however the Byte workaround got us closer and we were able to take the hex string being passed in by the setBytes and turn it into raw data and then convert that raw data to a varchar2 which ended up "working" -- however I don't know what implications we will run into later, but so far it seems to work.
Code:
static void Run(const std::string &connectionString, const std::string &user, const std::string &pwd)
{
Environment *env = Environment::createEnvironment();
Connection *conn = env->createConnection(user, pwd, connectionString);
Statement *stmt = conn->createStatement("UPDATE my_customers SET first_name = utl_raw.cast_to_varchar2(hextoraw(:1)) WHERE customer_id = :2");
std::string s("GEO\0RGE ", 20);
oracle::occi::Bytes bytes((unsigned char *)s.c_str(), 20, 0, env);
stmt->setBytes(1, bytes);
stmt->setInt(2, 10);
try
{
oracle::occi::Statement::Status status = stmt->execute();
}
catch (oracle::occi::SQLException &e)
{
std::cout << "Error " << e.getErrorCode() << ": " << e.what() << std::endl;
}
conn->terminateStatement(stmt);
conn->commit();
}
Then checking the database:
SELECT rawtohex(first_name) FROM my_customers WHERE customer_id = 10;
47454F0052474520202020202020202020202020
So it seems to work