Browse code

Preparation for implementation of UPDATE db statement. First of all we need two sets of params in db_cmd. First for match clause and the second as column-value pairs of changed columns. Currently it uses three sets of parameters: result, match and vals. - result - DB_GET output - match - DB_GET, DB_DEL (and DB_UPD in the future) - vals - DB_PUT (and DB_UPD)

Libor Chocholaty authored on 25/06/2007 17:51:27
Showing 3 changed files
... ...
@@ -26,6 +26,10 @@
26 26
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27 27
  */
28 28
 
29
+/** @addtogroup mysql
30
+ *  @{
31
+ */
32
+
29 33
 #define _XOPEN_SOURCE 4     /* bsd */
30 34
 #define _XOPEN_SOURCE_EXTENDED 1    /* solaris */
31 35
 #define _SVID_SOURCE 1 /* timegm */
... ...
@@ -50,6 +54,7 @@ enum {
50 54
 	STR_UPDATE,
51 55
 	STR_SELECT,
52 56
 	STR_REPLACE,
57
+	STR_SET,
53 58
 	STR_WHERE,
54 59
 	STR_IS,
55 60
 	STR_AND,
... ...
@@ -67,9 +72,10 @@ enum {
67 72
 static str strings[] = {
68 73
 	STR_STATIC_INIT("delete from "),
69 74
 	STR_STATIC_INIT("insert into "),
70
-	STR_STATIC_INIT("update "),
75
+	STR_STATIC_INIT("UPDATE "),
71 76
 	STR_STATIC_INIT("select "),
72 77
 	STR_STATIC_INIT("replace "),
78
+	STR_STATIC_INIT(" SET "),
73 79
 	STR_STATIC_INIT(" where "),
74 80
 	STR_STATIC_INIT(" is "),
75 81
 	STR_STATIC_INIT(" and "),
... ...
@@ -108,6 +114,11 @@ static void my_cmd_free(db_cmd_t* cmd, struct my_cmd* payload)
108 114
 }
109 115
 
110 116
 
117
+/**
118
+ *  Builds DELETE statement where cmd->match specify WHERE clause.
119
+ * @param query  SQL statement as a result of this function
120
+ * @param cmd    input for statement creation
121
+ */
111 122
 static int build_delete_query(str* query, db_cmd_t* cmd)
112 123
 {
113 124
 	db_fld_t* fld;
... ...
@@ -117,10 +128,10 @@ static int build_delete_query(str* query, db_cmd_t* cmd)
117 128
 	query->len = strings[STR_DELETE].len;
118 129
 	query->len += cmd->table.len;
119 130
 
120
-	if (!DB_FLD_EMPTY(cmd->params)) {
131
+	if (!DB_FLD_EMPTY(cmd->match)) {
121 132
 		query->len += strings[STR_WHERE].len;
122 133
 
123
-		for(i = 0, fld = cmd->params; !DB_FLD_LAST(fld[i]); i++) {
134
+		for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) {
124 135
 			query->len += strlen(fld[i].name);
125 136
 
126 137
 			switch(fld[i].op) {
... ...
@@ -150,10 +161,10 @@ static int build_delete_query(str* query, db_cmd_t* cmd)
150 161
 	APPEND_STR(p, strings[STR_DELETE]);
151 162
 	APPEND_STR(p, cmd->table);
152 163
 
153
-	if (!DB_FLD_EMPTY(cmd->params)) {
164
+	if (!DB_FLD_EMPTY(cmd->match)) {
154 165
 		APPEND_STR(p, strings[STR_WHERE]);
155 166
 
156
-		for(i = 0, fld = cmd->params; !DB_FLD_LAST(fld[i]); i++) {
167
+		for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) {
157 168
 			APPEND_CSTR(p, fld[i].name);
158 169
 
159 170
 			switch(fld[i].op) {
... ...
@@ -174,6 +185,12 @@ static int build_delete_query(str* query, db_cmd_t* cmd)
174 185
 }
175 186
 
176 187
 
188
+/**
189
+ *  Builds SELECT statement where cmd->values specify column names
190
+ *  and cmd->match specify WHERE clause.
191
+ * @param query  SQL statement as a result of this function
192
+ * @param cmd    input for statement creation
193
+ */
177 194
 static int build_select_query(str* query, db_cmd_t* cmd)
178 195
 {
179 196
 	db_fld_t* fld;
... ...
@@ -193,10 +210,10 @@ static int build_select_query(str* query, db_cmd_t* cmd)
193 210
 	query->len += strings[STR_FROM].len;
194 211
 	query->len += cmd->table.len;
195 212
 
196
-	if (!DB_FLD_EMPTY(cmd->params)) {
213
+	if (!DB_FLD_EMPTY(cmd->match)) {
197 214
 		query->len += strings[STR_WHERE].len;
198 215
 
199
-		for(i = 0, fld = cmd->params; !DB_FLD_LAST(fld[i]); i++) {
216
+		for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) {
200 217
 			query->len += strlen(fld[i].name);
201 218
 
202 219
 			switch(fld[i].op) {
... ...
@@ -235,10 +252,10 @@ static int build_select_query(str* query, db_cmd_t* cmd)
235 252
 	APPEND_STR(p, strings[STR_FROM]);
236 253
 	APPEND_STR(p, cmd->table);
237 254
 
238
-	if (!DB_FLD_EMPTY(cmd->params)) {
255
+	if (!DB_FLD_EMPTY(cmd->match)) {
239 256
 		APPEND_STR(p, strings[STR_WHERE]);
240 257
 
241
-		for(i = 0, fld = cmd->params; !DB_FLD_LAST(fld[i]); i++) {
258
+		for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) {
242 259
 			APPEND_CSTR(p, fld[i].name);
243 260
 
244 261
 			switch(fld[i].op) {
... ...
@@ -259,6 +276,11 @@ static int build_select_query(str* query, db_cmd_t* cmd)
259 276
 }
260 277
 
261 278
 
279
+/**
280
+ *  Builds REPLACE statement where cmd->values specify column names.
281
+ * @param query  SQL statement as a result of this function
282
+ * @param cmd    input for statement creation
283
+ */
262 284
 static int build_replace_query(str* query, db_cmd_t* cmd)
263 285
 {
264 286
 	db_fld_t* fld;
... ...
@@ -269,7 +291,7 @@ static int build_replace_query(str* query, db_cmd_t* cmd)
269 291
 	query->len += cmd->table.len;
270 292
 	query->len += 2; /* " (" */
271 293
 
272
-	for(i = 0, fld = cmd->params; !DB_FLD_LAST(fld[i]); i++) {
294
+	for(i = 0, fld = cmd->vals; !DB_FLD_LAST(fld[i]); i++) {
273 295
 		query->len += strlen(fld[i].name);
274 296
 		query->len += strings[STR_ESC].len;
275 297
 		if (!DB_FLD_LAST(fld[i + 1])) query->len += 2; /* , twice */
... ...
@@ -289,13 +311,13 @@ static int build_replace_query(str* query, db_cmd_t* cmd)
289 311
 	*p++ = ' ';
290 312
 	*p++ = '(';
291 313
 
292
-	for(i = 0, fld = cmd->params; !DB_FLD_LAST(fld[i]); i++) {
314
+	for(i = 0, fld = cmd->vals; !DB_FLD_LAST(fld[i]); i++) {
293 315
 		APPEND_CSTR(p, fld[i].name);
294 316
 		if (!DB_FLD_LAST(fld[i + 1])) *p++ = ',';
295 317
 	}
296 318
 	APPEND_STR(p, strings[STR_VALUES]);
297 319
 
298
-	for(i = 0, fld = cmd->params; !DB_FLD_LAST(fld[i]); i++) {
320
+	for(i = 0, fld = cmd->vals; !DB_FLD_LAST(fld[i]); i++) {
299 321
 		APPEND_STR(p, strings[STR_ESC]);
300 322
 		if (!DB_FLD_LAST(fld[i + 1])) *p++ = ',';
301 323
 	}
... ...
@@ -304,6 +326,117 @@ static int build_replace_query(str* query, db_cmd_t* cmd)
304 326
 	return 0;
305 327
 }
306 328
 
329
+/**
330
+ *  Reallocatable string buffer.
331
+ */
332
+struct string_buffer {
333
+	char *s;			/**< allocated memory itself */
334
+	int   len;			/**< used memory */
335
+	int   size;			/**< total size of allocated memory */
336
+	int   increment;	/**< increment when realloc is necessary */ 
337
+};
338
+/**
339
+ *  Add new string into string buffer.
340
+ * @param sb    string buffer
341
+ * @param nstr  string to add
342
+ * @return      0 if OK, -1 if failed
343
+ */
344
+static inline int sb_add(struct string_buffer *sb, str *nstr)
345
+{
346
+	int new_size = 0;
347
+	int rsize = sb->len + nstr->len;
348
+	int asize;
349
+	char *newp;
350
+	
351
+	if ( rsize > sb->size ) {
352
+		asize = rsize - sb->size;
353
+		new_size = sb->size + (asize / sb->increment  + (asize % sb->increment > 0)) * sb->increment;
354
+		newp = pkg_malloc(new_size);
355
+		if (!newp) {
356
+			ERR("not enough memory\n");
357
+			return -1;
358
+		}
359
+		memcpy(newp, sb->s, sb->len);
360
+		pkg_free(sb->s);
361
+		sb->s = newp;
362
+		sb->size = new_size;
363
+	}
364
+	memcpy(sb->s + sb->len, nstr->s, nstr->len);
365
+	sb->len += nstr->len;
366
+	return 0;
367
+}
368
+/**
369
+ *  Set members of str variable.
370
+ *  Used for temporary str variables. 
371
+ */
372
+static inline str* set_str(str *str, const char *s)
373
+{
374
+	str->s = (char *)s;
375
+	str->len = strlen(s);
376
+	return str;
377
+}
378
+
379
+
380
+/**
381
+ *  Builds UPDATE statement where cmd->valss specify column name-value pairs
382
+ *  and cmd->match specify WHERE clause.
383
+ * @param query  SQL statement as a result of this function
384
+ * @param cmd    input for statement creation
385
+ */
386
+static int build_update_query(str* query, db_cmd_t* cmd)
387
+{
388
+	struct string_buffer sql_buf = {.s = NULL, .len = 0, .size = 0, .increment = 128};
389
+	db_fld_t* fld;
390
+	int i;
391
+	int rv = 0;
392
+	str tmpstr;
393
+
394
+	rv = sb_add(&sql_buf, &strings[STR_UPDATE]);	/* "UPDATE " */
395
+	rv |= sb_add(&sql_buf, &cmd->table);			/* table name */
396
+	rv |= sb_add(&sql_buf, &strings[STR_SET]);		/* " SET " */
397
+
398
+	/* column name-value pairs */
399
+	for(i = 0, fld = cmd->vals; !DB_FLD_LAST(fld[i]); i++) {
400
+		rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));
401
+		rv |= sb_add(&sql_buf, set_str(&tmpstr, " = "));
402
+		rv |= sb_add(&sql_buf, &strings[STR_ESC]);
403
+		if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, set_str(&tmpstr, ", "));
404
+	}
405
+	if (rv) {
406
+		goto err;
407
+	}
408
+
409
+	if (!DB_FLD_EMPTY(cmd->match)) {
410
+		rv |= sb_add(&sql_buf, &strings[STR_WHERE]);
411
+
412
+		for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) {
413
+			rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));
414
+
415
+			switch(fld[i].op) {
416
+			case DB_EQ:  rv |= sb_add(&sql_buf, &strings[STR_OP_EQ]);  break;
417
+			case DB_LT:  rv |= sb_add(&sql_buf, &strings[STR_OP_LT]);  break;
418
+			case DB_GT:  rv |= sb_add(&sql_buf, &strings[STR_OP_GT]);  break;
419
+			case DB_LEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_LEQ]); break;
420
+			case DB_GEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_GEQ]); break;
421
+			}
422
+			
423
+			rv |= sb_add(&sql_buf, &strings[STR_ESC]);
424
+			if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, &strings[STR_AND]);
425
+		}
426
+	}
427
+	rv |= sb_add(&sql_buf, set_str(&tmpstr, "\0"));
428
+	if (rv) {
429
+		goto err;
430
+	}
431
+	query->s = sql_buf.s;
432
+
433
+	return 0;
434
+
435
+err:
436
+	if (sql_buf.s) pkg_free(sql_buf.s);
437
+	return -1;
438
+}
439
+
307 440
 
308 441
 static inline int update_params(MYSQL_STMT* st, db_fld_t* params)
309 442
 {
... ...
@@ -437,13 +570,17 @@ static inline int update_result(db_fld_t* result, MYSQL_STMT* st)
437 570
 	return 0;
438 571
 }
439 572
 
440
-
573
+/**
574
+ *  DB_DEL uses cmd->match
575
+ *  DB_PUT uses cmd->vals
576
+ */
441 577
 int my_cmd_write(db_res_t* res, db_cmd_t* cmd)
442 578
 {
443 579
 	struct my_cmd* mcmd;
444 580
 
445 581
 	mcmd = DB_GET_PAYLOAD(cmd);
446
-	if (mcmd->st->param_count && update_params(mcmd->st, cmd->params) < 0) return -1;
582
+	if (cmd->type == DB_DEL && mcmd->st->param_count && update_params(mcmd->st, cmd->match) < 0) return -1;
583
+	if (cmd->type == DB_PUT && mcmd->st->param_count && update_params(mcmd->st, cmd->vals) < 0) return -1;
447 584
 	if (mysql_stmt_execute(mcmd->st)) {
448 585
 		ERR("Error while executing query: %s\n", mysql_stmt_error(mcmd->st));
449 586
 		return -1;
... ...
@@ -457,7 +594,22 @@ int my_cmd_read(db_res_t* res, db_cmd_t* cmd)
457 594
 	struct my_cmd* mcmd;
458 595
    
459 596
 	mcmd = DB_GET_PAYLOAD(cmd);
460
-	if (mcmd->st->param_count && update_params(mcmd->st, cmd->params) < 0) return -1;
597
+	if (mcmd->st->param_count && update_params(mcmd->st, cmd->match) < 0) return -1;
598
+	if (mysql_stmt_execute(mcmd->st)) {
599
+		ERR("Error while executing query: %s\n", mysql_stmt_error(mcmd->st));
600
+		return -1;
601
+	}
602
+	return 0;
603
+}
604
+
605
+
606
+int my_cmd_update(db_res_t* res, db_cmd_t* cmd)
607
+{
608
+	struct my_cmd* mcmd;
609
+
610
+	mcmd = DB_GET_PAYLOAD(cmd);
611
+	if (mcmd->st->param_count && update_params(mcmd->st, cmd->match) < 0) return -1;
612
+	if (mcmd->st->param_count && update_params(mcmd->st, cmd->vals) < 0) return -1;
461 613
 	if (mysql_stmt_execute(mcmd->st)) {
462 614
 		ERR("Error while executing query: %s\n", mysql_stmt_error(mcmd->st));
463 615
 		return -1;
... ...
@@ -478,71 +630,87 @@ int my_cmd_sql(db_res_t* res, db_cmd_t* cmd)
478 630
 	return 0;
479 631
 }
480 632
 
481
-
482
-static int bind_params(MYSQL_STMT* st, db_fld_t* fld)
633
+static void set_field(MYSQL_BIND *bind, db_fld_t* fld )
483 634
 {
484
-	int i, n;
485 635
 	struct my_fld* f;
486
-	MYSQL_BIND* params;
636
+	
637
+	f = DB_GET_PAYLOAD(fld);
638
+	bind->is_null = &f->is_null;
639
+	/* We can do it for all the types here, mysql will ignore it
640
+	 * for fixed-size types such as MYSQL_TYPE_LONG
641
+	 */
642
+	bind->length = &f->length;
643
+	switch(fld->type) {
644
+	case DB_INT:
645
+	case DB_BITMAP:
646
+		bind->buffer_type = MYSQL_TYPE_LONG;
647
+		bind->buffer = &fld->v.int4;
648
+		break;
649
+	
650
+	case DB_FLOAT:
651
+		bind->buffer_type = MYSQL_TYPE_FLOAT;
652
+		bind->buffer = &fld->v.flt;
653
+		break;
654
+		
655
+	case DB_DOUBLE:
656
+		bind->buffer_type = MYSQL_TYPE_DOUBLE;
657
+		bind->buffer = &fld->v.dbl;
658
+		break;
659
+	
660
+	case DB_DATETIME:
661
+		bind->buffer_type = MYSQL_TYPE_DATETIME;
662
+		bind->buffer = &f->time;
663
+		break;
664
+	
665
+	case DB_STR:
666
+	case DB_CSTR:
667
+		bind->buffer_type = MYSQL_TYPE_VAR_STRING;
668
+		bind->buffer = ""; /* Updated on runtime */
669
+		break;
670
+	
671
+	case DB_BLOB:
672
+		bind->buffer_type = MYSQL_TYPE_BLOB;
673
+		bind->buffer = ""; /* Updated on runtime */
674
+		break;
675
+	
676
+	case DB_NONE:
677
+		/* Eliminates gcc warning */
678
+		break;
679
+	
680
+	}
681
+}
682
+
683
+/**
684
+ *  Bind params, values first and match after them.
685
+ */
686
+static int bind_params(MYSQL_STMT* st, db_fld_t* fld_value, db_fld_t* fld_match)
687
+{
688
+	int my_idx, fld_idx;
689
+	int value_count, match_count;
690
+	MYSQL_BIND* my_params;
487 691
 
488 692
 	/* Calculate the number of parameters */
489
-	for(n = 0; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[n]); n++);
693
+	for(value_count = 0; !DB_FLD_EMPTY(fld_value) && !DB_FLD_LAST(fld_value[value_count]); value_count++);
694
+	for(match_count = 0; !DB_FLD_EMPTY(fld_match) && !DB_FLD_LAST(fld_match[match_count]); match_count++);
490 695
 
491
-	params = (MYSQL_BIND*)pkg_malloc(sizeof(MYSQL_BIND) * n);
492
-	if (params == NULL) {
696
+	my_params = (MYSQL_BIND*)pkg_malloc(sizeof(MYSQL_BIND) * (value_count+match_count));
697
+	if (my_params == NULL) {
493 698
 		ERR("No memory left\n");
494 699
 		return -1;
495 700
 	}
496
-	memset(params, '\0', sizeof(MYSQL_BIND) * n);
497
-	
498
-	for(i = 0; i < n; i++) {
499
-		f = DB_GET_PAYLOAD(fld + i);
500
-		params[i].is_null = &f->is_null;
501
-		/* We can do it for all the types here, mysql will ignore it
502
-		 * for fixed-size types such as MYSQL_TYPE_LONG
503
-		 */
504
-		params[i].length = &f->length;
505
-		switch(fld[i].type) {
506
-		case DB_INT:
507
-		case DB_BITMAP:
508
-			params[i].buffer_type = MYSQL_TYPE_LONG;
509
-			params[i].buffer = &fld[i].v.int4;
510
-			break;
511
-
512
-		case DB_FLOAT:
513
-			params[i].buffer_type = MYSQL_TYPE_FLOAT;
514
-			params[i].buffer = &fld[i].v.flt;
515
-			break;
516
-			
517
-		case DB_DOUBLE:
518
-			params[i].buffer_type = MYSQL_TYPE_DOUBLE;
519
-			params[i].buffer = &fld[i].v.dbl;
520
-			break;
521
-
522
-		case DB_DATETIME:
523
-			params[i].buffer_type = MYSQL_TYPE_DATETIME;
524
-			params[i].buffer = &f->time;
525
-			break;
701
+	memset(my_params, '\0', sizeof(MYSQL_BIND) * (value_count+match_count));
526 702
 
527
-		case DB_STR:
528
-		case DB_CSTR:
529
-			params[i].buffer_type = MYSQL_TYPE_VAR_STRING;
530
-			params[i].buffer = ""; /* Updated on runtime */
531
-			break;
532
-
533
-		case DB_BLOB:
534
-			params[i].buffer_type = MYSQL_TYPE_BLOB;
535
-			params[i].buffer = ""; /* Updated on runtime */
536
-			break;
537
-
538
-		case DB_NONE:
539
-			/* Eliminates gcc warning */
540
-			break;
541
-
542
-		}
703
+	/* values */
704
+	my_idx = 0;
705
+	for (fld_idx = 0; fld_idx < value_count; fld_idx++, my_idx++) {
706
+		set_field(&my_params[my_idx], fld_value + fld_idx);
543 707
 	}
544
-
545
-	if (mysql_stmt_bind_param(st, params)) {
708
+	/* match */
709
+	for (fld_idx = 0; fld_idx < match_count; fld_idx++, my_idx++) {
710
+		set_field(&my_params[my_idx], fld_match + fld_idx);
711
+	}
712
+	
713
+	if (mysql_stmt_bind_param(st, my_params)) {
546 714
 		ERR("Error while binding parameters: %s\n", mysql_stmt_error(st));
547 715
 		goto error;
548 716
 	}
... ...
@@ -550,28 +718,31 @@ static int bind_params(MYSQL_STMT* st, db_fld_t* fld)
550 718
 	/* We do not need the array of MYSQL_BIND anymore, mysql_stmt_bind_param
551 719
 	 * creates a copy in the statement and we will update it there
552 720
 	 */
553
-	pkg_free(params);
721
+	pkg_free(my_params);
554 722
 	return 0;
555 723
    
556 724
  error:
557
-	if (params) pkg_free(params);
725
+	if (my_params) pkg_free(my_params);
558 726
 	return -1;
559 727
 }
560 728
 
729
+#include <stdlib.h>
561 730
 /* FIXME: Add support for DB_NONE, in this case the function should determine
562 731
  * the type of the column in the database and set the field type appropriately
563 732
  */
564
-
565 733
 static int bind_result(MYSQL_STMT* st, db_fld_t* fld)
566 734
 {
567 735
 	int i, n;
568 736
 	struct my_fld* f;
569 737
 	MYSQL_BIND* result;
570 738
 
739
+INFO("bind_result(st = %p, fld = %p)\n", st, fld);
740
+INFO("bind_result: field count: %d\n", st->field_count);
571 741
 	/* Calculate the number of fields in the result */
572 742
 	for(n = 0; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[n]); n++);
573
-
743
+INFO("bind_result: n = %d\n", n);
574 744
 	result = (MYSQL_BIND*)pkg_malloc(sizeof(MYSQL_BIND) * n);
745
+INFO("bind_result: result = %p\n", result);
575 746
 	if (result == NULL) {
576 747
 		ERR("No memory left\n");
577 748
 		return -1;
... ...
@@ -579,6 +750,8 @@ static int bind_result(MYSQL_STMT* st, db_fld_t* fld)
579 750
 	memset(result, '\0', sizeof(MYSQL_BIND) * n);
580 751
 	
581 752
 	for(i = 0; i < n; i++) {
753
+INFO("bind_result: i = %d\n", i);
754
+INFO("bind_result: fld[%d].type = %d\n", i, fld[i].type);
582 755
 		f = DB_GET_PAYLOAD(fld + i);
583 756
 		result[i].is_null = &f->is_null;
584 757
 		/* We can do it for all the types here, mysql will ignore it
... ...
@@ -649,7 +822,7 @@ static int bind_result(MYSQL_STMT* st, db_fld_t* fld)
649 822
 
650 823
 		}
651 824
 	}
652
-
825
+INFO("bind_result: result = %p\n", result);
653 826
 	if (mysql_stmt_bind_result(st, result)) {
654 827
 		ERR("Error while binding result: %s\n", mysql_stmt_error(st));
655 828
 		goto error;
... ...
@@ -662,6 +835,7 @@ static int bind_result(MYSQL_STMT* st, db_fld_t* fld)
662 835
 	return 0;
663 836
    
664 837
  error:
838
+ 	abort();
665 839
 	if (result) pkg_free(result);
666 840
 	return -1;
667 841
 }
... ...
@@ -672,6 +846,7 @@ int my_cmd(db_cmd_t* cmd)
672 846
 	struct my_cmd* res;
673 847
 	struct my_con* mcon;
674 848
 
849
+INFO("my_cmd(cmd = %p, res = %p, match = %p, vals = %p)\n", cmd, cmd->result, cmd->match, cmd->vals);
675 850
 	res = (struct my_cmd*)pkg_malloc(sizeof(struct my_cmd));
676 851
 	if (res == NULL) {
677 852
 		ERR("No memory left\n");
... ...
@@ -690,48 +865,77 @@ int my_cmd(db_cmd_t* cmd)
690 865
 
691 866
 	switch(cmd->type) {
692 867
 	case DB_PUT:
693
-		if (DB_FLD_EMPTY(cmd->params)) {
868
+		if (DB_FLD_EMPTY(cmd->vals)) {
694 869
 			ERR("BUG: No parameters provided for DB_PUT in context '%.*s'\n", 
695 870
 				cmd->ctx->id.len, ZSW(cmd->ctx->id.s));
696 871
 			goto error;
697 872
 		}
698 873
 		if (build_replace_query(&res->query, cmd) < 0) goto error;
874
+		INFO("build_replace_query: query = '%.*s'\n", res->query.len, res->query.s);
699 875
 		if (mysql_stmt_prepare(res->st, res->query.s, res->query.len)) {
700 876
 			ERR("Error while preparing replace query: %s\n", 
701 877
 				mysql_stmt_error(res->st));
702 878
 			goto error;
703 879
 		}
704
-		if (bind_params(res->st, cmd->params) < 0) goto error;
880
+		if (bind_params(res->st, cmd->vals, NULL) < 0) goto error;
705 881
 		break;
706 882
 
707 883
 	case DB_DEL:
708 884
 		if (build_delete_query(&res->query, cmd) < 0) goto error;
885
+		INFO("build_delete_query: query = '%.*s'\n", res->query.len, res->query.s);
709 886
 		if (mysql_stmt_prepare(res->st, res->query.s, res->query.len)) {
710 887
 			ERR("Error while preparing delete query: %s\n",
711 888
 				mysql_stmt_error(res->st));
712 889
 				goto error;
713 890
 		}
714
-		if (!DB_FLD_EMPTY(cmd->params)) {
715
-			if (bind_params(res->st, cmd->params) < 0) goto error;
891
+		if (!DB_FLD_EMPTY(cmd->match)) {
892
+			if (bind_params(res->st, NULL, cmd->match) < 0) goto error;
716 893
 		}
717 894
 		break;
718 895
 
719 896
 	case DB_GET:
720 897
 		if (build_select_query(&res->query, cmd) < 0) goto error;
898
+		INFO("build_select_query: query = '%.*s'\n", res->query.len, res->query.s);
721 899
 		if (mysql_stmt_prepare(res->st, res->query.s, res->query.len)) {
722 900
 			ERR("Error while preparing select query: %s\n",
723 901
 				mysql_stmt_error(res->st));
724 902
 			goto error;
725 903
 		}
726
-		if (!DB_FLD_EMPTY(cmd->params)) {
727
-			if (bind_params(res->st, cmd->params) < 0) goto error;
904
+		if (!DB_FLD_EMPTY(cmd->match)) {
905
+			if (bind_params(res->st, NULL, cmd->match) < 0) goto error;
906
+		}
907
+		if (bind_result(res->st, cmd->result) < 0) {
908
+			ERR("mysql: DB_GET bind_result() failed\n");
909
+			goto error;
910
+		}
911
+		break;
912
+
913
+	case DB_UPD:
914
+		if (build_update_query(&res->query, cmd) < 0) goto error;
915
+		INFO("build_update_query: query = '%.*s'\n", res->query.len, res->query.s);
916
+		if (mysql_stmt_prepare(res->st, res->query.s, res->query.len)) {
917
+			ERR("mysql: Error while preparing UPDATE query: %s\n",
918
+				mysql_stmt_error(res->st));
919
+			goto error;
920
+		}
921
+		/* FIXME: remove ELSE */
922
+		if (!DB_FLD_EMPTY(cmd->vals)) {
923
+			if (bind_params(res->st, cmd->vals, cmd->match) < 0) {
924
+				ERR("mysql: DB_UPD bind_params() failed\n");
925
+				goto error;
926
+			}
927
+		}
928
+		else {
929
+			if (bind_params(res->st, NULL, cmd->match) < 0) {
930
+				ERR("mysql: DB_UPD bind_params() failed\n");
931
+				goto error;
932
+			}
728 933
 		}
729
-		if (bind_result(res->st, cmd->result) < 0) goto error;
730 934
 		break;
731 935
 
732 936
 	case DB_SQL:
733 937
 		if (mysql_stmt_prepare(res->st, cmd->table.s, cmd->table.len)) {
734
-			ERR("Error while preparing raw SQL query: %s\n",
938
+			ERR("mysql: Error while preparing raw SQL query: %s\n",
735 939
 				mysql_stmt_error(res->st));
736 940
 			goto error;
737 941
 		}
... ...
@@ -751,6 +955,7 @@ int my_cmd(db_cmd_t* cmd)
751 955
 		if (res->st) mysql_stmt_close(res->st);
752 956
 		pkg_free(res);
753 957
 	}
958
+	ERR("mysql: my_cmd() failed\n");
754 959
 	return -1;
755 960
 }
756 961
 
... ...
@@ -779,3 +984,4 @@ int my_cmd_next(db_res_t* res)
779 984
 	return 0;
780 985
 }
781 986
 
987
+/** @} */
... ...
@@ -48,6 +48,9 @@ int my_cmd_read(db_res_t* res, db_cmd_t* cmd);
48 48
 /* Runtime execution function for DB_PUT and DB_DEL */
49 49
 int my_cmd_write(db_res_t* res, db_cmd_t* cmd);
50 50
 
51
+/* Runtime execution function for DB_UPD */
52
+int my_cmd_update(db_res_t* res, db_cmd_t* cmd);
53
+
51 54
 /* Raw SQL query */
52 55
 int my_cmd_sql(db_res_t* res, db_cmd_t* cmd);
53 56
 
... ...
@@ -69,6 +69,7 @@ static cmd_export_t cmds[] = {
69 69
 	{"db_put",         (cmd_function)my_cmd_write, 0, 0, 0},
70 70
 	{"db_del",         (cmd_function)my_cmd_write, 0, 0, 0},
71 71
 	{"db_get",         (cmd_function)my_cmd_read, 0, 0, 0},
72
+	{"db_upd",         (cmd_function)my_cmd_update, 0, 0, 0},
72 73
 	{"db_sql",         (cmd_function)my_cmd_sql, 0, 0, 0},
73 74
 	{"db_res",         (cmd_function)my_res,  0, 0, 0},
74 75
 	{"db_fld",         (cmd_function)my_fld,  0, 0, 0},