Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Rework iterators structure.
Vsevolod Stakhov committed 11 years ago
commit 520877cc2a8d6f8b37e0aed41023582369ea5e28
parent 206e634
3 files changed +25 -1040
modified libpkg/pkgdb.c
@@ -94,192 +94,6 @@ static int pkgdb_insert_scripts(struct pkg *pkg, int64_t package_id, sqlite3 *s)

extern int sqlite3_shell(int, char**);

-
/*
-
 * Keep entries sorted by name!
-
 */
-
static struct column_mapping {
-
	const char * const name;
-
	pkg_attr type;
-
	enum {
-
		PKG_SQLITE_STRING,
-
		PKG_SQLITE_INT64,
-
		PKG_SQLITE_BOOL
-
	} pkg_type;
-
} columns[] = {
-
	{ "arch",	PKG_ARCH, PKG_SQLITE_STRING },
-
	{ "automatic",	PKG_AUTOMATIC, PKG_SQLITE_BOOL },
-
	{ "cksum",	PKG_CKSUM, PKG_SQLITE_STRING },
-
	{ "comment",	PKG_COMMENT, PKG_SQLITE_STRING },
-
	{ "dbname",	PKG_REPONAME, PKG_SQLITE_STRING },
-
	{ "desc",	PKG_DESC, PKG_SQLITE_STRING },
-
	{ "flatsize",	PKG_FLATSIZE, PKG_SQLITE_INT64 },
-
	{ "id",		PKG_ROWID, PKG_SQLITE_INT64 },
-
	{ "licenselogic", PKG_LICENSE_LOGIC, PKG_SQLITE_INT64 },
-
	{ "locked",	PKG_LOCKED, PKG_SQLITE_BOOL },
-
	{ "maintainer",	PKG_MAINTAINER, PKG_SQLITE_STRING },
-
	{ "manifestdigest",	PKG_DIGEST, PKG_SQLITE_STRING },
-
	{ "message",	PKG_MESSAGE, PKG_SQLITE_STRING },
-
	{ "name",	PKG_NAME, PKG_SQLITE_STRING },
-
	{ "oldflatsize", PKG_OLD_FLATSIZE, PKG_SQLITE_INT64 },
-
	{ "oldversion",	PKG_OLD_VERSION, PKG_SQLITE_STRING },
-
	{ "origin",	PKG_ORIGIN, PKG_SQLITE_STRING },
-
	{ "pkgsize",	PKG_PKGSIZE, PKG_SQLITE_INT64 },
-
	{ "prefix",	PKG_PREFIX, PKG_SQLITE_STRING },
-
	{ "repopath",	PKG_REPOPATH, PKG_SQLITE_STRING },
-
	{ "rowid",	PKG_ROWID, PKG_SQLITE_INT64 },
-
	{ "time",	PKG_TIME, PKG_SQLITE_INT64 },
-
	{ "uniqueid",	PKG_UNIQUEID, PKG_SQLITE_STRING },
-
	{ "version",	PKG_VERSION, PKG_SQLITE_STRING },
-
	{ "weight",	-1, PKG_SQLITE_INT64 },
-
	{ "www",	PKG_WWW, PKG_SQLITE_STRING },
-
	{ NULL,		-1, PKG_SQLITE_STRING }
-
};
-

-
static int
-
load_val(sqlite3 *db, struct pkg *pkg, const char *sql, unsigned flags,
-
    int (*pkg_adddata)(struct pkg *pkg, const char *data), int list)
-
{
-
	sqlite3_stmt	*stmt;
-
	int		 ret;
-
	int64_t		 rowid;
-

-
	assert(db != NULL && pkg != NULL);
-

-
	if (pkg->flags & flags)
-
		return (EPKG_OK);
-

-
	pkg_debug(4, "Pkgdb: running '%s'", sql);
-
	if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK) {
-
		ERROR_SQLITE(db, sql);
-
		return (EPKG_FATAL);
-
	}
-

-
	pkg_get(pkg, PKG_ROWID, &rowid);
-
	sqlite3_bind_int64(stmt, 1, rowid);
-

-
	while ((ret = sqlite3_step(stmt)) == SQLITE_ROW) {
-
		pkg_adddata(pkg, sqlite3_column_text(stmt, 0));
-
	}
-

-
	sqlite3_finalize(stmt);
-

-
	if (ret != SQLITE_DONE) {
-
		if (list != -1)
-
			pkg_list_free(pkg, list);
-
		ERROR_SQLITE(db, sql);
-
		return (EPKG_FATAL);
-
	}
-

-
	pkg->flags |= flags;
-
	return (EPKG_OK);
-
}
-

-
static int
-
load_tag_val(sqlite3 *db, struct pkg *pkg, const char *sql, unsigned flags,
-
	     int (*pkg_addtagval)(struct pkg *pkg, const char *tag, const char *val),
-
	     int list)
-
{
-
	sqlite3_stmt	*stmt;
-
	int		 ret;
-
	int64_t		 rowid;
-

-
	assert(db != NULL && pkg != NULL);
-

-
	if (pkg->flags & flags)
-
		return (EPKG_OK);
-

-
	pkg_debug(4, "Pkgdb: running '%s'", sql);
-
	if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK) {
-
		ERROR_SQLITE(db, sql);
-
		return (EPKG_FATAL);
-
	}
-

-
	pkg_get(pkg, PKG_ROWID, &rowid);
-
	sqlite3_bind_int64(stmt, 1, rowid);
-

-
	while ((ret = sqlite3_step(stmt)) == SQLITE_ROW) {
-
		pkg_addtagval(pkg, sqlite3_column_text(stmt, 0),
-
			      sqlite3_column_text(stmt, 1));
-
	}
-
	sqlite3_finalize(stmt);
-

-
	if (ret != SQLITE_DONE) {
-
		if (list != -1)
-
			pkg_list_free(pkg, list);
-
		ERROR_SQLITE(db, sql);
-
		return (EPKG_FATAL);
-
	}
-

-
	pkg->flags |= flags;
-
	return (EPKG_OK);
-
}
-

-
static int
-
compare_column_func(const void *pkey, const void *pcolumn)
-
{
-
	const char *key = (const char*)pkey;
-
	const struct column_mapping *column =
-
			(const struct column_mapping*)pcolumn;
-

-
	return strcmp(key, column->name);
-
}
-

-
static void
-
populate_pkg(sqlite3_stmt *stmt, struct pkg *pkg) {
-
	int		 icol = 0;
-
	const char	*colname;
-

-
	assert(stmt != NULL);
-

-
	for (icol = 0; icol < sqlite3_column_count(stmt); icol++) {
-
		colname = sqlite3_column_name(stmt, icol);
-
		struct column_mapping *column;
-
		switch (sqlite3_column_type(stmt, icol)) {
-
		case SQLITE_TEXT:
-
			column = bsearch(colname, columns, NELEM(columns) - 1,
-
					sizeof(columns[0]), compare_column_func);
-
			if (column == NULL) {
-
				pkg_emit_error("unknown column %s", colname);
-
			}
-
			else {
-
				if (column->pkg_type == PKG_SQLITE_STRING)
-
					pkg_set(pkg, column->type,
-
						sqlite3_column_text(stmt, icol));
-
				else
-
					pkg_emit_error("want string for column %s and got number",
-
							colname);
-
			}
-
			break;
-
		case SQLITE_INTEGER:
-
			column = bsearch(colname, columns, NELEM(columns) - 1,
-
					sizeof(columns[0]), compare_column_func);
-
			if (column == NULL) {
-
				pkg_emit_error("Unknown column %s", colname);
-
			}
-
			else {
-
				if (column->pkg_type == PKG_SQLITE_INT64)
-
					pkg_set(pkg, column->type,
-
						sqlite3_column_int64(stmt, icol));
-
				else if (column->pkg_type == PKG_SQLITE_BOOL)
-
					pkg_set(pkg, column->type,
-
							(bool)sqlite3_column_int(stmt, icol));
-
				else
-
					pkg_emit_error("want number for column %s and got string",
-
							colname);
-
			}
-
			break;
-
		case SQLITE_BLOB:
-
		case SQLITE_FLOAT:
-
			pkg_emit_error("wrong type for column: %s",
-
			    colname);
-
			/* just ignore currently */
-
			break;
-
		case SQLITE_NULL:
-
			break;
-
		}
-
	}
-
}
-

static void
pkgdb_regex(sqlite3_context *ctx, int argc, sqlite3_value **argv)
{
@@ -1339,143 +1153,7 @@ pkgdb_transaction_rollback(sqlite3 *sqlite, const char *savepoint)
}


-
struct pkgdb_it *
-
pkgdb_it_new(struct pkgdb *db, sqlite3_stmt *s, int type, short flags)
-
{
-
	struct pkgdb_it	*it;
-

-
	assert(db != NULL && s != NULL);
-
	assert(!(flags & (PKGDB_IT_FLAG_CYCLED & PKGDB_IT_FLAG_ONCE)));
-
	assert(!(flags & (PKGDB_IT_FLAG_AUTO & (PKGDB_IT_FLAG_CYCLED | PKGDB_IT_FLAG_ONCE))));
-

-
	if ((it = malloc(sizeof(struct pkgdb_it))) == NULL) {
-
		pkg_emit_errno("malloc", "pkgdb_it");
-
		sqlite3_finalize(s);
-
		return (NULL);
-
	}

-
	it->db = db;
-
	it->sqlite = db->sqlite;
-
	it->stmt = s;
-
	it->type = type;
-
	it->flags = flags;
-
	it->finished = 0;
-
	return (it);
-
}
-

-
static struct load_on_flag {
-
	int	flag;
-
	int	(*load)(struct pkgdb *db, struct pkg *p);
-
} load_on_flag[] = {
-
	{ PKG_LOAD_DEPS,		pkgdb_load_deps },
-
	{ PKG_LOAD_RDEPS,		pkgdb_load_rdeps },
-
	{ PKG_LOAD_FILES,		pkgdb_load_files },
-
	{ PKG_LOAD_DIRS,		pkgdb_load_dirs },
-
	{ PKG_LOAD_SCRIPTS,		pkgdb_load_scripts },
-
	{ PKG_LOAD_OPTIONS,		pkgdb_load_options },
-
	{ PKG_LOAD_MTREE,		pkgdb_load_mtree },
-
	{ PKG_LOAD_CATEGORIES,		pkgdb_load_category },
-
	{ PKG_LOAD_LICENSES,		pkgdb_load_license },
-
	{ PKG_LOAD_USERS,		pkgdb_load_user },
-
	{ PKG_LOAD_GROUPS,		pkgdb_load_group },
-
	{ PKG_LOAD_SHLIBS_REQUIRED,	pkgdb_load_shlib_required },
-
	{ PKG_LOAD_SHLIBS_PROVIDED,	pkgdb_load_shlib_provided },
-
	{ PKG_LOAD_ANNOTATIONS,		pkgdb_load_annotations },
-
	{ PKG_LOAD_CONFLICTS,		pkgdb_load_conflicts },
-
	{ PKG_LOAD_PROVIDES,		pkgdb_load_provides },
-
	{ -1,			        NULL }
-
};
-

