Exemplo n.º 1
0
Arquivo: util.c Projeto: Pakrik/libdb
int
secondary_callback(DB *db_arg, const DBT *key, const DBT *data, DBT *result)
{
	DbField *f;
	DbRecord record;
	void *faddr, *addr;

	/* Populate the field. */
	if (DbRecord_init(key, data, &record) != 0)
		return (-1);

	f = db_arg->app_private;
	faddr = (u_int8_t *)&record + f->offset;

	/*
	 * If necessary, copy the field into separate memory.
	 * Set up the result DBT.
	 */
	switch (f->type) {
	case STRING:
		result->data = *(char **)faddr;
		result->size = (u_int32_t)strlen(*(char **)faddr) + 1;
		break;
	case DOUBLE:
		if ((addr = malloc(sizeof(double))) == NULL)
			return (-1);
		result->data = addr;
		result->size = sizeof(double);
		result->flags = DB_DBT_APPMALLOC;
		memcpy(addr, faddr, sizeof(double));
		break;
	case UNSIGNED_LONG:
		if ((addr = malloc(sizeof(u_long))) == NULL)
			return (-1);
		result->data = addr;
		result->size = sizeof(u_long);
		result->flags = DB_DBT_APPMALLOC;
		memcpy(addr, faddr, sizeof(u_long));
		break;
	default:
	case NOTSET:
		abort();
		/* NOTREACHED */
	}

	return (0);
}
Exemplo n.º 2
0
/*
 * DbRecord_read --
 *	Read a specific record from the database.
 */
int
DbRecord_read(u_long recno_ulong, DbRecord *recordp)
{
	DBT key, data;
	u_int32_t recno;
	int ret;

	/*
	 * XXX
	 * This code assumes a record number (typed as u_int32_t) is the same
	 * size as an unsigned long, and there's no reason to believe that.
	 */
	recno = recno_ulong;

	/*
	 * Retrieve the requested record from the primary database.  Have
	 * Berkeley DB allocate memory for us, keeps the DB handle thread
	 * safe.
	 *
	 * We have the Berkeley DB library allocate memory for the record,
	 * which we own and must eventually free.  The reason is so we can
	 * have the string fields in the structure point into the actual
	 * record, rather than allocating structure local memory to hold them
	 * and copying them out of the record.
	 */
	memset(&key, 0, sizeof(key));
	memset(&data, 0, sizeof(data));
	key.data = &recno;
	key.size = sizeof(recno);
	data.flags = DB_DBT_MALLOC;
	if ((ret = db->get(db, NULL, &key, &data, 0)) != 0)
		return (ret);

	if ((ret = DbRecord_init(&key, &data, recordp)) != 0)
		return (ret);

	return (0);
}
Exemplo n.º 3
0
/*
 * DbRecord_search_field --
 *	Search, looking for a record by field.
 */
