|
@@ -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;
|
|
|
}
|
|
|
|