-
int
-
pkgdb_it_next(struct pkgdb_it *it, struct pkg **pkg_p, unsigned flags)
-
{
-
	struct pkg	*pkg;
-
	int		 i;
-
	int		 ret;
-
	const char *digest;
-

-
	assert(it != NULL);
-

-
	/*
-
	 * XXX:
-
	 * Currently, we have a lot of issues related to pkg digests.
-
	 * So we want to ensure that we always have a valid package digest
-
	 * even if we work with pkg 1.2 repo. Therefore, we explicitly check
-
	 * manifest digests and set it to NULL if it is invalid.
-
	 *
-
	 */
-

-
	if (it->finished && (it->flags & PKGDB_IT_FLAG_ONCE))
-
		return (EPKG_END);
-

-
	switch (sqlite3_step(it->stmt)) {
-
	case SQLITE_ROW:
-
		if (*pkg_p == NULL) {
-
			ret = pkg_new(pkg_p, it->type);
-
			if (ret != EPKG_OK)
-
				return (ret);
-
		} else
-
			pkg_reset(*pkg_p, it->type);
-
		pkg = *pkg_p;
-

-
		populate_pkg(it->stmt, pkg);
-

-
		pkg_get(pkg, PKG_DIGEST, &digest);
-
		if (digest != NULL && !pkg_checksum_is_valid(digest, strlen(digest)))
-
			pkg_set(pkg, PKG_DIGEST, NULL);
-

-
		for (i = 0; load_on_flag[i].load != NULL; i++) {
-
			if (flags & load_on_flag[i].flag) {
-
				if (it->db != NULL) {
-
					ret = load_on_flag[i].load(it->db, pkg);
-
					if (ret != EPKG_OK)
-
						return (ret);
-
				}
-
				else {
-
					pkg_emit_error("invalid iterator passed to pkgdb_it_next");
-
					return (EPKG_FATAL);
-
				}
-
			}
-
		}
-

-
		return (EPKG_OK);
-
	case SQLITE_DONE:
-
		it->finished ++;
-
		if (it->flags & PKGDB_IT_FLAG_CYCLED) {
-
			sqlite3_reset(it->stmt);
-
			return (EPKG_OK);
-
		}
-
		else {
-
			if (it->flags & PKGDB_IT_FLAG_AUTO)
-
				pkgdb_it_free(it);
-
			return (EPKG_END);
-
		}
-
		break;
-
	default:
-
		ERROR_SQLITE(it->sqlite, "iterator");
-
		return (EPKG_FATAL);
-
	}
-
}
-

-
void
-
pkgdb_it_reset(struct pkgdb_it *it)
-
{
-
	if (it == NULL)
-
		return;
-

-
	it->finished = 0;
-
	sqlite3_reset(it->stmt);
-
}
-

-
void
-
pkgdb_it_free(struct pkgdb_it *it)
-
{
-
	if (it == NULL)
-
		return;
-

-
	sqlite3_finalize(it->stmt);
-
	free(it);
-
}

