Merge pull request #339 from realm/al-indexed
Support for indexed properties
This commit is contained in:
commit
7e9df63777
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
```
|
```
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -65,10 +65,10 @@ public:
|
||||||
// Should only be called in test code, as continuing to use the previously
|
// Should only be called in test code, as continuing to use the previously
|
||||||
// cached instances will have odd results
|
// cached instances will have odd results
|
||||||
static void clear_cache();
|
static void clear_cache();
|
||||||
|
|
||||||
// Clears all caches on existing coordinators
|
// Clears all caches on existing coordinators
|
||||||
static void clear_all_caches();
|
static void clear_all_caches();
|
||||||
|
|
||||||
// Explicit constructor/destructor needed for the unique_ptrs to forward-declared types
|
// Explicit constructor/destructor needed for the unique_ptrs to forward-declared types
|
||||||
RealmCoordinator();
|
RealmCoordinator();
|
||||||
~RealmCoordinator();
|
~RealmCoordinator();
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
namespace realm {
|
namespace realm {
|
||||||
class Group;
|
class Group;
|
||||||
class Property;
|
struct Property;
|
||||||
|
|
||||||
class ObjectSchema {
|
class ObjectSchema {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -52,7 +52,7 @@ namespace realm {
|
||||||
// determines if a realm with the given old schema needs non-migration
|
// determines if a realm with the given old schema needs non-migration
|
||||||
// changes to make it compatible with the given target schema
|
// changes to make it compatible with the given target schema
|
||||||
static bool needs_update(Schema const& old_schema, Schema const& schema);
|
static bool needs_update(Schema const& old_schema, Schema const& schema);
|
||||||
|
|
||||||
// updates a Realm from old_schema to the given target schema, creating and updating tables as needed
|
// updates a Realm from old_schema to the given target schema, creating and updating tables as needed
|
||||||
// passed in target schema is updated with the correct column mapping
|
// passed in target schema is updated with the correct column mapping
|
||||||
// optionally runs migration function if schema is out of date
|
// optionally runs migration function if schema is out of date
|
||||||
|
|
|
@ -112,7 +112,7 @@ struct ParserState
|
||||||
{
|
{
|
||||||
return group_stack.back();
|
return group_stack.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
Predicate *last_predicate()
|
Predicate *last_predicate()
|
||||||
{
|
{
|
||||||
Predicate *pred = current_group();
|
Predicate *pred = current_group();
|
||||||
|
@ -121,12 +121,12 @@ struct ParserState
|
||||||
}
|
}
|
||||||
return pred;
|
return pred;
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_predicate_to_current_group(Predicate::Type type)
|
void add_predicate_to_current_group(Predicate::Type type)
|
||||||
{
|
{
|
||||||
current_group()->cpnd.sub_predicates.emplace_back(type, negate_next);
|
current_group()->cpnd.sub_predicates.emplace_back(type, negate_next);
|
||||||
negate_next = false;
|
negate_next = false;
|
||||||
|
|
||||||
if (current_group()->cpnd.sub_predicates.size() > 1) {
|
if (current_group()->cpnd.sub_predicates.size() > 1) {
|
||||||
if (next_type == Predicate::Type::Or) {
|
if (next_type == Predicate::Type::Or) {
|
||||||
apply_or();
|
apply_or();
|
||||||
|
@ -136,10 +136,10 @@ struct ParserState
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool negate_next = false;
|
bool negate_next = false;
|
||||||
Predicate::Type next_type = Predicate::Type::And;
|
Predicate::Type next_type = Predicate::Type::And;
|
||||||
|
|
||||||
void add_expression(Expression && exp)
|
void add_expression(Expression && exp)
|
||||||
{
|
{
|
||||||
Predicate *current = last_predicate();
|
Predicate *current = last_predicate();
|
||||||
|
@ -151,32 +151,32 @@ struct ParserState
|
||||||
last_predicate()->cmpr.expr[0] = std::move(exp);
|
last_predicate()->cmpr.expr[0] = std::move(exp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void apply_or()
|
void apply_or()
|
||||||
{
|
{
|
||||||
Predicate *group = current_group();
|
Predicate *group = current_group();
|
||||||
if (group->type == Predicate::Type::Or) {
|
if (group->type == Predicate::Type::Or) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert to OR
|
// convert to OR
|
||||||
group->type = Predicate::Type::Or;
|
group->type = Predicate::Type::Or;
|
||||||
if (group->cpnd.sub_predicates.size() > 2) {
|
if (group->cpnd.sub_predicates.size() > 2) {
|
||||||
// split the current group into an AND group ORed with the last subpredicate
|
// split the current group into an AND group ORed with the last subpredicate
|
||||||
Predicate new_sub(Predicate::Type::And);
|
Predicate new_sub(Predicate::Type::And);
|
||||||
new_sub.cpnd.sub_predicates = std::move(group->cpnd.sub_predicates);
|
new_sub.cpnd.sub_predicates = std::move(group->cpnd.sub_predicates);
|
||||||
|
|
||||||
group->cpnd.sub_predicates = { new_sub, std::move(new_sub.cpnd.sub_predicates.back()) };
|
group->cpnd.sub_predicates = { new_sub, std::move(new_sub.cpnd.sub_predicates.back()) };
|
||||||
group->cpnd.sub_predicates[0].cpnd.sub_predicates.pop_back();
|
group->cpnd.sub_predicates[0].cpnd.sub_predicates.pop_back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void apply_and()
|
void apply_and()
|
||||||
{
|
{
|
||||||
if (current_group()->type == Predicate::Type::And) {
|
if (current_group()->type == Predicate::Type::And) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto &sub_preds = current_group()->cpnd.sub_predicates;
|
auto &sub_preds = current_group()->cpnd.sub_predicates;
|
||||||
auto second_last = sub_preds.end() - 2;
|
auto second_last = sub_preds.end() - 2;
|
||||||
if (second_last->type == Predicate::Type::And && !second_last->negate) {
|
if (second_last->type == Predicate::Type::And && !second_last->negate) {
|
||||||
|
|
|
@ -462,7 +462,7 @@ void update_query_with_predicate(Query &query, const Predicate &pred, Arguments
|
||||||
if (pred.negate) {
|
if (pred.negate) {
|
||||||
query.Not();
|
query.Not();
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (pred.type) {
|
switch (pred.type) {
|
||||||
case Predicate::Type::And:
|
case Predicate::Type::And:
|
||||||
query.group();
|
query.group();
|
||||||
|
@ -474,7 +474,7 @@ void update_query_with_predicate(Query &query, const Predicate &pred, Arguments
|
||||||
}
|
}
|
||||||
query.end_group();
|
query.end_group();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Predicate::Type::Or:
|
case Predicate::Type::Or:
|
||||||
query.group();
|
query.group();
|
||||||
for (auto &sub : pred.cpnd.sub_predicates) {
|
for (auto &sub : pred.cpnd.sub_predicates) {
|
||||||
|
@ -486,7 +486,7 @@ void update_query_with_predicate(Query &query, const Predicate &pred, Arguments
|
||||||
}
|
}
|
||||||
query.end_group();
|
query.end_group();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Predicate::Type::Comparison: {
|
case Predicate::Type::Comparison: {
|
||||||
add_comparison_to_query(query, pred, arguments, schema, type);
|
add_comparison_to_query(query, pred, arguments, schema, type);
|
||||||
break;
|
break;
|
||||||
|
@ -494,11 +494,11 @@ void update_query_with_predicate(Query &query, const Predicate &pred, Arguments
|
||||||
case Predicate::Type::True:
|
case Predicate::Type::True:
|
||||||
query.and_query(std::unique_ptr<realm::Expression>(new TrueExpression));
|
query.and_query(std::unique_ptr<realm::Expression>(new TrueExpression));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Predicate::Type::False:
|
case Predicate::Type::False:
|
||||||
query.and_query(std::unique_ptr<realm::Expression>(new FalseExpression));
|
query.and_query(std::unique_ptr<realm::Expression>(new FalseExpression));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("Invalid predicate type");
|
throw std::runtime_error("Invalid predicate type");
|
||||||
}
|
}
|
||||||
|
@ -507,7 +507,7 @@ void update_query_with_predicate(Query &query, const Predicate &pred, Arguments
|
||||||
void apply_predicate(Query &query, const Predicate &predicate, Arguments &arguments, const Schema &schema, const 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);
|
update_query_with_predicate(query, predicate, arguments, schema, objectType);
|
||||||
|
|
||||||
// Test the constructed query in core
|
// Test the constructed query in core
|
||||||
std::string validateMessage = query.validate();
|
std::string validateMessage = query.validate();
|
||||||
precondition(validateMessage.empty(), validateMessage.c_str());
|
precondition(validateMessage.empty(), validateMessage.c_str());
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -83,10 +83,10 @@ public:
|
||||||
|
|
||||||
// Get the Realm
|
// Get the Realm
|
||||||
SharedRealm get_realm() const { return m_realm; }
|
SharedRealm get_realm() const { return m_realm; }
|
||||||
|
|
||||||
// Object schema describing the vendored object type
|
// Object schema describing the vendored object type
|
||||||
const ObjectSchema &get_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
|
// 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
|
// Returned query will not be valid if the current mode is Empty
|
||||||
Query get_query() const;
|
Query get_query() const;
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
@ -231,7 +229,7 @@ namespace realm {
|
||||||
public:
|
public:
|
||||||
UnitializedRealmException(std::string message) : std::runtime_error(message) {}
|
UnitializedRealmException(std::string message) : std::runtime_error(message) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class InvalidEncryptionKeyException : public std::runtime_error {
|
class InvalidEncryptionKeyException : public std::runtime_error {
|
||||||
public:
|
public:
|
||||||
InvalidEncryptionKeyException() : std::runtime_error("Encryption key must be 64 bytes.") {}
|
InvalidEncryptionKeyException() : std::runtime_error("Encryption key must be 64 bytes.") {}
|
||||||
|
|
|
@ -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]});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue