def getFlattenedOverlayTree(self, derived_series): """See `IDistroSeriesParentSet`.""" self.getByDerivedSeries(derived_series) rec_overlay_query = ''' RECURSIVE t_parents(parent_series) AS ( SELECT parent_series FROM DistroSeriesParent WHERE derived_series=? AND is_overlay = True UNION ALL SELECT dsp.parent_series FROM DistroSeriesParent dsp, t_parents p WHERE dsp.derived_series = p.parent_series AND dsp.is_overlay = True ) ''' store = IStore(DistroSeriesParent) # XXX: rvb 2011-05-20 bug=785733: Order by DSD.id for now. # Once the ordering is specified in the database, it should # be used to sort the results. return store.with_( SQL(rec_overlay_query, (derived_series.id, ))).find( DistroSeriesParent, SQL('DistroSeriesParent.parent_series IN ' '(SELECT parent_series FROM t_parents)') ).order_by(DistroSeriesParent.id)
def get_specification_privacy_filter(user): # Circular imports. from lp.registry.model.accesspolicy import AccessPolicyGrant public_spec_filter = ( Specification.information_type.is_in(PUBLIC_INFORMATION_TYPES)) if user is None: return [public_spec_filter] elif IPersonRoles.providedBy(user): user = user.person artifact_grant_query = Coalesce( ArrayIntersects( SQL('Specification.access_grants'), Select(ArrayAgg(TeamParticipation.teamID), tables=TeamParticipation, where=(TeamParticipation.person == user))), False) policy_grant_query = Coalesce( ArrayIntersects( Array(SQL('Specification.access_policy')), Select(ArrayAgg(AccessPolicyGrant.policy_id), tables=(AccessPolicyGrant, Join( TeamParticipation, TeamParticipation.teamID == AccessPolicyGrant.grantee_id)), where=(TeamParticipation.person == user))), False) return [Or(public_spec_filter, artifact_grant_query, policy_grant_query)]
def all_deps(self, user=None): return list( Store.of(self).with_( SQL(recursive_dependent_query(user), params=(self.id, ))).find( Specification, Specification.id != self.id, Specification.id.is_in(SQL('select id from dependencies')), ).order_by(Specification.name, Specification.id))
def all_blocked(self, user=None): """See `ISpecification`.""" return list( Store.of(self).with_( SQL(recursive_blocked_query(user), params=(self.id, ))).find( Specification, Specification.id != self.id, Specification.id.is_in(SQL('select id from blocked')), ).order_by(Specification.name, Specification.id))
def _order_by(self): """Look at the context to provide grouping. If the blueprint is for a project, then matching results for that project should be first. If the blueprint is set for a series, then that series should come before others for the project. Similarly for the distribution, and the series goal for the distribution. If all else is equal, the ordering is by name, then database id as a final uniqueness resolver. """ order_statements = [] spec = self.context if spec.product is not None: order_statements.append( "(CASE Specification.product WHEN %s THEN 0 ELSE 1 END)" % spec.product.id) if spec.productseries is not None: order_statements.append( "(CASE Specification.productseries" " WHEN %s THEN 0 ELSE 1 END)" % spec.productseries.id) elif spec.distribution is not None: order_statements.append( "(CASE Specification.distribution WHEN %s THEN 0 ELSE 1 END)" % spec.distribution.id) if spec.distroseries is not None: order_statements.append( "(CASE Specification.distroseries" " WHEN %s THEN 0 ELSE 1 END)" % spec.distroseries.id) order_statements.append("Specification.name") order_statements.append("Specification.id") return SQL(', '.join(order_statements))
def create(cls, repository_name, repository_path): "See `IReclaimGitRepositorySpaceJobSource`.""" metadata = { "repository_name": repository_name, "repository_path": repository_path, } # The GitJob has a repository of None, as there is no repository # left in the database to refer to. start = SQL("CURRENT_TIMESTAMP AT TIME ZONE 'UTC' + '7 days'") git_job = GitJob( None, cls.class_job_type, metadata, scheduled_start=start) job = cls(git_job) job.celeryRunOnCommit() return job
def search(self, text, limit): """See `IPillarSet`.""" # Avoid circular import. from lp.registry.model.product import ProductWithLicenses if limit is None: limit = config.launchpad.default_batch_size # Pull out the licences as a subselect which is converted # into a PostgreSQL array so that multiple licences per product # can be retrieved in a single row for each product. extra_column = ProductWithLicenses.composeLicensesColumn() result = self.build_search_query(text, [extra_column]) # If the search text matches the name or title of the # Product, Project, or Distribution exactly, then this # row should get the highest search rank (9999999). # Each row in the PillarName table will join with only one # of either the Product, Project, or Distribution tables, # so the coalesce() is necessary to find the rank() which # is not null. result.order_by( SQL(''' (CASE WHEN PillarName.name = lower(%(text)s) OR lower(Product.title) = lower(%(text)s) OR lower(Project.title) = lower(%(text)s) OR lower(Distribution.title) = lower(%(text)s) THEN 9999999 ELSE coalesce(rank(Product.fti, ftq(%(text)s)), rank(Project.fti, ftq(%(text)s)), rank(Distribution.fti, ftq(%(text)s))) END) DESC, PillarName.name ''' % sqlvalues(text=text))) # People shouldn't be calling this method with too big limits longest_expected = 2 * config.launchpad.default_batch_size if limit > longest_expected: warnings.warn("The search limit (%s) was greater " "than the longest expected size (%s)" % (limit, longest_expected), stacklevel=2) pillars = [] # Prefill pillar.product.licenses. for pillar_name, other, product, project, distro, licenses in ( result[:limit]): pillar = pillar_name.pillar if IProduct.providedBy(pillar): pillar = ProductWithLicenses(pillar, licenses) pillars.append(pillar) return pillars
def getOnePOFile(self): """See `ITranslationMessage`.""" from lp.translations.model.pofile import POFile # Get any POFile where this translation exists. # Because we can't create a subselect with "LIMIT" using Storm, # we directly embed a subselect using raw SQL instead. # We can do this because our message sharing code ensures a POFile # exists for any of the sharing templates. # This approach gives us roughly a 100x performance improvement # compared to straightforward join as of 2010-11-11. - danilo pofile = IStore(self).find( POFile, POFile.potemplateID == SQL("""(SELECT potemplate FROM TranslationTemplateItem WHERE potmsgset = %s AND sequence > 0 LIMIT 1)""" % sqlvalues(self.potmsgsetID)), POFile.language == self.language).one() return pofile
def getSharedEquivalent(self): """See `ITranslationMessage`.""" clauses = [ 'potemplate IS NULL', 'potmsgset = %s' % sqlvalues(self.potmsgset), 'language = %s' % sqlvalues(self.language), ] for form in range(TranslationConstants.MAX_PLURAL_FORMS): msgstr_name = 'msgstr%d' % form msgstr = getattr(self, 'msgstr%dID' % form) if msgstr is None: form_clause = "%s IS NULL" % msgstr_name else: form_clause = "%s = %s" % (msgstr_name, quote(msgstr)) clauses.append(form_clause) where_clause = SQL(' AND '.join(clauses)) return Store.of(self).find(TranslationMessage, where_clause).one()
def build_search_query(self, text, extra_columns=()): """Query parameters shared by search() and count_search_matches(). :returns: Storm ResultSet object """ # These classes are imported in this method to prevent an import loop. from lp.registry.model.product import Product from lp.registry.model.projectgroup import ProjectGroup from lp.registry.model.distribution import Distribution OtherPillarName = ClassAlias(PillarName) origin = [ PillarName, LeftJoin(OtherPillarName, PillarName.alias_for == OtherPillarName.id), LeftJoin(Product, PillarName.product == Product.id), LeftJoin(ProjectGroup, PillarName.project == ProjectGroup.id), LeftJoin(Distribution, PillarName.distribution == Distribution.id), ] conditions = SQL(''' PillarName.active = TRUE AND (PillarName.name = lower(%(text)s) OR Product.fti @@ ftq(%(text)s) OR lower(Product.title) = lower(%(text)s) OR Project.fti @@ ftq(%(text)s) OR lower(Project.title) = lower(%(text)s) OR Distribution.fti @@ ftq(%(text)s) OR lower(Distribution.title) = lower(%(text)s) ) ''' % sqlvalues(text=ensure_unicode(text))) columns = [ PillarName, OtherPillarName, Product, ProjectGroup, Distribution ] for column in extra_columns: columns.append(column) return IStore(PillarName).using(*origin).find(tuple(columns), conditions)
def preloadBuildsData(self, builds): # Circular import. from lp.snappy.model.snap import Snap load_related(Person, builds, ["requester_id"]) lfas = load_related(LibraryFileAlias, builds, ["log_id"]) load_related(LibraryFileContent, lfas, ["contentID"]) archives = load_related(Archive, builds, ["archive_id"]) load_related(Person, archives, ["ownerID"]) distroarchseries = load_related( DistroArchSeries, builds, ['distro_arch_series_id']) distroseries = load_related( DistroSeries, distroarchseries, ['distroseriesID']) load_related(Distribution, distroseries, ['distributionID']) snaps = load_related(Snap, builds, ["snap_id"]) getUtility(ISnapSet).preloadDataForSnaps(snaps) snapbuild_ids = set(map(attrgetter("id"), builds)) latest_jobs_cte = With("LatestJobs", Select( (SnapBuildJob.job_id, SQL( "rank() OVER " "(PARTITION BY snapbuild ORDER BY job DESC) AS rank")), tables=SnapBuildJob, where=And( SnapBuildJob.snapbuild_id.is_in(snapbuild_ids), SnapBuildJob.job_type == SnapBuildJobType.STORE_UPLOAD))) LatestJobs = Table("LatestJobs") sbjs = list(IStore(SnapBuildJob).with_(latest_jobs_cte).using( SnapBuildJob, LatestJobs).find( SnapBuildJob, SnapBuildJob.job_id == Column("job", LatestJobs), Column("rank", LatestJobs) == 1)) sbj_map = {} for sbj in sbjs: sbj_map[sbj.snapbuild] = sbj.makeDerived() for build in builds: get_property_cache(build).last_store_upload_job = ( sbj_map.get(build)) load_related(Job, sbjs, ["job_id"])
def _exclude_blocked_query(self): """Return the select statement to exclude already blocked specs.""" user = getattr(getUtility(ILaunchBag), 'user', None) return SQL( "Specification.id not in (WITH %s select id from blocked)" % ( recursive_blocked_query(user)), params=(self.context.id,))