MySQL C Connector / mysql_autocommit function - mysql

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 );

Related

Problems with C prog fetching SQL table and integration of JSON to display table on webserver

I have two problems that drive me crazy.
The first one is to integrate JSON in the following code to use JSON as a kind of wrapper around the sqlite statements. This should be for the purpose to display just the entire sql table on a webserver page embedded in HTML. To connect to the database and fetch the table I used sqlite3 and the given functions like sqlite3_open()/sqlite3_close() and so on. I know that sqlite3 has functions to handle JSON as well like json_array()/json_insert() etc. I think this should be a good possible solution to reach my goal. I played around with those functions a bit, but nothing has worked yet. Means there was absolutely no result. Maybe anyone knows how to put the sqlite3 commands/requests in JSON objects to display in a further step those table entries on a simple HTML page. I have to say I`m a absolutely beginer in this section, but read and tried a lot to get into it. But didnt catch it yet.
The second problem is, that the following C code does not execute the while loop to return the rows of my sql table. Output is "Database sucessfull opened unable to fetch data, means it stopps within the last if statement. But I dont know why. Tried to fix it but didnt solve the puzzle yet. The while statement "sqlite3_step(stmt) == SQLITE_ROW" seems to be false, but why? Maybe something is wrong with the stmt pointer.
Hope you could help me. Would be very thankful for every hint to get it work.
C code:
#include "sqlite3.h"
#include <stdio.h>
int main(void) {
sqlite3 *db;
sqlite3_stmt *stmt;
int rc = 0;
rc = sqlite3_open("test.db",&db);
if(rc != SQLITE_OK)
{
printf("Database could not be opened %s \n",sqlite3_errmsg(db));
exit(EXIT_FAILURE);
}
else
{
printf("Database sucessful opened");
}
sqlite3_close(db);
char *sql_stmt = "SELECT * FROM students";
rc = sqlite3_prepare_v2(db, sql_stmt, -1, &stmt, 0);
if(rc != SQLITE_OK)
{
printf("\nUnable to fetch data");
sqlite3_close(db);
return 1;
}
printf("student records\n");
while(sqlite3_step(stmt) == SQLITE_ROW)
{
printf("%s %s %s\n", sqlite3_column_text(stmt, 0), sqlite3_column_text(stmt, 1),
sqlite3_column_text(stmt, 2));
}
sqlite3_finalize(stmt);
sqlite3_close(db);
return 0;
}
I suggest you first figure out why rc = sqlite3_prepare_v2(db, sql_stmt, -1, &stmt, 0); doesn't return an error. Then remove the first sqlite3_close(db); so you are operating on a open database handle.

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 C API mysql_query

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.

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.

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