/* By default, MATCH_EXACT and MATCH_REGEX are case sensitive.  This
 * is modified in many actions according to the value of
@@ -1763,596 +1441,6 @@ pkgdb_is_dir_used(struct pkgdb *db, const char *dir, int64_t *res)

}

-
int
-
pkgdb_load_deps(struct pkgdb *db, struct pkg *pkg)
-
{
-
	sqlite3_stmt	*stmt = NULL;
-
	int		 ret = EPKG_OK;
-
	int64_t		 rowid;
-
	char		 sql[BUFSIZ];
-
	const char	*reponame = NULL;
-
	const char	*mainsql = ""
-
		"SELECT d.name, d.origin, d.version, p.locked "
-
		"FROM main.deps AS d "
-
		"LEFT JOIN main.packages AS p ON p.origin = d.origin "
-
		"AND p.name = d.name "
-
		"WHERE d.package_id = ?1 ORDER BY d.origin DESC;";
-
	const char	*reposql = ""
-
		"SELECT d.name, d.origin, d.version, 0 "
-
		"FROM %Q.deps AS d "
-
		"WHERE d.package_id = ?1 ORDER BY d.origin DESC;";
-

-
	assert(db != NULL && pkg != NULL);
-

-
	if (pkg->flags & PKG_LOAD_DEPS)
-
		return (EPKG_OK);
-

-
	if (pkg->type == PKG_REMOTE) {
-
		assert(db->type == PKGDB_REMOTE);
-
		pkg_get(pkg, PKG_REPONAME, &reponame);
-
		sqlite3_snprintf(sizeof(sql), sql, reposql, reponame);
-
		pkg_debug(4, "Pkgdb: running '%s'", sql);
-
		ret = sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL);
-
	} else {
-
		pkg_debug(4, "Pkgdb: running '%s'", mainsql);
-
		ret = sqlite3_prepare_v2(db->sqlite, mainsql, -1, &stmt, NULL);
-
	}
-

-
	if (ret != SQLITE_OK) {
-
		ERROR_SQLITE(db->sqlite, sql);
-
		return (EPKG_FATAL);
-
	}
-

-
	pkg_get(pkg, PKG_ROWID, &rowid);
-
	sqlite3_bind_int64(stmt, 1, rowid);
-

-
	while ((ret = sqlite3_step(stmt)) == SQLITE_ROW) {
-
		pkg_adddep(pkg, sqlite3_column_text(stmt, 0),
-
			   sqlite3_column_text(stmt, 1),
-
			   sqlite3_column_text(stmt, 2),
-
			   sqlite3_column_int(stmt, 3));
-
	}
-
	sqlite3_finalize(stmt);
-

-
	if (ret != SQLITE_DONE) {
-
		pkg_list_free(pkg, PKG_DEPS);
-
		ERROR_SQLITE(db->sqlite, sql);
-
		return (EPKG_FATAL);
-
	}
-

-
	pkg->flags |= PKG_LOAD_DEPS;
-
	return (EPKG_OK);
-
}
-

-
int
-
pkgdb_load_rdeps(struct pkgdb *db, struct pkg *pkg)
-
{
-
	sqlite3_stmt	*stmt = NULL;
-
	int		 ret;
-
	const char	*uniqueid;
-
	const char	*reponame = NULL;
-
	char		 sql[BUFSIZ];
-
	const char	*mainsql = ""
-
		"SELECT p.name, p.origin, p.version, p.locked "
-
		"FROM main.packages AS p "
-
		"INNER JOIN main.deps AS d ON p.id = d.package_id "
-
		"WHERE d.name = SPLIT_UID('name', ?1) AND "
-
		"d.origin = SPLIT_UID('origin', ?1);";
-
	const char	*reposql = ""
-
		"SELECT p.name, p.origin, p.version, 0 "
-
		"FROM %Q.packages AS p "
-
		"INNER JOIN %Q.deps AS d ON p.id = d.package_id "
-
		"WHERE d.name = SPLIT_UID('name', ?1) AND "
-
		"d.origin = SPLIT_UID('origin', ?1);";
-

-
	assert(db != NULL && pkg != NULL);
-

-
	if (pkg->flags & PKG_LOAD_RDEPS)
-
		return (EPKG_OK);
-

-
	if (pkg->type == PKG_REMOTE) {
-
		assert(db->type == PKGDB_REMOTE);
-
		pkg_get(pkg, PKG_REPONAME, &reponame);
-
		sqlite3_snprintf(sizeof(sql), sql, reposql, reponame, reponame);
-
		pkg_debug(4, "Pkgdb: running '%s'", sql);
-
		ret = sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL);
-
	} else {
-
		pkg_debug(4, "Pkgdb: running '%s'", mainsql);
-
		ret = sqlite3_prepare_v2(db->sqlite, mainsql, -1, &stmt, NULL);
-
	}
-

-
	if (ret != SQLITE_OK) {
-
		ERROR_SQLITE(db->sqlite, mainsql);
-
		return (EPKG_FATAL);
-
	}
-

-
	pkg_get(pkg, PKG_UNIQUEID, &uniqueid);
-
	sqlite3_bind_text(stmt, 1, uniqueid, -1, SQLITE_STATIC);
-

-
	while ((ret = sqlite3_step(stmt)) == SQLITE_ROW) {
-
		pkg_addrdep(pkg, sqlite3_column_text(stmt, 0),
-
			    sqlite3_column_text(stmt, 1),
-
			    sqlite3_column_text(stmt, 2),
-
			    sqlite3_column_int(stmt, 3));
-
	}
-
	sqlite3_finalize(stmt);
-

-
	if (ret != SQLITE_DONE) {
-
		pkg_list_free(pkg, PKG_RDEPS);
-
		ERROR_SQLITE(db->sqlite, mainsql);
-
		return (EPKG_FATAL);
-
	}
-

-
	pkg->flags |= PKG_LOAD_RDEPS;
-
	return (EPKG_OK);
-
}
-

-
int
-
pkgdb_load_files(struct pkgdb *db, struct pkg *pkg)
-
{
-
	sqlite3_stmt	*stmt = NULL;
-
	int		 ret;
-
	int64_t		 rowid;
-
	const char	 sql[] = ""
-
		"SELECT path, sha256 "
-
		"FROM files "
-
		"WHERE package_id = ?1 "
-
		"ORDER BY PATH ASC";
-

-
	assert(db != NULL && pkg != NULL);
-
	assert(pkg->type == PKG_INSTALLED);
-

-
	if (pkg->flags & PKG_LOAD_FILES)
-
		return (EPKG_OK);
-

-
	pkg_debug(4, "Pkgdb: running '%s'", sql);
-
	if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK) {
-
		ERROR_SQLITE(db->sqlite, sql);
-
		return (EPKG_FATAL);
-
	}
-

-
	pkg_get(pkg, PKG_ROWID, &rowid);
-
	sqlite3_bind_int64(stmt, 1, rowid);
-

-
	while ((ret = sqlite3_step(stmt)) == SQLITE_ROW) {
-
		pkg_addfile(pkg, sqlite3_column_text(stmt, 0),
-
		    sqlite3_column_text(stmt, 1), false);
-
	}
-
	sqlite3_finalize(stmt);
-

-
	if (ret != SQLITE_DONE) {
-
		pkg_list_free(pkg, PKG_FILES);
-
		ERROR_SQLITE(db->sqlite, sql);
-
		return (EPKG_FATAL);
-
	}
-

-
	pkg->flags |= PKG_LOAD_FILES;
-
	return (EPKG_OK);
-
}
-

-
int
-
pkgdb_load_dirs(struct pkgdb *db, struct pkg *pkg)
-
{
-
	const char	 sql[] = ""
-
		"SELECT path, try "
-
		"FROM pkg_directories, directories "
-
		"WHERE package_id = ?1 "
-
		"AND directory_id = directories.id "
-
		"ORDER by path DESC";
-
	sqlite3_stmt	*stmt;
-
	int		 ret;
-
	int64_t		 rowid;
-

-
	assert(db != NULL && pkg != NULL);
-
	assert(pkg->type == PKG_INSTALLED);
-

-
	if (pkg->flags & PKG_LOAD_DIRS)
-
		return (EPKG_OK);
-

-
	pkg_debug(4, "Pkgdb: running '%s'", sql);
-
	if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK) {
-
		ERROR_SQLITE(db->sqlite, sql);
-
		return (EPKG_FATAL);
-
	}
-

-
	pkg_get(pkg, PKG_ROWID, &rowid);
-
	sqlite3_bind_int64(stmt, 1, rowid);
-

-
	while ((ret = sqlite3_step(stmt)) == SQLITE_ROW) {
-
		pkg_adddir(pkg, sqlite3_column_text(stmt, 0),
-
		    sqlite3_column_int(stmt, 1), false);
-
	}
-

-
	sqlite3_finalize(stmt);
-
	if (ret != SQLITE_DONE) {
-
		pkg_list_free(pkg, PKG_DIRS);
-
		ERROR_SQLITE(db->sqlite, sql);
-
		return (EPKG_FATAL);
-
	}
-

-
	pkg->flags |= PKG_LOAD_DIRS;
-

-
	return (EPKG_OK);
-
}
-

-
int
-
pkgdb_load_license(struct pkgdb *db, struct pkg *pkg)
-
{
-
	char		 sql[BUFSIZ];
-
	const char	*reponame = NULL;
-
	const char	*basesql = ""
-
		"SELECT name "
-
		"FROM %Q.pkg_licenses, %Q.licenses AS l "
-
		"WHERE package_id = ?1 "
-
			"AND license_id = l.id "
-
		"ORDER by name DESC";
-

-
	assert(db != NULL && pkg != NULL);
-

-
	if (pkg->type == PKG_REMOTE) {
-
		assert(db->type == PKGDB_REMOTE);
-
		pkg_get(pkg, PKG_REPONAME, &reponame);
-
		sqlite3_snprintf(sizeof(sql), sql, basesql, reponame, reponame);
-
	} else
-
		sqlite3_snprintf(sizeof(sql), sql, basesql, "main", "main");
-

-
	return (load_val(db->sqlite, pkg, sql, PKG_LOAD_LICENSES,
-
	    pkg_addlicense, PKG_LICENSES));
-
}
-

-
int
-
pkgdb_load_category(struct pkgdb *db, struct pkg *pkg)
-
{
-
	char		 sql[BUFSIZ];
-
	const char	*reponame = NULL;
-
	const char	*basesql = ""
-
		"SELECT name "
-
		"FROM %Q.pkg_categories, %Q.categories AS c "
-
		"WHERE package_id = ?1 "
-
			"AND category_id = c.id "
-
		"ORDER by name DESC";
-
	
-
	assert(db != NULL && pkg != NULL);
-

-
	if (pkg->type == PKG_REMOTE) {
-
		assert(db->type == PKGDB_REMOTE);
-
		pkg_get(pkg, PKG_REPONAME, &reponame);
-
		sqlite3_snprintf(sizeof(sql), sql, basesql, reponame, reponame);
-
	} else
-
		sqlite3_snprintf(sizeof(sql), sql, basesql, "main", "main");
-

-
	return (load_val(db->sqlite, pkg, sql, PKG_LOAD_CATEGORIES,
-
	    pkg_addcategory, PKG_CATEGORIES));
-
}
-

-
int
-
pkgdb_load_user(struct pkgdb *db, struct pkg *pkg)
-
{
-
	/*struct pkg_user *u = NULL;
-
	struct passwd *pwd = NULL;*/