static int
DbRecord_search_field(DbField *f, char *value, OPERATOR op)
{
#ifdef HAVE_WILDCARD_SUPPORT
	regex_t preq;
#endif
	DBC *dbc;
	DbRecord record;
	DBT key, data, pkey;
	double value_double;
	u_long value_ulong;
	u_int32_t cursor_flags;
	int ret, t_ret;
	int (*cmp)(void *, void *, OPERATOR);
	void *faddr, *valuep;

	dbc = NULL;
	memset(&key, 0, sizeof(key));
	memset(&pkey, 0, sizeof(pkey));
	memset(&data, 0, sizeof(data));

	/*
	 * Initialize the comparison function, crack the value.  Wild cards
	 * are always strings, otherwise we follow the field type.
	 */
	if (op == WC || op == NWC) {
#ifdef HAVE_WILDCARD_SUPPORT
		if (f->type != STRING) {
			dbenv->errx(dbenv,
		    "wildcard operator only supported for string fields");
			return (1);
		}
		if (regcomp(&preq, value, 0) != 0) {
			dbenv->errx(dbenv, "regcomp of pattern failed");
			return (1);
		}
		valuep = &preq;
		cmp = field_cmp_re;
#else
		dbenv->errx(dbenv,
		    "wildcard operators not supported in this build");
		return (1);
#endif
	} else
		switch (f->type) {
		case DOUBLE:
			if (strtod_err(value, &value_double) != 0)
				return (1);
			cmp = field_cmp_double;
			valuep = &value_double;
			key.size = sizeof(double);
			break;
		case STRING:
			valuep = value;
			cmp = field_cmp_string;
			key.size = (u_int32_t)strlen(value);
			break;
		case UNSIGNED_LONG:
			if (strtoul_err(value, &value_ulong) != 0)
				return (1);
			cmp = field_cmp_ulong;
			valuep = &value_ulong;
			key.size = sizeof(u_long);
			break;
		default:
		case NOTSET:
			abort();
			/* NOTREACHED */
		}

	/*
	 * Retrieve the first record that interests us.  The range depends on
	 * the operator:
	 *
	 *	~		beginning to end
	 *	!=		beginning to end
	 *	<		beginning to first match
	 *	<=		beginning to last match
	 *	=		first match to last match
	 *	>		record after last match to end
	 *	>=		first match to end
	 *
	 * If we have a secondary, set a cursor in the secondary, else set the
	 * cursor to the beginning of the primary.
	 *
	 * XXX
	 * If the wildcard string has a leading non-magic character we should
	 * be able to do a range search instead of a full-database search.
	 *
	 * Step through records to the first non-match or to the end of the
	 * database, depending on the operation.  If the comparison function
	 * returns success for a key/data pair, print the pair.
	 */
	if (f->secondary == NULL || op == NEQ || op == WC || op == NWC) {
		if ((ret = db->cursor(db, NULL, &dbc, 0)) != 0)
			goto err;
		while ((ret = dbc->c_get(dbc, &key, &data, DB_NEXT)) == 0) {
			if ((ret = DbRecord_init(&key, &data, &record)) != 0)
				break;
			faddr = (u_int8_t *)&record + f->offset;
			if (cmp(faddr, valuep, op))
				DbRecord_print(&record, NULL);
			else
				if (op == EQ || op == LT || op == LTEQ)
					break;
		}
	} else {
		if ((ret =
		    f->secondary->cursor(f->secondary, NULL, &dbc, 0)) != 0)
			goto err;
		key.data = valuep;
		cursor_flags = op == LT || op == LTEQ ? DB_FIRST : DB_SET_RANGE;
		if ((ret =
		    dbc->c_pget(dbc, &key, &pkey, &data, cursor_flags)) != 0)
			goto done;
		if (op == GT) {
			while ((ret = dbc->c_pget(
			    dbc, &key, &pkey, &data, DB_NEXT)) == 0) {
				if ((ret =
				    DbRecord_init(&pkey, &data, &record)) != 0)
					break;
				faddr = (u_int8_t *)&record + f->offset;
				if (cmp(faddr, valuep, op) != 0)
					break;
			}
			if (ret != 0)
				goto done;
		}
		do {
			if ((ret = DbRecord_init(&pkey, &data, &record)) != 0)
				break;
			faddr = (u_int8_t *)&record + f->offset;
			if (cmp(faddr, valuep, op))
				DbRecord_print(&record, NULL);
			else
				if (op == EQ || op == LT || op == LTEQ)
					break;
		} while ((ret =
		    dbc->c_pget(dbc, &key, &pkey, &data, DB_NEXT)) == 0);
	}

done:	if (ret == DB_NOTFOUND)
		ret = 0;

err:	if (dbc != NULL && (t_ret = dbc->c_close(dbc)) != 0 && ret == 0)
		ret = t_ret;

#ifdef HAVE_WILDCARD_SUPPORT
	if (op == WC || op == NWC)
		regfree(&preq);
#endif

	return (ret);
}
Exemplo n.º 4
0
/*
 * DbRecord_search_recno --
 *	Search, looking for a record by record number.
 */
static int
DbRecord_search_recno(char *value, OPERATOR op)
{
	DBC *dbc;
	DbRecord record;
	DBT key, data;
	u_int32_t recno;
	u_long recno_ulong;
	int ret;

	/*
	 * XXX
	 * This code assumes a record number (typed as u_int32_t) is the same
	 * size as an unsigned long, and there's no reason to believe that.
	 */
	if (strtoul_err(value, &recno_ulong) != 0)
		return (1);

	memset(&key, 0, sizeof(key));
	memset(&data, 0, sizeof(data));
	key.data = &recno;
	key.size = sizeof(recno);

	if ((ret = db->cursor(db, NULL, &dbc, 0)) != 0)
		return (ret);

	/*
	 * Retrieve the first record that interests us.  The range depends on
	 * the operator:
	 *
	 *	~		error
	 *	!=		beginning to end
	 *	<		beginning to first match
	 *	<=		beginning to last match
	 *	=		first match to last match
	 *	>		record after last match to end
	 *	>=		first match to end
	 */
	if (op == LT || op == LTEQ || op == NEQ || op == WC || op == NWC)
		recno = 1;
	else if (op == WC || op == NWC) {
		dbenv->errx(dbenv,
		    "wildcard operator only supported for string fields");
		return (1);
	} else {
		recno = recno_ulong;
		if (op == GT)
			++recno;
	}
	if ((ret = dbc->c_get(dbc, &key, &data, DB_SET)) != 0)
		goto err;

	for (;;) {
		if ((ret = DbRecord_init(&key, &data, &record)) != 0)
			break;
		if (field_cmp_ulong(&record.recno, &recno_ulong, op))
			DbRecord_print(&record, NULL);
		else
			if (op == LT || op == LTEQ || op == EQ)
				break;
		if ((ret = dbc->c_get(dbc, &key, &data, DB_NEXT)) != 0)
			break;
	}

err:	return (ret == DB_NOTFOUND ? 0 : ret);
}