Hello, I have attached the patch for the conjunctive search. Raw sql commands are the following: First I find files with the ctags. (there are 2 tags in the following case) SELECT ctags.file_id AS file_id FROM ctags JOIN files ON files.id = ctags.file_id WHERE ctags.tag IN (:tag_1, :tag_2) GROUP BY ctags.file_id HAVING count(DISTINCT ctags.tag) = 2 then i use the ids i recovered to find the package names etc. (there are 4 ids as the first command had 4 results.) SELECT files.id AS file_id, package_names.name AS package, packages.version AS version, files.path AS path FROM files, package_names, packages WHERE files.package_id = packages.id AND files.id IN (:id_1, :id_2, :id_3, :id_4) AND packages.name_id = package_names.id Cheers
From 34e6c018afeba3e633afebe80a77ca4e9a777a59 Mon Sep 17 00:00:00 2001 From: Orestis Ioannou <orestis@oioannou.com> Date: Thu, 12 Mar 2015 13:53:34 +0100 Subject: [PATCH] Webapp: Add conjunctive search for ctags Closes: #761867 --- debsources/app/sources/routes.py | 9 +++++ .../app/sources/templates/sources/test_ctag.html | 43 ++++++++++++++++++++++ debsources/app/views.py | 16 ++++++-- debsources/models.py | 32 ++++++++++++++++ debsources/tests/test_webapp.py | 7 ++++ 5 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 debsources/app/sources/templates/sources/test_ctag.html diff --git a/debsources/app/sources/routes.py b/debsources/app/sources/routes.py index 1ac8282..eec69c3 100644 --- a/debsources/app/sources/routes.py +++ b/debsources/app/sources/routes.py @@ -198,6 +198,15 @@ bp_sources.add_url_rule( err_func=ErrorHandler('sources'), pagination=True)) +# CtagView +bp_sources.add_url_rule( + '/test_ctag/', + view_func=CtagView.as_view( + 'test_ctag', + render_func=bind_render('sources/test_ctag.html'), + err_func=ErrorHandler('sources'), + pagination=True)) + # api bp_sources.add_url_rule( diff --git a/debsources/app/sources/templates/sources/test_ctag.html b/debsources/app/sources/templates/sources/test_ctag.html new file mode 100644 index 0000000..fa5e41e --- /dev/null +++ b/debsources/app/sources/templates/sources/test_ctag.html @@ -0,0 +1,43 @@ +{# + Copyright (C) 2013 Matthieu Caneill <matthieu.caneill@gmail.com> + License: GNU Affero General Public License, version 3 or above. +#} +{# copied from templates/ctag.html #} + +{% extends "sources/base.html" %} +n +{% block title %}Ctag: {{ ctag }} +{% if package %}(in package {{ package }}){% endif %} +(page {{ page }}){% endblock %} + +{% block breadcrumbs %}ctag / {{ sha256 }}{% endblock %} + +{% block content %} + +<h2>{{ self.title() }}</h2> + +{{ count }} result{% if count >= 2 %}s{% endif %}: + +<ul> + {% for result in results %} + <li> + {% if conjunctive %} + <a href="{{ url_for('.source', + path_to="%s/%s/%s" % (result.package, result.version, + result.path)) }}"> + {{ result.package }}/{{ result.version }}/{{ result.path }}</a> + {% else %} + <a href="{{ url_for('.source', + path_to="%s/%s/%s" % (result.package, result.version, + result.path), + hl = result.line, + _anchor="L%d" % result.line) }}"> + {{ result.package }}/{{ result.version }}/{{ result.path }}</a> + {% endif %} + </li> + {% endfor %} +</ul> + +{{ macros.render_pagination(pagination) }} + +{% endblock %} diff --git a/debsources/app/views.py b/debsources/app/views.py index ba27494..99bc2b8 100644 --- a/debsources/app/views.py +++ b/debsources/app/views.py @@ -425,8 +425,17 @@ class CtagView(GeneralView): else: pagination = None slice_ = None - count, results = Ctag.find_ctag(session, ctag, slice_=slice_, - package=package) + + conjunctive = False + if ',' in ctag: + ctags = ctag.split(',') + conjunctive = True + (count, results) = Ctag.conjunctive_search(session, + ctags, slice_=slice_, + package=package) + else: + (count, results) = Ctag.find_ctag(session, ctag, slice_=slice_, + package=package) if self.d.get('pagination'): pagination = Pagination(page, offset, count) else: @@ -437,7 +446,8 @@ class CtagView(GeneralView): count=count, page=page, package=package, - pagination=pagination) + pagination=pagination, + conjunctive=conjunctive) class PrefixView(GeneralView): diff --git a/debsources/models.py b/debsources/models.py index e4d05fc..94d4f42 100644 --- a/debsources/models.py +++ b/debsources/models.py @@ -386,6 +386,38 @@ class Ctag(Base): for res in results.all()] return (count, results) + @staticmethod + def conjunctive_search(session, ctags, package=None, slice_=None): + find_files = (session.query(Ctag.file_id.label("file_id")) + .join(File) + .filter(Ctag.tag.in_(ctags)) + .group_by(Ctag.file_id) + .having(sql_func.count(Ctag.tag.distinct()) + == len(ctags)) + ) + + results = (session.query(File.id.label("file_id"), + PackageName.name.label("package"), + Package.version.label("version"), + File.path.label("path"), + ) + .filter(File.package_id == Package.id) + .filter(File.id.in_(find_files.all())) + .filter(Package.name_id == PackageName.id) + ) + if package is not None: + results = results.filter(PackageName.name == package) + results = results.order_by(File.id, File.path) + count = results.count() + if slice_ is not None: + results = results.slice(slice_[0], slice_[1]) + results = [dict(package=res.package, + version=res.version, + path=res.path, + id=res.file_id) + for res in results.all()] + return (count, results) + class Metric(Base): __tablename__ = 'metrics' diff --git a/debsources/tests/test_webapp.py b/debsources/tests/test_webapp.py index d4eb3c8..c5cf3bd 100644 --- a/debsources/tests/test_webapp.py +++ b/debsources/tests/test_webapp.py @@ -422,6 +422,13 @@ class DebsourcesTestCase(unittest.TestCase, DbTestFixture): self.assertEqual(rv["count"], 113) self.assertEqual(len(rv["results"]), 113) + def test_api_conjunctive_search_ctag(self): + rv = json.loads(self.app.get('/api/ctag/?ctag=size,main').data) + self.assertEqual(len(rv["results"]), 4) + self.assertEqual(rv["results"][3], {'path': 'examples/input.c', + 'version': u'0.99.beta17-1', + 'id': 3891, 'package': u'libcaca'}) + def test_api_search_ctag_within_package(self): rv = json.loads(self.app.get( '/api/ctag/?ctag=name&package=ledger').data) -- 2.1.4
Attachment:
signature.asc
Description: OpenPGP digital signature