-
	int		ret;
-
	const char	sql[] = ""
-
		"SELECT users.name "
-
		"FROM pkg_users, users "
-
		"WHERE package_id = ?1 "
-
			"AND user_id = users.id "
-
		"ORDER by name DESC";
-

-
	assert(db != NULL && pkg != NULL);
-
	assert(pkg->type == PKG_INSTALLED);
-

-
	ret = load_val(db->sqlite, pkg, sql, PKG_LOAD_USERS,
-
	    pkg_adduser, PKG_USERS);
-

-
	/* TODO get user uidstr from local database */
-
/*	while (pkg_users(pkg, &u) == EPKG_OK) {
-
		pwd = getpwnam(pkg_user_name(u));
-
		if (pwd == NULL)
-
			continue;
-
		strlcpy(u->uidstr, pw_make(pwd), sizeof(u->uidstr));
-
	}*/
-

-
	return (ret);
-
}
-

-
int
-
pkgdb_load_group(struct pkgdb *db, struct pkg *pkg)
-
{
-
	struct pkg_group	*g = NULL;
-
	struct group		*grp = NULL;
-
	int			 ret;
-
	const char		 sql[] = ""
-
		"SELECT groups.name "
-
		"FROM pkg_groups, groups "
-
		"WHERE package_id = ?1 "
-
			"AND group_id = groups.id "
-
		"ORDER by name DESC";
-

-
	assert(db != NULL && pkg != NULL);
-
	assert(pkg->type == PKG_INSTALLED);
-

-
	ret = load_val(db->sqlite, pkg, sql, PKG_LOAD_GROUPS,
-
	    pkg_addgroup, PKG_GROUPS);
-

-
	while (pkg_groups(pkg, &g) == EPKG_OK) {
-
		grp = getgrnam(pkg_group_name(g));
-
		if (grp == NULL)
-
			continue;
-
		strlcpy(g->gidstr, gr_make(grp), sizeof(g->gidstr));
-
	}
-

-
	return (ret);
-
}
-

-
int
-
pkgdb_load_shlib_required(struct pkgdb *db, struct pkg *pkg)
-
{
-
	char		 sql[BUFSIZ];
-
	const char	*reponame = NULL;
-
	const char	*basesql = ""
-
		"SELECT name "
-
		"FROM %Q.pkg_shlibs_required, %Q.shlibs AS s "
-
		"WHERE package_id = ?1 "
-
			"AND shlib_id = s.id "
-
		"ORDER by name DESC";
-

-
	assert(db != NULL && pkg != NULL);
-

-
	if (pkg->type == PKG_REMOTE) {
-
		assert(db->type == PKGDB_REMOTE);
-
		pkg_get(pkg, PKG_REPONAME, &reponame);
-
		sqlite3_snprintf(sizeof(sql), sql, basesql, reponame, reponame);
-
	} else
-
		sqlite3_snprintf(sizeof(sql), sql, basesql, "main", "main");
-

-
	return (load_val(db->sqlite, pkg, sql, PKG_LOAD_SHLIBS_REQUIRED,
-
	    pkg_addshlib_required, PKG_SHLIBS_REQUIRED));
-
}
-

