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