Пример #1
0
/*!
 * \brief Allocate new result set with private structure
 * \return db1_res_t object on success, NULL on failure
 */
db1_res_t* db_mysql_new_result(void)
{
	db1_res_t* obj;

	obj = db_new_result();
	if (!obj)
		return NULL;
	RES_PTR(obj) = pkg_malloc(sizeof(struct my_res));
	if (!RES_PTR(obj)) {
		db_free_result(obj);
		return NULL;
	}
	return obj;
}
Пример #2
0
db1_res_t* db_mongodb_new_result(void)
{
	db1_res_t* obj;

	obj = db_new_result();
	if (!obj)
		return NULL;
	RES_PTR(obj) = pkg_malloc(sizeof(db_mongodb_result_t));
	if (!RES_PTR(obj)) {
		db_free_result(obj);
		return NULL;
	}
	memset(RES_PTR(obj), 0, sizeof(db_mongodb_result_t));
	return obj;
}
Пример #3
0
/*
 * Retrieve result set
 */
static int db_mongodb_store_result(const db1_con_t* _h, db1_res_t** _r)
{
	km_mongodb_con_t *mgcon;
	db_mongodb_result_t *mgres;
	const bson_t *itdoc;

	mgcon = MONGODB_CON(_h);
	if(!_r) {
		LM_ERR("invalid result parameter\n");
		return -1;
	}

	*_r = db_mongodb_new_result();
	if (!*_r)  {
		LM_ERR("no memory left for result \n");
		goto error;
	}
	mgres = (db_mongodb_result_t*)RES_PTR(*_r);
	mgres->collection = mgcon->collection;
	mgcon->collection = NULL;
	mgres->cursor = mgcon->cursor;
	mgcon->cursor = NULL;
	mgres->colsdoc = mgcon->colsdoc;
	mgcon->colsdoc = NULL;
	mgres->nrcols = mgcon->nrcols;
	mgcon->nrcols = 0;
	if(!mongoc_cursor_more (mgres->cursor)
			|| !mongoc_cursor_next (mgres->cursor, &itdoc)
			|| !itdoc) {
		LM_DBG("no result from mongodb\n");
		return 0;
	}
	/* first document linked internally in result to get columns */
	mgres->rdoc = (bson_t*)itdoc;
	if(db_mongodb_get_columns(_h, *_r)<0) {
		LM_ERR("failed to set the columns\n");
		goto error;
	}
	if(db_mongodb_convert_result(_h, *_r)<0) {
		LM_ERR("failed to set the rows in result\n");
		goto error;
	}
	return 0;

error:
	if(mgcon->colsdoc) {
		bson_destroy (mgcon->colsdoc);
		mgcon->colsdoc = NULL;
	}
	mgcon->nrcols = 0;
	if(mgcon->cursor) {
		mongoc_cursor_destroy (mgcon->cursor);
		mgcon->cursor = NULL;
	}
	if(mgcon->collection) {
		mongoc_collection_destroy (mgcon->collection);
		mgcon->collection = NULL;
	}
	return -1;
}
Пример #4
0
/**
 * Release a result set from memory.
 * \param _h handle to the database
 * \param _r result set that should be freed
 * \return zero on success, negative value on failure
 */
int db_mysql_free_result(const db1_con_t* _h, db1_res_t* _r)
{
     if ((!_h) || (!_r)) {
	     LM_ERR("invalid parameter value\n");
	     return -1;
     }

     mysql_free_result(RES_RESULT(_r));
     RES_RESULT(_r) = 0;
     pkg_free(RES_PTR(_r));

     if (db_free_result(_r) < 0) {
	     LM_ERR("unable to free result structure\n");
	     return -1;
     }
     return 0;
}
Пример #5
0
/*
 * Release a result set from memory
 */
int db_mongodb_free_result(db1_con_t* _h, db1_res_t* _r)
{
	if(!_r)
		return -1;
	if(RES_PTR(_r)) {
		if(((db_mongodb_result_t*)RES_PTR(_r))->rdoc) {
			bson_destroy(((db_mongodb_result_t*)RES_PTR(_r))->rdoc);
			((db_mongodb_result_t*)RES_PTR(_r))->rdoc = NULL;
		}
		if(((db_mongodb_result_t*)RES_PTR(_r))->colsdoc) {
			bson_destroy (((db_mongodb_result_t*)RES_PTR(_r))->colsdoc);
			((db_mongodb_result_t*)RES_PTR(_r))->colsdoc = NULL;
		}
		((db_mongodb_result_t*)RES_PTR(_r))->nrcols = 0;
		if(((db_mongodb_result_t*)RES_PTR(_r))->cursor) {
			mongoc_cursor_destroy (((db_mongodb_result_t*)RES_PTR(_r))->cursor);
			((db_mongodb_result_t*)RES_PTR(_r))->cursor = NULL;
		}
		if(((db_mongodb_result_t*)RES_PTR(_r))->collection) {
			mongoc_collection_destroy (((db_mongodb_result_t*)RES_PTR(_r))->collection);
			((db_mongodb_result_t*)RES_PTR(_r))->collection = NULL;
		}
		pkg_free(RES_PTR(_r));
	}
	db_free_result(_r);
	return 0;
}
Пример #6
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_result(const db1_con_t* _h, db1_res_t* _r)
{
	int row;
	db_mongodb_result_t *mgres;
	const bson_t *itdoc;
	char *jstr;

	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) {
		LM_DBG("no fields to return\n");
		return 0;
	}

	if(!mongoc_cursor_more (mgres->cursor)) {
		RES_ROW_N(_r) = 1;
		mgres->maxrows = 1;
	} else {
		RES_ROW_N(_r) = DB_MONGODB_ROWS_STEP;
		mgres->maxrows = DB_MONGODB_ROWS_STEP;
	}

	if (db_allocate_rows(_r) < 0) {
		LM_ERR("could not allocate rows\n");
		RES_ROW_N(_r) = 0;
		return -2;
	}

	itdoc = mgres->rdoc;
	row = 0;
	do {
		if(row >= RES_ROW_N(_r)) {
			if (db_reallocate_rows(_r,
						RES_ROW_N(_r)+DB_MONGODB_ROWS_STEP) < 0) {
				LM_ERR("could not reallocate rows\n");
				return -2;
			}
			mgres->maxrows = RES_ROW_N(_r);
		}
		if(is_printable(L_DBG)) {
			jstr = bson_as_json (itdoc, NULL);
			LM_DBG("selected document: %s\n", jstr);
			bson_free (jstr);
		}
		if(db_mongodb_convert_bson(_h, _r, row, itdoc)) {
			LM_ERR("failed to convert bson at pos %d\n", row);
			return -1;
		}
		row++;
	} while (mongoc_cursor_more (mgres->cursor)
			&& mongoc_cursor_next (mgres->cursor, &itdoc));
	RES_ROW_N(_r) = row;
	LM_DBG("retrieved number of rows: %d\n", row);
	return 0;
}
Пример #7
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;
}
Пример #8
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;
}