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
* Accept constructor in create() and objects() methods
* Support relative paths when opening realms
* Support for indexed bool, string, date, and int properties
### Bugfixes
* 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
* otherwise specified.
* @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": {
"get-version": "echo $npm_package_version",
"set-version": "scripts/set-version.sh",
"get-core-version": "scripts/download-core.sh --version",
"jsdoc": "rm -rf docs/output && jsdoc -c docs/conf.json",
"lint": "eslint",
"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 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.
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 downloadsDir = new File("$projectDir/downloads")
def jscDownloadDir = new File("$projectDir/src/main/jni/jsc")

View File

@ -3,7 +3,7 @@
set -e
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.
cd "$(dirname "$0")/.."
@ -46,6 +46,11 @@ check_release_notes() {
grep -Fqi "$REALM_CORE_VERSION RELEASE NOTES" "$@"
}
if [[ $1 = "--version" ]]; then
echo $REALM_CORE_VERSION
exit 0
fi
if [ ! -e core ]; then
download_core
elif [ -d core -a -d ../realm-core -a ! -L core ]; then

View File

@ -2,7 +2,8 @@
set -e
set -o pipefail
export REALM_CORE_VERSION=$(./scripts/download-core.sh --version)
echo "Core Version: $REALM_CORE_VERSION"
cd "$(dirname "$0")/.."
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 JSStringRef defaultString = JSStringCreateWithUTF8CString("default");
static JSStringRef indexedString = JSStringCreateWithUTF8CString("indexed");
static JSStringRef typeString = JSStringCreateWithUTF8CString("type");
static JSStringRef objectTypeString = JSStringCreateWithUTF8CString("objectType");
static JSStringRef optionalString = JSStringCreateWithUTF8CString("optional");
@ -123,6 +124,11 @@ static inline Property RJSParseProperty(JSContextRef ctx, JSValueRef propertyAtt
JSValueProtect(ctx, defaultValue);
objectDefaults.emplace(prop.name, defaultValue);
}
JSValueRef indexedValue = RJSValidatedPropertyValue(ctx, propertyObject, indexedString);
if (!JSValueIsUndefined(ctx, indexedValue)) {
prop.is_indexed = JSValueToBoolean(ctx, indexedValue);
}
}
return prop;

View File

