瀏覽代碼

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

Bogdan-Andrei Iancu 22 年之前
父節點
當前提交
b592f42cee
共有 3 個文件被更改,包括 541 次插入84 次删除
  1. 534 83
      db/db_fifo.c
  2. 2 0
      db/db_fifo.h
  3. 5 1
      fifo_server.c

+ 534 - 83
db/db_fifo.c

@@ -32,49 +32,330 @@
 #include <strings.h>
 #include <string.h>
 #include <ctype.h>
+#include <time.h>
 
 #include "../mem/mem.h"
 #include "../fifo_server.h"
 #include "../dprint.h"
 #include "../str.h"
+//#include "../ut.h"
 #include "db.h"
 
-#define MAX_SIZE_LINE 256
+#define MAX_SIZE_LINE 512
 #define MAX_ARRAY     32
 
 #define SELECT_CMD  1
 #define DELETE_CMD  2
 #define INSERT_CMD  3
 #define UPDATE_CMD  4
-#define SELECT_STR      "select"
-#define SELECT_STR_LEN  (sizeof(SELECT_STR)-1)
-#define DELETE_STR      "delete"
-#define DELETE_STR_LEN  (sizeof(DELETE_STR)-1)
-#define INSERT_STR      "insert"
-#define INSERT_STR_LEN  (sizeof(INSERT_STR)-1)
-#define UPDATE_STR      "update"
-#define UPDATE_STR_LEN  (sizeof(UPDATE_STR)-1)
+#define RAWQUERY_CMD     5
+#define RAWQUERYRES_CMD  6
+
+#define SELECT_STR          "select"
+#define SELECT_STR_LEN      (sizeof(SELECT_STR)-1)
+#define DELETE_STR          "delete"
+#define DELETE_STR_LEN      (sizeof(DELETE_STR)-1)
+#define INSERT_STR          "insert"
+#define INSERT_STR_LEN      (sizeof(INSERT_STR)-1)
+#define UPDATE_STR          "update"
+#define UPDATE_STR_LEN      (sizeof(UPDATE_STR)-1)
+#define RAWQUERY_STR        "raw_query"
+#define RAWQUERY_STR_LEN    (sizeof(RAWQUERY_STR)-1)
+#define RAWQUERYRES_STR     "raw_query_response"
+#define RAWQUERYRES_STR_LEN (sizeof(RAWQUERYRES_STR)-1)
 #define END_CHR    '.'
 
+#define INT_TYPE         "int"
+#define INT_TYPE_LEN     (sizeof(INT_TYPE)-1)
+#define DOUBLE_TYPE      "double"
+#define DOUBLE_TYPE_LEN  (sizeof(DOUBLE_TYPE)-1)
+#define STRING_TYPE      "string"
+#define STRING_TYPE_LEN  (sizeof(STRING_TYPE)-1)
+#define DATE_TYPE        "date"
+#define DATE_TYPE_LEN    (sizeof(DATE_TYPE)-1)
+#define BLOB_TYPE        "blob"
+#define BLOB_TYPE_LEN    (sizeof(BLOB_TYPE)-1)
+#define BITMAP_TYPE      "bitmap"
+#define BITMAP_TYPE_LEN  (sizeof(BITMAP_TYPE)-1)
 
-#define trim_spaces(string) \
+#define NULL_VAL         "null"
+#define NULL_VAL_LEN    (sizeof(NULL_VAL)-1)
+
+
+#define trim_spaces(str) \
+	do { \
+		for(;*(str).s==' ';(str).s++,(str).len--);\
+		for(;(str).s[(str).len-1]==' ';(str).s[--(str).len]=='\0');\
+	}while(0)
+
+#define double_log( _str_ ) \
+	do { \
+		fprintf( rpl, "ERROR: %s\n",_str_); \
+		LOG( L_ERR, "ERROR:(%s:%d): %s\n",__FILE__,__LINE__,_str_); \
+	}while(0)
+
+#define semidouble_log( _str_ ) \
 	do { \
-		for(;*string.s==' ';string.s++,string.len--);\
-		for(;string.s[string.len-1]==' ';string.len--);\
+		fprintf( rpl, "ERROR: Internal Server Error\n"); \
+		LOG( L_ERR, "ERROR:(%s:%d): %s\n",__FILE__,__LINE__,_str_); \
 	}while(0)
 
