Browse code

- DB interface is exported via FIFO server (final version)

Bogdan-Andrei Iancu authored on 30/10/2003 20:00:23
Showing 3 changed files
... ...
@@ -32,49 +32,330 @@
32 32
 #include <strings.h>
33 33
 #include <string.h>
34 34
 #include <ctype.h>
35
+#include <time.h>
35 36
 
36 37
 #include "../mem/mem.h"
37 38
 #include "../fifo_server.h"
38 39
 #include "../dprint.h"
39 40
 #include "../str.h"
41
+//#include "../ut.h"
40 42
 #include "db.h"
41 43
 
42
-#define MAX_SIZE_LINE 256
44
+#define MAX_SIZE_LINE 512
43 45
 #define MAX_ARRAY     32
44 46
 
45 47
 #define SELECT_CMD  1
46 48
 #define DELETE_CMD  2
47 49
 #define INSERT_CMD  3
48 50
 #define UPDATE_CMD  4
49
-#define SELECT_STR      "select"
50
-#define SELECT_STR_LEN  (sizeof(SELECT_STR)-1)
51
-#define DELETE_STR      "delete"
52
-#define DELETE_STR_LEN  (sizeof(DELETE_STR)-1)
53
-#define INSERT_STR      "insert"
54
-#define INSERT_STR_LEN  (sizeof(INSERT_STR)-1)
55
-#define UPDATE_STR      "update"
56
-#define UPDATE_STR_LEN  (sizeof(UPDATE_STR)-1)
51
+#define RAWQUERY_CMD     5
52
+#define RAWQUERYRES_CMD  6
53
+
54
+#define SELECT_STR          "select"
55
+#define SELECT_STR_LEN      (sizeof(SELECT_STR)-1)
56
+#define DELETE_STR          "delete"
57
+#define DELETE_STR_LEN      (sizeof(DELETE_STR)-1)
58
+#define INSERT_STR          "insert"
59
+#define INSERT_STR_LEN      (sizeof(INSERT_STR)-1)
60
+#define UPDATE_STR          "update"
61
+#define UPDATE_STR_LEN      (sizeof(UPDATE_STR)-1)
62
+#define RAWQUERY_STR        "raw_query"
63
+#define RAWQUERY_STR_LEN    (sizeof(RAWQUERY_STR)-1)
64
+#define RAWQUERYRES_STR     "raw_query_response"
65
+#define RAWQUERYRES_STR_LEN (sizeof(RAWQUERYRES_STR)-1)
57 66
 #define END_CHR    '.'
58 67
 
68
+#define INT_TYPE         "int"
69
+#define INT_TYPE_LEN     (sizeof(INT_TYPE)-1)
70
+#define DOUBLE_TYPE      "double"
71
+#define DOUBLE_TYPE_LEN  (sizeof(DOUBLE_TYPE)-1)
72
+#define STRING_TYPE      "string"
73
+#define STRING_TYPE_LEN  (sizeof(STRING_TYPE)-1)
74
+#define DATE_TYPE        "date"
75
+#define DATE_TYPE_LEN    (sizeof(DATE_TYPE)-1)
76
+#define BLOB_TYPE        "blob"
77
+#define BLOB_TYPE_LEN    (sizeof(BLOB_TYPE)-1)
78
+#define BITMAP_TYPE      "bitmap"
79
+#define BITMAP_TYPE_LEN  (sizeof(BITMAP_TYPE)-1)
59 80
 
60
-#define trim_spaces(string) \
81
+#define NULL_VAL         "null"
82
+#define NULL_VAL_LEN    (sizeof(NULL_VAL)-1)
83
+
84
+
85
+#define trim_spaces(str) \
86
+	do { \
87
+		for(;*(str).s==' ';(str).s++,(str).len--);\
88
+		for(;(str).s[(str).len-1]==' ';(str).s[--(str).len]=='\0');\
89
+	}while(0)
90
+
91
+#define double_log( _str_ ) \
92
+	do { \
93
+		fprintf( rpl, "ERROR: %s\n",_str_); \
94
+		LOG( L_ERR, "ERROR:(%s:%d): %s\n",__FILE__,__LINE__,_str_); \
95
+	}while(0)
96
+
97
+#define semidouble_log( _str_ ) \
61 98
 	do { \
62
-		for(;*string.s==' ';string.s++,string.len--);\
63
-		for(;string.s[string.len-1]==' ';string.len--);\
99
+		fprintf( rpl, "ERROR: Internal Server Error\n"); \
100
+		LOG( L_ERR, "ERROR:(%s:%d): %s\n",__FILE__,__LINE__,_str_); \
64 101
 	}while(0)
