Search in sources :

Example 1 with JPASubQuery

use of com.mysema.query.jpa.JPASubQuery in project opencast by opencast.

the class AbstractAssetManagerDeleteSnapshotTest method testDeleteOneVersionOfOne.

/**
 * If, after deleting versions of an episode at least one version remains, no properties of the episode should be deleted.
 */
@Test
public void testDeleteOneVersionOfOne() throws Exception {
    final String[] mp = createAndAddMediaPackagesSimple(3, 2, 2);
    am.setProperty(p.agent.mk(mp[0], "agent-1"));
    am.setProperty(p.agent.mk(mp[1], "agent-2"));
    am.setProperty(p.agent.mk(mp[2], "agent-2"));
    assertTotals(6, 6, 3);
    assertStoreSize(6 * 2);
    if (RUN_RAW_QUERIES) {
        assertEquals(3, delete(Q_ASSET, Q_ASSET.snapshotId.in(new JPASubQuery().from(Q_SNAPSHOT).where(Q_SNAPSHOT.version.eq(new JPASubQuery().from(Q_SNAPSHOT).unique(Q_SNAPSHOT.version.min()))).list(Q_SNAPSHOT.id))));
        assertEquals(3, delete(Q_SNAPSHOT, Q_SNAPSHOT.version.eq(new JPASubQuery().from(Q_SNAPSHOT).unique(Q_SNAPSHOT.version.min()))));
    } else {
        assertEquals("Three snapshots should be deleted", 3, q.delete(OWNER, q.snapshot()).where(q.version().isFirst()).run());
    }
    assertTotals(3, 3, 3);
    assertStoreSize(3 * 2);
}
Also used : JPASubQuery(com.mysema.query.jpa.JPASubQuery) Test(org.junit.Test)

Example 2 with JPASubQuery

use of com.mysema.query.jpa.JPASubQuery in project opencast by opencast.

the class AbstractAssetManagerDeleteSnapshotTest method testDeleteAllVersionsOfOne.

/**
 * Deleting a complete episode should also delete all of its properties.
 * This test case deletes all versions (snapshots) of one episode.
 */
@Test
public void testDeleteAllVersionsOfOne() throws Exception {
    final int mpCount = 3;
    final int versionCount = 5;
    final String[] mp = createAndAddMediaPackagesSimple(mpCount, versionCount, versionCount);
    // each mp has one property
    am.setProperty(p.agent.mk(mp[0], "agent-1"));
    am.setProperty(p.agent.mk(mp[1], "agent-2"));
    am.setProperty(p.agent.mk(mp[2], "agent-2"));
    assertTotals(mpCount * versionCount, mpCount * versionCount, 3);
    assertStoreSize(mpCount * versionCount * 2);
    if (RUN_RAW_QUERIES) {
        delete(Q_PROPERTY, Q_PROPERTY.mediaPackageId.eq(mp[0]));
        delete(Q_ASSET, Q_ASSET.snapshotId.in(new JPASubQuery().from(Q_SNAPSHOT).where(Q_SNAPSHOT.mediaPackageId.eq(mp[0])).list(Q_SNAPSHOT.id)));
        delete(Q_SNAPSHOT, Q_SNAPSHOT.mediaPackageId.eq(mp[0]));
    } else {
        assertEquals(versionCount, q.delete(OWNER, q.snapshot()).where(q.mediaPackageId(mp[0])).run());
    }
    assertTotals((mpCount - 1) * versionCount, (mpCount - 1) * versionCount, 2);
    assertStoreSize((mpCount - 1) * versionCount * 2);
    assertPropertiesOfMediaPackage(0, mp[0]);
}
Also used : JPASubQuery(com.mysema.query.jpa.JPASubQuery) Test(org.junit.Test)

Example 3 with JPASubQuery

use of com.mysema.query.jpa.JPASubQuery in project opencast by opencast.

the class AbstractADeleteQuery method runQueries.

/**
 * Run this in a transaction.
 */
