MySQL C API mysql_query - mysql

I have two problems with the MySQL C API. How do I get variable to be added to the table when I do the mysql_query() and how do I get the table show decimals?
Here is my code:
void insertDataToTable(MYSQL* con, float temp, int k)
{
mysql_query(con, "INSERT INTO Weatherstation VALUES(#k,'Temperature:', #temp)");
}
Thank you!

Try this
void insertDataToTable(MYSQL* con, float temp, int k)
{
char query[255] ;
sprintf( query, "INSERT INTO Weatherstation VALUES(%ld,'Temperature:', %d)", temp, k );
mysql_query(con, query );
}

MySQL does not support host variables that well, the previous answer shows the correct approach in building the query into a string and then using mysql_query(someconnection, string).
What is absolutely shocking is that this is not documented as much as it should be. When I had to learn this I had 30 years of DB2 and C, and I had to get this from GitHub after 2 hours of fruitless searching for "MySQL Host Variables".
You should also be aware of mysql_real_query if your query is not a conventional string and contains embedded nulls, it is passed the length of the string, but can also move a strlen() call off the server.

Related

MySQL C Connector / mysql_autocommit function

I'm having a little trouble with the mysql connector in C.
I'm converting some (working) node.js scripts to a standalone C application, and for one part of this I need to switch off auto-commit, make two updates to the database and commit.
However, every time I call mysql_autocommit(mysql, 0); it fails - returning non-zero. I know my connection is good, since I've just completed a query and I'm operating on the results of that query.
Interestingly the MySQL logs are empty...which isn't very helpful.
Any ideas how might find out what the problem is, or fix it? The Node.js scripts were also switching off autocommit and [apparently] work.
Thanks in advance
I use this function the following way in my C application:
int main( int argc, char **argv ) {
my_bool reconnect = 1;
...
dbconnect(); // my function (-> conn)
mysql_options( conn, MYSQL_OPT_RECONNECT, &reconnect );
...
exit (0);
}
Then this code switch out the auto-commit:
mysql_autocommit( conn, 0 );
And this switch back:
mysql_commit( conn );
mysql_autocommit( conn, 1 );

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.

Extracting integers from a query string

I am creating a program that can make mysql transactions through C and html.
I have this query string
query = -id=103&-id=101&-id=102&-act=Delete
Extracting "Delete" by sscanf isn't that hard, but I need help extracting the integers and putting them in an array of int id[]. The number of -id entries can vary depending on how many checkboxes were checked in the html form.
I've been searching for hours but haven't found any applicable solution; or I just did not understand them. Any ideas?
Thanks
You can use strstr and atoi to extract the numbers in a loop, like this:
char *query = "-id=103&-id=101&-id=102&-act=Delete";
char *ptr = strstr(query, "-id=");
if (ptr) {
ptr += 4;
int n = atoi(ptr);
printf("%d\n", n);
for (;;) {
ptr = strstr(ptr, "&-id=");
if (!ptr) break;
ptr += 5;
int n = atoi(ptr);
printf("%d\n", n);
}
}
Demo on ideone.
You want to use strtok or a better solution, to tokenize this string with & and = as tokens.
Take a look at cplusplus.com for more information and an example.
This is the output you would get from strtok
Output:
Splitting string "- This, a sample string." into tokens:
This
a
sample
string
Once you figure out how to split them, the next hurdle is to convert the numbers from strings to ints. For this you need to look at atoi or its safer more robust cousin strtol
Most likely I would write a small lexical scanner to tackle the task. Meaning, I would analyze the string one character at a time, according to a regular expression representing the set of possible inputs.

recently switch from sqlite to mysql. need to convert some code in c

