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");
}
Related
I want to try out Critcl to enhance memory performance using a Z-order curve for a 2d-grid. What I need from Critcl is allocation, setter, getter and some size info. Reading about the Critcl ByteArray and examples does not make me confident on how to do it.
How do I create and return a ByteArray (i.e. Z-order curve)?
Any caveats I should know about when using ByteArray?
According to the documentation, you should be using the bytes type instead (when you get a pointer to a structure that has a len field with the number of bytes in it, and an s field that is the pointer to the actual read only block of bytes. (As a char * and not an unsigned char * for reasons I don't know. And why it isn't const is another mystery to me; there are cases where that's indeed true, but you need to look at the o field to figure that out.)
To return a byte array, you use the object (or object0) result type, and make the object with, for example, Tcl_NewByteArrayObj(), or Tcl_NewObj() and Tcl_SetByteArrayLength().
Here's an example (just the command definition) that does trivial byte reversing (since I don't understand Z-order curves at all):
critcl::cproc example {bytes dataPtr} object0 {
Tcl_Obj *result = Tcl_NewObj();
unsigned char *targetBytes = Tcl_SetByteArrayLength(result, dataPtr->len);
for (int i = 0, j = dataPtr->len - 1; j >= 0; i++, j--) {
targetBytes[i] = (unsigned byte) dataPtr->s[j];
}
return result;
}
Naturally, you'll want to read the Critcl usage guide when getting this to work, and if you're going to produce errors (by returning NULL), remember to set an error message in the interpreter. You can get access to that by using Tcl_Interp* interp as your first pseudo-argument to the command you create with critcl::cproc (it's documented, but easily missed).
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.
When i try to use the code, I find that row[i] is the i'th row in the form of a string. But I need to use my data which was in the form of a int. Also, the row[i] contains the entire row in the form of a string. How do I extract the data from it. I tried to parse the data and convert it into integer, but the entire data is just one string and does have any spaces! so i am having a difficult time doing the parsing as I have no way to know where the previous field ended and the next began in the dataset.
So to sum it up;
when i do:
mysql_real_connect(conn, "localhost", "root", "abcd", "Hybr", 0, NULL, 0);
mysql_query(conn, "SELECT * FROM Data");
result = mysql_store_result(conn);
num_fields = mysql_num_fields(result);
while ((row = mysql_fetch_row(result)))
{
for(i = 0; i < num_fields; i++)
{
row[i] //this is a string containing all the
//fields. I want the individual values !
}
}
My Data 34, 45, host gets converted into a string "34 45 host". And the wierd thing is that when i print row[i], atleast it prints the spaces but when i copy it into a char*, the space somehow disappears! so it becomes impossible to parse it.
I think there is a different way of reading records ,maybe I have overlooked some part of the API, but i cant seem to find which ...
EDIT
I realised I havent overlooked the API; its just that the row[i] is an array of strings. I still need help extracting the individual values from it.
You can use atoi on the field if you know it will be int. For example, units is int and so "SELECT units FROM data" could be read into an int array or whatever.
mysql_query conn, "SELECT units FROM data"
res = mysql_store_result(conn)
num_fields = mysql_num_fields(res)
while (row = mysql_fetch_row(res))
for i = 0; i < num_fields; i++
printf "%03i ",atoi(row[i])
puts ""
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
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);
`