001/*
002 * #%L
003 * HAPI FHIR JPA Server
004 * %%
005 * Copyright (C) 2014 - 2024 Smile CDR, Inc.
006 * %%
007 * Licensed under the Apache License, Version 2.0 (the "License");
008 * you may not use this file except in compliance with the License.
009 * You may obtain a copy of the License at
010 *
011 *      http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 * #L%
019 */
020package ca.uhn.fhir.jpa.dao.data;
021
022import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
023import org.springframework.data.domain.Pageable;
024import org.springframework.data.domain.Slice;
025import org.springframework.data.jpa.repository.JpaRepository;
026import org.springframework.data.jpa.repository.Modifying;
027import org.springframework.data.jpa.repository.Query;
028import org.springframework.data.repository.query.Param;
029
030import java.util.List;
031
032public interface IResourceHistoryTableDao extends JpaRepository<ResourceHistoryTable, Long>, IHapiFhirJpaRepository {
033
034        /**
035         * This is really only intended for unit tests - There can be many versions of resources in
036         * the real world, use a pageable query for real uses.
037         */
038        @Query("SELECT t FROM ResourceHistoryTable t WHERE t.myResourceId = :resId ORDER BY t.myResourceVersion ASC")
039        List<ResourceHistoryTable> findAllVersionsForResourceIdInOrder(@Param("resId") Long theId);
040
041        @Query("SELECT t FROM ResourceHistoryTable t WHERE t.myResourceId = :id AND t.myResourceVersion = :version")
042        ResourceHistoryTable findForIdAndVersion(@Param("id") long theId, @Param("version") long theVersion);
043
044        @Query(
045                        "SELECT t.myId FROM ResourceHistoryTable t WHERE t.myResourceId = :resId AND t.myResourceVersion <> :dontWantVersion")
046        Slice<Long> findForResourceId(
047                        Pageable thePage, @Param("resId") Long theId, @Param("dontWantVersion") Long theDontWantVersion);
048
049        @Query(
050                        "SELECT t FROM ResourceHistoryTable t WHERE t.myResourceId = :resId AND t.myResourceVersion <> :dontWantVersion")
051        Slice<ResourceHistoryTable> findAllVersionsExceptSpecificForResourcePid(
052                        Pageable thePage, @Param("resId") Long theId, @Param("dontWantVersion") Long theDontWantVersion);
053
054        @Query("" + "SELECT v.myId FROM ResourceHistoryTable v "
055                        + "LEFT OUTER JOIN ResourceTable t ON (v.myResourceId = t.myId) "
056                        + "WHERE v.myResourceVersion <> t.myVersion AND "
057                        + "t.myId = :resId")
058        Slice<Long> findIdsOfPreviousVersionsOfResourceId(Pageable thePage, @Param("resId") Long theResourceId);
059
060        @Query("" + "SELECT v.myId FROM ResourceHistoryTable v "
061                        + "LEFT OUTER JOIN ResourceTable t ON (v.myResourceId = t.myId) "
062                        + "WHERE v.myResourceVersion <> t.myVersion AND "
063                        + "t.myResourceType = :restype")
064        Slice<Long> findIdsOfPreviousVersionsOfResources(Pageable thePage, @Param("restype") String theResourceName);
065
066        @Query("" + "SELECT v.myId FROM ResourceHistoryTable v "
067                        + "LEFT OUTER JOIN ResourceTable t ON (v.myResourceId = t.myId) "
068                        + "WHERE v.myResourceVersion <> t.myVersion")
069        Slice<Long> findIdsOfPreviousVersionsOfResources(Pageable thePage);
070
071        @Modifying
072        @Query(
073                        "UPDATE ResourceHistoryTable r SET r.myResourceVersion = :newVersion WHERE r.myResourceId = :id AND r.myResourceVersion = :oldVersion")
074        void updateVersion(
075                        @Param("id") long theId, @Param("oldVersion") long theOldVersion, @Param("newVersion") long theNewVersion);
076
077        @Modifying
078        @Query("DELETE FROM ResourceHistoryTable t WHERE t.myId = :pid")
079        void deleteByPid(@Param("pid") Long theId);
080
081        /**
082         * This method is only for use in unit tests - It is used to move the stored resource body contents from the new
083         * <code>RES_TEXT_VC</code> column to the legacy <code>RES_TEXT</code> column, which is where data may have
084         * been stored by versions of HAPI FHIR prior to 7.0.0
085         *
086         * @since 7.0.0
087         */
088        @Modifying
089        @Query(
090                        "UPDATE ResourceHistoryTable r SET r.myResourceTextVc = null, r.myResource = :text, r.myEncoding = 'JSONC' WHERE r.myId = :pid")
091        void updateNonInlinedContents(@Param("text") byte[] theText, @Param("pid") long thePid);
092
093        @Query("SELECT v FROM ResourceHistoryTable v " + "JOIN FETCH v.myResourceTable t "
094                        + "WHERE v.myResourceId IN (:pids) "
095                        + "AND t.myVersion = v.myResourceVersion")
096        List<ResourceHistoryTable> findCurrentVersionsByResourcePidsAndFetchResourceTable(
097                        @Param("pids") List<Long> theVersionlessPids);
098}