I'm writing C program to access database.
I recently switch from sqlite to mysql.
I'm not familiar with mysql c api, so I need help converting some code.
Below example is executing sql statement with parameter.
sqlite:
char *zSQL = sqlite3_mprintf("SELECT price FROM warehouse WHERE p_ID='%q'", input_value);
sqlite3_prepare_v2(handle,zSQL,-1,&stmt,0);
my attempt in mysql:
char zSQL[60] = {'\0'};
int n = 0;
n = sprintf(zSQL, "SELECT price FROM warehouse WHERE p_ID='%s'", input_value);
mysql_real_query(conn, zSQL, n);
Another example is parsing result of sql statement to variable
sqlite:
double price_value = 0;
if (sqlite3_step (stmt) == SQLITE_ROW) {
price_value = sqlite3_column_double (stmt, 0);
}
mysql:
MYSQL_ROW row;
while ((row = mysql_fetch_row(result)))
{
price_value = atof(row[0]);
}
While the code in mysql works for me, but I feel like I'm not utilizing the API enough.
Is there any function in mysql c api which has the same functionality as sqlite3_mprintf() and sqlite3_column_double() ?
Edit:
My attempt on mysql_real_escape_string():
ulong in_length = strlen(input_value);
char input_esc[(2 * in_length)+1];
mysql_real_escape_string(conn, input_esc, input_value, in_length);
char sql_stmnt[56] = {'\0'};
n = sprintf(zSQL, "SELECT price FROM warehouse WHERE p_ID='%s'", input_esc);
mysql_real_query(conn, sql_stmnt, n);
For your first exampe, the short answer is no, you have to do it yourself, see http://dev.mysql.com/doc/refman/5.5/en/mysql-real-escape-string.html
unsigned long mysql_real_escape_string(MYSQL *mysql, char *to, const char *from, unsigned long length)
The second one, yes, that's the way to go, with some additional check that row[0] is indeed of type double.
Alternatively, you can use the prepared statement API which works quite similar to the one in sqlite3. The key is you provide buffers of type MYSQL_BIND and then either bind the inputs to it, or have mysql binding output values there.
Prepared statement documentation: http://dev.mysql.com/doc/refman/5.5/en/c-api-prepared-statement-data-structures.html

Why is mysql_num_rows returning zero?

I am using C MySQL API
int numr=mysql_num_rows(res);
It always returns zero, but in my table there are 4 rows are there. However, I am getting the correct fields count.
what is the problem? Am i doing anything wrong?
Just a guess:
If you use mysql_use_result(), mysql_num_rows() does not return the correct value until all the rows in the result set have been retrieved.
(from the mysql manual)
The only reason to receive a zero from mysql_num_rows(<variable_name>) is because the query did not return anything.
You haven't posted the query here that you run and then assign the result to your res variable so we can't check it.
But try running that exact query in your DB locally through whatever DB management software you use and see if you are able to achieve any results.
If the query is working fine, then it must be the way you're running the query in C, otherwise your query is broken.
Maybe post up a bit more of your code from C where you make the query and then run it.
Thanks
If you just want to count the number of rows in a table, say
SELECT COUNT(*) FROM table_name
You will get back a single column in a single row containing the answer.
I too have this problem. But I noticed that mysql.h defines mysql_num_rows() to return a "my_ulonglong". Also in the header file you will see that there is a type def for my_ulonglong. On my system size of a my_ulonglong is 8 bytes. When we try to print this out or cast this to an int we probably get the first four bytes which are zero. However I printed out the eight bytes at the address of my_ulonglong variable and it prints all zeros. So I think this function just doesn't work.
`my_ulonglong numOfRows;
MYSQL *resource;
MYSQL *connection;
mysql_query(connection,"SELECT * FROM channels");
resource = mysql_use_result(connection);
numChannels = mysql_num_rows(resource);
printf("Writing numChannels: %lu\n", numChannels); // returns 0
printf("Size of numChannels is %d.\n", sizeof(numChannels)); // returns 8
// however
unsigned char * tempChar;
tempChar = (unsigned char *) &numChannels;
for (i=0; i< (int) sizeof(numChannels); ++i) {
printf("%02x", (unsigned int) *tempChar++);
}
printf("\n");
// returned 0000000000000000 so I think its a bug.
//mysql.h typedef for my_ulonglong and function mysql_num_rows()
#ifndef _global_h
#if defined(NO_CLIENT_LONG_LONG)
typedef unsigned long my_ulonglong;
#elif defined (__WIN__)
typedef unsigned __int64 my_ulonglong;
#else
typedef unsigned long long my_ulonglong;
#endif
#endif
my_ulonglong STDCALL mysql_num_rows(MYSQL_RES *res);
`