예제 #1
0
파일: bdb_base.c 프로젝트: 4N7HR4X/kamailio
/*
 * 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;
}
예제 #2
0
파일: db_res.c 프로젝트: SipCoSystems/hush
/*
 * 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;
}
예제 #3
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;
}
예제 #4
0
파일: sql_api.c 프로젝트: SipCoSystems/hush
int sql_do_pvquery(struct sip_msg *msg, sql_con_t *con, pv_elem_t *query,
		pvname_list_t *res)
{
	db1_res_t* db_res = NULL;
	pvname_list_t* pv;
	str sv;
	int i, j;

	if(msg==NULL || query==NULL || res==NULL)
	{
		LM_ERR("bad parameters\n");
		return -1;
	}
	if(pv_printf_s(msg, query, &sv)!=0)
	{
		LM_ERR("cannot print the sql query\n");
		return -1;
	}

	if(con->dbf.raw_query(con->dbh, &sv, &db_res)!=0)
	{
		LM_ERR("cannot do the query\n");
		return -1;
	}

	if(db_res==NULL || RES_ROW_N(db_res)<=0 || RES_COL_N(db_res)<=0)
	{
		LM_DBG("no result after query\n");
		con->dbf.free_result(con->dbh, db_res);
		return 2;
	}

	for(i=RES_ROW_N(db_res)-1; i>=0; i--)
	{
		pv = res;
		for(j=0; j<RES_COL_N(db_res); j++)
		{
			if (pv == NULL) {
				LM_ERR("Missing pv spec for column %d\n", j+1);
				goto error;
			}
			if (db_val2pv_spec(msg, &RES_ROWS(db_res)[i].values[j], &pv->sname) != 0) {
				LM_ERR("Failed to convert value for column %.*s (row %d)\n",
				       RES_NAMES(db_res)[j]->len, RES_NAMES(db_res)[j]->s, i);
				goto error;
			}
			pv = pv->next;
		}
	}

	con->dbf.free_result(con->dbh, db_res);
	return 1;

error:
	con->dbf.free_result(con->dbh, db_res);
	return -1;
}
예제 #5
0
/*
 * Generate AVPs from the database result
 */
static int generate_avps(struct sip_msg* msg, db1_res_t* db_res)
{
	pv_elem_t *cred;
	int i;

	for (cred=credentials, i=1; cred; cred=cred->next, i++) {
		if (db_val2pv_spec(msg, &RES_ROWS(db_res)[0].values[i], cred->spec) != 0) {
			LM_ERR("Failed to convert value for column %.*s\n",
					RES_NAMES(db_res)[i]->len, RES_NAMES(db_res)[i]->s);
			return -1;
		}
	}
	return 0;
}
예제 #6
0
파일: db_res.c 프로젝트: SipCoSystems/hush
/*
 * 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;
}
예제 #7
0
파일: db_res.c 프로젝트: vladpaiu/opensips
/*
 * 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;
}
예제 #8
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;
}
예제 #9
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;
}
예제 #10
0
파일: bdb_res.c 프로젝트: KISSMonX/opensips
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;
}
예제 #11
0
파일: dbt_api.c 프로젝트: OpenSIPS/opensips
/*
 * 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;
}
예제 #12
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;
}
예제 #13
0
/*
 * Release a result set from memory
 */
