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

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

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.

Incompatible pointer type with mysql_store_result

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;

C MySQL Types Error

I'm trying to store results taken from a MySQL query into an array of structs. I can't seem to get the types to work though, and I've found the MySQL documentation difficult to sort through.
My struct is:
struct login_session
{
char* user[10];
time_t time;
int length;
};
And the loop where I'm trying to get the data is:
while ( (row = mysql_fetch_row(res)) != NULL ) {
strcpy(records[cnt].user, &row[0]);
cnt++;
}
No matter what I try though I constantly get the error:
test.c:45: warning: passing argument 1 of ‘strcpy’ from incompatible pointer type
/usr/include/string.h:128: note: expected ‘char * __restrict__’ but argument is of type ‘char **’
test.c:45: warning: passing argument 2 of ‘strcpy’ from incompatible pointer type
/usr/include/string.h:128: note: expected ‘const char * __restrict__’ but argument is of type ‘MYSQL_ROW’
Any pointers?
Multiple problems, all related to pointers and arrays, I recommend you do some reading.
First, char * user[10] is defining an array of 10 char * values, not an array of char, which is was I suspect you want. The warning even says as much, strcpy() expects a char *, the user field on its own is seen as a char **.
Second, you're one & away from what you want in the second argument.
Copied from mysql.h header:
typedef char **MYSQL_ROW; /* return data as array of strings */
A MYSQL_ROW is an array of char arrays. Using [] does a dereference, so you dereference down to a char * which is what strcpy() takes, but then you take the address of it using &.
Your code should look more like this:
struct login_session
{
char user[10];
time_t time;
int length;
};
while ( (row = mysql_fetch_row(res)) != NULL ) {
strcpy(records[cnt].user, row[0]);
cnt++;
}
I don't know what guarantees you have about the data coming from mysql, but if you can't be absolutely sure that the rows are <= 10 characters long and null ('\0') terminated, you should use strncpy() to avoid any possibility of overflowing the user array.

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

MySQL C API using results

I am using the MySQL C API to query the database and I have the results stored in MYSQL_ROW types. I am able to print the results to the console with
printf("%s", row[0]);
however, according to the MySQL C API documentation, I cannot use them as null-terminated strings.
At the bottom of the function overview, they say I can "extract" the information with mysql_store_result() or mysql_use_result(). However, I am still confused as to how this is done.
Ideally, I want to use the results as a string so I can do stuff like strcmp, but otherwise I definitely need to use the information somehow with those two functions.
Can somebody show me an example of how to do this?
Basically, you call mysql_store_result() or mysql_use_result() to access the result set, the former loads all the rows into memory on the client side, the latter accesses rows one at a time from the server. If you use mysql_use_result(), you need to call mysql_fetch_row() to access each row until the function returns NULL. Each successful call to mysql_fetch_row() will return a MYSQL_ROW which you can use to access the individual field values.
Since the fields are not nul-terminated, you need to use mysql_fetch_lengths() to get the lengths of each of the fields so that you can copy them somewhere else via memcpy, etc.
Since the field values are not nul-terminated you will need to add your own NUL character when you make the copy if you want to use it as a string. Be aware that the field values may contain binary data, so if you do treat it as a string, functions that expect a C string will stop processing data if it encounters a nul-character in the data.
Here is an example from the documentation that should help you put all this together:
MYSQL_ROW row;
unsigned int num_fields;
unsigned int i;
num_fields = mysql_num_fields(result);
while ((row = mysql_fetch_row(result)))
{
unsigned long *lengths;
lengths = mysql_fetch_lengths(result);
for(i = 0; i < num_fields; i++)
{
printf("[%.*s] ", (int) lengths[i],
row[i] ? row[i] : "NULL");
}
printf("\n");
}