Connecteur C / MariaDB

Connecteur C / MariaDB - C - Programmation

Marsh Posté le 18-07-2019 à 15:15:01    

Salut, je galère...
 
Je souhaite faire une application en C qui récupère des données d'un broker MQTT pour les stocker dans une bdd MariaDB.
Je m'en sors globalement, sauf au moment de l'insertion du DATETIME.
 
Il m'a fallut déjà un jour pour comprendre que je ne pouvais pas mettre un simple string correctement formaté mais qu'il fallait une structure MYSQL_TIME. :o
Maintenant, le programme plante sans explication. Par d'erreur SQL, rien, ça sort du programme avec l'erreur suivante :  
 

Citation :

Program received signal SIGSEGV, Segmentation fault.
In mysql_stmt_warning_count () (C:\Users\c.dutriez\Documents\Programmation_EVO2\usage_evo2\bin\Debug\libmariadb.dll)
#3  0x00401f30 in main (argc=1, argv=0xd2ef0) at C:\Users\c.dutriez\Documents\Programmation_EVO2\usage_evo2\main.c:375
C:\Users\c.dutriez\Documents\Programmation_EVO2\usage_evo2\main.c:375:10954:beg:0x401f30
At C:\Users\c.dutriez\Documents\Programmation_EVO2\usage_evo2\main.c:375
#3  0x00401f30 in main (argc=1, argv=0xd2ef0) at C:\Users\c.dutriez\Documents\Programmation_EVO2\usage_evo2\main.c:375
C:\Users\c.dutriez\Documents\Programmation_EVO2\usage_evo2\main.c:375:10954:beg:0x401f30


 
 
