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
00060 #include "../../dprint.h"
00061 #include "../../sr_module.h"
00062 #include "../../mem/mem.h"
00063 #include "../../ut.h"
00064 #include "db_cap.h"
00065 #include "db_id.h"
00066 #include "db_pool.h"
00067 #include "db_query.h"
00068 #include "db.h"
00069
00070 static unsigned int MAX_URL_LENGTH = 255;
00073 int db_check_api(db_func_t* dbf, char *mname)
00074 {
00075 if(dbf==NULL)
00076 return -1;
00077
00078
00079 if (dbf->use_table == 0) {
00080 LM_ERR("module %s does not export db_use_table function\n", mname);
00081 goto error;
00082 }
00083
00084
00085 if (dbf->init == 0) {
00086 LM_ERR("module %s does not export db_init function\n", mname);
00087 goto error;
00088 }
00089
00090
00091 if (dbf->close == 0) {
00092 LM_ERR("module %s does not export db_close function\n", mname);
00093 goto error;
00094 }
00095
00096 if (dbf->query) {
00097 dbf->cap |= DB_CAP_QUERY;
00098 }
00099
00100 if (dbf->fetch_result) {
00101 dbf->cap |= DB_CAP_FETCH;
00102 }
00103
00104 if (dbf->raw_query) {
00105 dbf->cap |= DB_CAP_RAW_QUERY;
00106 }
00107
00108
00109
00110 if ((dbf->cap & (DB_CAP_QUERY|DB_CAP_RAW_QUERY)) && (dbf->free_result==0)) {
00111 LM_ERR("module %s supports queries but does not export free_result\n",
00112 mname);
00113 goto error;
00114 }
00115
00116 if (dbf->insert) {
00117 dbf->cap |= DB_CAP_INSERT;
00118 }
00119
00120 if (dbf->delete) {
00121 dbf->cap |= DB_CAP_DELETE;
00122 }
00123
00124 if (dbf->update) {
00125 dbf->cap |= DB_CAP_UPDATE;
00126 }
00127
00128 if (dbf->replace) {
00129 dbf->cap |= DB_CAP_REPLACE;
00130 }
00131
00132 if (dbf->last_inserted_id) {
00133 dbf->cap |= DB_CAP_LAST_INSERTED_ID;
00134 }
00135
00136 if (dbf->insert_update) {
00137 dbf->cap |= DB_CAP_INSERT_UPDATE;
00138 }
00139
00140 if (dbf->insert_delayed) {
00141 dbf->cap |= DB_CAP_INSERT_DELAYED;
00142 }
00143
00144 if (dbf->affected_rows) {
00145 dbf->cap |= DB_CAP_AFFECTED_ROWS;
00146 }
00147
00148 return 0;
00149 error:
00150 return -1;
00151 }
00152
00158 int db_bind_mod(const str* mod, db_func_t* mydbf)
00159 {
00160 char *name, *tmp, *p;
00161 int len;
00162 db_func_t dbf;
00163 db_bind_api_f dbind;
00164
00165 if (!mod || !mod->s) {
00166 LM_CRIT("null database module name\n");
00167 return -1;
00168 }
00169 if (mydbf==0) {
00170 LM_CRIT("null dbf parameter\n");
00171 return -1;
00172 }
00173 if (mod->len > MAX_URL_LENGTH)
00174 {
00175 LM_ERR("SQL URL too long\n");
00176 return -1;
00177 }
00178
00179 name = pkg_malloc(mod->len + 4);
00180 if (!name) {
00181 LM_ERR("no private memory left\n");
00182 return -1;
00183 }
00184 memcpy(name, "db_", 3);
00185 memcpy(name+3, mod->s, mod->len);
00186 name[mod->len+3] = 0;
00187
00188
00189
00190
00191 memset((void*)mydbf, 0, sizeof(db_func_t));
00192
00193 p = strchr(name, ':');
00194 if (p) {
00195 len = p - name;
00196 tmp = (char*)pkg_malloc(len + 4);
00197 if (!tmp) {
00198 LM_ERR("no private memory left\n");
00199 pkg_free(name);
00200 return -1;
00201 }
00202 memcpy(tmp, name, len);
00203 tmp[len] = '\0';
00204 pkg_free(name);
00205 } else {
00206 tmp = name;
00207 }
00208
00209 dbind = (db_bind_api_f)find_mod_export(tmp, "db_bind_api", 0, 0);
00210 if(dbind != NULL)
00211 {
00212 LM_DBG("using db bind api for %s\n", tmp);
00213 if(dbind(&dbf)<0)
00214 {
00215 LM_ERR("db_bind_api returned error for module %s\n", tmp);
00216 goto error;
00217 }
00218 } else {
00219 memset(&dbf, 0, sizeof(db_func_t));
00220 LM_DBG("using export interface to bind %s\n", tmp);
00221 dbf.use_table = (db_use_table_f)find_mod_export(tmp,
00222 "db_use_table", 2, 0);
00223 dbf.init = (db_init_f)find_mod_export(tmp, "db_init", 1, 0);
00224 dbf.init2 = (db_init2_f)find_mod_export(tmp, "db_init2", 1, 0);
00225 dbf.close = (db_close_f)find_mod_export(tmp, "db_close", 2, 0);
00226 dbf.query = (db_query_f)find_mod_export(tmp, "db_query", 2, 0);
00227 dbf.fetch_result = (db_fetch_result_f)find_mod_export(tmp,
00228 "db_fetch_result", 2, 0);
00229 dbf.raw_query = (db_raw_query_f)find_mod_export(tmp,
00230 "db_raw_query", 2, 0);
00231 dbf.free_result = (db_free_result_f)find_mod_export(tmp,
00232 "db_free_result", 2, 0);
00233 dbf.insert = (db_insert_f)find_mod_export(tmp, "db_insert", 2, 0);
00234 dbf.delete = (db_delete_f)find_mod_export(tmp, "db_delete", 2, 0);
00235 dbf.update = (db_update_f)find_mod_export(tmp, "db_update", 2, 0);
00236 dbf.replace = (db_replace_f)find_mod_export(tmp, "db_replace", 2, 0);
00237 dbf.last_inserted_id= (db_last_inserted_id_f)find_mod_export(tmp,
00238 "db_last_inserted_id", 1, 0);
00239 dbf.affected_rows = (db_affected_rows_f)find_mod_export(tmp,
00240 "db_affected_rows", 1, 0);
00241 dbf.insert_update = (db_insert_update_f)find_mod_export(tmp,
00242 "db_insert_update", 2, 0);
00243 dbf.insert_delayed = (db_insert_delayed_f)find_mod_export(tmp,
00244 "db_insert_delayed", 2, 0);
00245 dbf.start_transaction = (db_start_transaction_f)find_mod_export(tmp,
00246 "db_start_transaction", 1, 0);
00247 dbf.end_transaction = (db_end_transaction_f)find_mod_export(tmp,
00248 "db_end_transaction", 1, 0);
00249 dbf.abort_transaction = (db_abort_transaction_f)find_mod_export(tmp,
00250 "db_abort_transaction", 1, 0);
00251 }
00252 if(db_check_api(&dbf, tmp)!=0)
00253 goto error;
00254
00255 *mydbf=dbf;
00256 pkg_free(tmp);
00257 return 0;
00258
00259 error:
00260 pkg_free(tmp);
00261 return -1;
00262 }
00263
00264
00269 db1_con_t* db_do_init(const str* url, void* (*new_connection)())
00270 {
00271 return db_do_init2(url, *new_connection, DB_POOLING_PERMITTED);
00272 }
00273
00274
00279 db1_con_t* db_do_init2(const str* url, void* (*new_connection)(), db_pooling_t pooling)
00280 {
00281 struct db_id* id;
00282 void* con;
00283 db1_con_t* res;
00284
00285 int con_size = sizeof(db1_con_t) + sizeof(void *);
00286 id = 0;
00287 res = 0;
00288
00289 if (!url || !url->s || !new_connection) {
00290 LM_ERR("invalid parameter value\n");
00291 return 0;
00292 }
00293 if (url->len > MAX_URL_LENGTH)
00294 {
00295 LM_ERR("The configured db_url is too long\n");
00296 return 0;
00297 }
00298
00299
00300 res = (db1_con_t*)pkg_malloc(con_size);
00301 if (!res) {
00302 LM_ERR("no private memory left\n");
00303 return 0;
00304 }
00305 memset(res, 0, con_size);
00306
00307 id = new_db_id(url, pooling);
00308 if (!id) {
00309 LM_ERR("cannot parse URL '%.*s'\n", url->len, url->s);
00310 goto err;
00311 }
00312
00313
00314 con = pool_get(id);
00315 if (!con) {
00316 LM_DBG("connection %p not found in pool\n", id);
00317
00318 con = new_connection(id);
00319 if (!con) {
00320 LM_ERR("could not add connection to the pool");
00321 goto err;
00322 }
00323 pool_insert((struct pool_con*)con);
00324 } else {
00325 LM_DBG("connection %p found in pool\n", id);
00326 }
00327
00328 res->tail = (unsigned long)con;
00329 return res;
00330
00331 err:
00332 if (id) free_db_id(id);
00333 if (res) pkg_free(res);
00334 return 0;
00335 }
00336
00337
00342 void db_do_close(db1_con_t* _h, void (*free_connection)())
00343 {
00344 struct pool_con* con;
00345
00346 if (!_h || !_h->tail) {
00347 LM_ERR("invalid parameter value\n");
00348 return;
00349 }
00350
00351 con = (struct pool_con*)_h->tail;
00352 if (pool_remove(con) == 1) {
00353 free_connection(con);
00354 }
00355
00356 pkg_free(_h);
00357 }
00358
00359
00360
00368 int db_table_version(const db_func_t* dbf, db1_con_t* connection, const str* table)
00369 {
00370 db_key_t key[1], col[1];
00371 db_val_t val[1];
00372 db1_res_t* res = NULL;
00373 db_val_t* ver = 0;
00374 str version = str_init(VERSION_TABLE);
00375 str tmp1 = str_init(TABLENAME_COLUMN);
00376 str tmp2 = str_init(VERSION_COLUMN);
00377 int ret;
00378
00379 if (!dbf||!connection || !table || !table->s) {
00380 LM_CRIT("invalid parameter value\n");
00381 return -1;
00382 }
00383
00384 if (dbf->use_table(connection, &version) < 0) {
00385 LM_ERR("error while changing table\n");
00386 return -1;
00387 }
00388 key[0] = &tmp1;
00389
00390 VAL_TYPE(val) = DB1_STR;
00391 VAL_NULL(val) = 0;
00392 VAL_STR(val) = *table;
00393
00394 col[0] = &tmp2;
00395
00396 if (dbf->query(connection, key, 0, val, col, 1, 1, 0, &res) < 0) {
00397 LM_ERR("error in db_query\n");
00398 return -1;
00399 }
00400
00401 if (RES_ROW_N(res) == 0) {
00402 LM_DBG("no row for table %.*s found\n",
00403 table->len, ZSW(table->s));
00404 return 0;
00405 }
00406
00407 if (RES_ROW_N(res) != 1) {
00408 LM_ERR("invalid number of rows received:"
00409 " %d, %.*s\n", RES_ROW_N(res), table->len, ZSW(table->s));
00410 dbf->free_result(connection, res);
00411 return -1;
00412 }
00413
00414 ver = ROW_VALUES(RES_ROWS(res));
00415 if ( VAL_TYPE(ver)!=DB1_INT || VAL_NULL(ver) ) {
00416 LM_ERR("invalid type (%d) or nul (%d) version "
00417 "columns for %.*s\n", VAL_TYPE(ver), VAL_NULL(ver),
00418 table->len, ZSW(table->s));
00419 dbf->free_result(connection, res);
00420 return -1;
00421 }
00422
00423 ret = VAL_INT(ver);
00424 dbf->free_result(connection, res);
00425 return ret;
00426 }
00427
00432 int db_check_table_version(db_func_t* dbf, db1_con_t* dbh, const str* table, const unsigned int version)
00433 {
00434 int ver = db_table_version(dbf, dbh, table);
00435 if (ver < 0) {
00436 LM_ERR("querying version for table %.*s\n", table->len, table->s);
00437 return -1;
00438 } else if (ver != version) {
00439 LM_ERR("invalid version %d for table %.*s found, expected %d (check table structure and table \"version\")\n", ver, table->len, table->s, version);
00440 return -1;
00441 }
00442 return 0;
00443 }
00444
00449 int db_use_table(db1_con_t* _h, const str* _t)
00450 {
00451 if (!_h || !_t || !_t->s) {
00452 LM_ERR("invalid parameter value\n");
00453 return -1;
00454 }
00455
00456 CON_TABLE(_h) = _t;
00457 return 0;
00458 }
00459
00460
00474 int db_load_bulk_data(db_func_t* binding, db1_con_t* handle, str* name, db_key_t* cols,
00475 unsigned int count, unsigned int strict, db1_res_t* res)
00476 {
00477 if (binding == NULL) {
00478 LM_ERR("invalid database module binding\n");
00479 return -1;
00480 }
00481
00482 if(handle == NULL) {
00483 LM_ERR("invalid database handle\n");
00484 return -1;
00485 }
00486
00487 if (binding->use_table(handle, name) < 0) {
00488 LM_ERR("error in use_table for database\n");
00489 return -1;
00490 }
00491
00492
00493 if(binding->query(handle, 0, 0, 0, cols, 0, count, 0, &res) < 0) {
00494 LM_ERR("error while querying database\n");
00495 return -1;
00496 }
00497
00498 if(RES_ROW_N(res) == 0) {
00499 binding->free_result(handle, res);
00500 if (strict == 1) {
00501 LM_ERR("no data in the database table %.*s\n", name->len, name->s);
00502 return -1;
00503 } else {
00504 LM_WARN("no data in the database table %.*s, use an empty set\n", name->len, name->s);
00505 return 0;
00506 }
00507 }
00508
00509 return 0;
00510 }
00511
00519 int db_api_init(void)
00520 {
00521 if(db_query_init()<0)
00522 return -1;
00523 return 0;
00524 }