private DeletionResult runQueries(JPAQueryFactory jpa, DeleteQueryContribution c) {
    // # create Querydsl delete clause
    // # from
    // put into a set to remove duplicates
    final EntityPath<?> from;
    {
        final Set<EntityPath<?>> f = c.from.toSet(SetB.MH);
        if (f.size() == 1) {
            from = $(f).head2();
        } else {
            throw new RuntimeException("Only one entity is allowed in the from clause");
        }
    }
    // 
    if (from instanceof QSnapshotDto) {
        // from Snapshot
        // 
        final BooleanExpression where = Expressions.allOf(c.targetPredicate.orNull(), c.where.apply(Q_SNAPSHOT));
        // get snapshots to delete
        // TODO ATTENTION: this query has the potential to yield a massive amount of elements
        // return the list of snapshots to delete them outside the transaction since
        // it may take a while.
        final List<Tuple> deletedSnapshots = jpa.query().from(Q_SNAPSHOT).where(where).list(Q_SNAPSHOT.organizationId, Q_SNAPSHOT.mediaPackageId, Q_SNAPSHOT.version);
        // <BLOCK>
        // TODO database only approach to determine deleted episodes
        // TODO does not run with H2 so unit tests break
        /*
SELECT
  e.mediapackage_id,
  count(*) AS v
FROM oc_assets_snapshot e
GROUP BY e.mediapackage_id
HAVING v = (SELECT count(*)
            FROM oc_assets_snapshot e2
            WHERE e.mediapackage_id = e2.mediapackage_id
                  AND
                  -- delete where clause
                  (e2.version = 2 OR e2.mediapackage_id = '24ec925e-ea57-43a5-a7bb-58dc5aae54dd')
            GROUP BY mediapackage_id);
       */
        // final QSnapshotDto e2 = new QSnapshotDto("eee");
        // final List<String> deletedSnapshots = jpa.query()
        // .from(e2)
        // .groupBy(e2.mediaPackageId)
        // .having(e2.count().eq(
        // jpa.subQuery()
        // .from(Q_SNAPSHOT)
        // .where(Q_SNAPSHOT.mediaPackageId.eq(e2.mediaPackageId).and(where))
        // .groupBy(Q_SNAPSHOT.mediaPackageId)
        // .count()))
        // .list(e2.mediaPackageId);
        // </BLOCK>
        // delete assets from database
        final JPADeleteClause qAssets = jpa.delete(Q_ASSET).where(Q_ASSET.snapshotId.in(new JPASubQuery().from(Q_SNAPSHOT).where(where).list(Q_SNAPSHOT.id)));
        am.getDb().logDelete(formatQueryName(c.name, "delete assets"), qAssets);
        qAssets.execute();
        // main delete query
        final JPADeleteClause qMain = jpa.delete(Q_SNAPSHOT).where(where);
        am.getDb().logDelete(formatQueryName(c.name, "main"), qMain);
        final long deletedItems = qMain.execute();
        // delete orphaned properties
        deleteOrphanedProperties();
        // <BLOCK>
        // TODO Bad solution. Yields all media package IDs which can easily be thousands
        // TODO The above SQL solution does not work with H2 so I suspect the query is not 100% clean
        // TODO Rework the query and replace this code.
        // calculate deleted episodes, i.e. where all snapshots have been deleted
        final Set<String> deletedEpisodes;
        {
            final List<String> remainingSnapshots = jpa.query().from(Q_SNAPSHOT).distinct().list(Q_SNAPSHOT.mediaPackageId);
            final Set<String> d = $(deletedSnapshots).map(new Fn<Tuple, String>() {

                @Override
                public String apply(Tuple tuple) {
                    return tuple.get(Q_SNAPSHOT.mediaPackageId);
                }
            }).toSet(SetB.MH);
            d.removeAll(remainingSnapshots);
            deletedEpisodes = Collections.unmodifiableSet(d);
        }
        // </BLOCK>
        return new DeletionResult(deletedItems, deletedSnapshots, deletedEpisodes);
    } else if (from instanceof QPropertyDto) {
        // from Property
        // 
        final BooleanExpression where;
        {
            final BooleanExpression w = c.where.apply(Q_PROPERTY);
            if (w != null) {
                /* The original sub query used an "ON" clause to filter the join by mediapackage id [1].
             Unfortunately Eclipse link drops this clause completely when transforming the query
             into SQL. It creates a cross join instead of the inner join, which is perfectly legal
             if the "ON" clause would be moved to the "WHERE" clause.
             The example [2] shows that neither an "ON" clause nor an additional "WHERE" predicate is generated.

             [1]
             new JPASubQuery()
                .from(Q_PROPERTY)
                .join(Q_SNAPSHOT) <- inner join
                .on(Q_PROPERTY.mediaPackageId.eq(Q_SNAPSHOT.mediaPackageId)) <- dropped by Eclipse link
                .where(Q_PROPERTY.mediaPackageId.eq(Q_SNAPSHOT.mediaPackageId).and(w))
                .distinct()
                .list(Q_PROPERTY.mediaPackageId)

             [2]
             SELECT DISTINCT t1.mediapackage_id FROM oc_assets_snapshot t2, oc_assets_properties t1 WHERE (t2.organization_id = ?)
           */
                where = Q_PROPERTY.mediaPackageId.in(new JPASubQuery().from(Q_PROPERTY).join(Q_SNAPSHOT).where(Q_PROPERTY.mediaPackageId.eq(Q_SNAPSHOT.mediaPackageId).and(w)).distinct().list(Q_PROPERTY.mediaPackageId));
            } else {
                where = null;
            }
        }
        final JPADeleteClause qProperties = jpa.delete(from).where(Expressions.allOf(c.targetPredicate.orNull(), where));
        am.getDb().logDelete(formatQueryName(c.name, "main"), qProperties);
        final long deletedItems = qProperties.execute();
        return new DeletionResult(deletedItems, Collections.<Tuple>emptyList(), Collections.<String>emptySet());
    } else {
        // from contains an unsupported entity
        throw new RuntimeException("[Bug]");
    }
}
Also used : Set(java.util.Set) JPADeleteClause(com.mysema.query.jpa.impl.JPADeleteClause) QPropertyDto(org.opencastproject.assetmanager.impl.persistence.QPropertyDto) BooleanExpression(com.mysema.query.types.expr.BooleanExpression) JPASubQuery(com.mysema.query.jpa.JPASubQuery) QSnapshotDto(org.opencastproject.assetmanager.impl.persistence.QSnapshotDto) List(java.util.List) Tuple(com.mysema.query.Tuple)

