diff --git a/src/modules/db_text/db_text.c b/src/modules/db_text/db_text.c index 7ce455249b4..7dc2cbbcb14 100644 --- a/src/modules/db_text/db_text.c +++ b/src/modules/db_text/db_text.c @@ -38,6 +38,7 @@ static int mod_init(void); static void destroy(void); #define DEFAULT_DB_TEXT_READ_BUFFER_SIZE 16384 +#define DEFAULT_MAX_RESULT_ROWS 100000; /* * Module parameter variables @@ -45,6 +46,7 @@ static void destroy(void); int db_mode = 0; /* Database usage mode: 0 = cache, 1 = no cache */ int empty_string = 0; /* Treat empty string as "" = 0, 1 = NULL */ int _db_text_read_buffer_size = DEFAULT_DB_TEXT_READ_BUFFER_SIZE; +int _db_text_max_result_rows = DEFAULT_MAX_RESULT_ROWS; int dbt_bind_api(db_func_t *dbb); @@ -64,6 +66,7 @@ static param_export_t params[] = { {"db_mode", INT_PARAM, &db_mode}, {"emptystring", INT_PARAM, &empty_string}, {"file_buffer_size", INT_PARAM, &_db_text_read_buffer_size}, + {"max_result_rows", INT_PARAM, &_db_text_max_result_rows}, {0, 0, 0} }; @@ -108,7 +111,7 @@ static int mod_init(void) static void destroy(void) { LM_DBG("destroy ...\n"); - dbt_cache_print(0); + dbt_cache_print2(0, 0); dbt_cache_destroy(); } @@ -125,6 +128,7 @@ int dbt_bind_api(db_func_t *dbb) dbb->init = dbt_init; dbb->close = dbt_close; dbb->query = (db_query_f)dbt_query; + dbb->fetch_result = (db_fetch_result_f) dbt_fetch_result; dbb->free_result = dbt_free_result; dbb->insert = (db_insert_f)dbt_insert; dbb->delete = (db_delete_f)dbt_delete; @@ -132,8 +136,7 @@ int dbt_bind_api(db_func_t *dbb) dbb->replace = (db_replace_f)dbt_replace; dbb->affected_rows = (db_affected_rows_f) dbt_affected_rows; dbb->raw_query = (db_raw_query_f) dbt_raw_query; - dbb->cap = DB_CAP_ALL | DB_CAP_AFFECTED_ROWS | DB_CAP_RAW_QUERY - | DB_CAP_REPLACE; + dbb->cap = DB_CAP_ALL | DB_CAP_AFFECTED_ROWS | DB_CAP_RAW_QUERY | DB_CAP_REPLACE | DB_CAP_FETCH; return 0; } diff --git a/src/modules/db_text/db_text.h b/src/modules/db_text/db_text.h index d328d1f62ed..dd5abbe6b89 100644 --- a/src/modules/db_text/db_text.h +++ b/src/modules/db_text/db_text.h @@ -56,6 +56,10 @@ int dbt_free_result(db1_con_t* _h, db1_res_t* _r); int dbt_query(db1_con_t* _h, db_key_t* _k, db_op_t* _op, db_val_t* _v, db_key_t* _c, int _n, int _nc, db_key_t _o, db1_res_t** _r); +/* + * fetch result + */ +int dbt_fetch_result(db1_con_t* _h, db1_res_t** _r, const int nrows); /* * Raw SQL query diff --git a/src/modules/db_text/dbt_api.c b/src/modules/db_text/dbt_api.c index 4beb86b4e36..d0e15b82837 100644 --- a/src/modules/db_text/dbt_api.c +++ b/src/modules/db_text/dbt_api.c @@ -39,7 +39,7 @@ int dbt_use_table(db1_con_t* _h, const str* _t) /* * Get and convert columns from a result */ -static int dbt_get_columns(db1_res_t* _r, dbt_result_p _dres) +static int dbt_get_columns(db1_res_t* _r, dbt_table_p _dres) { int col; @@ -73,10 +73,10 @@ static int dbt_get_columns(db1_res_t* _r, dbt_result_p _dres) LM_DBG("allocate %d bytes for RES_NAMES[%d] at %p\n", (int)sizeof(str), col, RES_NAMES(_r)[col]); - RES_NAMES(_r)[col]->s = _dres->colv[col].name.s; - RES_NAMES(_r)[col]->len = _dres->colv[col].name.len; + RES_NAMES(_r)[col]->s = _dres->colv[col]->name.s; + RES_NAMES(_r)[col]->len = _dres->colv[col]->name.len; - switch(_dres->colv[col].type) + switch(_dres->colv[col]->type) { case DB1_STR: case DB1_STRING: @@ -84,12 +84,12 @@ static int dbt_get_columns(db1_res_t* _r, dbt_result_p _dres) case DB1_INT: case DB1_DATETIME: case DB1_DOUBLE: - RES_TYPES(_r)[col] = _dres->colv[col].type; + RES_TYPES(_r)[col] = _dres->colv[col]->type; break; default: LM_WARN("unhandled data type column (%.*s) type id (%d), " "use STR as default\n", RES_NAMES(_r)[col]->len, - RES_NAMES(_r)[col]->s, _dres->colv[col].type); + RES_NAMES(_r)[col]->s, _dres->colv[col]->type); RES_TYPES(_r)[col] = DB1_STR; break; } @@ -173,7 +173,7 @@ static int dbt_convert_row(db1_res_t* _res, db_row_t* _r, dbt_row_p _r1) break; default: - LM_ERR("val type [%d] not supported\n", RES_TYPES(_res)[i]); + LM_ERR("val type [%d] for column %i not supported\n", RES_TYPES(_res)[i], i); return -1; } } @@ -184,25 +184,31 @@ static int dbt_convert_row(db1_res_t* _res, db_row_t* _r, dbt_row_p _r1) /* * Convert rows from internal to db API representation */ -static int dbt_convert_rows(db1_res_t* _r, dbt_result_p _dres) +static int dbt_convert_rows(db1_res_t* _r, dbt_table_p _dres, int offset, int nrows) { - int row; + int row = 0, c = 0; dbt_row_p _rp = NULL; if (!_r || !_dres) { LM_ERR("invalid parameter\n"); return -1; } - RES_ROW_N(_r) = _dres->nrrows; - if (!RES_ROW_N(_r)) { + + if (nrows == 0) { return 0; } + if (db_allocate_rows(_r) < 0) { LM_ERR("could not allocate rows\n"); return -2; } - row = 0; + _rp = _dres->rows; - while(_rp) { + while(_rp && c < offset) { + c++; + _rp = _rp->next; + } + + while(_rp && row < nrows) { if (dbt_convert_row(_r, &(RES_ROWS(_r)[row]), _rp) < 0) { LM_ERR("failed to convert row #%d\n", row); RES_ROW_N(_r) = row; @@ -212,36 +218,76 @@ static int dbt_convert_rows(db1_res_t* _r, dbt_result_p _dres) row++; _rp = _rp->next; } + RES_ROW_N(_r) = row; + RES_LAST_ROW(_r) = c + row; return 0; } +static int dbt_convert_all_rows(db1_res_t* _r, dbt_table_p _dres) +{ + if (!_r || !_dres) { + LM_ERR("invalid parameter\n"); + return -1; + } + RES_ROW_N(_r) = _dres->nrrows; + return dbt_convert_rows(_r, _dres, 0, _dres->nrrows); +} + + /* * Fill the structure with data from database */ -static int dbt_convert_result(db1_res_t* _r, dbt_result_p _dres) +//static int dbt_convert_result(db1_res_t* _r, dbt_table_p _dres) +//{ +// if (!_r || !_dres) { +// LM_ERR("invalid parameter\n"); +// return -1; +// } +// if (dbt_get_columns(_r, _dres) < 0) { +// LM_ERR("failed to get column names\n"); +// return -2; +// } +// +// if (dbt_convert_all_rows(_r, _dres) < 0) { +// LM_ERR("failed to convert rows\n"); +// db_free_columns(_r); +// return -3; +// } +// return 0; +//} + +/* + * Retrieve result set + */ +int dbt_get_result(db1_res_t** _r, dbt_table_p _dres) { - if (!_r || !_dres) { - LM_ERR("invalid parameter\n"); - return -1; + int res = dbt_init_result(_r, _dres); + if ( res != 0) { + return res; } - if (dbt_get_columns(_r, _dres) < 0) { - LM_ERR("failed to get column names\n"); - return -2; + + if (dbt_convert_all_rows(*_r, _dres) < 0) { + LM_ERR("failed to convert rows\n"); + db_free_columns(*_r); + return -3; } - if (dbt_convert_rows(_r, _dres) < 0) { + return 0; +} + +int dbt_get_next_result(db1_res_t** _r, int offset, int rows) +{ + dbt_table_p _dres = (dbt_table_p)(*_r)->ptr; + if (dbt_convert_rows(*_r, _dres, offset, rows) < 0) { LM_ERR("failed to convert rows\n"); - db_free_columns(_r); + db_free_columns(*_r); return -3; } return 0; } -/* - * Retrieve result set - */ -int dbt_get_result(db1_res_t** _r, dbt_result_p _dres) +int dbt_init_result(db1_res_t** _r, dbt_table_p _dres) { if ( !_r) { LM_ERR("invalid parameter value\n"); @@ -262,13 +308,12 @@ int dbt_get_result(db1_res_t** _r, dbt_result_p _dres) return -2; } - if (dbt_convert_result(*_r, _dres) < 0) - { - LM_ERR("failed to convert result\n"); - pkg_free(*_r); - return -4; + if (dbt_get_columns(*_r, _dres) < 0) { + LM_ERR("failed to get column names\n"); + return -2; } + RES_NUM_ROWS(*_r) = _dres->nrrows; (*_r)->ptr = _dres; return 0; } diff --git a/src/modules/db_text/dbt_api.h b/src/modules/db_text/dbt_api.h index 5f7f520b67a..ee3622f8d19 100644 --- a/src/modules/db_text/dbt_api.h +++ b/src/modules/db_text/dbt_api.h @@ -34,7 +34,11 @@ /* * Retrieve result set */ -int dbt_get_result(db1_res_t** _r, dbt_result_p _dres); +//int dbt_get_result(db1_res_t** _r, dbt_result_p _dres); +int dbt_get_result(db1_res_t** _r, dbt_table_p _dres); +int dbt_init_result(db1_res_t** _r, dbt_table_p _dres); +int dbt_get_next_result(db1_res_t** _r, int offset, int rows); + int dbt_use_table(db1_con_t* _h, const str* _t); diff --git a/src/modules/db_text/dbt_base.c b/src/modules/db_text/dbt_base.c index abbc3fd3126..425d351f15f 100644 --- a/src/modules/db_text/dbt_base.c +++ b/src/modules/db_text/dbt_base.c @@ -131,7 +131,7 @@ int dbt_free_result(db1_con_t* _h, db1_res_t* _r) if (!_r) return 0; - if(dbt_result_free((dbt_result_p)_r->ptr) < 0) + if(dbt_result_free(_h, (dbt_table_p)_r->ptr) < 0) { LM_ERR("unable to free internal structure\n"); } @@ -145,6 +145,7 @@ int dbt_free_result(db1_con_t* _h, db1_res_t* _r) return 0; } +static dbt_table_p last_temp_table = NULL; /* * Query table for specified rows @@ -162,9 +163,13 @@ int dbt_query(db1_con_t* _h, db_key_t* _k, db_op_t* _op, db_val_t* _v, db_key_t* _c, int _n, int _nc, db_key_t _o, db1_res_t** _r) { dbt_table_p _tbc = NULL; + dbt_table_p _tbc_temp = NULL; dbt_row_p _drp = NULL; - dbt_result_p _dres = NULL; + dbt_row_p *_res = NULL; +// dbt_result_p _dres = NULL; int result = 0; + int counter = 0; + int i=0; int *lkey=NULL, *lres=NULL; @@ -172,15 +177,16 @@ int dbt_query(db1_con_t* _h, db_key_t* _k, db_op_t* _op, db_val_t* _v, char *_o_op=NULL; /* operators for oder-by */ int _o_n; /* no of elements in order-by */ int *_o_l=NULL; /* column selection for order-by */ - int _o_nc; /* no of elements in _o_l but not lres */ +// int _o_nc; /* no of elements in _o_l but not lres */ - if ((!_h) || (!_r) || !CON_TABLE(_h)) + if(_r) + *_r = NULL; + + if ((!_h) || !CON_TABLE(_h)) { LM_ERR("invalid parameters\n"); return -1; } - *_r = NULL; - if (_o) { @@ -188,11 +194,19 @@ int dbt_query(db1_con_t* _h, db_key_t* _k, db_op_t* _op, db_val_t* _v, return -1; } + _tbc_temp = dbt_db_get_temp_table(DBT_CON_CONNECTION(_h)); + if(!_tbc_temp) + { + LM_ERR("unable to allocate temp table\n"); + return -1; + } + /* lock database */ _tbc = dbt_db_get_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h)); if(!_tbc) { LM_ERR("table %.*s does not exist!\n", CON_TABLE(_h)->len, CON_TABLE(_h)->s); + dbt_db_del_table(DBT_CON_CONNECTION(_h), &_tbc_temp->name, 0); return -1; } @@ -220,72 +234,117 @@ int dbt_query(db1_con_t* _h, db_key_t* _k, db_op_t* _op, db_val_t* _v, if (!_o_l) goto error; /* enlarge select-columns lres by all order-by columns, _o_nc is how many */ - if (dbt_mangle_columnselection(&lres, &_nc, &_o_nc, _o_l, _o_n) < 0) - goto error; +// if (dbt_mangle_columnselection(&lres, &_nc, &_o_nc, _o_l, _o_n) < 0) +// goto error; } +/* LM_DBG("new res with %d cols\n", _nc); _dres = dbt_result_new(_tbc, lres, _nc); if(!_dres) goto error; +*/ + + dbt_column_p pPrevCol = NULL; + _tbc_temp->colv = (dbt_column_p*) shm_malloc(_nc*sizeof(dbt_column_p)); + for(i=0; i < _nc; i++) { + dbt_column_p pCol = dbt_column_new(_tbc->colv[ lres[i] ]->name.s, _tbc->colv[ lres[i] ]->name.len); + pCol->type = _tbc->colv[ lres[i] ]->type; + pCol->flag = _tbc->colv[ lres[i] ]->flag; + if(pPrevCol) + { + pCol->prev = pPrevCol; + pPrevCol->next = pCol; + } + else + _tbc_temp->cols = pCol; + + _tbc_temp->colv[i] = pCol; + pPrevCol = pCol; + _tbc_temp->nrcols++; + } + + _res = (dbt_row_p*) pkg_malloc(_db_text_max_result_rows * sizeof(dbt_row_p)); + if(!_res) { + LM_ERR("no more space to allocate for query rows\n"); + goto error; + } + _drp = _tbc->rows; - while(_drp) + while(_drp && counter < _db_text_max_result_rows) { if(dbt_row_match(_tbc, _drp, lkey, _op, _v, _n)) { - if(dbt_result_extract_fields(_tbc, _drp, lres, _dres)) - { - LM_ERR("failed to extract result fields!\n"); - goto clean; - } + _res[counter] = _drp; +// if(dbt_result_extract_fields(_tbc, _drp, lres, _dres)) +// { +// LM_ERR("failed to extract result fields!\n"); +// goto clean; +// } + counter++; } _drp = _drp->next; } - dbt_table_update_flags(_tbc, DBT_TBFL_ZERO, DBT_FL_IGN, 1); - - /* unlock database */ - dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h)); - if (_o_l) { - if (_dres->nrrows > 1) + if (counter > 1) { - if (dbt_sort_result(_dres, _o_l, _o_op, _o_n, lres, _nc) < 0) - goto error_nounlock; + if (dbt_sort_result_temp(_res, counter, _o_l, _o_op, _o_n) < 0) + goto error; } /* last but not least, remove surplus columns */ - if (_o_nc) - dbt_project_result(_dres, _o_nc); +// if (_o_nc) +// dbt_project_result(_dres, _o_nc); } + // copy results to temp table + _tbc_temp->rows = dbt_result_extract_results(_tbc, _res, counter, lres, _nc); + _tbc_temp->nrrows = (_tbc_temp->rows == NULL ? 0 : counter); - /* dbt_result_print(_dres); */ + dbt_table_update_flags(_tbc, DBT_TBFL_ZERO, DBT_FL_IGN, 1); + + /* unlock database */ + dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h)); + +// DBT_CON_TEMP_TABLE(_h) = _tbc_temp; + last_temp_table = _tbc_temp; +// dbt_release_table(DBT_CON_CONNECTION(_h), &_tbc_temp->name); + +// dbt_result_print(_tbc_temp); if(lkey) pkg_free(lkey); if(lres) pkg_free(lres); if(_o_k) - pkg_free(_o_k); - if(_o_op) - pkg_free(_o_op); - if(_o_l) - pkg_free(_o_l); - - result = dbt_get_result(_r, _dres); - if(result != 0) - dbt_result_free(_dres); + pkg_free(_o_k); + if(_o_op) + pkg_free(_o_op); + if(_o_l) + pkg_free(_o_l); + if(_res) + pkg_free(_res); + + if(_r) { + result = dbt_get_result(_r, _tbc_temp); +// dbt_db_del_table(DBT_CON_CONNECTION(_h), &_tbc_temp->name, 1); + if(result != 0) + dbt_result_free(_h, _tbc_temp); + } return result; error: - /* unlock database */ - dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h)); -error_nounlock: + /* unlock database */ + dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h)); + /* delete temp table */ + dbt_db_del_table(DBT_CON_CONNECTION(_h), &_tbc_temp->name, 1); + if(_res) + pkg_free(_res); if(lkey) pkg_free(lkey); if(lres) @@ -296,14 +355,12 @@ int dbt_query(db1_con_t* _h, db_key_t* _k, db_op_t* _op, db_val_t* _v, pkg_free(_o_op); if(_o_l) pkg_free(_o_l); - if(_dres) - dbt_result_free(_dres); LM_ERR("failed to query the table!\n"); return -1; +/* clean: - /* unlock database */ dbt_release_table(DBT_CON_CONNECTION(_h), CON_TABLE(_h)); if(lkey) pkg_free(lkey); @@ -315,10 +372,54 @@ int dbt_query(db1_con_t* _h, db_key_t* _k, db_op_t* _op, db_val_t* _v, pkg_free(_o_op); if(_o_l) pkg_free(_o_l); - if(_dres) - dbt_result_free(_dres); return -1; +*/ +} + + +int dbt_fetch_result(db1_con_t* _h, db1_res_t** _r, const int nrows) +{ + int rows; + + if (!_h || !_r || nrows < 0) { + LM_ERR("Invalid parameter value\n"); + return -1; + } + + /* exit if the fetch count is zero */ + if (nrows == 0) { + dbt_free_result(_h, *_r); + *_r = 0; + return 0; + } + + if(*_r==0) { + /* Allocate a new result structure */ + dbt_init_result(_r, last_temp_table); + } else { + /* free old rows */ + if(RES_ROWS(*_r)!=0) + db_free_rows(*_r); + RES_ROWS(*_r) = 0; + RES_ROW_N(*_r) = 0; + } + + /* determine the number of rows remaining to be processed */ + rows = RES_NUM_ROWS(*_r) - RES_LAST_ROW(*_r); + + /* If there aren't any more rows left to process, exit */ + if(rows<=0) + return 0; + + /* if the fetch count is less than the remaining rows to process */ + /* set the number of rows to process (during this call) equal to the fetch count */ + if(nrows < rows) + rows = nrows; + + RES_ROW_N(*_r) = rows; + + return dbt_get_next_result(_r, RES_LAST_ROW(*_r), rows); } /* diff --git a/src/modules/db_text/dbt_lib.c b/src/modules/db_text/dbt_lib.c index b3926d1d781..8177ebdc3e9 100644 --- a/src/modules/db_text/dbt_lib.c +++ b/src/modules/db_text/dbt_lib.c @@ -40,6 +40,8 @@ static gen_lock_t *_dbt_cachesem = NULL; static dbt_tbl_cachel_p _dbt_cachetbl = NULL; +extern int is_main; + #define DBT_CACHETBL_SIZE 16 /** @@ -265,6 +267,7 @@ dbt_table_p dbt_db_get_table(dbt_cache_p _dc, const str *_s) hash = core_hash(&_dc->name, _s, DBT_CACHETBL_SIZE); hashidx = hash % DBT_CACHETBL_SIZE; + if(!is_main) lock_get(&_dbt_cachetbl[hashidx].sem); _tbc = _dbt_cachetbl[hashidx].dtp; @@ -380,7 +383,7 @@ int dbt_cache_destroy(void) /** * */ -int dbt_cache_print(int _f) +int dbt_cache_print2(int _f, int _lock) { int i; dbt_table_p _tbc; @@ -390,10 +393,12 @@ int dbt_cache_print(int _f) for(i=0; i< DBT_CACHETBL_SIZE; i++) { - lock_get(&_dbt_cachetbl[i].sem); + if(_lock) + lock_get(&_dbt_cachetbl[i].sem); _tbc = _dbt_cachetbl[i].dtp; while(_tbc) { + if(! (_tbc->flag & DBT_TBFL_TEMP)) { if(_f) fprintf(stdout, "\n--- Database [%.*s]\n", _tbc->dbname.len, _tbc->dbname.s); @@ -412,14 +417,21 @@ int dbt_cache_print(int _f) dbt_table_update_flags(_tbc,DBT_TBFL_MODI, DBT_FL_UNSET, 0); } } + } _tbc = _tbc->next; } - lock_release(&_dbt_cachetbl[i].sem); + if(_lock) + lock_release(&_dbt_cachetbl[i].sem); } return 0; } +int dbt_cache_print(int _f) +{ + return dbt_cache_print2(_f, !is_main); +} + int dbt_is_neq_type(db_type_t _t0, db_type_t _t1) { // LM_DBG("t0=%d t1=%d!\n", _t0, _t1); @@ -461,3 +473,47 @@ int dbt_is_neq_type(db_type_t _t0, db_type_t _t1) return 1; } +static int tmp_table_number = 0; + +dbt_table_p dbt_db_get_temp_table(dbt_cache_p _dc) +{ + dbt_table_p _tbc = NULL; + str _s; + char buf[30]; + int hash; + int hashidx; + + + if(!_dbt_cachetbl || !_dc) { + LM_ERR("invalid parameter\n"); + return NULL; + } + + sprintf(buf, "tmp-%i-%i", my_pid(), ++tmp_table_number); + _s.s = buf; + _s.len = strlen(buf); + + hash = core_hash(&_dc->name, &_s, DBT_CACHETBL_SIZE); + hashidx = hash % DBT_CACHETBL_SIZE; + + lock_get(&_dbt_cachetbl[hashidx].sem); + + _tbc = _dbt_cachetbl[hashidx].dtp; + + + + _tbc = dbt_table_new(&_s, &(_dc->name), NULL); + + _tbc->hash = hash; + _tbc->next = _dbt_cachetbl[hashidx].dtp; + if(_dbt_cachetbl[hashidx].dtp) + _dbt_cachetbl[hashidx].dtp->prev = _tbc; + + _dbt_cachetbl[hashidx].dtp = _tbc; + + dbt_table_update_flags(_tbc, DBT_TBFL_TEMP, DBT_FL_SET, 0); + + + lock_release(&_dbt_cachetbl[hashidx].sem); + return _tbc; +} diff --git a/src/modules/db_text/dbt_lib.h b/src/modules/db_text/dbt_lib.h index 00969fe1bfd..007886b5464 100644 --- a/src/modules/db_text/dbt_lib.h +++ b/src/modules/db_text/dbt_lib.h @@ -35,6 +35,7 @@ #define DBT_TBFL_ZERO 0 #define DBT_TBFL_MODI 1 +#define DBT_TBFL_TEMP 2 #define DBT_FL_IGN -1 #define DBT_FL_SET 0 @@ -50,6 +51,7 @@ extern int db_mode; /* Database usage mode: 0 = no cache, 1 = cache */ extern int empty_string; /* If TRUE, an empty string is an empty string, otherwise NULL */ extern int _db_text_read_buffer_size; /* size of the buffer to allocate when reading file */ +extern int _db_text_max_result_rows; /* max result rows */ typedef db_val_t dbt_val_t, *dbt_val_p; @@ -109,6 +111,7 @@ typedef struct _dbt_cache int dbt_init_cache(void); int dbt_cache_destroy(void); int dbt_cache_print(int); +int dbt_cache_print2(int, int); dbt_cache_p dbt_cache_get_db(str*); int dbt_cache_check_db(str*); @@ -121,12 +124,13 @@ int dbt_cache_free(dbt_cache_p); dbt_column_p dbt_column_new(char*, int); dbt_row_p dbt_row_new(int); dbt_table_p dbt_table_new(const str*, const str*, const char*); +dbt_table_p dbt_db_get_temp_table(dbt_cache_p _dc); int dbt_row_free(dbt_table_p, dbt_row_p); int dbt_column_free(dbt_column_p); int dbt_table_free_rows(dbt_table_p); int dbt_table_free(dbt_table_p); - +int dbt_db_del_table(dbt_cache_p _dc, const str *_s, int sync); int dbt_row_set_val(dbt_row_p, dbt_val_p, int, int); int dbt_row_update_val(dbt_row_p, dbt_val_p, int, int); diff --git a/src/modules/db_text/dbt_res.c b/src/modules/db_text/dbt_res.c index 2c0bc1f1df7..06fd7a4b10e 100644 --- a/src/modules/db_text/dbt_res.c +++ b/src/modules/db_text/dbt_res.c @@ -92,7 +92,7 @@ dbt_result_p dbt_result_new(dbt_table_p _dtp, int *_lres, int _sz) return NULL; } -int dbt_result_free(dbt_result_p _dres) +int _dbt_result_free(dbt_result_p _dres) { dbt_row_p _rp=NULL, _rp0=NULL; int i; @@ -134,6 +134,22 @@ int dbt_result_free(dbt_result_p _dres) return 0; } +int dbt_result_free(db1_con_t* _h, dbt_table_p _dres) +{ + if ((!_h)) + { + LM_ERR("invalid parameter value\n"); + return -1; + } + + if (!_dres) + return 0; + + dbt_db_del_table(DBT_CON_CONNECTION(_h), &_dres->name, 1); + + return 0; +} + int dbt_result_add_row(dbt_result_p _dres, dbt_row_p _drp) { if(!_dres || !_drp) @@ -316,45 +332,48 @@ int dbt_result_extract_fields(dbt_table_p _dtp, dbt_row_p _drp, return -1; } -int dbt_result_print(dbt_result_p _dres) +int dbt_result_print(dbt_table_p _dres) { -#if 0 int i; - FILE *fout = stdout; + FILE *fout = stderr; dbt_row_p rowp = NULL; char *p; - if(!_dres || _dres->nrcols<=0) + if(!_dres || _dres->nrcols<=0) { + LM_INFO("NO PRINT\n"); return -1; + } fprintf(fout, "\nContent of result\n"); for(i=0; i<_dres->nrcols; i++) { - switch(_dres->colv[i].type) + switch(_dres->colv[i]->type) { case DB1_INT: - fprintf(fout, "%.*s(int", _dres->colv[i].name.len, - _dres->colv[i].name.s); - if(_dres->colv[i].flag & DBT_FLAG_NULL) + fprintf(fout, "%.*s(int", _dres->colv[i]->name.len, + _dres->colv[i]->name.s); + if(_dres->colv[i]->flag & DBT_FLAG_NULL) fprintf(fout, ",null"); fprintf(fout, ") "); break; case DB1_DOUBLE: - fprintf(fout, "%.*s(double", _dres->colv[i].name.len, - _dres->colv[i].name.s); - if(_dres->colv[i].flag & DBT_FLAG_NULL) + fprintf(fout, "%.*s(double", _dres->colv[i]->name.len, + _dres->colv[i]->name.s); + if(_dres->colv[i]->flag & DBT_FLAG_NULL) fprintf(fout, ",null"); fprintf(fout, ") "); break; case DB1_STR: - fprintf(fout, "%.*s(str", _dres->colv[i].name.len, - _dres->colv[i].name.s); - if(_dres->colv[i].flag & DBT_FLAG_NULL) + case DB1_STRING: + fprintf(fout, "%.*s(str", _dres->colv[i]->name.len, + _dres->colv[i]->name.s); + if(_dres->colv[i]->flag & DBT_FLAG_NULL) fprintf(fout, ",null"); fprintf(fout, ") "); break; default: + LM_INFO("TYPE NOT HANDLED %i\n", _dres->colv[i]->type); return -1; } } @@ -364,7 +383,7 @@ int dbt_result_print(dbt_result_p _dres) { for(i=0; i<_dres->nrcols; i++) { - switch(_dres->colv[i].type) + switch(_dres->colv[i]->type) { case DB1_INT: if(rowp->fields[i].nul) @@ -381,6 +400,7 @@ int dbt_result_print(dbt_result_p _dres) rowp->fields[i].val.double_val); break; case DB1_STR: + case DB1_STRING: fprintf(fout, "\""); if(!rowp->fields[i].nul) { @@ -423,7 +443,6 @@ int dbt_result_print(dbt_result_p _dres) fprintf(fout, "\n"); rowp = rowp->next; } -#endif return 0; } @@ -526,6 +545,29 @@ dbt_row_p dbt_result_new_row(dbt_result_p _dres) return _drp; } +//dbt_row_p dbt_result_new_rows(dbt_row_p* _res, int rows, int cols) +//{ +// dbt_row_p _drp = NULL; +// if(!_dres || _dres->nrcols<=0) +// return NULL; +// +// _drp = (dbt_row_p)shm_malloc(sizeof(dbt_row_t) * rows); +// if(!_drp) +// return NULL; +// memset(_drp, 0, sizeof(dbt_row_t)); +// _drp->fields = (dbt_val_p)shm_malloc(_dres->nrcols*sizeof(dbt_val_t)); +// if(!_drp->fields) +// { +// shm_free(_drp); +// return NULL; +// } +// memset(_drp->fields, 0, _dres->nrcols*sizeof(dbt_val_t)); +// +// _drp->next = _drp->prev = NULL; +// +// return _drp; +//} + /* The _o clause to query is not really a db_key_t, it is SQL (str). * db_mysql and db_postgres simply paste it into SQL, we need to parse it. */ @@ -824,3 +866,129 @@ void dbt_project_result(dbt_result_p _dres, int _o_nc) _dres->nrcols -= _o_nc; } +/* comparison function for qsort */ +int dbt_qsort_compare_temp(const void *_a, const void *_b) +{ + int _i, _j, _r; + + for (_i=0; _ifields[_j], &(*(dbt_row_p *)_b)->fields[_j]); + if (_r == 0) + continue; /* no result yet, compare next column */ + if (_r == +1 || _r == -1) + return (dbt_sort_o_op[_i] == '<') ? _r : -_r; /* ASC OR DESC */ + /* error */ + longjmp(dbt_sort_jmpenv, _r); + } + + /* no result after comparing all columns, same */ + return 0; +} + +int dbt_sort_result_temp(dbt_row_p *_res, int count, int *_o_l, char *_o_op, int _o_n) +{ + int _i; + + /* set globals */ + dbt_sort_o_l = _o_l; + dbt_sort_o_op = _o_op; + dbt_sort_o_n = _o_n; + _i = setjmp(dbt_sort_jmpenv); /* exception handling */ + if (_i) + { + /* error occured during qsort */ + LM_ERR("qsort aborted\n"); + return _i; + } + + qsort(_res, count, sizeof(dbt_row_p), &dbt_qsort_compare_temp); + + return 0; +} + +dbt_row_p dbt_result_extract_results(dbt_table_p _dtp, dbt_row_p* pRows, int _nrows, int* _lres, int _ncols) +{ + dbt_row_p pRow=NULL; + dbt_row_p pTopRow=NULL; + dbt_row_p pPrvRow=NULL; + int i, n, r; + + if(!_dtp || !pRows || _ncols<=0) + return NULL; + + for(r=0; r < _nrows; r++) { + pRow = dbt_row_new(_ncols); + + for(i=0; i<_ncols; i++) + { + n = _lres[i]; + pRow->fields[i].nul = pRows[r]->fields[n].nul; + if(pRow->fields[i].nul) + { + memset(&(pRow->fields[i].val), 0, sizeof(pRow->fields[i].val)); + continue; + } + + switch(_dtp->colv[n]->type) + { + case DB1_INT: + case DB1_DATETIME: + case DB1_BITMAP: + pRow->fields[i].type = _dtp->colv[n]->type; + pRow->fields[i].val.int_val = pRows[r]->fields[n].val.int_val; + break; + case DB1_DOUBLE: + pRow->fields[i].type = DB1_DOUBLE; + pRow->fields[i].val.double_val=pRows[r]->fields[n].val.double_val; + break; + case DB1_STRING: + case DB1_STR: + case DB1_BLOB: + pRow->fields[i].type = _dtp->colv[n]->type; + pRow->fields[i].val.str_val.len = + pRows[r]->fields[n].val.str_val.len; + pRow->fields[i].val.str_val.s =(char*)shm_malloc(sizeof(char)* + (pRows[r]->fields[n].val.str_val.len+1)); + if(!pRow->fields[i].val.str_val.s) + goto clean; + memcpy(pRow->fields[i].val.str_val.s, + pRows[r]->fields[n].val.str_val.s, + pRows[r]->fields[n].val.str_val.len); + pRow->fields[i].val.str_val.s[pRows[r]->fields[n].val.str_val.len]=0; + break; + default: + goto clean; + } + } + + if(pTopRow == NULL) { + pTopRow = pRow; + } else { + pRow->prev = pPrvRow; + pPrvRow->next = pRow; + } + pPrvRow = pRow; + } + + return pTopRow; + +clean: + LM_DBG("make clean!\n"); + while(i>=0) + { + if((pRow->fields[i].type == DB1_STRING + || pRow->fields[i].type == DB1_STR + || pRow->fields[i].type == DB1_BLOB) + && !pRow->fields[i].nul + && pRow->fields[i].val.str_val.s) + shm_free(pRow->fields[i].val.str_val.s); + + i--; + } + shm_free(pRow->fields); + shm_free(pRow); + + return pTopRow; +} diff --git a/src/modules/db_text/dbt_res.h b/src/modules/db_text/dbt_res.h index 5eeee7ad2a7..dbd48631ecb 100644 --- a/src/modules/db_text/dbt_res.h +++ b/src/modules/db_text/dbt_res.h @@ -34,6 +34,7 @@ typedef struct _dbt_result { int nrcols; int nrrows; + int last_row; dbt_column_p colv; dbt_row_p rows; } dbt_result_t, *dbt_result_p; @@ -42,17 +43,22 @@ typedef struct _dbt_con { dbt_cache_p con; int affected; + dbt_table_p last_query; } dbt_con_t, *dbt_con_p; #define DBT_CON_CONNECTION(db_con) (((dbt_con_p)((db_con)->tail))->con) +#define DBT_CON_TEMP_TABLE(db_con) (((dbt_con_p)((db_con)->tail))->last_query) dbt_result_p dbt_result_new(dbt_table_p, int*, int); -int dbt_result_free(dbt_result_p); + +//int dbt_result_free(dbt_result_p); +int dbt_result_free(db1_con_t* _h, dbt_table_p _dres); + int dbt_row_match(dbt_table_p _dtp, dbt_row_p _drp, int* _lkey, db_op_t* _op, db_val_t* _v, int _n); int dbt_result_extract_fields(dbt_table_p _dtp, dbt_row_p _drp, int* lres, dbt_result_p _dres); -int dbt_result_print(dbt_result_p _dres); +int dbt_result_print(dbt_table_p _dres); int* dbt_get_refs(dbt_table_p, db_key_t*, int); int dbt_cmp_val(dbt_val_p _vp, db_val_t* _v); @@ -63,5 +69,9 @@ int dbt_mangle_columnselection(int **_lres, int *_nc, int *_o_nc, int *_o_l, int int dbt_sort_result(dbt_result_p _dres, int *_o_l, char *_o_op, int _o_n, int *_lres, int _nc); void dbt_project_result(dbt_result_p _dres, int _o_nc); +int dbt_qsort_compare_temp(const void *_a, const void *_b); +int dbt_sort_result_temp(dbt_row_p *_res, int count, int *_o_l, char *_o_op, int _o_n); +dbt_row_p dbt_result_extract_results(dbt_table_p _dtp, dbt_row_p* pRows, int _nrows, int* _lres, int _ncols); + #endif diff --git a/src/modules/db_text/dbt_tb.c b/src/modules/db_text/dbt_tb.c index e259d6b76a2..213d1f9c50a 100644 --- a/src/modules/db_text/dbt_tb.c +++ b/src/modules/db_text/dbt_tb.c @@ -137,7 +137,7 @@ dbt_table_p dbt_table_new(const str *_tbname, const str *_dbname, const char *pa { struct stat s; dbt_table_p dtp = NULL; - if(!_tbname || !_dbname || !path) + if(!_tbname || !_dbname) return NULL; dtp = (dbt_table_p)shm_malloc(sizeof(dbt_table_t)); @@ -175,7 +175,7 @@ dbt_table_p dbt_table_new(const str *_tbname, const str *_dbname, const char *pa dtp->nrrows = dtp->nrcols = dtp->auto_val = 0; dtp->auto_col = -1; dtp->mt = 0; - if(stat(path, &s) == 0) + if(path && stat(path, &s) == 0) { dtp->mt = s.st_mtime; LM_DBG("mtime is %d\n", (int)s.st_mtime);