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