int db_oracle_free_result(db_con_t* _h, db_res_t* _r)
{
	ub4 i;

	if (!_h || !_r) {
		LM_ERR("invalid parameter value\n");
		return -1;
	}

	if (RES_NAMES(_r))
		for (i=0; i < RES_COL_N(_r); ++i)
			if (RES_NAMES(_r)[i]->s)
				pkg_free(RES_NAMES(_r)[i]->s);

	if (db_free_result(_r) < 0)
	{
		LM_ERR("failed to free result structure\n");
		return -1;
	}
	return 0;
}
예제 #14
0
static int print_res(db_res_t* _r)
{
	int i, j;

	for(i = 0; i < RES_COL_N(_r); i++) {
		printf("%s ", RES_NAMES(_r)[i]);
	}
	printf("\n");

	for(i = 0; i < RES_ROW_N(_r); i++) {
		for(j = 0; j < RES_COL_N(_r); j++) {
			if (RES_ROWS(_r)[i].values[j].nul == TRUE) {
				printf("NULL ");
				continue;
			}
			switch(RES_ROWS(_r)[i].values[j].type) {
			case DB_INT:
				printf("%d ", RES_ROWS(_r)[i].values[j].val.int_val);
				break;
			case DB_DOUBLE:
				printf("%f ", RES_ROWS(_r)[i].values[j].val.double_val);
				break;
			case DB_DATETIME:
				printf("%s ", ctime(&(RES_ROWS(_r)[i].values[j].val.time_val)));
				break;
			case DB_STRING:
				printf("%s ", RES_ROWS(_r)[i].values[j].val.string_val);
				break;
			case DB_STR:
				printf("%.*s ", 
				       RES_ROWS(_r)[i].values[j].val.str_val.len,
				       RES_ROWS(_r)[i].values[j].val.str_val.s);
				break;

			case DB_BLOB:
				printf("%.*s ",
				       RES_ROWS(_r)[i].values[j].val.blob_val.len,
				       RES_ROWS(_r)[i].values[j].val.blob_val.s);
				break;

			case DB_BITMAP:
				printf("%d ", RES_ROWS(_r)[i].values[j].val.bitmap_val);
				break;
			}
			
		}
		printf("\n");
	}
			
	return TRUE;
}
예제 #15
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;
}
예제 #16
0
/*
 * Release a result set from memory
 */
