Beispiel #1
0
/*
 * Release memory used by a result structure
 */
int db_free_result(db1_res_t* _r)
{
	if (!_r)
	{
		LM_ERR("invalid parameter\n");
		return -1;
	}

	db_free_columns(_r);
	db_free_rows(_r);
	LM_DBG("freeing result set at %p\n", _r);
	pkg_free(_r);
	_r = NULL;
	return 0;
}
Beispiel #2
0
/*
 * Fill the structure with data from database
 */
static int dbt_convert_result(db1_res_t* _r, dbt_result_p _dres)
{
	if (!_r || !_dres) {
		LM_ERR("invalid parameter\n");
		return -1;
	}
	if (dbt_get_columns(_r, _dres) < 0) {
		LM_ERR("failed to get column names\n");
		return -2;
	}

	if (dbt_convert_rows(_r, _dres) < 0) {
		LM_ERR("failed to convert rows\n");
		db_free_columns(_r);
		return -3;
	}
	return 0;
}
Beispiel #3
0
/*!
 * \brief Fill the result structure with data from database
 * \param _h database connection
 * \param _r database result
 * \return 0 on success, negative on failure
 */
int db_mysql_convert_result(const db1_con_t* _h, db1_res_t* _r)
{
	if ((!_h) || (!_r)) {
		LM_ERR("invalid parameter\n");
		return -1;
	}

	if (db_mysql_get_columns(_h, _r) < 0) {
		LM_ERR("error while getting column names\n");
		return -2;
	}

	if (db_mysql_convert_rows(_h, _r) < 0) {
		LM_ERR("error while converting rows\n");
		db_free_columns(_r);
		return -3;
	}
	return 0;
}
Beispiel #4
0
/*
 * Fill the structure with data from database
 */
int db_unixodbc_convert_result(const db1_con_t* _h, db1_res_t* _r)
{
	if (!_h || !_r) {
		LM_ERR("invalid parameter\n");
		return -1;
	}

	if (db_unixodbc_get_columns(_h, _r) < 0) {
		LM_ERR("getting column names failed\n");
		return -2;
	}

	if (db_unixodbc_convert_rows(_h, _r) < 0) {
		LM_ERR("converting rows failed\n");
		db_free_columns(_r);
		return -3;
	}
	return 0;
}
Beispiel #5
0
/**
 * Fill the result structure with data from the query
 */
int db_postgres_convert_result(const db_con_t* _h, db_res_t* _r)
{
	if (!_h || !_r)  {
		LM_ERR("invalid parameter value\n");
		return -1;
	}

	if (db_postgres_get_columns(_h, _r) < 0) {
		LM_ERR("failed to get column names\n");
		return -2;
	}

	if (db_postgres_convert_rows(_h, _r) < 0) {
		LM_ERR("failed to convert rows\n");
		db_free_columns(_r);
		return -3;
	}
	return 0;
}
Beispiel #6
0
db_res_t * new_full_db_res(int rows, int cols)
{
	db_res_t * res;
	int i;

	res = db_new_result();

	if( res == NULL)
	{
		LM_ERR("Error allocating db result\n");
		return NULL;
	}

	if( db_allocate_columns(res,cols) < 0)
	{
		LM_ERR("Error allocating db result columns\n");
		pkg_free(res);
		return NULL;
	}
	res->col.n = cols;

	if( db_allocate_rows(res,rows) < 0 )
	{
		LM_ERR("Error allocating db result rows\n");
		db_free_columns( res );
		pkg_free(res);
		return NULL;
	}

	res->n = rows;
	res->res_rows = rows;
	res->last_row = rows;


	for( i=0;i<rows;i++)
		res->rows[i].n = cols;

	return res;
}
Beispiel #7
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;
}
Beispiel #8
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;
}
Beispiel #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, dbcassa_table_p tbc)
{
	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);

		/* search the column in table schema to get the type */
		dbcassa_column_p colp = cassa_search_col(tbc, (db_key_t) RES_NAMES(_r)[col]);
		if(!colp) {
			LM_ERR("No column with name [%.*s] found\n", RES_NAMES(_r)[col]->len, RES_NAMES(_r)[col]->s);
			RES_COL_N(_r) = col;
			db_free_columns(_r);
			return -4;
		}

		RES_TYPES(_r)[col] = colp->type;

		LM_DBG("Column with name [%.*s] found: %d\n", RES_NAMES(_r)[col]->len, RES_NAMES(_r)[col]->s, colp->type);
		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;
}
Beispiel #10
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;
}
Beispiel #11
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*)&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;
}
Beispiel #12
0
/*!
 * \brief Gets a partial result set, fetch rows from a result
 *
 * Gets a partial result set, fetch a number of rows from a databae result.
 * This function initialize the given result structure on the first run, and
 * fetches the nrows number of rows. On subsequenting runs, it uses the
 * existing result and fetches more rows, until it reaches the end of the
 * result set. Because of this the result needs to be null in the first
 * invocation of the function. If the number of wanted rows is zero, the
 * function returns anything with a result of zero.
 * \param _h structure representing the database connection
 * \param _r pointer to a structure representing the result
 * \param nrows number of fetched rows
 * \return return zero on success, negative value on failure
 */