-

-
int
-
pkgdb_load_shlib_provided(struct pkgdb *db, struct pkg *pkg)
-
{
-
	char		 sql[BUFSIZ];
-
	const char	*reponame = NULL;
-
	const char	*basesql = ""
-
		"SELECT name "
-
		"FROM %Q.pkg_shlibs_provided, %Q.shlibs AS s "
-
		"WHERE package_id = ?1 "
-
			"AND shlib_id = s.id "
-
		"ORDER by name DESC";
-

-
	assert(db != NULL && pkg != NULL);
-

-
	if (pkg->type == PKG_REMOTE) {
-
		assert(db->type == PKGDB_REMOTE);
-
		pkg_get(pkg, PKG_REPONAME, &reponame);
-
		sqlite3_snprintf(sizeof(sql), sql, basesql, reponame, reponame);
-
	} else
-
		sqlite3_snprintf(sizeof(sql), sql, basesql, "main", "main");
-

-
	return (load_val(db->sqlite, pkg, sql, PKG_LOAD_SHLIBS_PROVIDED,
-
	    pkg_addshlib_provided, PKG_SHLIBS_PROVIDED));
-
}
-

-
int
-
pkgdb_load_annotations(struct pkgdb *db, struct pkg *pkg)
-
{
-
	char		 sql[BUFSIZ];
-
	const char	*reponame = NULL;
-
	const char	*basesql = ""
-
		"SELECT k.annotation AS tag, v.annotation AS value"
-
		"  FROM %Q.pkg_annotation p"
-
		"    JOIN %Q.annotation k ON (p.tag_id = k.annotation_id)"
-
		"    JOIN %Q.annotation v ON (p.value_id = v.annotation_id)"
-
		"  WHERE p.package_id = ?1"
-
		"  ORDER BY tag, value";
-

-
	assert(db != NULL && pkg != NULL);
-

-
	if (pkg->type == PKG_REMOTE) {
-
		assert(db->type == PKGDB_REMOTE);
-
		pkg_get(pkg, PKG_REPONAME, &reponame);
-
		sqlite3_snprintf(sizeof(sql), sql, basesql, reponame,
-
		    reponame, reponame);
-
	} else
-
		sqlite3_snprintf(sizeof(sql), sql, basesql, "main",
-
                    "main", "main");
-

-
	return (load_tag_val(db->sqlite, pkg, sql, PKG_LOAD_ANNOTATIONS,
-
		   pkg_addannotation, PKG_ANNOTATIONS));
-
}
-

-
int
-
pkgdb_load_scripts(struct pkgdb *db, struct pkg *pkg)
-
{
-
	sqlite3_stmt	*stmt = NULL;
-
	int		 ret;
-
	int64_t		 rowid;
-
	const char	 sql[] = ""
-
		"SELECT script, type "
-
		"FROM pkg_script JOIN script USING(script_id) "
-
		"WHERE package_id = ?1";
-

-
	assert(db != NULL && pkg != NULL);
-
	assert(pkg->type == PKG_INSTALLED);
-

-
	if (pkg->flags & PKG_LOAD_SCRIPTS)
-
		return (EPKG_OK);
-

-
	pkg_debug(4, "Pkgdb: running '%s'", sql);
-
	if (sqlite3_prepare_v2(db->sqlite, sql, -1, &stmt, NULL) != SQLITE_OK) {
-
		ERROR_SQLITE(db->sqlite, sql);
-
		return (EPKG_FATAL);
-
	}
-

-
	pkg_get(pkg, PKG_ROWID, &rowid);
-
	sqlite3_bind_int64(stmt, 1, rowid);
-

-
	while ((ret = sqlite3_step(stmt)) == SQLITE_ROW) {
-
		pkg_addscript(pkg, sqlite3_column_text(stmt, 0),
-
		    sqlite3_column_int(stmt, 1));
-
	}
-
	sqlite3_finalize(stmt);
-

-
	if (ret != SQLITE_DONE) {
-
		ERROR_SQLITE(db->sqlite, sql);
-
		return (EPKG_FATAL);
-
	}
-

-
	pkg->flags |= PKG_LOAD_SCRIPTS;
-
	return (EPKG_OK);
-
}
-

-

