Improve 'latest' filter

Previous version didn't consider user's filters, and
therefore 'latest' filter was applied before them. It led to
the fact that some artifacts weren't shown in list output.
New version fixes this behaviour.

Change-Id: I7ae870d3cb575a6060901ac8321fdc7a7b6d4b4d
This commit is contained in:
Mike Fedosin 2016-09-22 10:02:33 +03:00
parent 58bf974671
commit b96c2cb8a2
2 changed files with 73 additions and 42 deletions

View File

@ -203,14 +203,46 @@ def get_all(context, session, filters=None, marker=None, limit=None,
return [af.to_dict() for af in artifacts]
def _get_all(context, session, filters=None, marker=None, limit=None,
sort=None, latest=False):
def _apply_latest_filter(context, session, query,
basic_conds, tag_conds, prop_conds):
# Subquery to fetch max version suffix for a group (name,
# version_prefix)
ver_suffix_subq = _apply_query_base_filters(
session.query(
models.Artifact.name,
models.Artifact.version_prefix,
func.max(models.Artifact.version_suffix).label(
'max_suffix')).group_by(
models.Artifact.name, models.Artifact.version_prefix),
context)
ver_suffix_subq = _apply_user_filters(
ver_suffix_subq, basic_conds, tag_conds, prop_conds).subquery()
# Subquery to fetch max version prefix for a name group
ver_prefix_subq = _apply_query_base_filters(
session.query(models.Artifact.name, func.max(
models.Artifact.version_prefix).label('max_prefix')).group_by(
models.Artifact.name),
context)
ver_prefix_subq = _apply_user_filters(
ver_prefix_subq, basic_conds, tag_conds, prop_conds).subquery()
# Combine two subqueries together joining them with Artifact table
query = query.join(
ver_prefix_subq,
and_(models.Artifact.name == ver_prefix_subq.c.name,
models.Artifact.version_prefix ==
ver_prefix_subq.c.max_prefix)).join(
ver_suffix_subq,
and_(models.Artifact.name == ver_suffix_subq.c.name,
models.Artifact.version_prefix ==
ver_suffix_subq.c.version_prefix,
models.Artifact.version_suffix ==
ver_suffix_subq.c.max_suffix)
)
filters = filters or {}
return query
query = _do_artifacts_query(context, session, latest)
basic_conds, tag_conds, prop_conds = _do_query_filters(filters)
def _apply_user_filters(query, basic_conds, tag_conds, prop_conds):
if basic_conds:
for basic_condition in basic_conds:
@ -226,6 +258,24 @@ def _get_all(context, session, filters=None, marker=None, limit=None,
query = query.join(models.ArtifactProperty, aliased=True).filter(
and_(*prop_condition))
return query
def _get_all(context, session, filters=None, marker=None, limit=None,
sort=None, latest=False):
filters = filters or {}
query = _do_artifacts_query(context, session)
basic_conds, tag_conds, prop_conds = _do_query_filters(filters)
query = _apply_user_filters(query, basic_conds, tag_conds, prop_conds)
if latest:
query = _apply_latest_filter(context, session, query,
basic_conds, tag_conds, prop_conds)
marker_artifact = None
if marker is not None:
marker_artifact = get(context, marker, session)
@ -334,37 +384,6 @@ def _do_artifacts_query(context, session, latest=False):
query = session.query(models.Artifact)
if latest:
# Subquery to fetch max version suffix for a group (name,
# version_prefix)
ver_suffix_subq = _apply_query_base_filters(
session.query(
models.Artifact.name,
models.Artifact.version_prefix,
func.max(models.Artifact.version_suffix).label(
'max_suffix')).group_by(
models.Artifact.name, models.Artifact.version_prefix),
context).subquery()
# Subquery to fetch max version prefix for a name group
ver_prefix_subq = _apply_query_base_filters(
session.query(models.Artifact.name, func.max(
models.Artifact.version_prefix).label('max_prefix')).group_by(
models.Artifact.name),
context).subquery()
# Combine two subqueries together joining them with Artifact table
query = query.join(
ver_prefix_subq,
and_(models.Artifact.name == ver_prefix_subq.c.name,
models.Artifact.version_prefix ==
ver_prefix_subq.c.max_prefix)).join(
ver_suffix_subq,
and_(models.Artifact.name == ver_suffix_subq.c.name,
models.Artifact.version_prefix ==
ver_suffix_subq.c.version_prefix,
models.Artifact.version_suffix ==
ver_suffix_subq.c.max_suffix)
)
query = (query.options(joinedload(models.Artifact.properties)).
options(joinedload(models.Artifact.tags)).
options(joinedload(models.Artifact.blobs)))
@ -373,10 +392,6 @@ def _do_artifacts_query(context, session, latest=False):
def _apply_query_base_filters(query, context):
# Don't show deleted artifacts
query = query.filter(models.Artifact.status != 'deleted')
# Don't show deleted artifacts
query = query.filter(models.Artifact.status != 'deleted')

View File

@ -687,17 +687,19 @@ class TestList(TestArtifact):
{'name': 'group1',
'version': group1_versions[i],
'tags': ['tag%s' % i],
'int1': 2048,
'int1': 2048 + i,
'float1': 123.456,
'str1': 'bugaga',
"string_required": "test_str",
'bool1': True})
self.create_artifact(
{'name': 'group2',
'version': group2_versions[i],
'tags': ['tag%s' % i],
'int1': 2048,
'int1': 2048 + i,
'float1': 123.456,
'str1': 'bugaga',
"string_required": "test_str",
'bool1': True})
url = '/sample_artifact?version=latest&sort=name:asc'
@ -706,6 +708,20 @@ class TestList(TestArtifact):
self.assertEqual('20.0.0', res[0]['version'])
self.assertEqual('1000.0.1', res[1]['version'])
self.patch('/sample_artifact/' + res[0]['id'], self.make_active)
url = '/sample_artifact?version=latest&sort=name:asc&status=drafted'
res = self.get(url=url, status=200)['sample_artifact']
self.assertEqual(2, len(res))
self.assertEqual('2.0.1', res[0]['version'])
self.assertEqual('1000.0.1', res[1]['version'])
url = '/sample_artifact?version=latest&sort=name:asc&int1=2050'
res = self.get(url=url, status=200)['sample_artifact']
self.assertEqual(2, len(res))
self.assertEqual('2.0.0', res[0]['version'])
self.assertEqual('99.0.0', res[1]['version'])
url = '/sample_artifact?version=latest&name=group1'
res = self.get(url=url, status=200)['sample_artifact']
self.assertEqual(1, len(res))