int db_unixodbc_fetch_result(const db1_con_t* _h, db1_res_t** _r, const int nrows)
{
	int row_n = 0, i = 0, ret = 0, len;
	SQLSMALLINT columns;
	list* rows = NULL;
	list* rowstart = NULL;
	strn* temp_row = NULL;

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

	/* exit if the fetch count is zero */
	if (nrows == 0) {
		if (*_r)
			db_free_result(*_r);
		*_r = 0;
		return 0;
	}

	/* On the first fetch for a query, allocate structures and get columns */
	if(*_r == NULL) {
		/* Allocate a new result structure */
		*_r = db_new_result();
		LM_DBG("just allocated a new db result structure");

		if (*_r == NULL) {
			LM_ERR("no memory left\n");
			return -2;
		}

		/* Get columns names and count */
		if (db_unixodbc_get_columns(_h, *_r) < 0) {
			LM_ERR("getting column names failed\n");
			db_free_columns(*_r);
			return -2;
		}

	/* On subsequent fetch attempts, reuse already allocated structures */
	} else {
		LM_DBG("db result structure already exist, reusing\n");
		/* free old rows */
		if(RES_ROWS(*_r) != NULL)
			db_free_rows(*_r);
		RES_ROWS(*_r) = 0;
		RES_ROW_N(*_r) = 0;
	}

	SQLNumResultCols(CON_RESULT(_h), (SQLSMALLINT *)&columns);

	/* Now fetch nrows at most */
	len = sizeof(db_row_t) * nrows;
	RES_ROWS(*_r) = (struct db_row*)pkg_malloc(len);
	if (!RES_ROWS(*_r)) {
		LM_ERR("no memory left\n");
		return -5;
	}
	LM_DBG("allocated %d bytes for RES_ROWS at %p\n", len, RES_ROWS(*_r));

	LM_DBG("Now fetching %i rows at most\n", nrows);
	while(SQL_SUCCEEDED(ret = SQLFetch(CON_RESULT(_h)))) {
		/* Allocate a temporary row */
		temp_row = db_unixodbc_new_cellrow(columns);
		if (!temp_row) {
			LM_ERR("no private memory left\n");
			pkg_free(RES_ROWS(*_r));
			pkg_free(*_r);
			*_r = 0;
			return -1;
		}

		LM_DBG("fetching %d columns for row %d...\n",columns, row_n);
		for(i=0; i < columns; i++) {
			LM_DBG("fetching column %d\n",i);
			if (!db_unixodbc_load_cell(_h, i+1, temp_row + i, RES_TYPES(*_r)[i])) {
			    pkg_free(RES_ROWS(*_r));
			    db_unixodbc_free_cellrow(columns, temp_row);
			    pkg_free(*_r);
			    *_r = 0;
			    return -5;
			}
		}

		LM_DBG("got temp_row at %p\n", temp_row);

		if (db_unixodbc_list_insert(&rowstart, &rows, columns, temp_row) < 0) {
			LM_ERR("SQL result row insert failed\n");
			pkg_free(RES_ROWS(*_r));
			db_unixodbc_free_cellrow(columns, temp_row);
			pkg_free(*_r);
			*_r = 0;
			return -5;
		}

		/* Free temporary row data */
		LM_DBG("freeing temp_row at %p\n", temp_row);
		db_unixodbc_free_cellrow(columns, temp_row);
		temp_row = NULL;

		row_n++;
		if (row_n == nrows) {
			break;
		}
	}

	CON_ROW(_h) = NULL;

	RES_ROW_N(*_r) = row_n;
	if (!row_n) {
		LM_DBG("no more rows to process for db fetch");
		pkg_free(RES_ROWS(*_r));
		RES_ROWS(*_r) = 0;
		return 0;
	}

	/* Convert rows to internal format */
	memset(RES_ROWS(*_r), 0, len);
	i = 0;
	rows = rowstart;
	while(rows)
	{
		LM_DBG("converting row #%d\n", i);
		CON_ROW(_h) = rows->data;
		if (!CON_ROW(_h))
		{
			LM_ERR("string null\n");
			RES_ROW_N(*_r) = row_n;
			db_free_rows(*_r);
			return -3;
		}
		if (db_unixodbc_convert_row(_h, *_r, &(RES_ROWS(*_r)[i]), rows->lengths) < 0) {
			LM_ERR("converting fetched row #%d failed\n", i);
			RES_ROW_N(*_r) = i;
			db_free_rows(*_r);
			return -4;
		}
		i++;
		rows = rows->next;
	}
	db_unixodbc_list_destroy(rowstart);

	/* update the total number of rows processed */
	RES_LAST_ROW(*_r) += row_n;
	LM_DBG("fetch from db processed %d rows so far\n", RES_LAST_ROW(*_r));

	return 0;
}
Beispiel #13
0
/*
 * 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;
}
Beispiel #14
0
/*!
 * \brief Get and convert columns from a result set
 * \param _h database connection
 * \param _r result set
 * \return 0 on success, negative on error
 */
int db_postgres_get_columns(const db1_con_t* _h, db1_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++) {

        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\n", (unsigned int) sizeof(str), col,
               RES_NAMES(_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:
            LM_DBG("use DB1_INT result type\n");
            RES_TYPES(_r)[col] = DB1_INT;
            break;

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

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

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

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

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

        case BITOID:
        case VARBITOID:
            LM_DBG("use DB1_BITMAP result type\n");
            RES_TYPES(_r)[col] = DB1_BITMAP;
            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;
}