int perlvdb_db_free_result(db_con_t* _h, db_res_t* _r) {
	int i,j;
	SV* temp;
	/* free result set
	 * use the order of allocation
	 * first free values
	*/
	if(_r){
		/* for each row */
		for(i=0; i < RES_ROW_N(_r); i++){
			/* for each column in row i */
			for(j=0; j < RES_ROWS(_r)[i].n; j++){
                                switch ( (RES_ROWS(_r)[i].values)[j].type ) { /* the type of a value j in row i */
                                        case DB_STRING:
                                        case DB_STR:
						pkg_free((RES_ROWS(_r)[i].values)[j].val.str_val.s);
                                                break;
                                        case DB_BLOB:
                                                pkg_free((RES_ROWS(_r)[i].values)[j].val.blob_val.s) ;
                                                break;
					case DB_INT:
					case DB_BIGINT:
					case DB_DOUBLE:
					case DB_BITMAP:
					case DB_DATETIME:
						break;
                                }
			} /* for each column in row i*/
		} /* for each row */

		for(i=0; i< RES_COL_N(_r); i++){
			pkg_free(RES_NAMES(_r)[i]->s);
		}
		db_free_result(_r);
	}
	return 0;
}
예제 #17
0
파일: db_res.c 프로젝트: vladpaiu/opensips
/*
 * 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;
}
예제 #18
0
파일: km_res.c 프로젝트: 4N7HR4X/kamailio
/*!
 * \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;
}
예제 #19
0
파일: sql_api.c 프로젝트: SipCoSystems/hush
int sql_do_query(sql_con_t *con, str *query, sql_result_t *res)
{
	db1_res_t* db_res = NULL;
	int i, j;
	str sv;

	if(res) sql_reset_result(res);

	if(query==NULL)
	{
		LM_ERR("bad parameters\n");
		return -1;
	}
	if(con->dbf.raw_query(con->dbh, query, &db_res)!=0)
	{
		LM_ERR("cannot do the query [%.*s]\n",
				(query->len>32)?32:query->len, query->s);
		return -1;
	}

	if(db_res==NULL || RES_ROW_N(db_res)<=0 || RES_COL_N(db_res)<=0)
	{
		LM_DBG("no result after query\n");
		con->dbf.free_result(con->dbh, db_res);
		return 2;
	}
	if(!res)
	{
		LM_DBG("no sqlresult parameter, ignoring result from query\n");
		con->dbf.free_result(con->dbh, db_res);
		return 3;
	}

	res->ncols = RES_COL_N(db_res);
	res->nrows = RES_ROW_N(db_res);
	LM_DBG("rows [%d] cols [%d]\n", res->nrows, res->ncols);

	res->cols = (sql_col_t*)pkg_malloc(res->ncols*sizeof(sql_col_t));
	if(res->cols==NULL)
	{
		res->ncols = 0;
		res->nrows = 0;
		LM_ERR("no more memory\n");
		return -1;
	}
	memset(res->cols, 0, res->ncols*sizeof(sql_col_t));
	for(i=0; i<res->ncols; i++)
	{
		res->cols[i].name.len = (RES_NAMES(db_res)[i])->len;
		res->cols[i].name.s = (char*)pkg_malloc((res->cols[i].name.len+1)
				*sizeof(char));
		if(res->cols[i].name.s==NULL)
		{
			LM_ERR("no more memory\n");
			goto error;
		}
		memcpy(res->cols[i].name.s, RES_NAMES(db_res)[i]->s,
				res->cols[i].name.len);
		res->cols[i].name.s[res->cols[i].name.len]='\0';
		res->cols[i].colid = core_case_hash(&res->cols[i].name, 0, 0);
	}

	res->vals = (sql_val_t**)pkg_malloc(res->nrows*sizeof(sql_val_t*));
	if(res->vals==NULL)
	{
		LM_ERR("no more memory\n");
		goto error;
	}
	memset(res->vals, 0, res->nrows*sizeof(sql_val_t*));
	for(i=0; i<res->nrows; i++)
	{
		res->vals[i] = (sql_val_t*)pkg_malloc(res->ncols*sizeof(sql_val_t));
		if(res->vals[i]==NULL)
		{
			LM_ERR("no more memory\n");
			goto error;
		}
		memset(res->vals[i], 0, res->ncols*sizeof(sql_val_t));
		for(j=0; j<res->ncols; j++)
		{
			if(RES_ROWS(db_res)[i].values[j].nul)
			{
				res->vals[i][j].flags = PV_VAL_NULL;
				continue;
			}
			sv.s = NULL;
			sv.len = 0;
			switch(RES_ROWS(db_res)[i].values[j].type)
			{
				case DB1_STRING:
					res->vals[i][j].flags = PV_VAL_STR;
					sv.s=
						(char*)RES_ROWS(db_res)[i].values[j].val.string_val;
					sv.len=strlen(sv.s);
				break;
				case DB1_STR:
					res->vals[i][j].flags = PV_VAL_STR;
					sv.len=
						RES_ROWS(db_res)[i].values[j].val.str_val.len;
					sv.s=
						(char*)RES_ROWS(db_res)[i].values[j].val.str_val.s;
				break;
				case DB1_BLOB:
					res->vals[i][j].flags = PV_VAL_STR;
					sv.len=
						RES_ROWS(db_res)[i].values[j].val.blob_val.len;
					sv.s=
						(char*)RES_ROWS(db_res)[i].values[j].val.blob_val.s;
				break;
				case DB1_INT:
					res->vals[i][j].flags = PV_VAL_INT;
					res->vals[i][j].value.n
						= (int)RES_ROWS(db_res)[i].values[j].val.int_val;
				break;
				case DB1_DATETIME:
					res->vals[i][j].flags = PV_VAL_INT;
					res->vals[i][j].value.n
						= (int)RES_ROWS(db_res)[i].values[j].val.time_val;
				break;
				case DB1_BITMAP:
					res->vals[i][j].flags = PV_VAL_INT;
					res->vals[i][j].value.n
						= (int)RES_ROWS(db_res)[i].values[j].val.bitmap_val;
				break;
				case DB1_BIGINT:
					res->vals[i][j].flags = PV_VAL_STR;
					res->vals[i][j].value.s.len = 21*sizeof(char);
					res->vals[i][j].value.s.s
						= (char*)pkg_malloc(res->vals[i][j].value.s.len);
					if(res->vals[i][j].value.s.s==NULL)
					{
						LM_ERR("no more memory\n");
						goto error;
					}
					db_longlong2str(RES_ROWS(db_res)[i].values[j].val.ll_val,
							res->vals[i][j].value.s.s, &res->vals[i][j].value.s.len);
				break;
				default:
					res->vals[i][j].flags = PV_VAL_NULL;
			}
			if(res->vals[i][j].flags == PV_VAL_STR && sv.s)
			{
				if(sv.len<=0)
				{
					res->vals[i][j].value.s.s = _sql_empty_buf;
					res->vals[i][j].value.s.len = 0;
					continue;
				}
				res->vals[i][j].value.s.s 
					= (char*)pkg_malloc(sv.len*sizeof(char));
				if(res->vals[i][j].value.s.s==NULL)
				{
					LM_ERR("no more memory\n");
					goto error;
				}
				memcpy(res->vals[i][j].value.s.s, sv.s, sv.len);
				res->vals[i][j].value.s.len = sv.len;
			}
		}
	}

	con->dbf.free_result(con->dbh, db_res);
	return 1;

error:
	con->dbf.free_result(con->dbh, db_res);
	sql_reset_result(res);
	return -1;
}
예제 #20
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;
}
예제 #21
0
파일: res.c 프로젝트: KISSMonX/opensips
/**
 * 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;
}
예제 #22
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;
}
예제 #23
0
파일: res.c 프로젝트: billyyh/kamailio
/*
 * Get and convert columns from a result
 */
