001/*
002 * #%L
003 * HAPI FHIR JPA Server
004 * %%
005 * Copyright (C) 2014 - 2025 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.dao.JpaPid;
023import ca.uhn.fhir.jpa.model.dao.JpaPidFk;
024import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
025import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTablePk;
026import org.springframework.data.domain.Pageable;
027import org.springframework.data.domain.Slice;
028import org.springframework.data.jpa.repository.JpaRepository;
029import org.springframework.data.jpa.repository.Modifying;
030import org.springframework.data.jpa.repository.Query;
031import org.springframework.data.repository.query.Param;
032
033import java.util.List;
034import java.util.stream.Stream;
035
036public interface IResourceHistoryTableDao
037                extends JpaRepository<ResourceHistoryTable, ResourceHistoryTablePk>, IHapiFhirJpaRepository {
038
039        /**
040         * This is really only intended for unit tests - There can be many versions of resources in
041         * the real world, use a pageable query for real uses.
042         */
043        @Query("SELECT t FROM ResourceHistoryTable t WHERE t.myResourcePid = :resId ORDER BY t.myResourceVersion ASC")
044        List<ResourceHistoryTable> findAllVersionsForResourceIdInOrder(@Param("resId") JpaPidFk theId);
045
046        @Query("SELECT t FROM ResourceHistoryTable t WHERE t.myResourcePid = :id AND t.myResourceVersion = :version")
047        ResourceHistoryTable findForIdAndVersion(@Param("id") JpaPidFk theId, @Param("version") long theVersion);
048
049        @Query(
050                        "SELECT t.myId FROM ResourceHistoryTable t WHERE t.myResourcePid = :resId AND t.myResourceVersion <> :dontWantVersion")
051        Slice<ResourceHistoryTablePk> findForResourceId(
052                        Pageable thePage, @Param("resId") JpaPidFk theId, @Param("dontWantVersion") Long theDontWantVersion);
053
054        @Query(
055                        "SELECT t FROM ResourceHistoryTable t WHERE t.myResourcePid = :resId AND t.myResourceVersion <> :dontWantVersion")
056        Slice<ResourceHistoryTable> findAllVersionsExceptSpecificForResourcePid(
057                        Pageable thePage, @Param("resId") JpaPidFk theId, @Param("dontWantVersion") Long theDontWantVersion);
058
059        @Query("SELECT v.myId FROM ResourceHistoryTable v "
060                        + "LEFT OUTER JOIN ResourceTable t ON (v.myResourceTable = t) "
061                        + "WHERE v.myResourceVersion <> t.myVersion AND "
062                        + "t.myPid = :resId")
063        Slice<ResourceHistoryTablePk> findIdsOfPreviousVersionsOfResourceId(
064                        Pageable thePage, @Param("resId") JpaPid theResourceId);
065
066        @Query("SELECT v.myId FROM ResourceHistoryTable v "
067                        + "LEFT OUTER JOIN ResourceTable t ON (v.myResourceTable = t) "
068                        + "WHERE v.myResourceVersion <> t.myVersion AND "
069                        + "t.myResourceType = :restype")
070        Slice<ResourceHistoryTablePk> findIdsOfPreviousVersionsOfResources(
071                        Pageable thePage, @Param("restype") String theResourceName);
072
073        @Query("" + "SELECT v.myId FROM ResourceHistoryTable v "
074                        + "LEFT OUTER JOIN ResourceTable t ON (v.myResourceTable = t) "
075                        + "WHERE v.myResourceVersion <> t.myVersion")
076        Slice<ResourceHistoryTablePk> findIdsOfPreviousVersionsOfResources(Pageable thePage);
077
078        @Modifying
079        @Query(
080                        "UPDATE ResourceHistoryTable r SET r.myResourceVersion = :newVersion WHERE r.myResourcePid = :id AND r.myResourceVersion = :oldVersion")
081        void updateVersion(
082                        @Param("id") JpaPidFk theId,
083                        @Param("oldVersion") long theOldVersion,
084                        @Param("newVersion") long theNewVersion);
085
086        @Modifying
087        @Query("DELETE FROM ResourceHistoryTable t WHERE t.myId = :pid")
088        void deleteByPid(@Param("pid") ResourceHistoryTablePk theId);
089
090        /**
091         * This method is only for use in unit tests - It is used to move the stored resource body contents from the new
092         * <code>RES_TEXT_VC</code> column to the legacy <code>RES_TEXT</code> column, which is where data may have
093         * been stored by versions of HAPI FHIR prior to 7.0.0
094         *
095         * @since 7.0.0
096         */
097        @Modifying
098        @Query(
099                        "UPDATE ResourceHistoryTable r SET r.myResourceTextVc = null, r.myResource = :text, r.myEncoding = 'JSONC' WHERE r.myId = :pid")
100        void updateNonInlinedContents(@Param("text") byte[] theText, @Param("pid") ResourceHistoryTablePk thePid);
101
102        @Query("SELECT v FROM ResourceHistoryTable v " + "JOIN FETCH v.myResourceTable t "
103                        + "WHERE v.myResourcePid IN (:pids) "
104                        + "AND t.myVersion = v.myResourceVersion")
105        List<ResourceHistoryTable> findCurrentVersionsByResourcePidsAndFetchResourceTable(
106                        @Param("pids") List<JpaPidFk> theVersionlessPids);
107
108        @Query("SELECT v FROM ResourceHistoryTable v " + "WHERE v.myResourcePid = :pid "
109                        + "ORDER BY v.myResourceVersion DESC")
110        Stream<ResourceHistoryTable> findVersionsForResource(Pageable thePage, @Param("pid") JpaPidFk theFk);
111
112        @Query(
113                        "SELECT new ca.uhn.fhir.jpa.model.dao.JpaPid(v.myPartitionIdValue, v.myResourcePid.myId, v.myResourceVersion) FROM ResourceHistoryTable v WHERE v.myResourcePid IN :resIds")
114        Stream<JpaPid> findVersionPidsForResources(Pageable thePage, @Param("resIds") List<JpaPidFk> theIds);
115}