65 102
 
103
+#define get_int(_p_,_end_,_res_,_n_,_err_s_,_err_) \
104
+	do { \
105
+		_res_ = 0;\
106
+		for( _n_=0 ; (_p_)<(_end_) && isdigit(*(_p_)) ; (_p_)++,(_n_)++)\
107
+			(_res_)=(_res_)*10+(*(_p_)-'0');\
108
+		if ((_n_)==0) {\
109
+			double_log( _err_s_ );\
110
+			goto _err_;\
111
+		}\
112
+	}while(0);
113
+
114
+
115
+
116
+
117
+static char   buf[MAX_SIZE_LINE];
118
+static FILE*  rpl;
119
+db_con_t*     fifo_db_con;
120
+
66 121
 
67
-static char buf[MAX_SIZE_LINE];
68 122
 
69 123
 
124
+static inline int sgn_str2float(str* _s, float* _r, db_type_t* _type )
125
+{
126
+	int i, dot = 0;
127
+	int ngv = 0;
128
+	float order = 0.1;
129
+
130
+	*_r = 0;
131
+	*_type = DB_INT;
132
+	i = 0;
133
+	if (_s->len==0) return -3;
134
+	if ( (_s->s[0]=='-' && (ngv=1)==1) || (_s->s[0]=='+') )
135
+		i++;
136
+	for( ; i < _s->len; i++) {
137
+		if (_s->s[i] == '.') {
138
+			if (dot) return -1;
139
+			dot = 1;
140
+			*_type = DB_DOUBLE;
141
+			continue;
142
+		}
143
+		if ((_s->s[i] >= '0') && (_s->s[i] <= '9')) {
144
+			if (dot) {
145
+				*_r += (_s->s[i] - '0') * order;
146
+				order /= 10;
147
+			} else {
148
+				*_r *= 10;
149
+				*_r += _s->s[i] - '0';
150
+			}
151
+		} else {
152
+			return -2;
153
+		}
154
+	}
155
+	if (ngv) *_r = -(*_r);
156
+	return 0;
157
+}
158
+
70 159
 
71 160
 