voici une partie du programme :
 

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <mosquitto.h>
  5. #include <usage_evo2.h>
  6. #include <mysql.h>
  7. #include <time.h>
  8. char evo2msg[16];
  9. char evo2tps[20];
  10. int evo2grille;
  11. int evo2coiffe;
  12. int evo2ddv;
  13. int evo2vitessemoteur;
  14. int evo2consigne;
  15. int evo2cartouche;
  16. int evo2omron;
  17. MYSQL_TIME timestamp;
  18. char* getPayload (char *message);
  19. char* getTimestamp (char *message);
  20. void my_message_callback(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *message);
  21. void my_connect_callback(struct mosquitto *mosq, void *userdata, int result);
  22. void my_subscribe_callback(struct mosquitto *mosq, void *userdata, int mid, int qos_count, const int *granted_qos);
  23. void my_log_callback(struct mosquitto *mosq, void *userdata, int level, const char *str);
  24. static void show_mysql_error(MYSQL *mysql);
  25. static void show_stmt_error(MYSQL_STMT *stmt);
  26. int main(int argc, char *argv[]){
  27.     MYSQL *mysql;
  28.     MYSQL_STMT *stmt;
  29.     MYSQL_BIND bind[10];
  30.     timestamp.year = 2002;
  31.     timestamp.month = 10;
  32.     timestamp.day = 5;
  33.     timestamp.hour = 11;
  34.     timestamp.minute = 57;
  35.     timestamp.second = 34;
  36.     timestamp.
  37. /* MQTT parameters */
  38. char *host = "localhost";
  39. int port = 1883;
  40. int keepalive = 10;
  41. bool clean_session = true;
  42. struct mosquitto *mosq = NULL;
  43.  /* MYSQL parameters */
  44.     char *payload[] = {"0123456789ABCDEF"};
  45.     int omron[] = {0};
  46.     int coiffe[] = {0};
  47.     int grille[] = {0};
  48.     int vitesse_moteur[] = {0};
  49.     int ddv[] = {0};
  50.     int consigne[] = {0};
  51.     int defaut[] = {0};
  52.     unsigned long payload_length[]= {16};
  53.     char forename_ind[]= {STMT_INDICATOR_NTS};
  54.     char id_ind[]= {STMT_INDICATOR_NULL};
  55.     unsigned int array_size= 1;
  56. /* clock parameters */
  57. clock_t t1,t2;
  58. clock_t t_intervalle = 5000;
  59. mosquitto_lib_init();
  60. mosq = mosquitto_new("timestamp456", clean_session, NULL);
  61.  if(!mosq){
  62.  fprintf(stderr, "Error: Out of memory.\n" );
  63.  return 1;
  64. }
  65. /* callback fonctions */
  66. mosquitto_username_pw_set(mosq, "application", "timestamp456" );
  67. mosquitto_log_callback_set(mosq, my_log_callback);
  68. mosquitto_connect_callback_set(mosq, my_connect_callback);
  69. mosquitto_message_callback_set(mosq, my_message_callback);
  70. mosquitto_subscribe_callback_set(mosq, my_subscribe_callback);
  71. if(mosquitto_connect(mosq, host, port, keepalive)){
  72.  fprintf(stderr, "Unable to connect.\n" );
  73.  return 1;
  74. }
  75. mysql= mysql_init(NULL);
  76.     t2 = clock();
  77.     if (!mysql_real_connect(mysql, "localhost", "nom", "mdp","usage_db", 0, "/tmp/mysql.sock", 0)) show_mysql_error(mysql);
  78.     if (mysql_query(mysql, "DROP TABLE IF EXISTS bulk_example3" )) show_mysql_error(mysql);
  79.     if (mysql_query(mysql, "CREATE TABLE IF NOT EXISTS evo2_usage (\
  80.         id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,\
  81.         datemsg CHAR(20),\
  82.         message CHAR(16),\
  83.         omron SMALLINT,\
  84.         coiffe SMALLINT,\
  85.         grille SMALLINT,\
  86.         vitesse_moteur SMALLINT,\
  87.         ddv SMALLINT,\
  88.         consigne SMALLINT,\
  89.         cart SMALLINT)" )) show_mysql_error(mysql);
  90.     while(1){
  91.     t1 = clock();
  92.         if (t1-t2 > t_intervalle){
  93.             t2 = t1;
  94.             mosquitto_loop(mosq,-1,1);
  95.             payload[0]= evo2msg;
  96.             //timestamp[0]= evo2tps;
  97.             omron[0] = evo2omron;
  98.             coiffe[0] = evo2coiffe;
  99.             grille[0] = evo2grille;
  100.             vitesse_moteur[0] = evo2vitessemoteur;
  101.             ddv[0] = evo2ddv;
  102.             consigne[0] = evo2consigne;
  103.             defaut[0] = evo2cartouche;
  104.                 stmt= mysql_stmt_init(mysql);
  105.                 if (mysql_stmt_prepare(stmt, "INSERT INTO evo2_usage VALUES (?,?,?,?,?,?,?,?,?,?)", -1)){
  106.                     show_stmt_error(stmt);
  107.                     printf("ca plante la\n" );
  108.                 }
  109.                 memset(bind, 0, sizeof(MYSQL_BIND) * 10);
  110.                 /* We autogenerate id's, so all indicators are STMT_INDICATOR_NULL */
  111.                 bind[0].u.indicator= id_ind;
  112.                 bind[0].buffer_type= MYSQL_TYPE_LONG;
  113.                 bind[1].buffer= (char *)&timestamp;          //datetime
  114.                 bind[1].buffer_type= MYSQL_TYPE_DATETIME;
  115.                 bind[1].is_null= 0;
  116.                 bind[1].length= 0;
  117.                 bind[2].buffer= payload;                        // msg entier
  118.                 bind[2].buffer_type= MYSQL_TYPE_STRING;
  119.                 bind[2].length= payload_length;
  120.                 bind[3].buffer = omron;                         // OMRON (vent)
  121.                 bind[3].buffer_type= MYSQL_TYPE_LONG;
  122.                 bind[3].u.indicator= forename_ind;
  123.                 bind[4].buffer = coiffe;                        // coiffe
  124.                 bind[4].buffer_type= MYSQL_TYPE_LONG;
  125.                 bind[4].u.indicator= forename_ind;
  126.                 bind[5].buffer = grille;                        // grille
  127.                 bind[5].buffer_type= MYSQL_TYPE_LONG;
  128.                 bind[5].u.indicator= forename_ind;
  129.                 bind[6].buffer = vitesse_moteur;                // vitesse_moteur
  130.                 bind[6].buffer_type= MYSQL_TYPE_LONG;
  131.                 bind[6].u.indicator= forename_ind;
  132.                 bind[7].buffer = ddv;                           // ddv
  133.                 bind[7].buffer_type= MYSQL_TYPE_LONG;
  134.                 bind[7].u.indicator= forename_ind;
  135.                 bind[8].buffer = consigne;                      // consigne
  136.                 bind[8].buffer_type= MYSQL_TYPE_LONG;
  137.                 bind[8].u.indicator= forename_ind;
  138.                 bind[9].buffer = defaut;                        // défaut
  139.                 bind[9].buffer_type= MYSQL_TYPE_LONG;
  140.                 bind[9].u.indicator= forename_ind;
  141.                 /* set array size */
  142.                 mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size);
  143.                 /* bind parameter */
  144.                 mysql_stmt_bind_param(stmt, bind);
  145.                 printf("ERREUR" );
  146.                
  147.                 /* execute */
  148.                 if (mysql_stmt_execute(stmt))
  149.                 show_stmt_error(stmt);
  150.                 printf("INSCRIPTION" );
  151.             }
  152.     }
  153. mosquitto_destroy(mosq);
  154. mosquitto_lib_cleanup();
  155.     mysql_stmt_close(stmt);
  156.     mysql_close(mysql);
  157.     return 0;
  158. }


 