@ -7,7 +7,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake")
include(CompilerFlags)
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})
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
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
```

View File

@ -159,7 +159,7 @@ void AsyncQuery::run()
if (m_initial_run_complete) {
// Make an empty tableview from the query to get the table version, since
// 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;
}
}
@ -181,7 +181,7 @@ void AsyncQuery::prepare_handover()
REALM_ASSERT(m_tv.is_in_sync());
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);
// 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;
Results::Internal::set_table_view(*m_target_results,
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);
@ -259,8 +259,8 @@ std::function<void (std::exception_ptr)> AsyncQuery::next_callback()
std::lock_guard<std::mutex> callback_lock(m_callback_mutex);
for (++m_callback_index; m_callback_index < m_callbacks.size(); ++m_callback_index) {
auto& callback = m_callbacks[m_callback_index];
if (m_error || callback.delivered_version != m_delievered_table_version) {
callback.delivered_version = m_delievered_table_version;
if (m_error || callback.delivered_version != m_delivered_table_version) {
callback.delivered_version = m_delivered_table_version;
return callback.fn;
}
}

View File

@ -97,7 +97,7 @@ private:
SharedGroup* m_sg = nullptr;
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
// remove_callback() updates this when needed

View File

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

View File

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

View File

@ -25,7 +25,7 @@
namespace realm {
class AsyncQueryCallback;
class ClientHistory;
class Replication;
class Results;
class Schema;
class SharedGroup;
@ -65,10 +65,10 @@ public:
// Should only be called in test code, as continuing to use the previously
// cached instances will have odd results
static void clear_cache();
// Clears all caches on existing coordinators
static void clear_all_caches();
// Explicit constructor/destructor needed for the unique_ptrs to forward-declared types
RealmCoordinator();
~RealmCoordinator();
@ -102,13 +102,13 @@ private:
// SharedGroup used for actually running async queries
// 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;
// SharedGroup used to advance queries in m_new_queries to the main shared
// group's transaction version
// 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::exception_ptr m_async_error;

View File

@ -432,23 +432,21 @@ public:
namespace realm {
namespace _impl {
namespace transaction {
void advance(SharedGroup& sg, ClientHistory& history, BindingContext* context,
SharedGroup::VersionID version)
void advance(SharedGroup& sg, BindingContext* context, SharedGroup::VersionID version)
{
TransactLogObserver(context, sg, [&](auto&&... args) {
LangBindHelper::advance_read(sg, history, std::move(args)...);
LangBindHelper::advance_read(sg, std::move(args)...);
}, true);
}
void begin(SharedGroup& sg, ClientHistory& history, BindingContext* context,
bool validate_schema_changes)
void begin(SharedGroup& sg, BindingContext* context, bool validate_schema_changes)
{
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);
}
void commit(SharedGroup& sg, ClientHistory&, BindingContext* context)
void commit(SharedGroup& sg, BindingContext* context)
{
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) {
LangBindHelper::rollback_and_continue_as_read(sg, history, std::move(args)...);
LangBindHelper::rollback_and_continue_as_read(sg, std::move(args)...);
}, false);
}

View File

@ -24,27 +24,26 @@
namespace realm {
class BindingContext;
class SharedGroup;
class ClientHistory;
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, BindingContext* binding_context,
void advance(SharedGroup& sg, BindingContext* binding_context,
SharedGroup::VersionID version=SharedGroup::VersionID{});
// 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, BindingContext* binding_context,
void begin(SharedGroup& sg, BindingContext* binding_context,
bool validate_schema_changes=true);
// 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
// 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 _impl
} // namespace realm

View File

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

View File

@ -52,7 +52,7 @@ namespace realm {
// determines if a realm with the given old schema needs non-migration
// changes to make it compatible with the given target 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
// passed in target schema is updated with the correct column mapping
// optionally runs migration function if schema is out of date

View File

@ -112,7 +112,7 @@ struct ParserState
{
return group_stack.back();
}
Predicate *last_predicate()
{
Predicate *pred = current_group();
@ -121,12 +121,12 @@ struct ParserState
}
return pred;
}
void add_predicate_to_current_group(Predicate::Type type)
{
current_group()->cpnd.sub_predicates.emplace_back(type, negate_next);
negate_next = false;
if (current_group()->cpnd.sub_predicates.size() > 1) {
if (next_type == Predicate::Type::Or) {
apply_or();
@ -136,10 +136,10 @@ struct ParserState
}
}
}
bool negate_next = false;
Predicate::Type next_type = Predicate::Type::And;
void add_expression(Expression && exp)
{
Predicate *current = last_predicate();
@ -151,32 +151,32 @@ struct ParserState
last_predicate()->cmpr.expr[0] = std::move(exp);
}
}
void apply_or()
{
Predicate *group = current_group();
if (group->type == Predicate::Type::Or) {
return;
}
// convert to OR
group->type = Predicate::Type::Or;
if (group->cpnd.sub_predicates.size() > 2) {
// split the current group into an AND group ORed with the last subpredicate
Predicate new_sub(Predicate::Type::And);
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[0].cpnd.sub_predicates.pop_back();
}
}
void apply_and()
{
if (current_group()->type == Predicate::Type::And) {
return;
}
auto &sub_preds = current_group()->cpnd.sub_predicates;
auto second_last = sub_preds.end() - 2;
if (second_last->type == Predicate::Type::And && !second_last->negate) {

View File

@ -462,7 +462,7 @@ void update_query_with_predicate(Query &query, const Predicate &pred, Arguments
if (pred.negate) {
query.Not();
}
switch (pred.type) {
case Predicate::Type::And:
query.group();
@ -474,7 +474,7 @@ void update_query_with_predicate(Query &query, const Predicate &pred, Arguments
}
query.end_group();
break;
case Predicate::Type::Or:
query.group();
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();
break;
case Predicate::Type::Comparison: {
add_comparison_to_query(query, pred, arguments, schema, type);
break;
@ -494,11 +494,11 @@ void update_query_with_predicate(Query &query, const Predicate &pred, Arguments
case Predicate::Type::True:
query.and_query(std::unique_ptr<realm::Expression>(new TrueExpression));
break;
case Predicate::Type::False:
query.and_query(std::unique_ptr<realm::Expression>(new FalseExpression));
break;
default:
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)
{
update_query_with_predicate(query, predicate, arguments, schema, objectType);
// Test the constructed query in core
std::string validateMessage = query.validate();
precondition(validateMessage.empty(), validateMessage.c_str());

View File

@ -55,6 +55,7 @@ namespace realm {
size_t table_column = -1;
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) {

View File

@ -83,10 +83,10 @@ public:
// Get the Realm
SharedRealm get_realm() const { return m_realm; }
// Object schema describing the vendored object type
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
Query get_query() const;

View File

@ -89,7 +89,7 @@ void Schema::validate() const
// check indexable
if (prop.is_indexed) {
if (prop.type != PropertyTypeString && prop.type != PropertyTypeInt) {
if (!prop.is_indexable()) {
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,
std::unique_ptr<ClientHistory>& history,
std::unique_ptr<Replication>& history,
std::unique_ptr<SharedGroup>& shared_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();
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);
m_in_transaction = true;
struct WriteTransactionGuard {
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()
{
check_read_write(this);
verify_thread();
if (m_in_transaction) {
if (is_in_transaction()) {
throw InvalidTransactionException("The Realm is already in a write transaction");
}
// make sure we have a read transaction
read_group();
transaction::begin(*m_shared_group, *m_history, m_binding_context.get());
m_in_transaction = true;
transaction::begin(*m_shared_group, m_binding_context.get());
}
void Realm::commit_transaction()
@ -310,12 +316,11 @@ void Realm::commit_transaction()
check_read_write(this);
verify_thread();
if (!m_in_transaction) {
if (!is_in_transaction()) {
throw InvalidTransactionException("Can't commit a non-existing write transaction");
}
m_in_transaction = false;
transaction::commit(*m_shared_group, *m_history, m_binding_context.get());
transaction::commit(*m_shared_group, m_binding_context.get());
m_coordinator->send_commit_notifications();
}
@ -324,18 +329,19 @@ void Realm::cancel_transaction()
check_read_write(this);
verify_thread();
if (!m_in_transaction) {
if (!is_in_transaction()) {
throw InvalidTransactionException("Can't cancel a non-existing write transaction");
}
m_in_transaction = false;
transaction::cancel(*m_shared_group, *m_history, m_binding_context.get());
transaction::cancel(*m_shared_group, m_binding_context.get());
}
void Realm::invalidate()
{
verify_thread();
if (m_in_transaction) {
check_read_write(this);
if (is_in_transaction()) {
cancel_transaction();
}
if (!m_group) {
@ -353,7 +359,7 @@ bool Realm::compact()
if (m_config.read_only) {
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");
}
@ -395,7 +401,7 @@ bool Realm::refresh()
check_read_write(this);
// can't be any new changes if we're in a write transaction
if (m_in_transaction) {
if (is_in_transaction()) {
return false;
}
@ -405,7 +411,7 @@ bool Realm::refresh()
}
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);
}
else {

View File

@ -32,7 +32,7 @@
namespace realm {
class BindingContext;
class ClientHistory;
class Replication;
class Group;
class Realm;
class RealmDelegate;
@ -114,7 +114,7 @@ namespace realm {
void begin_transaction();
void commit_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 refresh();
@ -149,7 +149,6 @@ namespace realm {
// AsyncQuery needs access to the SharedGroup to be able to call the
// handover functions, which are not very wrappable
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
// 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,
std::unique_ptr<ClientHistory>& history,
std::unique_ptr<Replication>& history,
std::unique_ptr<SharedGroup>& shared_group,
std::unique_ptr<Group>& read_only_group);
private:
Config m_config;
std::thread::id m_thread_id = std::this_thread::get_id();
bool m_in_transaction = false;
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<Group> m_read_only_group;
@ -231,7 +229,7 @@ namespace realm {
public:
UnitializedRealmException(std::string message) : std::runtime_error(message) {}
};
class InvalidEncryptionKeyException : public std::runtime_error {
public:
InvalidEncryptionKeyException() : std::runtime_error("Encryption key must be 64 bytes.") {}

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() {
var realm = new Realm({schema: [schemas.DefaultValues, schemas.TestObject]});