From ff9b73ec2f5eaa47c1506d06b2fb5257bfd318ea Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Tue, 27 Oct 2015 03:13:21 -0700 Subject: [PATCH 01/41] Non-existent object getters shouldn't throw exceptions --- object_accessor.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/object_accessor.hpp b/object_accessor.hpp index 5636a2cb..1afdf772 100644 --- a/object_accessor.hpp +++ b/object_accessor.hpp @@ -117,7 +117,7 @@ namespace realm { { const Property *prop = object_schema.property_for_name(prop_name); if (!prop) { - throw std::runtime_error("Setting invalid property '" + prop_name + "' on object '" + object_schema.name + "'."); + throw std::runtime_error("Getting invalid property '" + prop_name + "' on object '" + object_schema.name + "'."); } return get_property_value_impl(ctx, *prop); }; From ccdfaa8ae9e23a8fb535a0d15b959e4c3beac86d Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Tue, 27 Oct 2015 09:12:39 -0700 Subject: [PATCH 02/41] use typed exceptions --- object_accessor.hpp | 38 ++++++++++++++++++++++++++++++++------ object_store.cpp | 7 ++++++- object_store.hpp | 2 ++ 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/object_accessor.hpp b/object_accessor.hpp index 1afdf772..25d79dfd 100644 --- a/object_accessor.hpp +++ b/object_accessor.hpp @@ -99,6 +99,28 @@ namespace realm { static Mixed to_mixed(ContextType ctx, ValueType &val) { throw std::runtime_error("'Any' type is unsupported"); } }; + class InvalidPropertyException : public std::runtime_error + { + public: + InvalidPropertyException(const std::string object_type, const std::string property_name, const std::string message) : std::runtime_error(message), object_type(object_type), property_name(property_name) {} + const std::string object_type; + const std::string property_name; + }; + + class MissingPropertyValueException : public std::runtime_error + { + public: + MissingPropertyValueException(const std::string object_type, const std::string property_name, const std::string message) : std::runtime_error(message), object_type(object_type), property_name(property_name) {} + const std::string object_type; + const std::string property_name; + }; + + class MutationOutsideTransactionException : public std::runtime_error + { + public: + MutationOutsideTransactionException(std::string message) : std::runtime_error(message) {} + }; + // // template method implementations // @@ -107,7 +129,8 @@ namespace realm { { const Property *prop = object_schema.property_for_name(prop_name); if (!prop) { - throw std::runtime_error("Setting invalid property '" + prop_name + "' on object '" + object_schema.name + "'."); + throw InvalidPropertyException(object_schema.name, prop_name, + "Setting invalid property '" + prop_name + "' on object '" + object_schema.name + "'."); } set_property_value_impl(ctx, *prop, value, try_update); }; @@ -117,7 +140,8 @@ namespace realm { { const Property *prop = object_schema.property_for_name(prop_name); if (!prop) { - throw std::runtime_error("Getting invalid property '" + prop_name + "' on object '" + object_schema.name + "'."); + throw InvalidPropertyException(object_schema.name, prop_name, + "Getting invalid property '" + prop_name + "' on object '" + object_schema.name + "'."); } return get_property_value_impl(ctx, *prop); }; @@ -128,7 +152,7 @@ namespace realm { using Accessor = NativeAccessor; if (!m_realm->is_in_transaction()) { - throw std::runtime_error("Can only set property values within a transaction."); + throw MutationOutsideTransactionException("Can only set property values within a transaction."); } size_t column = property.table_column; @@ -223,7 +247,7 @@ namespace realm { using Accessor = NativeAccessor; if (!realm->is_in_transaction()) { - throw std::runtime_error("Can only create objects within a transaction."); + throw MutationOutsideTransactionException("Can only create objects within a transaction."); } // get or create our accessor @@ -244,7 +268,8 @@ namespace realm { } if (!try_update && row_index != realm::not_found) { - throw std::runtime_error("Attempting to create an object of type '" + object_schema.name + "' with an exising primary key value."); + throw DuplicatePrimaryKeyValueException(object_schema.name, *primary_prop, + "Attempting to create an object of type '" + object_schema.name + "' with an exising primary key value."); } } @@ -267,7 +292,8 @@ namespace realm { object.set_property_value_impl(ctx, prop, Accessor::default_value_for_property(ctx, realm.get(), object_schema, prop.name), try_update); } else { - throw std::runtime_error("Missing property value for property " + prop.name); + throw MissingPropertyValueException(object_schema.name, prop.name, + "Missing property value for property " + prop.name); } } } diff --git a/object_store.cpp b/object_store.cpp index 59b94f3b..c282e20b 100644 --- a/object_store.cpp +++ b/object_store.cpp @@ -514,8 +514,12 @@ DuplicatePrimaryKeyValueException::DuplicatePrimaryKeyValueException(std::string m_object_type(object_type), m_property(property) { m_what = "Primary key property '" + property.name + "' has duplicate values after migration."; -}; +} +DuplicatePrimaryKeyValueException::DuplicatePrimaryKeyValueException(std::string const& object_type, Property const& property, const std::string message) : m_object_type(object_type), m_property(property) +{ + m_what = message; +} SchemaValidationException::SchemaValidationException(std::vector const& errors) : m_validation_errors(errors) @@ -600,3 +604,4 @@ DuplicatePrimaryKeysException::DuplicatePrimaryKeysException(std::string const& { m_what = "Duplicate primary keys for object '" + object_type + "'."; } + diff --git a/object_store.hpp b/object_store.hpp index f38524f8..9972b089 100644 --- a/object_store.hpp +++ b/object_store.hpp @@ -137,6 +137,8 @@ namespace realm { class DuplicatePrimaryKeyValueException : public MigrationException { public: DuplicatePrimaryKeyValueException(std::string const& object_type, Property const& property); + DuplicatePrimaryKeyValueException(std::string const& object_type, Property const& property, const std::string message); + std::string object_type() const { return m_object_type; } Property const& property() const { return m_property; } private: From dca7e7d7919683f2f0e14ffa1b8f124fa8ad1c14 Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Tue, 27 Oct 2015 09:51:06 -0700 Subject: [PATCH 03/41] enable nullable propeties without a macro --- object_store.cpp | 4 ---- schema.cpp | 4 ---- 2 files changed, 8 deletions(-) diff --git a/object_store.cpp b/object_store.cpp index c282e20b..1949c285 100644 --- a/object_store.cpp +++ b/object_store.cpp @@ -555,11 +555,7 @@ InvalidNullabilityException::InvalidNullabilityException(std::string const& obje m_what = "'Object' property '" + property.name + "' must be nullable."; } else { -#if REALM_NULL_STRINGS == 1 m_what = "Array or Mixed property '" + property.name + "' cannot be nullable"; -#else - m_what = "Only 'Object' property types are nullable"; -#endif } } diff --git a/schema.cpp b/schema.cpp index bf7a6181..911dc4e5 100644 --- a/schema.cpp +++ b/schema.cpp @@ -71,11 +71,7 @@ void Schema::validate() const // check nullablity if (prop.is_nullable) { -#if REALM_NULL_STRINGS == 1 if (prop.type == PropertyTypeArray || prop.type == PropertyTypeAny) { -#else - if (prop.type != PropertyTypeObject) { -#endif exceptions.emplace_back(InvalidNullabilityException(object.name, prop)); } } From faa1297d3bd75e9e8e2ab2022c2e762caf9ab5f8 Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Tue, 27 Oct 2015 10:04:56 -0700 Subject: [PATCH 04/41] support null for basic propety types --- object_accessor.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/object_accessor.hpp b/object_accessor.hpp index 25d79dfd..cd45e8f7 100644 --- a/object_accessor.hpp +++ b/object_accessor.hpp @@ -156,6 +156,11 @@ namespace realm { } size_t column = property.table_column; + if (property.is_nullable && Accessor::is_null(ctx, value)) { + m_row.set_null(column); + return; + } + switch (property.type) { case PropertyTypeBool: m_row.set_bool(column, Accessor::to_bool(ctx, value)); @@ -209,6 +214,10 @@ namespace realm { using Accessor = NativeAccessor; size_t column = property.table_column; + if (property.is_nullable && m_row.is_null(column)) { + return Accessor::null_value(ctx); + } + switch (property.type) { case PropertyTypeBool: return Accessor::from_bool(ctx, m_row.get_bool(column)); From 2e2beabc40064cf8009cadf94956331ff8e92ef2 Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Tue, 27 Oct 2015 13:59:15 -0700 Subject: [PATCH 05/41] change the license before starting the beta --- list.cpp | 20 +++----------------- list.hpp | 20 +++----------------- object_accessor.hpp | 20 +++----------------- results.cpp | 20 +++----------------- results.hpp | 20 +++----------------- 5 files changed, 15 insertions(+), 85 deletions(-) diff --git a/list.cpp b/list.cpp index 89632a09..ff57ef27 100644 --- a/list.cpp +++ b/list.cpp @@ -1,20 +1,6 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2015 Realm Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//////////////////////////////////////////////////////////////////////////// +/* Copyright 2015 Realm Inc - All Rights Reserved + * Proprietary and Confidential + */ #include "list.hpp" #import diff --git a/list.hpp b/list.hpp index 9165d194..18ef44e7 100644 --- a/list.hpp +++ b/list.hpp @@ -1,20 +1,6 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2015 Realm Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//////////////////////////////////////////////////////////////////////////// +/* Copyright 2015 Realm Inc - All Rights Reserved + * Proprietary and Confidential + */ #ifndef REALM_LIST_HPP #define REALM_LIST_HPP diff --git a/object_accessor.hpp b/object_accessor.hpp index cd45e8f7..a1350e3d 100644 --- a/object_accessor.hpp +++ b/object_accessor.hpp @@ -1,20 +1,6 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2015 Realm Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//////////////////////////////////////////////////////////////////////////// +/* Copyright 2015 Realm Inc - All Rights Reserved + * Proprietary and Confidential + */ #ifndef REALM_OBJECT_ACCESSOR_HPP #define REALM_OBJECT_ACCESSOR_HPP diff --git a/results.cpp b/results.cpp index e4ad126e..1977e5be 100644 --- a/results.cpp +++ b/results.cpp @@ -1,20 +1,6 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2015 Realm Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//////////////////////////////////////////////////////////////////////////// +/* Copyright 2015 Realm Inc - All Rights Reserved + * Proprietary and Confidential + */ #include "results.hpp" #import diff --git a/results.hpp b/results.hpp index fcb3e894..fff37124 100644 --- a/results.hpp +++ b/results.hpp @@ -1,20 +1,6 @@ -//////////////////////////////////////////////////////////////////////////// -// -// Copyright 2015 Realm Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -//////////////////////////////////////////////////////////////////////////// +/* Copyright 2015 Realm Inc - All Rights Reserved + * Proprietary and Confidential + */ #ifndef REALM_RESULTS_HPP #define REALM_RESULTS_HPP From 49738275312e441b092e5f19a53b538e432d033e Mon Sep 17 00:00:00 2001 From: Kristian Dupont Date: Thu, 29 Oct 2015 10:42:56 +0100 Subject: [PATCH 06/41] Rename RealmDelegate to RealmBindingContext --- ..._delegate.hpp => realm_binding_context.hpp | 20 +++++++++---------- shared_realm.cpp | 20 +++++++++---------- shared_realm.hpp | 4 ++-- 3 files changed, 22 insertions(+), 22 deletions(-) rename realm_delegate.hpp => realm_binding_context.hpp (90%) diff --git a/realm_delegate.hpp b/realm_binding_context.hpp similarity index 90% rename from realm_delegate.hpp rename to realm_binding_context.hpp index 0d9e9dfe..1e82e1e2 100644 --- a/realm_delegate.hpp +++ b/realm_binding_context.hpp @@ -16,8 +16,8 @@ // //////////////////////////////////////////////////////////////////////////// -#ifndef REALM_DELEGATE_HPP -#define REALM_DELEGATE_HPP +#ifndef REALM_BINDING_CONTEXT_HPP +#define REALM_BINDING_CONTEXT_HPP #include "index_set.hpp" @@ -25,15 +25,15 @@ #include namespace realm { -// RealmDelegate is the extension point for adding binding-specific behavior to +// RealmBindingContext is the extension point for adding binding-specific behavior to // a SharedRealm. It can be used to store additonal data associated with the // Realm which is needed by the binding, and there are several methods which // can be overridden to receive notifications of state changes within the Realm. // -// A simple delegate implementation which lets the user register functions to be +// A simple implementation which lets the user register functions to be // called on refresh could look like the following: // -// class DelegateImplementation : public RealmDelegate { +// class BindingContextImplementation : public RealmBindingContext { // public: // // A token returned from add_notification that can be used to remove the // // notification later @@ -66,9 +66,9 @@ namespace realm { // private: // std::list> m_registered_notifications; // }; -class RealmDelegate { +class RealmBindingContext { public: - virtual ~RealmDelegate() = default; + virtual ~RealmBindingContext() = default; // Called by the Realm when a write transaction is committed to the file by // a different Realm instance (possibly in a different process) @@ -147,8 +147,8 @@ public: }; }; -inline void RealmDelegate::will_change(std::vector const&, std::vector const&) { } -inline void RealmDelegate::did_change(std::vector const&, std::vector const&) { } +inline void RealmBindingContext::will_change(std::vector const&, std::vector const&) { } +inline void RealmBindingContext::did_change(std::vector const&, std::vector const&) { } } // namespace realm -#endif /* REALM_DELEGATE_HPP */ +#endif /* REALM_BINDING_CONTEXT_HPP */ diff --git a/shared_realm.cpp b/shared_realm.cpp index 2ca84649..5eeb57da 100644 --- a/shared_realm.cpp +++ b/shared_realm.cpp @@ -19,7 +19,7 @@ #include "shared_realm.hpp" #include "external_commit_helper.hpp" -#include "realm_delegate.hpp" +#include "realm_binding_context.hpp" #include "schema.hpp" #include "transact_log_handler.hpp" @@ -247,7 +247,7 @@ void Realm::begin_transaction() // make sure we have a read transaction read_group(); - transaction::begin(*m_shared_group, *m_history, m_delegate.get()); + transaction::begin(*m_shared_group, *m_history, m_binding_context.get()); m_in_transaction = true; } @@ -261,7 +261,7 @@ void Realm::commit_transaction() } m_in_transaction = false; - transaction::commit(*m_shared_group, *m_history, m_delegate.get()); + transaction::commit(*m_shared_group, *m_history, m_binding_context.get()); m_notifier->notify_others(); } @@ -275,7 +275,7 @@ void Realm::cancel_transaction() } m_in_transaction = false; - transaction::cancel(*m_shared_group, *m_history, m_delegate.get()); + transaction::cancel(*m_shared_group, *m_history, m_binding_context.get()); } void Realm::invalidate() @@ -320,15 +320,15 @@ void Realm::notify() verify_thread(); if (m_shared_group->has_changed()) { // Throws - if (m_delegate) { - m_delegate->changes_available(); + if (m_binding_context) { + m_binding_context->changes_available(); } if (m_auto_refresh) { if (m_group) { - transaction::advance(*m_shared_group, *m_history, m_delegate.get()); + transaction::advance(*m_shared_group, *m_history, m_binding_context.get()); } - else if (m_delegate) { - m_delegate->did_change({}, {}); + else if (m_binding_context) { + m_binding_context->did_change({}, {}); } } } @@ -351,7 +351,7 @@ bool Realm::refresh() } if (m_group) { - transaction::advance(*m_shared_group, *m_history, m_delegate.get()); + transaction::advance(*m_shared_group, *m_history, m_binding_context.get()); } else { // Create the read transaction diff --git a/shared_realm.hpp b/shared_realm.hpp index dc5c4b92..bc078fba 100644 --- a/shared_realm.hpp +++ b/shared_realm.hpp @@ -30,7 +30,7 @@ namespace realm { class ClientHistory; class Realm; class RealmCache; - class RealmDelegate; + class RealmBindingContext; typedef std::shared_ptr SharedRealm; typedef std::weak_ptr WeakRealm; @@ -120,7 +120,7 @@ namespace realm { std::shared_ptr<_impl::ExternalCommitHelper> m_notifier; public: - std::unique_ptr m_delegate; + std::unique_ptr m_binding_context; // FIXME private Group *read_group(); From 70e1967782c78ce6a936d13f063fe77437659a98 Mon Sep 17 00:00:00 2001 From: Kristian Dupont Date: Thu, 29 Oct 2015 13:16:36 +0100 Subject: [PATCH 07/41] Rename realm delegate in transact_log_handler as well --- impl/transact_log_handler.cpp | 40 +++++++++++++++++------------------ impl/transact_log_handler.hpp | 10 ++++----- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/impl/transact_log_handler.cpp b/impl/transact_log_handler.cpp index e1b95405..685dbd38 100644 --- a/impl/transact_log_handler.cpp +++ b/impl/transact_log_handler.cpp @@ -18,7 +18,7 @@ #include "transact_log_handler.hpp" -#include "realm_delegate.hpp" +#include "../realm_binding_context.hpp" #include #include @@ -28,15 +28,15 @@ using namespace realm; namespace { class TransactLogHandler { - using ColumnInfo = RealmDelegate::ColumnInfo; - using ObserverState = RealmDelegate::ObserverState; + using ColumnInfo = RealmBindingContext::ColumnInfo; + using ObserverState = RealmBindingContext::ObserverState; // Observed table rows which need change information std::vector m_observers; // Userdata pointers for rows which have been deleted std::vector invalidated; // Delegate to send change information to - RealmDelegate* m_delegate; + RealmBindingContext* m_binding_context; // Index of currently selected table size_t m_current_table = 0; @@ -84,33 +84,33 @@ class TransactLogHandler { public: template - TransactLogHandler(RealmDelegate* delegate, SharedGroup& sg, Func&& func) - : m_delegate(delegate) + TransactLogHandler(RealmBindingContext* binding_context, SharedGroup& sg, Func&& func) + : m_binding_context(binding_context) { - if (!delegate) { + if (!binding_context) { func(); return; } - m_observers = delegate->get_observed_rows(); + m_observers = binding_context->get_observed_rows(); if (m_observers.empty()) { auto old_version = sg.get_version_of_current_transaction(); func(); if (old_version != sg.get_version_of_current_transaction()) { - delegate->did_change({}, {}); + binding_context->did_change({}, {}); } return; } func(*this); - delegate->did_change(m_observers, invalidated); + binding_context->did_change(m_observers, invalidated); } // Called at the end of the transaction log immediately before the version // is advanced void parse_complete() { - m_delegate->will_change(m_observers, invalidated); + m_binding_context->will_change(m_observers, invalidated); } // These would require having an observer before schema init @@ -318,28 +318,28 @@ public: namespace realm { namespace _impl { namespace transaction { -void advance(SharedGroup& sg, ClientHistory& history, RealmDelegate* delegate) { - TransactLogHandler(delegate, sg, [&](auto&&... args) { +void advance(SharedGroup& sg, ClientHistory& history, RealmBindingContext* binding_context) { + TransactLogHandler(binding_context, sg, [&](auto&&... args) { LangBindHelper::advance_read(sg, history, std::move(args)...); }); } -void begin(SharedGroup& sg, ClientHistory& history, RealmDelegate* delegate) { - TransactLogHandler(delegate, sg, [&](auto&&... args) { +void begin(SharedGroup& sg, ClientHistory& history, RealmBindingContext* binding_context) { + TransactLogHandler(binding_context, sg, [&](auto&&... args) { LangBindHelper::promote_to_write(sg, history, std::move(args)...); }); } -void commit(SharedGroup& sg, ClientHistory&, RealmDelegate* delegate) { +void commit(SharedGroup& sg, ClientHistory&, RealmBindingContext* binding_context) { LangBindHelper::commit_and_continue_as_read(sg); - if (delegate) { - delegate->did_change({}, {}); + if (binding_context) { + binding_context->did_change({}, {}); } } -void cancel(SharedGroup& sg, ClientHistory& history, RealmDelegate* delegate) { - TransactLogHandler(delegate, sg, [&](auto&&... args) { +void cancel(SharedGroup& sg, ClientHistory& history, RealmBindingContext* binding_context) { + TransactLogHandler(binding_context, sg, [&](auto&&... args) { LangBindHelper::rollback_and_continue_as_read(sg, history, std::move(args)...); }); } diff --git a/impl/transact_log_handler.hpp b/impl/transact_log_handler.hpp index dbb54a53..321a67c9 100644 --- a/impl/transact_log_handler.hpp +++ b/impl/transact_log_handler.hpp @@ -20,7 +20,7 @@ #define REALM_TRANSACT_LOG_HANDLER_HPP namespace realm { -class RealmDelegate; +class RealmBindingContext; class SharedGroup; class ClientHistory; @@ -28,19 +28,19 @@ namespace _impl { namespace transaction { // Advance the read transaction version, with change notifications sent to delegate // Must not be called from within a write transaction. -void advance(SharedGroup& sg, ClientHistory& history, RealmDelegate* delegate); +void advance(SharedGroup& sg, ClientHistory& history, RealmBindingContext* binding_context); // Begin a write transaction // If the read transaction version is not up to date, will first advance to the // most recent read transaction and sent notifications to delegate -void begin(SharedGroup& sg, ClientHistory& history, RealmDelegate* delegate); +void begin(SharedGroup& sg, ClientHistory& history, RealmBindingContext* binding_context); // Commit a write transaction -void commit(SharedGroup& sg, ClientHistory& history, RealmDelegate* delegate); +void commit(SharedGroup& sg, ClientHistory& history, RealmBindingContext* binding_context); // Cancel a write transaction and roll back all changes, with change notifications // for reverting to the old values sent to delegate -void cancel(SharedGroup& sg, ClientHistory& history, RealmDelegate* delegate); +void cancel(SharedGroup& sg, ClientHistory& history, RealmBindingContext* binding_context); } // namespace transaction } // namespace _impl } // namespace realm From db36ca5b9c551aa396130bea5f183ef53af82222 Mon Sep 17 00:00:00 2001 From: Kristian Dupont Date: Tue, 3 Nov 2015 08:37:54 +0100 Subject: [PATCH 08/41] Remove Realm suffix --- ..._binding_context.hpp => binding_context.hpp | 18 +++++++++--------- shared_realm.cpp | 2 +- shared_realm.hpp | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) rename realm_binding_context.hpp => binding_context.hpp (91%) diff --git a/realm_binding_context.hpp b/binding_context.hpp similarity index 91% rename from realm_binding_context.hpp rename to binding_context.hpp index 1e82e1e2..4aa6dd94 100644 --- a/realm_binding_context.hpp +++ b/binding_context.hpp @@ -16,8 +16,8 @@ // //////////////////////////////////////////////////////////////////////////// -#ifndef REALM_BINDING_CONTEXT_HPP -#define REALM_BINDING_CONTEXT_HPP +#ifndef BINDING_CONTEXT_HPP +#define BINDING_CONTEXT_HPP #include "index_set.hpp" @@ -25,7 +25,7 @@ #include namespace realm { -// RealmBindingContext is the extension point for adding binding-specific behavior to +// BindingContext is the extension point for adding binding-specific behavior to // a SharedRealm. It can be used to store additonal data associated with the // Realm which is needed by the binding, and there are several methods which // can be overridden to receive notifications of state changes within the Realm. @@ -33,7 +33,7 @@ namespace realm { // A simple implementation which lets the user register functions to be // called on refresh could look like the following: // -// class BindingContextImplementation : public RealmBindingContext { +// class BindingContextImplementation : public BindingContext { // public: // // A token returned from add_notification that can be used to remove the // // notification later @@ -66,9 +66,9 @@ namespace realm { // private: // std::list> m_registered_notifications; // }; -class RealmBindingContext { +class BindingContext { public: - virtual ~RealmBindingContext() = default; + virtual ~BindingContext() = default; // Called by the Realm when a write transaction is committed to the file by // a different Realm instance (possibly in a different process) @@ -147,8 +147,8 @@ public: }; }; -inline void RealmBindingContext::will_change(std::vector const&, std::vector const&) { } -inline void RealmBindingContext::did_change(std::vector const&, std::vector const&) { } +inline void BindingContext::will_change(std::vector const&, std::vector const&) { } +inline void BindingContext::did_change(std::vector const&, std::vector const&) { } } // namespace realm -#endif /* REALM_BINDING_CONTEXT_HPP */ +#endif /* BINDING_CONTEXT_HPP */ diff --git a/shared_realm.cpp b/shared_realm.cpp index 5eeb57da..861b9d6d 100644 --- a/shared_realm.cpp +++ b/shared_realm.cpp @@ -19,7 +19,7 @@ #include "shared_realm.hpp" #include "external_commit_helper.hpp" -#include "realm_binding_context.hpp" +#include "binding_context.hpp" #include "schema.hpp" #include "transact_log_handler.hpp" diff --git a/shared_realm.hpp b/shared_realm.hpp index bc078fba..7aedb3c5 100644 --- a/shared_realm.hpp +++ b/shared_realm.hpp @@ -30,7 +30,7 @@ namespace realm { class ClientHistory; class Realm; class RealmCache; - class RealmBindingContext; + class BindingContext; typedef std::shared_ptr SharedRealm; typedef std::weak_ptr WeakRealm; @@ -120,7 +120,7 @@ namespace realm { std::shared_ptr<_impl::ExternalCommitHelper> m_notifier; public: - std::unique_ptr m_binding_context; + std::unique_ptr m_binding_context; // FIXME private Group *read_group(); From 52e7e6168b5bd8dfcce1a9162b289e8869e1daaa Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Wed, 4 Nov 2015 15:24:29 -0800 Subject: [PATCH 09/41] Update for core 0.94.4 --- impl/transact_log_handler.cpp | 13 ++++++++++--- object_schema.hpp | 2 +- object_store.cpp | 4 ---- schema.cpp | 4 ---- schema.hpp | 2 +- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/impl/transact_log_handler.cpp b/impl/transact_log_handler.cpp index 685dbd38..fba97129 100644 --- a/impl/transact_log_handler.cpp +++ b/impl/transact_log_handler.cpp @@ -175,7 +175,7 @@ public: return true; } - bool select_link_list(size_t col, size_t row) + bool select_link_list(size_t col, size_t row, size_t) { m_active_linklist = nullptr; for (auto& o : m_observers) { @@ -303,15 +303,22 @@ public: bool set_date_time(size_t col, size_t row, DateTime) { return mark_dirty(row, col); } bool set_table(size_t col, size_t row) { return mark_dirty(row, col); } bool set_mixed(size_t col, size_t row, const Mixed&) { return mark_dirty(row, col); } - bool set_link(size_t col, size_t row, size_t) { return mark_dirty(row, col); } + bool set_link(size_t col, size_t row, size_t, size_t) { return mark_dirty(row, col); } bool set_null(size_t col, size_t row) { return mark_dirty(row, col); } - bool nullify_link(size_t col, size_t row) { return mark_dirty(row, col); } + bool nullify_link(size_t col, size_t row, size_t) { return mark_dirty(row, col); } // Doesn't change any data bool optimize_table() { return true; } // Used for subtables, which we currently don't support bool select_descriptor(int, const size_t*) { return false; } + + // Not implemented + bool insert_substring(size_t, size_t, size_t, StringData) { return false; } + bool erase_substring(size_t, size_t, size_t, size_t) { return false; } + bool swap_rows(size_t, size_t) { return false; } + bool move_column(size_t, size_t) { return false; } + bool move_group_level_table(size_t, size_t) { return false; } }; } // anonymous namespace diff --git a/object_schema.hpp b/object_schema.hpp index aca4af31..4ede6ce5 100644 --- a/object_schema.hpp +++ b/object_schema.hpp @@ -25,8 +25,8 @@ #include namespace realm { - class Property; class Group; + struct Property; class ObjectSchema { public: diff --git a/object_store.cpp b/object_store.cpp index ba7a868b..2cd4a077 100644 --- a/object_store.cpp +++ b/object_store.cpp @@ -550,11 +550,7 @@ InvalidNullabilityException::InvalidNullabilityException(std::string const& obje m_what = "'Object' property '" + property.name + "' must be nullable."; } else { -#if REALM_NULL_STRINGS == 1 m_what = "Array or Mixed property '" + property.name + "' cannot be nullable"; -#else - m_what = "Only 'Object' property types are nullable"; -#endif } } diff --git a/schema.cpp b/schema.cpp index bf7a6181..911dc4e5 100644 --- a/schema.cpp +++ b/schema.cpp @@ -71,11 +71,7 @@ void Schema::validate() const // check nullablity if (prop.is_nullable) { -#if REALM_NULL_STRINGS == 1 if (prop.type == PropertyTypeArray || prop.type == PropertyTypeAny) { -#else - if (prop.type != PropertyTypeObject) { -#endif exceptions.emplace_back(InvalidNullabilityException(object.name, prop)); } } diff --git a/schema.hpp b/schema.hpp index 0a7fa425..4d9c7bed 100644 --- a/schema.hpp +++ b/schema.hpp @@ -52,4 +52,4 @@ public: }; } -#endif /* defined(REALM_SCHEMA_HPP) */ \ No newline at end of file +#endif /* defined(REALM_SCHEMA_HPP) */ From e1e9cd8cd706b78ffdc8118c6b4b2cbde60cb22b Mon Sep 17 00:00:00 2001 From: JP Simard Date: Sun, 13 Sep 2015 15:11:54 +0200 Subject: [PATCH 10/41] Add ObjectStore::is_empty() --- object_store.cpp | 14 +++++++++++++- object_store.hpp | 5 ++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/object_store.cpp b/object_store.cpp index ba7a868b..d4ef716c 100644 --- a/object_store.cpp +++ b/object_store.cpp @@ -501,7 +501,19 @@ void ObjectStore::delete_data_for_object(Group *group, const StringData &object_ } } - +bool ObjectStore::is_empty(const Group *group) { + for (size_t i = 0; i < group->size(); i++) { + ConstTableRef table = group->get_table(i); + std::string object_type = object_type_for_table_name(table->get_name()); + if (!object_type.length()) { + continue; + } + if (!table->is_empty()) { + return false; + } + } + return true; +} InvalidSchemaVersionException::InvalidSchemaVersionException(uint64_t old_version, uint64_t new_version) : m_old_version(old_version), m_new_version(new_version) diff --git a/object_store.hpp b/object_store.hpp index f38524f8..3da680fb 100644 --- a/object_store.hpp +++ b/object_store.hpp @@ -70,7 +70,10 @@ namespace realm { // deletes the table for the given type static void delete_data_for_object(Group *group, const StringData &object_type); - private: + // indicates if this group contains any objects + static bool is_empty(const Group *group); + + private: // set a new schema version static void set_schema_version(Group *group, uint64_t version); From b93e5cedff7a0dfc562e281806e31998887f2a24 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Tue, 3 Nov 2015 17:00:06 -0800 Subject: [PATCH 11/41] Include the path of the file which actually failed to open in exceptions When the user (or our tests...) do dumb things it's sometimes not actually the realm file itself that failed to open. --- shared_realm.cpp | 18 +++++++++++------- shared_realm.hpp | 7 +++++-- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/shared_realm.cpp b/shared_realm.cpp index 861b9d6d..6d57f111 100644 --- a/shared_realm.cpp +++ b/shared_realm.cpp @@ -73,18 +73,22 @@ Realm::Realm(Config config) } } catch (util::File::PermissionDenied const& ex) { - throw RealmFileException(RealmFileException::Kind::PermissionDenied, "Unable to open a realm at path '" + m_config.path + - "'. Please use a path where your app has " + (m_config.read_only ? "read" : "read-write") + " permissions."); + throw RealmFileException(RealmFileException::Kind::PermissionDenied, ex.get_path(), + "Unable to open a realm at path '" + ex.get_path() + + "'. Please use a path where your app has " + (m_config.read_only ? "read" : "read-write") + " permissions."); } catch (util::File::Exists const& ex) { - throw RealmFileException(RealmFileException::Kind::Exists, "Unable to open a realm at path '" + m_config.path + "'"); + throw RealmFileException(RealmFileException::Kind::Exists, ex.get_path(), + "File at path '" + ex.get_path() + "' already exists."); } catch (util::File::AccessError const& ex) { - throw RealmFileException(RealmFileException::Kind::AccessError, "Unable to open a realm at path '" + m_config.path + "'"); + throw RealmFileException(RealmFileException::Kind::AccessError, ex.get_path(), + "Unable to open a realm at path '" + ex.get_path() + "'"); } - catch (IncompatibleLockFile const&) { - throw RealmFileException(RealmFileException::Kind::IncompatibleLockFile, "Realm file is currently open in another process " - "which cannot share access with this process. All processes sharing a single file must be the same architecture."); + catch (IncompatibleLockFile const& ex) { + throw RealmFileException(RealmFileException::Kind::IncompatibleLockFile, m_config.path, + "Realm file is currently open in another process " + "which cannot share access with this process. All processes sharing a single file must be the same architecture."); } } diff --git a/shared_realm.hpp b/shared_realm.hpp index 7aedb3c5..e6c94fc2 100644 --- a/shared_realm.hpp +++ b/shared_realm.hpp @@ -151,7 +151,7 @@ namespace realm { /** Thrown if the user does not have permission to open or create the specified file in the specified access mode when the realm is opened. */ PermissionDenied, - /** Thrown if no_create was specified and the file did already exist when the realm is opened. */ + /** Thrown if create_Always was specified and the file did already exist when the realm is opened. */ Exists, /** Thrown if no_create was specified and the file was not found when the realm is opened. */ NotFound, @@ -160,11 +160,14 @@ namespace realm { architecture mismatch. */ IncompatibleLockFile, }; - RealmFileException(Kind kind, std::string message) : std::runtime_error(message), m_kind(kind) {} + RealmFileException(Kind kind, std::string path, std::string message) : + std::runtime_error(std::move(message)), m_kind(kind), m_path(std::move(path)) {} Kind kind() const { return m_kind; } + const std::string& path() const { return m_path; } private: Kind m_kind; + std::string m_path; }; class MismatchedConfigException : public std::runtime_error From 883ef12c7f377cf2f134a2659349a08500a395a2 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Sat, 1 Aug 2015 15:31:45 -0700 Subject: [PATCH 12/41] Add Realm::close() and call it in RealmCache::clear() This is needed for the Swift tests due to that throwing an exception over Swift code unavoidably results in objects being leaked. --- shared_realm.cpp | 23 +++++++++++++++++++++++ shared_realm.hpp | 4 ++++ 2 files changed, 27 insertions(+) diff --git a/shared_realm.cpp b/shared_realm.cpp index 6d57f111..c87dd5d4 100644 --- a/shared_realm.cpp +++ b/shared_realm.cpp @@ -374,6 +374,22 @@ uint64_t Realm::get_schema_version(const realm::Realm::Config &config) return ObjectStore::get_schema_version(Realm(config).read_group()); } +void Realm::close() +{ + invalidate(); + + if (m_notifier) { + m_notifier->remove_realm(this); + } + + m_group = nullptr; + m_shared_group = nullptr; + m_history = nullptr; + m_read_only_group = nullptr; + m_notifier = nullptr; + m_binding_context = nullptr; +} + SharedRealm RealmCache::get_realm(const std::string &path, std::thread::id thread_id) { std::lock_guard lock(m_mutex); @@ -446,6 +462,13 @@ void RealmCache::cache_realm(SharedRealm &realm, std::thread::id thread_id) void RealmCache::clear() { std::lock_guard lock(m_mutex); + for (auto const& path : m_cache) { + for (auto const& thread : path.second) { + if (auto realm = thread.second.lock()) { + realm->close(); + } + } + } m_cache.clear(); } diff --git a/shared_realm.hpp b/shared_realm.hpp index e6c94fc2..81b14bf7 100644 --- a/shared_realm.hpp +++ b/shared_realm.hpp @@ -101,6 +101,10 @@ namespace realm { std::thread::id thread_id() const { return m_thread_id; } void verify_thread() const; + // Close this Realm and remove it from the cache. Continuing to use a + // Realm after closing it will produce undefined behavior. + void close(); + ~Realm(); private: From e4732994b7eba872ba414127806d51302f0479f1 Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Fri, 13 Nov 2015 18:20:40 -0800 Subject: [PATCH 13/41] integrate latest object store changes --- impl/transact_log_handler.cpp | 22 ++++++++++------------ impl/transact_log_handler.hpp | 10 +++++----- shared_realm.cpp | 4 +++- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/impl/transact_log_handler.cpp b/impl/transact_log_handler.cpp index fba97129..2deba2fd 100644 --- a/impl/transact_log_handler.cpp +++ b/impl/transact_log_handler.cpp @@ -18,25 +18,23 @@ #include "transact_log_handler.hpp" -#include "../realm_binding_context.hpp" +#include "../binding_context.hpp" #include #include #include -using namespace realm; - -namespace { +namespace realm { class TransactLogHandler { - using ColumnInfo = RealmBindingContext::ColumnInfo; - using ObserverState = RealmBindingContext::ObserverState; + using ColumnInfo = BindingContext::ColumnInfo; + using ObserverState = BindingContext::ObserverState; // Observed table rows which need change information std::vector m_observers; // Userdata pointers for rows which have been deleted std::vector invalidated; // Delegate to send change information to - RealmBindingContext* m_binding_context; + BindingContext* m_binding_context; // Index of currently selected table size_t m_current_table = 0; @@ -84,7 +82,7 @@ class TransactLogHandler { public: template - TransactLogHandler(RealmBindingContext* binding_context, SharedGroup& sg, Func&& func) + TransactLogHandler(BindingContext* binding_context, SharedGroup& sg, Func&& func) : m_binding_context(binding_context) { if (!binding_context) { @@ -325,19 +323,19 @@ public: namespace realm { namespace _impl { namespace transaction { -void advance(SharedGroup& sg, ClientHistory& history, RealmBindingContext* binding_context) { +void advance(SharedGroup& sg, ClientHistory& history, BindingContext* binding_context) { TransactLogHandler(binding_context, sg, [&](auto&&... args) { LangBindHelper::advance_read(sg, history, std::move(args)...); }); } -void begin(SharedGroup& sg, ClientHistory& history, RealmBindingContext* binding_context) { +void begin(SharedGroup& sg, ClientHistory& history, BindingContext* binding_context) { TransactLogHandler(binding_context, sg, [&](auto&&... args) { LangBindHelper::promote_to_write(sg, history, std::move(args)...); }); } -void commit(SharedGroup& sg, ClientHistory&, RealmBindingContext* binding_context) { +void commit(SharedGroup& sg, ClientHistory&, BindingContext* binding_context) { LangBindHelper::commit_and_continue_as_read(sg); if (binding_context) { @@ -345,7 +343,7 @@ void commit(SharedGroup& sg, ClientHistory&, RealmBindingContext* binding_contex } } -void cancel(SharedGroup& sg, ClientHistory& history, RealmBindingContext* binding_context) { +void cancel(SharedGroup& sg, ClientHistory& history, BindingContext* binding_context) { TransactLogHandler(binding_context, sg, [&](auto&&... args) { LangBindHelper::rollback_and_continue_as_read(sg, history, std::move(args)...); }); diff --git a/impl/transact_log_handler.hpp b/impl/transact_log_handler.hpp index 321a67c9..40ddf3f6 100644 --- a/impl/transact_log_handler.hpp +++ b/impl/transact_log_handler.hpp @@ -20,7 +20,7 @@ #define REALM_TRANSACT_LOG_HANDLER_HPP namespace realm { -class RealmBindingContext; +class BindingContext; class SharedGroup; class ClientHistory; @@ -28,19 +28,19 @@ namespace _impl { namespace transaction { // Advance the read transaction version, with change notifications sent to delegate // Must not be called from within a write transaction. -void advance(SharedGroup& sg, ClientHistory& history, RealmBindingContext* binding_context); +void advance(SharedGroup& sg, ClientHistory& history, BindingContext* binding_context); // Begin a write transaction // If the read transaction version is not up to date, will first advance to the // most recent read transaction and sent notifications to delegate -void begin(SharedGroup& sg, ClientHistory& history, RealmBindingContext* binding_context); +void begin(SharedGroup& sg, ClientHistory& history, BindingContext* binding_context); // Commit a write transaction -void commit(SharedGroup& sg, ClientHistory& history, RealmBindingContext* binding_context); +void commit(SharedGroup& sg, ClientHistory& history, BindingContext* binding_context); // Cancel a write transaction and roll back all changes, with change notifications // for reverting to the old values sent to delegate -void cancel(SharedGroup& sg, ClientHistory& history, RealmBindingContext* binding_context); +void cancel(SharedGroup& sg, ClientHistory& history, BindingContext* binding_context); } // namespace transaction } // namespace _impl } // namespace realm diff --git a/shared_realm.cpp b/shared_realm.cpp index c87dd5d4..09b4d188 100644 --- a/shared_realm.cpp +++ b/shared_realm.cpp @@ -203,7 +203,9 @@ bool Realm::update_schema(std::unique_ptr schema, uint64_t version) auto migration_function = [&](Group*, Schema&) { SharedRealm old_realm(new Realm(old_config)); auto updated_realm = shared_from_this(); - m_config.migration_function(old_realm, updated_realm); + if (m_config.migration_function) { + m_config.migration_function(old_realm, updated_realm); + } }; try { From 85286b88078385fa9862bb1e3207726a8b87e274 Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Mon, 16 Nov 2015 11:16:09 -0800 Subject: [PATCH 14/41] block refresh until the last context has finished execution --- shared_realm.cpp | 6 ++++-- shared_realm.hpp | 6 ++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/shared_realm.cpp b/shared_realm.cpp index 09b4d188..d95b8bd2 100644 --- a/shared_realm.cpp +++ b/shared_realm.cpp @@ -287,8 +287,6 @@ void Realm::cancel_transaction() void Realm::invalidate() { verify_thread(); - check_read_write(this); - if (m_in_transaction) { cancel_transaction(); } @@ -384,6 +382,10 @@ void Realm::close() m_notifier->remove_realm(this); } + if (m_group) { + m_shared_group->end_read(); + } + m_group = nullptr; m_shared_group = nullptr; m_history = nullptr; diff --git a/shared_realm.hpp b/shared_realm.hpp index 81b14bf7..09685128 100644 --- a/shared_realm.hpp +++ b/shared_realm.hpp @@ -197,6 +197,12 @@ namespace realm { public: UnitializedRealmException(std::string message) : std::runtime_error(message) {} }; + + class ClosedRealmException : public std::runtime_error + { + public: + ClosedRealmException(std::string message) : std::runtime_error(message) {} + }; } #endif /* defined(REALM_REALM_HPP) */ From 9d373e630aaaf3433926a548a62a4abad031637b Mon Sep 17 00:00:00 2001 From: Scott Kyle Date: Mon, 16 Nov 2015 03:26:33 -0800 Subject: [PATCH 15/41] Update data properties to return ArrayBuffers As a convenience, the setters will take typed Arrays (e.g. Uint8Array) since that is a common representation of data in JS (as they are "views" of ArrayBuffer objects). The tests have been updated to reflect this new behavior. --- object_accessor.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/object_accessor.hpp b/object_accessor.hpp index a1350e3d..d1e78b80 100644 --- a/object_accessor.hpp +++ b/object_accessor.hpp @@ -62,6 +62,8 @@ namespace realm { static ValueType from_double(ContextType, double); static std::string to_string(ContextType, ValueType &); static ValueType from_string(ContextType, StringData); + static std::string to_binary(ContextType, ValueType &); + static ValueType from_binary(ContextType, BinaryData); static DateTime to_datetime(ContextType, ValueType &); static ValueType from_datetime(ContextType, DateTime); @@ -164,7 +166,7 @@ namespace realm { m_row.set_string(column, Accessor::to_string(ctx, value)); break; case PropertyTypeData: - m_row.set_binary(column, BinaryData(Accessor::to_string(ctx, value))); + m_row.set_binary(column, BinaryData(Accessor::to_binary(ctx, value))); break; case PropertyTypeAny: m_row.set_mixed(column, Accessor::to_mixed(ctx, value)); @@ -216,7 +218,7 @@ namespace realm { case PropertyTypeString: return Accessor::from_string(ctx, m_row.get_string(column)); case PropertyTypeData: - return Accessor::from_string(ctx, (std::string)m_row.get_binary(column)); + return Accessor::from_binary(ctx, m_row.get_binary(column)); case PropertyTypeAny: throw "Any not supported"; case PropertyTypeDate: From e3c9ec8ee7145ef8c320871835ea4fe8ebee75af Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Wed, 18 Nov 2015 14:36:46 -0800 Subject: [PATCH 16/41] fixes to list.cpp/hpp based on object store pr feedback - use lowercase strings for property names --- list.cpp | 54 ++++++++++++++++++++++++++++++++++++++++----- list.hpp | 38 ++++++++++++++++++++++++++----- object_accessor.hpp | 21 ++++++++++++++++++ shared_realm.cpp | 4 ---- shared_realm.hpp | 6 ----- 5 files changed, 103 insertions(+), 20 deletions(-) diff --git a/list.cpp b/list.cpp index ff57ef27..1cbf1477 100644 --- a/list.cpp +++ b/list.cpp @@ -1,6 +1,20 @@ -/* Copyright 2015 Realm Inc - All Rights Reserved - * Proprietary and Confidential - */ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2015 Realm Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////// #include "list.hpp" #import @@ -8,22 +22,46 @@ using namespace realm; size_t List::size() { + verify_attached(); return m_link_view->size(); } Row List::get(std::size_t row_ndx) { + verify_attached(); verify_valid_row(row_ndx); return m_link_view->get(row_ndx); } void List::set(std::size_t row_ndx, std::size_t target_row_ndx) { + verify_attached(); + verify_in_tranaction(); verify_valid_row(row_ndx); m_link_view->set(row_ndx, target_row_ndx); } -void List::verify_valid_row(std::size_t row_ndx) { +void List::add(std::size_t target_row_ndx) { + verify_attached(); + verify_in_tranaction(); + m_link_view->add(target_row_ndx); +} + +void List::insert(std::size_t row_ndx, std::size_t target_row_ndx) { + verify_attached(); + verify_in_tranaction(); + verify_valid_row(row_ndx, true); + m_link_view->insert(row_ndx, target_row_ndx); +} + +void List::remove(std::size_t row_ndx) { + verify_attached(); + verify_in_tranaction(); + verify_valid_row(row_ndx); + m_link_view->remove(row_ndx); +} + +void List::verify_valid_row(std::size_t row_ndx, bool insertion) { size_t size = m_link_view->size(); - if (row_ndx >= size) { + if (row_ndx > size || (!insertion && row_ndx == size)) { throw std::out_of_range(std::string("Index ") + std::to_string(row_ndx) + " is outside of range 0..." + std::to_string(size) + "."); } } @@ -34,3 +72,9 @@ void List::verify_attached() { } m_link_view->sync_if_needed(); } + +void List::verify_in_tranaction() { + if (!m_realm->is_in_transaction()) { + throw std::runtime_error("Can only mutate a list within a transaction."); + } +} diff --git a/list.hpp b/list.hpp index 18ef44e7..54bbed41 100644 --- a/list.hpp +++ b/list.hpp @@ -1,6 +1,20 @@ -/* Copyright 2015 Realm Inc - All Rights Reserved - * Proprietary and Confidential - */ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2015 Realm Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////// #ifndef REALM_LIST_HPP #define REALM_LIST_HPP @@ -15,14 +29,27 @@ namespace realm { const ObjectSchema &object_schema; SharedRealm realm() { return m_realm; } - LinkViewRef link_view() { return m_link_view; } size_t size(); Row get(std::size_t row_ndx); void set(std::size_t row_ndx, std::size_t target_row_ndx); - void verify_valid_row(std::size_t row_ndx); + void add(size_t target_row_ndx); + void remove(size_t list_ndx); + void insert(size_t list_ndx, size_t target_row_ndx); + + template + void add(ContextType ctx, ValueType value); + + template + void insert(ContextType ctx, ValueType value, size_t list_ndx); + + template + void set(ContextType ctx, ValueType value, size_t list_ndx); + + void verify_valid_row(std::size_t row_ndx, bool insertion = false); void verify_attached(); + void verify_in_tranaction(); private: SharedRealm m_realm; @@ -31,4 +58,5 @@ namespace realm { } + #endif /* REALM_LIST_HPP */ diff --git a/object_accessor.hpp b/object_accessor.hpp index d1e78b80..5cc7a358 100644 --- a/object_accessor.hpp +++ b/object_accessor.hpp @@ -297,6 +297,27 @@ namespace realm { } return object; } + + // + // List implementation + // + template + void List::add(ContextType ctx, ValueType value) + { + add(NativeAccessor::to_object_index(ctx, m_realm, value, object_schema.name, false)); + } + + template + void List::insert(ContextType ctx, ValueType value, size_t list_ndx) + { + insert(list_ndx, NativeAccessor::to_object_index(ctx, m_realm, value, object_schema.name, false)); + } + + template + void List::set(ContextType ctx, ValueType value, size_t list_ndx) + { + set(list_ndx, NativeAccessor::to_object_index(ctx, m_realm, value, object_schema.name, false)); + } } #endif /* defined(REALM_OBJECT_ACCESSOR_HPP) */ diff --git a/shared_realm.cpp b/shared_realm.cpp index d95b8bd2..9c0a4e1e 100644 --- a/shared_realm.cpp +++ b/shared_realm.cpp @@ -382,10 +382,6 @@ void Realm::close() m_notifier->remove_realm(this); } - if (m_group) { - m_shared_group->end_read(); - } - m_group = nullptr; m_shared_group = nullptr; m_history = nullptr; diff --git a/shared_realm.hpp b/shared_realm.hpp index 09685128..81b14bf7 100644 --- a/shared_realm.hpp +++ b/shared_realm.hpp @@ -197,12 +197,6 @@ namespace realm { public: UnitializedRealmException(std::string message) : std::runtime_error(message) {} }; - - class ClosedRealmException : public std::runtime_error - { - public: - ClosedRealmException(std::string message) : std::runtime_error(message) {} - }; } #endif /* defined(REALM_REALM_HPP) */ From a492966949f7bb51f13f025b10b35c1c78f43d31 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Sun, 28 Jun 2015 15:30:56 -0700 Subject: [PATCH 17/41] Move Realm::Config's default constructor out-of-line Removes the need for things including shared_realm.hpp to include schema.hpp. --- shared_realm.cpp | 2 ++ shared_realm.hpp | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/shared_realm.cpp b/shared_realm.cpp index 9c0a4e1e..e8a497e3 100644 --- a/shared_realm.cpp +++ b/shared_realm.cpp @@ -47,6 +47,8 @@ Realm::Config::Config(const Config& c) } } +Realm::Config::Config() = default; +Realm::Config::Config(Config&&) = default; Realm::Config::~Config() = default; Realm::Config& Realm::Config::operator=(realm::Realm::Config const& c) diff --git a/shared_realm.hpp b/shared_realm.hpp index 81b14bf7..0b51af5b 100644 --- a/shared_realm.hpp +++ b/shared_realm.hpp @@ -56,8 +56,8 @@ namespace realm { MigrationFunction migration_function; - Config() = default; - Config(Config&&) = default; + Config(); + Config(Config&&); Config(const Config& c); ~Config(); From 73b605d62ce8134f58ecafa2f9dbe8c3ef3a2c49 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Sun, 19 Jul 2015 15:31:08 -0700 Subject: [PATCH 18/41] Add results.{hpp,cpp} from realm-js --- results.cpp | 20 +++++++++++++++++--- results.hpp | 20 +++++++++++++++++--- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/results.cpp b/results.cpp index 1977e5be..e4ad126e 100644 --- a/results.cpp +++ b/results.cpp @@ -1,6 +1,20 @@ -/* Copyright 2015 Realm Inc - All Rights Reserved - * Proprietary and Confidential - */ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2015 Realm Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////// #include "results.hpp" #import diff --git a/results.hpp b/results.hpp index fff37124..fcb3e894 100644 --- a/results.hpp +++ b/results.hpp @@ -1,6 +1,20 @@ -/* Copyright 2015 Realm Inc - All Rights Reserved - * Proprietary and Confidential - */ +//////////////////////////////////////////////////////////////////////////// +// +// Copyright 2015 Realm Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////// #ifndef REALM_RESULTS_HPP #define REALM_RESULTS_HPP From ab7f3dcaa6d879f178bc4fed4344522a2b2971a5 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Sun, 2 Aug 2015 15:31:22 -0700 Subject: [PATCH 19/41] Port most of RLMResults's functionality to realm::Results --- results.cpp | 296 +++++++++++++++++++++++++++++++++++++++++++---- results.hpp | 147 +++++++++++++++++++---- shared_realm.cpp | 7 +- shared_realm.hpp | 2 +- 4 files changed, 404 insertions(+), 48 deletions(-) diff --git a/results.cpp b/results.cpp index e4ad126e..367a3c46 100644 --- a/results.cpp +++ b/results.cpp @@ -17,42 +17,288 @@ //////////////////////////////////////////////////////////////////////////// #include "results.hpp" -#import + +#include using namespace realm; -Results::Results(SharedRealm &r, ObjectSchema &o, Query q, SortOrder s) : - realm(r), object_schema(o), backing_query(q), table_view(backing_query.find_all()) +Results::Results(SharedRealm r, Query q, SortOrder s) +: m_realm(std::move(r)) +, m_query(std::move(q)) +, m_table(m_query.get_table().get()) +, m_sort(std::move(s)) +, m_mode(Mode::Query) { - setSort(std::move(s)); +} + +Results::Results(SharedRealm r, Table& table) +: m_realm(std::move(r)) +, m_table(&table) +, m_mode(Mode::Table) +{ +} + +void Results::validate_read() const +{ + if (m_realm && !m_realm->check_thread()) + throw Error::IncorrectThread; + if (m_table && !m_table->is_attached()) + throw Error::Invalidated; +} + +void Results::validate_write() const +{ + validate_read(); + if (!m_realm || !m_realm->is_in_transaction()) + throw Error::NotInWrite; } size_t Results::size() { - verify_attached(); - return table_view.size(); -} - -void Results::setSort(SortOrder s) -{ - sort_order = std::make_unique(std::move(s)); - table_view.sort(sort_order->columnIndices, sort_order->ascending); -} - -Row Results::get(std::size_t row_ndx) -{ - verify_attached(); - if (row_ndx >= table_view.size()) { - throw std::out_of_range(std::string("Index ") + std::to_string(row_ndx) + " is outside of range 0..." + - std::to_string(table_view.size()) + "."); + validate_read(); + switch (m_mode) { + case Mode::Empty: return 0; + case Mode::Table: return m_table->size(); + case Mode::Query: return m_query.count(); + case Mode::TableView: + update_tableview(); + return m_table_view.size(); } - return table_view.get(row_ndx); } -void Results::verify_attached() +RowExpr Results::get(size_t row_ndx) { - if (!table_view.is_attached()) { - throw std::runtime_error("Tableview is not attached"); + validate_read(); + switch (m_mode) { + case Mode::Empty: break; + case Mode::Table: + if (row_ndx < m_table->size()) + return m_table->get(row_ndx); + break; + case Mode::Query: + case Mode::TableView: + update_tableview(); + if (row_ndx < m_table_view.size()) + return m_table_view.get(row_ndx); + break; } - table_view.sync_if_needed(); + + throw Error::OutOfBoundsIndex; +} + +util::Optional Results::first() +{ + validate_read(); + switch (m_mode) { + case Mode::Empty: + return none; + case Mode::Table: + return m_table->size() == 0 ? util::none : util::Optional(m_table->front()); + case Mode::Query: + update_tableview(); + [[clang::fallthrough]]; + case Mode::TableView: + return m_table_view.size() == 0 ? util::none : util::Optional(m_table_view.front()); + } +} + +util::Optional Results::last() +{ + validate_read(); + switch (m_mode) { + case Mode::Empty: + return none; + case Mode::Table: + return m_table->size() == 0 ? util::none : util::Optional(m_table->back()); + case Mode::Query: + update_tableview(); + [[clang::fallthrough]]; + case Mode::TableView: + return m_table_view.size() == 0 ? util::none : util::Optional(m_table_view.back()); + } +} + +void Results::update_tableview() +{ + validate_read(); + switch (m_mode) { + case Mode::Empty: + case Mode::Table: + return; + case Mode::Query: + m_table_view = m_query.find_all(); + if (m_sort) { + m_table_view.sort(m_sort.columnIndices, m_sort.ascending); + } + m_mode = Mode::TableView; + break; + case Mode::TableView: + m_table_view.sync_if_needed(); + break; + } +} + +size_t Results::index_of(Row const& row) +{ + validate_read(); + if (!row) { + throw Error::DetachedAccessor; + } + if (m_table && row.get_table() != m_table) { + throw Error::IncorrectTable; + } + return index_of(row.get_index()); +} + +size_t Results::index_of(size_t row_ndx) +{ + validate_read(); + switch (m_mode) { + case Mode::Empty: + return not_found; + case Mode::Table: + return row_ndx; + case Mode::Query: + if (!m_sort) + return m_query.count(row_ndx, row_ndx + 1) ? m_query.count(0, row_ndx) : not_found; + [[clang::fallthrough]]; + case Mode::TableView: + update_tableview(); + return m_table_view.find_by_source_ndx(row_ndx); + } + +} + +template +util::Optional Results::aggregate(size_t column, bool return_none_for_empty, + Int agg_int, Float agg_float, + Double agg_double, DateTime agg_datetime) +{ + validate_read(); + if (!m_table) + return none; + if (column > m_table->get_column_count()) + throw Error::OutOfBoundsIndex; + + auto do_agg = [&](auto const& getter) -> util::Optional { + switch (m_mode) { + case Mode::Empty: + return none; + case Mode::Table: + if (return_none_for_empty && m_table->size() == 0) + return none; + return util::Optional(getter(*m_table)); + case Mode::Query: + case Mode::TableView: + update_tableview(); + if (return_none_for_empty && m_table_view.size() == 0) + return none; + return util::Optional(getter(m_table_view)); + } + }; + + switch (m_table->get_column_type(column)) + { + case type_DateTime: return do_agg(agg_datetime); + case type_Double: return do_agg(agg_double); + case type_Float: return do_agg(agg_float); + case type_Int: return do_agg(agg_int); + default: + throw Error::UnsupportedColumnType; + } +} + +util::Optional Results::max(size_t column) +{ + return aggregate(column, true, + [=](auto const& table) { return table.maximum_int(column); }, + [=](auto const& table) { return table.maximum_float(column); }, + [=](auto const& table) { return table.maximum_double(column); }, + [=](auto const& table) { return table.maximum_datetime(column); }); +} + +util::Optional Results::min(size_t column) +{ + return aggregate(column, true, + [=](auto const& table) { return table.minimum_int(column); }, + [=](auto const& table) { return table.minimum_float(column); }, + [=](auto const& table) { return table.minimum_double(column); }, + [=](auto const& table) { return table.minimum_datetime(column); }); +} + +util::Optional Results::sum(size_t column) +{ + return aggregate(column, false, + [=](auto const& table) { return table.sum_int(column); }, + [=](auto const& table) { return table.sum_float(column); }, + [=](auto const& table) { return table.sum_double(column); }, + [=](auto const&) -> util::None { throw Error::UnsupportedColumnType; }); +} + +util::Optional Results::average(size_t column) +{ + return aggregate(column, true, + [=](auto const& table) { return table.average_int(column); }, + [=](auto const& table) { return table.average_float(column); }, + [=](auto const& table) { return table.average_double(column); }, + [=](auto const&) -> util::None { throw Error::UnsupportedColumnType; }); +} + +void Results::clear() +{ + switch (m_mode) { + case Mode::Empty: + return; + case Mode::Table: + validate_write(); + m_table->clear(); + break; + case Mode::Query: + // Not using Query:remove() because bulding the tableview and + // clearing it is actually significantly faster + case Mode::TableView: + validate_write(); + update_tableview(); + m_table_view.clear(); + break; + } +} + +Query Results::get_query() const +{ + validate_read(); + switch (m_mode) { + case Mode::Empty: + case Mode::Query: + case Mode::TableView: + return m_query; + case Mode::Table: + return m_table->where(); + } +} + +TableView Results::get_tableview() +{ + validate_read(); + switch (m_mode) { + case Mode::Empty: + return {}; + case Mode::Query: + case Mode::TableView: + update_tableview(); + return m_table_view; + case Mode::Table: + return m_table->where().find_all(); + } + REALM_UNREACHABLE(); +} + +Results Results::sort(realm::SortOrder&& sort) const +{ + return Results(m_realm, get_query(), std::move(sort)); +} + +Results Results::filter(Query&& q) const +{ + return Results(m_realm, get_query().and_query(q), get_sort()); } diff --git a/results.hpp b/results.hpp index fcb3e894..ef941b03 100644 --- a/results.hpp +++ b/results.hpp @@ -19,35 +19,140 @@ #ifndef REALM_RESULTS_HPP #define REALM_RESULTS_HPP -#import "shared_realm.hpp" -#import +#include "shared_realm.hpp" + +#include +#include +#include namespace realm { - struct SortOrder { - std::vector columnIndices; - std::vector ascending; +template class BasicRowExpr; +using RowExpr = BasicRowExpr; +class Mixed; - explicit operator bool() const { - return !columnIndices.empty(); - } +struct SortOrder { + std::vector columnIndices; + std::vector ascending; + + explicit operator bool() const + { + return !columnIndices.empty(); + } +}; + +class Results { +public: + // Results can be either be backed by nothing, a thin wrapper around a table, + // or a wrapper around a query and a sort order which creates and updates + // the tableview as needed + Results() = default; + Results(SharedRealm r, Table& table); + Results(SharedRealm r, Query q, SortOrder s = {}); + + // Results is copyable and moveable + Results(Results const&) = default; + Results(Results&&) = default; + Results& operator=(Results const&) = default; + Results& operator=(Results&&) = default; + + // Get a query which will match the same rows as is contained in this Results + // Returned query will not be valid if the current mode is Empty + Query get_query() const; + + // Get the currently applied sort order for this Results + SortOrder const& get_sort() const noexcept { return m_sort; } + + // Get a tableview containing the same rows as this Results + TableView get_tableview(); + + // Get the size of this results + // Can be either O(1) or O(N) depending on the state of things + size_t size(); + + // Get the row accessor for the given index + // Throws OutOfBoundsIndex if index >= size() + RowExpr get(size_t index); + + // Get a row accessor for the first/last row, or none if the results are empty + // More efficient than calling size()+get() + util::Optional first(); + util::Optional last(); + + // Get the first index of the given row in this results, or not_found + // Throws DetachedAccessor if row is not attached + // Throws IncorrectTable if row belongs to a different table + size_t index_of(size_t row_ndx); + size_t index_of(Row const& row); + + // Delete all of the rows in this Results from the Realm + // size() will always be zero afterwards + // Throws NotInWrite + void clear(); + + // Create a new Results by further filtering or sorting this Results + Results filter(Query&& q) const; + Results sort(SortOrder&& sort) const; + + // Get the min/max/average/sum of the given column + // All but sum() returns none when there are zero matching rows + // sum() returns 0, except for when it returns none + // Throws UnsupportedColumnType for sum/average on datetime or non-numeric column + // Throws OutOfBoundsIndex for an out-of-bounds column + util::Optional max(size_t column); + util::Optional min(size_t column); + util::Optional average(size_t column); + util::Optional sum(size_t column); + + enum class Mode { + Empty, // Backed by nothing (for missing tables) + Table, // Backed directly by a Table + Query, // Backed by a query that has not yet been turned into a TableView + TableView // Backed by a TableView created from a Query + }; + // Get the currrent mode of the Results + // Ideally this would not be public but it's needed for some KVO stuff + Mode get_mode() const { return m_mode; } + + // All errors thrown by Results are one of the following error codes + // Invalidated and IncorrectThread can be thrown by all non-noexcept functions + // Other errors are thrown only where indicated + enum class Error { + // The Results object has been invalidated (due to the Realm being invalidated) + Invalidated, + // The Results object is being accessed from the wrong thread + IncorrectThread, + // The containing Realm is not in a write transaction + NotInWrite, + + // The input index parameter was out of bounds + OutOfBoundsIndex, + // The input Row object belongs to a different table + IncorrectTable, + // The input Row object is not attached + DetachedAccessor, + // The requested aggregate operation is not supported for the column type + UnsupportedColumnType }; - static SortOrder s_defaultSort = {{}, {}}; +private: + SharedRealm m_realm; + Query m_query; + TableView m_table_view; + Table* m_table = nullptr; + SortOrder m_sort; - struct Results { - Results(SharedRealm &r, ObjectSchema &o, Query q, SortOrder s = s_defaultSort); - size_t size(); - Row get(std::size_t row_ndx); - void verify_attached(); + Mode m_mode = Mode::Empty; - SharedRealm realm; - ObjectSchema &object_schema; - Query backing_query; - TableView table_view; - std::unique_ptr sort_order; + void validate_read() const; + void validate_write() const; - void setSort(SortOrder s); - }; + void update_tableview(); + + template + util::Optional aggregate(size_t column, bool return_none_for_empty, + Int agg_int, Float agg_float, + Double agg_double, DateTime agg_datetime); +}; } #endif /* REALM_RESULTS_HPP */ diff --git a/shared_realm.cpp b/shared_realm.cpp index e8a497e3..1a670563 100644 --- a/shared_realm.cpp +++ b/shared_realm.cpp @@ -236,9 +236,14 @@ static void check_read_write(Realm *realm) } } +bool Realm::check_thread() const noexcept +{ + return m_thread_id == std::this_thread::get_id(); +} + void Realm::verify_thread() const { - if (m_thread_id != std::this_thread::get_id()) { + if (!check_thread()) { throw IncorrectThreadException("Realm accessed from incorrect thread."); } } diff --git a/shared_realm.hpp b/shared_realm.hpp index 0b51af5b..ef848fcb 100644 --- a/shared_realm.hpp +++ b/shared_realm.hpp @@ -19,7 +19,6 @@ #ifndef REALM_REALM_HPP #define REALM_REALM_HPP -#include #include #include #include @@ -99,6 +98,7 @@ namespace realm { bool compact(); std::thread::id thread_id() const { return m_thread_id; } + bool check_thread() const noexcept; void verify_thread() const; // Close this Realm and remove it from the cache. Continuing to use a From 9dc5165a58706d6e719404ebfb635f8800dcf86c Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Wed, 5 Aug 2015 15:31:25 -0700 Subject: [PATCH 20/41] Fix compilation with GCC 4.9 --- results.cpp | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/results.cpp b/results.cpp index 367a3c46..3b3654d8 100644 --- a/results.cpp +++ b/results.cpp @@ -22,6 +22,18 @@ using namespace realm; +#ifdef __has_cpp_attribute +#define REALM_HAS_CCP_ATTRIBUTE(attr) __has_cpp_attribute(attr) +#else +#define REALM_HAS_CCP_ATTRIBUTE(attr) 0 +#endif + +#if REALM_HAS_CCP_ATTRIBUTE(clang::fallthrough) +#define REALM_FALLTHROUGH [[clang::fallthrough]] +#else +#define REALM_FALLTHROUGH +#endif + Results::Results(SharedRealm r, Query q, SortOrder s) : m_realm(std::move(r)) , m_query(std::move(q)) @@ -64,6 +76,7 @@ size_t Results::size() update_tableview(); return m_table_view.size(); } + REALM_UNREACHABLE(); } RowExpr Results::get(size_t row_ndx) @@ -96,10 +109,11 @@ util::Optional Results::first() return m_table->size() == 0 ? util::none : util::Optional(m_table->front()); case Mode::Query: update_tableview(); - [[clang::fallthrough]]; + REALM_FALLTHROUGH; case Mode::TableView: return m_table_view.size() == 0 ? util::none : util::Optional(m_table_view.front()); } + REALM_UNREACHABLE(); } util::Optional Results::last() @@ -112,10 +126,11 @@ util::Optional Results::last() return m_table->size() == 0 ? util::none : util::Optional(m_table->back()); case Mode::Query: update_tableview(); - [[clang::fallthrough]]; + REALM_FALLTHROUGH; case Mode::TableView: return m_table_view.size() == 0 ? util::none : util::Optional(m_table_view.back()); } + REALM_UNREACHABLE(); } void Results::update_tableview() @@ -161,12 +176,12 @@ size_t Results::index_of(size_t row_ndx) case Mode::Query: if (!m_sort) return m_query.count(row_ndx, row_ndx + 1) ? m_query.count(0, row_ndx) : not_found; - [[clang::fallthrough]]; + REALM_FALLTHROUGH; case Mode::TableView: update_tableview(); return m_table_view.find_by_source_ndx(row_ndx); } - + REALM_UNREACHABLE(); } template @@ -190,11 +205,12 @@ util::Optional Results::aggregate(size_t column, bool return_none_for_emp return util::Optional(getter(*m_table)); case Mode::Query: case Mode::TableView: - update_tableview(); + this->update_tableview(); if (return_none_for_empty && m_table_view.size() == 0) return none; return util::Optional(getter(m_table_view)); } + REALM_UNREACHABLE(); }; switch (m_table->get_column_type(column)) @@ -275,6 +291,7 @@ Query Results::get_query() const case Mode::Table: return m_table->where(); } + REALM_UNREACHABLE(); } TableView Results::get_tableview() From d1175fe364c6a812030719bc8dcef5b7d1f02758 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Thu, 6 Aug 2015 15:31:28 -0700 Subject: [PATCH 21/41] Switch to throwing exceptions with all of the info needed to build error messages --- object_store.cpp | 21 +++++++++--------- object_store.hpp | 9 ++++---- results.cpp | 28 ++++++++++++++---------- results.hpp | 55 +++++++++++++++++++++++++++--------------------- shared_realm.cpp | 16 ++++++++------ shared_realm.hpp | 34 ++++++++++++------------------ 6 files changed, 87 insertions(+), 76 deletions(-) diff --git a/object_store.cpp b/object_store.cpp index 3e32b98c..3aed85c5 100644 --- a/object_store.cpp +++ b/object_store.cpp @@ -30,6 +30,7 @@ using namespace realm; +namespace { const char * const c_metadataTableName = "metadata"; const char * const c_versionColumnName = "version"; const size_t c_versionColumnIndex = 0; @@ -42,8 +43,8 @@ const size_t c_primaryKeyPropertyNameColumnIndex = 1; const size_t c_zeroRowIndex = 0; -const std::string c_object_table_prefix = "class_"; -const size_t c_object_table_prefix_length = c_object_table_prefix.length(); +const char c_object_table_prefix[] = "class_"; +} const uint64_t ObjectStore::NotVersioned = std::numeric_limits::max(); @@ -119,15 +120,15 @@ void ObjectStore::set_primary_key_for_object(Group *group, StringData object_typ } } -std::string ObjectStore::object_type_for_table_name(const std::string &table_name) { - if (table_name.size() >= c_object_table_prefix_length && table_name.compare(0, c_object_table_prefix_length, c_object_table_prefix) == 0) { - return table_name.substr(c_object_table_prefix_length, table_name.length() - c_object_table_prefix_length); +StringData ObjectStore::object_type_for_table_name(StringData table_name) { + if (table_name.begins_with(c_object_table_prefix)) { + return table_name.substr(sizeof(c_object_table_prefix) - 1); } - return std::string(); + return StringData(); } -std::string ObjectStore::table_name_for_object_type(const std::string &object_type) { - return c_object_table_prefix + object_type; +std::string ObjectStore::table_name_for_object_type(StringData object_type) { + return std::string(c_object_table_prefix) + object_type.data(); } TableRef ObjectStore::table_for_object_type(Group *group, StringData object_type) { @@ -138,7 +139,7 @@ ConstTableRef ObjectStore::table_for_object_type(const Group *group, StringData return group->get_table(table_name_for_object_type(object_type)); } -TableRef ObjectStore::table_for_object_type_create_if_needed(Group *group, const StringData &object_type, bool &created) { +TableRef ObjectStore::table_for_object_type_create_if_needed(Group *group, StringData object_type, bool &created) { return group->get_or_add_table(table_name_for_object_type(object_type), &created); } @@ -494,7 +495,7 @@ void ObjectStore::validate_primary_column_uniqueness(const Group *group, Schema } } -void ObjectStore::delete_data_for_object(Group *group, const StringData &object_type) { +void ObjectStore::delete_data_for_object(Group *group, StringData object_type) { TableRef table = table_for_object_type(group, object_type); if (table) { group->remove_table(table->get_index_in_group()); diff --git a/object_store.hpp b/object_store.hpp index 60671f55..d41ec3fd 100644 --- a/object_store.hpp +++ b/object_store.hpp @@ -68,11 +68,14 @@ namespace realm { static Schema schema_from_group(const Group *group); // deletes the table for the given type - static void delete_data_for_object(Group *group, const StringData &object_type); + static void delete_data_for_object(Group *group, StringData object_type); // indicates if this group contains any objects static bool is_empty(const Group *group); + static std::string table_name_for_object_type(StringData class_name); + static StringData object_type_for_table_name(StringData table_name); + private: // set a new schema version static void set_schema_version(Group *group, uint64_t version); @@ -102,9 +105,7 @@ namespace realm { // must be in write transaction to set static void set_primary_key_for_object(Group *group, StringData object_type, StringData primary_key); - static TableRef table_for_object_type_create_if_needed(Group *group, const StringData &object_type, bool &created); - static std::string table_name_for_object_type(const std::string &class_name); - static std::string object_type_for_table_name(const std::string &table_name); + static TableRef table_for_object_type_create_if_needed(Group *group, StringData object_type, bool &created); // returns if any indexes were changed static bool update_indexes(Group *group, Schema &schema); diff --git a/results.cpp b/results.cpp index 3b3654d8..42956d37 100644 --- a/results.cpp +++ b/results.cpp @@ -52,17 +52,17 @@ Results::Results(SharedRealm r, Table& table) void Results::validate_read() const { - if (m_realm && !m_realm->check_thread()) - throw Error::IncorrectThread; + if (m_realm) + m_realm->verify_thread(); if (m_table && !m_table->is_attached()) - throw Error::Invalidated; + throw InvalidatedException(); } void Results::validate_write() const { validate_read(); if (!m_realm || !m_realm->is_in_transaction()) - throw Error::NotInWrite; + throw InvalidTransactionException("Must be in a write transaction"); } size_t Results::size() @@ -96,7 +96,7 @@ RowExpr Results::get(size_t row_ndx) break; } - throw Error::OutOfBoundsIndex; + throw OutOfBoundsIndexException{row_ndx, size()}; } util::Optional Results::first() @@ -157,10 +157,10 @@ size_t Results::index_of(Row const& row) { validate_read(); if (!row) { - throw Error::DetachedAccessor; + throw DetatchedAccessorException{}; } if (m_table && row.get_table() != m_table) { - throw Error::IncorrectTable; + throw IncorrectTableException{m_table, row.get_table()}; } return index_of(row.get_index()); } @@ -193,7 +193,7 @@ util::Optional Results::aggregate(size_t column, bool return_none_for_emp if (!m_table) return none; if (column > m_table->get_column_count()) - throw Error::OutOfBoundsIndex; + throw OutOfBoundsIndexException{column, m_table->get_column_count()}; auto do_agg = [&](auto const& getter) -> util::Optional { switch (m_mode) { @@ -220,7 +220,7 @@ util::Optional Results::aggregate(size_t column, bool return_none_for_emp case type_Float: return do_agg(agg_float); case type_Int: return do_agg(agg_int); default: - throw Error::UnsupportedColumnType; + throw UnsupportedColumnTypeException{column, m_table}; } } @@ -248,7 +248,7 @@ util::Optional Results::sum(size_t column) [=](auto const& table) { return table.sum_int(column); }, [=](auto const& table) { return table.sum_float(column); }, [=](auto const& table) { return table.sum_double(column); }, - [=](auto const&) -> util::None { throw Error::UnsupportedColumnType; }); + [=](auto const&) -> util::None { throw UnsupportedColumnTypeException{column, m_table}; }); } util::Optional Results::average(size_t column) @@ -257,7 +257,7 @@ util::Optional Results::average(size_t column) [=](auto const& table) { return table.average_int(column); }, [=](auto const& table) { return table.average_float(column); }, [=](auto const& table) { return table.average_double(column); }, - [=](auto const&) -> util::None { throw Error::UnsupportedColumnType; }); + [=](auto const&) -> util::None { throw UnsupportedColumnTypeException{column, m_table}; }); } void Results::clear() @@ -319,3 +319,9 @@ Results Results::filter(Query&& q) const { return Results(m_realm, get_query().and_query(q), get_sort()); } + +Results::UnsupportedColumnTypeException::UnsupportedColumnTypeException(size_t column, const Table* table) { + column_index = column; + column_name = table->get_column_name(column); + column_type = table->get_column_type(column); +} diff --git a/results.hpp b/results.hpp index ef941b03..895c084c 100644 --- a/results.hpp +++ b/results.hpp @@ -70,7 +70,7 @@ public: size_t size(); // Get the row accessor for the given index - // Throws OutOfBoundsIndex if index >= size() + // Throws OutOfBoundsIndexException if index >= size() RowExpr get(size_t index); // Get a row accessor for the first/last row, or none if the results are empty @@ -79,14 +79,14 @@ public: util::Optional last(); // Get the first index of the given row in this results, or not_found - // Throws DetachedAccessor if row is not attached - // Throws IncorrectTable if row belongs to a different table + // Throws DetachedAccessorException if row is not attached + // Throws IncorrectTableException if row belongs to a different table size_t index_of(size_t row_ndx); size_t index_of(Row const& row); // Delete all of the rows in this Results from the Realm // size() will always be zero afterwards - // Throws NotInWrite + // Throws InvalidTransactionException if not in a write transaction void clear(); // Create a new Results by further filtering or sorting this Results @@ -96,8 +96,8 @@ public: // Get the min/max/average/sum of the given column // All but sum() returns none when there are zero matching rows // sum() returns 0, except for when it returns none - // Throws UnsupportedColumnType for sum/average on datetime or non-numeric column - // Throws OutOfBoundsIndex for an out-of-bounds column + // Throws UnsupportedColumnTypeException for sum/average on datetime or non-numeric column + // Throws OutOfBoundsIndexException for an out-of-bounds column util::Optional max(size_t column); util::Optional min(size_t column); util::Optional average(size_t column); @@ -113,25 +113,32 @@ public: // Ideally this would not be public but it's needed for some KVO stuff Mode get_mode() const { return m_mode; } - // All errors thrown by Results are one of the following error codes - // Invalidated and IncorrectThread can be thrown by all non-noexcept functions - // Other errors are thrown only where indicated - enum class Error { - // The Results object has been invalidated (due to the Realm being invalidated) - Invalidated, - // The Results object is being accessed from the wrong thread - IncorrectThread, - // The containing Realm is not in a write transaction - NotInWrite, + // The Results object has been invalidated (due to the Realm being invalidated) + // All non-noexcept functions can throw this + struct InvalidatedException {}; - // The input index parameter was out of bounds - OutOfBoundsIndex, - // The input Row object belongs to a different table - IncorrectTable, - // The input Row object is not attached - DetachedAccessor, - // The requested aggregate operation is not supported for the column type - UnsupportedColumnType + // The input index parameter was out of bounds + struct OutOfBoundsIndexException { + size_t requested; + size_t valid_count; + }; + + // The input Row object is not attached + struct DetatchedAccessorException { }; + + // The input Row object belongs to a different table + struct IncorrectTableException { + const Table* expected; + const Table* actual; + }; + + // The requested aggregate operation is not supported for the column type + struct UnsupportedColumnTypeException { + size_t column_index; + StringData column_name; + DataType column_type; + + UnsupportedColumnTypeException(size_t column, const Table* table); }; private: diff --git a/shared_realm.cpp b/shared_realm.cpp index 1a670563..28bb81b6 100644 --- a/shared_realm.cpp +++ b/shared_realm.cpp @@ -236,15 +236,17 @@ static void check_read_write(Realm *realm) } } -bool Realm::check_thread() const noexcept -{ - return m_thread_id == std::this_thread::get_id(); -} - void Realm::verify_thread() const { - if (!check_thread()) { - throw IncorrectThreadException("Realm accessed from incorrect thread."); + if (m_thread_id != std::this_thread::get_id()) { + throw IncorrectThreadException(); + } +} + +void Realm::verify_in_write() const +{ + if (!is_in_transaction()) { + throw InvalidTransactionException("Cannot modify persisted objects outside of a write transaction."); } } diff --git a/shared_realm.hpp b/shared_realm.hpp index ef848fcb..0503282a 100644 --- a/shared_realm.hpp +++ b/shared_realm.hpp @@ -98,8 +98,8 @@ namespace realm { bool compact(); std::thread::id thread_id() const { return m_thread_id; } - bool check_thread() const noexcept; void verify_thread() const; + void verify_in_write() const; // Close this Realm and remove it from the cache. Continuing to use a // Realm after closing it will produce undefined behavior. @@ -145,11 +145,9 @@ namespace realm { std::mutex m_mutex; }; - class RealmFileException : public std::runtime_error - { - public: - enum class Kind - { + class RealmFileException : public std::runtime_error { + public: + enum class Kind { /** Thrown for any I/O related exception scenarios when a realm is opened. */ AccessError, /** Thrown if the user does not have permission to open or create @@ -169,32 +167,28 @@ namespace realm { Kind kind() const { return m_kind; } const std::string& path() const { return m_path; } - private: + private: Kind m_kind; std::string m_path; }; - class MismatchedConfigException : public std::runtime_error - { - public: + class MismatchedConfigException : public std::runtime_error { + public: MismatchedConfigException(std::string message) : std::runtime_error(message) {} }; - class InvalidTransactionException : public std::runtime_error - { - public: + class InvalidTransactionException : public std::runtime_error { + public: InvalidTransactionException(std::string message) : std::runtime_error(message) {} }; - class IncorrectThreadException : public std::runtime_error - { - public: - IncorrectThreadException(std::string message) : std::runtime_error(message) {} + class IncorrectThreadException : public std::runtime_error { + public: + IncorrectThreadException() : std::runtime_error("Realm accessed from incorrect thread.") {} }; - class UnitializedRealmException : public std::runtime_error - { - public: + class UnitializedRealmException : public std::runtime_error { + public: UnitializedRealmException(std::string message) : std::runtime_error(message) {} }; } From d7fe9f9fb840b6fc8d9591857f63be2b34dd868a Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Sat, 8 Aug 2015 15:31:41 -0700 Subject: [PATCH 22/41] Expose the object class name from Results --- results.cpp | 9 ++++++++- results.hpp | 7 +++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/results.cpp b/results.cpp index 42956d37..0ad41d39 100644 --- a/results.cpp +++ b/results.cpp @@ -160,7 +160,9 @@ size_t Results::index_of(Row const& row) throw DetatchedAccessorException{}; } if (m_table && row.get_table() != m_table) { - throw IncorrectTableException{m_table, row.get_table()}; + throw IncorrectTableException{ + ObjectStore::object_type_for_table_name(m_table->get_name()), + ObjectStore::object_type_for_table_name(row.get_table()->get_name())}; } return index_of(row.get_index()); } @@ -310,6 +312,11 @@ TableView Results::get_tableview() REALM_UNREACHABLE(); } +StringData Results::get_object_type() const noexcept +{ + return ObjectStore::object_type_for_table_name(m_table->get_name()); +} + Results Results::sort(realm::SortOrder&& sort) const { return Results(m_realm, get_query(), std::move(sort)); diff --git a/results.hpp b/results.hpp index 895c084c..b239f440 100644 --- a/results.hpp +++ b/results.hpp @@ -65,6 +65,9 @@ public: // Get a tableview containing the same rows as this Results TableView get_tableview(); + // Get the object type which will be returned by get() + StringData get_object_type() const noexcept; + // Get the size of this results // Can be either O(1) or O(N) depending on the state of things size_t size(); @@ -128,8 +131,8 @@ public: // The input Row object belongs to a different table struct IncorrectTableException { - const Table* expected; - const Table* actual; + StringData expected; + StringData actual; }; // The requested aggregate operation is not supported for the column type From 1698da2143596bace0864312c27957af722d6fe9 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Tue, 10 Nov 2015 15:37:06 -0800 Subject: [PATCH 23/41] Fix typo in comment --- results.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/results.cpp b/results.cpp index 0ad41d39..96937d76 100644 --- a/results.cpp +++ b/results.cpp @@ -272,7 +272,7 @@ void Results::clear() m_table->clear(); break; case Mode::Query: - // Not using Query:remove() because bulding the tableview and + // Not using Query:remove() because building the tableview and // clearing it is actually significantly faster case Mode::TableView: validate_write(); From 5683fa1e581c40ffe14ac556503b33b1e0e15566 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Tue, 10 Nov 2015 15:45:34 -0800 Subject: [PATCH 24/41] Use make_optional() --- results.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/results.cpp b/results.cpp index 96937d76..aa05b50a 100644 --- a/results.cpp +++ b/results.cpp @@ -106,12 +106,12 @@ util::Optional Results::first() case Mode::Empty: return none; case Mode::Table: - return m_table->size() == 0 ? util::none : util::Optional(m_table->front()); + return m_table->size() == 0 ? util::none : util::make_optional(m_table->front()); case Mode::Query: update_tableview(); REALM_FALLTHROUGH; case Mode::TableView: - return m_table_view.size() == 0 ? util::none : util::Optional(m_table_view.front()); + return m_table_view.size() == 0 ? util::none : util::make_optional(m_table_view.front()); } REALM_UNREACHABLE(); } @@ -123,12 +123,12 @@ util::Optional Results::last() case Mode::Empty: return none; case Mode::Table: - return m_table->size() == 0 ? util::none : util::Optional(m_table->back()); + return m_table->size() == 0 ? util::none : util::make_optional(m_table->back()); case Mode::Query: update_tableview(); REALM_FALLTHROUGH; case Mode::TableView: - return m_table_view.size() == 0 ? util::none : util::Optional(m_table_view.back()); + return m_table_view.size() == 0 ? util::none : util::make_optional(m_table_view.back()); } REALM_UNREACHABLE(); } From a8f1b235d7da3303332894b5cda9b7ff545a22f2 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Tue, 10 Nov 2015 16:07:54 -0800 Subject: [PATCH 25/41] Eliminate a query copy in Results::filter() --- results.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/results.cpp b/results.cpp index aa05b50a..215fcc3c 100644 --- a/results.cpp +++ b/results.cpp @@ -324,7 +324,7 @@ Results Results::sort(realm::SortOrder&& sort) const Results Results::filter(Query&& q) const { - return Results(m_realm, get_query().and_query(q), get_sort()); + return Results(m_realm, get_query().and_query(std::move(q)), get_sort()); } Results::UnsupportedColumnTypeException::UnsupportedColumnTypeException(size_t column, const Table* table) { From e53a53438416cbc37fcbca55f3dab3899de4a483 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Tue, 3 Nov 2015 11:23:04 -0800 Subject: [PATCH 26/41] End the read transaction after schema init --- shared_realm.cpp | 7 +++++++ shared_realm.hpp | 1 + 2 files changed, 8 insertions(+) diff --git a/shared_realm.cpp b/shared_realm.cpp index 28bb81b6..432f06d9 100644 --- a/shared_realm.cpp +++ b/shared_realm.cpp @@ -171,6 +171,13 @@ SharedRealm Realm::get_shared_realm(Config config) else { realm->update_schema(std::move(target_schema), target_schema_version); } + + if (!m_config.read_only) { + // End the read transaction created to validation/update the + // schema to avoid pinning the version even if the user never + // actually reads data + invalidate(); + } } } diff --git a/shared_realm.hpp b/shared_realm.hpp index 0503282a..02367b9e 100644 --- a/shared_realm.hpp +++ b/shared_realm.hpp @@ -88,6 +88,7 @@ namespace realm { void commit_transaction(); void cancel_transaction(); bool is_in_transaction() const { return m_in_transaction; } + bool is_in_read_transaction() const { return !!m_group; } bool refresh(); void set_auto_refresh(bool auto_refresh) { m_auto_refresh = auto_refresh; } From 9102924a7d686906c5bbb45f13fe408e30c9a731 Mon Sep 17 00:00:00 2001 From: Tim Oliver Date: Sat, 24 Oct 2015 15:44:56 +1100 Subject: [PATCH 27/41] Added support for suppressing file format upgrades. --- shared_realm.cpp | 8 +++++++- shared_realm.hpp | 3 +++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/shared_realm.cpp b/shared_realm.cpp index 28bb81b6..d5a7257f 100644 --- a/shared_realm.cpp +++ b/shared_realm.cpp @@ -38,6 +38,7 @@ Realm::Config::Config(const Config& c) , read_only(c.read_only) , in_memory(c.in_memory) , cache(c.cache) +, disable_format_upgrade(c.disable_format_upgrade) , encryption_key(c.encryption_key) , schema_version(c.schema_version) , migration_function(c.migration_function) @@ -71,7 +72,7 @@ Realm::Realm(Config config) m_history = realm::make_client_history(m_config.path, m_config.encryption_key.data()); SharedGroup::DurabilityLevel durability = m_config.in_memory ? SharedGroup::durability_MemOnly : SharedGroup::durability_Full; - m_shared_group = std::make_unique(*m_history, durability, m_config.encryption_key.data()); + m_shared_group = std::make_unique(*m_history, durability, m_config.encryption_key.data(), !m_config.disable_format_upgrade); } } catch (util::File::PermissionDenied const& ex) { @@ -92,6 +93,11 @@ Realm::Realm(Config config) "Realm file is currently open in another process " "which cannot share access with this process. All processes sharing a single file must be the same architecture."); } + catch (FileFormatUpgradeRequired const& ex) { + throw RealmFileException(RealmFileException::Kind::FormatUpgradeRequired, m_config.path, + "The Realm file format must be allowed to be upgraded " + "in order to proceed."); + } } Realm::~Realm() { diff --git a/shared_realm.hpp b/shared_realm.hpp index 0503282a..b9a09e55 100644 --- a/shared_realm.hpp +++ b/shared_realm.hpp @@ -48,6 +48,7 @@ namespace realm { bool read_only = false; bool in_memory = false; bool cache = true; + bool disable_format_upgrade = false; std::vector encryption_key; std::unique_ptr schema; @@ -161,6 +162,8 @@ namespace realm { process which cannot share with the current process due to an architecture mismatch. */ IncompatibleLockFile, + /** Thrown if the file needs to be upgraded to a new format, but upgrades have been explicitly disabled. */ + FormatUpgradeRequired, }; RealmFileException(Kind kind, std::string path, std::string message) : std::runtime_error(std::move(message)), m_kind(kind), m_path(std::move(path)) {} From 853658b3fc1ff07c2e9414dba53e338b1cf84fd1 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Thu, 3 Dec 2015 09:03:31 -0800 Subject: [PATCH 28/41] Change #import to #include --- list.cpp | 3 ++- list.hpp | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/list.cpp b/list.cpp index 1cbf1477..fdad3bac 100644 --- a/list.cpp +++ b/list.cpp @@ -17,7 +17,8 @@ //////////////////////////////////////////////////////////////////////////// #include "list.hpp" -#import + +#include using namespace realm; diff --git a/list.hpp b/list.hpp index 54bbed41..0b751728 100644 --- a/list.hpp +++ b/list.hpp @@ -19,8 +19,8 @@ #ifndef REALM_LIST_HPP #define REALM_LIST_HPP -#import "shared_realm.hpp" -#import +#include "shared_realm.hpp" +#include namespace realm { class List { From 473028c153cecb37e4c05e95c02075b9beb9db1c Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Thu, 3 Dec 2015 09:05:16 -0800 Subject: [PATCH 29/41] Add some missing header inclusions --- index_set.hpp | 1 + schema.hpp | 1 + shared_realm.hpp | 7 ++++--- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/index_set.hpp b/index_set.hpp index 7a229177..9cd9257d 100644 --- a/index_set.hpp +++ b/index_set.hpp @@ -19,6 +19,7 @@ #ifndef REALM_INDEX_SET_HPP #define REALM_INDEX_SET_HPP +#include #include namespace realm { diff --git a/schema.hpp b/schema.hpp index 4d9c7bed..b8d50777 100644 --- a/schema.hpp +++ b/schema.hpp @@ -19,6 +19,7 @@ #ifndef REALM_SCHEMA_HPP #define REALM_SCHEMA_HPP +#include #include namespace realm { diff --git a/shared_realm.hpp b/shared_realm.hpp index 0503282a..67b4f3a5 100644 --- a/shared_realm.hpp +++ b/shared_realm.hpp @@ -19,12 +19,13 @@ #ifndef REALM_REALM_HPP #define REALM_REALM_HPP +#include "object_store.hpp" + #include +#include #include #include -#include "object_store.hpp" - namespace realm { class ClientHistory; class Realm; @@ -166,7 +167,7 @@ namespace realm { std::runtime_error(std::move(message)), m_kind(kind), m_path(std::move(path)) {} Kind kind() const { return m_kind; } const std::string& path() const { return m_path; } - + private: Kind m_kind; std::string m_path; From 5028c4a58275bb42c8b25a33095207db75c77934 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Thu, 3 Dec 2015 09:11:28 -0800 Subject: [PATCH 30/41] Fix some warnings when building with GCC 4.9 --- list.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/list.hpp b/list.hpp index 0b751728..326a44fa 100644 --- a/list.hpp +++ b/list.hpp @@ -25,7 +25,7 @@ namespace realm { class List { public: - List(SharedRealm &r, const ObjectSchema &s, LinkViewRef l) : m_realm(r), object_schema(s), m_link_view(l) {} + List(SharedRealm &r, const ObjectSchema &s, LinkViewRef l) : object_schema(s), m_realm(r), m_link_view(l) {} const ObjectSchema &object_schema; SharedRealm realm() { return m_realm; } From 635bafe90f8347791fada2689f22643e78e595ab Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Tue, 1 Dec 2015 16:39:23 -0800 Subject: [PATCH 31/41] Update existing TableViews in first() and last() The call to update_tableview() was in the wrong place, resulting in it creating the table view, but not updating an existing one. --- results.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/results.cpp b/results.cpp index 215fcc3c..691e843d 100644 --- a/results.cpp +++ b/results.cpp @@ -108,9 +108,8 @@ util::Optional Results::first() case Mode::Table: return m_table->size() == 0 ? util::none : util::make_optional(m_table->front()); case Mode::Query: - update_tableview(); - REALM_FALLTHROUGH; case Mode::TableView: + update_tableview(); return m_table_view.size() == 0 ? util::none : util::make_optional(m_table_view.front()); } REALM_UNREACHABLE(); @@ -125,9 +124,8 @@ util::Optional Results::last() case Mode::Table: return m_table->size() == 0 ? util::none : util::make_optional(m_table->back()); case Mode::Query: - update_tableview(); - REALM_FALLTHROUGH; case Mode::TableView: + update_tableview(); return m_table_view.size() == 0 ? util::none : util::make_optional(m_table_view.back()); } REALM_UNREACHABLE(); From 87003ae6acae31ab144fdf4ac5ed30746c80153d Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Mon, 7 Dec 2015 10:11:44 -0800 Subject: [PATCH 32/41] Call TableView::clear() with RemoveMode::unordered --- results.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/results.cpp b/results.cpp index 691e843d..3b115e3a 100644 --- a/results.cpp +++ b/results.cpp @@ -275,7 +275,7 @@ void Results::clear() case Mode::TableView: validate_write(); update_tableview(); - m_table_view.clear(); + m_table_view.clear(RemoveMode::unordered); break; } } From 6199fba9f905ed8b7d448593b832bebe5d097dd3 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Tue, 22 Dec 2015 08:30:32 -0800 Subject: [PATCH 33/41] Add set_*_unique handlers to TransactLogHandler --- impl/transact_log_handler.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/impl/transact_log_handler.cpp b/impl/transact_log_handler.cpp index 2deba2fd..ed1630ca 100644 --- a/impl/transact_log_handler.cpp +++ b/impl/transact_log_handler.cpp @@ -304,6 +304,8 @@ public: bool set_link(size_t col, size_t row, size_t, size_t) { return mark_dirty(row, col); } bool set_null(size_t col, size_t row) { return mark_dirty(row, col); } bool nullify_link(size_t col, size_t row, size_t) { return mark_dirty(row, col); } + bool set_int_unique(size_t col, size_t row, int_fast64_t) { return mark_dirty(row, col); } + bool set_string_unique(size_t col, size_t row, StringData) { return mark_dirty(row, col); } // Doesn't change any data bool optimize_table() { return true; } From e8a26aa533e9681a4d2504b1a65a5c37bafc892b Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Tue, 22 Dec 2015 11:07:48 -0800 Subject: [PATCH 34/41] Fix compilation errors --- shared_realm.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared_realm.cpp b/shared_realm.cpp index 9807144f..2e4f2b03 100644 --- a/shared_realm.cpp +++ b/shared_realm.cpp @@ -178,11 +178,11 @@ SharedRealm Realm::get_shared_realm(Config config) realm->update_schema(std::move(target_schema), target_schema_version); } - if (!m_config.read_only) { + if (!realm->m_config.read_only) { // End the read transaction created to validation/update the // schema to avoid pinning the version even if the user never // actually reads data - invalidate(); + realm->invalidate(); } } } From aa5e1bef7d726e0b2ecba46e5b3cacd42663fcfe Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Mon, 4 Jan 2016 15:54:03 -0800 Subject: [PATCH 35/41] remove invalid usage of const Schema --- src/object-store/results.cpp | 22 ++++++++++------------ src/object-store/shared_realm.cpp | 4 ++-- src/object-store/shared_realm.hpp | 4 ++-- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/object-store/results.cpp b/src/object-store/results.cpp index ea591276..32b00dda 100644 --- a/src/object-store/results.cpp +++ b/src/object-store/results.cpp @@ -171,9 +171,10 @@ size_t Results::index_of(Row const& row) throw DetatchedAccessorException{}; } if (m_table && row.get_table() != m_table) { - throw IncorrectTableException{ - ObjectStore::object_type_for_table_name(m_table->get_name()), - ObjectStore::object_type_for_table_name(row.get_table()->get_name())}; + throw IncorrectTableException(object_schema.name, + ObjectStore::object_type_for_table_name(row.get_table()->get_name()), + "Attempting to get the index of a Row of the wrong type" + ); } return index_of(row.get_index()); } @@ -323,11 +324,6 @@ TableView Results::get_tableview() REALM_UNREACHABLE(); } -StringData Results::get_object_type() const noexcept -{ - return ObjectStore::object_type_for_table_name(m_table->get_name()); -} - Results Results::sort(realm::SortOrder&& sort) const { return Results(m_realm, object_schema, get_query(), std::move(sort)); @@ -338,8 +334,10 @@ Results Results::filter(Query&& q) const return Results(m_realm, object_schema, get_query().and_query(std::move(q)), get_sort()); } -Results::UnsupportedColumnTypeException::UnsupportedColumnTypeException(size_t column, const Table* table) { - column_index = column; - column_name = table->get_column_name(column); - column_type = table->get_column_type(column); +Results::UnsupportedColumnTypeException::UnsupportedColumnTypeException(size_t column, const Table* table) +: column_index(column) +, column_name(table->get_column_name(column)) +, column_type(table->get_column_type(column)) +, std::runtime_error((std::string)"Operation not supported on '" + table->get_column_name(column).data() + "' columns") +{ } diff --git a/src/object-store/shared_realm.cpp b/src/object-store/shared_realm.cpp index aeeeaa28..c43f27db 100644 --- a/src/object-store/shared_realm.cpp +++ b/src/object-store/shared_realm.cpp @@ -193,13 +193,13 @@ SharedRealm Realm::get_shared_realm(Config config) return realm; } -bool Realm::update_schema(std::unique_ptr schema, uint64_t version) +bool Realm::update_schema(std::unique_ptr schema, uint64_t version) { schema->validate(); bool needs_update = !m_config.read_only && (m_config.schema_version != version || ObjectStore::needs_update(*m_config.schema, *schema)); if (!needs_update) { - ObjectStore::verify_schema(*m_config.schema, const_cast(*schema), m_config.read_only); + ObjectStore::verify_schema(*m_config.schema, *schema, m_config.read_only); m_config.schema = std::move(schema); m_config.schema_version = version; return false; diff --git a/src/object-store/shared_realm.hpp b/src/object-store/shared_realm.hpp index ffb86937..85e42224 100644 --- a/src/object-store/shared_realm.hpp +++ b/src/object-store/shared_realm.hpp @@ -52,7 +52,7 @@ namespace realm { bool disable_format_upgrade = false; std::vector encryption_key; - std::unique_ptr schema; + std::unique_ptr schema; uint64_t schema_version = ObjectStore::NotVersioned; MigrationFunction migration_function; @@ -80,7 +80,7 @@ namespace realm { // on the Config, and the resulting Schema and version with updated // column mappings are set on the realms config upon success. // returns if any changes were made - bool update_schema(std::unique_ptr schema, uint64_t version); + bool update_schema(std::unique_ptr schema, uint64_t version); static uint64_t get_schema_version(Config const& config); From df901c636feaaaceaf2de433f0b9ab8d1023f067 Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Mon, 4 Jan 2016 16:04:01 -0800 Subject: [PATCH 36/41] store ObjectSchema as a pointer rather than a reference --- src/js_list.cpp | 8 ++++---- src/js_results.cpp | 6 +++--- src/object-store/list.hpp | 5 +++-- src/object-store/object_accessor.hpp | 6 +++--- src/object-store/results.cpp | 21 +++++---------------- src/object-store/results.hpp | 7 ++++--- src/rpc.cpp | 4 ++-- 7 files changed, 24 insertions(+), 33 deletions(-) diff --git a/src/js_list.cpp b/src/js_list.cpp index 987701fd..a60334b8 100644 --- a/src/js_list.cpp +++ b/src/js_list.cpp @@ -21,7 +21,7 @@ JSValueRef ListGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef pro return JSValueMakeNumber(ctx, size); } - return RJSObjectCreate(ctx, Object(list->realm(), list->object_schema, list->get(RJSValidatedPositiveIndex(indexStr)))); + return RJSObjectCreate(ctx, Object(list->realm(), list->object_schema(), list->get(RJSValidatedPositiveIndex(indexStr)))); } catch (std::out_of_range &exp) { // getters for nonexistent properties in JS should always return undefined @@ -103,7 +103,7 @@ JSValueRef ListPop(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObjec return JSValueMakeUndefined(ctx); } size_t index = size - 1; - JSValueRef obj = RJSObjectCreate(ctx, Object(list->realm(), list->object_schema, list->get(index))); + JSValueRef obj = RJSObjectCreate(ctx, Object(list->realm(), list->object_schema(), list->get(index))); list->remove(index); return obj; } @@ -140,7 +140,7 @@ JSValueRef ListShift(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObj list->verify_in_tranaction(); return JSValueMakeUndefined(ctx); } - JSValueRef obj = RJSObjectCreate(ctx, Object(list->realm(), list->object_schema, list->get(0))); + JSValueRef obj = RJSObjectCreate(ctx, Object(list->realm(), list->object_schema(), list->get(0))); list->remove(0); return obj; } @@ -168,7 +168,7 @@ JSValueRef ListSplice(JSContextRef ctx, JSObjectRef function, JSObjectRef thisOb std::vector removedObjects(remove); for (size_t i = 0; i < remove; i++) { - removedObjects[i] = RJSObjectCreate(ctx, Object(list->realm(), list->object_schema, list->get(index))); + removedObjects[i] = RJSObjectCreate(ctx, Object(list->realm(), list->object_schema(), list->get(index))); list->remove(index); } for (size_t i = 2; i < argumentCount; i++) { diff --git a/src/js_results.cpp b/src/js_results.cpp index 789d18da..35132fe9 100644 --- a/src/js_results.cpp +++ b/src/js_results.cpp @@ -23,7 +23,7 @@ JSValueRef ResultsGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef } return RJSObjectCreate(ctx, Object(results->get_realm(), - results->object_schema, + results->object_schema(), results->get(RJSValidatedPositiveIndex(indexStr)))); } catch (std::out_of_range &exp) { @@ -76,9 +76,9 @@ JSValueRef SortByProperty(JSContextRef ctx, JSObjectRef function, JSObjectRef th Results *results = RJSGetInternal(thisObject); RJSValidateArgumentRange(argumentCount, 1, 2); std::string propName = RJSValidatedStringForValue(ctx, arguments[0]); - const Property *prop = results->object_schema.property_for_name(propName); + const Property *prop = results->object_schema().property_for_name(propName); if (!prop) { - throw std::runtime_error("Property '" + propName + "' does not exist on object type '" + results->object_schema.name + "'"); + throw std::runtime_error("Property '" + propName + "' does not exist on object type '" + results->object_schema().name + "'"); } bool ascending = true; diff --git a/src/object-store/list.hpp b/src/object-store/list.hpp index ef84846a..e7c6465c 100644 --- a/src/object-store/list.hpp +++ b/src/object-store/list.hpp @@ -25,9 +25,9 @@ namespace realm { class List { public: - List(SharedRealm &r, const ObjectSchema &s, LinkViewRef l) : m_realm(r), object_schema(s), m_link_view(l) {} + List(SharedRealm &r, const ObjectSchema &s, LinkViewRef l) : m_realm(r), m_object_schema(&s), m_link_view(l) {} - const ObjectSchema &object_schema; + const ObjectSchema &object_schema() const { return *m_object_schema; } SharedRealm realm() { return m_realm; } size_t size(); @@ -53,6 +53,7 @@ namespace realm { private: SharedRealm m_realm; + const ObjectSchema *m_object_schema; LinkViewRef m_link_view; }; } diff --git a/src/object-store/object_accessor.hpp b/src/object-store/object_accessor.hpp index ae1025f0..eed939e1 100644 --- a/src/object-store/object_accessor.hpp +++ b/src/object-store/object_accessor.hpp @@ -308,19 +308,19 @@ namespace realm { template void List::add(ContextType ctx, ValueType value) { - add(NativeAccessor::to_object_index(ctx, m_realm, value, object_schema.name, false)); + add(NativeAccessor::to_object_index(ctx, m_realm, value, object_schema().name, false)); } template void List::insert(ContextType ctx, ValueType value, size_t list_ndx) { - insert(list_ndx, NativeAccessor::to_object_index(ctx, m_realm, value, object_schema.name, false)); + insert(list_ndx, NativeAccessor::to_object_index(ctx, m_realm, value, object_schema().name, false)); } template void List::set(ContextType ctx, ValueType value, size_t list_ndx) { - set(list_ndx, NativeAccessor::to_object_index(ctx, m_realm, value, object_schema.name, false)); + set(list_ndx, NativeAccessor::to_object_index(ctx, m_realm, value, object_schema().name, false)); } } diff --git a/src/object-store/results.cpp b/src/object-store/results.cpp index 32b00dda..e8d4bfd2 100644 --- a/src/object-store/results.cpp +++ b/src/object-store/results.cpp @@ -40,7 +40,7 @@ Results::Results(SharedRealm r, const ObjectSchema &o, Query q, SortOrder s) , m_table(m_query.get_table().get()) , m_sort(std::move(s)) , m_mode(Mode::Query) -, object_schema(o) +, m_object_schema(&o) { } @@ -48,21 +48,10 @@ Results::Results(SharedRealm r, const ObjectSchema &o, Table& table) : m_realm(std::move(r)) , m_table(&table) , m_mode(Mode::Table) -, object_schema(o) +, m_object_schema(&o) { } -Results& Results::operator=(Results const& r) -{ - m_realm = r.m_realm; - m_table = r.m_table; - m_sort = r.m_sort; - m_query = r.get_query(); - m_mode = Mode::Query; - const_cast(object_schema) = r.object_schema; - return *this; -} - void Results::validate_read() const { if (m_realm) @@ -171,7 +160,7 @@ size_t Results::index_of(Row const& row) throw DetatchedAccessorException{}; } if (m_table && row.get_table() != m_table) { - throw IncorrectTableException(object_schema.name, + throw IncorrectTableException(m_object_schema->name, ObjectStore::object_type_for_table_name(row.get_table()->get_name()), "Attempting to get the index of a Row of the wrong type" ); @@ -326,12 +315,12 @@ TableView Results::get_tableview() Results Results::sort(realm::SortOrder&& sort) const { - return Results(m_realm, object_schema, get_query(), std::move(sort)); + return Results(m_realm, object_schema(), get_query(), std::move(sort)); } Results Results::filter(Query&& q) const { - return Results(m_realm, object_schema, get_query().and_query(std::move(q)), get_sort()); + return Results(m_realm, object_schema(), get_query().and_query(std::move(q)), get_sort()); } Results::UnsupportedColumnTypeException::UnsupportedColumnTypeException(size_t column, const Table* table) diff --git a/src/object-store/results.hpp b/src/object-store/results.hpp index 9866cae8..42dbda8f 100644 --- a/src/object-store/results.hpp +++ b/src/object-store/results.hpp @@ -53,13 +53,13 @@ public: Results(Results const&) = default; Results(Results&&) = default; Results& operator=(Results&&) = default; - Results& operator=(Results const&); + Results& operator=(Results const&) = default; // Get the Realm SharedRealm get_realm() const { return m_realm; } // Object schema describing the vendored object type - const ObjectSchema &object_schema; + const ObjectSchema &object_schema() const { return *m_object_schema; } // Get a query which will match the same rows as is contained in this Results // Returned query will not be valid if the current mode is Empty @@ -72,7 +72,7 @@ public: TableView get_tableview(); // Get the object type which will be returned by get() - StringData get_object_type() const noexcept { return object_schema.name; } + StringData get_object_type() const noexcept { return object_schema().name; } // Get the size of this results // Can be either O(1) or O(N) depending on the state of things @@ -163,6 +163,7 @@ public: private: SharedRealm m_realm; + const ObjectSchema *m_object_schema; Query m_query; TableView m_table_view; Table* m_table = nullptr; diff --git a/src/rpc.cpp b/src/rpc.cpp index 962eb94d..2b04702b 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -229,7 +229,7 @@ json RPCServer::serialize_json_value(JSValueRef value) { {"type", RJSTypeGet(realm::PropertyTypeArray)}, {"id", store_object(js_object)}, {"size", list->size()}, - {"schema", serialize_object_schema(list->object_schema)} + {"schema", serialize_object_schema(list->object_schema())} }; } else if (JSValueIsObjectOfClass(m_context, value, RJSResultsClass())) { @@ -238,7 +238,7 @@ json RPCServer::serialize_json_value(JSValueRef value) { {"type", RealmObjectTypesResults}, {"id", store_object(js_object)}, {"size", results->size()}, - {"schema", serialize_object_schema(results->object_schema)} + {"schema", serialize_object_schema(results->object_schema())} }; } else if (RJSIsValueArray(m_context, value)) { From d964c77d2d8a40a5595dadf7e71982444e44d544 Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Mon, 4 Jan 2016 16:21:28 -0800 Subject: [PATCH 37/41] store ObjectSchema as a pointer rather than a reference --- src/js_object.cpp | 4 ++-- src/js_realm.cpp | 2 +- src/object-store/object_accessor.hpp | 17 +++++++++-------- src/rpc.cpp | 2 +- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/js_object.cpp b/src/js_object.cpp index 9ee910c5..3a5217b8 100644 --- a/src/js_object.cpp +++ b/src/js_object.cpp @@ -45,7 +45,7 @@ bool ObjectSetProperty(JSContextRef ctx, JSObjectRef jsObject, JSStringRef jsPro void ObjectPropertyNames(JSContextRef ctx, JSObjectRef jsObject, JSPropertyNameAccumulatorRef propertyNames) { Object *obj = RJSGetInternal(jsObject); - for (auto &prop : obj->object_schema.properties) { + for (auto &prop : obj->object_schema().properties) { JSStringRef propertyName = RJSStringForString(prop.name); JSPropertyNameAccumulatorAddName(propertyNames, propertyName); JSStringRelease(propertyName); @@ -58,7 +58,7 @@ JSClassRef RJSObjectClass() { } JSObjectRef RJSObjectCreate(JSContextRef ctx, Object object) { - JSValueRef prototype = RJSPrototypes(object.realm().get())[object.object_schema.name]; + JSValueRef prototype = RJSPrototypes(object.realm().get())[object.object_schema().name]; JSObjectRef jsObject = RJSWrapObject(ctx, RJSObjectClass(), new Object(object), prototype); return jsObject; } diff --git a/src/js_realm.cpp b/src/js_realm.cpp index 641e0792..855ec6a7 100644 --- a/src/js_realm.cpp +++ b/src/js_realm.cpp @@ -332,7 +332,7 @@ JSValueRef RealmDelete(JSContextRef ctx, JSObjectRef function, JSObjectRef thisO throw std::runtime_error("Can only delete objects within a transaction."); } - realm::TableRef table = ObjectStore::table_for_object_type(realm->read_group(), object->object_schema.name); + realm::TableRef table = ObjectStore::table_for_object_type(realm->read_group(), object->object_schema().name); table->move_last_over(object->row().get_index()); return NULL; diff --git a/src/object-store/object_accessor.hpp b/src/object-store/object_accessor.hpp index eed939e1..dc50240d 100644 --- a/src/object-store/object_accessor.hpp +++ b/src/object-store/object_accessor.hpp @@ -14,7 +14,7 @@ namespace realm { class Object { public: - Object(SharedRealm r, const ObjectSchema &s, Row o) : m_realm(r), object_schema(s), m_row(o) {} + Object(SharedRealm r, const ObjectSchema &s, Row o) : m_realm(r), m_object_schema(&s), m_row(o) {} // property getter/setter template @@ -27,12 +27,13 @@ namespace realm { template static inline Object create(ContextType ctx, SharedRealm realm, const ObjectSchema &object_schema, ValueType value, bool try_update); - const ObjectSchema &object_schema; SharedRealm realm() { return m_realm; } + const ObjectSchema &object_schema() { return *m_object_schema; } Row row() { return m_row; } private: SharedRealm m_realm; + const ObjectSchema *m_object_schema; Row m_row; template @@ -119,10 +120,10 @@ namespace realm { template inline void Object::set_property_value(ContextType ctx, std::string prop_name, ValueType value, bool try_update) { - const Property *prop = object_schema.property_for_name(prop_name); + const Property *prop = m_object_schema->property_for_name(prop_name); if (!prop) { - throw InvalidPropertyException(object_schema.name, prop_name, - "Setting invalid property '" + prop_name + "' on object '" + object_schema.name + "'."); + throw InvalidPropertyException(m_object_schema->name, prop_name, + "Setting invalid property '" + prop_name + "' on object '" + m_object_schema->name + "'."); } set_property_value_impl(ctx, *prop, value, try_update); }; @@ -130,10 +131,10 @@ namespace realm { template inline ValueType Object::get_property_value(ContextType ctx, std::string prop_name) { - const Property *prop = object_schema.property_for_name(prop_name); + const Property *prop = m_object_schema->property_for_name(prop_name); if (!prop) { - throw InvalidPropertyException(object_schema.name, prop_name, - "Getting invalid property '" + prop_name + "' on object '" + object_schema.name + "'."); + throw InvalidPropertyException(m_object_schema->name, prop_name, + "Getting invalid property '" + prop_name + "' on object '" + m_object_schema->name + "'."); } return get_property_value_impl(ctx, *prop); }; diff --git a/src/rpc.cpp b/src/rpc.cpp index 2b04702b..74d91229 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -220,7 +220,7 @@ json RPCServer::serialize_json_value(JSValueRef value) { return { {"type", RJSTypeGet(realm::PropertyTypeObject)}, {"id", store_object(js_object)}, - {"schema", serialize_object_schema(object->object_schema)} + {"schema", serialize_object_schema(object->object_schema())} }; } else if (JSValueIsObjectOfClass(m_context, value, RJSListClass())) { From 4c7d6d8b2fbd87aed95a9782752a4f7d03525637 Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Mon, 4 Jan 2016 16:27:37 -0800 Subject: [PATCH 38/41] remove unnecessary const cast --- src/object-store/shared_realm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/object-store/shared_realm.cpp b/src/object-store/shared_realm.cpp index c43f27db..7c48bf55 100644 --- a/src/object-store/shared_realm.cpp +++ b/src/object-store/shared_realm.cpp @@ -171,7 +171,7 @@ SharedRealm Realm::get_shared_realm(Config config) throw UnitializedRealmException("Can't open an un-initialized Realm without a Schema"); } target_schema->validate(); - ObjectStore::verify_schema(*realm->m_config.schema, const_cast(*target_schema), true); + ObjectStore::verify_schema(*realm->m_config.schema, *target_schema, true); realm->m_config.schema = std::move(target_schema); } else { From 3e4562574890e49c599dc0db19901986ece0bd08 Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Mon, 4 Jan 2016 16:37:07 -0800 Subject: [PATCH 39/41] pr fixes --- src/object-store/results.cpp | 4 ++-- src/object-store/shared_realm.cpp | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/object-store/results.cpp b/src/object-store/results.cpp index e8d4bfd2..437cfff7 100644 --- a/src/object-store/results.cpp +++ b/src/object-store/results.cpp @@ -324,9 +324,9 @@ Results Results::filter(Query&& q) const } Results::UnsupportedColumnTypeException::UnsupportedColumnTypeException(size_t column, const Table* table) -: column_index(column) +: std::runtime_error((std::string)"Operation not supported on '" + table->get_column_name(column).data() + "' columns") +, column_index(column) , column_name(table->get_column_name(column)) , column_type(table->get_column_type(column)) -, std::runtime_error((std::string)"Operation not supported on '" + table->get_column_name(column).data() + "' columns") { } diff --git a/src/object-store/shared_realm.cpp b/src/object-store/shared_realm.cpp index 7c48bf55..fd85e8f9 100644 --- a/src/object-store/shared_realm.cpp +++ b/src/object-store/shared_realm.cpp @@ -212,6 +212,9 @@ bool Realm::update_schema(std::unique_ptr schema, uint64_t version) old_config.read_only = true; old_config.schema = std::move(old_schema); + m_config.schema = std::move(schema); + m_config.schema_version = version; + auto migration_function = [&](Group*, Schema&) { SharedRealm old_realm(new Realm(old_config)); auto updated_realm = shared_from_this(); @@ -224,9 +227,8 @@ bool Realm::update_schema(std::unique_ptr schema, uint64_t version) // update and migrate begin_transaction(); bool changed = ObjectStore::update_realm_with_schema(read_group(), *old_config.schema, - version, const_cast(*schema), migration_function); - m_config.schema = std::move(schema); - m_config.schema_version = version; + version, *m_config.schema, + migration_function); commit_transaction(); return changed; } From 24be3ab82513a56df7f76899becdfcdb00e694f1 Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Mon, 4 Jan 2016 16:51:51 -0800 Subject: [PATCH 40/41] remove unnedded constructors/destructor --- src/object-store/parser/parser.cpp | 2 +- src/object-store/parser/parser.hpp | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/object-store/parser/parser.cpp b/src/object-store/parser/parser.cpp index 2753fbd8..7d425ee5 100644 --- a/src/object-store/parser/parser.cpp +++ b/src/object-store/parser/parser.cpp @@ -227,7 +227,7 @@ template<> struct action< or_op > template<> struct action< rule > { \ static void apply( const input & in, ParserState & state ) { \ DEBUG_PRINT_TOKEN(in.string()); \ - state.add_expression(Expression(type, in.string())); }}; + state.add_expression(Expression{type, in.string()}); }}; EXPRESSION_ACTION(dq_string_content, Expression::Type::String) EXPRESSION_ACTION(sq_string_content, Expression::Type::String) diff --git a/src/object-store/parser/parser.hpp b/src/object-store/parser/parser.hpp index 377eda5d..bad15381 100644 --- a/src/object-store/parser/parser.hpp +++ b/src/object-store/parser/parser.hpp @@ -30,8 +30,6 @@ namespace realm { { enum class Type { None, Number, String, KeyPath, Argument, True, False } type = Type::None; std::string s; - Expression() {} - Expression(Type t, std::string s) : type(t), s(s) {} }; struct Predicate @@ -63,7 +61,6 @@ namespace realm { { Operator op = Operator::None; Expression expr[2]; - ~Comparison() {} }; struct Compound From 518133e76900b9facae3f80193bb4bc9cfeac29c Mon Sep 17 00:00:00 2001 From: Ari Lazier Date: Mon, 4 Jan 2016 18:13:09 -0800 Subject: [PATCH 41/41] bdash pr fixes --- src/js_list.cpp | 8 +- src/js_object.cpp | 4 +- src/js_realm.cpp | 2 +- src/js_results.cpp | 6 +- src/object-store/list.hpp | 2 +- src/object-store/object_accessor.hpp | 8 +- src/object-store/parser/parser.hpp | 98 +++++++++++------------ src/object-store/parser/query_builder.cpp | 16 ++-- src/object-store/parser/query_builder.hpp | 86 ++++++++++---------- src/object-store/results.cpp | 4 +- src/object-store/results.hpp | 8 +- src/rpc.cpp | 6 +- 12 files changed, 124 insertions(+), 124 deletions(-) diff --git a/src/js_list.cpp b/src/js_list.cpp index a60334b8..9b01c15e 100644 --- a/src/js_list.cpp +++ b/src/js_list.cpp @@ -21,7 +21,7 @@ JSValueRef ListGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef pro return JSValueMakeNumber(ctx, size); } - return RJSObjectCreate(ctx, Object(list->realm(), list->object_schema(), list->get(RJSValidatedPositiveIndex(indexStr)))); + return RJSObjectCreate(ctx, Object(list->realm(), list->get_object_schema(), list->get(RJSValidatedPositiveIndex(indexStr)))); } catch (std::out_of_range &exp) { // getters for nonexistent properties in JS should always return undefined @@ -103,7 +103,7 @@ JSValueRef ListPop(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObjec return JSValueMakeUndefined(ctx); } size_t index = size - 1; - JSValueRef obj = RJSObjectCreate(ctx, Object(list->realm(), list->object_schema(), list->get(index))); + JSValueRef obj = RJSObjectCreate(ctx, Object(list->realm(), list->get_object_schema(), list->get(index))); list->remove(index); return obj; } @@ -140,7 +140,7 @@ JSValueRef ListShift(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObj list->verify_in_tranaction(); return JSValueMakeUndefined(ctx); } - JSValueRef obj = RJSObjectCreate(ctx, Object(list->realm(), list->object_schema(), list->get(0))); + JSValueRef obj = RJSObjectCreate(ctx, Object(list->realm(), list->get_object_schema(), list->get(0))); list->remove(0); return obj; } @@ -168,7 +168,7 @@ JSValueRef ListSplice(JSContextRef ctx, JSObjectRef function, JSObjectRef thisOb std::vector removedObjects(remove); for (size_t i = 0; i < remove; i++) { - removedObjects[i] = RJSObjectCreate(ctx, Object(list->realm(), list->object_schema(), list->get(index))); + removedObjects[i] = RJSObjectCreate(ctx, Object(list->realm(), list->get_object_schema(), list->get(index))); list->remove(index); } for (size_t i = 2; i < argumentCount; i++) { diff --git a/src/js_object.cpp b/src/js_object.cpp index 3a5217b8..0938b493 100644 --- a/src/js_object.cpp +++ b/src/js_object.cpp @@ -45,7 +45,7 @@ bool ObjectSetProperty(JSContextRef ctx, JSObjectRef jsObject, JSStringRef jsPro void ObjectPropertyNames(JSContextRef ctx, JSObjectRef jsObject, JSPropertyNameAccumulatorRef propertyNames) { Object *obj = RJSGetInternal(jsObject); - for (auto &prop : obj->object_schema().properties) { + for (auto &prop : obj->get_object_schema().properties) { JSStringRef propertyName = RJSStringForString(prop.name); JSPropertyNameAccumulatorAddName(propertyNames, propertyName); JSStringRelease(propertyName); @@ -58,7 +58,7 @@ JSClassRef RJSObjectClass() { } JSObjectRef RJSObjectCreate(JSContextRef ctx, Object object) { - JSValueRef prototype = RJSPrototypes(object.realm().get())[object.object_schema().name]; + JSValueRef prototype = RJSPrototypes(object.realm().get())[object.get_object_schema().name]; JSObjectRef jsObject = RJSWrapObject(ctx, RJSObjectClass(), new Object(object), prototype); return jsObject; } diff --git a/src/js_realm.cpp b/src/js_realm.cpp index 855ec6a7..bc72d7ae 100644 --- a/src/js_realm.cpp +++ b/src/js_realm.cpp @@ -332,7 +332,7 @@ JSValueRef RealmDelete(JSContextRef ctx, JSObjectRef function, JSObjectRef thisO throw std::runtime_error("Can only delete objects within a transaction."); } - realm::TableRef table = ObjectStore::table_for_object_type(realm->read_group(), object->object_schema().name); + realm::TableRef table = ObjectStore::table_for_object_type(realm->read_group(), object->get_object_schema().name); table->move_last_over(object->row().get_index()); return NULL; diff --git a/src/js_results.cpp b/src/js_results.cpp index 35132fe9..30b4ae14 100644 --- a/src/js_results.cpp +++ b/src/js_results.cpp @@ -23,7 +23,7 @@ JSValueRef ResultsGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef } return RJSObjectCreate(ctx, Object(results->get_realm(), - results->object_schema(), + results->get_object_schema(), results->get(RJSValidatedPositiveIndex(indexStr)))); } catch (std::out_of_range &exp) { @@ -76,9 +76,9 @@ JSValueRef SortByProperty(JSContextRef ctx, JSObjectRef function, JSObjectRef th Results *results = RJSGetInternal(thisObject); RJSValidateArgumentRange(argumentCount, 1, 2); std::string propName = RJSValidatedStringForValue(ctx, arguments[0]); - const Property *prop = results->object_schema().property_for_name(propName); + const Property *prop = results->get_object_schema().property_for_name(propName); if (!prop) { - throw std::runtime_error("Property '" + propName + "' does not exist on object type '" + results->object_schema().name + "'"); + throw std::runtime_error("Property '" + propName + "' does not exist on object type '" + results->get_object_schema().name + "'"); } bool ascending = true; diff --git a/src/object-store/list.hpp b/src/object-store/list.hpp index e7c6465c..0440f003 100644 --- a/src/object-store/list.hpp +++ b/src/object-store/list.hpp @@ -27,7 +27,7 @@ namespace realm { public: List(SharedRealm &r, const ObjectSchema &s, LinkViewRef l) : m_realm(r), m_object_schema(&s), m_link_view(l) {} - const ObjectSchema &object_schema() const { return *m_object_schema; } + const ObjectSchema &get_object_schema() const { return *m_object_schema; } SharedRealm realm() { return m_realm; } size_t size(); diff --git a/src/object-store/object_accessor.hpp b/src/object-store/object_accessor.hpp index dc50240d..bad38f9e 100644 --- a/src/object-store/object_accessor.hpp +++ b/src/object-store/object_accessor.hpp @@ -28,7 +28,7 @@ namespace realm { static inline Object create(ContextType ctx, SharedRealm realm, const ObjectSchema &object_schema, ValueType value, bool try_update); SharedRealm realm() { return m_realm; } - const ObjectSchema &object_schema() { return *m_object_schema; } + const ObjectSchema &get_object_schema() { return *m_object_schema; } Row row() { return m_row; } private: @@ -309,19 +309,19 @@ namespace realm { template void List::add(ContextType ctx, ValueType value) { - add(NativeAccessor::to_object_index(ctx, m_realm, value, object_schema().name, false)); + add(NativeAccessor::to_object_index(ctx, m_realm, value, get_object_schema().name, false)); } template void List::insert(ContextType ctx, ValueType value, size_t list_ndx) { - insert(list_ndx, NativeAccessor::to_object_index(ctx, m_realm, value, object_schema().name, false)); + insert(list_ndx, NativeAccessor::to_object_index(ctx, m_realm, value, get_object_schema().name, false)); } template void List::set(ContextType ctx, ValueType value, size_t list_ndx) { - set(list_ndx, NativeAccessor::to_object_index(ctx, m_realm, value, object_schema().name, false)); + set(list_ndx, NativeAccessor::to_object_index(ctx, m_realm, value, get_object_schema().name, false)); } } diff --git a/src/object-store/parser/parser.hpp b/src/object-store/parser/parser.hpp index bad15381..681847f0 100644 --- a/src/object-store/parser/parser.hpp +++ b/src/object-store/parser/parser.hpp @@ -23,64 +23,64 @@ #include namespace realm { - class Schema; +class Schema; - namespace parser { - struct Expression - { - enum class Type { None, Number, String, KeyPath, Argument, True, False } type = Type::None; - std::string s; - }; +namespace parser { +struct Expression +{ + enum class Type { None, Number, String, KeyPath, Argument, True, False } type = Type::None; + std::string s; +}; - struct Predicate - { - enum class Type - { - Comparison, - Or, - And, - True, - False - } type = Type::And; +struct Predicate +{ + enum class Type + { + Comparison, + Or, + And, + True, + False + } type = Type::And; - enum class Operator - { - None, - Equal, - NotEqual, - LessThan, - LessThanOrEqual, - GreaterThan, - GreaterThanOrEqual, - BeginsWith, - EndsWith, - Contains - }; + enum class Operator + { + None, + Equal, + NotEqual, + LessThan, + LessThanOrEqual, + GreaterThan, + GreaterThanOrEqual, + BeginsWith, + EndsWith, + Contains + }; - struct Comparison - { - Operator op = Operator::None; - Expression expr[2]; - }; + struct Comparison + { + Operator op = Operator::None; + Expression expr[2]; + }; - struct Compound - { - std::vector sub_predicates; - }; + struct Compound + { + std::vector sub_predicates; + }; - Comparison cmpr; - Compound cpnd; + Comparison cmpr; + Compound cpnd; - bool negate = false; + bool negate = false; - Predicate(Type t, bool n = false) : type(t), negate(n) {} - }; + Predicate(Type t, bool n = false) : type(t), negate(n) {} +}; - Predicate parse(const std::string &query); - - void analyzeGrammar(); - bool testGrammar(); - } +Predicate parse(const std::string &query); + +void analyzeGrammar(); +bool testGrammar(); +} } #endif // REALM_PARSER_HPP diff --git a/src/object-store/parser/query_builder.cpp b/src/object-store/parser/query_builder.cpp index 6f74f3b2..e3834ee1 100644 --- a/src/object-store/parser/query_builder.cpp +++ b/src/object-store/parser/query_builder.cpp @@ -230,7 +230,7 @@ void add_binary_constraint_to_query(realm::Query &query, void add_link_constraint_to_query(realm::Query &query, Predicate::Operator op, - PropertyExpression &prop_expr, + const PropertyExpression &prop_expr, size_t row_index) { precondition(prop_expr.indexes.empty(), "KeyPath queries not supported for object comparisons."); switch (op) { @@ -260,12 +260,12 @@ void add_link_constraint_to_query(realm::Query &query, } } -auto link_argument(PropertyExpression &propExpr, parser::Expression &argExpr, Arguments &args) +auto link_argument(const PropertyExpression &propExpr, const parser::Expression &argExpr, Arguments &args) { return args.object_index_for_argument(std::stoi(argExpr.s)); } -auto link_argument(parser::Expression &argExpr, PropertyExpression &propExpr, Arguments &args) +auto link_argument(const parser::Expression &argExpr, const PropertyExpression &propExpr, Arguments &args) { return args.object_index_for_argument(std::stoi(argExpr.s)); } @@ -376,7 +376,7 @@ auto value_of_type_for_query(TableGetter&& tables, Value&& value, Arguments &arg template void do_add_comparison_to_query(Query &query, const Schema &schema, const ObjectSchema &object_schema, Predicate::Operator op, - PropertyExpression &expr, A &lhs, B &rhs, Arguments &args) + const PropertyExpression &expr, A &lhs, B &rhs, Arguments &args) { auto type = expr.prop->type; switch (type) { @@ -418,9 +418,9 @@ void do_add_comparison_to_query(Query &query, const Schema &schema, const Object } } -void add_comparison_to_query(Query &query, Predicate &pred, Arguments &args, const Schema &schema, const std::string &type) +void add_comparison_to_query(Query &query, const Predicate &pred, Arguments &args, const Schema &schema, const std::string &type) { - Predicate::Comparison &cmpr = pred.cmpr; + const Predicate::Comparison &cmpr = pred.cmpr; auto t0 = cmpr.expr[0].type, t1 = cmpr.expr[1].type; auto object_schema = schema.find(type); if (t0 == parser::Expression::Type::KeyPath && t1 != parser::Expression::Type::KeyPath) { @@ -436,7 +436,7 @@ void add_comparison_to_query(Query &query, Predicate &pred, Arguments &args, con } } -void update_query_with_predicate(Query &query, Predicate &pred, Arguments &arguments, const Schema &schema, const std::string &type) +void update_query_with_predicate(Query &query, const Predicate &pred, Arguments &arguments, const Schema &schema, const std::string &type) { if (pred.negate) { query.Not(); @@ -484,7 +484,7 @@ void update_query_with_predicate(Query &query, Predicate &pred, Arguments &argum } } -void apply_predicate(Query &query, Predicate &predicate, Arguments &arguments, const Schema &schema, std::string objectType) +void apply_predicate(Query &query, const Predicate &predicate, Arguments &arguments, const Schema &schema, const std::string &objectType) { update_query_with_predicate(query, predicate, arguments, schema, objectType); diff --git a/src/object-store/parser/query_builder.hpp b/src/object-store/parser/query_builder.hpp index 713ef6ac..e5f519dc 100644 --- a/src/object-store/parser/query_builder.hpp +++ b/src/object-store/parser/query_builder.hpp @@ -24,57 +24,57 @@ #include "object_accessor.hpp" namespace realm { - class Query; - class Schema; +class Query; +class Schema; - namespace query_builder { - class Arguments; +namespace query_builder { +class Arguments; - void apply_predicate(Query &query, parser::Predicate &predicate, Arguments &arguments, const Schema &schema, std::string objectType); +void apply_predicate(Query &query, const parser::Predicate &predicate, Arguments &arguments, const Schema &schema, const std::string &objectType); - class Arguments - { - public: - virtual bool bool_for_argument(size_t argument_index) = 0; - virtual long long long_for_argument(size_t argument_index) = 0; - virtual float float_for_argument(size_t argument_index) = 0; - virtual double double_for_argument(size_t argument_index) = 0; - virtual std::string string_for_argument(size_t argument_index) = 0; - virtual std::string binary_for_argument(size_t argument_index) = 0; - virtual DateTime datetime_for_argument(size_t argument_index) = 0; - virtual size_t object_index_for_argument(size_t argument_index) = 0; - virtual bool is_argument_null(size_t argument_index) = 0; - }; +class Arguments +{ + public: + virtual bool bool_for_argument(size_t argument_index) = 0; + virtual long long long_for_argument(size_t argument_index) = 0; + virtual float float_for_argument(size_t argument_index) = 0; + virtual double double_for_argument(size_t argument_index) = 0; + virtual std::string string_for_argument(size_t argument_index) = 0; + virtual std::string binary_for_argument(size_t argument_index) = 0; + virtual DateTime datetime_for_argument(size_t argument_index) = 0; + virtual size_t object_index_for_argument(size_t argument_index) = 0; + virtual bool is_argument_null(size_t argument_index) = 0; +}; - template - class ArgumentConverter : public Arguments - { - public: - ArgumentConverter(ContextType context, std::vector arguments) : m_arguments(arguments), m_ctx(context) {}; +template +class ArgumentConverter : public Arguments +{ + public: + ArgumentConverter(ContextType context, std::vector arguments) : m_arguments(arguments), m_ctx(context) {}; - using Accessor = realm::NativeAccessor; - virtual bool bool_for_argument(size_t argument_index) { return Accessor::to_bool(m_ctx, argument_at(argument_index)); } - virtual long long long_for_argument(size_t argument_index) { return Accessor::to_long(m_ctx, argument_at(argument_index)); } - virtual float float_for_argument(size_t argument_index) { return Accessor::to_float(m_ctx, argument_at(argument_index)); } - virtual double double_for_argument(size_t argument_index) { return Accessor::to_double(m_ctx, argument_at(argument_index)); } - virtual std::string string_for_argument(size_t argument_index) { return Accessor::to_string(m_ctx, argument_at(argument_index)); } - virtual std::string binary_for_argument(size_t argument_index) { return Accessor::to_binary(m_ctx, argument_at(argument_index)); } - virtual DateTime datetime_for_argument(size_t argument_index) { return Accessor::to_datetime(m_ctx, argument_at(argument_index)); } - virtual size_t object_index_for_argument(size_t argument_index) { return Accessor::to_existing_object_index(m_ctx, argument_at(argument_index)); } - virtual bool is_argument_null(size_t argument_index) { return Accessor::is_null(m_ctx, argument_at(argument_index)); } + using Accessor = realm::NativeAccessor; + virtual bool bool_for_argument(size_t argument_index) { return Accessor::to_bool(m_ctx, argument_at(argument_index)); } + virtual long long long_for_argument(size_t argument_index) { return Accessor::to_long(m_ctx, argument_at(argument_index)); } + virtual float float_for_argument(size_t argument_index) { return Accessor::to_float(m_ctx, argument_at(argument_index)); } + virtual double double_for_argument(size_t argument_index) { return Accessor::to_double(m_ctx, argument_at(argument_index)); } + virtual std::string string_for_argument(size_t argument_index) { return Accessor::to_string(m_ctx, argument_at(argument_index)); } + virtual std::string binary_for_argument(size_t argument_index) { return Accessor::to_binary(m_ctx, argument_at(argument_index)); } + virtual DateTime datetime_for_argument(size_t argument_index) { return Accessor::to_datetime(m_ctx, argument_at(argument_index)); } + virtual size_t object_index_for_argument(size_t argument_index) { return Accessor::to_existing_object_index(m_ctx, argument_at(argument_index)); } + virtual bool is_argument_null(size_t argument_index) { return Accessor::is_null(m_ctx, argument_at(argument_index)); } - private: - std::vector m_arguments; - ContextType m_ctx; + private: + std::vector m_arguments; + ContextType m_ctx; - ValueType &argument_at(size_t index) { - if (index >= m_arguments.size()) { - throw std::out_of_range((std::string)"Argument index " + std::to_string(index) + " out of range 0.." + std::to_string(m_arguments.size()-1)); - } - return m_arguments[index]; - } - }; + ValueType &argument_at(size_t index) { + if (index >= m_arguments.size()) { + throw std::out_of_range((std::string)"Argument index " + std::to_string(index) + " out of range 0.." + std::to_string(m_arguments.size()-1)); + } + return m_arguments[index]; } +}; +} } #endif // REALM_QUERY_BUILDER_HPP diff --git a/src/object-store/results.cpp b/src/object-store/results.cpp index 437cfff7..0839f1f5 100644 --- a/src/object-store/results.cpp +++ b/src/object-store/results.cpp @@ -315,12 +315,12 @@ TableView Results::get_tableview() Results Results::sort(realm::SortOrder&& sort) const { - return Results(m_realm, object_schema(), get_query(), std::move(sort)); + return Results(m_realm, get_object_schema(), get_query(), std::move(sort)); } Results Results::filter(Query&& q) const { - return Results(m_realm, object_schema(), get_query().and_query(std::move(q)), get_sort()); + return Results(m_realm, get_object_schema(), get_query().and_query(std::move(q)), get_sort()); } Results::UnsupportedColumnTypeException::UnsupportedColumnTypeException(size_t column, const Table* table) diff --git a/src/object-store/results.hpp b/src/object-store/results.hpp index 42dbda8f..ec6b7bee 100644 --- a/src/object-store/results.hpp +++ b/src/object-store/results.hpp @@ -46,8 +46,8 @@ public: // or a wrapper around a query and a sort order which creates and updates // the tableview as needed Results() = default; - Results(SharedRealm r, const ObjectSchema &o, Table& table); - Results(SharedRealm r, const ObjectSchema &o, Query q, SortOrder s = {}); + Results(SharedRealm r, const ObjectSchema& o, Table& table); + Results(SharedRealm r, const ObjectSchema& o, Query q, SortOrder s = {}); // Results is copyable and moveable Results(Results const&) = default; @@ -59,7 +59,7 @@ public: SharedRealm get_realm() const { return m_realm; } // Object schema describing the vendored object type - const ObjectSchema &object_schema() const { return *m_object_schema; } + const ObjectSchema &get_object_schema() const { return *m_object_schema; } // Get a query which will match the same rows as is contained in this Results // Returned query will not be valid if the current mode is Empty @@ -72,7 +72,7 @@ public: TableView get_tableview(); // Get the object type which will be returned by get() - StringData get_object_type() const noexcept { return object_schema().name; } + StringData get_object_type() const noexcept { return get_object_schema().name; } // Get the size of this results // Can be either O(1) or O(N) depending on the state of things diff --git a/src/rpc.cpp b/src/rpc.cpp index 74d91229..ce270d5a 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -220,7 +220,7 @@ json RPCServer::serialize_json_value(JSValueRef value) { return { {"type", RJSTypeGet(realm::PropertyTypeObject)}, {"id", store_object(js_object)}, - {"schema", serialize_object_schema(object->object_schema())} + {"schema", serialize_object_schema(object->get_object_schema())} }; } else if (JSValueIsObjectOfClass(m_context, value, RJSListClass())) { @@ -229,7 +229,7 @@ json RPCServer::serialize_json_value(JSValueRef value) { {"type", RJSTypeGet(realm::PropertyTypeArray)}, {"id", store_object(js_object)}, {"size", list->size()}, - {"schema", serialize_object_schema(list->object_schema())} + {"schema", serialize_object_schema(list->get_object_schema())} }; } else if (JSValueIsObjectOfClass(m_context, value, RJSResultsClass())) { @@ -238,7 +238,7 @@ json RPCServer::serialize_json_value(JSValueRef value) { {"type", RealmObjectTypesResults}, {"id", store_object(js_object)}, {"size", results->size()}, - {"schema", serialize_object_schema(results->object_schema())} + {"schema", serialize_object_schema(results->get_object_schema())} }; } else if (RJSIsValueArray(m_context, value)) {