Merge pull request #339 from realm/al-indexed

Support for indexed properties
This commit is contained in:
Ari Lazier 2016-03-21 13:27:23 -07:00
commit 7e9df63777
26 changed files with 150 additions and 86 deletions

View File

@ -8,6 +8,7 @@
* Add common Array methods to List and Results * Add common Array methods to List and Results
* Accept constructor in create() and objects() methods * Accept constructor in create() and objects() methods
* Support relative paths when opening realms * Support relative paths when opening realms
* Support for indexed bool, string, date, and int properties
### Bugfixes ### Bugfixes
* Fix for crash on Android when initializing the Realm module * Fix for crash on Android when initializing the Realm module

View File

@ -150,6 +150,8 @@ Realm.defaultPath;
* @property {any} [default] - The default value for this property on creation when not * @property {any} [default] - The default value for this property on creation when not
* otherwise specified. * otherwise specified.
* @property {boolean} [optional] - Signals if this property may be assigned `null` or `undefined`. * @property {boolean} [optional] - Signals if this property may be assigned `null` or `undefined`.
* @property {boolean} [indexed] - Signals if this property should be indexed. Only supported for
* `"string"`, `"int"`, and `"bool"` properties.
*/ */
/** /**

View File

@ -41,6 +41,7 @@
"scripts": { "scripts": {
"get-version": "echo $npm_package_version", "get-version": "echo $npm_package_version",
"set-version": "scripts/set-version.sh", "set-version": "scripts/set-version.sh",
"get-core-version": "scripts/download-core.sh --version",
"jsdoc": "rm -rf docs/output && jsdoc -c docs/conf.json", "jsdoc": "rm -rf docs/output && jsdoc -c docs/conf.json",
"lint": "eslint", "lint": "eslint",
"test": "scripts/test.sh", "test": "scripts/test.sh",

View File

@ -27,8 +27,8 @@ import org.apache.tools.ant.filters.ReplaceTokens
// We download various C++ open-source dependencies into downloads. // We download various C++ open-source dependencies into downloads.
// We then copy both the downloaded code and our custom makefiles and headers into third-party-ndk. // We then copy both the downloaded code and our custom makefiles and headers into third-party-ndk.
// After that we build native code from src/main/jni with module path pointing at third-party-ndk. // After that we build native code from src/main/jni with module path pointing at third-party-ndk.
ext.coreVersion = '0.96.2'
ext.coreVersion = "npm --silent run get-core-version".execute().text.trim()
def currentVersion = "npm --silent run get-version".execute().text.trim() def currentVersion = "npm --silent run get-version".execute().text.trim()
def downloadsDir = new File("$projectDir/downloads") def downloadsDir = new File("$projectDir/downloads")
def jscDownloadDir = new File("$projectDir/src/main/jni/jsc") def jscDownloadDir = new File("$projectDir/src/main/jni/jsc")

View File

@ -3,7 +3,7 @@
set -e set -e
set -o pipefail set -o pipefail
: ${REALM_CORE_VERSION:=0.96.2} # set to "current" to always use the current build : ${REALM_CORE_VERSION:=0.97.1} # set to "current" to always use the current build
# Start current working directory at the root of the project. # Start current working directory at the root of the project.
cd "$(dirname "$0")/.." cd "$(dirname "$0")/.."
@ -46,6 +46,11 @@ check_release_notes() {
grep -Fqi "$REALM_CORE_VERSION RELEASE NOTES" "$@" grep -Fqi "$REALM_CORE_VERSION RELEASE NOTES" "$@"
} }
if [[ $1 = "--version" ]]; then
echo $REALM_CORE_VERSION
exit 0
fi
if [ ! -e core ]; then if [ ! -e core ]; then
download_core download_core
elif [ -d core -a -d ../realm-core -a ! -L core ]; then elif [ -d core -a -d ../realm-core -a ! -L core ]; then

View File

@ -2,7 +2,8 @@
set -e set -e
set -o pipefail set -o pipefail
export REALM_CORE_VERSION=$(./scripts/download-core.sh --version)
echo "Core Version: $REALM_CORE_VERSION"
cd "$(dirname "$0")/.." cd "$(dirname "$0")/.."
if [ -n "$REALM_BUILD_ANDROID" ]; then if [ -n "$REALM_BUILD_ANDROID" ]; then

View File

@ -47,6 +47,7 @@ JSObjectRef RJSSchemaCreate(JSContextRef ctx, Schema &schema) {
static inline Property RJSParseProperty(JSContextRef ctx, JSValueRef propertyAttributes, std::string propertyName, ObjectDefaults &objectDefaults) { static inline Property RJSParseProperty(JSContextRef ctx, JSValueRef propertyAttributes, std::string propertyName, ObjectDefaults &objectDefaults) {
static JSStringRef defaultString = JSStringCreateWithUTF8CString("default"); static JSStringRef defaultString = JSStringCreateWithUTF8CString("default");
static JSStringRef indexedString = JSStringCreateWithUTF8CString("indexed");
static JSStringRef typeString = JSStringCreateWithUTF8CString("type"); static JSStringRef typeString = JSStringCreateWithUTF8CString("type");
static JSStringRef objectTypeString = JSStringCreateWithUTF8CString("objectType"); static JSStringRef objectTypeString = JSStringCreateWithUTF8CString("objectType");
static JSStringRef optionalString = JSStringCreateWithUTF8CString("optional"); static JSStringRef optionalString = JSStringCreateWithUTF8CString("optional");
@ -123,6 +124,11 @@ static inline Property RJSParseProperty(JSContextRef ctx, JSValueRef propertyAtt
JSValueProtect(ctx, defaultValue); JSValueProtect(ctx, defaultValue);
objectDefaults.emplace(prop.name, defaultValue); objectDefaults.emplace(prop.name, defaultValue);
} }
JSValueRef indexedValue = RJSValidatedPropertyValue(ctx, propertyObject, indexedString);
if (!JSValueIsUndefined(ctx, indexedValue)) {
prop.is_indexed = JSValueToBoolean(ctx, indexedValue);
}
} }
return prop; return prop;

View File

@ -7,7 +7,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake")
include(CompilerFlags) include(CompilerFlags)
include(RealmCore) include(RealmCore)
set(REALM_CORE_VERSION "0.96.2" CACHE STRING "") set(REALM_CORE_VERSION "0.97.0" CACHE STRING "")
use_realm_core(${REALM_CORE_VERSION}) use_realm_core(${REALM_CORE_VERSION})
include_directories(${REALM_CORE_INCLUDE_DIR} src external/pegtl) include_directories(${REALM_CORE_INCLUDE_DIR} src external/pegtl)

View File

@ -11,7 +11,7 @@ Cross-platform code used accross bindings. Binding developers can choose to use
The object store's build system currently only suports building for OS X. The object store itself can build for all Apple The object store's build system currently only suports building for OS X. The object store itself can build for all Apple
platforms when integrated into a binding. platforms when integrated into a binding.
1. Install CMake. You can download an installer for OS X from the [CMake download page], or install via [Homebrew](http://brew.sh): 1. Install CMake. You can download an installer for OS X from the [CMake download page](https://cmake.org/download/), or install via [Homebrew](http://brew.sh):
``` ```
brew install cmake brew install cmake
``` ```

View File

@ -159,7 +159,7 @@ void AsyncQuery::run()
if (m_initial_run_complete) { if (m_initial_run_complete) {
// Make an empty tableview from the query to get the table version, since // Make an empty tableview from the query to get the table version, since
// Query doesn't expose it // Query doesn't expose it
if (m_query->find_all(0, 0, 0).outside_version() == m_handed_over_table_version) { if (m_query->find_all(0, 0, 0).sync_if_needed() == m_handed_over_table_version) {
return; return;
} }
} }
@ -181,7 +181,7 @@ void AsyncQuery::prepare_handover()
REALM_ASSERT(m_tv.is_in_sync()); REALM_ASSERT(m_tv.is_in_sync());
m_initial_run_complete = true; m_initial_run_complete = true;
m_handed_over_table_version = m_tv.outside_version(); m_handed_over_table_version = m_tv.sync_if_needed();
m_tv_handover = m_sg->export_for_handover(m_tv, MutableSourcePayload::Move); m_tv_handover = m_sg->export_for_handover(m_tv, MutableSourcePayload::Move);
// detach the TableView as we won't need it again and keeping it around // detach the TableView as we won't need it again and keeping it around
@ -231,7 +231,7 @@ bool AsyncQuery::deliver(SharedGroup& sg, std::exception_ptr err)
m_tv_handover->version = m_sg_version; m_tv_handover->version = m_sg_version;
Results::Internal::set_table_view(*m_target_results, Results::Internal::set_table_view(*m_target_results,
std::move(*sg.import_from_handover(std::move(m_tv_handover)))); std::move(*sg.import_from_handover(std::move(m_tv_handover))));
m_delievered_table_version = m_handed_over_table_version; m_delivered_table_version = m_handed_over_table_version;
} }
REALM_ASSERT(!m_tv_handover); REALM_ASSERT(!m_tv_handover);
@ -259,8 +259,8 @@ std::function<void (std::exception_ptr)> AsyncQuery::next_callback()
std::lock_guard<std::mutex> callback_lock(m_callback_mutex); std::lock_guard<std::mutex> callback_lock(m_callback_mutex);
for (++m_callback_index; m_callback_index < m_callbacks.size(); ++m_callback_index) { for (++m_callback_index; m_callback_index < m_callbacks.size(); ++m_callback_index) {
auto& callback = m_callbacks[m_callback_index]; auto& callback = m_callbacks[m_callback_index];
if (m_error || callback.delivered_version != m_delievered_table_version) { if (m_error || callback.delivered_version != m_delivered_table_version) {
callback.delivered_version = m_delievered_table_version; callback.delivered_version = m_delivered_table_version;
return callback.fn; return callback.fn;
} }
} }

View File

@ -97,7 +97,7 @@ private:
SharedGroup* m_sg = nullptr; SharedGroup* m_sg = nullptr;
uint_fast64_t m_handed_over_table_version = -1; uint_fast64_t m_handed_over_table_version = -1;
uint_fast64_t m_delievered_table_version = -1; uint_fast64_t m_delivered_table_version = -1;
// Iteration variable for looping over callbacks // Iteration variable for looping over callbacks
// remove_callback() updates this when needed // remove_callback() updates this when needed

View File

@ -21,7 +21,7 @@
#include <future> #include <future>
namespace realm { namespace realm {
class ClientHistory; class Replication;
namespace _impl { namespace _impl {
class RealmCoordinator; class RealmCoordinator;
@ -38,7 +38,7 @@ private:
RealmCoordinator& m_parent; RealmCoordinator& m_parent;
// A shared group used to listen for changes // A shared group used to listen for changes
std::unique_ptr<ClientHistory> m_history; std::unique_ptr<Replication> m_history;
SharedGroup m_sg; SharedGroup m_sg;
// The listener thread // The listener thread

View File

@ -385,7 +385,7 @@ void RealmCoordinator::move_new_queries_to_main()
void RealmCoordinator::advance_helper_shared_group_to_latest() void RealmCoordinator::advance_helper_shared_group_to_latest()
{ {
if (m_new_queries.empty()) { if (m_new_queries.empty()) {
LangBindHelper::advance_read(*m_query_sg, *m_query_history); LangBindHelper::advance_read(*m_query_sg);
return; return;
} }
@ -397,14 +397,13 @@ void RealmCoordinator::advance_helper_shared_group_to_latest()
// Import all newly added queries to our helper SG // Import all newly added queries to our helper SG
for (auto& query : m_new_queries) { for (auto& query : m_new_queries) {
LangBindHelper::advance_read(*m_advancer_sg, *m_advancer_history, query->version()); LangBindHelper::advance_read(*m_advancer_sg, query->version());
query->attach_to(*m_advancer_sg); query->attach_to(*m_advancer_sg);
} }
// Advance both SGs to the newest version // Advance both SGs to the newest version
LangBindHelper::advance_read(*m_advancer_sg, *m_advancer_history); LangBindHelper::advance_read(*m_advancer_sg);
LangBindHelper::advance_read(*m_query_sg, *m_query_history, LangBindHelper::advance_read(*m_query_sg, m_advancer_sg->get_version_of_current_transaction());
m_advancer_sg->get_version_of_current_transaction());
// Transfer all new queries over to the main SG // Transfer all new queries over to the main SG
for (auto& query : m_new_queries) { for (auto& query : m_new_queries) {
@ -421,7 +420,6 @@ void RealmCoordinator::advance_to_ready(Realm& realm)
decltype(m_queries) queries; decltype(m_queries) queries;
auto& sg = Realm::Internal::get_shared_group(realm); auto& sg = Realm::Internal::get_shared_group(realm);
auto& history = Realm::Internal::get_history(realm);
auto get_query_version = [&] { auto get_query_version = [&] {
for (auto& query : m_queries) { for (auto& query : m_queries) {
@ -440,8 +438,8 @@ void RealmCoordinator::advance_to_ready(Realm& realm)
} }
// no async queries; just advance to latest // no async queries; just advance to latest
if (version.version == 0) { if (version.version == std::numeric_limits<uint_fast64_t>::max()) {
transaction::advance(sg, history, realm.m_binding_context.get()); transaction::advance(sg, realm.m_binding_context.get());
return; return;
} }
@ -453,14 +451,14 @@ void RealmCoordinator::advance_to_ready(Realm& realm)
while (true) { while (true) {
// Advance to the ready version without holding any locks because it // Advance to the ready version without holding any locks because it
// may end up calling user code (in did_change() notifications) // may end up calling user code (in did_change() notifications)
transaction::advance(sg, history, realm.m_binding_context.get(), version); transaction::advance(sg, realm.m_binding_context.get(), version);
// Reacquire the lock and recheck the query version, as the queries may // Reacquire the lock and recheck the query version, as the queries may
// have advanced to a later version while we didn't hold the lock. If // have advanced to a later version while we didn't hold the lock. If
// so, we need to release the lock and re-advance // so, we need to release the lock and re-advance
std::lock_guard<std::mutex> lock(m_query_mutex); std::lock_guard<std::mutex> lock(m_query_mutex);
version = get_query_version(); version = get_query_version();
if (version.version == 0) if (version.version == std::numeric_limits<uint_fast64_t>::max())
return; return;
if (version != sg.get_version_of_current_transaction()) if (version != sg.get_version_of_current_transaction())
continue; continue;

View File

@ -25,7 +25,7 @@
namespace realm { namespace realm {
class AsyncQueryCallback; class AsyncQueryCallback;
class ClientHistory; class Replication;
class Results; class Results;
class Schema; class Schema;
class SharedGroup; class SharedGroup;
@ -102,13 +102,13 @@ private:
// SharedGroup used for actually running async queries // SharedGroup used for actually running async queries
// Will have a read transaction iff m_queries is non-empty // Will have a read transaction iff m_queries is non-empty
std::unique_ptr<ClientHistory> m_query_history; std::unique_ptr<Replication> m_query_history;
std::unique_ptr<SharedGroup> m_query_sg; std::unique_ptr<SharedGroup> m_query_sg;
// SharedGroup used to advance queries in m_new_queries to the main shared // SharedGroup used to advance queries in m_new_queries to the main shared
// group's transaction version // group's transaction version
// Will have a read transaction iff m_new_queries is non-empty // Will have a read transaction iff m_new_queries is non-empty
std::unique_ptr<ClientHistory> m_advancer_history; std::unique_ptr<Replication> m_advancer_history;
std::unique_ptr<SharedGroup> m_advancer_sg; std::unique_ptr<SharedGroup> m_advancer_sg;
std::exception_ptr m_async_error; std::exception_ptr m_async_error;

View File

@ -432,23 +432,21 @@ public:
namespace realm { namespace realm {
namespace _impl { namespace _impl {
namespace transaction { namespace transaction {
void advance(SharedGroup& sg, ClientHistory& history, BindingContext* context, void advance(SharedGroup& sg, BindingContext* context, SharedGroup::VersionID version)
SharedGroup::VersionID version)
{ {
TransactLogObserver(context, sg, [&](auto&&... args) { TransactLogObserver(context, sg, [&](auto&&... args) {
LangBindHelper::advance_read(sg, history, std::move(args)...); LangBindHelper::advance_read(sg, std::move(args)...);
}, true); }, true);
} }
void begin(SharedGroup& sg, ClientHistory& history, BindingContext* context, void begin(SharedGroup& sg, BindingContext* context, bool validate_schema_changes)
bool validate_schema_changes)
{ {
TransactLogObserver(context, sg, [&](auto&&... args) { TransactLogObserver(context, sg, [&](auto&&... args) {
LangBindHelper::promote_to_write(sg, history, std::move(args)...); LangBindHelper::promote_to_write(sg, std::move(args)...);
}, validate_schema_changes); }, validate_schema_changes);
} }
void commit(SharedGroup& sg, ClientHistory&, BindingContext* context) void commit(SharedGroup& sg, BindingContext* context)
{ {
LangBindHelper::commit_and_continue_as_read(sg); LangBindHelper::commit_and_continue_as_read(sg);
@ -457,10 +455,10 @@ void commit(SharedGroup& sg, ClientHistory&, BindingContext* context)
} }
} }
void cancel(SharedGroup& sg, ClientHistory& history, BindingContext* context) void cancel(SharedGroup& sg, BindingContext* context)
{ {
TransactLogObserver(context, sg, [&](auto&&... args) { TransactLogObserver(context, sg, [&](auto&&... args) {
LangBindHelper::rollback_and_continue_as_read(sg, history, std::move(args)...); LangBindHelper::rollback_and_continue_as_read(sg, std::move(args)...);
}, false); }, false);
} }

View File

@ -24,27 +24,26 @@
namespace realm { namespace realm {
class BindingContext; class BindingContext;
class SharedGroup; class SharedGroup;
class ClientHistory;
namespace _impl { namespace _impl {
namespace transaction { namespace transaction {
// Advance the read transaction version, with change notifications sent to delegate // Advance the read transaction version, with change notifications sent to delegate
// Must not be called from within a write transaction. // Must not be called from within a write transaction.
void advance(SharedGroup& sg, ClientHistory& history, BindingContext* binding_context, void advance(SharedGroup& sg, BindingContext* binding_context,
SharedGroup::VersionID version=SharedGroup::VersionID{}); SharedGroup::VersionID version=SharedGroup::VersionID{});
// Begin a write transaction // Begin a write transaction
// If the read transaction version is not up to date, will first advance to the // If the read transaction version is not up to date, will first advance to the
// most recent read transaction and sent notifications to delegate // most recent read transaction and sent notifications to delegate
void begin(SharedGroup& sg, ClientHistory& history, BindingContext* binding_context, void begin(SharedGroup& sg, BindingContext* binding_context,
bool validate_schema_changes=true); bool validate_schema_changes=true);
// Commit a write transaction // Commit a write transaction
void commit(SharedGroup& sg, ClientHistory& history, BindingContext* binding_context); void commit(SharedGroup& sg, BindingContext* binding_context);
// Cancel a write transaction and roll back all changes, with change notifications // Cancel a write transaction and roll back all changes, with change notifications
// for reverting to the old values sent to delegate // for reverting to the old values sent to delegate
void cancel(SharedGroup& sg, ClientHistory& history, BindingContext* binding_context); void cancel(SharedGroup& sg, BindingContext* binding_context);
} // namespace transaction } // namespace transaction
} // namespace _impl } // namespace _impl
} // namespace realm } // namespace realm

View File

@ -26,7 +26,7 @@
namespace realm { namespace realm {
class Group; class Group;
class Property; struct Property;
class ObjectSchema { class ObjectSchema {
public: public:

View File

@ -55,6 +55,7 @@ namespace realm {
size_t table_column = -1; size_t table_column = -1;
bool requires_index() const { return is_primary || is_indexed; } bool requires_index() const { return is_primary || is_indexed; }
bool is_indexable() const { return type == PropertyTypeInt || type == PropertyTypeBool || type == PropertyTypeString || type == PropertyTypeDate; }
}; };
static inline const char *string_for_property_type(PropertyType type) { static inline const char *string_for_property_type(PropertyType type) {

View File

@ -89,7 +89,7 @@ void Schema::validate() const
// check indexable // check indexable
if (prop.is_indexed) { if (prop.is_indexed) {
if (prop.type != PropertyTypeString && prop.type != PropertyTypeInt) { if (!prop.is_indexable()) {
exceptions.emplace_back(PropertyTypeNotIndexableException(object.name, prop)); exceptions.emplace_back(PropertyTypeNotIndexableException(object.name, prop));
} }
} }

View File

@ -72,7 +72,7 @@ Realm::Realm(Config config)
} }
void Realm::open_with_config(const Config& config, void Realm::open_with_config(const Config& config,
std::unique_ptr<ClientHistory>& history, std::unique_ptr<Replication>& history,
std::unique_ptr<SharedGroup>& shared_group, std::unique_ptr<SharedGroup>& shared_group,
std::unique_ptr<Group>& read_only_group) std::unique_ptr<Group>& read_only_group)
{ {
@ -211,9 +211,8 @@ void Realm::update_schema(std::unique_ptr<Schema> schema, uint64_t version)
} }
read_group(); read_group();
transaction::begin(*m_shared_group, *m_history, m_binding_context.get(), transaction::begin(*m_shared_group, m_binding_context.get(),
/* error on schema changes */ false); /* error on schema changes */ false);
m_in_transaction = true;
struct WriteTransactionGuard { struct WriteTransactionGuard {
Realm& realm; Realm& realm;
@ -289,20 +288,27 @@ void Realm::verify_in_write() const
} }
} }
bool Realm::is_in_transaction() const noexcept
{
if (!m_shared_group) {
return false;
}
return m_shared_group->get_transact_stage() == SharedGroup::transact_Writing;
}
void Realm::begin_transaction() void Realm::begin_transaction()
{ {
check_read_write(this); check_read_write(this);
verify_thread(); verify_thread();
if (m_in_transaction) { if (is_in_transaction()) {
throw InvalidTransactionException("The Realm is already in a write transaction"); throw InvalidTransactionException("The Realm is already in a write transaction");
} }
// make sure we have a read transaction // make sure we have a read transaction
read_group(); read_group();
transaction::begin(*m_shared_group, *m_history, m_binding_context.get()); transaction::begin(*m_shared_group, m_binding_context.get());
m_in_transaction = true;
} }
void Realm::commit_transaction() void Realm::commit_transaction()
@ -310,12 +316,11 @@ void Realm::commit_transaction()
check_read_write(this); check_read_write(this);
verify_thread(); verify_thread();
if (!m_in_transaction) { if (!is_in_transaction()) {
throw InvalidTransactionException("Can't commit a non-existing write transaction"); throw InvalidTransactionException("Can't commit a non-existing write transaction");
} }
m_in_transaction = false; transaction::commit(*m_shared_group, m_binding_context.get());
transaction::commit(*m_shared_group, *m_history, m_binding_context.get());
m_coordinator->send_commit_notifications(); m_coordinator->send_commit_notifications();
} }
@ -324,18 +329,19 @@ void Realm::cancel_transaction()
check_read_write(this); check_read_write(this);
verify_thread(); verify_thread();
if (!m_in_transaction) { if (!is_in_transaction()) {
throw InvalidTransactionException("Can't cancel a non-existing write transaction"); throw InvalidTransactionException("Can't cancel a non-existing write transaction");
} }
m_in_transaction = false; transaction::cancel(*m_shared_group, m_binding_context.get());
transaction::cancel(*m_shared_group, *m_history, m_binding_context.get());
} }
void Realm::invalidate() void Realm::invalidate()
{ {
verify_thread(); verify_thread();
if (m_in_transaction) { check_read_write(this);
if (is_in_transaction()) {
cancel_transaction(); cancel_transaction();
} }
if (!m_group) { if (!m_group) {
@ -353,7 +359,7 @@ bool Realm::compact()
if (m_config.read_only) { if (m_config.read_only) {
throw InvalidTransactionException("Can't compact a read-only Realm"); throw InvalidTransactionException("Can't compact a read-only Realm");
} }
if (m_in_transaction) { if (is_in_transaction()) {
throw InvalidTransactionException("Can't compact a Realm within a write transaction"); throw InvalidTransactionException("Can't compact a Realm within a write transaction");
} }
@ -395,7 +401,7 @@ bool Realm::refresh()
check_read_write(this); check_read_write(this);
// can't be any new changes if we're in a write transaction // can't be any new changes if we're in a write transaction
if (m_in_transaction) { if (is_in_transaction()) {
return false; return false;
} }
@ -405,7 +411,7 @@ bool Realm::refresh()
} }
if (m_group) { if (m_group) {
transaction::advance(*m_shared_group, *m_history, m_binding_context.get()); transaction::advance(*m_shared_group, m_binding_context.get());
m_coordinator->process_available_async(*this); m_coordinator->process_available_async(*this);
} }
else { else {

View File

@ -32,7 +32,7 @@
namespace realm { namespace realm {
class BindingContext; class BindingContext;
class ClientHistory; class Replication;
class Group; class Group;
class Realm; class Realm;
class RealmDelegate; class RealmDelegate;
@ -114,7 +114,7 @@ namespace realm {
void begin_transaction(); void begin_transaction();
void commit_transaction(); void commit_transaction();
void cancel_transaction(); void cancel_transaction();
bool is_in_transaction() const { return m_in_transaction; } bool is_in_transaction() const noexcept;
bool is_in_read_transaction() const { return !!m_group; } bool is_in_read_transaction() const { return !!m_group; }
bool refresh(); bool refresh();
@ -149,7 +149,6 @@ namespace realm {
// AsyncQuery needs access to the SharedGroup to be able to call the // AsyncQuery needs access to the SharedGroup to be able to call the
// handover functions, which are not very wrappable // handover functions, which are not very wrappable
static SharedGroup& get_shared_group(Realm& realm) { return *realm.m_shared_group; } static SharedGroup& get_shared_group(Realm& realm) { return *realm.m_shared_group; }
static ClientHistory& get_history(Realm& realm) { return *realm.m_history; }
// AsyncQuery needs to be able to access the owning coordinator to // AsyncQuery needs to be able to access the owning coordinator to
// wake up the worker thread when a callback is added, and // wake up the worker thread when a callback is added, and
@ -158,17 +157,16 @@ namespace realm {
}; };
static void open_with_config(const Config& config, static void open_with_config(const Config& config,
std::unique_ptr<ClientHistory>& history, std::unique_ptr<Replication>& history,
std::unique_ptr<SharedGroup>& shared_group, std::unique_ptr<SharedGroup>& shared_group,
std::unique_ptr<Group>& read_only_group); std::unique_ptr<Group>& read_only_group);
private: private:
Config m_config; Config m_config;
std::thread::id m_thread_id = std::this_thread::get_id(); std::thread::id m_thread_id = std::this_thread::get_id();
bool m_in_transaction = false;
bool m_auto_refresh = true; bool m_auto_refresh = true;
std::unique_ptr<ClientHistory> m_history; std::unique_ptr<Replication> m_history;
std::unique_ptr<SharedGroup> m_shared_group; std::unique_ptr<SharedGroup> m_shared_group;
std::unique_ptr<Group> m_read_only_group; std::unique_ptr<Group> m_read_only_group;

View File

@ -258,6 +258,54 @@ module.exports = BaseTest.extend({
}); });
}, },
testRealmWithIndexedProperties: function() {
var IndexedTypes = {
name: 'IndexedTypesObject',
properties: {
boolCol: {type: 'bool', indexed: true},
intCol: {type: 'int', indexed: true},
stringCol: {type: 'string', indexed: true},
dateCol: {type: 'date', indexed: true},
}
};
var realm = new Realm({schema: [IndexedTypes]});
realm.write(function() {
realm.create('IndexedTypesObject', {boolCol: true, intCol: 1, stringCol: '1', dateCol: new Date(1)});
});
var NotIndexed = {
name: 'NotIndexedObject',
properties: {
floatCol: {type: 'float', indexed: false}
}
};
new Realm({schema: [NotIndexed], path: '1'});
TestCase.assertThrows(function() {
IndexedTypes.properties = { floatCol: {type: 'float', indexed: true} }
new Realm({schema: [IndexedTypes], path: '2'});
});
TestCase.assertThrows(function() {
IndexedTypes.properties = { doubleCol: {type: 'double', indexed: true} }
new Realm({schema: [IndexedTypes], path: '3'});
});
TestCase.assertThrows(function() {
IndexedTypes.properties = { dataCol: {type: 'data', indexed: true} }
new Realm({schema: [IndexedTypes], path: '4'});
});
// primary key
IndexedTypes.primaryKey = 'boolCol';
IndexedTypes.properties = { boolCol: {type: 'bool', indexed: true} }
// Test this doesn't throw
new Realm({schema: [IndexedTypes], path: '5'});
},
testRealmCreateWithDefaults: function() { testRealmCreateWithDefaults: function() {
var realm = new Realm({schema: [schemas.DefaultValues, schemas.TestObject]}); var realm = new Realm({schema: [schemas.DefaultValues, schemas.TestObject]});