+#define get_int(_p_,_end_,_res_,_n_,_err_s_,_err_) \
+	do { \
+		_res_ = 0;\
+		for( _n_=0 ; (_p_)<(_end_) && isdigit(*(_p_)) ; (_p_)++,(_n_)++)\
+			(_res_)=(_res_)*10+(*(_p_)-'0');\
+		if ((_n_)==0) {\
+			double_log( _err_s_ );\
+			goto _err_;\
+		}\
+	}while(0);
+
+
+
+
+static char   buf[MAX_SIZE_LINE];
+static FILE*  rpl;
+db_con_t*     fifo_db_con;
+
 
-static char buf[MAX_SIZE_LINE];
 
 
+static inline int sgn_str2float(str* _s, float* _r, db_type_t* _type )
+{
+	int i, dot = 0;
+	int ngv = 0;
+	float order = 0.1;
+
+	*_r = 0;
+	*_type = DB_INT;
+	i = 0;
+	if (_s->len==0) return -3;
+	if ( (_s->s[0]=='-' && (ngv=1)==1) || (_s->s[0]=='+') )
+		i++;
+	for( ; i < _s->len; i++) {
+		if (_s->s[i] == '.') {
+			if (dot) return -1;
+			dot = 1;
+			*_type = DB_DOUBLE;
+			continue;
+		}
+		if ((_s->s[i] >= '0') && (_s->s[i] <= '9')) {
+			if (dot) {
+				*_r += (_s->s[i] - '0') * order;
+				order /= 10;
+			} else {
+				*_r *= 10;
+				*_r += _s->s[i] - '0';
+			}
+		} else {
+			return -2;
+		}
+	}
+	if (ngv) *_r = -(*_r);
+	return 0;
+}
+
 
 
-int get_avps( FILE *fifo , db_key_t *keys, db_op_t *ops, db_val_t *vals,
-													int *nr, int max_nr)
+static inline int parse_db_value( str *s, db_val_t *val, str **ret_s)
+{
+	db_type_t type;
+	db_type_t nr_type;
+	int cast;
+	struct tm td;
+	char *p;
+	char *end;
+	int n;
+	float nr;
+
+	cast = 0;
+	*ret_s = 0;
+	p = 0;
+	type = DB_STR;
+
+	/* some safety checks */
+	if (s->len==0 || s->s==0) {
+		semidouble_log("BUG -> parse_db_value gets a len/s=0 string");
+		goto error;
+	}
+
+	/* is there some data cast operator? */
+	if (s->s[0]=='[') {
+		/* get the end of the cast operator */
+		for(p=s->s,end=s->s+s->len ; p<end && *p!=']' ; p++);
+		if (p>=end-1) {
+			double_log("Bad cast operator format (expected attr=[type]val)");
+			goto error;
+		}
+		n = p - s->s - 1;
+		p = s->s + 1;
+		DBG("---><%.*s>\n",n,p);
+		/*identify the cast type*/
+		if (n==INT_TYPE_LEN && !strncasecmp(p,INT_TYPE,n)) {
+			type = DB_INT;
+		} else if (n==DOUBLE_TYPE_LEN && !strncasecmp(p,DOUBLE_TYPE,n)) {
+			type = DB_DOUBLE;
+		} else if (n==STRING_TYPE_LEN && !strncasecmp(p,STRING_TYPE,n)) {
+			type = DB_STR;
+		} else if (n==BLOB_TYPE_LEN && !strncasecmp(p,BLOB_TYPE,n)) {
+			type = DB_BLOB;
+		} else if (n==DATE_TYPE_LEN && !strncasecmp(p,DATE_TYPE,n)) {
+			type = DB_DATETIME;
+		} else if (n==BITMAP_TYPE_LEN && !strncasecmp(p,BITMAP_TYPE,n)) {
+			type = DB_BITMAP;
+		} else {
+			double_log("Unknown cast type");
+			goto error;
+		}
+		cast = 1;
+		s->s += n+2;
+		s->len -= n+2;
+	}
+
+	/* string has at least one caracter */
+	DBG("DEBUG:parse_db_value: value id <%.*s>\n",s->len,s->s);
+	if ( s->s[0]=='\"' && s->s[s->len-1]=='\"' && s->len!=1) {
+		/* can be DB_STR, DB_STRING, DB_BLOB */
+		/* get rid of the quoting */
+		s->s++;
+		s->len -= 2;
+		/* if casted, check if is valid */
+		if (cast) {
+			if (type!=DB_STR && type!=DB_BLOB) {
+				double_log("Invalid cast for quoted value");
+				goto error;
+			}
+		} else {
+			type = DB_STR;
+		}
+		/* fill in the val struct */
+		memset( val, 0, sizeof(db_val_t));
+		val->type = type;
+		if (type==DB_STR) {
+			val->val.str_val = *s;
+			*ret_s = &val->val.str_val;
+		} else if (type==DB_BLOB) {
+			val->val.blob_val = *s;
+			*ret_s = &val->val.blob_val;
+		} else {
+			semidouble_log("BUG -> type is not STR or BLOB");
+			goto error;
+		}
+	} else if ( s->s[0]=='<' && s->s[s->len-1]=='>' && s->len!=1) {
+		/* can be only date+time type DB_DATETIME*/
+		/* if casted, check if is valid */
+		if (cast && type!=DB_DATETIME) {
+			double_log("Invalid cast for quoted value");
+			goto error;
+		}
+		/* get rid of the quoting */
+		s->s++;
+		s->len -= 2;
+		/* start parsing */
+		p = s->s;
+		end = s->s + s->len;
+		td.tm_wday = 0;
+		td.tm_yday = 0;
+		/* get year */
+		get_int( p, end, td.tm_year, n, "Missing year in date format",error);
+		td.tm_year -= 1900; /* corection */
+		if (*(p++)!='-') goto date_error;
+		/* get month */
+		get_int( p, end, td.tm_mon, n, "Missing month in date format",error);
+		td.tm_mon --; /* corection */
+		if (*(p++)!='-') goto date_error;
+		/* get day */
+		get_int( p, end, td.tm_mday, n, "Missing day in date format",error);
+		if (*(p++)!=' ') goto date_error;
+		/* get hour */
+		get_int( p, end, td.tm_hour, n, "Missing hour in date format",error);
+		if (*(p++)!=':') goto date_error;
+		/* get minutes */
+		get_int( p, end, td.tm_min, n, "Missing minutes in date format",error);
+		if (*(p++)!=':') goto date_error;
+		/* get seconds */
+		get_int( p, end, td.tm_sec, n,"Missing seconds in date format",error);
+		if (p!=end) goto date_error;
+		td.tm_isdst = daylight;
+		/* fill the val struct */
+		val->type = DB_DATETIME;
+		val->val.time_val = mktime( &td );
+		DBG("DBG: <%.*s> is %s\n",s->len,s->s,ctime(&val->val.time_val));
+	} else if ( (*(p=s->s)=='+') || (*p=='-') || isdigit(*p) ) {
+		/* can be a DB_INT / DB_DOUBLE / DB_BITMAP value */
+		if (sgn_str2float( s, &nr, &nr_type)!=0) {
+			double_log("Bad int/float value format (expected [+/-]nr[.nr])");
+			goto error;
+		}
+		/* if casted, check if valid */
+		if (cast) {
+			switch (type) {
+				case DB_BITMAP:
+					if ( nr_type!=DB_INT || nr<0 ) {
+						double_log("Invalid value for BITMAP type");
+						goto error;
+					}
+					break;
+				case DB_INT:
+				case DB_DOUBLE:
+					if (type==DB_INT && nr_type==DB_DOUBLE ) {
+						double_log("Invalid cast to INT for a DOUBLE value");
+						goto error;
+					}
+					break;
+				default:
+					double_log("Invalid cast for numerical value");
+					goto error;
+			}
+		} else {
+			type = nr_type;
+		}
+		/* fill the val struct */
+		val->type = type;
+		switch (type) {
+			case DB_INT:
+				val->val.int_val = (int)nr; break;
+			case DB_DOUBLE:
+				val->val.double_val = nr; break;
+			case DB_BITMAP:
+				val->val.bitmap_val = (int)nr; break;
+			default:
+				semidouble_log("BUG -> unknown type when filling num. val");
+				goto error;
+		}
+	} else if (s->len==NULL_VAL_LEN && !strncasecmp(s->s,NULL_VAL,s->len) ) {
+		/* it's a NULL val */
+		if (!cast) {
+			double_log("NULL values requires type casting");
+			goto error;
+		}
+		val->type = type;
+		val->nul = 1;
+	} else {
+		double_log("Unable to recognize value type");
+		goto error;
+	}
+
+	return 0;
+date_error:
+	double_log("Bad <date time> format (expected <YYYY-MM-DD hh:mm:ss>)\n");
+error:
+	return -1;
+}
+
+
+
+/* returns : -1 error
+ *            0 success */
+static inline int get_avps( FILE *fifo , db_key_t *keys, db_op_t *ops,
+										db_val_t *vals, int *nr, int max_nr)
 {
 	str  line;
 	str  key,op,val;
 	char *c;
+	str  *p_val;
+	int  sp_found;
 
 	*nr = 0;
 
@@ -82,56 +363,78 @@ int get_avps( FILE *fifo , db_key_t *keys, db_op_t *ops, db_val_t *vals,
 		/* read a new line */
 		line.s = buf;
 		if (read_line( line.s, MAX_SIZE_LINE, fifo, &line.len)!=1) {
-			LOG(L_ERR,"ERROR:get_avps: cannot read avp(key|op|val)\n");
+			double_log("Comamnd end when reading AVPs - missing . at after "
+				"AVP list?");
 			goto error;
 		}
 		trim_spaces(line);
 		/* is this the separter/end char? */
 		if (line.len==1 && *line.s==END_CHR)
-			return 1;
+			return 0;
 		/* we have a new avp */
 		if (*nr<max_nr) {
 			/* parse the line key|op|val */
 			c = line.s;
-			/* parse thr key name */
-			for( key.s=c ; isalnum(*c)||*c=='_'||*c=='-' ; c++ );
+			/* parse the key name */
+			for( key.s=c ; *c && (isalnum(*c)||*c=='_') ; c++ );
+			if (!*c) goto parse_error;
 			key.len = c-key.s;
 			if (key.len==0) goto parse_error;
 			/* possible spaces? */
-			for( ; isspace(*c) ; c++ );
-			/* parse the operater */
+			for( sp_found=0 ; *c && isspace(*c) ; c++,sp_found=1 );
+			if (!*c) goto parse_error;
+			/* parse the operator */
 			op.s = c;
-			if (*c=='='||*c=='<'||*c=='>')
-				c++;
-			else
-				goto parse_error;
+			switch (*c) {
+				case '<':
+				case '>':
+					if (*(c+1)=='=') c++;
+				case '=':
+					c++;
+					if (!*c) goto parse_error;
+					break;
+				default:
+					/* at least one space must be before unknown ops */
+					if(!sp_found) goto parse_error;
+					/* eat everything to first space */
+					for( ; *c && !isspace(*c) ; c++ );
+					if (!*c || c==op.s) goto parse_error; /* 0 length */
+					/* include into operator str. one space before and after*/
+					op.s--;
+					c++;
+			}
 			op.len = c - op.s;
 			/* possible spaces? */
-			for( ; isspace(*c) ; c++ );
-			/* parse value */
+			for( ; *c && isspace(*c) ; c++ );
+			if (!*c) goto parse_error;
+			/* get value */
 			val.s = c;
 			val.len = line.len - (c-line.s);
+			if (val.len==0) goto parse_error;
+			if (parse_db_value( &val, &vals[*nr], &p_val)!=0)
+				goto error;
 			/* duplicate the avp -> make all null terminated */
-			c = (char*)pkg_malloc(key.len+op.len+val.len+3);
+			c = (char*)pkg_malloc(key.len+op.len+2+(p_val?p_val->len+1:0));
 			if (c==0) {
-				LOG(L_ERR,"ERROR:get_avps: no more pkg memory\n");
+				semidouble_log("no more pkg memory");
 				goto error;
 			}
 			/*copy the key */
 			keys[*nr] = c;
 			memcpy( c, key.s, key.len);
 			c[key.len] = 0;
-			c += key.len;
+			c += key.len + 1;
 			/*copy the op */
 			ops[*nr] = c;
 			memcpy( c, op.s, op.len);
 			c[op.len] = 0;
-			c += op.len;
+			c += op.len + 1;
 			/*copy the val */
-			vals[*nr].val.string_val = c;
-			memcpy( c, val.s, val.len);
-			c[val.len] = 0;
-			c += val.len;
+			if (p_val) {
+				memcpy( c, p_val->s, p_val->len);
+				c[p_val->len] = 0;
+				p_val->s = c;
+			}
 			/* done */
 			(*nr)++;
 		} else {
@@ -142,44 +445,42 @@ int get_avps( FILE *fifo , db_key_t *keys, db_op_t *ops, db_val_t *vals,
 parse_error:
 	LOG(L_ERR,"ERROR:get_avps: parse error in \"%.*s\" at char [%d][%c] "
 		"offset %d\n",line.len,line.s,*c,*c,c-line.s);
+	double_log("Broken AVP(attr|op|val) in DB command");
 error:
 	for(;*nr;*nr--)
-		pkg_free( (void*)keys[*nr] );
+		pkg_free( (void*)keys[*nr-1] );
 	return -1;
 }
 
 
-/* returns : -1 bad key list
- *           -2 server error
- *            1 success */
-int get_keys( FILE *fifo , db_key_t *keys, int *nr, int max_nr)
+
+/* returns : -1 error
+ *            0 success */
+static inline int get_keys( FILE *fifo , db_key_t *keys, int *nr, int max_nr)
 {
 	str line;
 	char *key;
-	int ret;
 
 	*nr = 0;
-	ret = -1;
 
 	while(1) {
 		/* read a new line */
 		line.s = buf;
 		if (!read_line( line.s, MAX_SIZE_LINE, fifo, &line.len) || !line.len) {
-			LOG(L_ERR,"ERROR:get_keys: cannot read key name\n");
+			double_log("Bad key list in SELECT DB command "
+				"(missing '.' at the end?)");
 			goto error;
 		}
 		trim_spaces(line);
-		DBG("---read <%.*s>\n",line.len,line.s);
 		/* is this the separter/end char? */
 		if (line.len==1 && *line.s==END_CHR)
-			return 1;
+			return 0;
 		/* we have a new key */
 		if (*nr<max_nr) {
 			/* duplicate the key -> null terminated */
 			key = (char*)pkg_malloc(line.len+1);
 			if (key==0) {
-				LOG(L_ERR,"ERROR:get_key: no more pkg memory\n");
-				ret = -2;
+				semidouble_log("no more pkg memory");
 				goto error;
 			}
 			memcpy( key, line.s, line.len);
@@ -191,27 +492,87 @@ int get_keys( FILE *fifo , db_key_t *keys, int *nr, int max_nr)
 				"\"%.*s\"\n",max_nr,line.len,line.s);
 		}
 	}
+
 error:
 	for(;*nr;*nr--)
-		pkg_free( (void*)keys[*nr] );
-	return ret;
+		pkg_free( (void*)keys[*nr-1] );
+	return -1;
+}
+
+
+
+static inline void print_res(db_res_t* res, FILE *rpl)
+{
+	int i, j;
+
+	for(i = 0; i < RES_COL_N(res); i++) {
+		fprintf(rpl, "%s ", RES_NAMES(res)[i]);
+	}
+	fprintf(rpl,"\n");
+
+	for(i = 0; i < RES_ROW_N(res); i++) {
+		for(j = 0; j < RES_COL_N(res); j++) {
+			if (RES_ROWS(res)[i].values[j].nul) {
+				fprintf(rpl,"NULL ");
+				continue;
+			}
+			switch(RES_ROWS(res)[i].values[j].type) {
+				case DB_INT:
+					fprintf(rpl,"%d ",
+						RES_ROWS(res)[i].values[j].val.int_val);
+					break;
+				case DB_DOUBLE:
+					fprintf(rpl,"%f ",
+						RES_ROWS(res)[i].values[j].val.double_val);
+				break;
+				case DB_DATETIME:
+					fprintf(rpl,"%s ",
+						ctime(&(RES_ROWS(res)[i].values[j].val.time_val)));
+					break;
+				case DB_STRING:
+					fprintf(rpl,"%s ",
+						RES_ROWS(res)[i].values[j].val.string_val);
+					break;
+				case DB_STR:
+					fprintf(rpl,"%.*s ", 
+						RES_ROWS(res)[i].values[j].val.str_val.len,
+						RES_ROWS(res)[i].values[j].val.str_val.s);
+					break;
+				case DB_BLOB:
+					fprintf(rpl,"%.*s ",
+						RES_ROWS(res)[i].values[j].val.blob_val.len,
+						RES_ROWS(res)[i].values[j].val.blob_val.s);
+					break;
+				case DB_BITMAP:
+					fprintf(rpl,"%d ",
+						RES_ROWS(res)[i].values[j].val.bitmap_val);
+					break;
+			}
+		}
+		fprintf(rpl,"\n");
+	}
 }
 
 
 
+
 int db_fifo( FILE *fifo, char *response_file )
 {
 	static db_key_t keys1[MAX_ARRAY];
-	//static db_op_t  ops1[MAX_ARRAY];
-	//static db_val_t vals1[MAX_ARRAY];
+	static db_op_t  ops1[MAX_ARRAY];
+	static db_val_t vals1[MAX_ARRAY];
 	static db_key_t keys2[MAX_ARRAY];
 	static db_op_t  ops2[MAX_ARRAY];
 	static db_val_t vals2[MAX_ARRAY];
-	FILE *rpl = 0;
+	static db_res_t *select_res;
 	str   line;
 	int   db_cmd;
 	int   nr1, nr2;
 	int   ret;
+	int   n;
+
+	ret = -1; /* default is error */
+	rpl =  0;
 
 	/* first check the response file */
 	rpl = open_reply_pipe( response_file );
@@ -221,8 +582,7 @@ int db_fifo( FILE *fifo, char *response_file )
 	/* first name must be the real name of the DB operation */
 	line.s = buf;
 	if (!read_line( line.s, MAX_SIZE_LINE, fifo, &line.len) || line.len==0) {
-		fprintf( rpl, "DB command name expected\n");
-		LOG(L_ERR,"ERROR:db_fifo: cannot read fifo cmd name\n");
+		double_log("DB command name expected");
 		goto error;
 	}
 	trim_spaces(line);
@@ -240,57 +600,148 @@ int db_fifo( FILE *fifo, char *response_file )
 	} else if (line.len==UPDATE_STR_LEN
 	&& !strncasecmp( line.s, UPDATE_STR, line.len)) {
 		db_cmd = UPDATE_CMD;
+	} else if (line.len==RAWQUERY_STR_LEN
+	&& !strncasecmp( line.s, RAWQUERY_STR, line.len)) {
+		db_cmd = RAWQUERY_CMD;
+	} else if (line.len==RAWQUERYRES_STR_LEN
+	&& !strncasecmp( line.s, RAWQUERYRES_STR, line.len)) {
+		db_cmd = RAWQUERYRES_CMD;
 	} else {
-		fprintf( rpl, "unknown DB command \"%.*s\"\n",line.len,line.s);
-		LOG(L_ERR,"ERROR:db_fifo: unknown command \"%.*s\"\n",
-			line.len,line.s);
+		double_log("Unknown DB command name");
 		goto error;
 	}
 	DBG("DEBUG:db_fifo: cmd \"%.*s\" received\n",line.len,line.s);
 
+	nr1 = 0;
+	nr2 = 0;
+
 	if (db_cmd==SELECT_CMD) {
 		/* read the colums to be fetched */
-		ret = get_keys( fifo, keys1, &nr1, MAX_ARRAY);
-		if (ret==-1) {
-			fprintf( rpl, "Bad key list in SELECT DB command "
-				"(missing '.' at the end?)\n");
-			LOG(L_ERR,"ERROR:db_fifo: bad key list termination in SELECT cmd"
-				"(missing '.' at the end?)\n");
+		if ( get_keys( fifo, keys1, &nr1, MAX_ARRAY)!=0 )
 			goto error;
-		} else if (ret==-2) {
-			fprintf( rpl, "Internal Server error\n");
+	} else if (db_cmd==UPDATE_CMD) {
+		/* read the col=val pairs to be updated */
+		if (get_avps( fifo , keys1, ops1, vals1, &nr1, MAX_ARRAY)!=0 )
 			goto error;
-		} else if (nr1==0) {
-			fprintf( rpl, "Empty key list found in SELECT DB command\n");
-			LOG(L_ERR,"ERROR:db_fifo: no keys specified in SELECT cmd\n");
+		/* must be at least one AVP in an update command */
+		if (nr1==0) {
+			double_log("UPDATE command must have at least one"
+				" field to update");
 			goto error;
 		}
-	} else if (db_cmd==UPDATE_CMD) {
-		/* read the col=val pairs to be updated */
+		/* all the operators must be '=' */
+		for(n=0;n<nr1;n++) {
+			if (ops1[n][0]!='=' || ops1[n][1]!='\0') {
+				double_log("Invalid operator in updated fileds (expected = )");
+				goto error1;
+			}
+		}/*end for*/
+	} else if (db_cmd==RAWQUERY_CMD || db_cmd==RAWQUERYRES_CMD) {
+		/* read the raw db command  */
+		line.s = buf;
+		if (!read_line( line.s, MAX_SIZE_LINE-1,fifo,&line.len) || !line.len) {
+			double_log("Raw db command expected");
+			goto error;
+		}
+		trim_spaces(line);
+		/* run the command */
+		if (db_cmd==RAWQUERY_CMD)
+			n = db_raw_query( fifo_db_con, line.s, 0);
+		else
+			n = db_raw_query( fifo_db_con, line.s, &select_res);
+		if (n!=0) {
+			double_log("Internal Server error - DB query failed");
+			goto error;
+		}
+		/* any results? */
+		if (db_cmd==RAWQUERYRES_CMD) {
+			/* get all response and write them into reply fifo */
+			print_res( select_res, rpl);
+			/* free the query response */
+			db_free_query( fifo_db_con, select_res);
+		}
+		/* done with success */
+		goto done;
 	}
 
 	/* read the table name */
 	line.s = buf;
-	if (!read_line( line.s, MAX_SIZE_LINE, fifo, &line.len) || !line.len) {
-		fprintf( rpl, "Table name expected\n");
-		LOG(L_ERR,"ERROR:db_fifo: cannot read table name\n");
-		goto error;
+	if (!read_line( line.s, MAX_SIZE_LINE-1, fifo, &line.len) || !line.len) {
+		double_log("Table name expected");
+		goto error1;
 	}
 	trim_spaces(line);
 
-	/*read 'where' avps */
-	//if (get_avps( fifo , keys2, ops2, vals2, &nr2, MAX_ARRAY)==-1)
-	//	goto error;
-
+	/* select the correct table */
+	line.s[line.len] = 0; /* make it null terminated */
+	db_use_table( fifo_db_con, line.s);
 
-	if (db_cmd==SELECT_CMD) {
-		 
+	/*read 'where' avps */
+	if (get_avps( fifo , keys2, ops2, vals2, &nr2, MAX_ARRAY)!=0 )
+		goto error1;
+
+	switch (db_cmd) {
+		case SELECT_CMD:
+			if (line.len==1 && line.s[0]=='.')
+			/* push the query */
+			n = db_query( fifo_db_con, nr2?keys2:0, nr2?ops2:0, nr2?vals2:0,
+				nr1?keys1:0, nr2, nr1, 0, &select_res );
+			if (n!=0) {
+				double_log("Internal Server error - DB query failed");
+				goto error2;
+			}
+			/* get all response and write them into reply fifo */
+			print_res( select_res, rpl);
+			/* free the query response */
+			db_free_query( fifo_db_con, select_res);
+			break;
+		case UPDATE_CMD:
+			/* push the query */
+			n = db_update( fifo_db_con, nr2?keys2:0, nr2?ops2:0, nr2?vals2:0,
+				keys1, vals1, nr2, nr1 );
+			if (n!=0) {
+				double_log("Internal Server error - DB query failed");
+				goto error2;
+			}
+			break;
+		case DELETE_CMD:
+			/* push the query */
+			n = db_delete( fifo_db_con, nr2?keys2:0, nr2?ops2:0, nr2?vals2:0,
+				nr2);
+			if (n!=0) {
+				double_log("Internal Server error - DB query failed");
+				goto error2;
+			}
+			break;
+		case INSERT_CMD:
+			/* all the operators must be '=' */
+			for(n=0;n<nr2;n++) {
+				if (ops2[n][0]!='=' || ops2[n][1]!='\0') {
+					double_log("Invalid operatpr in inserted fileds "
+						"(expected = )");
+					goto error;
+				}
+			}/*end for*/
+			/* push the query */
+			n = db_insert( fifo_db_con, nr2?keys2:0, nr2?vals2:0, nr2);
+			if (n!=0) {
+				double_log("Internal Server error - DB query failed");
+				goto error2;
+			}
+			break;
 	}
 
-	fclose(rpl);
-	return 0;
+	/* success */
+done:
+	ret = 0;
+error2:
+	for(;nr2;nr2--)
+		pkg_free( (void*)keys2[nr2-1] );
+error1:
+	for(;nr1;nr1--)
+		pkg_free( (void*)keys1[nr1-1] );
 error:
 	if (rpl) fclose(rpl);
-	return -1;
+	return ret;
 }
 

+ 2 - 0
db/db_fifo.h

@@ -31,6 +31,8 @@
 #define db_fifo_cmd  db_fifo
 #define FIFO_DB      "DB"
 
+extern db_con_t*   fifo_db_con;
+
 int db_fifo( FILE *fifo_stream, char *response_file );
 
 

+ 5 - 1
fifo_server.c

@@ -858,7 +858,11 @@ int register_core_fifo()
 			LOG(L_ERR, "ERROR: unable to register '%s' FIFO cmd\n", FIFO_DB);
 			return -1;
 		} else {
-			/* call db_init() */
+			if ( (fifo_db_con=db_init( fifo_db_url ))==0) {
+				/* connection failed */
+			LOG(L_ERR,"ERROR: unable to connect to database -> "
+				"fifo DB commands disabled!\n");
+			}
 		}
 	} else {
 		LOG(L_WARN,"WARNING: unable to find any db module - "