How to save an array of unsigned char to MySQL - mysql

Any idea on how to save an array of unsigned char to a field in MySQL database ? I'm considering BLOB, but how can I convert it to QByteArray and convert it back to an array of unsigned char when I want to ? BTW, I'm trying to save fingerprint data.

I managed to solve this using the codes below (copied directly from my project)
struct fp {
unsigned char Template[MAX_TEMPLATE_SIZE];
int size;
};
// unsigned char to QByteArray
QByteArray FingerPrint::charArrayToByteArray(fp fp0) {
QByteArray ba;
for (int i=0; i
// QByteArray to unsigned char
fp FingerPrint::byteToFp(QByteArray *ba) {
fp fp0;
for (int i=0; isize(); i++) {
fp0.Template[i] = ba->at(i);
}
fp0.size = ba->size();
return fp0;
}

Related

MySQL UDF responds with garbage characters appended to returned string

So I created a UDF that accepts 2 strings and concats them.
My UDF: // concat_kv.c
#include <my_global.h>
#include <my_sys.h>
#include <mysql.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
typedef unsigned long ulong;
my_bool concat_kv_init(UDF_INIT *initid, UDF_ARGS *args, char *message) {
if(args->arg_count != 2 || args->arg_type[0] != STRING_RESULT || args->arg_type[1] != STRING_RESULT) {
strcpy(message, "concat_kv(): Requires 2 string parameters: Key - Value.");
return 1;
}
return 0;
}
char *concat_kv(UDF_INIT *initid, UDF_ARGS *args, char *result, ulong *length, char *is_null, char *error) {
char *key = (char*)calloc(strlen(args->args[0]), sizeof(char));
char *value = (char*)calloc(strlen(args->args[1]), sizeof(char));
char *res = (char *)calloc(strlen(args->args[0]) + strlen(args->args[1]) + 2, sizeof(char));
int len = strlen(args->args[0]) + strlen(args->args[1]) + 2;
key = args->args[0];
value = args->args[1];
strcat(res, key);
strcat(res, " ");
strcat(res, value);
res[len-1] = '\0'; // Terminating character...
return res;
}
void concat_kv_deinit(UDF_INIT *initid) {
}
Compiled the file as:
gcc $(mysql_config --cflags) -shared concat_kv.c -o concat_kv.so
Moved the concat_kv.so file to /usr/lib/mysql/plugins/.
Created the function in mysql as:
CREATE FUNCTION concat_kv RETURNS STRING SONAME 'concat_kv.so';
Then doing:
SELECT concat_kv("Aditya", "Singh") as conc;
Expected output:
| conc |
--------
| "Aditya Singh" |
But getting unexpected output as:
mysql> SELECT concat_kv("Aditya", "Singh") as conc;
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| conc
|
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Aditya Singh �T
|+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)
I am getting something unprintable after the concatinated string. Some garbage values are appended after the string.
Your concat_kv function should look more like so:
char *concat_kv(UDF_INIT *initid, UDF_ARGS *args, char *result, ulong *length, char *is_null, char *error) {
char *key = args->args[0];
char *value = args->args[1];
strcpy(result, key);
strcat(result, " ");
strcat(result, value);
*length = strlen(result);
return result;
}
Some remarks:
the result param should be used for the result
the length should be returned
the length should be without terminating null character, see here: https://dev.mysql.com/doc/refman/8.0/en/udf-return-values.html
key and value are just used from args and copied via strcpy/strcat into result
Demo
Dynamic Memory Allocation
As already pointed out in the comments, there is a danger of a buffer overrun if the size of the preallocated buffer is exceeded.
Memory Leak
If we were to dynamically allocate memory in concat_kv(), we would introduce a memory leak, since memory is requested every time the user-defined function is called, and is never released again.
The solution is to use the concat_kv_init() and concat_kv_deinit() functions, which are called by MySQL directly before and after the concat_kv() call.
Here a quote from the MySQL documentation:
MySQL passes a buffer to the xxx() function using the result parameter. This buffer is sufficiently long to hold 255 characters, which can be multibyte characters. The xxx() function can store the result in this buffer if it fits, in which case the return value should be a pointer to the buffer. If the function stores the result in a different buffer, it should return a pointer to that buffer.
If your string function does not use the supplied buffer (for example, if it needs to return a string longer than 255 characters), you must allocate the space for your own buffer with malloc() in your xxx_init() function or your xxx() function and free it in your xxx_deinit() function.
see https://dev.mysql.com/doc/refman/8.0/en/udf-return-values.html
Example with Dynamic Memory Allocation
So if we can't guarantee that the size of the result is large then the preallocated buffer, we need to allocate the memory in concat_kv_init() and free it in concat_kv_deinit().
my_bool concat_kv_init(UDF_INIT *initid, UDF_ARGS *args, char *message) {
if(args->arg_count != 2 || args->arg_type[0] != STRING_RESULT || args->arg_type[1] != STRING_RESULT) {
strcpy(message, "concat_kv(): Requires 2 string parameters: Key - Value.");
return 1;
}
ulong length = strlen(args->args[0]) + strlen(args->args[1]) + 2;
initid->ptr = (char *)malloc(length);
return 0;
}
char *concat_kv(UDF_INIT *initid, UDF_ARGS *args, char *result, ulong *length, char *is_null, char *error) {
char *key = args->args[0];
char *value = args->args[1];
strcpy(initid->ptr, key);
strcat(initid->ptr, " ");
strcat(initid->ptr, value);
*length = strlen(initid->ptr);
return initid->ptr;
}
void concat_kv_deinit(UDF_INIT *initid) {
free(initid->ptr);
initid->ptr = NULL;
}

best way to store data from mysql result using C

My C programming is decidedly rusty:-(
I have studied http://zetcode.com/db/mysqlc/ and essentially comfortable with it.
But I am unsure of the best way of storing the data retrieved.
int num_fields = mysql_num_fields(result);
MYSQL_ROW row;
while ((row = mysql_fetch_row(result))) {
for(int i = 0; i < num_fields; ) {
printf("%s ", row[i] ? row[i] : "NULL");
}
printf("\n");
this works fine and give me exactly the correct results.
Being familiar with perl hashes, I am tempted to use a C structure. Each record in my (small) database consists of different types of columns: char, float, int etc.
So I have:
struct Parameter {
char name[LEN_NAME];
float max;
float min;
float sample_interval;
int active;
char units[LEN_UNITS];
char start[LEN_START];
char start_time[LEN_START_TIME];
char end[LEN_END];
char end_time[LEN_END_TIME];
char type[LEN_TYPE];
};
struct Parameter parameters[MAX_PARAMETERS];
Where the LENs are defined constants.
I am trying things like:
num_fields = mysql_num_fields(result);
int r = 0;
while ((row = mysql_fetch_row(result))) {
for(int i = 0; i < num_fields; i++) {
printf("%s ", row[i] ? row[i] : "NULL");
sscanf(row[0], "%LEN_NAMEs", parameters[r].name);
sscanf(row[1], "%d", &parameters[r].max);
Which seems to be working OK for the chars, but not for the other types.
Struggling. Perhaps I am up a gum tree!

Strcmp not with working data in mysql

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <mysql.h>
#include <my_global.h>
void replace(char * o_string, char * s_string, char * r_string) {
char buffer[1024];
char * ch;
if(!(ch = strstr(o_string, s_string)))
return;
strncpy(buffer, o_string, ch-o_string);
buffer[ch-o_string] = 0;
sprintf(buffer+(ch - o_string), "%s%s", r_string, ch + strlen(s_string));
o_string[0] = 0;
strcpy(o_string, buffer);
return replace(o_string, s_string, r_string);
}
int main()
{
MYSQL *pConn;
MYSQL_RES *pRes;
MYSQL_ROW aRow;
MYSQL_FIELD *field;
int nfields, iCounter;
pConn = mysql_init(NULL);
char aPassword[1024]="";
if (pConn == NULL){
printf("Error %u: %s\n", mysql_errno(pConn), mysql_error(pConn));
exit(1);
}
if(mysql_real_connect(pConn, 0, "root",aPassword,"data",0,NULL,0) == NULL){
printf("Error %u: %s\n", mysql_errno(pConn), mysql_error(pConn));
exit(1);
}
char *info;
printf("Content-type:text/html\n\n");
printf("<html><body>");
info = getenv("QUERY_STRING");
char sub[20]="";
int nsub;
char teacher[20]="";
char room[20]="";
int nroom;
int count=0;
char *token;
char arr[5][20];
char data[1024];
char aCommand[1024];
char data2[1024];
replace(info,"%20"," ");
replace(info,"name=","");
token = strtok(info, " ");
while(token!=NULL){
strcpy(arr[count],token);
count++;
token = strtok(NULL," ");
}
if(count==5){
strcat(arr[0]," ");
strcat(arr[0],arr[1]);
strcpy(sub,arr[0]);
strcpy(teacher,arr[2]);
strcat(arr[3]," ");
strcat(arr[3],arr[4]);
strcpy(room,arr[3]);
}
if(count==4){
strcat(arr[0]," ");
strcat(arr[0],arr[1]);
strcpy(sub,arr[0]);
strcpy(teacher,arr[2]);
strcpy(room,arr[3]);
}
strcat(teacher," ");
strcat(teacher,room);
strcat(sub," ");
strcat(sub,teacher);
puts(sub);
sprintf(aCommand,"select * from Schedule");
mysql_query(pConn, aCommand);
pRes = mysql_store_result(pConn);
nfields = mysql_num_fields(pRes);
while ((aRow = mysql_fetch_row(pRes))){
if(strncmp(aRow[2],sub,strlen(sub)-1)==0)
puts("YS");
else
puts("NO");
}
mysql_free_result(pRes);
mysql_close(pConn);
printf("</body></html>");
return 0;
}
That's the whole code. I don't know where the problem is. After I parsed the query string and display them, it seems that the field and the parsed string are equal. But I've been trying to use strcmp and they just won't work. What could be the error?
I found the problem. I tried using strstr to find the string that only matches with the data in the MySQL table. It doesn't match the whole string so I just modified the program. Instead of matching the whole string, I just used a part of the string to match with the data in the table.

Hunspell returns bool instead words

help please with Hunspell problem, can\t make this stuff works well.
Here is my code, it returns bool value TRUE unstead the suggestion of word.
int main(array<System::String ^> ^args)
{
char *aff = "c:\\en_US.aff";
char *dic = "c:\\en_US.dic";
Hunspell *spellObj = new Hunspell(aff,dic);
const char *named = "hello";
int result = spellObj->spell(named);
char ** wlst;
char ** wlst2;
int ns = spellObj->suggest(&wlst,named);
int abc = spellObj->analyze(&wlst2,named);
Console::WriteLine(ns);
for (int i = 0; i<ns; i++)
{
Console::WriteLine(&wlst[i]);
}
spellObj->free_list(&wlst,ns);
delete spellObj;
Console::WriteLine(result);
getchar();
return 0;
How can i make this suggestion works?
must use std::cout instead Console::WriteLine (facepalm)

CUDA program giving garbage value

I really do not understand why the output for the below code is not a and b.
#include<cutil.h>
#include<iostream>
__global__ void p(unsigned char **a){
unsigned char temp[2];
temp[0] = 'a';
temp[1] = 'b';
a[0] = temp;
}
void main(){
unsigned char **a ;
cudaMalloc((void**)&a, sizeof(unsigned char*));
p<<<1,1>>>(a);
unsigned char **c;
unsigned char b[2];
cudaMemcpy(c, a, sizeof(unsigned char *), cudaMemcpyDeviceToHost);
cudaMemcpy(b, c[0], 2*sizeof(unsigned char), cudaMemcpyDeviceToHost);
for( int i=0 ; i < 2; i++){
printf("%c\n", b[i]);
}
getchar();
}
what is wrong with my logic?
Let's leave out CUDA for now. Let's just make a function that writes data to a user-provided array. The user passes the array via a pointer:
void fill_me_up(int * dst)
{
// We sure hope that `dst` points to a large enough area of memory!
dst[0] = 28;
dst[1] = 75;
}
Now, what you're doing with the local variable doesn't make sense, because you want to use the address of a local variable, which becomes invalid after you leave the function scope. The next best thing you could do is memcpy(), or some equivalent C++ algorithm:
void fill_me_up_again(int * dst)
{
int temp[] = { 28, 75 };
memcpy((void *)dst, (const void *)temp, sizeof(temp));
}
OK, now on to calling that function: We first must provide the target memory, and then pass a pointer:
int main()
{
int my_memory[2]; // here's our memory -- automatic local storage
fill_me_up(my_memory); // OK, array decays to pointer-to-beginning
fill_me_up(&my_memory[0]); // A bit more explicit
int * your_memory = malloc(sizeof(int) * 2); // more memory, this time dynamic
fill_me_up_again(your_memory);
/* ... */
free(your_memory);
}
(In C++ you would probably have uses new int[2] and delete your_memory instead, but by using C malloc() the connection to CUDA hopefully becomes clear.)
When you're moving fill_me_up to the CUDA device, you have to give it a device pointer rather than a host pointer, so you have to set that one up first and afterwards copy the results back out, but that's about the only change.