int db_unixodbc_get_columns(const db1_con_t* _h, db1_res_t* _r)
{
	int col;
	SQLSMALLINT cols; /* because gcc don't like RES_COL_N */

	if ((!_h) || (!_r)) {
		LM_ERR("invalid parameter\n");
		return -1;
	}

	/* Save number of columns in the result structure */
	SQLNumResultCols(CON_RESULT(_h), &cols);
	RES_COL_N(_r) = cols;
	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(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]);

		char columnname[80];
		SQLRETURN ret;
		SQLSMALLINT namelength, datatype, decimaldigits, nullable;
		SQLULEN columnsize;

		ret = SQLDescribeCol(CON_RESULT(_h), col + 1, (SQLCHAR *)columnname, 80,
			&namelength, &datatype, &columnsize, &decimaldigits, &nullable);
		if(!SQL_SUCCEEDED(ret)) {
			LM_ERR("SQLDescribeCol failed: %d\n", ret);
			db_unixodbc_extract_error("SQLExecDirect", CON_RESULT(_h), SQL_HANDLE_STMT,
				NULL);
			// FIXME should we fail here completly?
		}
		/* The pointer that is here returned is part of the result structure. */
		RES_NAMES(_r)[col]->s = columnname;
		RES_NAMES(_r)[col]->len = namelength;

		LM_DBG("RES_NAMES(%p)[%d]=[%.*s]\n", RES_NAMES(_r)[col], col,
				RES_NAMES(_r)[col]->len, RES_NAMES(_r)[col]->s);

		switch(datatype)
		{
			case SQL_SMALLINT:
			case SQL_INTEGER:
			case SQL_TINYINT:
			case SQL_DECIMAL:
			case SQL_NUMERIC:
				LM_DBG("use DB1_INT result type\n");
				RES_TYPES(_r)[col] = DB1_INT;
				break;

			case SQL_BIGINT:
				LM_DBG("use DB1_BIGINT result type\n");
				RES_TYPES(_r)[col] = DB1_BIGINT;
				break;

			case SQL_REAL:
			case SQL_FLOAT:
			case SQL_DOUBLE:
				LM_DBG("use DB1_DOUBLE result type\n");
				RES_TYPES(_r)[col] = DB1_DOUBLE;
				break;

			case SQL_TYPE_TIMESTAMP:
			case SQL_DATE:
			case SQL_TIME:
			case SQL_TIMESTAMP:
			case SQL_TYPE_DATE:
			case SQL_TYPE_TIME:
				LM_DBG("use DB1_DATETIME result type\n");
				RES_TYPES(_r)[col] = DB1_DATETIME;
				break;

			case SQL_CHAR:
			case SQL_VARCHAR:
			case SQL_WCHAR:
			case SQL_WVARCHAR:
				LM_DBG("use DB1_STRING result type\n");
				RES_TYPES(_r)[col] = DB1_STRING;
				break;

			case SQL_BINARY:
			case SQL_VARBINARY:
			case SQL_LONGVARBINARY:
			case SQL_BIT:
			case SQL_LONGVARCHAR:
			case SQL_WLONGVARCHAR:
				LM_DBG("use DB1_BLOB result type\n");
				RES_TYPES(_r)[col] = DB1_BLOB;
				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, datatype);
				RES_TYPES(_r)[col] = DB1_STRING;
				break;
		}
	}
	return 0;
}
예제 #24
0
파일: res.c 프로젝트: mtulio/mtulio
/**
 * Get and convert columns from a result set
 */
