00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <stdlib.h>
00030 #include <string.h>
00031
00032 #include "../../mem/mem.h"
00033 #include "../../mem/shm_mem.h"
00034 #include "../../db/db.h"
00035 #include "../../dprint.h"
00036 #include "avpops_parse.h"
00037 #include "avpops_db.h"
00038
00039
00040 static db_con_t *db_hdl=0;
00041 static db_func_t avpops_dbf;
00042 static str def_table;
00043 static str **db_columns;
00044
00045 static db_key_t keys_cmp[3];
00046 static db_val_t vals_cmp[3];
00047
00048
00049 static struct db_scheme *db_scheme_list=0;
00050
00051
00052 int avpops_db_bind(const str* db_url)
00053 {
00054 if (db_bind_mod(db_url, &avpops_dbf ))
00055 {
00056 LM_CRIT("cannot bind to database module! "
00057 "Did you load a database module ?\n");
00058 return -1;
00059 }
00060
00061 if (!DB_CAPABILITY(avpops_dbf, DB_CAP_ALL))
00062 {
00063 LM_CRIT("database modules does not "
00064 "provide all functions needed by avpops module\n");
00065 return -1;
00066 }
00067
00068 return 0;
00069
00070 }
00071
00072
00073 int avpops_db_init(const str* db_url, const str* db_table, str** db_cols)
00074 {
00075
00076 db_hdl = avpops_dbf.init(db_url);
00077 if (db_hdl==0)
00078 {
00079 LM_ERR("cannot initialize database connection\n");
00080 goto error;
00081 }
00082 if (avpops_dbf.use_table(db_hdl, db_table)<0)
00083 {
00084 LM_ERR("cannot select table \"%.*s\"\n", db_table->len, db_table->s);
00085 goto error;
00086 }
00087 def_table.s = db_table->s;
00088 def_table.len = db_table->len;
00089 db_columns = db_cols;
00090
00091 return 0;
00092 error:
00093 if (db_hdl)
00094 {
00095 avpops_dbf.close(db_hdl);
00096 db_hdl=0;
00097 }
00098 return -1;
00099 }
00100
00101
00102 int avp_add_db_scheme( modparam_t type, void* val)
00103 {
00104 struct db_scheme *scheme;
00105
00106 scheme = (struct db_scheme*)pkg_malloc( sizeof(struct db_scheme) );
00107 if (scheme==0)
00108 {
00109 LM_ERR("no more pkg memory\n");
00110 goto error;
00111 }
00112 memset( scheme, 0, sizeof(struct db_scheme));
00113
00114
00115 if ( parse_avp_db_scheme( (char*)val, scheme)!=0 )
00116 {
00117 LM_ERR("failed to parse scheme\n");
00118 goto error;
00119 }
00120
00121
00122 if ( avp_get_db_scheme(&scheme->name)!=0 )
00123 {
00124 LM_ERR("duplicated scheme name <%.*s>\n",
00125 scheme->name.len,scheme->name.s);
00126 goto error;
00127 }
00128
00129
00130 LM_DBG("new scheme <%.*s> added\n"
00131 "\t\tuuid_col=<%.*s>\n\t\tusername_col=<%.*s>\n"
00132 "\t\tdomain_col=<%.*s>\n\t\tvalue_col=<%.*s>\n"
00133 "\t\tdb_flags=%d\n\t\ttable=<%.*s>\n",
00134 scheme->name.len,scheme->name.s,
00135 scheme->uuid_col.len, scheme->uuid_col.s, scheme->username_col.len,
00136 scheme->username_col.s, scheme->domain_col.len, scheme->domain_col.s,
00137 scheme->value_col.len, scheme->value_col.s, scheme->db_flags,
00138 scheme->table.len, scheme->table.s);
00139
00140 scheme->next = db_scheme_list;
00141 db_scheme_list = scheme;
00142
00143 return 0;
00144 error:
00145 return -1;
00146 }
00147
00148
00149 struct db_scheme *avp_get_db_scheme (str *name)
00150 {
00151 struct db_scheme *scheme;
00152
00153 for( scheme=db_scheme_list ; scheme ; scheme=scheme->next )
00154 if ( name->len==scheme->name.len &&
00155 !strcasecmp( name->s, scheme->name.s) )
00156 return scheme;
00157 return 0;
00158 }
00159
00160
00161 static inline int set_table( const str *table, char *func)
00162 {
00163 if (table && table->s)
00164 {
00165 if ( avpops_dbf.use_table( db_hdl, table)<0 )
00166 {
00167 LM_ERR("db-%s: cannot set table \"%.*s\"\n", func, table->len, table->s);
00168 return -1;
00169 }
00170 } else {
00171 if ( avpops_dbf.use_table( db_hdl, &def_table)<0 )
00172 {
00173 LM_ERR("db-%s: cannot set table \"%.*s\"\n", func, def_table.len, def_table.s);
00174 return -1;
00175 }
00176 }
00177 return 0;
00178 }
00179
00180
00181
00182 static inline int prepare_selection( str *uuid, str *username, str *domain,
00183 char *attr, struct db_scheme *scheme)
00184 {
00185 unsigned int nr_keys_cmp;
00186
00187 nr_keys_cmp = 0;
00188 if (uuid)
00189 {
00190
00191 keys_cmp[ nr_keys_cmp ] =
00192 (scheme&&scheme->uuid_col.s)?&scheme->uuid_col:db_columns[0];
00193 vals_cmp[ nr_keys_cmp ].type = DB_STR;
00194 vals_cmp[ nr_keys_cmp ].nul = 0;
00195 vals_cmp[ nr_keys_cmp ].val.str_val = *uuid;
00196 nr_keys_cmp++;
00197 } else {
00198 if (username)
00199 {
00200
00201 keys_cmp[ nr_keys_cmp ] =
00202 (scheme&&scheme->username_col.s)?&scheme->username_col:db_columns[4];
00203 vals_cmp[ nr_keys_cmp ].type = DB_STR;
00204 vals_cmp[ nr_keys_cmp ].nul = 0;
00205 vals_cmp[ nr_keys_cmp ].val.str_val = *username;
00206 nr_keys_cmp++;
00207 }
00208 if (domain)
00209 {
00210
00211 keys_cmp[ nr_keys_cmp ] =
00212 (scheme&&scheme->domain_col.s)?&scheme->domain_col:db_columns[5];
00213 vals_cmp[ nr_keys_cmp ].type = DB_STR;
00214 vals_cmp[ nr_keys_cmp ].nul = 0;
00215 vals_cmp[ nr_keys_cmp ].val.str_val = *domain;
00216 nr_keys_cmp++;
00217 }
00218 }
00219 if (attr && scheme==0)
00220 {
00221
00222 keys_cmp[ nr_keys_cmp ] = db_columns[1];
00223 vals_cmp[ nr_keys_cmp ].type = DB_STRING;
00224 vals_cmp[ nr_keys_cmp ].nul = 0;
00225 vals_cmp[ nr_keys_cmp ].val.string_val = attr;
00226 nr_keys_cmp++;
00227 }
00228 return nr_keys_cmp;
00229 }
00230
00231
00232 db_res_t *db_load_avp( str *uuid, str *username, str *domain,
00233 char *attr, const str *table, struct db_scheme *scheme)
00234 {
00235 static db_key_t keys_ret[3];
00236 unsigned int nr_keys_cmp;
00237 unsigned int nr_keys_ret;
00238 db_res_t *res = NULL;
00239
00240
00241 nr_keys_cmp = prepare_selection( uuid, username, domain, attr, scheme);
00242
00243
00244 if (set_table( scheme?&scheme->table:table ,"load")!=0)
00245 return 0;
00246
00247
00248 if (scheme==0)
00249 {
00250 keys_ret[0] = db_columns[2];
00251 keys_ret[1] = db_columns[1];
00252 keys_ret[2] = db_columns[3];
00253 nr_keys_ret = 3;
00254 } else {
00255
00256 keys_ret[0] = scheme->value_col.s?&scheme->value_col:db_columns[2];
00257 nr_keys_ret = 1;
00258 }
00259
00260
00261 if ( avpops_dbf.query( db_hdl, keys_cmp, 0, vals_cmp, keys_ret,
00262 nr_keys_cmp, nr_keys_ret, 0, &res) < 0)
00263 return 0;
00264
00265 return res;
00266 }
00267
00268
00269 void db_close_query( db_res_t *res )
00270 {
00271 LM_DBG("close avp query\n");
00272 avpops_dbf.free_result( db_hdl, res);
00273 }
00274
00275
00276 int db_store_avp( db_key_t *keys, db_val_t *vals, int n, const str *table)
00277 {
00278 int r;
00279 if (set_table( table ,"store")!=0)
00280 return -1;
00281
00282 r = avpops_dbf.insert( db_hdl, keys, vals, n);
00283 if (r<0)
00284 {
00285 LM_ERR("insert failed\n");
00286 return -1;
00287 }
00288 return 0;
00289 }
00290
00291
00292
00293 int db_delete_avp( str *uuid, str *username, str *domain, char *attr,
00294 const str *table)
00295 {
00296 unsigned int nr_keys_cmp;
00297
00298
00299 nr_keys_cmp = prepare_selection( uuid, username, domain, attr, 0);
00300
00301
00302 if (set_table( table ,"delete")!=0)
00303 return -1;
00304
00305
00306 if ( avpops_dbf.delete( db_hdl, keys_cmp, 0, vals_cmp, nr_keys_cmp) < 0)
00307 return 0;
00308
00309 return 0;
00310 }
00311
00312 int db_query_avp(struct sip_msg *msg, char *query, pvname_list_t* dest)
00313 {
00314 int_str avp_val;
00315 int_str avp_name;
00316 unsigned short avp_type;
00317 db_res_t* db_res = NULL;
00318 int i, j;
00319 pvname_list_t* crt;
00320 static str query_str;
00321
00322 if(query==NULL)
00323 {
00324 LM_ERR("bad parameter\n");
00325 return -1;
00326 }
00327
00328 query_str.s = query;
00329 query_str.len = strlen(query);
00330
00331 if(avpops_dbf.raw_query(db_hdl, &query_str, &db_res)!=0)
00332 {
00333 LM_ERR("cannot do the query\n");
00334 return -1;
00335 }
00336
00337 if(db_res==NULL || RES_ROW_N(db_res)<=0 || RES_COL_N(db_res)<=0)
00338 {
00339 LM_DBG("no result after query\n");
00340 db_close_query( db_res );
00341 return -2;
00342 }
00343
00344 LM_DBG("rows [%d]\n", RES_ROW_N(db_res));
00345
00346 for(i = RES_ROW_N(db_res)-1; i >= 0; i--)
00347 {
00348 LM_DBG("row [%d]\n", i);
00349 crt = dest;
00350 for(j = 0; j < RES_COL_N(db_res); j++)
00351 {
00352 if(RES_ROWS(db_res)[i].values[j].nul)
00353 goto next_avp;
00354 avp_type = 0;
00355 if(crt==NULL)
00356 {
00357 avp_name.n = j+1;
00358 } else {
00359 if(pv_get_avp_name(msg, &crt->sname.pvp, &avp_name,
00360 &avp_type)!=0)
00361 {
00362 LM_ERR("cant get avp name [%d/%d]\n", i, j);
00363 goto next_avp;
00364 }
00365 }
00366 switch(RES_ROWS(db_res)[i].values[j].type)
00367 {
00368 case DB_STRING:
00369 avp_type |= AVP_VAL_STR;
00370 avp_val.s.s=
00371 (char*)RES_ROWS(db_res)[i].values[j].val.string_val;
00372 avp_val.s.len=strlen(avp_val.s.s);
00373 if(avp_val.s.len<=0)
00374 goto next_avp;
00375 break;
00376 case DB_STR:
00377 avp_type |= AVP_VAL_STR;
00378 avp_val.s.len=
00379 RES_ROWS(db_res)[i].values[j].val.str_val.len;
00380 avp_val.s.s=
00381 (char*)RES_ROWS(db_res)[i].values[j].val.str_val.s;
00382 if(avp_val.s.len<=0)
00383 goto next_avp;
00384 break;
00385 case DB_BLOB:
00386 avp_type |= AVP_VAL_STR;
00387 avp_val.s.len=
00388 RES_ROWS(db_res)[i].values[j].val.blob_val.len;
00389 avp_val.s.s=
00390 (char*)RES_ROWS(db_res)[i].values[j].val.blob_val.s;
00391 if(avp_val.s.len<=0)
00392 goto next_avp;
00393 break;
00394 case DB_INT:
00395 avp_val.n
00396 = (int)RES_ROWS(db_res)[i].values[j].val.int_val;
00397 break;
00398 case DB_DATETIME:
00399 avp_val.n
00400 = (int)RES_ROWS(db_res)[i].values[j].val.time_val;
00401 break;
00402 case DB_BITMAP:
00403 avp_val.n
00404 = (int)RES_ROWS(db_res)[i].values[j].val.bitmap_val;
00405 break;
00406 default:
00407 goto next_avp;
00408 }
00409 if(add_avp(avp_type, avp_name, avp_val)!=0)
00410 {
00411 LM_ERR("unable to add avp\n");
00412 db_close_query( db_res );
00413 return -1;
00414 }
00415 next_avp:
00416 if(crt)
00417 {
00418 crt = crt->next;
00419 if(crt==NULL)
00420 break;
00421 }
00422 }
00423 }
00424
00425 db_close_query( db_res );
00426 return 0;
00427 }