Skip to content

Instantly share code, notes, and snippets.

@dnaeon
Created July 31, 2011 13:18
Show Gist options
  • Save dnaeon/1116790 to your computer and use it in GitHub Desktop.
Save dnaeon/1116790 to your computer and use it in GitHub Desktop.
int
pkgdb_rquery_build_search_query(struct sbuf *sql, match_t match, unsigned int field)
{
switch (match) {
case MATCH_ALL:
case MATCH_EXACT:
sbuf_cat(sql, "name LIKE ?1 ");
if (field & REPO_SEARCH_COMMENT)
sbuf_cat(sql, "OR comment LIKE ?1 ");
else if (field & REPO_SEARCH_DESCRIPTION)
sbuf_cat(sql, "OR desc LIKE ?1 ");
break;
case MATCH_GLOB:
sbuf_cat(sql, "name GLOB ?1 ");
if (field & REPO_SEARCH_COMMENT)
sbuf_cat(sql, "OR comment GLOB ?1 ");
else if (field & REPO_SEARCH_DESCRIPTION)
sbuf_cat(sql, "OR desc GLOB ?1 ");
break;
case MATCH_REGEX:
sbuf_cat(sql, "name REGEXP ?1 ");
if (field & REPO_SEARCH_COMMENT)
sbuf_cat(sql, "OR comment REGEXP ?1 ");
else if (field & REPO_SEARCH_DESCRIPTION)
sbuf_cat(sql, "OR desc REGEXP ?1 ");
break;
case MATCH_EREGEX:
sbuf_cat(sql, "EREGEXP(?1, name) ");
if (field & REPO_SEARCH_COMMENT)
sbuf_cat(sql, "OR EREGEXP(?1, comment) ");
else if (field & REPO_SEARCH_DESCRIPTION)
sbuf_cat(sql, "OR EREGEXP(?1, desc) ");
break;
}
return (EPKG_OK);
}
struct pkgdb_it *
pkgdb_rquery(struct pkgdb *db, const char *pattern, match_t match, unsigned int field)
{
const char *dbname = NULL;
char tmpbuf[BUFSIZ];
sqlite3_stmt *stmt = NULL;
struct sbuf *sql = NULL;
struct pkg_repos *repos = NULL;
struct pkg_repos_entry *re = NULL;
const char *basesql = "SELECT rowid, origin, name, version, comment, "
"desc, arch, arch, osversion, maintainer, www, "
"flatsize, pkgsize, cksum, path, dbname FROM ";
assert(pattern != NULL && pattern[0] != '\0');
if (db->type != PKGDB_REMOTE) {
EMIT_PKG_ERROR("%s", "remote database not attached (misuse)");
return (NULL);
}
sql = sbuf_new_auto();
sbuf_cat(sql, basesql);
if (strcmp(pkg_config("PKG_MULTIREPOS"), "true") == 0) {
/*
* Working on multiple remote repositories
*/
if (pkg_repos_new(&repos) != EPKG_OK) {
EMIT_PKG_ERROR("pkg_repos_new: %s", "cannot create multi repo object");
return (NULL);
}
if (pkg_repos_load(repos) != EPKG_OK) {
EMIT_PKG_ERROR("pkg_repos_load: %s", "cannot load repositories");
return (NULL);
}
/* get the first repository entry */
if (pkg_repos_next(repos, &re) == EPKG_OK) {
dbname = pkg_repos_get_name(re);
snprintf(tmpbuf, sizeof(tmpbuf),
"( SELECT rowid, origin, name, version, comment, "
"desc, arch, arch, osversion, maintainer, www, "
"flatsize, pkgsize, cksum, path, '%s' AS dbname FROM '%s'.packages WHERE ",
dbname, dbname);
// TODO: check for 1 remote repo, and directly select from it
sbuf_cat(sql, tmpbuf);
pkgdb_rquery_build_search_query(sql, match, field);
// TODO: choose a more generic name for the above function
}
while (pkg_repos_next(repos, &re) == EPKG_OK) {
dbname = pkg_repos_get_name(re);
snprintf(tmpbuf, sizeof(tmpbuf),
"UNION SELECT rowid, origin, name, version, comment, "
"desc, arch, arch, osversion, maintainer, www, "
"flatsize, pkgsize, cksum, path, '%s' AS dbname FROM '%s'.packages WHERE ",
dbname, dbname);
sbuf_cat(sql, tmpbuf);
pkgdb_rquery_build_search_query(sql, match, field);
}
pkg_repos_free(repos);
}
sbuf_cat(sql, " );");
sbuf_finish(sql);
printf("'%s'\n", sbuf_get(sql));
if (sqlite3_prepare_v2(db->sqlite, sbuf_get(sql), -1, &stmt, NULL) != SQLITE_OK) {
ERROR_SQLITE(db->sqlite);
return (NULL);
}
sbuf_delete(sql);
sqlite3_bind_text(stmt, 1, pattern, -1, SQLITE_TRANSIENT);
return (pkgdb_it_new(db, stmt, PKG_REMOTE));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment