def _filter_releases_by_query(queryset, organization, query, filter_params): search_filters = parse_search_query(query) for search_filter in search_filters: if search_filter.key.name == RELEASE_FREE_TEXT_KEY: query_q = Q(version__icontains=query) suffix_match = _release_suffix.match(query) if suffix_match is not None: query_q |= Q(version__icontains="%s+%s" % suffix_match.groups()) queryset = queryset.filter(query_q) if search_filter.key.name == RELEASE_ALIAS: if search_filter.value.is_wildcard(): raw_value = search_filter.value.raw_value if raw_value.endswith("*") and raw_value.startswith("*"): query_q = Q(version__contains=raw_value[1:-1]) elif raw_value.endswith("*"): query_q = Q(version__startswith=raw_value[:-1]) elif raw_value.startswith("*"): query_q = Q(version__endswith=raw_value[1:]) elif search_filter.operator == "!=": query_q = ~Q(version=search_filter.value.value) else: query_q = Q(version=search_filter.value.value) queryset = queryset.filter(query_q) if search_filter.key.name == SEMVER_ALIAS: queryset = queryset.filter_by_semver( organization.id, parse_semver(search_filter.value.raw_value, search_filter.operator) ) if search_filter.key.name == SEMVER_PACKAGE_ALIAS: negated = True if search_filter.operator == "!=" else False queryset = queryset.filter_by_semver( organization.id, SemverFilter("exact", [], search_filter.value.raw_value, negated), ) if search_filter.key.name == RELEASE_STAGE_ALIAS: queryset = queryset.filter_by_stage( organization.id, search_filter.operator, search_filter.value.value, project_ids=filter_params["project_id"], environments=filter_params.get("environment"), ) if search_filter.key.name == SEMVER_BUILD_ALIAS: (operator, negated) = handle_operator_negation(search_filter.operator) queryset = queryset.filter_by_semver_build( organization.id, OPERATOR_TO_DJANGO[operator], search_filter.value.raw_value, negated=negated, ) return queryset
def _filter_releases_by_query(queryset, organization, query): search_filters = parse_search_query(query) for search_filter in search_filters: if search_filter.key.name == RELEASE_FREE_TEXT_KEY: query_q = Q(version__icontains=query) suffix_match = _release_suffix.match(query) if suffix_match is not None: query_q |= Q(version__icontains="%s+%s" % suffix_match.groups()) queryset = queryset.filter(query_q) if search_filter.key.name == RELEASE_ALIAS: if search_filter.value.is_wildcard(): raw_value = search_filter.value.raw_value if raw_value.endswith("*") and raw_value.startswith("*"): query_q = Q(version__contains=raw_value[1:-1]) elif raw_value.endswith("*"): query_q = Q(version__startswith=raw_value[:-1]) elif raw_value.startswith("*"): query_q = Q(version__endswith=raw_value[1:]) else: query_q = Q(version=search_filter.value.value) queryset = queryset.filter(query_q) if search_filter.key.name == SEMVER_ALIAS: queryset = queryset.filter_by_semver( organization.id, parse_semver(search_filter.value.raw_value, search_filter.operator), ) if search_filter.key.name == SEMVER_PACKAGE_ALIAS: queryset = queryset.filter_by_semver( organization.id, SemverFilter("exact", [], search_filter.value.raw_value), ) if search_filter.key.name == RELEASE_STAGE_ALIAS: queryset = queryset.filter_by_stage( organization.id, search_filter.operator, search_filter.value.value ) if search_filter.key.name == SEMVER_BUILD_ALIAS: queryset = queryset.filter_by_semver_build( organization.id, OPERATOR_TO_DJANGO[search_filter.operator], search_filter.value.raw_value, ) return queryset
def _get_tag_values_for_semver( self, projects: Sequence[int], environments: Optional[Sequence[str]], query: Optional[str], ): from sentry.api.paginator import SequencePaginator query = query if query else "" organization_id = Project.objects.filter(id=projects[0]).values_list( "organization_id", flat=True )[0] if query and "@" not in query and re.search(r"[^\d.\*]", query): # Handle searching just on package include_package = True versions = self._get_semver_versions_for_package(projects, organization_id, query) else: include_package = "@" in query if not query: query = "*" elif query[-1] not in SEMVER_WILDCARDS | {"@"}: if query[-1] != ".": query += "." query += "*" versions = Release.objects.filter_by_semver( organization_id, parse_semver(query, "="), project_ids=projects, ) if environments: versions = versions.filter( id__in=ReleaseEnvironment.objects.filter( environment_id__in=environments ).values_list("release_id", flat=True) ) order_by = map(_flip_field_sort, Release.SEMVER_COLS + ["package"]) versions = ( versions.filter_to_semver().order_by(*order_by).values_list("version", flat=True)[:1000] ) seen = set() formatted_versions = [] # We want to format versions here in a way that makes sense for autocomplete. So we # - Only include package if we think the user entered a package # - Exclude build number, since it's not used as part of filtering # When we don't include package, this can result in duplicate version numbers, so we # also de-dupe here. This can result in less than 1000 versions returned, but we # typically use very few values so this works ok. for version in versions: formatted_version = version if include_package else version.split("@", 1)[1] formatted_version = formatted_version.split("+", 1)[0] if formatted_version in seen: continue seen.add(formatted_version) formatted_versions.append(formatted_version) return SequencePaginator( [ (i, TagValue(SEMVER_ALIAS, v, None, None, None)) for i, v in enumerate(formatted_versions) ] )