int db_postgres_get_columns(const db_con_t* _h, db_res_t* _r)
{
	int col, datatype;

	if (!_h || !_r)  {
		LM_ERR("invalid parameter value\n");
		return -1;
	}

	/* Get the number of rows (tuples) in the query result. */
	RES_ROW_N(_r) = PQntuples(CON_RESULT(_h));

	/* Get the number of columns (fields) in each row of the query result. */
	RES_COL_N(_r) = PQnfields(CON_RESULT(_h));

	if (!RES_COL_N(_r)) {
		LM_DBG("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 each column both the name and the OID number of the 
	 * data type are saved. */
	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 = PQfname(CON_RESULT(_h), col);
		RES_NAMES(_r)[col]->len = strlen(PQfname(CON_RESULT(_h), col));

		LM_DBG("RES_NAMES(%p)[%d]=[%.*s]\n", RES_NAMES(_r)[col], col,
				RES_NAMES(_r)[col]->len, RES_NAMES(_r)[col]->s);

		/* get the datatype of the column */
		switch(datatype = PQftype(CON_RESULT(_h),col))
		{
			case INT2OID:
			case INT4OID:
			case INT8OID:
				LM_DBG("use DB_INT result type\n");
				RES_TYPES(_r)[col] = DB_INT;
			break;

			case FLOAT4OID:
			case FLOAT8OID:
			case NUMERICOID:
				LM_DBG("use DB_DOUBLE result type\n");
				RES_TYPES(_r)[col] = DB_DOUBLE;
			break;

			case DATEOID:
			case TIMESTAMPOID:
			case TIMESTAMPTZOID:
				LM_DBG("use DB_DATETIME result type\n");
				RES_TYPES(_r)[col] = DB_DATETIME;
			break;

			case BOOLOID:
			case CHAROID:
			case VARCHAROID:
			case BPCHAROID:
				LM_DBG("use DB_STRING result type\n");
				RES_TYPES(_r)[col] = DB_STRING;
			break;

			case TEXTOID:
			case BYTEAOID:
				LM_DBG("use DB_BLOB result type\n");
				RES_TYPES(_r)[col] = DB_BLOB;
			break;

			case BITOID:
			case VARBITOID:
				LM_DBG("use DB_BITMAP result type\n");
				RES_TYPES(_r)[col] = DB_BITMAP;
			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, datatype);
				RES_TYPES(_r)[col] = DB_STRING;
			break;
		}
	}
	return 0;
}
예제 #25
0
int fetch_credentials(sip_msg_t *msg, str *user, str* domain, str *table, int flags)
{
	pv_elem_t *cred;
	db_key_t keys[2];
	db_val_t vals[2];
	db_key_t *col;
	db1_res_t *res = NULL;

	int n, nc;

	if(flags&AUTH_DB_SUBS_SKIP_CREDENTIALS) {
		nc = 1;
	} else {
		nc = credentials_n;
	}
	col = pkg_malloc(sizeof(*col) * (nc+1));
	if (col == NULL) {
		LM_ERR("no more pkg memory\n");
		return -1;
	}

	keys[0] = &user_column;
	keys[1] = &domain_column;

	if(flags&AUTH_DB_SUBS_SKIP_CREDENTIALS) {
		col[0] = &user_column;
	} else {
		for (n = 0, cred=credentials; cred ; n++, cred=cred->next) {
			col[n] = &cred->text;
		}
	}

	VAL_TYPE(vals) = VAL_TYPE(vals + 1) = DB1_STR;
	VAL_NULL(vals) = VAL_NULL(vals + 1) = 0;

	n = 1;
	VAL_STR(vals) = *user;

	if (domain && domain->len) {
		VAL_STR(vals + 1) = *domain;
		n = 2;
	}

	if (auth_dbf.use_table(auth_db_handle, table) < 0) {
		LM_ERR("failed to use_table\n");
		pkg_free(col);
		return -1;
	}

	if (auth_dbf.query(auth_db_handle, keys, 0, vals, col, n, nc, 0, &res) < 0) {
		LM_ERR("failed to query database\n");
		pkg_free(col);
		if(res)
			auth_dbf.free_result(auth_db_handle, res);
		return -1;
	}
	pkg_free(col);
	if (RES_ROW_N(res) == 0) {
		if(res)
			auth_dbf.free_result(auth_db_handle, res);
		LM_DBG("no result for user \'%.*s%s%.*s\' in [%.*s]\n",
				user->len, user->s, (n==2)?"@":"",
				(n==2)?domain->len:0, (n==2)?domain->s:"",
				table->len, table->s);
		return -2;
	}
	if(flags&AUTH_DB_SUBS_SKIP_CREDENTIALS) {
		/* there is a result and flag to skip loading credentials is set */
		goto done;
	}
	for (cred=credentials, n=0; cred; cred=cred->next, n++) {
		if (db_val2pv_spec(msg, &RES_ROWS(res)[0].values[n], cred->spec) != 0) {
			if(res)
				auth_dbf.free_result(auth_db_handle, res);
			LM_ERR("Failed to convert value for column %.*s\n",
					RES_NAMES(res)[n]->len, RES_NAMES(res)[n]->s);
			return -3;
		}
	}

done:
	if(res)
		auth_dbf.free_result(auth_db_handle, res);
	return 0;
}
예제 #26
0
파일: sql_api.c 프로젝트: SipCoSystems/hush
int sql_exec_xquery(struct sip_msg *msg, sql_con_t *con, str *query,
		str *xavp)
{
	db1_res_t* db_res = NULL;
	sr_xavp_t *row = NULL;
	sr_xval_t val;
	int i, j;

	if(msg==NULL || query==NULL || xavp==NULL)
	{
		LM_ERR("bad parameters\n");
		return -1;
	}

	if(con->dbf.raw_query(con->dbh, query, &db_res)!=0)
	{
		LM_ERR("cannot do the query\n");
		return -1;
	}

	if(db_res==NULL || RES_ROW_N(db_res)<=0 || RES_COL_N(db_res)<=0)
	{
		LM_DBG("no result after query\n");
		con->dbf.free_result(con->dbh, db_res);
		return 2;
	}

	for(i=RES_ROW_N(db_res)-1; i>=0; i--)
	{
		row = NULL;
		for(j=RES_COL_N(db_res)-1; j>=0; j--)
		{
			if(RES_ROWS(db_res)[i].values[j].nul)
			{
				val.type = SR_XTYPE_NULL;
			} else
			{
				switch(RES_ROWS(db_res)[i].values[j].type)
				{
					case DB1_STRING:
						val.type = SR_XTYPE_STR;
						val.v.s.s=
							(char*)RES_ROWS(db_res)[i].values[j].val.string_val;
						val.v.s.len=strlen(val.v.s.s);
					break;
					case DB1_STR:
						val.type = SR_XTYPE_STR;
						val.v.s.len=
							RES_ROWS(db_res)[i].values[j].val.str_val.len;
						val.v.s.s=
							(char*)RES_ROWS(db_res)[i].values[j].val.str_val.s;
					break;
					case DB1_BLOB:
						val.type = SR_XTYPE_STR;
						val.v.s.len=
							RES_ROWS(db_res)[i].values[j].val.blob_val.len;
						val.v.s.s=
							(char*)RES_ROWS(db_res)[i].values[j].val.blob_val.s;
					break;
					case DB1_INT:
						val.type = SR_XTYPE_INT;
						val.v.i
							= (int)RES_ROWS(db_res)[i].values[j].val.int_val;
					break;
					case DB1_DATETIME:
						val.type = SR_XTYPE_INT;
						val.v.i
							= (int)RES_ROWS(db_res)[i].values[j].val.time_val;
					break;
					case DB1_BITMAP:
						val.type = SR_XTYPE_INT;
						val.v.i
							= (int)RES_ROWS(db_res)[i].values[j].val.bitmap_val;
					break;
					case DB1_BIGINT:
						val.type = SR_XTYPE_LLONG;
						val.v.ll
							= RES_ROWS(db_res)[i].values[j].val.ll_val;
					break;
					default:
						val.type = SR_XTYPE_NULL;
				}
			}
			/* Add column to current row, under the column's name */
			LM_DBG("Adding column: %.*s\n", RES_NAMES(db_res)[j]->len, RES_NAMES(db_res)[j]->s);
			xavp_add_value(RES_NAMES(db_res)[j], &val, &row);
		}
		/* Add row to result xavp */
		val.type = SR_XTYPE_XAVP;
		val.v.xavp = row;
		LM_DBG("Adding row\n");
		xavp_add_value(xavp, &val, NULL);
	}

	con->dbf.free_result(con->dbh, db_res);
	return 1;
}
예제 #27
0
파일: res.c 프로젝트: mtulio/mtulio
/**
 * Convert rows from PostgreSQL to db API representation
 */