Example 4 with JPASubQuery

use of com.mysema.query.jpa.JPASubQuery in project opencast by opencast.

the class PropertyPredicates method mkWhereDelete.

public static Where mkWhereDelete(final Opt<String> namespace, final Opt<String> propertyName, final Fn<QPropertyDto, Opt<BooleanExpression>> mkValueExpression) {
    final Opt<BooleanExpression> valueExpression = mkValueExpression.apply(Q_PROPERTY);
    final BooleanExpression propertyPredicate = (namespace.isSome() ? Q_PROPERTY.namespace.eq(namespace.get()) : // The isNotNull predicate prevents this.
    Q_PROPERTY.namespace.isNotNull()).and(propertyName.isSome() ? Q_PROPERTY.propertyName.eq(propertyName.get()) : null).and(valueExpression.isSome() ? valueExpression.get() : null);
    // 
    return new Where() {

        @Override
        public BooleanExpression fromSnapshot(QSnapshotDto e) {
            return new JPASubQuery().from(Q_PROPERTY).where(e.mediaPackageId.eq(Q_PROPERTY.mediaPackageId).and(propertyPredicate)).exists();
        }

        @Override
        public BooleanExpression fromProperty(QPropertyDto p) {
            return p.mediaPackageId.in(new JPASubQuery().from(p).where(propertyPredicate).distinct().list(p.mediaPackageId));
        }
    };
}
Also used : QPropertyDto(org.opencastproject.assetmanager.impl.persistence.QPropertyDto) BooleanExpression(com.mysema.query.types.expr.BooleanExpression) JPASubQuery(com.mysema.query.jpa.JPASubQuery) QSnapshotDto(org.opencastproject.assetmanager.impl.persistence.QSnapshotDto) Where(org.opencastproject.assetmanager.impl.query.DeleteQueryContribution.Where)

Aggregations

JPASubQuery (com.mysema.query.jpa.JPASubQuery)4 BooleanExpression (com.mysema.query.types.expr.BooleanExpression)2 Test (org.junit.Test)2 QPropertyDto (org.opencastproject.assetmanager.impl.persistence.QPropertyDto)2 QSnapshotDto (org.opencastproject.assetmanager.impl.persistence.QSnapshotDto)2 Tuple (com.mysema.query.Tuple)1 JPADeleteClause (com.mysema.query.jpa.impl.JPADeleteClause)1 List (java.util.List)1 Set (java.util.Set)1 Where (org.opencastproject.assetmanager.impl.query.DeleteQueryContribution.Where)1