How to Know records updated with Update query? - mysql

How to know whether any record in the table updated with the update query or not.
I am using the Mysql C API..i have tried storing the mysql result after firing the UPDATE query but result is always returning NULL for successful upation also. Any help would be great.
Thanks
int main(void)
{
MYSQL *conn;
MYSQL_RES *res;
MYSQL_ROW row;
if ((conn = mysql_init(NULL)) == NULL)
{
fprintf(stderr, "Could not init DB\n");
return EXIT_FAILURE;
}
if (mysql_real_connect(conn, "localhost", "root", "password", "cpaas", 0, NULL, 0) == NULL)
{
fprintf(stderr, "DB Connection Error\n");
return EXIT_FAILURE;
}
if (mysql_query(conn, "update calldirection set callid='Hello' where callid='He'") != 0)
{
fprintf(stderr, "Query Failure\n");
return EXIT_FAILURE;
}
res = mysql_store_result(conn);
if(res == NULL){
printf("dssdg");
return 1;
}
if ((row = mysql_num_rows(res)) <= 0)
{
printf("FFFFFFF");
}
mysql_close(conn);
return EXIT_SUCCESS;
}

After Doing Some R&D nearly for 1 day...I found mysql_affected_rows(*mysql) function which will return the number of rows updated for the UPDATE query.

As stated in MySQL mysql-store-resul
After invoking mysql_query() or mysql_real_query(), you must call
mysql_store_result() or mysql_use_result() for every statement that
successfully produces a result set (SELECT, SHOW, DESCRIBE, EXPLAIN,
CHECK TABLE, and so forth). You must also call mysql_free_result()
after you are done with the result set.
You need not call mysql_store_result() or mysql_use_result() for other
statements, but it does not do any harm or cause any notable
performance degradation if you call mysql_store_result() in all cases.
You can detect whether the statement has a result set by checking
whether mysql_store_result() returns a nonzero value (more about this
later)
mysql_store_result returns NULL for the queries other than (SELECT, SHOW, DESCRIBE, EXPLAIN, CHECK TABLE) query types.
and Update query is not one of them, thus mysql_store_result returns NULL for it.

Related

Problem with handling the result of SELECT query in MYSQL C API

I'm getting a Internal Server Error with one of my scripts. I'm using MYSQL C API. https://dev.mysql.com/doc/refman/5.6/en/c-api.html
Here is the corresponding part of my script:
MYSQL *con;
MYSQL_RES *result;
MYSQL_ROW robe;
con = mysql_init(NULL);
if (!mysql_real_connect(valid values)) {
printf("Content-type: text/html\n\n");
printf("Could not connect\n");
exit(0); }
char somequery[512];
//userinput is sanitized beforehand
int sog = sprintf(somequery, "SELECT password from testtab WHERE username='%s'", userinput);
if (sog < 0) {
printf("Content-type: text/html\n\n");
printf("Something went wrong with Sprintf\n");
exit(0); }
int bos = mysql_real_query(con, somequery, strlen(somequery));
if (bos != 0) {
printf("Content-type: text/html\n\n");
printf("The query produced no result\n");
exit(0); }
result = mysql_store_result(con);
if (result == NULL) {
printf("Content-type: text/html\n\n");
printf("No Result Set Produced\n");
exit(0); }
robe = mysql_fetch_row(result);
char *passdb = robe[0];
printf("Content-type: text/html\n\n");
printf("And it is: %s", passdb);
A HTML form submits via POST to this script (part of which is seen above). When I submit a username which exists in the database beforehand, I'm receiving no error. Everything works fine.
The problem arises, when I'm submitting a username that doesn't exist in the said table(testtab). Well, I'm getting 500 Internal Server Error. I have looked at Apache Error log as well: "End of Script output before Headers".
I have tried a few things so far, but none of them worked. Any help is appreciated.
Note: Doing mysql_num_fields(result); in both cases gives 1.
First, you should NEVER store passwords in a database, especially one that is reachable through an online service. exit(0) indicates success. It's also short-circuiting your output before it is completed. You can't just call exit(0) in the middle of producing output. Use some kind of "data not available" string instead.
I have found the solution elsewhere, thanks to the help of some good people. It seems, that I had made a silly mistake as well as needed a thorough understanding of the difference between two MYSQL C API functions.
I'm writing the answer here, in hope of it benefiting others.
The mistakes is here:
robe = mysql_fetch_row(result);
Though it is correct in itself. I fail to check its result. What happens is that when the SQL query is performed using a username that did not exist in the DB beforehand, the result is a empty set (and not a error).
The mysql_store_result and mysql_fetch_row have a slight difference here. While the former will not return NULL if the set is empty, the later will.
All I have to do is add a check after the above line with the logic:
if (robe == NULL) {
//error occured
} else { //go on
}

