001/*
002 * (C) Copyright 2006-2017 Nuxeo (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Florent Guillaume
018 */
019package org.nuxeo.ecm.core.storage.sql;
020
021import java.io.Serializable;
022import java.util.Calendar;
023import java.util.Collection;
024import java.util.Map;
025import java.util.Set;
026
027import javax.transaction.xa.XAResource;
028
029import org.nuxeo.ecm.core.api.IterableQueryResult;
030import org.nuxeo.ecm.core.api.Lock;
031import org.nuxeo.ecm.core.api.PartialList;
032import org.nuxeo.ecm.core.api.ScrollResult;
033import org.nuxeo.ecm.core.query.QueryFilter;
034
035/**
036 * A {@link Mapper} maps {@link Row}s to and from the database.
037 */
038public interface Mapper extends RowMapper, XAResource {
039
040    /**
041     * Executes the given query and returns the first batch of results containing id of documents, next batch must be
042     * requested within the {@code keepAliveSeconds} delay.
043     *
044     * @since 8.4
045     */
046    ScrollResult<String> scroll(String query, int batchSize, int keepAliveSeconds);
047
048    /**
049     * Executes the given query and returns the first batch of results containing id of documents, next batch must be
050     * requested within the {@code keepAliveSeconds} delay.
051     *
052     * @since 10.3
053     */
054    ScrollResult<String> scroll(String query, QueryFilter queryFilter, int batchSize, int keepAliveSeconds);
055
056    /**
057     * Get the next batch of results containing id of documents, the {@code scrollId} is part of the previous
058     * {@link ScrollResult} response.
059     *
060     * @since 8.4
061     */
062    ScrollResult<String> scroll(String scrollId);
063
064    /**
065     * Identifiers assigned by a server to identify a client mapper and its repository.
066     */
067    final class Identification implements Serializable {
068
069        private static final long serialVersionUID = 1L;
070
071        public final String repositoryId;
072
073        public final String mapperId;
074
075        public Identification(String repositoryId, String mapperId) {
076            this.repositoryId = repositoryId;
077            this.mapperId = mapperId;
078        }
079
080        @Override
081        public String toString() {
082            return getClass().getSimpleName() + '(' + repositoryId + ',' + mapperId + ')';
083        }
084
085    }
086
087    /**
088     * Returns the repository id and mapper id assigned.
089     * <p>
090     * This is used in remote stateless mode to be able to identify to which mapper an incoming connection is targeted,
091     * and from which repository instance.
092     *
093     * @return the repository and mapper identification
094     */
095    Identification getIdentification();
096
097    // used for reflection
098    String GET_IDENTIFICATION = "getIdentification";
099
100    void close();
101
102    // used for reflection
103    String CLOSE = "close";
104
105    // TODO
106    int getTableSize(String tableName);
107
108    /**
109     * Creates the necessary structures in the database.
110     *
111     * @param ddlMode the DDL execution mode
112     */
113    void createDatabase(String ddlMode);
114
115    /*
116     * ========== Methods returning non-Rows ==========
117     */
118
119    /*
120     * ----- Root -----
121     */
122
123    /**
124     * Gets the root id for a given repository, if registered.
125     *
126     * @param repositoryId the repository id
127     * @return the root id, or null if not found
128     */
129    Serializable getRootId(String repositoryId);
130
131    /**
132     * Records the newly generated root id for a given repository.
133     *
134     * @param repositoryId the repository id, usually 0
135     * @param id the root id
136     */
137    void setRootId(Serializable repositoryId, Serializable id);
138
139    /*
140     * ----- Query -----
141     */
142
143    /**
144     * Makes a NXQL query to the database.
145     *
146     * @param query the query
147     * @param queryType the query type
148     * @param queryFilter the query filter
149     * @param countTotal if {@code true}, count the total size without limit/offset
150     * @return the list of matching document ids
151     */
152    PartialList<Serializable> query(String query, String queryType, QueryFilter queryFilter, boolean countTotal);
153
154    /**
155     * Makes a NXQL query to the database.
156     *
157     * @param query the query
158     * @param queryType the query type
159     * @param queryFilter the query filter
160     * @param countUpTo if {@code -1}, count the total size without offset/limit.<br>
161     *            If {@code 0}, don't count the total size.<br>
162     *            If {@code n}, count the total number if there are less than n documents otherwise set the size to
163     *            {@code -1}.
164     * @return the list of matching document ids
165     * @since 5.6
166     */
167    PartialList<Serializable> query(String query, String queryType, QueryFilter queryFilter, long countUpTo);
168
169    /**
170     * Makes a query to the database and returns an iterable (which must be closed when done).
171     *
172     * @param query the query
173     * @param queryType the query type
174     * @param queryFilter the query filter
175     * @param distinctDocuments if {@code true} then a maximum of one row per document will be returned
176     * @param params optional query-type-dependent parameters
177     * @return an iterable, which <b>must</b> be closed when done
178     */
179    // queryFilter used for principals and permissions
180    IterableQueryResult queryAndFetch(String query, String queryType, QueryFilter queryFilter,
181            boolean distinctDocuments, Object... params);
182
183    /**
184     * Makes a query to the database.
185     *
186     * @param query the query
187     * @param queryType the query type
188     * @param queryFilter the query filter
189     * @param distinctDocuments if {@code true} then a maximum of one row per document will be returned
190     * @param countUpTo if {@code -1}, also count the total size without offset/limit.<br>
191     *            If {@code 0}, don't count the total size.<br>
192     *            If {@code n}, count the total number if there are less than n documents otherwise set the size to
193     *            {@code -1}.
194     * @param params optional query-type-dependent parameters
195     * @return a projection
196     * @since 7.10-HF-25, 8.10-HF06, 9.2
197     */
198    PartialList<Map<String,Serializable>> queryProjection(String query, String queryType, QueryFilter queryFilter, boolean distinctDocuments,
199            long countUpTo, Object... params);
200
201    /**
202     * Gets the ids for all the ancestors of the given row ids.
203     *
204     * @param ids the ids
205     * @return the set of ancestor ids
206     */
207    Set<Serializable> getAncestorsIds(Collection<Serializable> ids);
208
209    /*
210     * ----- ACLs -----
211     */
212
213    void updateReadAcls();
214
215    void rebuildReadAcls();
216
217    /*
218     * ----- Clustering -----
219     */
220
221    int getClusterNodeIdType();
222
223    /**
224     * Informs the cluster that this node exists.
225     */
226    void createClusterNode(Serializable nodeId);
227
228    /**
229     * Removes this node from the cluster.
230     */
231    void removeClusterNode(Serializable nodeId);
232
233    /**
234     * Inserts the invalidation rows for the other cluster nodes.
235     */
236    void insertClusterInvalidations(Serializable nodeId, Invalidations invalidations);
237
238    /**
239     * Gets the invalidations from other cluster nodes.
240     */
241    Invalidations getClusterInvalidations(Serializable nodeId);
242
243    /*
244     * ----- Locking -----
245     */
246
247    /**
248     * Gets the lock state of a document.
249     * <p>
250     * If the document does not exist, {@code null} is returned.
251     *
252     * @param id the document id
253     * @return the existing lock, or {@code null} when there is no lock
254     */
255    Lock getLock(Serializable id);
256
257    /**
258     * Sets a lock on a document.
259     * <p>
260     * If the document is already locked, returns its existing lock status (there is no re-locking, {@link #removeLock}
261     * must be called first).
262     *
263     * @param id the document id
264     * @param lock the lock object to set
265     * @return {@code null} if locking succeeded, or the existing lock if locking failed, or a
266     */
267    Lock setLock(Serializable id, Lock lock);
268
269    /**
270     * Removes a lock from a document.
271     * <p>
272     * The previous lock is returned.
273     * <p>
274     * If {@code owner} is {@code null} then the lock is unconditionally removed.
275     * <p>
276     * If {@code owner} is not {@code null}, it must match the existing lock owner for the lock to be removed. If it
277     * doesn't match, the returned lock will return {@code true} for {@link Lock#getFailed}.
278     *
279     * @param id the document id
280     * @param owner the owner to check, or {@code null} for no check
281     * @param force {@code true} to just do the remove and not return the previous lock
282     * @return the previous lock
283     */
284    Lock removeLock(Serializable id, String owner, boolean force);
285
286    /**
287     * Marks the binaries in use by passing them to the binary manager(s)'s GC mark() method.
288     */
289    void markReferencedBinaries();
290
291    /**
292     * Cleans up (hard-delete) any rows that have been soft-deleted in the database.
293     *
294     * @param max the maximum number of rows to delete at a time
295     * @param beforeTime the maximum deletion time of the rows to delete
296     * @return the number of rows deleted
297     */
298    int cleanupDeletedRows(int max, Calendar beforeTime);
299
300    /**
301     * @since 5.9.3
302     */
303    boolean isConnected();
304
305    /**
306     * @since 5.9.3
307     */
308    void connect(boolean noSharing);
309
310    /**
311     * @since 5.9.3
312     */
313    void disconnect();
314
315}