-
int
-
pkgdb_load_options(struct pkgdb *db, struct pkg *pkg)
-
{
-
	const char	*reponame;
-
	char		 sql[BUFSIZ];
-
	unsigned int	 i;
-

-
	struct optionsql {
-
		const char	 *sql;
-
		int		(*pkg_addtagval)(struct pkg *pkg,
-
						  const char *tag,
-
						  const char *val);
-
		int		  nargs;
-
	}			  optionsql[] = {
-
		{
-
			"SELECT option, value "
-
			"FROM %Q.option JOIN %Q.pkg_option USING(option_id) "
-
			"WHERE package_id = ?1 ORDER BY option",
-
			pkg_addoption,
-
			2,
-
		},
-
		{
-
			"SELECT option, default_value "
-
			"FROM %Q.option JOIN %Q.pkg_option_default USING(option_id) "
-
			"WHERE package_id = ?1 ORDER BY option",
-
			pkg_addoption_default,
-
			2,
-
		},
-
		{
-
			"SELECT option, description "
-
			"FROM %Q.option JOIN %Q.pkg_option_desc USING(option_id) "
-
			"JOIN %Q.option_desc USING(option_desc_id) ORDER BY option",
-
			pkg_addoption_description,
-
			3,
-
		}
-
	};
-
	const char		 *opt_sql;
-
	int			(*pkg_addtagval)(struct pkg *pkg,
-
						 const char *tag,
-
						 const char *val);
-
	int			  nargs, ret;
-

-
	assert(db != NULL && pkg != NULL);
-

-
	if (pkg->flags & PKG_LOAD_OPTIONS)
-
		return (EPKG_OK);
-

-
	if (pkg->type == PKG_REMOTE) {
-
		assert(db->type == PKGDB_REMOTE);
-
		pkg_get(pkg, PKG_REPONAME, &reponame);
-
	} else {
-
		reponame = "main";
-
	}
-

-
	for (i = 0; i < NELEM(optionsql); i++) {
-
		opt_sql       = optionsql[i].sql;
-
		pkg_addtagval = optionsql[i].pkg_addtagval;
-
		nargs         = optionsql[i].nargs;
-

-
		switch(nargs) {
-
		case 1:
-
			sqlite3_snprintf(sizeof(sql), sql, opt_sql, reponame);
-
			break;
-
		case 2:
-
			sqlite3_snprintf(sizeof(sql), sql, opt_sql, reponame,
-
					 reponame);
-
			break;
-
		case 3:
-
			sqlite3_snprintf(sizeof(sql), sql, opt_sql, reponame,
-
					 reponame, reponame);
-
			break;
-
		default:
-
			/* Nothing needs 4 or more, yet... */
-
			return (EPKG_FATAL);
-
			break;
-
		}
-

-
		pkg_debug(4, "Pkgdb> adding option");
-
		ret = load_tag_val(db->sqlite, pkg, sql, PKG_LOAD_OPTIONS,
-
				   pkg_addtagval, PKG_OPTIONS);
-
		if (ret != EPKG_OK)
-
			break;
-
	}
-
	return (ret);
-
}
-

-
int
-
pkgdb_load_mtree(struct pkgdb *db, struct pkg *pkg)
-
{
-
	const char	sql[] = ""
-
		"SELECT m.content "
-
		"FROM mtree AS m, packages AS p "
-
		"WHERE m.id = p.mtree_id "
-
			"AND p.id = ?1;";
-

-
	assert(db != NULL && pkg != NULL);
-
	assert(pkg->type == PKG_INSTALLED);
-

-
	return (load_val(db->sqlite, pkg, sql, PKG_LOAD_MTREE, pkg_set_mtree, -1));
-
}
-

-
int
-
pkgdb_load_conflicts(struct pkgdb *db, struct pkg *pkg)
-
{
-
	char		 sql[BUFSIZ];
-
	const char	*reponame = NULL;
-
	const char	*basesql = ""
-
			"SELECT packages.origin "
-
			"FROM %Q.pkg_conflicts "
-
			"LEFT JOIN %Q.packages ON "
-
			"packages.id = pkg_conflicts.conflict_id "
-
			"WHERE package_id = ?1";
-

-
	assert(db != NULL && pkg != NULL);
-

-
	if (pkg->type == PKG_REMOTE) {
-
		assert(db->type == PKGDB_REMOTE);
-
		pkg_get(pkg, PKG_REPONAME, &reponame);
-
		sqlite3_snprintf(sizeof(sql), sql, basesql, reponame, reponame);
-
	} else
-
		sqlite3_snprintf(sizeof(sql), sql, basesql, "main", "main");
-

-
	return (load_val(db->sqlite, pkg, sql, PKG_LOAD_CONFLICTS,
-
			pkg_addconflict, PKG_CONFLICTS));
-
}
-

-
int
-
pkgdb_load_provides(struct pkgdb *db, struct pkg *pkg)
-
{
-
	char		 sql[BUFSIZ];
-
	const char	*reponame = NULL;
-
	const char	*basesql = ""
-
		"SELECT provide "
-
		"FROM %Q.provides "
-
		"WHERE package_id = ?1";
-

-
	assert(db != NULL && pkg != NULL);
-

-
	if (pkg->type == PKG_REMOTE) {
-
		assert(db->type == PKGDB_REMOTE);
-
		pkg_get(pkg, PKG_REPONAME, &reponame);
-
		sqlite3_snprintf(sizeof(sql), sql, basesql, reponame, reponame);
-
	} else
-
		sqlite3_snprintf(sizeof(sql), sql, basesql, "main", "main");
-

-
	return (load_val(db->sqlite, pkg, sql, PKG_LOAD_PROVIDES,
-
			pkg_addconflict, PKG_PROVIDES));
-
}

typedef enum _sql_prstmt_index {
	MTREE = 0,
@@ -3420,111 +2508,6 @@ sql_exec(sqlite3 *s, const char *sql, ...)
	return (ret);
}

-
bool
-
pkgdb_is_attached(sqlite3 *s, const char *name)
-
{
-
	sqlite3_stmt	*stmt;
-
	const char	*dbname;
-
	int		 ret;
-

-
	assert(s != NULL);
-

-
	ret = sqlite3_prepare_v2(s, "PRAGMA database_list;", -1, &stmt, NULL);
-
	if (ret != SQLITE_OK) {
-
		ERROR_SQLITE(s, "PRAGMA database_list;");
-
		return false;
-
	}
-

-
	while (sqlite3_step(stmt) != SQLITE_DONE) {
-
		dbname = sqlite3_column_text(stmt, 1);
-
		if (!strcmp(dbname, name)) {
-
			sqlite3_finalize(stmt);
-
			return (true);
-
		}
-
	}
-

-
	sqlite3_finalize(stmt);
-

-
	return (false);
-
}
-

