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.search.builder.models;
021
022import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
023import ca.uhn.fhir.rest.api.SortSpec;
024
025public class SearchQueryProperties {
026
027        /**
028         * True if this query is only to fetch the count (and not any results).
029         *
030         * True means this is a count only query
031         */
032        private boolean myDoCountOnlyFlag;
033        /**
034         * Whether or not we do deduplication of results in memory
035         * (using a hashset, etc), or push this to the database
036         * (using GROUP BY, etc).
037         *
038         * True means use the database
039         */
040        private boolean myDeduplicateInDB;
041
042        /**
043         * The maximum number of results to fetch (when we want it limited).
044         * Can be null if we are fetching everything or paging.
045         */
046        private Integer myMaxResultsRequested;
047        /**
048         * The offset for the results to fetch.
049         *
050         * null if the first page, some number if it's a later page
051         */
052        private Integer myOffset;
053
054        /**
055         * The sort spec for this search
056         */
057        private SortSpec mySortSpec;
058
059        public boolean isDoCountOnlyFlag() {
060                return myDoCountOnlyFlag;
061        }
062
063        public SearchQueryProperties setDoCountOnlyFlag(boolean theDoCountOnlyFlag) {
064                myDoCountOnlyFlag = theDoCountOnlyFlag;
065                return this;
066        }
067
068        public boolean isDeduplicateInDatabase() {
069                return myDeduplicateInDB;
070        }
071
072        /**
073         * Set of PIDs of results that have already been returned in a search.
074         *
075         * Searches use pre-fetch thresholds to avoid returning every result in the db
076         * (see {@link JpaStorageSettings mySearchPreFetchThresholds}). These threshold values
077         * dictate the usage of this set.
078         *
079         * Results from searches returning *less* than a prefetch threshold are put into this set
080         * for 2 purposes:
081         * 1) skipping already seen resources. ie, client requesting next "page" of
082         *    results should skip previously returned results
083         * 2) deduplication of returned results. ie, searches can return duplicate resources (due to
084         *    sort and filter criteria), so this set will be used to avoid returning duplicate results.
085         *
086         * NOTE: if a client requests *more* resources than *all* prefetch thresholds,
087         * we push the work of "deduplication" to the database. No newly seen resource
088         * will be stored in this set (to avoid this set exploding in size and the JVM running out memory).
089         * We will, however, still use it to skip previously seen results.
090         */
091        public SearchQueryProperties setDeduplicateInDatabase(boolean theDeduplicateInDBFlag) {
092                myDeduplicateInDB = theDeduplicateInDBFlag;
093                return this;
094        }
095
096        public Integer getMaxResultsRequested() {
097                return myMaxResultsRequested;
098        }
099
100        public SearchQueryProperties setMaxResultsRequested(Integer theMaxResultsRequested) {
101                myMaxResultsRequested = theMaxResultsRequested;
102                return this;
103        }
104
105        public boolean hasMaxResultsRequested() {
106                return myMaxResultsRequested != null;
107        }
108
109        public Integer getOffset() {
110                return myOffset;
111        }
112
113        public boolean hasOffset() {
114                return myOffset != null;
115        }
116
117        public SearchQueryProperties setOffset(Integer theOffset) {
118                myOffset = theOffset;
119                return this;
120        }
121
122        public SortSpec getSortSpec() {
123                return mySortSpec;
124        }
125
126        public boolean hasSort() {
127                return mySortSpec != null;
128        }
129
130        public SearchQueryProperties setSortSpec(SortSpec theSortSpec) {
131                mySortSpec = theSortSpec;
132                return this;
133        }
134
135        public SearchQueryProperties clone() {
136                return new SearchQueryProperties()
137                                .setMaxResultsRequested(myMaxResultsRequested)
138                                .setSortSpec(mySortSpec)
139                                .setOffset(myOffset)
140                                .setDoCountOnlyFlag(myDoCountOnlyFlag)
141                                .setDeduplicateInDatabase(myDeduplicateInDB);
142        }
143}