1 /**
2  *
3  * Hoel database abstraction library
4  *
5  * hoel.c: main functions
6  *
7  * Copyright 2015-2016 Nicolas Mora <mail@babelouest.org>
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation;
12  * version 2.1 of the License.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU GENERAL PUBLIC LICENSE for more details.
18  *
19  * You should have received a copy of the GNU General Public
20  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23 #include <ctype.h>
24 #include <string.h>
25 
26 #include "hoel.h"
27 #include "h-private.h"
28 
29 /**
30  * free data allocated by hoel functions
31  */
h_free(void * data)32 void h_free(void * data) {
33   o_free(data);
34 }
35 
36 /**
37  * Close a database connection
38  * return H_OK on success
39  */
h_close_db(struct _h_connection * conn)40 int h_close_db(struct _h_connection * conn) {
41   if (conn != NULL && conn->connection != NULL) {
42     if (0) {
43       /* Not happening */
44 #ifdef _HOEL_SQLITE
45     } else if (conn->type == HOEL_DB_TYPE_SQLITE) {
46       h_close_sqlite(conn);
47       return H_OK;
48 #endif
49 #ifdef _HOEL_MARIADB
50     } else if (conn->type == HOEL_DB_TYPE_MARIADB) {
51       h_close_mariadb(conn);
52       return H_OK;
53 #endif
54 #ifdef _HOEL_PGSQL
55     } else if (conn->type == HOEL_DB_TYPE_PGSQL) {
56       h_close_pgsql(conn);
57       return H_OK;
58 #endif
59     } else {
60       return H_ERROR_PARAMS;
61     }
62   } else {
63     return H_ERROR_PARAMS;
64   }
65 }
66 
67 /**
68  * h_escape_string
69  * Escapes a string
70  * returned value must be free'd after use
71  */
h_escape_string(const struct _h_connection * conn,const char * unsafe)72 char * h_escape_string(const struct _h_connection * conn, const char * unsafe) {
73   if (conn != NULL && conn->connection != NULL && unsafe != NULL) {
74     if (0) {
75       /* Not happening */
76 #ifdef _HOEL_SQLITE
77     } else if (conn->type == HOEL_DB_TYPE_SQLITE) {
78       return h_escape_string_sqlite(conn, unsafe);
79 #endif
80 #ifdef _HOEL_MARIADB
81     } else if (conn->type == HOEL_DB_TYPE_MARIADB) {
82       return h_escape_string_mariadb(conn, unsafe);
83 #endif
84 #ifdef _HOEL_PGSQL
85     } else if (conn->type == HOEL_DB_TYPE_PGSQL) {
86       return h_escape_string_pgsql(conn, unsafe);
87 #endif
88     } else {
89       return NULL;
90     }
91   } else {
92     return NULL;
93   }
94 }
95 
96 /**
97  * h_escape_string_with_quotes
98  * Escapes a string and returns it ready to be inserted in the query
99  * returned value must be h_h_free'd after use
100  */
h_escape_string_with_quotes(const struct _h_connection * conn,const char * unsafe)101 char * h_escape_string_with_quotes(const struct _h_connection * conn, const char * unsafe) {
102   if (conn != NULL && conn->connection != NULL && unsafe != NULL) {
103     if (0) {
104       /* Not happening */
105 #ifdef _HOEL_SQLITE
106     } else if (conn->type == HOEL_DB_TYPE_SQLITE) {
107       return h_escape_string_with_quotes_sqlite(conn, unsafe);
108 #endif
109 #ifdef _HOEL_MARIADB
110     } else if (conn->type == HOEL_DB_TYPE_MARIADB) {
111       return h_escape_string_with_quotes_mariadb(conn, unsafe);
112 #endif
113 #ifdef _HOEL_PGSQL
114     } else if (conn->type == HOEL_DB_TYPE_PGSQL) {
115       return h_escape_string_with_quotes_pgsql(conn, unsafe);
116 #endif
117     } else {
118       return NULL;
119     }
120   } else {
121     return NULL;
122   }
123 }
124 
125 /**
126  * h_execute_query
127  * Execute a query, set the result structure with the returned values if available
128  * if result is NULL, the query is executed but no value will be returned
129  * options available
130  * H_OPTION_NONE (0): no option
131  * H_OPTION_SELECT: Execute a prepare statement (sqlite only)
132  * H_OPTION_EXEC: Execute an exec statement (sqlite only)
133  * return H_OK on success
134  */
h_execute_query(const struct _h_connection * conn,const char * query,struct _h_result * result,int options)135 int h_execute_query(const struct _h_connection * conn, const char * query, struct _h_result * result, int options) {
136   if (conn != NULL && conn->connection != NULL && query != NULL) {
137     if (0) {
138       /* Not happening */
139 #ifdef _HOEL_SQLITE
140     } else if (conn->type == HOEL_DB_TYPE_SQLITE) {
141       if (options & H_OPTION_EXEC) {
142         return h_exec_query_sqlite(conn, query);
143       } else {
144         return h_select_query_sqlite(conn, query, result);
145       }
146 #else
147       UNUSED(options);
148 #endif
149 #ifdef _HOEL_MARIADB
150     } else if (conn->type == HOEL_DB_TYPE_MARIADB) {
151       return h_execute_query_mariadb(conn, query, result);
152 #endif
153 #ifdef _HOEL_PGSQL
154     } else if (conn->type == HOEL_DB_TYPE_PGSQL) {
155       return h_execute_query_pgsql(conn, query, result);
156 #endif
157     } else {
158       return H_ERROR_PARAMS;
159     }
160   } else {
161     return H_ERROR_PARAMS;
162   }
163 }
164 
165 /**
166  * h_execute_query_json
167  * Execute a query, set the returned values in the json result
168  * return H_OK on success
169  */
h_execute_query_json(const struct _h_connection * conn,const char * query,json_t ** j_result)170 int h_execute_query_json(const struct _h_connection * conn, const char * query, json_t ** j_result) {
171   if (conn != NULL && conn->connection != NULL && query != NULL && j_result != NULL) {
172     if (0) {
173       /* Not happening */
174 #ifdef _HOEL_SQLITE
175     } else if (conn->type == HOEL_DB_TYPE_SQLITE) {
176       return h_execute_query_json_sqlite(conn, query, j_result);
177 #endif
178 #ifdef _HOEL_MARIADB
179     } else if (conn->type == HOEL_DB_TYPE_MARIADB) {
180       return h_execute_query_json_mariadb(conn, query, j_result);
181 #endif
182 #ifdef _HOEL_PGSQL
183     } else if (conn->type == HOEL_DB_TYPE_PGSQL) {
184       return h_execute_query_json_pgsql(conn, query, j_result);
185 #endif
186     } else {
187       return H_ERROR_PARAMS;
188     }
189   } else {
190     return H_ERROR_PARAMS;
191   }
192 }
193 
194 /**
195  * Add a new struct _h_data * to an array of struct _h_data *, which already has cols columns
196  * return H_OK on success
197  */
h_row_add_data(struct _h_data ** row,struct _h_data * data,int cols)198 int h_row_add_data(struct _h_data ** row, struct _h_data * data, int cols) {
199   struct _h_data * tmp = o_realloc(*row, (cols+1)*sizeof(struct _h_data));
200   * row = tmp;
201   if (tmp == NULL) {
202     y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for h_row_add_data");
203     return H_ERROR_MEMORY;
204   } else {
205     switch (data->type) {
206       case HOEL_COL_TYPE_INT:
207         tmp[cols].type = HOEL_COL_TYPE_INT;
208         tmp[cols].t_data = o_malloc(sizeof(struct _h_type_int));
209         if (tmp[cols].t_data == NULL) {
210           y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for tmp[cols].t_data");
211           return H_ERROR_MEMORY;
212         } else {
213           ((struct _h_type_int *)tmp[cols].t_data)->value = ((struct _h_type_int *)data->t_data)->value;
214           return H_OK;
215         }
216         break;
217       case HOEL_COL_TYPE_DOUBLE:
218         tmp[cols].type = HOEL_COL_TYPE_DOUBLE;
219         tmp[cols].t_data = o_malloc(sizeof(struct _h_type_double));
220         if (tmp[cols].t_data == NULL) {
221           y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for tmp[cols].t_data");
222           return H_ERROR_MEMORY;
223         } else {
224           ((struct _h_type_double *)tmp[cols].t_data)->value = ((struct _h_type_double *)data->t_data)->value;
225           return H_OK;
226         }
227         break;
228       case HOEL_COL_TYPE_TEXT:
229         tmp[cols].type = HOEL_COL_TYPE_TEXT;
230         tmp[cols].t_data = o_malloc(sizeof(struct _h_type_text));
231         if (tmp[cols].t_data == NULL) {
232           y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for tmp[cols].t_data");
233           return H_ERROR_MEMORY;
234         } else {
235           ((struct _h_type_text *)tmp[cols].t_data)->value = o_malloc(((struct _h_type_text *)data->t_data)->length+sizeof(char));
236           if (((struct _h_type_text *)tmp[cols].t_data)->value == NULL) {
237             y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for ((struct _h_type_text *)tmp[cols].t_data)->value");
238             o_free(tmp[cols].t_data);
239             return H_ERROR_MEMORY;
240           }
241           memcpy(((struct _h_type_text *)tmp[cols].t_data)->value, ((struct _h_type_text *)data->t_data)->value, (((struct _h_type_text *)data->t_data)->length+1));
242           ((struct _h_type_text *)tmp[cols].t_data)->length = ((struct _h_type_text *)data->t_data)->length;
243           return H_OK;
244         }
245         break;
246       case HOEL_COL_TYPE_BLOB:
247         tmp[cols].type = HOEL_COL_TYPE_BLOB;
248         tmp[cols].t_data = o_malloc(sizeof(struct _h_type_blob));
249         if (tmp[cols].t_data == NULL) {
250           y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for tmp[cols].t_data");
251           return H_ERROR_MEMORY;
252         } else {
253           ((struct _h_type_blob *)tmp[cols].t_data)->length = ((struct _h_type_blob *)data->t_data)->length;
254           ((struct _h_type_blob *)tmp[cols].t_data)->value = o_malloc(((struct _h_type_blob *)data->t_data)->length);
255           if (((struct _h_type_blob *)tmp[cols].t_data)->value == NULL) {
256             y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for ((struct _h_type_blob *)tmp[cols].t_data)->value");
257             o_free(tmp[cols].t_data);
258             return H_ERROR_MEMORY;
259           }
260           memcpy(((struct _h_type_blob *)tmp[cols].t_data)->value, ((struct _h_type_blob *)data->t_data)->value, ((struct _h_type_blob *)data->t_data)->length);
261           return H_OK;
262         }
263         break;
264       case HOEL_COL_TYPE_DATE:
265         tmp[cols].type = HOEL_COL_TYPE_DATE;
266         tmp[cols].t_data = o_malloc(sizeof(struct _h_type_datetime));
267         if (tmp[cols].t_data == NULL) {
268           y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for tmp[cols].t_data");
269           return H_ERROR_MEMORY;
270         } else {
271           ((struct _h_type_datetime *)tmp[cols].t_data)->value = ((struct _h_type_datetime *)data->t_data)->value;
272           return H_OK;
273         }
274         break;
275       case HOEL_COL_TYPE_NULL:
276         tmp[cols].type = HOEL_COL_TYPE_NULL;
277         tmp[cols].t_data = NULL;
278         break;
279       default:
280         return H_ERROR_PARAMS;
281         break;
282     }
283     return H_OK;
284   }
285 }
286 
287 /**
288  * Add a new row of struct _h_data * in a struct _h_result *
289  * return H_OK on success
290  */
h_result_add_row(struct _h_result * result,struct _h_data * row,int rows)291 int h_result_add_row(struct _h_result * result, struct _h_data * row, int rows) {
292   result->data = o_realloc(result->data, (rows+1)*sizeof(struct _h_data *));
293   if (result->data == NULL) {
294     y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for result->data");
295     return H_ERROR_MEMORY;
296   } else {
297     result->data[rows] = row;
298     result->nb_rows++;
299     return H_OK;
300   }
301 }
302 
303 /**
304  * h_query_insert
305  * Execute an insert query
306  * return H_OK on success
307  */
h_query_insert(const struct _h_connection * conn,const char * query)308 int h_query_insert(const struct _h_connection * conn, const char * query) {
309   if (conn != NULL && conn->connection != NULL && query != NULL && o_strcasestr(query, "insert") != NULL) {
310     return h_execute_query(conn, query, NULL, H_OPTION_EXEC);
311   } else {
312     return H_ERROR_PARAMS;
313   }
314 }
315 
316 /**
317  * h_query_last_insert_id
318  * return the id of the last inserted value
319  * return H_OK on success
320  */
h_query_last_insert_id(const struct _h_connection * conn)321 struct _h_data * h_query_last_insert_id(const struct _h_connection * conn) {
322   struct _h_data * data = NULL;
323   if (conn != NULL && conn->connection != NULL) {
324     if (0) {
325       /* Not happening */
326 #ifdef _HOEL_SQLITE
327     } else if (conn->type == HOEL_DB_TYPE_SQLITE) {
328       int last_id = h_last_insert_id_sqlite(conn);
329       if (last_id > 0) {
330         data = h_new_data_int(last_id);
331       } else {
332         data = h_new_data_null();
333       }
334 #endif
335 #ifdef _HOEL_MARIADB
336     } else if (conn->type == HOEL_DB_TYPE_MARIADB) {
337       int last_id = h_last_insert_id_mariadb(conn);
338       if (last_id > 0) {
339         data = h_new_data_int(last_id);
340       } else {
341         data = h_new_data_null();
342       }
343 #endif
344 #ifdef _HOEL_PGSQL
345     } else if (conn->type == HOEL_DB_TYPE_PGSQL) {
346       int last_id = h_last_insert_id_pgsql(conn);
347       if (last_id > 0) {
348         data = h_new_data_int(last_id);
349       } else {
350         data = h_new_data_null();
351       }
352 #endif
353     } else {
354       data = h_new_data_null();
355     }
356   }
357   return data;
358 }
359 
360 /**
361  * h_query_update
362  * Execute an update query
363  * return H_OK on success
364  */
h_query_update(const struct _h_connection * conn,const char * query)365 int h_query_update(const struct _h_connection * conn, const char * query) {
366   if (conn != NULL && conn->connection != NULL && query != NULL && o_strcasestr(query, "update") != NULL) {
367     return h_execute_query(conn, query, NULL, H_OPTION_EXEC);
368   } else {
369     return H_ERROR_PARAMS;
370   }
371 }
372 
373 /**
374  * h_query_delete
375  * Execute an delete query
376  * return H_OK on success
377  */
h_query_delete(const struct _h_connection * conn,const char * query)378 int h_query_delete(const struct _h_connection * conn, const char * query) {
379   if (conn != NULL && conn->connection != NULL && query != NULL && o_strcasestr(query, "delete") != NULL) {
380     return h_execute_query(conn, query, NULL, H_OPTION_EXEC);
381   } else {
382     return H_ERROR_PARAMS;
383   }
384 }
385 
386 /**
387  * h_query_select
388  * Execute a select query, set the result structure with the returned values
389  * return H_OK on success
390  */
h_query_select(const struct _h_connection * conn,const char * query,struct _h_result * result)391 int h_query_select(const struct _h_connection * conn, const char * query, struct _h_result * result) {
392   if (conn != NULL && conn->connection != NULL && query != NULL && o_strcasestr(query, "select") != NULL) {
393     return h_execute_query(conn, query, result, H_OPTION_SELECT);
394   } else {
395     return H_ERROR_PARAMS;
396   }
397 }
398 
399 /**
400  * h_query_select_json
401  * Execute a select query, set the returned values in the json results
402  * return H_OK on success
403  */
h_query_select_json(const struct _h_connection * conn,const char * query,json_t ** j_result)404 int h_query_select_json(const struct _h_connection * conn, const char * query, json_t ** j_result) {
405   if (conn != NULL && conn->connection != NULL && query != NULL && o_strcasestr(query, "select") != NULL) {
406     return h_execute_query_json(conn, query, j_result);
407   } else {
408     return H_ERROR_PARAMS;
409   }
410 }
411 
412 /**
413  * h_clean_result
414  * Free all the memory allocated by the struct _h_result
415  */
h_clean_result(struct _h_result * result)416 int h_clean_result(struct _h_result * result) {
417   unsigned int col, row;
418   if (result != NULL) {
419     for (row=0; row<result->nb_rows; row++) {
420       for (col=0; col<result->nb_columns; col++) {
421         if (h_clean_data(&result->data[row][col]) != H_OK) {
422           return H_ERROR_MEMORY;
423         }
424       }
425       o_free(result->data[row]);
426     }
427     o_free(result->data);
428     return H_OK;
429   } else {
430     return H_ERROR_PARAMS;
431   }
432 }
433 
434 /**
435  * h_clean_data
436  * Free memory allocated by the struct _h_data
437  * return H_OK on success
438  */
h_clean_data(struct _h_data * data)439 int h_clean_data(struct _h_data * data) {
440   if (data != NULL) {
441     if (data->type == HOEL_COL_TYPE_TEXT) {
442       o_free(((struct _h_type_text *)data->t_data)->value);
443     } else if (data->type == HOEL_COL_TYPE_BLOB) {
444       o_free(((struct _h_type_blob *)data->t_data)->value);
445     }
446     if (data->t_data != NULL) {
447       o_free(data->t_data);
448     }
449     return H_OK;
450   } else {
451     return H_ERROR_PARAMS;
452   }
453 }
454 
455 /**
456  * h_clean_data_full
457  * Free memory allocated by the struct _h_data and the struct _h_data pointer
458  * return H_OK on success
459  */
h_clean_data_full(struct _h_data * data)460 int h_clean_data_full(struct _h_data * data) {
461   if (data != NULL) {
462     h_clean_data(data);
463     o_free(data);
464     return H_OK;
465   } else {
466     return H_ERROR_PARAMS;
467   }
468 }
469 
470 /**
471  * Allocate memory for a new struct _h_data * containing an int
472  * return pointer to the new structure
473  * return NULL on error
474  */
h_new_data_int(const long long int value)475 struct _h_data * h_new_data_int(const long long int value) {
476   struct _h_data * data = o_malloc(sizeof(struct _h_data));
477   if (data != NULL) {
478     data->t_data = o_malloc(sizeof(struct _h_type_int));
479     if (data->t_data == NULL) {
480       y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for data->t_data");
481       o_free(data);
482       return NULL;
483     }
484     data->type = HOEL_COL_TYPE_INT;
485     ((struct _h_type_int *)data->t_data)->value = value;
486   } else {
487     y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for data");
488   }
489   return data;
490 }
491 
492 /**
493  * Allocate memory for a new struct _h_data * containing a double
494  * return pointer to the new structure
495  * return NULL on error
496  */
h_new_data_double(const double value)497 struct _h_data * h_new_data_double(const double value) {
498   struct _h_data * data = o_malloc(sizeof(struct _h_data));
499   if (data != NULL) {
500     data->t_data = o_malloc(sizeof(struct _h_type_double));
501     if (data->t_data == NULL) {
502       y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for data->t_data");
503       o_free(data);
504       return NULL;
505     }
506     data->type = HOEL_COL_TYPE_DOUBLE;
507     ((struct _h_type_double *)data->t_data)->value = value;
508   } else {
509     y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for data");
510   }
511   return data;
512 }
513 
514 /**
515  * Allocate memory for a new struct _h_data * containing a text
516  * return pointer to the new structure
517  * return NULL on error
518  */
h_new_data_text(const char * value,const size_t length)519 struct _h_data * h_new_data_text(const char * value, const size_t length) {
520   struct _h_data * data = o_malloc(sizeof(struct _h_data));
521   if (data != NULL) {
522     data->t_data = o_malloc(sizeof(struct _h_type_text));
523     if (data->t_data == NULL) {
524       y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for data->t_data");
525       o_free(data);
526       return NULL;
527     }
528     data->type = HOEL_COL_TYPE_TEXT;
529     ((struct _h_type_text *)data->t_data)->value = o_malloc(length+sizeof(char));
530     if (((struct _h_type_text *)data->t_data)->value == NULL) {
531       y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for data->t_data->value");
532       o_free(data);
533       return NULL;
534     } else {
535       memcpy(((struct _h_type_text *)data->t_data)->value, value, length);
536       ((struct _h_type_text *)data->t_data)->length = length;
537       ((struct _h_type_text *)data->t_data)->value[length] = '\0';
538     }
539   } else {
540     y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for data");
541   }
542   return data;
543 }
544 
545 /**
546  * Allocate memory for a new struct _h_data * containing a blob
547  * return pointer to the new structure
548  * return NULL on error
549  */
h_new_data_blob(const void * value,const size_t length)550 struct _h_data * h_new_data_blob(const void * value, const size_t length) {
551   struct _h_data * data = o_malloc(sizeof(struct _h_data));
552   if (data != NULL) {
553     data->t_data = o_malloc(sizeof(struct _h_type_blob));
554     if (data->t_data == NULL) {
555       y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for data");
556       o_free(data);
557       return NULL;
558     }
559     data->type = HOEL_COL_TYPE_BLOB;
560     ((struct _h_type_blob *)data->t_data)->length = length;
561     ((struct _h_type_blob *)data->t_data)->value = o_malloc(length);
562     if (((struct _h_type_blob *)data->t_data)->value == NULL) {
563       y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for t_data->value");
564       o_free(data);
565       return NULL;
566     } else {
567       memcpy(((struct _h_type_blob *)data->t_data)->value, value, length);
568     }
569   } else {
570     y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for data");
571   }
572   return data;
573 }
574 
575 /**
576  * Allocate memory for a new struct _h_data * containing a null value
577  * return pointer to the new structure
578  * return NULL on error
579  */
h_new_data_null()580 struct _h_data * h_new_data_null() {
581   struct _h_data * data = o_malloc(sizeof(struct _h_data));
582   if (data != NULL) {
583     data->type = HOEL_COL_TYPE_NULL;
584     data->t_data = NULL;
585   } else {
586     y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for data");
587   }
588   return data;
589 }
590 
591 /**
592  * Allocate memory for a new struct _h_data * containing a date time structure
593  * return pointer to the new structure
594  * return NULL on error
595  */
h_new_data_datetime(const struct tm * datetime)596 struct _h_data * h_new_data_datetime(const struct tm * datetime) {
597   struct _h_data * data = NULL;
598   if (datetime != NULL) {
599     data = o_malloc(sizeof(struct _h_data));
600     if (data != NULL) {
601       data->type = HOEL_COL_TYPE_DATE;
602       data->t_data = o_malloc(sizeof(struct _h_type_datetime));
603 
604       if (data->t_data == NULL) {
605         y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for data->t_data");
606         o_free(data);
607         return NULL;
608       }
609       ((struct _h_type_datetime *)data->t_data)->value = * datetime;
610     } else {
611       y_log_message(Y_LOG_LEVEL_ERROR, "Hoel - Error allocating memory for data");
612     }
613   }
614   return data;
615 }
616 
617 /**
618  * h_clean_connection
619  * free memory allocated by the struct _h_connection
620  * return H_OK on success
621  */
h_clean_connection(struct _h_connection * conn)622 int h_clean_connection(struct _h_connection * conn) {
623   if (conn != NULL) {
624     o_free(conn->connection);
625     o_free(conn);
626     return H_OK;
627   } else {
628     return H_ERROR_PARAMS;
629   }
630 }
631