-
int
-
pkgdb_sql_all_attached(sqlite3 *s, struct sbuf *sql, const char *multireposql,
-
    const char *compound)
-
{
-
	sqlite3_stmt	*stmt;
-
	const char	*dbname;
-
	int		 dbcount = 0;
-
	int		 ret;
-

-
	assert(s != NULL);
-
	assert(compound != NULL);
-

-
	ret = sqlite3_prepare_v2(s, "PRAGMA database_list;", -1, &stmt, NULL);
-
	if (ret != SQLITE_OK) {
-
		ERROR_SQLITE(s, "PRAGMA database_list;");
-
		return (EPKG_FATAL);
-
	}
-

-
	while (sqlite3_step(stmt) != SQLITE_DONE) {
-
		dbname = sqlite3_column_text(stmt, 1);
-
		if ((strcmp(dbname, "main") == 0) ||
-
		    (strcmp(dbname, "temp") == 0))
-
			continue;
-

-
		dbcount++;
-

-
		if (dbcount > 1)
-
			sbuf_cat(sql, compound);
-

-
		/* replace any occurences of the dbname in the resulting SQL */
-
		sbuf_printf(sql, multireposql, dbname);
-
	}
-

-
	sqlite3_finalize(stmt);
-

-
	/* The generated SQL statement will not be syntactically
-
	 * correct unless there is at least one other attached DB than
-
	 * main or temp */
-

-
	return (dbcount > 0 ? EPKG_OK : EPKG_FATAL);
-
}
-

-
static void
-
pkgdb_detach_remotes(sqlite3 *s)
-
{
-
	sqlite3_stmt	*stmt;
-
	struct sbuf	*sql = NULL;
-
	const char	*dbname;
-
	int		 ret;
-

-
	assert(s != NULL);
-

-
	ret = sqlite3_prepare_v2(s, "PRAGMA database_list;", -1, &stmt, NULL);
-
	if (ret != SQLITE_OK) {
-
		ERROR_SQLITE(s, "PRAGMA database_list;");
-
		return;
-
	}
-

-
	sql = sbuf_new_auto();
-

-
	while (sqlite3_step(stmt) != SQLITE_DONE) {
-
		dbname = sqlite3_column_text(stmt, 1);
-
		if ((strcmp(dbname, "main") == 0) ||
-
		    (strcmp(dbname, "temp") == 0))
-
			continue;
-

-
		sbuf_clear(sql);
-
		sbuf_printf(sql, "DETACH '%s';", dbname);
-
		sbuf_finish(sql);
-
		sql_exec(s, sbuf_get(sql));
-
	}
-

-
	sqlite3_finalize(stmt);
-

-
	sbuf_delete(sql);
-
}
-

int
get_pragma(sqlite3 *s, const char *sql, int64_t *res, bool silence)
{
modified libpkg/private/pkg.h
@@ -320,6 +320,18 @@ struct pkg_repo_meta {
	time_t eol;
};

+
struct pkg_remote_it_ops {
+
	int (*next)(struct pkg_repo_it *it, struct pkg **pkg_p, unsigned flags);
+
	void (*free)(struct pkg_repo_it *it);
+
	void (*reset)(struct pkg_repo_it *it);
+
};
+

+
struct pkg_repo_it {
+
	struct pkg_repo *repo;
+
	struct pkg_remote_it_ops *ops;
+
	char data[0];
+
};
+

struct pkg_repo_ops {
	const char *type;
	/* Accessing repo */
@@ -333,7 +345,7 @@ struct pkg_repo_ops {
	int (*update)(struct pkg_repo *, bool);

	/* Query repo */
-
	struct pkgdb_it * (*query)(struct pkg_repo *,
+
	struct pkg_repo_it * (*query)(struct pkg_repo *,
					const char *, match_t);

	/* Fetch package from repo */
modified libpkg/private/pkgdb.h
@@ -39,15 +39,25 @@ struct pkgdb {
	bool		 prstmt_initialized;
};

-
struct pkgdb_it {
+
struct pkgdb_sqlite_it {
	struct pkgdb	*db;
	sqlite3	*sqlite;
	sqlite3_stmt	*stmt;
-
	short	type;
	short	flags;
	short	finished;
};

+
struct pkgdb_it {
+
	int	type;
+
	union _un_pkg_it {
+
		struct _pkg_repo_it_set {
+
			struct pkg_repo_it *it;
+
			struct _pkg_repo_it_set *next;
+
		} *remote;
+
		struct pkgdb_sqlite_it *local;
+
	} un;
+
};
+

#define PKGDB_IT_FLAG_CYCLED (0x1)
#define PKGDB_IT_FLAG_ONCE (0x1 << 1)
#define PKGDB_IT_FLAG_AUTO (0x1 << 2)
@@ -79,26 +89,6 @@ int pkgdb_repo_register_conflicts(const char *origin, char **conflicts,
		int conflicts_num, sqlite3 *sqlite);

/**
-
 * Execute SQL statement on all attached databases
-
 * @param s
-
 * @param sql
-
 * @param multireposql
-
 * @param compound
-
 * @return
-
 */
-
int
-
pkgdb_sql_all_attached(sqlite3 *s, struct sbuf *sql, const char *multireposql,
-
    const char *compound);
-

-
/**
-
 * Get repository name
-
 * @param db
-
 * @param repo
-
 * @return
-
 */
-
const char *pkgdb_get_reponame(struct pkgdb *db, const char *repo);
-

-
/**
 * Get query for the specified match type
 * @param pattern
 * @param match