MySQL Connector C/C API - Query with special characters

I a C program I have a function that takes in parameter a domain name:
void db_domains_query(char *name);
With mysql_query() I test if the domain name is existing in a database. If it's not the case, I insert the new domain name:
...
char *query[400];
sprintf(query, "SELECT Id, DomainName FROM domains WHERE domainName LIKE '%s'", name);
if (mysql_query(con, query))
finish_with_error(con);
MYSQL_RES *result = mysql_store_result(con);
if (result == NULL)
finish_with_error(con);
MYSQL_ROW row;
if ((row = mysql_fetch_row(result)))
printf("Element exists : %s %s\n", row[0], row[1]);
else
printf("Element %s doesn't found\n", name);
// Then insert the new domain name ...
This portion of code works perfectly if name contains only "normal characters". However, for domain names that contain "special characters" the query seems incorrect even if those are in the database for instance :
name = undaben.de : Element exists : 100 undaben.de
name = ®here.com : Element ®here.com is not found.
name = §travel.us : Element §travel.us is not found.
Extract of the table :
+-----+--------------+
| id | domainname |
+-----+--------------+
| 100 | undaben.de |
| 162 | §travel.us |
| 197 | ®here.com |
+-----+--------------+
The collation of the field domainname is utf8_unicode_ci.
So how can I pass to mysql_query all domain names including the "special" ones ?
I recommend you to avoid the C API unless you have a compelling reason to use it. The C++ API es way more usable.
You are embedding your arguments within your query string. This has a number of problems, including security risks. If you insist in this approach, in order to prevent problems with parameters messing with your query, you need to ensure a few things:
Make sure that your data encoding matches the encoding of the MySQL Client connection (this may be different from your database encoding). If your connection is set up as UTF-8, then you need to make sure that special characters such as © are encoded also in UTF-8 when used as input to the sprintf function.
You also need to protect from other SQL escape characters (like '). For this you can use the mysql_real_escape_string function, as mentioned in Efficiently escaping quotes in C before passing to mysql_query.
However, you should very likely be using prepared statements which circumvent these issues. You still need to make sure that your input data encoding matches the encoding of your client connection, but everything else shall be easier to handle.
I paste an example of a parameterized query using the C API with prepared statements looks like (example from http://lgallardo.com/2011/06/23/sentencias-preparadas-de-mysql-en-c-ejemplo-completo/). Note the example is for integers, not strings, you need to adapt to your use case.
sql = "select count(*) from addresses where id = ?";
// Open Database
openDB(&conn);
// Allocate statement handler
stmt = mysql_stmt_init(conn);
if (stmt == NULL) {
print_error(conn, "Could not initialize statement handler");
return;
}
// Prepare the statement
if (mysql_stmt_prepare(stmt, sql, strlen(sql)) != 0) {
print_stmt_error(stmt, "Could not prepare statement");
return;
}
// Initialize the result column structures
memset (param, 0, sizeof (param)); /* zero the structures */
memset (result, 0, sizeof (result)); /* zero the structures */
// Init param structure
// Select
param[0].buffer_type = MYSQL_TYPE_LONG;
param[0].buffer = (void *) &myId;
param[0].is_unsigned = 0;
param[0].is_null = 0;
param[0].length = 0;
// Result
result[0].buffer_type = MYSQL_TYPE_LONG;
result[0].buffer = (void *) &myNumAddresses;
result[0].is_unsigned = 0;
result[0].is_null = &is_null[0];
result[0].length = 0;
// Bind param structure to statement
if (mysql_stmt_bind_param(stmt, param) != 0) {
print_stmt_error(stmt, "Could not bind parameters");
return;
}
// Bind result
if (mysql_stmt_bind_result(stmt, result) != 0) {
print_stmt_error(stmt, "Could not bind results");
return;
}
// Set bind parameters
myId = id;
// Execute!!
if (mysql_stmt_execute(stmt) != 0) {
print_stmt_error(stmt, "Could not execute statement");
return;
}
if (mysql_stmt_store_result(stmt) != 0) {
print_stmt_error(stmt, "Could not buffer result set");
return;
}
// Init data
(*numAddresses) = 0;
// Fetch
if(mysql_stmt_fetch (stmt) == 0){
(*numAddresses) = myNumAddresses;
}
// Deallocate result set
mysql_stmt_free_result(stmt); /* deallocate result set */
// Close the statement
mysql_stmt_close(stmt);
// Close Database
closeDB(conn);
Again, if you can use some other client library (like the C++ client) your code will be way shorter and readable.
My bad, as #jjmontes mentioned it seems that the sent string was encoded in 'latin1'.
Using the function mysql_set_character_set(conn, "utf8") before doing the query solved this problem.
Now, I will try to use prepared statements instead of query strings.
thanks again!

C language variable type float and integer pass in mysql

I'm a beginner in C and mysql programing.For some days now I am trying to write float and integer values that i get from sensors to a database in mySQL.So far i'm just getting an error "too many arguments to function ‘mysql_query’" and " expected ‘const char *’".Below is my simple code.
int main()
{
int var1 = 1;
float var2 = 5.1;
MYSQL *conn;
MYSQL_RES *res;
MYSQL_ROW row;
conn = mysql_init(NULL);
if (!mysql_real_connect(conn, host, user, pass, dbname,port, unix_socket, flag))
{
fprintf(stderr, "\nError: %s [%d]\n",mysql_error(conn),mysql_errno(conn));
exit(1);
}
printf("Connection successful!\n");
mysql_query(conn,"INSERT INTO variables (var1) VALUE ('%d');",var1);
mysql_query(conn, mysql_query );
}
It's a nice idea, but mysql_query doesn't work with variable arguments.
You need to store the query in a buffer:
char buff[1024];
snprintf(buff, sizeof buff, "INSERT INTO variables (var1) VALUES ('%d');",var1);
and then you can call mysql_query with this buffer:
mysql_query(conn, buff);
EDIT:
As pointed out by #PaulOgilvie: Notice VALUES instead of VALUE in the query.
You should use a prepared statement, which would also take care of the types and all that (assuming conn is a valid connection object)
MYSQL_STMT *stmt;
MYSQL_BIND params[1];
const char *query;
// This is necessary or the program will crash
memset(params, 0, sizeof(params));
query = "INSERT INTO variables (var1) VALUES (?)";
stmt = mysql_stmt_init(conn);
params[0].buffer = &var1;
params[0].buffer_type = MYSQL_TYPE_LONG;
if (stmt == NULL)
exit(1); // Ideally handle the error and solve the problem
// but for simplicity ...
if (mysql_stmt_prepare(stmt, query, strlen(query)) != 0)
exit(1);
if (mysql_stmt_bind_param(stmt, params) != 0)
exit(1);
if (mysql_stmt_execute(stmt) != 0) {
// Ideally print mysql's error
fprintf(stderr, "an error occurred\n");
}
mysql_stmt_close(stmt);
This is the good safe way to do this, and also you can reuse the prepared statement as many times as you want and they promise it will be faster and more efficient because the query is prepared so the execution plan is known and you don't need to use the snprintf() which by the way should be checked for errors and also, you should check if the query did fit into the target array, read the documentation for that.
Also, you don't need to worry about escaping strings or anything. It will all be handled transparently for you. As long as you use the correct type and of course, specify the length of strings.
Note that you can bind parameters and results too in SELECT queries.
Are you sure you don't need "VALUES" here instead of "VALUE":
mysql_query(conn,"INSERT INTO variables (var1) VALUE ('%d');",var1);

C pass string to query and also check if result is empty

I need to pass a string to inside the query when connecting to a database using C, but since I have not been using C for a long time I don't know the correct way to do it. I tried the below but that doesn't work.
if (mysql_query(conn, "select * from t1 where c1 = %s and c2 = %s", sptr->name, sptr->desc)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
also what is the easiest method to check whether the query returned an empty result set?
IIRC, you cannot use format specifiers and corresponding arguments directly inside mysql_query() function.
What you need to do is
Allocate one temporary buffer.
use snprintf() to print the query command in the buffer
call mysql_query() with the buffer as second argument.

How to access the first element in a pointer to an array using the C mysql API

I am trying to implement part of the mysql C API to retrieve one known field which will be a TINYINT value (boolean, either 1 or 0)
The mysql C API offers a type which is a pointer to an array MYSQL_ROW row; where the elements of the array are accessed via row[i] where i is the index. The elements are returned as strings whatever the data type in the database.
The field I am trying to access is obviously boolean and will be either 1 or 0 if the query finds the field. I want to do a logic check as to the value of this field but am struggling with types. I tried casting row[i] to an int but no good, I seem to get the pointer returned. I know that C doesn't have a native bool type but can be implemented. Any ideas there would be welcome.. here's my code, many thanks in advance - Paul
void process_result_set (MYSQL *conn, MYSQL_RES *res_set) {
MYSQL_ROW row;
unsigned int i;
unsigned int logonstatus;
while ((row = mysql_fetch_row (res_set)) != NULL)
{
for (i = 0; i < mysql_num_fields (res_set); i++)
{
logonstatus = (int)(row[i]); // gives an int return but appears to return a memory location i.e. a pointer
printf("The value of logon status is: %d\n", logonstatus);
printf("\nThe value of the logon field is:%s\n", row[i]);
}
}
if (mysql_errno (conn) != 0)
print_error (conn, "mysql_fetch_row() failed");
else
printf ("%lu rows returned\n",(unsigned long) mysql_num_rows (res_set));
}