int db_postgres_convert_rows(const db_con_t* _h, db_res_t* _r)
{
	char **row_buf, *s;
	int row, col, len;

	if (!_h || !_r)  {
		LM_ERR("invalid parameter\n");
		return -1;
	}

	if (!RES_ROW_N(_r)) {
		LM_DBG("no rows returned from the query\n");
		RES_ROWS(_r) = 0;
		return 0;
	}
	/* Allocate an array of pointers per column to holds the string 
	 * representation */
	len = sizeof(char *) * RES_COL_N(_r);
	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(_r), len, row_buf);
	memset(row_buf, 0, len);

	if (db_allocate_rows( _r, RES_ROW_N(_r))!=0) {
		LM_ERR("no private memory left\n");
		return -2;
	}

	for(row=RES_LAST_ROW(_r); row<(RES_LAST_ROW(_r)+RES_ROW_N(_r)) ; row++) {
		for(col = 0; col < RES_COL_N(_r); col++) {
			/*
			 * The row data pointer returned by PQgetvalue points to 
			 * storage that is part of the PGresult structure. One should 
			 * not modify the data it points to, and one must explicitly 
			 * copy the data into other storage if it is to be used past 
			 * the lifetime of the PGresult structure itself.
			 */
			
			/*
			 * There's a weird bug (or just weird behavior) in the postgres
			 * API - if the result is a BLOB (like 'text') and is with 
			 * zero length, we get a pointer to nowhere, which is not 
			 * null-terminated. The fix for this is to check what does the 
			 * DB think about the length and use that as a correction.
			 */
			if (PQgetisnull(CON_RESULT(_h), row, col) == 0) {
				/* not null value */
				if ( (len=PQgetlength(CON_RESULT(_h), row, col))==0 ) {
					s="";
					LM_DBG("PQgetvalue(%p,%d,%d)=[], zero len\n", _h, row,col);
				} else {
					s = PQgetvalue(CON_RESULT(_h), row, col);
					LM_DBG("PQgetvalue(%p,%d,%d)=[%.*s]\n", _h, row,col,len,s);
				}
			
				row_buf[col] = pkg_malloc(len+1);
				if (!row_buf[col]) {
					LM_ERR("no private memory left\n");
					return -1;
				}
				memset(row_buf[col], 0, len+1);
				LM_DBG("allocated %d bytes for row_buf[%d] at %p\n",
					len, col, row_buf[col]);

				strncpy(row_buf[col], s, len);
				LM_DBG("[%d][%d] Column[%.*s]=[%s]\n",
					row, col, RES_NAMES(_r)[col]->len,
					RES_NAMES(_r)[col]->s, row_buf[col]);
			}
		}

		/* ASSERT: row_buf contains an entire row in strings */
		if(db_postgres_convert_row(_h, _r, &(RES_ROWS(_r)[row - RES_LAST_ROW(_r)]), row_buf)<0){
			LM_ERR("failed to convert row #%d\n",  row);
			RES_ROW_N(_r) = row - RES_LAST_ROW(_r);
			for (col = 0; col < RES_COL_N(_r); col++) {
				LM_DBG("freeing row_buf[%d] at %p\n", col, row_buf[col]);
				if (row_buf[col] &&  !row_buf[col][0]) pkg_free(row_buf[col]);
			}
			LM_DBG("freeing row buffer at %p\n", row_buf);
			pkg_free(row_buf);
			return -4;
		}
		/*
		 * pkg_free() must be done for the above allocations now that the row
		 * has been converted. During pg_convert_row (and subsequent pg_str2val)
		 * processing, data types that don't need to be converted (namely STRINGS
		 * and STR) have their addresses saved. These data types should not have
		 * their pkg_malloc() allocations freed here because they are still
		 * needed.  However, some data types (ex: INT, DOUBLE) should have their
		 * pkg_malloc() allocations freed because during the conversion process,
		 * their converted values are saved in the union portion of the db_val_t
		 * structure. BLOB will be copied during PQunescape in str2val, thus it
		 * has to be freed here AND in pg_free_row().
		 *
		 * Warning: when the converted row is no longer needed, the data types
		 * whose addresses were saved in the db_val_t structure must be freed
		 * or a memory leak will happen. This processing should happen in the
		 * pg_free_row() subroutine. The caller of this routine should ensure
		 * that pg_free_rows(), pg_free_row() or pg_free_result() is eventually
		 * called.
		 */
		for (col = 0; col < RES_COL_N(_r); col++) {
			switch (RES_TYPES(_r)[col]) {
				case DB_STRING:
				case DB_STR:
					break;
				default:
					LM_DBG("freeing row_buf[%d] at %p\n", col, row_buf[col]);
					if (row_buf[col]) pkg_free(row_buf[col]);
			}
			/*
			 * The following housekeeping may not be technically required, but it
			 * is a good practice to NULL pointer fields that are no longer valid.
			 * Note that DB_STRING fields have not been pkg_free(). NULLing DB_STRING
			 * fields would normally not be good to do because a memory leak would
			 * occur.  However, the pg_convert_row() routine  has saved the DB_STRING
			 * pointer in the db_val_t structure.  The db_val_t structure will 
			 * eventually be used to pkg_free() the DB_STRING storage.
			 */
			row_buf[col] = (char *)NULL;
		}
	}

	LM_DBG("freeing row buffer at %p\n", row_buf);
	pkg_free(row_buf);
	row_buf = NULL;
	return 0;
}
예제 #28
0
/*!
 * \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;
}
예제 #29
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;
}
예제 #30
0
파일: res.c 프로젝트: AndreiPlesa/opensips
/*
 * 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*)&param, 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;
}