Incompatible pointer type with mysql_store_result - mysql

I am new to C but I am currently working on a project where I have a compiler warning but I can't see what the problem is, or how I am able to fix it.
I am performing a mysql query and then storing the result but when I try I fetch the row to store in the MYSQL_ROW I get the following compilation warning
warning: assignment from incompatible pointer type
Below is how I am running the query and storing the result
int processDrilldownData(char **reportParameterArray, FILE *csvFile, char *sql, MYSQL *HandleDB, MYSQL_RES *resultReport, MYSQL_ROW rowReport, int UserLevel, int ParentUserLevel, char *CustomerDisplayName, Restrictions *reportRestrictions, int totalLookupNumberCount, numberLookupStruct *numberLookup, int maximumLookupChars, char * statsOutputTable, int targetNumber, FILE * sqlDebugFile)
{
MYSQL_RES * audioResult = NULL;
MYSQL_ROW * audioRow = NULL;
sqlLen = asprintf(&sql, "SELECT Tmp.SwitchID, Tmp.CorrelationID, SUM(IF(Direction=2,1,0)) as SSPAudio, "
"SUM(IF(Direction=1,Duration/100,0)) as SSPAudioDur FROM %s AS Tmp GROUP BY Tmp.SwitchID, "
"Tmp.CorrelationID ORDER BY Tmp.SwitchID, Tmp.CorrelationID, Direction, SeizeUTC, SeizeCSec",
statsOutputTable);
if ((mysql_real_query(HandleDB, sql, sqlLen))) return 1;
audioResult = mysql_store_result(HandleDB);
audioRow = mysql_fetch_row(audioResult);
}
Thanks for any help you can provide

The error message is from mysql_fetch_row() and not mysql_store_result(). mysql_fetch_row returns MYSQL_ROW, note the missing *.
So the declaration must look like
MYSQL_ROW audioRow;

Related

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.

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

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

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