1 /*************************************************************************
3 * Copyright 2016 Realm Inc.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 **************************************************************************/
19 #ifndef REALM_EXCEPTIONS_HPP
20 #define REALM_EXCEPTIONS_HPP
24 #include <realm/util/features.h>
28 /// Thrown by various functions to indicate that a specified table does not
30 class NoSuchTable : public std::exception {
32 const char* what() const noexcept override;
36 /// Thrown by various functions to indicate that a specified table name is
38 class TableNameInUse : public std::exception {
40 const char* what() const noexcept override;
44 // Thrown by functions that require a table to **not** be the target of link
45 // columns, unless those link columns are part of the table itself.
46 class CrossTableLinkTarget : public std::exception {
48 const char* what() const noexcept override;
52 /// Thrown by various functions to indicate that the dynamic type of a table
53 /// does not match a particular other table type (dynamic or static).
54 class DescriptorMismatch : public std::exception {
56 const char* what() const noexcept override;
60 /// The FileFormatUpgradeRequired exception can be thrown by the SharedGroup
61 /// constructor when opening a database that uses a deprecated file format
62 /// and/or a deprecated history schema, and the user has indicated he does not
63 /// want automatic upgrades to be performed. This exception indicates that until
64 /// an upgrade of the file format is performed, the database will be unavailable
65 /// for read or write operations.
66 class FileFormatUpgradeRequired : public std::exception {
68 const char* what() const noexcept override;
72 /// Thrown when a sync agent attempts to join a session in which there is
73 /// already a sync agent. A session may only contain one sync agent at any given
75 class MultipleSyncAgents : public std::exception {
77 const char* what() const noexcept override;
81 /// Thrown when memory can no longer be mapped to. When mmap/remap fails.
82 class AddressSpaceExhausted : public std::runtime_error {
84 AddressSpaceExhausted(const std::string& msg);
85 /// runtime_error::what() returns the msg provided in the constructor.
88 /// Thrown when creating references that are too large to be contained in our ref_type (size_t)
89 class MaximumFileSizeExceeded : public std::runtime_error {
91 MaximumFileSizeExceeded(const std::string& msg);
92 /// runtime_error::what() returns the msg provided in the constructor.
95 /// Thrown when writing fails because the disk is full.
96 class OutOfDiskSpace : public std::runtime_error {
98 OutOfDiskSpace(const std::string& msg);
99 /// runtime_error::what() returns the msg provided in the constructor.
103 /// The \c LogicError exception class is intended to be thrown only when
104 /// applications (or bindings) violate rules that are stated (or ought to have
105 /// been stated) in the documentation of the public API, and only in cases
106 /// where the violation could have been easily and efficiently predicted by the
107 /// application. In other words, this exception class is for the cases where
108 /// the error is due to incorrect use of the public API.
110 /// This class is not supposed to be caught by applications. It is not even
111 /// supposed to be considered part of the public API, and therefore the
112 /// documentation of the public API should **not** mention the \c LogicError
113 /// exception class by name. Note how this contrasts with other exception
114 /// classes, such as \c NoSuchTable, which are part of the public API, and are
115 /// supposed to be mentioned in the documentation by name. The \c LogicError
116 /// exception is part of Realm's private API.
118 /// In other words, the \c LogicError class should exclusively be used in
119 /// replacement (or in addition to) asserts (debug or not) in order to
120 /// guarantee program interruption, while still allowing for complete
121 /// test-cases to be written and run.
123 /// To this effect, the special `CHECK_LOGIC_ERROR()` macro is provided as a
124 /// test framework plugin to allow unit tests to check that the functions in
125 /// the public API do throw \c LogicError when rules are violated.
127 /// The reason behind hiding this class from the public API is to prevent users
128 /// from getting used to the idea that "Undefined Behaviour" equates a specific
129 /// exception being thrown. The whole point of properly documenting "Undefined
130 /// Behaviour" cases is to help the user know what the limits are, without
131 /// constraining the database to handle every and any use-case thrown at it.
133 /// FIXME: This exception class should probably be moved to the `_impl`
134 /// namespace, in order to avoid some confusion.
135 class LogicError : public std::exception {
141 column_name_too_long,
142 table_index_out_of_range,
143 row_index_out_of_range,
144 column_index_out_of_range,
145 string_position_out_of_range,
146 link_index_out_of_range,
150 /// Indicates that an argument has a value that is illegal in combination
151 /// with another argument, or with the state of an involved object.
154 /// Indicates a data type mismatch, such as when `Table::find_pkey_int()` is
155 /// called and the type of the primary key is not `type_Int`.
158 /// Indicates that two involved tables are not in the same group.
161 /// Indicates that an involved descriptor is of the wrong kind, i.e., if
162 /// it is a subtable descriptor, and the function requires a root table
164 wrong_kind_of_descriptor,
166 /// Indicates that an involved table is of the wrong kind, i.e., if it
167 /// is a subtable, and the function requires a root table, or if it is a
168 /// free-standing table, and the function requires a group-level table.
171 /// Indicates that an involved accessor is was detached, i.e., was not
172 /// attached to an underlying object.
175 /// Indicates that a specified row index of a target table (a link) is
176 /// out of range. This is used for disambiguation in cases such as
177 /// Table::set_link() where one specifies both a row index of the origin
178 /// table, and a row index of the target table.
179 target_row_index_out_of_range,
181 // Indicates that an involved column lacks a search index.
184 /// Indicates that a modification was attempted that would have produced a
185 /// duplicate primary value.
186 unique_constraint_violation,
188 /// User attempted to insert null in non-nullable column
191 /// Group::open() is called on a group accessor that is already in the
192 /// attached state. Or Group::open() or Group::commit() is called on a
193 /// group accessor that is managed by a SharedGroup object.
196 /// No active transaction on a particular SharedGroup object (e.g.,
197 /// SharedGroup::commit()), or the active transaction on the SharedGroup
198 /// object is of the wrong type (read/write), or an attampt was made to
199 /// initiate a new transaction while one is already in progress on the
200 /// same SharedGroup object.
201 wrong_transact_state,
203 /// Attempted use of a continuous transaction through a SharedGroup
204 /// object with no history. See Replication::get_history().
207 /// Durability setting (as passed to the SharedGroup constructor) was
208 /// not consistent across the session.
211 /// History type (as specified by the Replication implementation passed
212 /// to the SharedGroup constructor) was not consistent across the
216 /// History schema version (as specified by the Replication
217 /// implementation passed to the SharedGroup constructor) was not
218 /// consistent across the session.
219 mixed_history_schema_version,
221 /// Adding rows to a table with no columns is not supported.
222 table_has_no_columns,
224 /// Referring to a column that has been deleted.
225 column_does_not_exist,
227 /// You can not add index on a subtable of a subtable
228 subtable_of_subtable_index
231 LogicError(ErrorKind message);
233 const char* what() const noexcept override;
234 ErrorKind kind() const noexcept;
243 // LCOV_EXCL_START (Wording of what() strings are not to be tested)
245 inline const char* NoSuchTable::what() const noexcept
247 return "No such table exists";
250 inline const char* TableNameInUse::what() const noexcept
252 return "The specified table name is already in use";
255 inline const char* CrossTableLinkTarget::what() const noexcept
257 return "Table is target of cross-table link columns";
260 inline const char* DescriptorMismatch::what() const noexcept
262 return "Table descriptor mismatch";
265 inline const char* FileFormatUpgradeRequired::what() const noexcept
267 return "Database upgrade required but prohibited";
270 inline const char* MultipleSyncAgents::what() const noexcept
272 return "Multiple sync agents attempted to join the same session";
277 inline AddressSpaceExhausted::AddressSpaceExhausted(const std::string& msg)
278 : std::runtime_error(msg)
282 inline MaximumFileSizeExceeded::MaximumFileSizeExceeded(const std::string& msg)
283 : std::runtime_error(msg)
287 inline OutOfDiskSpace::OutOfDiskSpace(const std::string& msg)
288 : std::runtime_error(msg)
292 inline LogicError::LogicError(LogicError::ErrorKind k)
297 inline LogicError::ErrorKind LogicError::kind() const noexcept
305 #endif // REALM_EXCEPTIONS_HPP