C language variable type float and integer pass in mysql - 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);

Related

How to Know records updated with Update query?

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.

Calling MySQL stored procedure in c, passing variable argument

I made a database in MySQL and I created some Stored Procedures. Now I need to launch these SP using a C program.
I've already connected my db to c successfully, using:
char u[255];
char p[255];
int main (int argc, char *argv[])
{
scanf("%s",u);
scanf("%s",p);
conn = mysql_init (NULL);
login = mysql_real_connect(conn, "localhost",u,p, "ASL", 3306, NULL, 0);
}
I'm able to calling a SP without any parameter. For example my SP mostra_pazienti()shows all the rows contained in the MySQL table 'paziente', and I made in this way:
query = "call mostra_pazienti()";
mysql_query (conn,query);
MYSQL_RES *result = mysql_store_result(conn);
int num_fields = mysql_num_fields(result);
while ((row = mysql_fetch_row(result)))
{
for(int i = 0; i < num_fields; i++)
{
printf(" %s ", row[i] ? row[i] : "NULL");
}
printf ("\n");
}
}
But basically now I need to run a procedure which takes some parameters as input.
For example MySQL procedure esame_aggiungi(IN code CHAR(5),IN name VARCHAR(30),IN cost FLOAT) insert a new row in the table exam.
So, in C, how can I take the parameters code, name, and cost using scanf(), and how can I use them to execute my Stored procedure?
If you're asking "how do I build the CALL MYPROC(ARG1, ARG2...) string within my C program", you can use the function snprintf for that, which writes formatted data to a string of known length.
char query[1000];
snprintf(query, 1000, "CALL MYPROCEDURE(\"%s\", \"%s\", %f);", code, name, cost);
mysql_query(conn, query);
Note that bounds checking for the constraints in the MySQL table (i.e. the field code is of type CHAR (5) and name is of type VARCHAR (30)) must be taken care of as well. A column with type CHAR(N) rather than VARCHAR will contain exactly N characters.

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!

Using sprintf with mysql_query

I'm using a mysql snippet that connects to my mysql database (locally) in ANSI C. Everything is working perfectly, but I've been trying to create a function that connects to my database and inserts a new record based on some variables. I'm using sprintf to snag those variables and piece them together to form my SQL query.
Problem
Once I have my variables and my SQL ready, I send it over to mysql_query. Unfortunately, this does not work as expected, the program crashes and reports a buffer overflow.
Here are pieces of the overall function that may help explain the problem.
#include <mysql.h>
#include <string.h>
#include <stdio.h>
char *table = "test_table"; // table is called test_table
char *column = "value"; // column is called value
char *value = "working"; // what value we are inserting
char *query; // what we are sending to mysql_query
sprintf(query, "INSERT INTO %s (%s) VALUES ('%s')", table, column, value);
if (mysql_query(conn, query)) {
fprintf(stderr, "%s\n", mysql_error(conn));
return;
}
Purpose
The purpose of the overall function is so I don't have to keep rewriting SQL insert or update statements in my program. I want to call to one function and pass a few parameters that identify the table, columns and the values of said columns.
Any help would be most appreciated. I'm a bit rusty in C these days.
Question
Why is mysql_query not able to send the string?
Changes
This worked based on the comments.
const char *query[MAX_STRING_LENGTH];
sprintf((char *)query, "INSERT INTO %s (%s) VALUES ('%s')", table, column, value);
if (mysql_query(conn, (const char *)query)) {
You have no backing storage for query.
It's either set to NULL or some indeterminate value, depending on its storage duration, neither of which will end well :-)
Quick fix is to change it to
char query[1000];
though any coder worth their salary would also check to ensure buffer overflow didn't occur.

How to pass variable in mysql_query

I try to execute mysql query passing variable. Here is my code
char str[100] = "My String";
mysql_query(conn, printf("INSERT INTO table VALUES %s"), str);
I get that warning during compile process
warning: passing argument 2 of ‘mysql_query’ makes pointer from integer without a cast
What I miss ?
Extending #ckruse's answer, you should take care to use mysql_real_escape_string() if your string comes from arbitrary sources.
int insert_data(MYSQL * mysql, char * str, int len)
{
if (len < 0) {
len = strlen(str);
}
char esc[2*len+1];
unsigned long esclen = mysql_real_escape_string(mysql, esc, str, len);
char statement[512];
snprintf(statement, sizeof statement, "INSERT INTO table VALUES ('%s')", esc);
return mysql_query(mysql, statement);
}
(An alternative could be mysql_hex_string() if dealt with correctly.)
You cannot do that. printf() returns the number of characters printed. You have to create the string before calling mysql_query():
char statement[512], *my_str = "MyString";
snprintf(statement, 512, "INSERT INTO table VALUES ('%s')", str);
mysql_query(conn, statement);
Also, be careful when creating those query strings. Don't use functions like sprintf() if you cannot be sure how long the resulting string is. Don't write over the boundaries of the memory segment.
you should put "'' in front and after the string
like this
mysql_query(conn, printf("INSERT INTO table VALUES ('%s')"), str);