/* * Release memory used by columns */ int db_free_columns(db1_res_t* _r) { int col; if (!_r) { LM_ERR("invalid parameter value\n"); return -1; } LM_DBG("freeing %d columns\n", RES_COL_N(_r)); /* free memory previously allocated to save column names */ for(col = 0; col < RES_COL_N(_r); col++) { if (RES_NAMES(_r)[col]!=NULL) { LM_DBG("freeing RES_NAMES[%d] at %p\n", col, RES_NAMES(_r)[col]); pkg_free((str *)RES_NAMES(_r)[col]); RES_NAMES(_r)[col] = NULL; } } RES_COL_N(_r) = 0; /* free names and types */ if (RES_NAMES(_r)) { LM_DBG("freeing result names at %p\n", RES_NAMES(_r)); pkg_free(RES_NAMES(_r)); RES_NAMES(_r) = NULL; } if (RES_TYPES(_r)) { LM_DBG("freeing result types at %p\n", RES_TYPES(_r)); pkg_free(RES_TYPES(_r)); RES_TYPES(_r) = NULL; } return 0; }
/* * Allocate storage for column names and type in existing * result structure. */ int db_allocate_columns(db1_res_t* _r, const unsigned int cols) { RES_NAMES(_r) = (db_key_t*)pkg_malloc(sizeof(db_key_t) * cols); if (!RES_NAMES(_r)) { LM_ERR("no private memory left\n"); return -1; } memset(RES_NAMES(_r), 0, sizeof(db_key_t) * cols); LM_DBG("allocate %d bytes for result names at %p\n", (int)(sizeof(db_key_t) * cols), RES_NAMES(_r)); RES_TYPES(_r) = (db_type_t*)pkg_malloc(sizeof(db_type_t) * cols); if (!RES_TYPES(_r)) { LM_ERR("no private memory left\n"); pkg_free(RES_NAMES(_r)); return -1; } memset(RES_TYPES(_r), 0, sizeof(db_type_t) * cols); LM_DBG("allocate %d bytes for result types at %p\n", (int)(sizeof(db_type_t) * cols), RES_TYPES(_r)); return 0; }
/* * Get and convert columns from a result */ int dbt_get_columns(db_con_t* _h, db_res_t* _r) { int n, i; if ((!_h) || (!_r)) { #ifdef DBT_EXTRA_DEBUG LOG(L_ERR, "DBT:dbt_get_columns: Invalid parameter\n"); #endif return -1; } n = DBT_CON_RESULT(_h)->nrcols; if (!n) { LOG(L_ERR, "DBT:get_columns: No columns\n"); return -2; } RES_NAMES(_r) = (db_key_t*)pkg_malloc(sizeof(db_key_t) * n); if (!RES_NAMES(_r)) { LOG(L_ERR, "DBT:get_columns: No memory left\n"); return -3; } RES_TYPES(_r) = (db_type_t*)pkg_malloc(sizeof(db_type_t) * n); if (!RES_TYPES(_r)) { LOG(L_ERR, "DBT:get_columns: No memory left\n"); pkg_free(RES_NAMES(_r)); return -4; } RES_COL_N(_r) = n; for(i = 0; i < n; i++) { RES_NAMES(_r)[i] = DBT_CON_RESULT(_h)->colv[i].name.s; switch( DBT_CON_RESULT(_h)->colv[i].type) { case DB_INT: case DB_DATETIME: RES_TYPES(_r)[i] = DB_INT; break; case DB_DOUBLE: RES_TYPES(_r)[i] = DB_DOUBLE; break; default: RES_TYPES(_r)[i] = DB_STR; break; } } return 0; }
/* * Get and convert columns from a result */ static int dbt_get_columns(db1_res_t* _r, dbt_result_p _dres) { int col; if (!_r || !_dres) { LM_ERR("invalid parameter\n"); return -1; } RES_COL_N(_r) = _dres->nrcols; if (!RES_COL_N(_r)) { LM_ERR("no columns\n"); return -2; } if (db_allocate_columns(_r, RES_COL_N(_r)) != 0) { LM_ERR("could not allocate columns"); return -3; } for(col = 0; col < RES_COL_N(_r); col++) { /* * Its would be not necessary to allocate here new memory, because of * the internal structure of the db_text module. But we do this anyway * to stay confirm to the other database modules. */ RES_NAMES(_r)[col] = (str*)pkg_malloc(sizeof(str)); if (! RES_NAMES(_r)[col]) { LM_ERR("no private memory left\n"); db_free_columns(_r); return -4; } LM_DBG("allocate %d bytes for RES_NAMES[%d] at %p", (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; switch(_dres->colv[col].type) { case DB1_STR: case DB1_STRING: case DB1_BLOB: case DB1_INT: case DB1_DATETIME: case DB1_DOUBLE: 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_TYPES(_r)[col] = DB1_STR; break; } } return 0; }
/* * Release memory used by columns */ int dbt_free_columns(db_res_t* _r) { if (!_r) { #ifdef DBT_EXTRA_DEBUG LOG(L_ERR, "DBT:dbt_free_columns: Invalid parameter\n"); #endif return -1; } if (RES_NAMES(_r)) pkg_free(RES_NAMES(_r)); if (RES_TYPES(_r)) pkg_free(RES_TYPES(_r)); return 0; }
/*! * \brief Convert a row from the result query into db API representation * \param _h database connection * \param _r result set * \param _row row * \param row_buf row buffer * \return 0 on success, negative on error */ int db_postgres_convert_row(const db1_con_t* _h, db1_res_t* _r, db_row_t* _row, char **row_buf) { int col, col_len; if (!_h || !_r || !_row) { LM_ERR("invalid parameter value\n"); return -1; } if (db_allocate_row(_r, _row) != 0) { LM_ERR("could not allocate row\n"); return -2; } /* For each column in the row */ for(col = 0; col < ROW_N(_row); col++) { /* because it can contain NULL */ if (!row_buf[col]) { col_len = 0; } else { col_len = strlen(row_buf[col]); } /* Convert the string representation into the value representation */ if (db_postgres_str2val(RES_TYPES(_r)[col], &(ROW_VALUES(_row)[col]), row_buf[col], col_len) < 0) { LM_ERR("failed to convert value\n"); LM_DBG("free row at %p\n", _row); db_free_row(_row); return -3; } } return 0; }
int cql_convert_row(oac::CqlResult& _cql_res, db1_res_t* _r) { std::vector<oac::CqlRow> res_cql_rows = _cql_res.rows; int rows_no = res_cql_rows.size(); int cols_no = res_cql_rows[0].columns.size(); str col_val; RES_ROW_N(_r) = rows_no; if (db_allocate_rows(_r) < 0) { LM_ERR("Could not allocate rows.\n"); return -1; } for(int ri=0; ri < rows_no; ri++) { if (db_allocate_row(_r, &(RES_ROWS(_r)[ri])) != 0) { LM_ERR("Could not allocate row.\n"); return -2; } // complete the row with the columns for(int col = 0; col< cols_no; col++) { col_val.s = (char*)res_cql_rows[ri].columns[col].value.c_str(); col_val.len = strlen(col_val.s); RES_ROWS(_r)[ri].values[col].type = RES_TYPES(_r)[col]; cassa_convert_result_raw(&RES_ROWS(_r)[ri].values[col], &col_val); LM_DBG("Field index %d. %s = %s.\n", col, res_cql_rows[ri].columns[col].name.c_str(), res_cql_rows[ri].columns[col].value.c_str()); } } return 0; }
/** * Convert a row from the result query into db API representation */ int db_postgres_convert_row(const db_con_t* _h, db_res_t* _r, db_row_t* _row, char **row_buf) { int col, len; if (!_h || !_r || !_row) { LM_ERR("invalid parameter value\n"); return -1; } /* Save the number of columns in the ROW structure */ ROW_N(_row) = RES_COL_N(_r); /* For each column in the row */ for(col = 0; col < ROW_N(_row); col++) { /* compute the len of the value */ if ( row_buf[col]==NULL || row_buf[col][0]=='\0') len = 0; else len = strlen(row_buf[col]); /* Convert the string representation into the value representation */ if (db_postgres_str2val(RES_TYPES(_r)[col], &(ROW_VALUES(_row)[col]), row_buf[col], len) < 0) { LM_ERR("failed to convert value\n"); LM_DBG("free row at %pn", _row); db_free_row(_row); return -3; } } return 0; }
/*! * \brief Convert a row from result into DB API representation * \param _h database connection * \param _res database result in the DB API representation * \param _r database result row * \return 0 on success, -1 on failure */ int db_mysql_convert_row(const db1_con_t* _h, db1_res_t* _res, db_row_t* _r) { unsigned long* lengths; int i; if ((!_h) || (!_res) || (!_r)) { LM_ERR("invalid parameter value\n"); return -1; } if (db_allocate_row(_res, _r) != 0) { LM_ERR("could not allocate row"); return -2; } lengths = mysql_fetch_lengths(CON_RESULT(_h)); for(i = 0; i < RES_COL_N(_res); i++) { if (db_str2val(RES_TYPES(_res)[i], &(ROW_VALUES(_r)[i]), ((MYSQL_ROW)CON_ROW(_h))[i], lengths[i], 0) < 0) { LM_ERR("failed to convert value\n"); LM_DBG("free row at %p\n", _r); db_free_row(_r); return -3; } } return 0; }
/* * Convert a row from result into db API representation */ int convert_row(db_con_t* _h, db_res_t* _res, db_row_t* _r) { unsigned long* lengths; int i; #ifndef PARANOID if ((!_h) || (!_r) || (!_n)) { log(L_ERR, "convert_row(): Invalid parameter value\n"); return -1; } #endif ROW_VALUES(_r) = (db_val_t*)pkg_malloc(sizeof(db_val_t) * RES_COL_N(_res)); ROW_N(_r) = RES_COL_N(_res); if (!ROW_VALUES(_r)) { LOG(L_ERR, "convert_row(): No memory left\n"); return -1; } lengths = mysql_fetch_lengths(CON_RESULT(_h)); for(i = 0; i < RES_COL_N(_res); i++) { if (str2val(RES_TYPES(_res)[i], &(ROW_VALUES(_r)[i]), ((MYSQL_ROW)CON_ROW(_h))[i], lengths[i]) < 0) { LOG(L_ERR, "convert_row(): Error while converting value\n"); free_row(_r); return -3; } } return 0; }
/* * Free all memory allocated by get_result */ int bdb_free_result(db_con_t* _h, db_res_t* _r) { db_row_t* r; db_val_t* v; int i, j; if (!_r) { #ifdef BDB_EXTRA_DEBUG LOG(L_NOTICE, "BDB:bdb_free_result: NULL pointer\n"); #endif return 0; } for (i = 0; i < RES_ROW_N(_r); i++) { r = &(RES_ROWS(_r)[i]); for (j = 0; j < RES_COL_N(_r); j++) { v = &(ROW_VALUES(r)[j]); if (VAL_TYPE(v) == DB_STRING || VAL_TYPE(v) == DB_STR || VAL_TYPE(v) == DB_BLOB) { free(VAL_STR(v).s); } } free(ROW_VALUES(r)); } free(RES_ROWS(_r)); for (i = 0; i < RES_COL_N(_r); i++) { pkg_free((void *)RES_NAMES(_r)[i]); } pkg_free(RES_NAMES(_r)); pkg_free(RES_TYPES(_r)); pkg_free(_r); return 0; }
/* * Get and convert columns from a result */ static int dbt_get_columns(db_con_t* _h, db_res_t* _r) { int col; if (!_h || !_r) { LM_ERR("invalid parameter\n"); return -1; } RES_COL_N(_r) = DBT_CON_RESULT(_h)->nrcols; if (!RES_COL_N(_r)) { LM_ERR("no columns\n"); return -2; } if (db_allocate_columns(_r, RES_COL_N(_r)) != 0) { LM_ERR("could not allocate columns\n"); return -3; } for(col = 0; col < RES_COL_N(_r); col++) { RES_NAMES(_r)[col]->s = DBT_CON_RESULT(_h)->colv[col].name.s; RES_NAMES(_r)[col]->len = DBT_CON_RESULT(_h)->colv[col].name.len; switch(DBT_CON_RESULT(_h)->colv[col].type) { case DB_STR: case DB_STRING: case DB_BLOB: case DB_INT: case DB_BIGINT: case DB_DATETIME: case DB_DOUBLE: RES_TYPES(_r)[col] = DBT_CON_RESULT(_h)->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, DBT_CON_RESULT(_h)->colv[col].type); RES_TYPES(_r)[col] = DB_STR; break; } } return 0; }
/** * This function check the CQLresult of the CQL query and * adds the columns to the returning result structure. * * \param _cql_res handle for the CQLResult * \param _r result set for storage * \return zero on success, negative value on failure */ int cql_get_columns(oac::CqlResult& _cql_res, db1_res_t* _r) { std::vector<oac::CqlRow> res_cql_rows = _cql_res.rows; int rows_no = res_cql_rows.size(); int cols_no = 0; LM_DBG("cqlrow Vector size =%d\n", rows_no); if (rows_no > 0) { cols_no = res_cql_rows[0].columns.size(); LM_DBG("There are %d columns available, this should be the case for all %d rows (consider cql).\n", cols_no, rows_no); } else { LM_DBG("Got 0 rows. There is no result from the query.\n"); return 0; } RES_COL_N(_r) = cols_no; if (!RES_COL_N(_r)) { LM_ERR("no columns returned from the query\n"); return -2; } else { LM_DBG("%d columns returned from the query\n", RES_COL_N(_r)); } if (db_allocate_columns(_r, RES_COL_N(_r)) != 0) { LM_ERR("Could not allocate columns\n"); return -3; } /* For fields we will use the columns inside the first columns */ for(int col = 0; col < RES_COL_N(_r); col++) { RES_NAMES(_r)[col] = (str*)pkg_malloc(sizeof(str)); if (! RES_NAMES(_r)[col]) { LM_ERR("no private memory left\n"); RES_COL_N(_r) = col; db_free_columns(_r); return -4; } LM_DBG("Allocated %lu bytes for RES_NAMES[%d] at %p\n", (unsigned long)sizeof(str), col, RES_NAMES(_r)[col]); /* The pointer that is here returned is part of the result structure. */ RES_NAMES(_r)[col]->s = (char*) res_cql_rows[0].columns[col].name.c_str(); RES_NAMES(_r)[col]->len = strlen(RES_NAMES(_r)[col]->s); RES_TYPES(_r)[col] = DB1_STR; LM_DBG("RES_NAMES(%p)[%d]=[%.*s]\n", RES_NAMES(_r)[col], col, RES_NAMES(_r)[col]->len, RES_NAMES(_r)[col]->s); } return 0; }
/** * Convert a row from result into db API representation */ int db_mysql_convert_row(const db_con_t* _h, db_res_t* _res, db_row_t* _r) { unsigned long* lengths; int i; if ((!_h) || (!_res) || (!_r)) { LM_ERR("invalid parameter value\n"); return -1; } /* Save the number of columns in the ROW structure */ ROW_N(_r) = RES_COL_N(_res); if (CON_HAS_PS(_h)) { for(i=0; i < CON_MYSQL_PS(_h)->cols_out; i++) { if (db_mysql_str2val(RES_TYPES(_res)[i], &(ROW_VALUES(_r)[i]), CON_PS_OUTCOL(_h, i).null?NULL:CON_PS_OUTCOL(_h, i).buf, CON_PS_OUTCOL(_h,i).len) < 0) { LM_ERR("failed to convert value from stmt\n"); db_free_row(_r); return -3; } } } else { lengths = mysql_fetch_lengths(CON_RESULT(_h)); for(i = 0; i < RES_COL_N(_res); i++) { if (db_mysql_str2val(RES_TYPES(_res)[i], &(ROW_VALUES(_r)[i]), ((MYSQL_ROW)CON_ROW(_h))[i], lengths[i]) < 0) { LM_ERR("failed to convert value\n"); LM_DBG("free row at %p\n", _r); db_free_row(_r); return -3; } } } return 0; }
/* * Create a new result structure and initialize it */ db_res_t* dbt_new_result(void) { db_res_t* r; r = (db_res_t*)pkg_malloc(sizeof(db_res_t)); if (!r) { LOG(L_ERR, "new_result(): No memory left\n"); return 0; } RES_NAMES(r) = 0; RES_TYPES(r) = 0; RES_COL_N(r) = 0; RES_ROWS(r) = 0; RES_ROW_N(r) = 0; return r; }
/* * Release memory used by columns */ int db_free_columns(db_res_t* _r) { if (!_r) { LM_ERR("invalid parameter value\n"); return -1; } /* free names and types */ if (RES_NAMES(_r)) { LM_DBG("freeing result columns at %p\n", RES_NAMES(_r)); RES_TYPES(_r) = NULL; pkg_free(RES_NAMES(_r)); RES_NAMES(_r) = NULL; } return 0; }
int bdb_get_columns(table_p _tp, db_res_t* _res, int* _lres, int _nc) { int col; if (!_res) { LM_ERR("invalid parameter\n"); return -1; } if (_nc < 0 ) { LM_ERR("_nc parameter cannot be negative \n"); return -1; } /* the number of rows (tuples) in the query result. */ RES_NUM_ROWS(_res) = 1; if (!_lres) _nc = _tp->ncols; /* Save number of columns in the result structure */ RES_COL_N(_res) = _nc; if (db_allocate_columns(_res, RES_COL_N(_res)) != 0) { LM_ERR("could not allocate columns"); return -2; } /* * For each column both the name and the data type are saved. */ for(col = 0; col < RES_COL_N(_res); col++) { column_p cp = NULL; cp = (_lres) ? _tp->colp[_lres[col]] : _tp->colp[col]; /* The pointer that is here returned is part of the result structure.*/ RES_NAMES(_res)[col]->s = cp->name.s; RES_NAMES(_res)[col]->len = cp->name.len; LM_DBG("RES_NAMES(%p)[%d]=[%.*s]\n", RES_NAMES(_res)[col] , col, RES_NAMES(_res)[col]->len, RES_NAMES(_res)[col]->s); RES_TYPES(_res)[col] = cp->type; } return 0; }
/* * Allocate storage for column names and type in existing * result structure. */ int db_allocate_columns(db_res_t* _r, const unsigned int cols) { unsigned int i; RES_NAMES(_r) = (db_key_t*)pkg_malloc ( cols * (sizeof(db_key_t)+sizeof(db_type_t)+sizeof(str)) ); if (!RES_NAMES(_r)) { LM_ERR("no private memory left\n"); return -1; } LM_DBG("allocate %d bytes for result columns at %p\n", (int)(cols * (sizeof(db_key_t)+sizeof(db_type_t)+sizeof(str))), RES_NAMES(_r)); for ( i=0 ; i<cols ; i++) RES_NAMES(_r)[i] = (str*)(RES_NAMES(_r)+cols)+i; RES_TYPES(_r) = (db_type_t*)(RES_NAMES(_r)[0]+cols); return 0; }
/* * Convert a row from result into db API representation */ int db_unixodbc_convert_row(const db_con_t* _h, const db_res_t* _res, db_row_t* _r, const unsigned long* lengths) { int i; if ((!_h) || (!_res) || (!_r)) { LM_ERR("invalid parameter value\n"); return -1; } /* Save the number of columns in the ROW structure */ ROW_N(_r) = RES_COL_N(_res); for(i = 0; i < RES_COL_N(_res); i++) { if (db_unixodbc_str2val(RES_TYPES(_res)[i], &(ROW_VALUES(_r)[i]), ((CON_ROW(_h))[i]), lengths[i]) < 0) { LM_ERR("failed to convert value\n"); LM_DBG("free row at %p\n", _r); db_free_row(_r); return -3; } } return 0; }
/* * Convert a row from result into db API representation */ static int dbt_convert_row(db1_res_t* _res, db_row_t* _r, dbt_row_p _r1) { int i; if (!_r || !_res || !_r1) { LM_ERR("invalid parameter value\n"); return -1; } if (db_allocate_row(_res, _r) != 0) { LM_ERR("could not allocate row"); return -2; } for(i = 0; i < RES_COL_N(_res); i++) { (ROW_VALUES(_r)[i]).nul = _r1->fields[i].nul; switch(RES_TYPES(_res)[i]) { case DB1_INT: VAL_INT(&(ROW_VALUES(_r)[i])) = _r1->fields[i].val.int_val; VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB1_INT; break; case DB1_BIGINT: LM_ERR("BIGINT not supported"); return -1; case DB1_DOUBLE: VAL_DOUBLE(&(ROW_VALUES(_r)[i])) = _r1->fields[i].val.double_val; VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB1_DOUBLE; break; case DB1_STRING: VAL_STR(&(ROW_VALUES(_r)[i])).s = _r1->fields[i].val.str_val.s; VAL_STR(&(ROW_VALUES(_r)[i])).len = _r1->fields[i].val.str_val.len; VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB1_STRING; VAL_FREE(&(ROW_VALUES(_r)[i])) = 0; break; case DB1_STR: VAL_STR(&(ROW_VALUES(_r)[i])).s = _r1->fields[i].val.str_val.s; VAL_STR(&(ROW_VALUES(_r)[i])).len = _r1->fields[i].val.str_val.len; VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB1_STR; VAL_FREE(&(ROW_VALUES(_r)[i])) = 0; break; case DB1_DATETIME: VAL_INT(&(ROW_VALUES(_r)[i])) = _r1->fields[i].val.int_val; VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB1_DATETIME; break; case DB1_BLOB: VAL_STR(&(ROW_VALUES(_r)[i])).s = _r1->fields[i].val.str_val.s; VAL_STR(&(ROW_VALUES(_r)[i])).len = _r1->fields[i].val.str_val.len; VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB1_BLOB; VAL_FREE(&(ROW_VALUES(_r)[i])) = 0; break; case DB1_BITMAP: VAL_INT(&(ROW_VALUES(_r)[i])) = _r1->fields[i].val.bitmap_val; VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB1_INT; break; default: LM_ERR("val type [%d] not supported", RES_TYPES(_res)[i]); return -1; } } return 0; }
/** * Convert rows from Berkeley DB to db API representation */ int bdb_convert_row(db_res_t* _res, char *bdb_result, int* _lres) { int col, len, i, j; char **row_buf, *s; col = len = i = j = 0; struct db_row* row = NULL; if (!_res) { LM_ERR("invalid parameter\n"); return -1; } /* Save the number of rows in the current fetch */ RES_ROW_N(_res) = 1; row = RES_ROWS(_res); /* Save the number of columns in the ROW structure */ ROW_N(row) = RES_COL_N(_res); /* * Allocate an array of pointers one per column. * It that will be used to hold the address of the string * representation of each column. */ len = sizeof(char *) * RES_COL_N(_res); row_buf = (char **)pkg_malloc(len); if (!row_buf) { LM_ERR("no private memory left\n"); return -1; } LM_DBG("allocate for %d columns %d bytes in row buffer at %p\n", RES_COL_N(_res), len, row_buf); memset(row_buf, 0, len); /*populate the row_buf with bdb_result*/ /*bdb_result is memory from our callers stack so we copy here*/ LM_DBG("Found: [%s]\n",bdb_result); s = strsep(&bdb_result, DELIM); while( s!=NULL) { if(_lres) { /*only requested cols (_c was specified)*/ for(i=0; i<ROW_N(row); i++) { if (col == _lres[i]) { len = strlen(s); row_buf[i] = pkg_malloc(len+1); if (!row_buf[i]) { LM_ERR("no private memory left\n"); goto error; } LM_DBG("allocated %d bytes for row_buf[%d] at %p\n", len, i, row_buf[i]); memset(row_buf[i], 0, len+1); strncpy(row_buf[i], s, len); } } } else { /* TODO: TEST */ if( col >= RES_COL_N(_res)) break; len = strlen(s); row_buf[col] = pkg_malloc(len+1); if (!row_buf[col]) { LM_ERR("no private memory left\n"); return -1; } LM_DBG("allocated %d bytes for row_buf[%d] at %p\n", len, col, row_buf[col]); memset(row_buf[col], 0, len+1); strncpy(row_buf[col], s, len); } s = strsep(&bdb_result, DELIM); col++; } /*do the type conversion per col*/ for(col = 0; col < ROW_N(row); col++) { /*skip the unrequested cols (as already specified)*/ if(!row_buf[col]) continue; /* Convert the string representation into the value representation */ if (bdb_str2val(RES_TYPES(_res)[col], &(ROW_VALUES(row)[col]) , row_buf[col], strlen(row_buf[col])) < 0) { LM_ERR("while converting value\n"); goto error; } if( row->values[col].nul || row->values[col].type == DB_INT || row->values[col].type == DB_BIGINT || row->values[col].type == DB_DOUBLE || row->values[col].type == DB_DATETIME ) pkg_free(row_buf[col]); } LM_DBG("freeing row buffer at %p\n", row_buf); if( row_buf[col]) pkg_free(row_buf); row_buf = NULL; return 0; error: for(col = 0; col < ROW_N(row); col++) if( row_buf[col]) pkg_free(row_buf[col]); if( row_buf ) pkg_free(row_buf); return -1; }
/** * Get and convert columns from a result */ int db_mysql_get_columns(const db_con_t* _h, db_res_t* _r) { int col; MYSQL_FIELD* fields; if ((!_h) || (!_r)) { LM_ERR("invalid parameter\n"); return -1; } if (CON_HAS_PS(_h)) { RES_COL_N(_r) = CON_MYSQL_PS(_h)->cols_out; } else { RES_COL_N(_r) = mysql_field_count(CON_CONNECTION(_h)); } if (!RES_COL_N(_r)) { LM_ERR("no columns returned from the query\n"); return -2; } else { LM_DBG("%d columns returned from the query\n", RES_COL_N(_r)); } if (db_allocate_columns(_r, RES_COL_N(_r)) != 0) { LM_ERR("could not allocate columns\n"); return -3; } fields = mysql_fetch_fields(CON_RESULT(_h)); for(col = 0; col < RES_COL_N(_r); col++) { /* The pointer that is here returned is part of the result structure */ RES_NAMES(_r)[col]->s = fields[col].name; RES_NAMES(_r)[col]->len = strlen(fields[col].name); LM_DBG("RES_NAMES(%p)[%d]=[%.*s]\n", RES_NAMES(_r)[col], col, RES_NAMES(_r)[col]->len, RES_NAMES(_r)[col]->s); switch(fields[col].type) { case MYSQL_TYPE_TINY: case MYSQL_TYPE_SHORT: case MYSQL_TYPE_LONG: case MYSQL_TYPE_INT24: case MYSQL_TYPE_DECIMAL: #if MYSQL_VERSION_ID > 49999 case MYSQL_TYPE_NEWDECIMAL: #endif case MYSQL_TYPE_TIMESTAMP: LM_DBG("use DB_INT result type\n"); RES_TYPES(_r)[col] = DB_INT; break; case MYSQL_TYPE_FLOAT: case MYSQL_TYPE_DOUBLE: LM_DBG("use DB_DOUBLE result type\n"); RES_TYPES(_r)[col] = DB_DOUBLE; break; case MYSQL_TYPE_DATETIME: case MYSQL_TYPE_DATE: LM_DBG("use DB_DATETIME result type\n"); RES_TYPES(_r)[col] = DB_DATETIME; break; case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_BLOB: LM_DBG("use DB_BLOB result type\n"); RES_TYPES(_r)[col] = DB_BLOB; break; case FIELD_TYPE_SET: LM_DBG("use DB_BITMAP result type\n"); RES_TYPES(_r)[col] = DB_BITMAP; break; case MYSQL_TYPE_STRING: case MYSQL_TYPE_VAR_STRING: LM_DBG("use DB_STRING result type\n"); RES_TYPES(_r)[col] = DB_STRING; break; case MYSQL_TYPE_LONGLONG: LM_DBG("use DB_BIGINT result type\n"); RES_TYPES(_r)[col] = DB_BIGINT; break; default: LM_WARN("unhandled data type column (%.*s) type id (%d), " "use DB_STRING as default\n", RES_NAMES(_r)[col]->len, RES_NAMES(_r)[col]->s, fields[col].type); RES_TYPES(_r)[col] = DB_STRING; break; } } return 0; }
/*! * \brief Get and convert columns from a result * * Get and convert columns from a result, fills the result structure * with data from the database. * \param _h database connection * \param _r database result set * \return 0 on success, negative on failure */ int db_mysql_get_columns(const db1_con_t* _h, db1_res_t* _r) { int col; MYSQL_FIELD* fields; if ((!_h) || (!_r)) { LM_ERR("invalid parameter\n"); return -1; } RES_COL_N(_r) = mysql_field_count(CON_CONNECTION(_h)); if (!RES_COL_N(_r)) { LM_ERR("no columns returned from the query\n"); return -2; } else { LM_DBG("%d columns returned from the query\n", RES_COL_N(_r)); } if (db_allocate_columns(_r, RES_COL_N(_r)) != 0) { RES_COL_N(_r) = 0; LM_ERR("could not allocate columns\n"); return -3; } fields = mysql_fetch_fields(RES_RESULT(_r)); for(col = 0; col < RES_COL_N(_r); col++) { RES_NAMES(_r)[col] = (str*)pkg_malloc(sizeof(str)); if (! RES_NAMES(_r)[col]) { LM_ERR("no private memory left\n"); db_free_columns(_r); return -4; } LM_DBG("allocate %lu bytes for RES_NAMES[%d] at %p\n", (unsigned long)sizeof(str), col, RES_NAMES(_r)[col]); /* The pointer that is here returned is part of the result structure. */ RES_NAMES(_r)[col]->s = fields[col].name; RES_NAMES(_r)[col]->len = strlen(fields[col].name); LM_DBG("RES_NAMES(%p)[%d]=[%.*s]\n", RES_NAMES(_r)[col], col, RES_NAMES(_r)[col]->len, RES_NAMES(_r)[col]->s); switch(fields[col].type) { case MYSQL_TYPE_TINY: case MYSQL_TYPE_SHORT: case MYSQL_TYPE_LONG: case MYSQL_TYPE_INT24: case MYSQL_TYPE_TIMESTAMP: LM_DBG("use DB1_INT result type\n"); RES_TYPES(_r)[col] = DB1_INT; break; case MYSQL_TYPE_LONGLONG: LM_DBG("use DB1_BIGINT result type\n"); RES_TYPES(_r)[col] = DB1_BIGINT; break; case MYSQL_TYPE_FLOAT: case MYSQL_TYPE_DOUBLE: LM_DBG("use DB1_DOUBLE result type\n"); RES_TYPES(_r)[col] = DB1_DOUBLE; break; case MYSQL_TYPE_DATETIME: LM_DBG("use DB1_DATETIME result type\n"); RES_TYPES(_r)[col] = DB1_DATETIME; break; case MYSQL_TYPE_BLOB: LM_DBG("use DB1_BLOB result type\n"); RES_TYPES(_r)[col] = DB1_BLOB; break; case FIELD_TYPE_SET: LM_DBG("use DB1_BITMAP result type\n"); RES_TYPES(_r)[col] = DB1_BITMAP; break; case MYSQL_TYPE_DECIMAL: #if MYSQL_VERSION_ID > 49999 case MYSQL_TYPE_NEWDECIMAL: #endif case MYSQL_TYPE_STRING: case MYSQL_TYPE_VAR_STRING: LM_DBG("use DB1_STRING result type\n"); RES_TYPES(_r)[col] = DB1_STRING; break; default: LM_WARN("unhandled data type column (%.*s) type id (%d), " "use DB1_STRING as default\n", RES_NAMES(_r)[col]->len, RES_NAMES(_r)[col]->s, fields[col].type); RES_TYPES(_r)[col] = DB1_STRING; break; } } return 0; }
/* * Get and convert columns from a result */ int db_mysql_get_columns(db_con_t* _h, db_res_t* _r) { int n, i; MYSQL_FIELD* fields; if ((!_h) || (!_r)) { LM_ERR("invalid parameter\n"); return -1; } n = mysql_field_count(CON_CONNECTION(_h)); if (!n) { LM_ERR("no columns\n"); return -2; } RES_NAMES(_r) = (db_key_t*)pkg_malloc(sizeof(db_key_t) * n); if (!RES_NAMES(_r)) { LM_ERR("no private memory left\n"); return -3; } RES_TYPES(_r) = (db_type_t*)pkg_malloc(sizeof(db_type_t) * n); if (!RES_TYPES(_r)) { LM_ERR("no private memory left\n"); pkg_free(RES_NAMES(_r)); return -4; } RES_COL_N(_r) = n; fields = mysql_fetch_fields(CON_RESULT(_h)); for(i = 0; i < n; i++) { RES_NAMES(_r)[i] = fields[i].name; switch(fields[i].type) { case FIELD_TYPE_TINY: case FIELD_TYPE_SHORT: case FIELD_TYPE_LONG: case FIELD_TYPE_INT24: case FIELD_TYPE_LONGLONG: case FIELD_TYPE_DECIMAL: case FIELD_TYPE_TIMESTAMP: RES_TYPES(_r)[i] = DB_INT; break; case FIELD_TYPE_FLOAT: case FIELD_TYPE_DOUBLE: RES_TYPES(_r)[i] = DB_DOUBLE; break; case FIELD_TYPE_DATETIME: RES_TYPES(_r)[i] = DB_DATETIME; break; case FIELD_TYPE_BLOB: case FIELD_TYPE_TINY_BLOB: case FIELD_TYPE_MEDIUM_BLOB: case FIELD_TYPE_LONG_BLOB: RES_TYPES(_r)[i] = DB_BLOB; break; case FIELD_TYPE_SET: RES_TYPES(_r)[i] = DB_BITMAP; break; default: RES_TYPES(_r)[i] = DB_STRING; break; } } return 0; }
/* * Get and convert columns from a result. Define handlers and buffers */ static int get_columns(ora_con_t* con, db_res_t* _r, OCIStmt* _c, dmap_t* _d) { OCIParam *param; size_t tsz; ub4 i, n; sword status; status = OCIAttrGet(_c, OCI_HTYPE_STMT, &n, NULL, OCI_ATTR_PARAM_COUNT, con->errhp); if (status != OCI_SUCCESS) { LM_ERR("driver: %s\n", db_oracle_error(con, status)); return -1; } if (!n) { LM_ERR("no columns\n"); return -2; } if (n >= MAX_DEF_HANDLES) { LM_ERR("too many res. Rebuild with MAX_DEF_HANDLES >= %u\n", n); return -3; } if (db_allocate_columns(_r, n) != 0) { LM_ERR("could not allocate columns\n"); return -4; } for (i = 0; i < n; ++i) memset(RES_NAMES(_r)[i], 0, sizeof(db_key_t)); RES_COL_N(_r) = n; tsz = 0; memset(_d->defh, 0, sizeof(_d->defh[0]) * n); for (i = 0; i < n; i++) { ub4 len; ub2 dtype; status = OCIParamGet(_c, OCI_HTYPE_STMT, con->errhp, (dvoid**)(dvoid*)¶m, i+1); if (status != OCI_SUCCESS) goto ora_err; { text* name; status = OCIAttrGet(param, OCI_DTYPE_PARAM, (dvoid**)(dvoid*)&name, &len, OCI_ATTR_NAME, con->errhp); if (status != OCI_SUCCESS) goto ora_err; RES_NAMES(_r)[i]->s = (char*)pkg_malloc(len+1); if (!RES_NAMES(_r)[i]->s) { db_free_columns(_r); LM_ERR("no private memory left\n"); return -5; } RES_NAMES(_r)[i]->len = len; memcpy(RES_NAMES(_r)[i]->s, name, len); RES_NAMES(_r)[i]->s[len] = '\0'; } status = OCIAttrGet(param, OCI_DTYPE_PARAM, (dvoid**)(dvoid*)&dtype, NULL, OCI_ATTR_DATA_TYPE, con->errhp); if (status != OCI_SUCCESS) goto ora_err; switch (dtype) { case SQLT_UIN: /* unsigned integer */ set_bitmap: LM_DBG("use DB_BITMAP type\n"); RES_TYPES(_r)[i] = DB_BITMAP; len = sizeof(VAL_BITMAP((db_val_t*)NULL)); break; case SQLT_INT: /* (ORANET TYPE) integer */ set_int: LM_DBG("use DB_INT result type\n"); RES_TYPES(_r)[i] = DB_INT; len = sizeof(VAL_INT((db_val_t*)NULL)); break; case SQLT_LNG: /* long */ case SQLT_VNU: /* NUM with preceding length byte */ case SQLT_NUM: /* (ORANET TYPE) oracle numeric */ len = 0; /* PRECISION is ub1 */ status = OCIAttrGet(param, OCI_DTYPE_PARAM, (dvoid**)(dvoid*)&len, NULL, OCI_ATTR_PRECISION, con->errhp); if (status != OCI_SUCCESS) goto ora_err; if (len <= 11) { sb1 sc; status = OCIAttrGet(param, OCI_DTYPE_PARAM, (dvoid**)(dvoid*)&sc, NULL, OCI_ATTR_SCALE, con->errhp); if (status != OCI_SUCCESS) goto ora_err; if (!sc) { dtype = SQLT_INT; if (len != 11) goto set_int; dtype = SQLT_UIN; goto set_bitmap; } } LM_DBG("use DB_BIGINT result type\n"); RES_TYPES(_r)[i] = DB_BIGINT; len = sizeof(VAL_BIGINT((db_val_t*)NULL)); dtype = SQLT_NUM; break; case SQLT_FLT: /* (ORANET TYPE) Floating point number */ case SQLT_BFLOAT: /* Native Binary float*/ case SQLT_BDOUBLE: /* NAtive binary double */ case SQLT_IBFLOAT: /* binary float canonical */ case SQLT_IBDOUBLE: /* binary double canonical */ case SQLT_PDN: /* (ORANET TYPE) Packed Decimal Numeric */ LM_DBG("use DB_DOUBLE result type\n"); RES_TYPES(_r)[i] = DB_DOUBLE; len = sizeof(VAL_DOUBLE((db_val_t*)NULL)); dtype = SQLT_FLT; break; // case SQLT_TIME: /* TIME */ // case SQLT_TIME_TZ: /* TIME WITH TIME ZONE */ case SQLT_DATE: /* ANSI Date */ case SQLT_DAT: /* date in oracle format */ case SQLT_ODT: /* OCIDate type */ case SQLT_TIMESTAMP: /* TIMESTAMP */ case SQLT_TIMESTAMP_TZ: /* TIMESTAMP WITH TIME ZONE */ case SQLT_TIMESTAMP_LTZ:/* TIMESTAMP WITH LOCAL TZ */ // case SQLT_INTERVAL_YM: /* INTERVAL YEAR TO MONTH */ // case SQLT_INTERVAL_DS: /* INTERVAL DAY TO SECOND */ LM_DBG("use DB_DATETIME result type\n"); RES_TYPES(_r)[i] = DB_DATETIME; len = sizeof(OCIDate); dtype = SQLT_ODT; break; case SQLT_CLOB: /* character lob */ case SQLT_BLOB: /* binary lob */ // case SQLT_BFILEE: /* binary file lob */ // case SQLT_CFILEE: /* character file lob */ // case SQLT_BIN: /* binary data(DTYBIN) */ // case SQLT_LBI: /* long binary */ LM_DBG("use DB_BLOB result type\n"); RES_TYPES(_r)[i] = DB_BLOB; goto dyn_str; case SQLT_CHR: /* (ORANET TYPE) character string */ case SQLT_STR: /* zero terminated string */ case SQLT_VST: /* OCIString type */ case SQLT_VCS: /* Variable character string */ case SQLT_AFC: /* Ansi fixed char */ case SQLT_AVC: /* Ansi Var char */ // case SQLT_RID: /* rowid */ LM_DBG("use DB_STR result type\n"); RES_TYPES(_r)[i] = DB_STR; dyn_str: dtype = SQLT_CHR; len = 0; /* DATA_SIZE is ub2 */ status = OCIAttrGet(param, OCI_DTYPE_PARAM, (dvoid**)(dvoid*)&len, NULL, OCI_ATTR_DATA_SIZE, con->errhp); if (status != OCI_SUCCESS) goto ora_err; if (len >= 4000) { LM_DBG("use DB_BLOB result type\n"); RES_TYPES(_r)[i] = DB_BLOB; } ++len; break; default: LM_ERR("unsupported datatype %d\n", dtype); goto stop_load; } _d->ilen[i] = (ub2)len; _d->pv[i].v = st_buf + tsz; tsz += len; status = OCIDefineByPos(_c, &_d->defh[i], con->errhp, i+1, _d->pv[i].v, len, dtype, &_d->ind[i], &_d->len[i], NULL, OCI_DEFAULT); if (status != OCI_SUCCESS) goto ora_err; } #if STATIC_BUF_LEN < 65536 #error #endif if (tsz > 65536) { LM_ERR("Row size exceed 65K. IOB's are not supported\n"); goto stop_load; } return 0; ora_err: LM_ERR("driver: %s\n", db_oracle_error(con, status)); stop_load: db_free_columns(_r); return -6; }
/* * Convert a row from result into db API representation */ static int dbt_convert_row(db_con_t* _h, db_res_t* _res, db_row_t* _r) { int i; if (!_h || !_r || !_res) { LM_ERR("invalid parameter value\n"); return -1; } ROW_N(_r) = RES_COL_N(_res); for(i = 0; i < RES_COL_N(_res); i++) { (ROW_VALUES(_r)[i]).nul = DBT_CON_ROW(_h)->fields[i].nul; switch(RES_TYPES(_res)[i]) { case DB_INT: VAL_INT(&(ROW_VALUES(_r)[i])) = DBT_CON_ROW(_h)->fields[i].val.int_val; VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB_INT; break; case DB_BIGINT: VAL_BIGINT(&(ROW_VALUES(_r)[i])) = DBT_CON_ROW(_h)->fields[i].val.bigint_val; VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB_BIGINT; break; case DB_DOUBLE: VAL_DOUBLE(&(ROW_VALUES(_r)[i])) = DBT_CON_ROW(_h)->fields[i].val.double_val; VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB_DOUBLE; break; case DB_STRING: VAL_STR(&(ROW_VALUES(_r)[i])).s = DBT_CON_ROW(_h)->fields[i].val.str_val.s; VAL_STR(&(ROW_VALUES(_r)[i])).len = DBT_CON_ROW(_h)->fields[i].val.str_val.len; VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB_STRING; VAL_FREE(&(ROW_VALUES(_r)[i])) = 0; break; case DB_STR: VAL_STR(&(ROW_VALUES(_r)[i])).s = DBT_CON_ROW(_h)->fields[i].val.str_val.s; VAL_STR(&(ROW_VALUES(_r)[i])).len = DBT_CON_ROW(_h)->fields[i].val.str_val.len; VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB_STR; VAL_FREE(&(ROW_VALUES(_r)[i])) = 0; break; case DB_DATETIME: VAL_INT(&(ROW_VALUES(_r)[i])) = DBT_CON_ROW(_h)->fields[i].val.int_val; VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB_DATETIME; break; case DB_BLOB: VAL_STR(&(ROW_VALUES(_r)[i])).s = DBT_CON_ROW(_h)->fields[i].val.str_val.s; VAL_STR(&(ROW_VALUES(_r)[i])).len = DBT_CON_ROW(_h)->fields[i].val.str_val.len; VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB_BLOB; VAL_FREE(&(ROW_VALUES(_r)[i])) = 0; break; case DB_BITMAP: VAL_INT(&(ROW_VALUES(_r)[i])) = DBT_CON_ROW(_h)->fields[i].val.bitmap_val; VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB_INT; break; } } return 0; }
/*! * \brief Get and convert columns from a result * * Get and convert columns from a result, fills the result structure * with data from the database. * \param _h database connection * \param _r database result set * \return 0 on success, negative on failure */ int db_mongodb_get_columns(const db1_con_t* _h, db1_res_t* _r) { int col; db_mongodb_result_t *mgres; bson_iter_t riter; bson_iter_t citer; bson_t *cdoc; const char *colname; bson_type_t coltype; if ((!_h) || (!_r)) { LM_ERR("invalid parameter\n"); return -1; } mgres = (db_mongodb_result_t*)RES_PTR(_r); if(!mgres->rdoc) { mgres->nrcols = 0; return 0; } if(mgres->nrcols==0 || mgres->colsdoc==NULL) { mgres->nrcols = (int)bson_count_keys(mgres->rdoc); if(mgres->nrcols==0) { LM_ERR("no keys in bson document\n"); return -1; } cdoc = mgres->rdoc; } else { cdoc = mgres->colsdoc; } RES_COL_N(_r) = mgres->nrcols; if (!RES_COL_N(_r)) { LM_ERR("no columns returned from the query\n"); return -2; } else { LM_DBG("%d columns returned from the query\n", RES_COL_N(_r)); } if (db_allocate_columns(_r, RES_COL_N(_r)) != 0) { RES_COL_N(_r) = 0; LM_ERR("could not allocate columns\n"); return -3; } if (!bson_iter_init (&citer, cdoc)) { LM_ERR("failed to initialize columns iterator\n"); return -3; } if(mgres->colsdoc) { if (!bson_iter_init (&riter, mgres->rdoc)) { LM_ERR("failed to initialize result iterator\n"); return -3; } } col = 0; while (bson_iter_next (&citer)) { if(col >= RES_COL_N(_r)) { LM_ERR("invalid number of columns (%d/%d)\n", col, RES_COL_N(_r)); return -4; } colname = bson_iter_key (&citer); LM_DBG("Found a field[%d] named: %s\n", col, colname); if(mgres->colsdoc) { if(!bson_iter_find(&riter, colname)) { LM_ERR("field [%s] not found in result iterator\n", colname); return -4; } coltype = bson_iter_type(&riter); } else { coltype = bson_iter_type(&citer); } RES_NAMES(_r)[col] = (str*)pkg_malloc(sizeof(str)); if (! RES_NAMES(_r)[col]) { LM_ERR("no private memory left\n"); db_free_columns(_r); return -4; } LM_DBG("allocate %lu bytes for RES_NAMES[%d] at %p\n", (unsigned long)sizeof(str), col, RES_NAMES(_r)[col]); /* pointer linked here is part of the result structure */ RES_NAMES(_r)[col]->s = (char*)colname; RES_NAMES(_r)[col]->len = strlen(colname); switch(coltype) { case BSON_TYPE_BOOL: case BSON_TYPE_INT32: case BSON_TYPE_TIMESTAMP: LM_DBG("use DB1_INT result type\n"); RES_TYPES(_r)[col] = DB1_INT; break; case BSON_TYPE_INT64: LM_DBG("use DB1_BIGINT result type\n"); RES_TYPES(_r)[col] = DB1_BIGINT; break; case BSON_TYPE_DOUBLE: LM_DBG("use DB1_DOUBLE result type\n"); RES_TYPES(_r)[col] = DB1_DOUBLE; break; case BSON_TYPE_DATE_TIME: LM_DBG("use DB1_DATETIME result type\n"); RES_TYPES(_r)[col] = DB1_DATETIME; break; case BSON_TYPE_BINARY: LM_DBG("use DB1_BLOB result type\n"); RES_TYPES(_r)[col] = DB1_BLOB; break; case BSON_TYPE_UTF8: LM_DBG("use DB1_STRING result type\n"); RES_TYPES(_r)[col] = DB1_STRING; break; #if 0 case BSON_TYPE_EOD: case BSON_TYPE_DOCUMENT: case BSON_TYPE_ARRAY: case BSON_TYPE_UNDEFINED: case BSON_TYPE_OID: case BSON_TYPE_NULL: case BSON_TYPE_REGEX: case BSON_TYPE_DBPOINTER: case BSON_TYPE_CODE: case BSON_TYPE_SYMBOL: case BSON_TYPE_CODEWSCOPE: case BSON_TYPE_MAXKEY: case BSON_TYPE_MINKEY: #endif default: LM_INFO("unhandled data type column (%.*s) type id (%d), " "use DB1_STRING as default\n", RES_NAMES(_r)[col]->len, RES_NAMES(_r)[col]->s, coltype); RES_TYPES(_r)[col] = DB1_STRING; break; } LM_DBG("RES_NAMES(%p)[%d]=[%.*s] (%d)\n", RES_NAMES(_r)[col], col, RES_NAMES(_r)[col]->len, RES_NAMES(_r)[col]->s, coltype); col++; } return 0; }
/* * Query table for specified rows * _h: structure representing database connection * _k: key names * _op: operators * _v: values of the keys that must match * _c: column names to return * _n: number of key=values pairs to compare * _nc: number of columns to return * _o: order by the specified column */ int db_cassa_query(const db1_con_t* _h, const db_key_t* _k, const db_op_t* _op, const db_val_t* _v, const db_key_t* _c, int _n, int _nc, const db_key_t _o, db1_res_t** _r) { db1_res_t* db_res = 0; int rows_no; ColumnVecPtr cassa_result; dbcassa_table_p tbc; int seckey_len; if (!_h || !CON_TABLE(_h) || !_r) { LM_ERR("invalid parameter value\n"); return -1; } LM_DBG("query table=%s\n", _h->table->s); /** Construct and send the query to Cassandra Cluster **/ cassa_result = cassa_translate_query(_h, _k, _v, _c, _n, _nc, &rows_no); if(cassa_result.get() == NULL) { LM_ERR("Failed to query Cassandra cluster\n"); return -1; } /* compare the number of queried cols with the key cols*/ // if(no_kc + no_sec_kc < _n) { /* TODO */ /* filter manually for the rest of the values */ // } db_res = db_new_result(); if (!db_res) { LM_ERR("no memory left\n"); goto error; } RES_COL_N(db_res)= _nc; if(!db_allocate_columns(db_res, _nc) < 0) { LM_ERR("no more memory\n"); goto error; } tbc = dbcassa_db_get_table(&CON_CASSA(_h)->db_name, CON_TABLE(_h)); if(!tbc) { LM_ERR("table %.*s does not exist!\n", CON_TABLE(_h)->len, CON_TABLE(_h)->s); return -1; } /** Convert the result from Cassandra **/ /* fill in the columns name and type */ for(int col = 0; col < _nc; col++) { RES_NAMES(db_res)[col] = (str*)pkg_malloc(sizeof(str)); if (! RES_NAMES(db_res)[col]) { LM_ERR("no private memory left\n"); dbcassa_lock_release(tbc); RES_COL_N(db_res) = col; db_free_columns(db_res); goto error; } *RES_NAMES(db_res)[col] = *_c[col]; /* search the column in table schema to get the type */ dbcassa_column_p colp = cassa_search_col(tbc, _c[col]); if(!colp) { LM_ERR("No column with name [%.*s] found\n", _c[col]->len, _c[col]->s); dbcassa_lock_release(tbc); RES_COL_N(db_res) = col; db_free_columns(db_res); goto error; } RES_TYPES(db_res)[col] = colp->type; LM_DBG("RES_NAMES(%p)[%d]=[%.*s]\n", RES_NAMES(db_res)[col], col, RES_NAMES(db_res)[col]->len, RES_NAMES(db_res)[col]->s); } /* TODO if all columns asked - take from table schema */ seckey_len = tbc->seckey_len; dbcassa_lock_release(tbc); if(!cassa_result->size()) { LM_DBG("The query returned no result\n"); RES_ROW_N(db_res) = 0; goto done; } /* Initialize the row_slices vector for the case with one column and no secondary key */ if(rows_no == 1) { row_slices[0][0]= cassa_result->size(); row_slices[0][1]= 0; if(seckey_len) { /* if the table has a secondary key defined */ /* pass through the result once to see how many rows there are */ rows_no = cassa_result_separate_rows(*cassa_result); if(rows_no < 0) { LM_ERR("Wrong formated column names\n"); goto error; } } } RES_ROW_N(db_res) = rows_no; if (db_allocate_rows(db_res) < 0) { LM_ERR("could not allocate rows"); goto error; } for(int ri=0; ri < rows_no; ri++) { if (db_allocate_row(db_res, &(RES_ROWS(db_res)[ri])) != 0) { LM_ERR("could not allocate row"); goto error; } /* complete the row with the columns */ for(int col = 0; col< _nc; col++) { RES_ROWS(db_res)[ri].values[col].type = RES_TYPES(db_res)[col]; cassa_convert_result(_c[col], *cassa_result, (ri>0?row_slices[ri-1][0]:0), row_slices[ri][0], row_slices[ri][1], &RES_ROWS(db_res)[ri].values[col]); } } done: *_r = db_res; LM_DBG("Exited with success\n"); return 0; error: if(db_res) db_free_result(db_res); return -1; }
/*! * \brief Convert rows from mongodb to db API representation * \param _h database connection * \param _r database result set * \return 0 on success, negative on failure */ static int db_mongodb_convert_bson(const db1_con_t* _h, db1_res_t* _r, int _row, const bson_t *_rdoc) { static str dummy_string = {"", 0}; int col; db_mongodb_result_t *mgres; const char *colname; bson_type_t coltype; bson_iter_t riter; bson_iter_t citer; bson_iter_t *piter; db_val_t* dval; uint32_t i32tmp; bson_subtype_t subtype; bson_t *cdoc; mgres = (db_mongodb_result_t*)RES_PTR(_r); if(mgres->nrcols==0) { LM_ERR("no fields to convert\n"); return -1; } if(mgres->colsdoc==NULL) { cdoc = (bson_t*)_rdoc; } else { cdoc = (bson_t*)mgres->colsdoc; } if (!bson_iter_init (&citer, cdoc)) { LM_ERR("failed to initialize columns iterator\n"); return -3; } if(mgres->colsdoc) { if (!bson_iter_init (&riter, _rdoc)) { LM_ERR("failed to initialize result iterator\n"); return -3; } } if (db_allocate_row(_r, &(RES_ROWS(_r)[_row])) != 0) { LM_ERR("could not allocate row: %d\n", _row); return -2; } col = 0; while (bson_iter_next (&citer)) { if(col >= RES_COL_N(_r)) { LM_ERR("invalid number of columns (%d/%d)\n", col, RES_COL_N(_r)); return -4; } colname = bson_iter_key (&citer); LM_DBG("looking for field[%d] named: %s\n", col, colname); if(mgres->colsdoc) { if(!bson_iter_find(&riter, colname)) { LM_ERR("field [%s] not found in result iterator\n", colname); return -4; } piter = &riter; } else { piter = &citer; } coltype = bson_iter_type(piter); dval = &(ROW_VALUES(&(RES_ROWS(_r)[_row]))[col]); VAL_TYPE(dval) = RES_TYPES(_r)[col]; switch(coltype) { case BSON_TYPE_BOOL: VAL_INT(dval) = (int)bson_iter_bool (piter); break; case BSON_TYPE_INT32: VAL_INT(dval) = bson_iter_int32 (piter); break; case BSON_TYPE_TIMESTAMP: bson_iter_timestamp (piter, (uint32_t*)&VAL_INT(dval), &i32tmp); break; case BSON_TYPE_INT64: VAL_BIGINT(dval) = bson_iter_int64 (piter); break; case BSON_TYPE_DOUBLE: VAL_DOUBLE(dval) = bson_iter_double (piter); break; case BSON_TYPE_DATE_TIME: VAL_TIME(dval) = (time_t)(bson_iter_date_time (piter)/1000); break; case BSON_TYPE_BINARY: bson_iter_binary (piter, &subtype, (uint32_t*)&VAL_BLOB(dval).len, (const uint8_t**)&VAL_BLOB(dval).s); break; case BSON_TYPE_UTF8: VAL_STRING(dval) = (char*)bson_iter_utf8 (piter, &i32tmp); break; case BSON_TYPE_OID: break; case BSON_TYPE_NULL: memset(dval, 0, sizeof(db_val_t)); /* Initialize the string pointers to a dummy empty * string so that we do not crash when the NULL flag * is set but the module does not check it properly */ VAL_STRING(dval) = dummy_string.s; VAL_STR(dval) = dummy_string; VAL_BLOB(dval) = dummy_string; VAL_TYPE(dval) = RES_TYPES(_r)[col]; VAL_NULL(dval) = 1; break; #if 0 case BSON_TYPE_EOD: case BSON_TYPE_DOCUMENT: case BSON_TYPE_ARRAY: case BSON_TYPE_UNDEFINED: case BSON_TYPE_REGEX: case BSON_TYPE_DBPOINTER: case BSON_TYPE_CODE: case BSON_TYPE_SYMBOL: case BSON_TYPE_CODEWSCOPE: case BSON_TYPE_MAXKEY: case BSON_TYPE_MINKEY: #endif default: LM_WARN("unhandled data type column (%.*s) type id (%d), " "use DB1_STRING as default\n", RES_NAMES(_r)[col]->len, RES_NAMES(_r)[col]->s, coltype); RES_TYPES(_r)[col] = DB1_STRING; break; } LM_DBG("RES_NAMES(%p)[%d]=[%.*s] (%d)\n", RES_NAMES(_r)[col], col, RES_NAMES(_r)[col]->len, RES_NAMES(_r)[col]->s, coltype); col++; } return 0; }
/* * Convert a row from result into db API representation */ int dbt_convert_row(db_con_t* _h, db_res_t* _res, db_row_t* _r) { int i; if ((!_h) || (!_r) || (!_res)) { #ifdef DBT_EXTRA_DEBUG LOG(L_ERR, "DBT:dbt_convert_row: Invalid parameter value\n"); #endif return -1; } ROW_VALUES(_r) = (db_val_t*)pkg_malloc(sizeof(db_val_t)*RES_COL_N(_res)); ROW_N(_r) = RES_COL_N(_res); if (!ROW_VALUES(_r)) { LOG(L_ERR, "DBT:dbt_convert_row: No memory left\n"); return -1; } for(i = 0; i < RES_COL_N(_res); i++) { (ROW_VALUES(_r)[i]).nul = DBT_CON_ROW(_h)->fields[i].nul; switch(RES_TYPES(_res)[i]) { case DB_INT: VAL_INT(&(ROW_VALUES(_r)[i])) = DBT_CON_ROW(_h)->fields[i].val.int_val; VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB_INT; break; case DB_DOUBLE: VAL_DOUBLE(&(ROW_VALUES(_r)[i])) = DBT_CON_ROW(_h)->fields[i].val.double_val; VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB_DOUBLE; break; case DB_STRING: VAL_STR(&(ROW_VALUES(_r)[i])).s = DBT_CON_ROW(_h)->fields[i].val.str_val.s; VAL_STR(&(ROW_VALUES(_r)[i])).len = DBT_CON_ROW(_h)->fields[i].val.str_val.len; VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB_STR; break; case DB_STR: VAL_STR(&(ROW_VALUES(_r)[i])).s = DBT_CON_ROW(_h)->fields[i].val.str_val.s; VAL_STR(&(ROW_VALUES(_r)[i])).len = DBT_CON_ROW(_h)->fields[i].val.str_val.len; VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB_STR; break; case DB_DATETIME: VAL_INT(&(ROW_VALUES(_r)[i])) = DBT_CON_ROW(_h)->fields[i].val.int_val; VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB_INT; break; case DB_BLOB: VAL_STR(&(ROW_VALUES(_r)[i])).s = DBT_CON_ROW(_h)->fields[i].val.str_val.s; VAL_STR(&(ROW_VALUES(_r)[i])).len = DBT_CON_ROW(_h)->fields[i].val.str_val.len; VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB_STR; break; case DB_BITMAP: VAL_INT(&(ROW_VALUES(_r)[i])) = DBT_CON_ROW(_h)->fields[i].val.bitmap_val; VAL_TYPE(&(ROW_VALUES(_r)[i])) = DB_INT; break; } } return 0; }