72
-int get_avps( FILE *fifo , db_key_t *keys, db_op_t *ops, db_val_t *vals,
73
-													int *nr, int max_nr)
161
+static inline int parse_db_value( str *s, db_val_t *val, str **ret_s)
162
+{
163
+	db_type_t type;
164
+	db_type_t nr_type;
165
+	int cast;
166
+	struct tm td;
167
+	char *p;
168
+	char *end;
169
+	int n;
170
+	float nr;
171
+
172
+	cast = 0;
173
+	*ret_s = 0;
174
+	p = 0;
175
+	type = DB_STR;
176
+
177
+	/* some safety checks */
178
+	if (s->len==0 || s->s==0) {
179
+		semidouble_log("BUG -> parse_db_value gets a len/s=0 string");
180
+		goto error;
181
+	}
182
+
183
+	/* is there some data cast operator? */
184
+	if (s->s[0]=='[') {
185
+		/* get the end of the cast operator */
186
+		for(p=s->s,end=s->s+s->len ; p<end && *p!=']' ; p++);
187
+		if (p>=end-1) {
188
+			double_log("Bad cast operator format (expected attr=[type]val)");
189
+			goto error;
190
+		}
191
+		n = p - s->s - 1;
192
+		p = s->s + 1;
193
+		DBG("---><%.*s>\n",n,p);
194
+		/*identify the cast type*/
195
+		if (n==INT_TYPE_LEN && !strncasecmp(p,INT_TYPE,n)) {
196
+			type = DB_INT;
197
+		} else if (n==DOUBLE_TYPE_LEN && !strncasecmp(p,DOUBLE_TYPE,n)) {
198
+			type = DB_DOUBLE;
199
+		} else if (n==STRING_TYPE_LEN && !strncasecmp(p,STRING_TYPE,n)) {
200
+			type = DB_STR;
201
+		} else if (n==BLOB_TYPE_LEN && !strncasecmp(p,BLOB_TYPE,n)) {
202
+			type = DB_BLOB;
203
+		} else if (n==DATE_TYPE_LEN && !strncasecmp(p,DATE_TYPE,n)) {
204
+			type = DB_DATETIME;
205
+		} else if (n==BITMAP_TYPE_LEN && !strncasecmp(p,BITMAP_TYPE,n)) {
206
+			type = DB_BITMAP;
207
+		} else {
208
+			double_log("Unknown cast type");
209
+			goto error;
210
+		}
211
+		cast = 1;
212
+		s->s += n+2;
213
+		s->len -= n+2;
214
+	}
215
+
216
+	/* string has at least one caracter */
217
+	DBG("DEBUG:parse_db_value: value id <%.*s>\n",s->len,s->s);
218
+	if ( s->s[0]=='\"' && s->s[s->len-1]=='\"' && s->len!=1) {
219
+		/* can be DB_STR, DB_STRING, DB_BLOB */
220
+		/* get rid of the quoting */
221
+		s->s++;
222
+		s->len -= 2;
223
+		/* if casted, check if is valid */
224
+		if (cast) {
225
+			if (type!=DB_STR && type!=DB_BLOB) {
226
+				double_log("Invalid cast for quoted value");
227
+				goto error;
228
+			}
229
+		} else {
230
+			type = DB_STR;
231
+		}
232
+		/* fill in the val struct */
233
+		memset( val, 0, sizeof(db_val_t));
234
+		val->type = type;
235
+		if (type==DB_STR) {
236
+			val->val.str_val = *s;
237
+			*ret_s = &val->val.str_val;
238
+		} else if (type==DB_BLOB) {
239
+			val->val.blob_val = *s;
240
+			*ret_s = &val->val.blob_val;
241
+		} else {
242
+			semidouble_log("BUG -> type is not STR or BLOB");
243
+			goto error;
244
+		}
245
+	} else if ( s->s[0]=='<' && s->s[s->len-1]=='>' && s->len!=1) {
246
+		/* can be only date+time type DB_DATETIME*/
247
+		/* if casted, check if is valid */
248
+		if (cast && type!=DB_DATETIME) {
249
+			double_log("Invalid cast for quoted value");
250
+			goto error;
251
+		}
252
+		/* get rid of the quoting */
253
+		s->s++;
254
+		s->len -= 2;
255
+		/* start parsing */
256
+		p = s->s;
257
+		end = s->s + s->len;
258
+		td.tm_wday = 0;
259
+		td.tm_yday = 0;
260
+		/* get year */
261
+		get_int( p, end, td.tm_year, n, "Missing year in date format",error);
262
+		td.tm_year -= 1900; /* corection */
263
+		if (*(p++)!='-') goto date_error;
264
+		/* get month */
265
+		get_int( p, end, td.tm_mon, n, "Missing month in date format",error);
266
+		td.tm_mon --; /* corection */
267
+		if (*(p++)!='-') goto date_error;
268
+		/* get day */
269
+		get_int( p, end, td.tm_mday, n, "Missing day in date format",error);
270
+		if (*(p++)!=' ') goto date_error;
271
+		/* get hour */
272
+		get_int( p, end, td.tm_hour, n, "Missing hour in date format",error);
273
+		if (*(p++)!=':') goto date_error;
274
+		/* get minutes */
275
+		get_int( p, end, td.tm_min, n, "Missing minutes in date format",error);
276
+		if (*(p++)!=':') goto date_error;
277
+		/* get seconds */
278
+		get_int( p, end, td.tm_sec, n,"Missing seconds in date format",error);
279
+		if (p!=end) goto date_error;
280
+		td.tm_isdst = daylight;
281
+		/* fill the val struct */
282
+		val->type = DB_DATETIME;
283
+		val->val.time_val = mktime( &td );
284
+		DBG("DBG: <%.*s> is %s\n",s->len,s->s,ctime(&val->val.time_val));
285
+	} else if ( (*(p=s->s)=='+') || (*p=='-') || isdigit(*p) ) {
286
+		/* can be a DB_INT / DB_DOUBLE / DB_BITMAP value */
287
+		if (sgn_str2float( s, &nr, &nr_type)!=0) {
288
+			double_log("Bad int/float value format (expected [+/-]nr[.nr])");
289
+			goto error;
290
+		}
291
+		/* if casted, check if valid */
292
+		if (cast) {
293
+			switch (type) {
294
+				case DB_BITMAP:
295
+					if ( nr_type!=DB_INT || nr<0 ) {
296
+						double_log("Invalid value for BITMAP type");
297
+						goto error;
298
+					}
299
+					break;
300
+				case DB_INT:
301
+				case DB_DOUBLE:
302
+					if (type==DB_INT && nr_type==DB_DOUBLE ) {
303
+						double_log("Invalid cast to INT for a DOUBLE value");
304
+						goto error;
305
+					}
306
+					break;
307
+				default:
308
+					double_log("Invalid cast for numerical value");
309
+					goto error;
310
+			}
311
+		} else {
312
+			type = nr_type;
313
+		}
314
+		/* fill the val struct */
315
+		val->type = type;
316
+		switch (type) {
317
+			case DB_INT:
318
+				val->val.int_val = (int)nr; break;
319
+			case DB_DOUBLE:
320
+				val->val.double_val = nr; break;
321
+			case DB_BITMAP:
322
+				val->val.bitmap_val = (int)nr; break;
323
+			default:
324
+				semidouble_log("BUG -> unknown type when filling num. val");
325
+				goto error;
326
+		}
327
+	} else if (s->len==NULL_VAL_LEN && !strncasecmp(s->s,NULL_VAL,s->len) ) {
328
+		/* it's a NULL val */
329
+		if (!cast) {
330
+			double_log("NULL values requires type casting");
331
+			goto error;
332
+		}
333
+		val->type = type;
334
+		val->nul = 1;
335
+	} else {
336
+		double_log("Unable to recognize value type");
337
+		goto error;
338
+	}
339
+
340
+	return 0;
341
+date_error:
342
+	double_log("Bad <date time> format (expected <YYYY-MM-DD hh:mm:ss>)\n");
343
+error:
344
+	return -1;
345
+}
346
+
347
+
348
+
349
+/* returns : -1 error
350
+ *            0 success */
351
+static inline int get_avps( FILE *fifo , db_key_t *keys, db_op_t *ops,
352
+										db_val_t *vals, int *nr, int max_nr)
74 353
 {
75 354
 	str  line;
76 355
 	str  key,op,val;
77 356
 	char *c;
357
+	str  *p_val;
358
+	int  sp_found;
78 359
 
79 360
 	*nr = 0;
80 361
 
... ...
@@ -82,56 +363,78 @@ int get_avps( FILE *fifo , db_key_t *keys, db_op_t *ops, db_val_t *vals,
82 363
 		/* read a new line */
83 364
 		line.s = buf;
84 365
 		if (read_line( line.s, MAX_SIZE_LINE, fifo, &line.len)!=1) {
85
-			LOG(L_ERR,"ERROR:get_avps: cannot read avp(key|op|val)\n");
366
+			double_log("Comamnd end when reading AVPs - missing . at after "
367
+				"AVP list?");
86 368
 			goto error;
87 369
 		}
88 370
 		trim_spaces(line);
89 371
 		/* is this the separter/end char? */
90 372
 		if (line.len==1 && *line.s==END_CHR)
91
-			return 1;
373
+			return 0;
92 374
 		/* we have a new avp */
93 375
 		if (*nr<max_nr) {
94 376
 			/* parse the line key|op|val */
95 377
 			c = line.s;
96
-			/* parse thr key name */
97
-			for( key.s=c ; isalnum(*c)||*c=='_'||*c=='-' ; c++ );
378
+			/* parse the key name */
379
+			for( key.s=c ; *c && (isalnum(*c)||*c=='_') ; c++ );
380
+			if (!*c) goto parse_error;
98 381
 			key.len = c-key.s;
99 382
 			if (key.len==0) goto parse_error;
100 383
 			/* possible spaces? */
101
-			for( ; isspace(*c) ; c++ );
102
-			/* parse the operater */
384
+			for( sp_found=0 ; *c && isspace(*c) ; c++,sp_found=1 );
385
+			if (!*c) goto parse_error;
386
+			/* parse the operator */
103 387
 			op.s = c;
104
-			if (*c=='='||*c=='<'||*c=='>')
105
-				c++;
106
-			else
107
-				goto parse_error;
388
+			switch (*c) {
389
+				case '<':
390
+				case '>':
391
+					if (*(c+1)=='=') c++;
392
+				case '=':
393
+					c++;
394
+					if (!*c) goto parse_error;
395
+					break;
396
+				default:
397
+					/* at least one space must be before unknown ops */
398
+					if(!sp_found) goto parse_error;
399
+					/* eat everything to first space */
400
+					for( ; *c && !isspace(*c) ; c++ );
401
+					if (!*c || c==op.s) goto parse_error; /* 0 length */
402
+					/* include into operator str. one space before and after*/
403
+					op.s--;
404
+					c++;
405
+			}
108 406
 			op.len = c - op.s;
109 407
 			/* possible spaces? */
110
-			for( ; isspace(*c) ; c++ );
111
-			/* parse value */
408
+			for( ; *c && isspace(*c) ; c++ );
409
+			if (!*c) goto parse_error;
410
+			/* get value */
112 411
 			val.s = c;
113 412
 			val.len = line.len - (c-line.s);
413
+			if (val.len==0) goto parse_error;
414
+			if (parse_db_value( &val, &vals[*nr], &p_val)!=0)
415
+				goto error;
114 416
 			/* duplicate the avp -> make all null terminated */
115
-			c = (char*)pkg_malloc(key.len+op.len+val.len+3);
417
+			c = (char*)pkg_malloc(key.len+op.len+2+(p_val?p_val->len+1:0));
116 418
 			if (c==0) {
117
-				LOG(L_ERR,"ERROR:get_avps: no more pkg memory\n");
419
+				semidouble_log("no more pkg memory");
118 420
 				goto error;
119 421
 			}
120 422
 			/*copy the key */
121 423
 			keys[*nr] = c;
122 424
 			memcpy( c, key.s, key.len);
123 425
 			c[key.len] = 0;
124
-			c += key.len;
426
+			c += key.len + 1;
125 427
 			/*copy the op */
126 428
 			ops[*nr] = c;
127 429
 			memcpy( c, op.s, op.len);
128 430
 			c[op.len] = 0;
129
-			c += op.len;
431
+			c += op.len + 1;
130 432
 			/*copy the val */
131
-			vals[*nr].val.string_val = c;
132
-			memcpy( c, val.s, val.len);
133
-			c[val.len] = 0;
134
-			c += val.len;
433
+			if (p_val) {
434
+				memcpy( c, p_val->s, p_val->len);
435
+				c[p_val->len] = 0;
436
+				p_val->s = c;
437
+			}
135 438
 			/* done */
136 439
 			(*nr)++;
137 440
 		} else {
... ...
@@ -142,44 +445,42 @@ int get_avps( FILE *fifo , db_key_t *keys, db_op_t *ops, db_val_t *vals,
142 445
 parse_error:
143 446
 	LOG(L_ERR,"ERROR:get_avps: parse error in \"%.*s\" at char [%d][%c] "
144 447
 		"offset %d\n",line.len,line.s,*c,*c,c-line.s);
448
+	double_log("Broken AVP(attr|op|val) in DB command");
145 449
 error:
146 450
 	for(;*nr;*nr--)
147
-		pkg_free( (void*)keys[*nr] );
451
+		pkg_free( (void*)keys[*nr-1] );
148 452
 	return -1;
149 453
 }
150 454
 
151 455
 
152
-/* returns : -1 bad key list
153
- *           -2 server error
154
- *            1 success */
155
-int get_keys( FILE *fifo , db_key_t *keys, int *nr, int max_nr)
456
+
457
+/* returns : -1 error
458
+ *            0 success */
459
+static inline int get_keys( FILE *fifo , db_key_t *keys, int *nr, int max_nr)
156 460
 {
157 461
 	str line;
158 462
 	char *key;
159
-	int ret;
160 463
 
161 464
 	*nr = 0;
162
-	ret = -1;
163 465
 
164 466
 	while(1) {
165 467
 		/* read a new line */
166 468
 		line.s = buf;
167 469
 		if (!read_line( line.s, MAX_SIZE_LINE, fifo, &line.len) || !line.len) {
168
-			LOG(L_ERR,"ERROR:get_keys: cannot read key name\n");
470
+			double_log("Bad key list in SELECT DB command "
471
+				"(missing '.' at the end?)");
169 472
 			goto error;
170 473
 		}
171 474
 		trim_spaces(line);
172
-		DBG("---read <%.*s>\n",line.len,line.s);
173 475
 		/* is this the separter/end char? */
174 476
 		if (line.len==1 && *line.s==END_CHR)
175
-			return 1;
477
+			return 0;
176 478
 		/* we have a new key */
177 479
 		if (*nr<max_nr) {
178 480
 			/* duplicate the key -> null terminated */
179 481
 			key = (char*)pkg_malloc(line.len+1);
180 482
 			if (key==0) {
181
-				LOG(L_ERR,"ERROR:get_key: no more pkg memory\n");
182
-				ret = -2;
483
+				semidouble_log("no more pkg memory");
183 484
 				goto error;
184 485
 			}
185 486
 			memcpy( key, line.s, line.len);
... ...
@@ -191,27 +492,87 @@ int get_keys( FILE *fifo , db_key_t *keys, int *nr, int max_nr)
191 492
 				"\"%.*s\"\n",max_nr,line.len,line.s);
192 493
 		}
193 494
 	}
495
+
194 496
 error:
195 497
 	for(;*nr;*nr--)
196
-		pkg_free( (void*)keys[*nr] );
197
-	return ret;
498
+		pkg_free( (void*)keys[*nr-1] );
499
+	return -1;
500
+}
501
+
502
+
503
+
504
+static inline void print_res(db_res_t* res, FILE *rpl)
505
+{
506
+	int i, j;
507
+
508
+	for(i = 0; i < RES_COL_N(res); i++) {
509
+		fprintf(rpl, "%s ", RES_NAMES(res)[i]);
510
+	}
511
+	fprintf(rpl,"\n");
512
+
513
+	for(i = 0; i < RES_ROW_N(res); i++) {
514
+		for(j = 0; j < RES_COL_N(res); j++) {
515
+			if (RES_ROWS(res)[i].values[j].nul) {
516
+				fprintf(rpl,"NULL ");
517
+				continue;
518
+			}
519
+			switch(RES_ROWS(res)[i].values[j].type) {
520
+				case DB_INT:
521
+					fprintf(rpl,"%d ",
522
+						RES_ROWS(res)[i].values[j].val.int_val);
523
+					break;
524
+				case DB_DOUBLE:
525
+					fprintf(rpl,"%f ",
526
+						RES_ROWS(res)[i].values[j].val.double_val);
527
+				break;
528
+				case DB_DATETIME:
529
+					fprintf(rpl,"%s ",
530
+						ctime(&(RES_ROWS(res)[i].values[j].val.time_val)));
531
+					break;
532
+				case DB_STRING:
533
+					fprintf(rpl,"%s ",
534
+						RES_ROWS(res)[i].values[j].val.string_val);
535
+					break;
536
+				case DB_STR:
537
+					fprintf(rpl,"%.*s ", 
538
+						RES_ROWS(res)[i].values[j].val.str_val.len,
539
+						RES_ROWS(res)[i].values[j].val.str_val.s);
540
+					break;
541
+				case DB_BLOB:
542
+					fprintf(rpl,"%.*s ",
543
+						RES_ROWS(res)[i].values[j].val.blob_val.len,
544
+						RES_ROWS(res)[i].values[j].val.blob_val.s);
545
+					break;
546
+				case DB_BITMAP:
547
+					fprintf(rpl,"%d ",
548
+						RES_ROWS(res)[i].values[j].val.bitmap_val);
549
+					break;
550
+			}
551
+		}
552
+		fprintf(rpl,"\n");
553
+	}
198 554
 }
199 555
 
200 556
 
201 557
 
558
+
202 559
 int db_fifo( FILE *fifo, char *response_file )
203 560
 {
204 561
 	static db_key_t keys1[MAX_ARRAY];
205
-	//static db_op_t  ops1[MAX_ARRAY];
206
-	//static db_val_t vals1[MAX_ARRAY];
562
+	static db_op_t  ops1[MAX_ARRAY];
563
+	static db_val_t vals1[MAX_ARRAY];
207 564
 	static db_key_t keys2[MAX_ARRAY];
208 565
 	static db_op_t  ops2[MAX_ARRAY];
209 566
 	static db_val_t vals2[MAX_ARRAY];
210
-	FILE *rpl = 0;
567
+	static db_res_t *select_res;
211 568
 	str   line;
212 569
 	int   db_cmd;
213 570
 	int   nr1, nr2;
214 571
 	int   ret;
572
+	int   n;
573
+
574
+	ret = -1; /* default is error */
575
+	rpl =  0;
215 576
 
216 577
 	/* first check the response file */
217 578
 	rpl = open_reply_pipe( response_file );
... ...
@@ -221,8 +582,7 @@ int db_fifo( FILE *fifo, char *response_file )
221 582
 	/* first name must be the real name of the DB operation */
222 583
 	line.s = buf;
223 584
 	if (!read_line( line.s, MAX_SIZE_LINE, fifo, &line.len) || line.len==0) {
224
-		fprintf( rpl, "DB command name expected\n");
225
-		LOG(L_ERR,"ERROR:db_fifo: cannot read fifo cmd name\n");
585
+		double_log("DB command name expected");
226 586
 		goto error;
227 587
 	}
228 588
 	trim_spaces(line);
... ...
@@ -240,57 +600,148 @@ int db_fifo( FILE *fifo, char *response_file )
240 600
 	} else if (line.len==UPDATE_STR_LEN
241 601
 	&& !strncasecmp( line.s, UPDATE_STR, line.len)) {
242 602
 		db_cmd = UPDATE_CMD;
603
+	} else if (line.len==RAWQUERY_STR_LEN
604
+	&& !strncasecmp( line.s, RAWQUERY_STR, line.len)) {
605
+		db_cmd = RAWQUERY_CMD;
606
+	} else if (line.len==RAWQUERYRES_STR_LEN
607
+	&& !strncasecmp( line.s, RAWQUERYRES_STR, line.len)) {
608
+		db_cmd = RAWQUERYRES_CMD;
243 609
 	} else {
244
-		fprintf( rpl, "unknown DB command \"%.*s\"\n",line.len,line.s);
245
-		LOG(L_ERR,"ERROR:db_fifo: unknown command \"%.*s\"\n",
246
-			line.len,line.s);
610
+		double_log("Unknown DB command name");
247 611
 		goto error;
248 612
 	}
249 613
 	DBG("DEBUG:db_fifo: cmd \"%.*s\" received\n",line.len,line.s);
250 614
 
615
+	nr1 = 0;
616
+	nr2 = 0;
617
+
251 618
 	if (db_cmd==SELECT_CMD) {
252 619
 		/* read the colums to be fetched */
253
-		ret = get_keys( fifo, keys1, &nr1, MAX_ARRAY);
254
-		if (ret==-1) {
255
-			fprintf( rpl, "Bad key list in SELECT DB command "
256
-				"(missing '.' at the end?)\n");
257
-			LOG(L_ERR,"ERROR:db_fifo: bad key list termination in SELECT cmd"
258
-				"(missing '.' at the end?)\n");
620
+		if ( get_keys( fifo, keys1, &nr1, MAX_ARRAY)!=0 )
259 621
 			goto error;
260
-		} else if (ret==-2) {
261
-			fprintf( rpl, "Internal Server error\n");
622
+	} else if (db_cmd==UPDATE_CMD) {
623
+		/* read the col=val pairs to be updated */
624
+		if (get_avps( fifo , keys1, ops1, vals1, &nr1, MAX_ARRAY)!=0 )
262 625
 			goto error;
263
-		} else if (nr1==0) {
264
-			fprintf( rpl, "Empty key list found in SELECT DB command\n");
265
-			LOG(L_ERR,"ERROR:db_fifo: no keys specified in SELECT cmd\n");
626
+		/* must be at least one AVP in an update command */
627
+		if (nr1==0) {
628
+			double_log("UPDATE command must have at least one"
629
+				" field to update");
266 630
 			goto error;
267 631
 		}
268
-	} else if (db_cmd==UPDATE_CMD) {
269
-		/* read the col=val pairs to be updated */
632
+		/* all the operators must be '=' */
633
+		for(n=0;n<nr1;n++) {
634
+			if (ops1[n][0]!='=' || ops1[n][1]!='\0') {
635
+				double_log("Invalid operator in updated fileds (expected = )");
636
+				goto error1;
637
+			}
638
+		}/*end for*/
639
+	} else if (db_cmd==RAWQUERY_CMD || db_cmd==RAWQUERYRES_CMD) {
640
+		/* read the raw db command  */
641
+		line.s = buf;
642
+		if (!read_line( line.s, MAX_SIZE_LINE-1,fifo,&line.len) || !line.len) {
643
+			double_log("Raw db command expected");
644
+			goto error;
645
+		}
646
+		trim_spaces(line);
647
+		/* run the command */
648
+		if (db_cmd==RAWQUERY_CMD)
649
+			n = db_raw_query( fifo_db_con, line.s, 0);
650
+		else
651
+			n = db_raw_query( fifo_db_con, line.s, &select_res);
652
+		if (n!=0) {
653
+			double_log("Internal Server error - DB query failed");
654
+			goto error;
655
+		}
656
+		/* any results? */
657
+		if (db_cmd==RAWQUERYRES_CMD) {
658
+			/* get all response and write them into reply fifo */
659
+			print_res( select_res, rpl);
660
+			/* free the query response */
661
+			db_free_query( fifo_db_con, select_res);
662
+		}
663
+		/* done with success */
664
+		goto done;
270 665
 	}
271 666
 
272 667
 	/* read the table name */
273 668
 	line.s = buf;
274
-	if (!read_line( line.s, MAX_SIZE_LINE, fifo, &line.len) || !line.len) {
275
-		fprintf( rpl, "Table name expected\n");
276
-		LOG(L_ERR,"ERROR:db_fifo: cannot read table name\n");
277
-		goto error;
669
+	if (!read_line( line.s, MAX_SIZE_LINE-1, fifo, &line.len) || !line.len) {
670
+		double_log("Table name expected");
671
+		goto error1;
278 672
 	}
279 673
 	trim_spaces(line);
280 674
 
281
-	/*read 'where' avps */
282
-	//if (get_avps( fifo , keys2, ops2, vals2, &nr2, MAX_ARRAY)==-1)
283
-	//	goto error;
284
-
675
+	/* select the correct table */
676
+	line.s[line.len] = 0; /* make it null terminated */
677
+	db_use_table( fifo_db_con, line.s);
285 678
 
286
-	if (db_cmd==SELECT_CMD) {
287
-		 
679
+	/*read 'where' avps */
680
+	if (get_avps( fifo , keys2, ops2, vals2, &nr2, MAX_ARRAY)!=0 )
681
+		goto error1;
682
+
683
+	switch (db_cmd) {
684
+		case SELECT_CMD:
685
+			if (line.len==1 && line.s[0]=='.')
686
+			/* push the query */
687
+			n = db_query( fifo_db_con, nr2?keys2:0, nr2?ops2:0, nr2?vals2:0,
688
+				nr1?keys1:0, nr2, nr1, 0, &select_res );
689
+			if (n!=0) {
690
+				double_log("Internal Server error - DB query failed");
691
+				goto error2;
692
+			}
693
+			/* get all response and write them into reply fifo */
694
+			print_res( select_res, rpl);
695
+			/* free the query response */
696
+			db_free_query( fifo_db_con, select_res);
697
+			break;
698
+		case UPDATE_CMD:
699
+			/* push the query */
700
+			n = db_update( fifo_db_con, nr2?keys2:0, nr2?ops2:0, nr2?vals2:0,
701
+				keys1, vals1, nr2, nr1 );
702
+			if (n!=0) {
703
+				double_log("Internal Server error - DB query failed");
704
+				goto error2;
705
+			}
706
+			break;
707
+		case DELETE_CMD:
708
+			/* push the query */
709
+			n = db_delete( fifo_db_con, nr2?keys2:0, nr2?ops2:0, nr2?vals2:0,
710
+				nr2);
711
+			if (n!=0) {
712
+				double_log("Internal Server error - DB query failed");
713
+				goto error2;
714
+			}
715
+			break;
716
+		case INSERT_CMD:
717
+			/* all the operators must be '=' */
718
+			for(n=0;n<nr2;n++) {
719
+				if (ops2[n][0]!='=' || ops2[n][1]!='\0') {
720
+					double_log("Invalid operatpr in inserted fileds "
721
+						"(expected = )");
722
+					goto error;
723
+				}
724
+			}/*end for*/
725
+			/* push the query */
726
+			n = db_insert( fifo_db_con, nr2?keys2:0, nr2?vals2:0, nr2);
727
+			if (n!=0) {
728
+				double_log("Internal Server error - DB query failed");
729
+				goto error2;
730
+			}
731
+			break;
288 732
 	}
289 733
 
290
-	fclose(rpl);
291
-	return 0;
734
+	/* success */
735
+done:
736
+	ret = 0;
737
+error2:
738
+	for(;nr2;nr2--)
739
+		pkg_free( (void*)keys2[nr2-1] );
740
+error1:
741
+	for(;nr1;nr1--)
742
+		pkg_free( (void*)keys1[nr1-1] );
292 743
 error:
293 744
 	if (rpl) fclose(rpl);
294
-	return -1;
745
+	return ret;
295 746
 }
296 747
 
... ...
@@ -31,6 +31,8 @@
31 31
 #define db_fifo_cmd  db_fifo
32 32
 #define FIFO_DB      "DB"
33 33
 
34
+extern db_con_t*   fifo_db_con;
35
+
34 36
 int db_fifo( FILE *fifo_stream, char *response_file );
35 37
 
36 38
 
... ...
@@ -858,7 +858,11 @@ int register_core_fifo()
858 858
 			LOG(L_ERR, "ERROR: unable to register '%s' FIFO cmd\n", FIFO_DB);
859 859
 			return -1;
860 860
 		} else {
861
-			/* call db_init() */
861
+			if ( (fifo_db_con=db_init( fifo_db_url ))==0) {
862
+				/* connection failed */
863
+			LOG(L_ERR,"ERROR: unable to connect to database -> "
864
+				"fifo DB commands disabled!\n");
865
+			}
862 866
 		}
863 867
 	} else {
864 868
 		LOG(L_WARN,"WARNING: unable to find any db module - "