Pour info, j'ai bien le message ERREUR qui s'affiche, mais pas celui ISNCRIPTION, ça plante donc bien après le paramétrage de stmt, mais pendant son exécution.
Si vous avez une piste, je suis preneur. PS : si à la place de datetime, je remplace par n'importe quelle autre type de données (string, ....), la donnée s'inscrit dans la BDD sans problème.


Message édité par _pollux_ le 18-07-2019 à 15:26:50

---------------
Le topic du sport électronique@hfr : watch the l33t !
Reply

Marsh Posté le 18-07-2019 à 15:15:01   

Reply

Marsh Posté le 19-07-2019 à 18:51:38    

Je suppose que tu compiles déjà avec -Wall -Werror ou un truc semblable et que ça ne sors rien?
C'est quoi usage_evo2.h? Le moteur de recherche ne connaît pas...
Essaye de simplifier ton problème en virant la partie MQTT et si possible le evo_mystère, ça sera plus facile (même déjà possible) pour nous de compiler et débugger ce truc.

Reply

Marsh Posté le 20-07-2019 à 09:10:09    

bind[1].is_null= 0;
 bind[1].length= 0;
 [:sovxx]  
Si je lis bien la doc, https://dev.mysql.com/doc/refman/8. [...] tures.html
is_null is a pointer to a boolean scalar, not a boolean scalar,  
donc ça fait un premier truc qui me semble plantogène, et
For input parameter data binding, set *length to indicate the actual length of the parameter value stored in *buffer.
donc on devrait avoir  
size_t timesize = sizeof(MYSQL_TIME);
bind[1].buffer_type= MYSQL_TYPE_DATETIME;
bind[1].length=&timesize;  
bind[1].buffer_length=timesize;  
bind[1].buffer= (char *)&timestamp;
et ça devrait suffire, non?
 
A+,


Message édité par gilou le 20-07-2019 à 11:35:33

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 20-07-2019 à 09:41:51    

J'ai pas la main là dessus tout de suite, mais je promets de regarder ça de plus prêt :D

 

Comme je débute en C, je maitrise pas forcément très bien les pointeurs : par exemple, (char *)&timestamp, j'ai pas encore compris comment ça marche :D


Message édité par _pollux_ le 20-07-2019 à 13:18:51

---------------
Le topic du sport électronique@hfr : watch the l33t !
Reply

Marsh Posté le 20-07-2019 à 14:13:14    

Tu compiles bien avec -Wall -Werror? Indispensable pour un débutant, surtout quand on bricole les pointeurs! :o

Reply

Marsh Posté le 20-07-2019 à 18:16:08    

Oui, j'utilise code block et gcc. C'est par défaut et je n'ai aucune erreur. Mais j'ai pas encore eu le temps de tester les propositions de gilou. J'étais sur la doc de Maria DB, bien moins complète que celle de mysql.


Message édité par _pollux_ le 20-07-2019 à 18:16:28

---------------
Le topic du sport électronique@hfr : watch the l33t !
Reply

Marsh Posté le 22-07-2019 à 10:48:49    

