Browse code

core, lib, modules: restructured source code tree

- new folder src/ to hold the source code for main project applications
- main.c is in src/
- all core files are subfolder are in src/core/
- modules are in src/modules/
- libs are in src/lib/
- application Makefiles are in src/
- application binary is built in src/ (src/kamailio)

Daniel-Constantin Mierla authored on 07/12/2016 11:03:51
Showing 1 changed files
1 1
deleted file mode 100644
... ...
@@ -1,1370 +0,0 @@
1
-/* 
2
- * Copyright (C) 2001-2003 FhG Fokus
3
- * Copyright (C) 2006-2007 iptelorg GmbH
4
- *
5
- * This file is part of Kamailio, a free SIP server.
6
- *
7
- * Kamailio is free software; you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License as published by
9
- * the Free Software Foundation; either version 2 of the License, or
10
- * (at your option) any later version
11
- *
12
- * Kamailio is distributed in the hope that it will be useful,
13
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
- * GNU General Public License for more details.
16
- *
17
- * You should have received a copy of the GNU General Public License 
18
- * along with this program; if not, write to the Free Software 
19
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20
- */
21
-
22
-/** @addtogroup mysql
23
- *  @{
24
- */
25
-
26
-/* the following macro will break the compile on solaris */
27
-#if !defined (__SVR4) && !defined (__sun)
28
-   #define _XOPEN_SOURCE 4     /* bsd */
29
-#endif
30
-#define _XOPEN_SOURCE_EXTENDED 1    /* solaris */
31
-#define _SVID_SOURCE 1 /* timegm */
32
-#define _DEFAULT_SOURCE 1 /* _SVID_SOURCE is deprecated */
33
-
34
-#include "my_cmd.h"
35
-
36
-#include "my_con.h"
37
-#include "db_mysql.h"
38
-#include "my_fld.h"
39
-
40
-#include "../../mem/mem.h"
41
-#include "../../str.h"
42
-#include "../../lib/srdb2/db_cmd.h"
43
-#include "../../ut.h"
44
-#include "../../dprint.h"
45
-
46
-#include <strings.h>
47
-#include <stdio.h>
48
-#include <time.h>  /*strptime, XOPEN issue must be >=4 */
49
-#include <string.h>
50
-#include <errmsg.h>
51
-#include <mysqld_error.h>
52
-
53
-#define STR_BUF_SIZE 1024
54
-
55
-#ifdef MYSQL_FAKE_NULL
56
-
57
-#define FAKE_NULL_STRING "[~NULL~]"
58
-static str  FAKE_NULL_STR = STR_STATIC_INIT(FAKE_NULL_STRING);
59
-
60
-/* avoid warning: this decimal constant is unsigned only in ISO C90 :-) */
61
-#define FAKE_NULL_INT (-2147483647 - 1)
62
-#endif
63
-
64
-enum {
65
-	STR_DELETE,
66
-	STR_INSERT,
67
-	STR_UPDATE,
68
-	STR_SELECT,
69
-	STR_REPLACE,
70
-	STR_SET,
71
-	STR_WHERE,
72
-	STR_IS,
73
-	STR_AND,
74
-	STR_OR,
75
-	STR_ESC,
76
-	STR_OP_EQ,
77
-	STR_OP_NE,
78
-	STR_OP_LT,
79
-	STR_OP_GT,
80
-	STR_OP_LEQ,
81
-	STR_OP_GEQ,
82
-	STR_VALUES,
83
-	STR_FROM
84
-};
85
-
86
-static str strings[] = {
87
-	STR_STATIC_INIT("delete from "),
88
-	STR_STATIC_INIT("insert into "),
89
-	STR_STATIC_INIT("update "),
90
-	STR_STATIC_INIT("select "),
91
-	STR_STATIC_INIT("replace "),
92
-	STR_STATIC_INIT(" set "),
93
-	STR_STATIC_INIT(" where "),
94
-	STR_STATIC_INIT(" is "),
95
-	STR_STATIC_INIT(" and "),
96
-	STR_STATIC_INIT(" or "),
97
-	STR_STATIC_INIT("?"),
98
-	STR_STATIC_INIT("="),
99
-	STR_STATIC_INIT("!="),
100
-	STR_STATIC_INIT("<"),
101
-	STR_STATIC_INIT(">"),
102
-	STR_STATIC_INIT("<="),
103
-	STR_STATIC_INIT(">="),
104
-	STR_STATIC_INIT(") values ("),
105
-	STR_STATIC_INIT(" from ")
106
-};
107
-
108
-
109
-#define APPEND_STR(p, str) do {		 \
110
-	memcpy((p), (str).s, (str).len); \
111
-	(p) += (str).len;				 \
112
-} while(0)
113
-
114
-
115
-#define APPEND_CSTR(p, cstr) do { \
116
-    int _len = strlen(cstr);      \
117
-	memcpy((p), (cstr), _len);	  \
118
-	(p) += _len;				  \
119
-} while(0)
120
-
121
-
122
-static int upload_cmd(db_cmd_t* cmd);
123
-
124
-
125
-static void my_cmd_free(db_cmd_t* cmd, struct my_cmd* payload)
126
-{
127
-	db_drv_free(&payload->gen);
128
-	if (payload->sql_cmd.s) pkg_free(payload->sql_cmd.s);
129
-	if (payload->st) mysql_stmt_close(payload->st);
130
-	pkg_free(payload);
131
-}
132
-
133
-
134
-/** Builds a DELETE SQL statement.The function builds DELETE statement where
135
- * cmd->match specify WHERE clause.  
136
- * @param sql_cmd SQL statement as a result of this function 
137
- * @param cmd input for statement creation
138
- * @return -1 on error, 0 on success
139
- */
140
-static int build_delete_cmd(str* sql_cmd, db_cmd_t* cmd)
141
-{
142
-	db_fld_t* fld;
143
-	int i;
144
-	char* p;
145
-
146
-	sql_cmd->len = strings[STR_DELETE].len;
147
-	sql_cmd->len += cmd->table.len;
148
-
149
-	if (!DB_FLD_EMPTY(cmd->match)) {
150
-		sql_cmd->len += strings[STR_WHERE].len;
151
-
152
-		for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) {
153
-			sql_cmd->len += strlen(fld[i].name);
154
-
155
-			switch(fld[i].op) {
156
-			case DB_EQ:  sql_cmd->len += strings[STR_OP_EQ].len; break;
157
-			case DB_NE:  sql_cmd->len += strings[STR_OP_NE].len; break;
158
-			case DB_LT:  sql_cmd->len += strings[STR_OP_LT].len; break;
159
-			case DB_GT:  sql_cmd->len += strings[STR_OP_GT].len; break;
160
-			case DB_LEQ: sql_cmd->len += strings[STR_OP_LEQ].len; break;
161
-			case DB_GEQ: sql_cmd->len += strings[STR_OP_GEQ].len; break;
162
-			default:
163
-				ERR("mysql: Unsupported db_fld operator %d\n", fld[i].op);
164
-				return -1;
165
-			}
166
-
167
-			sql_cmd->len += strings[STR_ESC].len;
168
-			
169
-			if (!DB_FLD_LAST(fld[i + 1])) sql_cmd->len += strings[STR_AND].len;
170
-		}
171
-	}
172
-
173
-	sql_cmd->s = pkg_malloc(sql_cmd->len + 1);
174
-	if (sql_cmd->s == NULL) {
175
-		ERR("mysql: No memory left\n");
176
-		return -1;
177
-	}
178
-	p = sql_cmd->s;
179
-	
180
-	APPEND_STR(p, strings[STR_DELETE]);
181
-	APPEND_STR(p, cmd->table);
182
-
183
-	if (!DB_FLD_EMPTY(cmd->match)) {
184
-		APPEND_STR(p, strings[STR_WHERE]);
185
-
186
-		for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) {
187
-			APPEND_CSTR(p, fld[i].name);
188
-
189
-			switch(fld[i].op) {
190
-			case DB_EQ:  APPEND_STR(p, strings[STR_OP_EQ]);  break;
191
-			case DB_NE:  APPEND_STR(p, strings[STR_OP_NE]);  break;
192
-			case DB_LT:  APPEND_STR(p, strings[STR_OP_LT]);  break;
193
-			case DB_GT:  APPEND_STR(p, strings[STR_OP_GT]);  break;
194
-			case DB_LEQ: APPEND_STR(p, strings[STR_OP_LEQ]); break;
195
-			case DB_GEQ: APPEND_STR(p, strings[STR_OP_GEQ]); break;
196
-			}
197
-			
198
-			APPEND_STR(p, strings[STR_ESC]);
199
-			if (!DB_FLD_LAST(fld[i + 1])) APPEND_STR(p, strings[STR_AND]);
200
-		}
201
-	}
202
-			
203
-	*p = '\0';
204
-	return 0;
205
-}
206
-
207
-
208
-/**
209
- *  Builds SELECT statement where cmd->values specify column names
210
- *  and cmd->match specify WHERE clause.
211
- * @param sql_cmd SQL statement as a result of this function
212
- * @param cmd     input for statement creation
213
- */
214
-static int build_select_cmd(str* sql_cmd, db_cmd_t* cmd)
215
-{
216
-	db_fld_t* fld;
217
-	int i;
218
-	char* p;
219
-
220
-	sql_cmd->len = strings[STR_SELECT].len;
221
-
222
-	if (DB_FLD_EMPTY(cmd->result)) {
223
-		sql_cmd->len += 1; /* "*" */
224
-	} else {
225
-		for(i = 0, fld = cmd->result; !DB_FLD_LAST(fld[i]); i++) {
226
-			sql_cmd->len += strlen(fld[i].name);
227
-			if (!DB_FLD_LAST(fld[i + 1])) sql_cmd->len += 1; /* , */
228
-		}
229
-	}
230
-	sql_cmd->len += strings[STR_FROM].len;
231
-	sql_cmd->len += cmd->table.len;
232
-
233
-	if (!DB_FLD_EMPTY(cmd->match)) {
234
-		sql_cmd->len += strings[STR_WHERE].len;
235
-
236
-		for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) {
237
-			sql_cmd->len += strlen(fld[i].name);
238
-
239
-			switch(fld[i].op) {
240
-			case DB_EQ:  sql_cmd->len += strings[STR_OP_EQ].len; break;
241
-			case DB_NE:  sql_cmd->len += strings[STR_OP_NE].len; break;
242
-			case DB_LT:  sql_cmd->len += strings[STR_OP_LT].len; break;
243
-			case DB_GT:  sql_cmd->len += strings[STR_OP_GT].len; break;
244
-			case DB_LEQ: sql_cmd->len += strings[STR_OP_LEQ].len; break;
245
-			case DB_GEQ: sql_cmd->len += strings[STR_OP_GEQ].len; break;
246
-			default:
247
-				ERR("mysql: Unsupported db_fld operator %d\n", fld[i].op);
248
-				return -1;
249
-			}
250
-
251
-			sql_cmd->len += strings[STR_ESC].len;
252
-			
253
-			if (!DB_FLD_LAST(fld[i + 1])) sql_cmd->len += strings[STR_AND].len;
254
-		}
255
-	}
256
-
257
-	sql_cmd->s = pkg_malloc(sql_cmd->len + 1);
258
-	if (sql_cmd->s == NULL) {
259
-		ERR("mysql: No memory left\n");
260
-		return -1;
261
-	}
262
-	p = sql_cmd->s;
263
-	
264
-	APPEND_STR(p, strings[STR_SELECT]);
265
-	if (DB_FLD_EMPTY(cmd->result)) {
266
-		*p++ = '*';
267
-	} else {
268
-		for(i = 0, fld = cmd->result; !DB_FLD_LAST(fld[i]); i++) {
269
-			APPEND_CSTR(p, fld[i].name);
270
-			if (!DB_FLD_LAST(fld[i + 1])) *p++ = ',';
271
-		}
272
-	}
273
-	APPEND_STR(p, strings[STR_FROM]);
274
-	APPEND_STR(p, cmd->table);
275
-
276
-	if (!DB_FLD_EMPTY(cmd->match)) {
277
-		APPEND_STR(p, strings[STR_WHERE]);
278
-
279
-		for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) {
280
-			APPEND_CSTR(p, fld[i].name);
281
-
282
-			switch(fld[i].op) {
283
-			case DB_EQ:  APPEND_STR(p, strings[STR_OP_EQ]);  break;
284
-			case DB_NE:  APPEND_STR(p, strings[STR_OP_NE]);  break;
285
-			case DB_LT:  APPEND_STR(p, strings[STR_OP_LT]);  break;
286
-			case DB_GT:  APPEND_STR(p, strings[STR_OP_GT]);  break;
287
-			case DB_LEQ: APPEND_STR(p, strings[STR_OP_LEQ]); break;
288
-			case DB_GEQ: APPEND_STR(p, strings[STR_OP_GEQ]); break;
289
-			}
290
-			
291
-			APPEND_STR(p, strings[STR_ESC]);
292
-			if (!DB_FLD_LAST(fld[i + 1])) APPEND_STR(p, strings[STR_AND]);
293
-		}
294
-	}
295
-
296
-	*p = '\0';
297
-	return 0;
298
-}
299
-
300
-
301
-/**
302
- *  Builds REPLACE statement where cmd->values specify column names.
303
- * @param sql_cmd SQL statement as a result of this function
304
- * @param cmd     input for statement creation
305
- */
306
-static int build_replace_cmd(str* sql_cmd, db_cmd_t* cmd)
307
-{
308
-	db_fld_t* fld;
309
-	int i;
310
-	char* p;
311
-
312
-	sql_cmd->len = strings[STR_REPLACE].len;
313
-	sql_cmd->len += cmd->table.len;
314
-	sql_cmd->len += 2; /* " (" */
315
-
316
-	for(i = 0, fld = cmd->vals; !DB_FLD_LAST(fld[i]); i++) {
317
-		sql_cmd->len += strlen(fld[i].name);
318
-		sql_cmd->len += strings[STR_ESC].len;
319
-		if (!DB_FLD_LAST(fld[i + 1])) sql_cmd->len += 2; /* , twice */
320
-	}
321
-	sql_cmd->len += strings[STR_VALUES].len;
322
-    sql_cmd->len += 1; /* ) */
323
-
324
-	sql_cmd->s = pkg_malloc(sql_cmd->len + 1);
325
-	if (sql_cmd->s == NULL) {
326
-		ERR("mysql: No memory left\n");
327
-		return -1;
328
-	}
329
-	p = sql_cmd->s;
330
-	
331
-	APPEND_STR(p, strings[STR_REPLACE]);
332
-	APPEND_STR(p, cmd->table);
333
-	*p++ = ' ';
334
-	*p++ = '(';
335
-
336
-	for(i = 0, fld = cmd->vals; !DB_FLD_LAST(fld[i]); i++) {
337
-		APPEND_CSTR(p, fld[i].name);
338
-		if (!DB_FLD_LAST(fld[i + 1])) *p++ = ',';
339
-	}
340
-	APPEND_STR(p, strings[STR_VALUES]);
341
-
342
-	for(i = 0, fld = cmd->vals; !DB_FLD_LAST(fld[i]); i++) {
343
-		APPEND_STR(p, strings[STR_ESC]);
344
-		if (!DB_FLD_LAST(fld[i + 1])) *p++ = ',';
345
-	}
346
-	*p++ = ')';
347
-	*p = '\0';
348
-	return 0;
349
-}
350
-
351
-
352
-/**
353
- *  Reallocatable string buffer.
354
- */
355
-struct string_buffer {
356
-	char *s;			/**< allocated memory itself */
357
-	int   len;			/**< used memory */
358
-	int   size;			/**< total size of allocated memory */
359
-	int   increment;	/**< increment when realloc is necessary */ 
360
-};
361
-
362
-
363
-/**
364
- *  Add new string into string buffer.
365
- * @param sb    string buffer
366
- * @param nstr  string to add
367
- * @return      0 if OK, -1 if failed
368
- */
369
-static inline int sb_add(struct string_buffer *sb, str *nstr)
370
-{
371
-	int new_size = 0;
372
-	int rsize = sb->len + nstr->len;
373
-	int asize;
374
-	char *newp;
375
-	
376
-	if ( rsize > sb->size ) {
377
-		asize = rsize - sb->size;
378
-		new_size = sb->size + (asize / sb->increment  + (asize % sb->increment > 0)) * sb->increment;
379
-		newp = pkg_malloc(new_size);
380
-		if (!newp) {
381
-			ERR("mysql: No memory left\n");
382
-			return -1;
383
-		}
384
-		if (sb->s) {
385
-			memcpy(newp, sb->s, sb->len);
386
-			pkg_free(sb->s);
387
-		}
388
-		sb->s = newp;
389
-		sb->size = new_size;
390
-	}
391
-	memcpy(sb->s + sb->len, nstr->s, nstr->len);
392
-	sb->len += nstr->len;
393
-	return 0;
394
-}
395
-
396
-
397
-/**
398
- *  Set members of str variable.
399
- *  Used for temporary str variables. 
400
- */
401
-static inline str* set_str(str *str, const char *s)
402
-{
403
-	str->s = (char *)s;
404
-	str->len = strlen(s);
405
-	return str;
406
-}
407
-
408
-
409
-/**
410
- *  Builds UPDATE statement where cmd->valss specify column name-value pairs
411
- *  and cmd->match specify WHERE clause.
412
- * @param sql_cmd  SQL statement as a result of this function
413
- * @param cmd      input for statement creation
414
- */
415
-static int build_update_cmd(str* sql_cmd, db_cmd_t* cmd)
416
-{
417
-	struct string_buffer sql_buf = {.s = NULL, .len = 0, .size = 0, .increment = 128};
418
-	db_fld_t* fld;
419
-	int i;
420
-	int rv = 0;
421
-	str tmpstr;
422
-
423
-	rv = sb_add(&sql_buf, &strings[STR_UPDATE]);	/* "UPDATE " */
424
-	rv |= sb_add(&sql_buf, &cmd->table);			/* table name */
425
-	rv |= sb_add(&sql_buf, &strings[STR_SET]);		/* " SET " */
426
-
427
-	/* column name-value pairs */
428
-	for(i = 0, fld = cmd->vals; !DB_FLD_LAST(fld[i]); i++) {
429
-		rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));
430
-		rv |= sb_add(&sql_buf, set_str(&tmpstr, " = "));
431
-		rv |= sb_add(&sql_buf, &strings[STR_ESC]);
432
-		if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, set_str(&tmpstr, ", "));
433
-	}
434
-	if (rv) {
435
-		goto err;
436
-	}
437
-
438
-	if (!DB_FLD_EMPTY(cmd->match)) {
439
-		rv |= sb_add(&sql_buf, &strings[STR_WHERE]);
440
-
441
-		for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) {
442
-			rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));
443
-
444
-			switch(fld[i].op) {
445
-			case DB_EQ:  rv |= sb_add(&sql_buf, &strings[STR_OP_EQ]);  break;
446
-			case DB_NE:  rv |= sb_add(&sql_buf, &strings[STR_OP_NE]);  break;
447
-			case DB_LT:  rv |= sb_add(&sql_buf, &strings[STR_OP_LT]);  break;
448
-			case DB_GT:  rv |= sb_add(&sql_buf, &strings[STR_OP_GT]);  break;
449
-			case DB_LEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_LEQ]); break;
450
-			case DB_GEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_GEQ]); break;
451
-			}
452
-			
453
-			rv |= sb_add(&sql_buf, &strings[STR_ESC]);
454
-			if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, &strings[STR_AND]);
455
-		}
456
-	}
457
-	rv |= sb_add(&sql_buf, set_str(&tmpstr, "\0"));
458
-	if (rv) {
459
-		goto err;
460
-	}
461
-	sql_cmd->s = sql_buf.s;
462
-	sql_cmd->len = sql_buf.len;
463
-	return 0;
464
-
465
-err:
466
-	if (sql_buf.s) pkg_free(sql_buf.s);
467
-	return -1;
468
-}
469
-
470
-
471
-static inline void update_field(MYSQL_BIND *param, db_fld_t* fld)
472
-{
473
-	struct my_fld* fp;      /* field payload */
474
-	struct tm* t;
475
-	
476
-	fp = DB_GET_PAYLOAD(fld);
477
-
478
-#ifndef MYSQL_FAKE_NULL
479
-	fp->is_null = fld->flags & DB_NULL;
480
-	if (fp->is_null) return;
481
-#else
482
-	if (fld->flags & DB_NULL) {
483
-		switch(fld->type) {
484
-		case DB_STR:
485
-		case DB_CSTR:
486
-			param->buffer = FAKE_NULL_STR.s;
487
-			fp->length = FAKE_NULL_STR.len;
488
-			break;
489
-		case DB_INT:
490
-			*(int*)param->buffer = FAKE_NULL_INT;
491
-			break;
492
-		case DB_BLOB:
493
-		case DB_DATETIME:
494
-		case DB_NONE:
495
-		case DB_FLOAT:
496
-		case DB_DOUBLE:
497
-		case DB_BITMAP:
498
-			/* we don't have fake null value for these types */
499
-			fp->is_null = DB_NULL;
500
-			break;
501
-		}
502
-		return;
503
-	}
504
-#endif
505
-	switch(fld->type) {
506
-	case DB_STR:
507
-		param->buffer = fld->v.lstr.s;
508
-		fp->length = fld->v.lstr.len;
509
-		break;
510
-
511
-	case DB_BLOB:
512
-		param->buffer = fld->v.blob.s;
513
-		fp->length = fld->v.blob.len;
514
-		break;
515
-
516
-	case DB_CSTR:
517
-		param->buffer = (char*)fld->v.cstr;
518
-		fp->length = strlen(fld->v.cstr);
519
-		break;
520
-
521
-	case DB_DATETIME:
522
-		t = gmtime(&fld->v.time);
523
-		fp->time.second = t->tm_sec;
524
-		fp->time.minute = t->tm_min;
525
-		fp->time.hour = t->tm_hour;
526
-		fp->time.day = t->tm_mday;
527
-		fp->time.month = t->tm_mon + 1;
528
-		fp->time.year = t->tm_year + 1900;
529
-		break;
530
-		
531
-	case DB_NONE:
532
-	case DB_INT:
533
-	case DB_FLOAT:
534
-	case DB_DOUBLE:
535
-	case DB_BITMAP:
536
-		/* No need to do anything for these types */
537
-		break;
538
-
539
-	}
540
-}
541
-
542
-
543
-/**
544
- * Update values of MySQL bound parameters with values from
545
- * the DB API.
546
- * @param cmd Command structure which contains pointers to MYSQL_STMT and parameters values
547
- * @see bind_mysql_params
548
- */
549
-static inline void set_mysql_params(db_cmd_t* cmd)
550
-{
551
-	struct my_cmd* mcmd;
552
-	int i;
553
-
554
-	mcmd = DB_GET_PAYLOAD(cmd);
555
-
556
-	/* FIXME: We are updating internals of the prepared statement here,
557
-	 * this is probably not nice but I could not find another way of
558
-	 * updating the pointer to the buffer without the need to run
559
-	 * mysql_stmt_bind_param again (which would be innefficient)
560
-	 */
561
-	for(i = 0; i < cmd->vals_count; i++) {
562
-		update_field(mcmd->st->params + i, cmd->vals + i);
563
-	}
564
-
565
-	for(i = 0; i < cmd->match_count; i++) {
566
-		update_field(mcmd->st->params + cmd->vals_count + i, cmd->match + i);
567
-	}
568
-}
569
-
570
-
571
-static inline int update_result(db_fld_t* result, MYSQL_STMT* st)
572
-{
573
-	int i;
574
-	struct my_fld* rp; /* Payload of the current field in result */
575
-	struct tm t;
576
-
577
-	/* Iterate through all the fields returned by MySQL and convert
578
-	 * them to DB API representation if necessary
579
-	 */
580
-
581
-	for(i = 0; i < st->field_count; i++) {
582
-		rp = DB_GET_PAYLOAD(result + i);
583
-
584
-		if (rp->is_null) {
585
-			result[i].flags |= DB_NULL;
586
-			continue;
587
-		} else {
588
-			result[i].flags &= ~DB_NULL;
589
-		}
590
-
591
-		switch(result[i].type) {
592
-		case DB_STR:
593
-			result[i].v.lstr.len = rp->length;
594
-#ifdef MYSQL_FAKE_NULL
595
-			if (STR_EQ(FAKE_NULL_STR,result[i].v.lstr)) {
596
-				result[i].flags |= DB_NULL;
597
-			}
598
-#endif
599
-			break;
600
-
601
-		case DB_BLOB:
602
-			result[i].v.blob.len = rp->length;
603
-			break;
604
-
605
-		case DB_CSTR:
606
-			if (rp->length < STR_BUF_SIZE) {
607
-				result[i].v.cstr[rp->length] = '\0';
608
-			} else {
609
-				/* Truncated field but rp->length contains full size,
610
-				 * zero terminated the last byte in the buffer
611
-				 */
612
-				result[i].v.cstr[STR_BUF_SIZE - 1] = '\0';
613
-			}
614
-#ifdef MYSQL_FAKE_NULL
615
-			if (strcmp(FAKE_NULL_STR.s,result[i].v.cstr)==0) {
616
-				result[i].flags |= DB_NULL;
617
-			}
618
-#endif
619
-			break;
620
-			
621
-		case DB_DATETIME:
622
-			memset(&t, '\0', sizeof(struct tm));
623
-			t.tm_sec = rp->time.second;
624
-			t.tm_min = rp->time.minute;
625
-			t.tm_hour = rp->time.hour;
626
-			t.tm_mday = rp->time.day;
627
-			t.tm_mon = rp->time.month - 1;
628
-			t.tm_year = rp->time.year - 1900;
629
-
630
-			/* Daylight saving information got lost in the database
631
-			 * so let timegm to guess it. This eliminates the bug when
632
-			 * contacts reloaded from the database have different time
633
-			 * of expiration by one hour when daylight saving is used
634
-			 */ 
635
-			t.tm_isdst = -1;
636
-#ifdef HAVE_TIMEGM
637
-			result[i].v.time = timegm(&t);
638
-#else
639
-			result[i].v.time = _timegm(&t);
640
-#endif /* HAVE_TIMEGM */
641
-			break;
642
-
643
-		case DB_INT:
644
-#ifdef MYSQL_FAKE_NULL
645
-			if (FAKE_NULL_INT==result[i].v.int4) {
646
-				result[i].flags |= DB_NULL;
647
-			}
648
-			break;
649
-#endif
650
-		case DB_NONE:
651
-		case DB_FLOAT:
652
-		case DB_DOUBLE:
653
-		case DB_BITMAP:
654
-			/* No need to do anything for these types */
655
-			break;
656
-		}
657
-	}
658
-	
659
-	return 0;
660
-}
661
-
662
-
663
-/**
664
- * This is the main command execution function. The function contains
665
- * all the necessary logic to detect reset or disconnected database
666
- * connections and uploads commands to the server if necessary.
667
- * @param cmd Command to be executed
668
- * @return    0 if OK, <0 on MySQL failure, >0 on DB API failure
669
- */
670
-static int exec_cmd_safe(db_cmd_t* cmd)
671
-{
672
-    int i, err;
673
-    db_con_t* con;
674
-    struct my_cmd* mcmd;
675
-    struct my_con* mcon;
676
-	
677
-    /* First things first: retrieve connection info
678
-     * from the currently active connection and also
679
-     * mysql payload from the database command
680
-     */
681
-    mcmd = DB_GET_PAYLOAD(cmd);
682
-    con = cmd->ctx->con[db_payload_idx];
683
-    mcon = DB_GET_PAYLOAD(con);
684
-    
685
-    for(i = 0; i <= my_retries; i++) {
686
-	if ((mcon->flags & MY_CONNECTED) == 0) {
687
-	    /* The connection is disconnected, try to reconnect */
688
-	    if (my_con_connect(con)) {
689
-		INFO("mysql: exec_cmd_safe failed to re-connect\n");
690
-		continue;
691
-	    }
692
-	}	
693
-	
694
-	/* Next check the number of resets in the database connection, if this
695
-	 * number is higher than the number we keep in my_cmd structure in
696
-	 * last_reset variable then the connection was reset and we need to
697
-	 * upload the command again to the server before executing it, because
698
-	 * the server recycles all server side information upon disconnect.
699
-	 */
700
-	if (mcon->resets > mcmd->last_reset) {
701
-	    INFO("mysql: Connection reset detected, uploading command to server\n");
702
-	    err = upload_cmd(cmd);
703
-	    if (err < 0) {
704
-		INFO("mysql: Error while uploading command\n");
705
-		continue;
706
-	    } else if (err > 0) {
707
-		/* DB API error, this is a serious problem such as memory
708
-		 * allocation failure, bail out
709
-		 */
710
-		return 1;
711
-	    }
712
-	}
713
-	
714
-	set_mysql_params(cmd);
715
-	err = mysql_stmt_execute(mcmd->st);
716
-	if (err == 0) {
717
-	    /* The command was executed successfully, now fetch all data to
718
-	     * the client if it was requested by the user */
719
-	    if (mcmd->flags & MY_FETCH_ALL) {
720
-		err = mysql_stmt_store_result(mcmd->st);
721
-		if (err) {
722
-		    INFO("mysql: Error while fetching data to client.\n");
723
-		    goto error;
724
-		}
725
-	    }
726
-	    return 0;
727
-	}
728
-	
729
-    error:
730
-	/* Command execution failed, log a message and try to reconnect */
731
-	INFO("mysql: libmysql: %d, %s\n", mysql_stmt_errno(mcmd->st),
732
-	     mysql_stmt_error(mcmd->st));
733
-	INFO("mysql: Error while executing command on server, trying to reconnect\n");
734
-
735
-	my_con_disconnect(con);
736
-	if (my_con_connect(con)) {
737
-	    INFO("mysql: Failed to reconnect server\n");
738
-	} else {
739
-	    INFO("mysql: Successfully reconnected server\n");
740
-	}
741
-    }
742
-    
743
-    INFO("mysql: Failed to execute command, giving up\n");
744
-    return -1;
745
-}
746
-
747
-
748
-int my_cmd_exec(db_res_t* res, db_cmd_t* cmd)
749
-{
750
-	struct my_cmd* mcmd;
751
-
752
-	mcmd = DB_GET_PAYLOAD(cmd);
753
-
754
-	mcmd->next_flag = -1;
755
-	return exec_cmd_safe(cmd);
756
-}
757
-
758
-
759
-/**
760
- * Set MYSQL_BIND item.
761
- * @param bind destination
762
- * @param fld  source
763
- */
764
-static void set_field(MYSQL_BIND *bind, db_fld_t* fld)
765
-{
766
-	struct my_fld* f;
767
-	
768
-	f = DB_GET_PAYLOAD(fld);
769
-	bind->is_null = &f->is_null;
770
-	/* We can do it for all the types here, mysql will ignore it
771
-	 * for fixed-size types such as MYSQL_TYPE_LONG
772
-	 */
773
-	bind->length = &f->length;
774
-	switch(fld->type) {
775
-	case DB_INT:
776
-	case DB_BITMAP:
777
-		bind->buffer_type = MYSQL_TYPE_LONG;
778
-		bind->buffer = &fld->v.int4;
779
-		break;
780
-	
781
-	case DB_FLOAT:
782
-		bind->buffer_type = MYSQL_TYPE_FLOAT;
783
-		bind->buffer = &fld->v.flt;
784
-		break;
785
-		
786
-	case DB_DOUBLE:
787
-		bind->buffer_type = MYSQL_TYPE_DOUBLE;
788
-		bind->buffer = &fld->v.dbl;
789
-		break;
790
-	
791
-	case DB_DATETIME:
792
-		bind->buffer_type = MYSQL_TYPE_DATETIME;
793
-		bind->buffer = &f->time;
794
-		break;
795
-	
796
-	case DB_STR:
797
-	case DB_CSTR:
798
-		bind->buffer_type = MYSQL_TYPE_VAR_STRING;
799
-		bind->buffer = ""; /* Updated on runtime */
800
-		break;
801
-	
802
-	case DB_BLOB:
803
-		bind->buffer_type = MYSQL_TYPE_BLOB;
804
-		bind->buffer = ""; /* Updated on runtime */
805
-		break;
806
-	
807
-	case DB_NONE:
808
-		/* Eliminates gcc warning */
809
-		break;
810
-	
811
-	}
812
-}
813
-
814
-
815
-/**
816
- * Bind params, give real values into prepared statement.
817
- * Up to two sets of parameters are provided.
818
- * Both of them are used in UPDATE command, params1 as colspecs and values and
819
- * params2 as WHERE clause. In other cases one set could be enough because values
820
- * or match (WHERE clause) is needed.
821
- * @param st MySQL command statement
822
- * @param params1 first set of params
823
- * @param params2 second set of params
824
- * @return 0 if OK, <0 on MySQL error, >0 on DB API error
825
- * @see update_params
826
- */
827
-static int bind_mysql_params(MYSQL_STMT* st, db_fld_t* params1, db_fld_t* params2)
828
-{
829
-	int my_idx, fld_idx;
830
-	int count1, count2;
831
-	MYSQL_BIND* my_params;
832
-	int err = 0;
833
-
834
-	/* Calculate the number of parameters */
835
-	for(count1 = 0; !DB_FLD_EMPTY(params1) && !DB_FLD_LAST(params1[count1]); count1++);
836
-	for(count2 = 0; !DB_FLD_EMPTY(params2) && !DB_FLD_LAST(params2[count2]); count2++);
837
-	if (st->param_count != count1 + count2) {
838
-		BUG("mysql: Number of parameters in SQL command does not match number of DB API parameters\n");
839
-		return 1;
840
-	}
841
-	
842
-	my_params = (MYSQL_BIND*)pkg_malloc(sizeof(MYSQL_BIND) * (count1 + count2));
843
-	if (my_params == NULL) {
844
-		ERR("mysql: No memory left\n");
845
-		return -1;
846
-	}
847
-	memset(my_params, '\0', sizeof(MYSQL_BIND) * (count1 + count2));
848
-
849
-	/* params1 */
850
-	my_idx = 0;
851
-	for (fld_idx = 0; fld_idx < count1; fld_idx++, my_idx++) {
852
-		set_field(&my_params[my_idx], params1 + fld_idx);
853
-	}
854
-	/* params2 */
855
-	for (fld_idx = 0; fld_idx < count2; fld_idx++, my_idx++) {
856
-		set_field(&my_params[my_idx], params2 + fld_idx);
857
-	}
858
-
859
-	err = mysql_stmt_bind_param(st, my_params);
860
-	if (err) {
861
-		ERR("mysql: libmysqlclient: %d, %s\n", 
862
-			mysql_stmt_errno(st), mysql_stmt_error(st));
863
-		goto error;
864
-	}
865
-
866
-	/* We do not need the array of MYSQL_BIND anymore, mysql_stmt_bind_param
867
-	 * creates a copy in the statement and we will update it there
868
-	 */
869
-	pkg_free(my_params);
870
-	return err;
871
-   
872
- error:
873
-	if (my_params) pkg_free(my_params);
874
-	return err;
875
-}
876
-
877
-
878
-/*
879
- * FIXME: This function will only work if we have one db connection
880
- * in every context, otherwise it would initialize the result set
881
- * from the first connection in the context.
882
- */
883
-static int check_result(db_cmd_t* cmd, struct my_cmd* payload)
884
-{
885
-	int i, n;
886
-	MYSQL_FIELD *fld;
887
-	MYSQL_RES *meta = NULL;
888
-
889
-	meta = mysql_stmt_result_metadata(payload->st);
890
-	if (meta == NULL) {
891
-		/* No error means no result set to be checked */
892
-		if (mysql_stmt_errno(payload->st) == 0) return 0;
893
-		ERR("mysql: Error while getting metadata of SQL command: %d, %s\n",
894
-			mysql_stmt_errno(payload->st), mysql_stmt_error(payload->st));
895
-		return -1;
896
-	}
897
-	n = mysql_num_fields(meta);
898
-	if (cmd->result == NULL) {
899
-		/* The result set parameter of db_cmd function was empty, that
900
-		 * means the command is select * and we have to create the array
901
-		 * of result fields in the cmd structure manually.
902
-		 */
903
-		cmd->result = db_fld(n + 1);
904
-		cmd->result_count = n;
9