Pour repartir sur de bonnes bases, la version épurée :

 
Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <mysql.h>
  5. static void show_mysql_error(MYSQL *mysql)
  6. {
  7.   printf("Error(%d) [%s] \"%s\"", mysql_errno(mysql),
  8.                                   mysql_sqlstate(mysql),
  9.                                   mysql_error(mysql));
  10.   exit(-1);
  11. }
  12. static void show_stmt_error(MYSQL_STMT *stmt)
  13. {
  14.   printf("Error(%d) [%s] \"%s\"", mysql_stmt_errno(stmt),
  15.                                   mysql_stmt_sqlstate(stmt),
  16.                                   mysql_stmt_error(stmt));
  17.   exit(-1);
  18. }
  19. int main(int argc, char *argv[])
  20. {
  21.   MYSQL *mysql;
  22.   MYSQL_STMT *stmt;
  23.   MYSQL_BIND bind[4];
  24.   MYSQL_TIME timestamp;
  25.   timestamp.year = 2000;
  26.   timestamp.month = 4;
  27.   timestamp.day = 21;
  28.   timestamp.hour = 5;
  29.   timestamp.minute = 23;
  30.   timestamp.second = 59;
  31.   /* Data for insert */
  32.   const char *surnames[]= {"pollux"};
  33.   unsigned long surnames_length[]= {10};
  34.   const char *forenames[]= {"dog"};
  35.   char forename_ind[]= {STMT_INDICATOR_NTS};
  36.   char id_ind[]= {STMT_INDICATOR_NULL};
  37.   unsigned int array_size= 1;
  38.   mysql= mysql_init(NULL);
  39.   /* connect to MariaDB server */
  40.   if (!mysql_real_connect(mysql, "localhost", "root", "wesh","usage_db", 0, "/tmp/mysql.sock", 0)) show_mysql_error(mysql);
  41.   if (mysql_query(mysql, "DROP TABLE IF EXISTS bulk_example1" ))
  42.     show_mysql_error(mysql);
  43.   if (mysql_query(mysql,"CREATE TABLE bulk_example1 (\
  44.                         id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,\
  45.                         forename CHAR(30) NOT NULL DEFAULT 'unknown',\
  46.                         surname CHAR(30),\
  47.                         date DATETIME)" ))
  48.     show_mysql_error(mysql);
  49.   stmt= mysql_stmt_init(mysql);
  50.   if (mysql_stmt_prepare(stmt, "INSERT INTO bulk_example1 VALUES (?,?,?,?)", -1))
  51.     show_stmt_error(stmt);
  52.   memset(bind, 0, sizeof(MYSQL_BIND) * 4);
  53.   /* We autogenerate id's, so all indicators are STMT_INDICATOR_NULL */
  54.   bind[0].u.indicator= id_ind;
  55.   bind[0].buffer_type= MYSQL_TYPE_LONG;
  56.   bind[1].buffer= forenames;
  57.   bind[1].buffer_type= MYSQL_TYPE_STRING;
  58.   bind[1].u.indicator= forename_ind;
  59.   bind[2].buffer_type= MYSQL_TYPE_STRING;
  60.   bind[2].buffer= surnames;
  61.   bind[2].length= surnames_length;
  62.   bind[3].buffer_type= MYSQL_TYPE_DATETIME;
  63.   bind[3].buffer = (char *)&timestamp;
  64.   bind[3].length = 0;
  65.   bind[3].is_null = 0;
  66.   /* set array size */
  67.   mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &array_size);
  68.   /* bind parameter */
  69.   mysql_stmt_bind_param(stmt, bind);
  70.   /* execute */
  71.   if (mysql_stmt_execute(stmt))
  72.     show_stmt_error(stmt);
  73.   mysql_stmt_close(stmt);
  74.   mysql_close(mysql);
  75.   return 0;
  76. }


Message édité par _pollux_ le 22-07-2019 à 10:54:29

---------------
Le topic du sport électronique@hfr : watch the l33t !
Reply

Marsh Posté le 22-07-2019 à 10:52:27    

En corrigeant avec la proposition de Gilou,

 


j'ai une erreur de type sur le &timesize. :

Code :
  1. size_t timesize = sizeof(MYSQL_TIME);
  2.     bind[3].buffer_type= MYSQL_TYPE_DATETIME;
  3.     bind[3].length=&timesize;
  4.     bind[3].buffer_length=timesize;
  5.     bind[3].buffer= (char *)&timestamp;
 


C:\C\test2\main.c|3|warning: assignment from incompatible pointer type.


Message édité par _pollux_ le 22-07-2019 à 10:55:09

---------------
Le topic du sport électronique@hfr : watch the l33t !
Reply

Marsh Posté le 22-07-2019 à 11:49:18    

Tu remplaces 1 par  
unsigned long timesize = sizeof(MYSQL_TIME);
et ça devrait coller.
 
Et comme buffer devrait être un void *, au vu de la doc, tu peux aussi tant que tu y es faire pour 5
bind[3].buffer= (void *)&timestamp;
 
A+,


Message édité par gilou le 22-07-2019 à 12:00:52

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 22-07-2019 à 12:26:56    

ça marche mieux ! enfin, j'en reviens au départ, ça compile avec des données sans doute mieux traitées.

 

Par contre :/ :

Citation :

Program received signal SIGSEGV, Segmentation fault.
In mysql_stmt_warning_count () (C:\C\test2\bin\Debug\libmariadb.dll)
#3  0x00401652 in main (argc=1, argv=0x852ee8) at C:\C\test2\main.c:95
C:\C\test2\main.c:95:2658:beg:0x401652
At C:\C\test2\main.c:95
#3  0x00401652 in main (argc=1, argv=0x852ee8) at C:\C\test2\main.c:95
C:\C\test2\main.c:95:2658:beg:0x401652

 

D'autre part, sachant que :

Citation :

length is ignored for numeric and temporal data types because the buffer_type value determines the length of the data value.

 

J'ai carrément viré la ligne 3, mais ça ne change rien au problème.


Message édité par _pollux_ le 22-07-2019 à 16:01:17

---------------
Le topic du sport électronique@hfr : watch the l33t !
Reply

Marsh Posté le 22-07-2019 à 12:26:56   

Reply

Marsh Posté le 22-07-2019 à 16:35:37    

Bon désolé, j'ai finalement réussi à compiler le truc mais je sais pas le faire fonctionner, pourtant j'ai investi du temps...

 

Pour ceux qui veulent tester et qui sont sous Debian faut être sous Debian 10.

Message cité 1 fois
Message édité par rat de combat le 22-07-2019 à 16:37:45
Reply

Marsh Posté le 22-07-2019 à 16:49:35    

Merci d'avoir essayé en tout cas :o

 

J'vais essayer de contacter les dev via IRC, parce que je suis bien coincé là :/
ça fait un peu 4 jours que je suis sur cette connerie.


Message édité par _pollux_ le 22-07-2019 à 16:50:00

---------------
Le topic du sport électronique@hfr : watch the l33t !
Reply

Marsh Posté le 22-07-2019 à 17:08:12    

rat de combat a écrit :

Bon désolé, j'ai finalement réussi à compiler le truc mais je sais pas le faire fonctionner, pourtant j'ai investi du temps...
 
Pour ceux qui veulent tester et qui sont sous Debian faut être sous Debian 10.


pourquoi Debian 10 d'ailleurs ?  
 
(j'suis sous windows  [:cerveau eric] )


---------------
Le topic du sport électronique@hfr : watch the l33t !
Reply

Marsh Posté le 22-07-2019 à 18:24:11    

sinon, j'ai trouvé cette page là dans la doc de MYSQL :  
 
https://dev.mysql.com/doc/refman/8. [...] dling.html
mais ça m'aide pas trop :/
 


---------------
Le topic du sport électronique@hfr : watch the l33t !
Reply

Marsh Posté le 22-07-2019 à 18:32:11    

_pollux_ a écrit :


pourquoi Debian 10 d'ailleurs ?  
 
(j'suis sous windows  [:cerveau eric] )

Parce que il faut une version assez récente de MariaDB et celle de Debian 9 semble trop ancienne. J'ai pas poussé trop loin, j'ai changé de machine virtuelle.

Reply

Marsh Posté le 22-07-2019 à 18:34:53    

ok.

 

Bon, personne ne répond sur IRC, semblerait qu'il y ait des plages horaires pour les réponses :D ... par désespoir, j'ai laissé un message ici : https://mariadb.zulipchat.com/#narr [...] ew-members
C'est compliqué de joindre les teams de dev maintenant, on est loin de la facilité d'un forum :o


Message édité par _pollux_ le 22-07-2019 à 18:35:28

---------------
Le topic du sport électronique@hfr : watch the l33t !
Reply

Marsh Posté le 24-07-2019 à 14:25:16    

Bon, problème non résolu frontalement. Cependant, d'un strict point de vue fonctionnel, j'ai fait sans "prepared statement functions" et ça marche.


---------------
Le topic du sport électronique@hfr : watch the l33t !
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed