Merge pull request #194 from realm/al-os
Merge latest object store changes
This commit is contained in:
commit
5b113d23b8
|
@ -21,7 +21,7 @@ JSValueRef ListGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef pro
|
||||||
return JSValueMakeNumber(ctx, size);
|
return JSValueMakeNumber(ctx, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return RJSObjectCreate(ctx, Object(list->realm(), list->object_schema, list->get(RJSValidatedPositiveIndex(indexStr))));
|
return RJSObjectCreate(ctx, Object(list->realm(), list->get_object_schema(), list->get(RJSValidatedPositiveIndex(indexStr))));
|
||||||
}
|
}
|
||||||
catch (std::out_of_range &exp) {
|
catch (std::out_of_range &exp) {
|
||||||
// getters for nonexistent properties in JS should always return undefined
|
// getters for nonexistent properties in JS should always return undefined
|
||||||
|
@ -103,7 +103,7 @@ JSValueRef ListPop(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObjec
|
||||||
return JSValueMakeUndefined(ctx);
|
return JSValueMakeUndefined(ctx);
|
||||||
}
|
}
|
||||||
size_t index = size - 1;
|
size_t index = size - 1;
|
||||||
JSValueRef obj = RJSObjectCreate(ctx, Object(list->realm(), list->object_schema, list->get(index)));
|
JSValueRef obj = RJSObjectCreate(ctx, Object(list->realm(), list->get_object_schema(), list->get(index)));
|
||||||
list->remove(index);
|
list->remove(index);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,7 @@ JSValueRef ListShift(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObj
|
||||||
list->verify_in_tranaction();
|
list->verify_in_tranaction();
|
||||||
return JSValueMakeUndefined(ctx);
|
return JSValueMakeUndefined(ctx);
|
||||||
}
|
}
|
||||||
JSValueRef obj = RJSObjectCreate(ctx, Object(list->realm(), list->object_schema, list->get(0)));
|
JSValueRef obj = RJSObjectCreate(ctx, Object(list->realm(), list->get_object_schema(), list->get(0)));
|
||||||
list->remove(0);
|
list->remove(0);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
@ -168,7 +168,7 @@ JSValueRef ListSplice(JSContextRef ctx, JSObjectRef function, JSObjectRef thisOb
|
||||||
|
|
||||||
std::vector<JSObjectRef> removedObjects(remove);
|
std::vector<JSObjectRef> removedObjects(remove);
|
||||||
for (size_t i = 0; i < remove; i++) {
|
for (size_t i = 0; i < remove; i++) {
|
||||||
removedObjects[i] = RJSObjectCreate(ctx, Object(list->realm(), list->object_schema, list->get(index)));
|
removedObjects[i] = RJSObjectCreate(ctx, Object(list->realm(), list->get_object_schema(), list->get(index)));
|
||||||
list->remove(index);
|
list->remove(index);
|
||||||
}
|
}
|
||||||
for (size_t i = 2; i < argumentCount; i++) {
|
for (size_t i = 2; i < argumentCount; i++) {
|
||||||
|
|
|
@ -45,7 +45,7 @@ bool ObjectSetProperty(JSContextRef ctx, JSObjectRef jsObject, JSStringRef jsPro
|
||||||
void ObjectPropertyNames(JSContextRef ctx, JSObjectRef jsObject, JSPropertyNameAccumulatorRef propertyNames) {
|
void ObjectPropertyNames(JSContextRef ctx, JSObjectRef jsObject, JSPropertyNameAccumulatorRef propertyNames) {
|
||||||
Object *obj = RJSGetInternal<Object *>(jsObject);
|
Object *obj = RJSGetInternal<Object *>(jsObject);
|
||||||
|
|
||||||
for (auto &prop : obj->object_schema.properties) {
|
for (auto &prop : obj->get_object_schema().properties) {
|
||||||
JSStringRef propertyName = RJSStringForString(prop.name);
|
JSStringRef propertyName = RJSStringForString(prop.name);
|
||||||
JSPropertyNameAccumulatorAddName(propertyNames, propertyName);
|
JSPropertyNameAccumulatorAddName(propertyNames, propertyName);
|
||||||
JSStringRelease(propertyName);
|
JSStringRelease(propertyName);
|
||||||
|
@ -58,7 +58,7 @@ JSClassRef RJSObjectClass() {
|
||||||
}
|
}
|
||||||
|
|
||||||
JSObjectRef RJSObjectCreate(JSContextRef ctx, Object object) {
|
JSObjectRef RJSObjectCreate(JSContextRef ctx, Object object) {
|
||||||
JSValueRef prototype = RJSPrototypes(object.realm().get())[object.object_schema.name];
|
JSValueRef prototype = RJSPrototypes(object.realm().get())[object.get_object_schema().name];
|
||||||
JSObjectRef jsObject = RJSWrapObject(ctx, RJSObjectClass(), new Object(object), prototype);
|
JSObjectRef jsObject = RJSWrapObject(ctx, RJSObjectClass(), new Object(object), prototype);
|
||||||
return jsObject;
|
return jsObject;
|
||||||
}
|
}
|
||||||
|
|
|
@ -332,7 +332,7 @@ JSValueRef RealmDelete(JSContextRef ctx, JSObjectRef function, JSObjectRef thisO
|
||||||
throw std::runtime_error("Can only delete objects within a transaction.");
|
throw std::runtime_error("Can only delete objects within a transaction.");
|
||||||
}
|
}
|
||||||
|
|
||||||
realm::TableRef table = ObjectStore::table_for_object_type(realm->read_group(), object->object_schema.name);
|
realm::TableRef table = ObjectStore::table_for_object_type(realm->read_group(), object->get_object_schema().name);
|
||||||
table->move_last_over(object->row().get_index());
|
table->move_last_over(object->row().get_index());
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -23,7 +23,7 @@ JSValueRef ResultsGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef
|
||||||
}
|
}
|
||||||
|
|
||||||
return RJSObjectCreate(ctx, Object(results->get_realm(),
|
return RJSObjectCreate(ctx, Object(results->get_realm(),
|
||||||
results->object_schema,
|
results->get_object_schema(),
|
||||||
results->get(RJSValidatedPositiveIndex(indexStr))));
|
results->get(RJSValidatedPositiveIndex(indexStr))));
|
||||||
}
|
}
|
||||||
catch (std::out_of_range &exp) {
|
catch (std::out_of_range &exp) {
|
||||||
|
@ -76,9 +76,9 @@ JSValueRef SortByProperty(JSContextRef ctx, JSObjectRef function, JSObjectRef th
|
||||||
Results *results = RJSGetInternal<Results *>(thisObject);
|
Results *results = RJSGetInternal<Results *>(thisObject);
|
||||||
RJSValidateArgumentRange(argumentCount, 1, 2);
|
RJSValidateArgumentRange(argumentCount, 1, 2);
|
||||||
std::string propName = RJSValidatedStringForValue(ctx, arguments[0]);
|
std::string propName = RJSValidatedStringForValue(ctx, arguments[0]);
|
||||||
const Property *prop = results->object_schema.property_for_name(propName);
|
const Property *prop = results->get_object_schema().property_for_name(propName);
|
||||||
if (!prop) {
|
if (!prop) {
|
||||||
throw std::runtime_error("Property '" + propName + "' does not exist on object type '" + results->object_schema.name + "'");
|
throw std::runtime_error("Property '" + propName + "' does not exist on object type '" + results->get_object_schema().name + "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ascending = true;
|
bool ascending = true;
|
||||||
|
|
|
@ -304,6 +304,8 @@ public:
|
||||||
bool set_link(size_t col, size_t row, size_t, size_t) { return mark_dirty(row, col); }
|
bool set_link(size_t col, size_t row, size_t, size_t) { return mark_dirty(row, col); }
|
||||||
bool set_null(size_t col, size_t row) { return mark_dirty(row, col); }
|
bool set_null(size_t col, size_t row) { return mark_dirty(row, col); }
|
||||||
bool nullify_link(size_t col, size_t row, size_t) { return mark_dirty(row, col); }
|
bool nullify_link(size_t col, size_t row, size_t) { return mark_dirty(row, col); }
|
||||||
|
bool set_int_unique(size_t col, size_t row, int_fast64_t) { return mark_dirty(row, col); }
|
||||||
|
bool set_string_unique(size_t col, size_t row, StringData) { return mark_dirty(row, col); }
|
||||||
|
|
||||||
// Doesn't change any data
|
// Doesn't change any data
|
||||||
bool optimize_table() { return true; }
|
bool optimize_table() { return true; }
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#ifndef REALM_INDEX_SET_HPP
|
#ifndef REALM_INDEX_SET_HPP
|
||||||
#define REALM_INDEX_SET_HPP
|
#define REALM_INDEX_SET_HPP
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace realm {
|
namespace realm {
|
||||||
|
|
|
@ -17,7 +17,8 @@
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "list.hpp"
|
#include "list.hpp"
|
||||||
#import <stdexcept>
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
using namespace realm;
|
using namespace realm;
|
||||||
|
|
||||||
|
@ -26,40 +27,40 @@ size_t List::size() {
|
||||||
return m_link_view->size();
|
return m_link_view->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
Row List::get(size_t row_ndx) {
|
Row List::get(std::size_t row_ndx) {
|
||||||
verify_attached();
|
verify_attached();
|
||||||
verify_valid_row(row_ndx);
|
verify_valid_row(row_ndx);
|
||||||
return m_link_view->get(row_ndx);
|
return m_link_view->get(row_ndx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void List::set(size_t row_ndx, size_t target_row_ndx) {
|
void List::set(std::size_t row_ndx, std::size_t target_row_ndx) {
|
||||||
verify_attached();
|
verify_attached();
|
||||||
verify_in_tranaction();
|
verify_in_tranaction();
|
||||||
verify_valid_row(row_ndx);
|
verify_valid_row(row_ndx);
|
||||||
m_link_view->set(row_ndx, target_row_ndx);
|
m_link_view->set(row_ndx, target_row_ndx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void List::add(size_t target_row_ndx) {
|
void List::add(std::size_t target_row_ndx) {
|
||||||
verify_attached();
|
verify_attached();
|
||||||
verify_in_tranaction();
|
verify_in_tranaction();
|
||||||
m_link_view->add(target_row_ndx);
|
m_link_view->add(target_row_ndx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void List::insert(size_t row_ndx, size_t target_row_ndx) {
|
void List::insert(std::size_t row_ndx, std::size_t target_row_ndx) {
|
||||||
verify_attached();
|
verify_attached();
|
||||||
verify_in_tranaction();
|
verify_in_tranaction();
|
||||||
verify_valid_row(row_ndx, true);
|
verify_valid_row(row_ndx, true);
|
||||||
m_link_view->insert(row_ndx, target_row_ndx);
|
m_link_view->insert(row_ndx, target_row_ndx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void List::remove(size_t row_ndx) {
|
void List::remove(std::size_t row_ndx) {
|
||||||
verify_attached();
|
verify_attached();
|
||||||
verify_in_tranaction();
|
verify_in_tranaction();
|
||||||
verify_valid_row(row_ndx);
|
verify_valid_row(row_ndx);
|
||||||
m_link_view->remove(row_ndx);
|
m_link_view->remove(row_ndx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void List::verify_valid_row(size_t row_ndx, bool insertion) {
|
void List::verify_valid_row(std::size_t row_ndx, bool insertion) {
|
||||||
size_t size = m_link_view->size();
|
size_t size = m_link_view->size();
|
||||||
if (row_ndx > size || (!insertion && row_ndx == size)) {
|
if (row_ndx > size || (!insertion && row_ndx == size)) {
|
||||||
throw std::out_of_range(std::string("Index ") + std::to_string(row_ndx) + " is outside of range 0..." + std::to_string(size) + ".");
|
throw std::out_of_range(std::string("Index ") + std::to_string(row_ndx) + " is outside of range 0..." + std::to_string(size) + ".");
|
||||||
|
|
|
@ -19,20 +19,20 @@
|
||||||
#ifndef REALM_LIST_HPP
|
#ifndef REALM_LIST_HPP
|
||||||
#define REALM_LIST_HPP
|
#define REALM_LIST_HPP
|
||||||
|
|
||||||
#import "shared_realm.hpp"
|
#include "shared_realm.hpp"
|
||||||
#import <realm/link_view.hpp>
|
#include <realm/link_view.hpp>
|
||||||
|
|
||||||
namespace realm {
|
namespace realm {
|
||||||
class List {
|
class List {
|
||||||
public:
|
public:
|
||||||
List(SharedRealm &r, const ObjectSchema &s, LinkViewRef l) : m_realm(r), object_schema(s), m_link_view(l) {}
|
List(SharedRealm &r, const ObjectSchema &s, LinkViewRef l) : m_realm(r), m_object_schema(&s), m_link_view(l) {}
|
||||||
|
|
||||||
const ObjectSchema &object_schema;
|
const ObjectSchema &get_object_schema() const { return *m_object_schema; }
|
||||||
SharedRealm realm() { return m_realm; }
|
SharedRealm realm() { return m_realm; }
|
||||||
|
|
||||||
size_t size();
|
size_t size();
|
||||||
Row get(size_t row_ndx);
|
Row get(std::size_t row_ndx);
|
||||||
void set(size_t row_ndx, size_t target_row_ndx);
|
void set(std::size_t row_ndx, std::size_t target_row_ndx);
|
||||||
|
|
||||||
void add(size_t target_row_ndx);
|
void add(size_t target_row_ndx);
|
||||||
void remove(size_t list_ndx);
|
void remove(size_t list_ndx);
|
||||||
|
@ -47,12 +47,13 @@ namespace realm {
|
||||||
template<typename ValueType, typename ContextType>
|
template<typename ValueType, typename ContextType>
|
||||||
void set(ContextType ctx, ValueType value, size_t list_ndx);
|
void set(ContextType ctx, ValueType value, size_t list_ndx);
|
||||||
|
|
||||||
void verify_valid_row(size_t row_ndx, bool insertion = false);
|
void verify_valid_row(std::size_t row_ndx, bool insertion = false);
|
||||||
void verify_attached();
|
void verify_attached();
|
||||||
void verify_in_tranaction();
|
void verify_in_tranaction();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SharedRealm m_realm;
|
SharedRealm m_realm;
|
||||||
|
const ObjectSchema *m_object_schema;
|
||||||
LinkViewRef m_link_view;
|
LinkViewRef m_link_view;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace realm {
|
||||||
|
|
||||||
class Object {
|
class Object {
|
||||||
public:
|
public:
|
||||||
Object(SharedRealm r, const ObjectSchema &s, Row o) : m_realm(r), object_schema(s), m_row(o) {}
|
Object(SharedRealm r, const ObjectSchema &s, Row o) : m_realm(r), m_object_schema(&s), m_row(o) {}
|
||||||
|
|
||||||
// property getter/setter
|
// property getter/setter
|
||||||
template<typename ValueType, typename ContextType>
|
template<typename ValueType, typename ContextType>
|
||||||
|
@ -27,12 +27,13 @@ namespace realm {
|
||||||
template<typename ValueType, typename ContextType>
|
template<typename ValueType, typename ContextType>
|
||||||
static inline Object create(ContextType ctx, SharedRealm realm, const ObjectSchema &object_schema, ValueType value, bool try_update);
|
static inline Object create(ContextType ctx, SharedRealm realm, const ObjectSchema &object_schema, ValueType value, bool try_update);
|
||||||
|
|
||||||
const ObjectSchema &object_schema;
|
|
||||||
SharedRealm realm() { return m_realm; }
|
SharedRealm realm() { return m_realm; }
|
||||||
|
const ObjectSchema &get_object_schema() { return *m_object_schema; }
|
||||||
Row row() { return m_row; }
|
Row row() { return m_row; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SharedRealm m_realm;
|
SharedRealm m_realm;
|
||||||
|
const ObjectSchema *m_object_schema;
|
||||||
Row m_row;
|
Row m_row;
|
||||||
|
|
||||||
template<typename ValueType, typename ContextType>
|
template<typename ValueType, typename ContextType>
|
||||||
|
@ -119,10 +120,10 @@ namespace realm {
|
||||||
template <typename ValueType, typename ContextType>
|
template <typename ValueType, typename ContextType>
|
||||||
inline void Object::set_property_value(ContextType ctx, std::string prop_name, ValueType value, bool try_update)
|
inline void Object::set_property_value(ContextType ctx, std::string prop_name, ValueType value, bool try_update)
|
||||||
{
|
{
|
||||||
const Property *prop = object_schema.property_for_name(prop_name);
|
const Property *prop = m_object_schema->property_for_name(prop_name);
|
||||||
if (!prop) {
|
if (!prop) {
|
||||||
throw InvalidPropertyException(object_schema.name, prop_name,
|
throw InvalidPropertyException(m_object_schema->name, prop_name,
|
||||||
"Setting invalid property '" + prop_name + "' on object '" + object_schema.name + "'.");
|
"Setting invalid property '" + prop_name + "' on object '" + m_object_schema->name + "'.");
|
||||||
}
|
}
|
||||||
set_property_value_impl(ctx, *prop, value, try_update);
|
set_property_value_impl(ctx, *prop, value, try_update);
|
||||||
};
|
};
|
||||||
|
@ -130,10 +131,10 @@ namespace realm {
|
||||||
template <typename ValueType, typename ContextType>
|
template <typename ValueType, typename ContextType>
|
||||||
inline ValueType Object::get_property_value(ContextType ctx, std::string prop_name)
|
inline ValueType Object::get_property_value(ContextType ctx, std::string prop_name)
|
||||||
{
|
{
|
||||||
const Property *prop = object_schema.property_for_name(prop_name);
|
const Property *prop = m_object_schema->property_for_name(prop_name);
|
||||||
if (!prop) {
|
if (!prop) {
|
||||||
throw InvalidPropertyException(object_schema.name, prop_name,
|
throw InvalidPropertyException(m_object_schema->name, prop_name,
|
||||||
"Getting invalid property '" + prop_name + "' on object '" + object_schema.name + "'.");
|
"Getting invalid property '" + prop_name + "' on object '" + m_object_schema->name + "'.");
|
||||||
}
|
}
|
||||||
return get_property_value_impl<ValueType>(ctx, *prop);
|
return get_property_value_impl<ValueType>(ctx, *prop);
|
||||||
};
|
};
|
||||||
|
@ -308,19 +309,19 @@ namespace realm {
|
||||||
template<typename ValueType, typename ContextType>
|
template<typename ValueType, typename ContextType>
|
||||||
void List::add(ContextType ctx, ValueType value)
|
void List::add(ContextType ctx, ValueType value)
|
||||||
{
|
{
|
||||||
add(NativeAccessor<ValueType, ContextType>::to_object_index(ctx, m_realm, value, object_schema.name, false));
|
add(NativeAccessor<ValueType, ContextType>::to_object_index(ctx, m_realm, value, get_object_schema().name, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ValueType, typename ContextType>
|
template<typename ValueType, typename ContextType>
|
||||||
void List::insert(ContextType ctx, ValueType value, size_t list_ndx)
|
void List::insert(ContextType ctx, ValueType value, size_t list_ndx)
|
||||||
{
|
{
|
||||||
insert(list_ndx, NativeAccessor<ValueType, ContextType>::to_object_index(ctx, m_realm, value, object_schema.name, false));
|
insert(list_ndx, NativeAccessor<ValueType, ContextType>::to_object_index(ctx, m_realm, value, get_object_schema().name, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ValueType, typename ContextType>
|
template<typename ValueType, typename ContextType>
|
||||||
void List::set(ContextType ctx, ValueType value, size_t list_ndx)
|
void List::set(ContextType ctx, ValueType value, size_t list_ndx)
|
||||||
{
|
{
|
||||||
set(list_ndx, NativeAccessor<ValueType, ContextType>::to_object_index(ctx, m_realm, value, object_schema.name, false));
|
set(list_ndx, NativeAccessor<ValueType, ContextType>::to_object_index(ctx, m_realm, value, get_object_schema().name, false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -227,7 +227,7 @@ template<> struct action< or_op >
|
||||||
template<> struct action< rule > { \
|
template<> struct action< rule > { \
|
||||||
static void apply( const input & in, ParserState & state ) { \
|
static void apply( const input & in, ParserState & state ) { \
|
||||||
DEBUG_PRINT_TOKEN(in.string()); \
|
DEBUG_PRINT_TOKEN(in.string()); \
|
||||||
state.add_expression(Expression(type, in.string())); }};
|
state.add_expression(Expression{type, in.string()}); }};
|
||||||
|
|
||||||
EXPRESSION_ACTION(dq_string_content, Expression::Type::String)
|
EXPRESSION_ACTION(dq_string_content, Expression::Type::String)
|
||||||
EXPRESSION_ACTION(sq_string_content, Expression::Type::String)
|
EXPRESSION_ACTION(sq_string_content, Expression::Type::String)
|
||||||
|
|
|
@ -23,67 +23,64 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace realm {
|
namespace realm {
|
||||||
class Schema;
|
class Schema;
|
||||||
|
|
||||||
namespace parser {
|
namespace parser {
|
||||||
struct Expression
|
struct Expression
|
||||||
{
|
{
|
||||||
enum class Type { None, Number, String, KeyPath, Argument, True, False } type = Type::None;
|
enum class Type { None, Number, String, KeyPath, Argument, True, False } type = Type::None;
|
||||||
std::string s;
|
std::string s;
|
||||||
Expression() {}
|
};
|
||||||
Expression(Type t, std::string s) : type(t), s(s) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Predicate
|
struct Predicate
|
||||||
{
|
{
|
||||||
enum class Type
|
enum class Type
|
||||||
{
|
{
|
||||||
Comparison,
|
Comparison,
|
||||||
Or,
|
Or,
|
||||||
And,
|
And,
|
||||||
True,
|
True,
|
||||||
False
|
False
|
||||||
} type = Type::And;
|
} type = Type::And;
|
||||||
|
|
||||||
enum class Operator
|
enum class Operator
|
||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
Equal,
|
Equal,
|
||||||
NotEqual,
|
NotEqual,
|
||||||
LessThan,
|
LessThan,
|
||||||
LessThanOrEqual,
|
LessThanOrEqual,
|
||||||
GreaterThan,
|
GreaterThan,
|
||||||
GreaterThanOrEqual,
|
GreaterThanOrEqual,
|
||||||
BeginsWith,
|
BeginsWith,
|
||||||
EndsWith,
|
EndsWith,
|
||||||
Contains
|
Contains
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Comparison
|
struct Comparison
|
||||||
{
|
{
|
||||||
Operator op = Operator::None;
|
Operator op = Operator::None;
|
||||||
Expression expr[2];
|
Expression expr[2];
|
||||||
~Comparison() {}
|
};
|
||||||
};
|
|
||||||
|
|
||||||
struct Compound
|
struct Compound
|
||||||
{
|
{
|
||||||
std::vector<Predicate> sub_predicates;
|
std::vector<Predicate> sub_predicates;
|
||||||
};
|
};
|
||||||
|
|
||||||
Comparison cmpr;
|
Comparison cmpr;
|
||||||
Compound cpnd;
|
Compound cpnd;
|
||||||
|
|
||||||
bool negate = false;
|
bool negate = false;
|
||||||
|
|
||||||
Predicate(Type t, bool n = false) : type(t), negate(n) {}
|
Predicate(Type t, bool n = false) : type(t), negate(n) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
Predicate parse(const std::string &query);
|
Predicate parse(const std::string &query);
|
||||||
|
|
||||||
void analyzeGrammar();
|
void analyzeGrammar();
|
||||||
bool testGrammar();
|
bool testGrammar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // REALM_PARSER_HPP
|
#endif // REALM_PARSER_HPP
|
||||||
|
|
|
@ -230,7 +230,7 @@ void add_binary_constraint_to_query(realm::Query &query,
|
||||||
|
|
||||||
void add_link_constraint_to_query(realm::Query &query,
|
void add_link_constraint_to_query(realm::Query &query,
|
||||||
Predicate::Operator op,
|
Predicate::Operator op,
|
||||||
PropertyExpression &prop_expr,
|
const PropertyExpression &prop_expr,
|
||||||
size_t row_index) {
|
size_t row_index) {
|
||||||
precondition(prop_expr.indexes.empty(), "KeyPath queries not supported for object comparisons.");
|
precondition(prop_expr.indexes.empty(), "KeyPath queries not supported for object comparisons.");
|
||||||
switch (op) {
|
switch (op) {
|
||||||
|
@ -260,12 +260,12 @@ void add_link_constraint_to_query(realm::Query &query,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto link_argument(PropertyExpression &propExpr, parser::Expression &argExpr, Arguments &args)
|
auto link_argument(const PropertyExpression &propExpr, const parser::Expression &argExpr, Arguments &args)
|
||||||
{
|
{
|
||||||
return args.object_index_for_argument(std::stoi(argExpr.s));
|
return args.object_index_for_argument(std::stoi(argExpr.s));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto link_argument(parser::Expression &argExpr, PropertyExpression &propExpr, Arguments &args)
|
auto link_argument(const parser::Expression &argExpr, const PropertyExpression &propExpr, Arguments &args)
|
||||||
{
|
{
|
||||||
return args.object_index_for_argument(std::stoi(argExpr.s));
|
return args.object_index_for_argument(std::stoi(argExpr.s));
|
||||||
}
|
}
|
||||||
|
@ -376,7 +376,7 @@ auto value_of_type_for_query(TableGetter&& tables, Value&& value, Arguments &arg
|
||||||
|
|
||||||
template <typename A, typename B>
|
template <typename A, typename B>
|
||||||
void do_add_comparison_to_query(Query &query, const Schema &schema, const ObjectSchema &object_schema, Predicate::Operator op,
|
void do_add_comparison_to_query(Query &query, const Schema &schema, const ObjectSchema &object_schema, Predicate::Operator op,
|
||||||
PropertyExpression &expr, A &lhs, B &rhs, Arguments &args)
|
const PropertyExpression &expr, A &lhs, B &rhs, Arguments &args)
|
||||||
{
|
{
|
||||||
auto type = expr.prop->type;
|
auto type = expr.prop->type;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -418,9 +418,9 @@ void do_add_comparison_to_query(Query &query, const Schema &schema, const Object
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_comparison_to_query(Query &query, Predicate &pred, Arguments &args, const Schema &schema, const std::string &type)
|
void add_comparison_to_query(Query &query, const Predicate &pred, Arguments &args, const Schema &schema, const std::string &type)
|
||||||
{
|
{
|
||||||
Predicate::Comparison &cmpr = pred.cmpr;
|
const Predicate::Comparison &cmpr = pred.cmpr;
|
||||||
auto t0 = cmpr.expr[0].type, t1 = cmpr.expr[1].type;
|
auto t0 = cmpr.expr[0].type, t1 = cmpr.expr[1].type;
|
||||||
auto object_schema = schema.find(type);
|
auto object_schema = schema.find(type);
|
||||||
if (t0 == parser::Expression::Type::KeyPath && t1 != parser::Expression::Type::KeyPath) {
|
if (t0 == parser::Expression::Type::KeyPath && t1 != parser::Expression::Type::KeyPath) {
|
||||||
|
@ -436,7 +436,7 @@ void add_comparison_to_query(Query &query, Predicate &pred, Arguments &args, con
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_query_with_predicate(Query &query, Predicate &pred, Arguments &arguments, const Schema &schema, const std::string &type)
|
void update_query_with_predicate(Query &query, const Predicate &pred, Arguments &arguments, const Schema &schema, const std::string &type)
|
||||||
{
|
{
|
||||||
if (pred.negate) {
|
if (pred.negate) {
|
||||||
query.Not();
|
query.Not();
|
||||||
|
@ -484,7 +484,7 @@ void update_query_with_predicate(Query &query, Predicate &pred, Arguments &argum
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void apply_predicate(Query &query, Predicate &predicate, Arguments &arguments, const Schema &schema, std::string objectType)
|
void apply_predicate(Query &query, const Predicate &predicate, Arguments &arguments, const Schema &schema, const std::string &objectType)
|
||||||
{
|
{
|
||||||
update_query_with_predicate(query, predicate, arguments, schema, objectType);
|
update_query_with_predicate(query, predicate, arguments, schema, objectType);
|
||||||
|
|
||||||
|
|
|
@ -24,57 +24,57 @@
|
||||||
#include "object_accessor.hpp"
|
#include "object_accessor.hpp"
|
||||||
|
|
||||||
namespace realm {
|
namespace realm {
|
||||||
class Query;
|
class Query;
|
||||||
class Schema;
|
class Schema;
|
||||||
|
|
||||||
namespace query_builder {
|
namespace query_builder {
|
||||||
class Arguments;
|
class Arguments;
|
||||||
|
|
||||||
void apply_predicate(Query &query, parser::Predicate &predicate, Arguments &arguments, const Schema &schema, std::string objectType);
|
void apply_predicate(Query &query, const parser::Predicate &predicate, Arguments &arguments, const Schema &schema, const std::string &objectType);
|
||||||
|
|
||||||
class Arguments
|
class Arguments
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual bool bool_for_argument(size_t argument_index) = 0;
|
virtual bool bool_for_argument(size_t argument_index) = 0;
|
||||||
virtual long long long_for_argument(size_t argument_index) = 0;
|
virtual long long long_for_argument(size_t argument_index) = 0;
|
||||||
virtual float float_for_argument(size_t argument_index) = 0;
|
virtual float float_for_argument(size_t argument_index) = 0;
|
||||||
virtual double double_for_argument(size_t argument_index) = 0;
|
virtual double double_for_argument(size_t argument_index) = 0;
|
||||||
virtual std::string string_for_argument(size_t argument_index) = 0;
|
virtual std::string string_for_argument(size_t argument_index) = 0;
|
||||||
virtual std::string binary_for_argument(size_t argument_index) = 0;
|
virtual std::string binary_for_argument(size_t argument_index) = 0;
|
||||||
virtual DateTime datetime_for_argument(size_t argument_index) = 0;
|
virtual DateTime datetime_for_argument(size_t argument_index) = 0;
|
||||||
virtual size_t object_index_for_argument(size_t argument_index) = 0;
|
virtual size_t object_index_for_argument(size_t argument_index) = 0;
|
||||||
virtual bool is_argument_null(size_t argument_index) = 0;
|
virtual bool is_argument_null(size_t argument_index) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ValueType, typename ContextType>
|
template<typename ValueType, typename ContextType>
|
||||||
class ArgumentConverter : public Arguments
|
class ArgumentConverter : public Arguments
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ArgumentConverter(ContextType context, std::vector<ValueType> arguments) : m_arguments(arguments), m_ctx(context) {};
|
ArgumentConverter(ContextType context, std::vector<ValueType> arguments) : m_arguments(arguments), m_ctx(context) {};
|
||||||
|
|
||||||
using Accessor = realm::NativeAccessor<ValueType, ContextType>;
|
using Accessor = realm::NativeAccessor<ValueType, ContextType>;
|
||||||
virtual bool bool_for_argument(size_t argument_index) { return Accessor::to_bool(m_ctx, argument_at(argument_index)); }
|
virtual bool bool_for_argument(size_t argument_index) { return Accessor::to_bool(m_ctx, argument_at(argument_index)); }
|
||||||
virtual long long long_for_argument(size_t argument_index) { return Accessor::to_long(m_ctx, argument_at(argument_index)); }
|
virtual long long long_for_argument(size_t argument_index) { return Accessor::to_long(m_ctx, argument_at(argument_index)); }
|
||||||
virtual float float_for_argument(size_t argument_index) { return Accessor::to_float(m_ctx, argument_at(argument_index)); }
|
virtual float float_for_argument(size_t argument_index) { return Accessor::to_float(m_ctx, argument_at(argument_index)); }
|
||||||
virtual double double_for_argument(size_t argument_index) { return Accessor::to_double(m_ctx, argument_at(argument_index)); }
|
virtual double double_for_argument(size_t argument_index) { return Accessor::to_double(m_ctx, argument_at(argument_index)); }
|
||||||
virtual std::string string_for_argument(size_t argument_index) { return Accessor::to_string(m_ctx, argument_at(argument_index)); }
|
virtual std::string string_for_argument(size_t argument_index) { return Accessor::to_string(m_ctx, argument_at(argument_index)); }
|
||||||
virtual std::string binary_for_argument(size_t argument_index) { return Accessor::to_binary(m_ctx, argument_at(argument_index)); }
|
virtual std::string binary_for_argument(size_t argument_index) { return Accessor::to_binary(m_ctx, argument_at(argument_index)); }
|
||||||
virtual DateTime datetime_for_argument(size_t argument_index) { return Accessor::to_datetime(m_ctx, argument_at(argument_index)); }
|
virtual DateTime datetime_for_argument(size_t argument_index) { return Accessor::to_datetime(m_ctx, argument_at(argument_index)); }
|
||||||
virtual size_t object_index_for_argument(size_t argument_index) { return Accessor::to_existing_object_index(m_ctx, argument_at(argument_index)); }
|
virtual size_t object_index_for_argument(size_t argument_index) { return Accessor::to_existing_object_index(m_ctx, argument_at(argument_index)); }
|
||||||
virtual bool is_argument_null(size_t argument_index) { return Accessor::is_null(m_ctx, argument_at(argument_index)); }
|
virtual bool is_argument_null(size_t argument_index) { return Accessor::is_null(m_ctx, argument_at(argument_index)); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<ValueType> m_arguments;
|
std::vector<ValueType> m_arguments;
|
||||||
ContextType m_ctx;
|
ContextType m_ctx;
|
||||||
|
|
||||||
ValueType &argument_at(size_t index) {
|
ValueType &argument_at(size_t index) {
|
||||||
if (index >= m_arguments.size()) {
|
if (index >= m_arguments.size()) {
|
||||||
throw std::out_of_range((std::string)"Argument index " + std::to_string(index) + " out of range 0.." + std::to_string(m_arguments.size()-1));
|
throw std::out_of_range((std::string)"Argument index " + std::to_string(index) + " out of range 0.." + std::to_string(m_arguments.size()-1));
|
||||||
}
|
}
|
||||||
return m_arguments[index];
|
return m_arguments[index];
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // REALM_QUERY_BUILDER_HPP
|
#endif // REALM_QUERY_BUILDER_HPP
|
||||||
|
|
|
@ -1,6 +1,20 @@
|
||||||
/* Copyright 2015 Realm Inc - All Rights Reserved
|
////////////////////////////////////////////////////////////////////////////
|
||||||
* Proprietary and Confidential
|
//
|
||||||
*/
|
// Copyright 2015 Realm Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "results.hpp"
|
#include "results.hpp"
|
||||||
|
|
||||||
|
@ -26,7 +40,7 @@ Results::Results(SharedRealm r, const ObjectSchema &o, Query q, SortOrder s)
|
||||||
, m_table(m_query.get_table().get())
|
, m_table(m_query.get_table().get())
|
||||||
, m_sort(std::move(s))
|
, m_sort(std::move(s))
|
||||||
, m_mode(Mode::Query)
|
, m_mode(Mode::Query)
|
||||||
, object_schema(o)
|
, m_object_schema(&o)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,21 +48,10 @@ Results::Results(SharedRealm r, const ObjectSchema &o, Table& table)
|
||||||
: m_realm(std::move(r))
|
: m_realm(std::move(r))
|
||||||
, m_table(&table)
|
, m_table(&table)
|
||||||
, m_mode(Mode::Table)
|
, m_mode(Mode::Table)
|
||||||
, object_schema(o)
|
, m_object_schema(&o)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Results& Results::operator=(Results const& r)
|
|
||||||
{
|
|
||||||
m_realm = r.m_realm;
|
|
||||||
m_table = r.m_table;
|
|
||||||
m_sort = r.m_sort;
|
|
||||||
m_query = r.get_query();
|
|
||||||
m_mode = Mode::Query;
|
|
||||||
const_cast<ObjectSchema &>(object_schema) = r.object_schema;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Results::validate_read() const
|
void Results::validate_read() const
|
||||||
{
|
{
|
||||||
if (m_realm)
|
if (m_realm)
|
||||||
|
@ -107,9 +110,8 @@ util::Optional<RowExpr> Results::first()
|
||||||
case Mode::Table:
|
case Mode::Table:
|
||||||
return m_table->size() == 0 ? util::none : util::make_optional(m_table->front());
|
return m_table->size() == 0 ? util::none : util::make_optional(m_table->front());
|
||||||
case Mode::Query:
|
case Mode::Query:
|
||||||
update_tableview();
|
|
||||||
REALM_FALLTHROUGH;
|
|
||||||
case Mode::TableView:
|
case Mode::TableView:
|
||||||
|
update_tableview();
|
||||||
return m_table_view.size() == 0 ? util::none : util::make_optional(m_table_view.front());
|
return m_table_view.size() == 0 ? util::none : util::make_optional(m_table_view.front());
|
||||||
}
|
}
|
||||||
REALM_UNREACHABLE();
|
REALM_UNREACHABLE();
|
||||||
|
@ -124,9 +126,8 @@ util::Optional<RowExpr> Results::last()
|
||||||
case Mode::Table:
|
case Mode::Table:
|
||||||
return m_table->size() == 0 ? util::none : util::make_optional(m_table->back());
|
return m_table->size() == 0 ? util::none : util::make_optional(m_table->back());
|
||||||
case Mode::Query:
|
case Mode::Query:
|
||||||
update_tableview();
|
|
||||||
REALM_FALLTHROUGH;
|
|
||||||
case Mode::TableView:
|
case Mode::TableView:
|
||||||
|
update_tableview();
|
||||||
return m_table_view.size() == 0 ? util::none : util::make_optional(m_table_view.back());
|
return m_table_view.size() == 0 ? util::none : util::make_optional(m_table_view.back());
|
||||||
}
|
}
|
||||||
REALM_UNREACHABLE();
|
REALM_UNREACHABLE();
|
||||||
|
@ -159,9 +160,10 @@ size_t Results::index_of(Row const& row)
|
||||||
throw DetatchedAccessorException{};
|
throw DetatchedAccessorException{};
|
||||||
}
|
}
|
||||||
if (m_table && row.get_table() != m_table) {
|
if (m_table && row.get_table() != m_table) {
|
||||||
throw IncorrectTableException(object_schema.name,
|
throw IncorrectTableException(m_object_schema->name,
|
||||||
ObjectStore::object_type_for_table_name(row.get_table()->get_name()),
|
ObjectStore::object_type_for_table_name(row.get_table()->get_name()),
|
||||||
"Attempting to get the index of a Row of the wrong type");
|
"Attempting to get the index of a Row of the wrong type"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return index_of(row.get_index());
|
return index_of(row.get_index());
|
||||||
}
|
}
|
||||||
|
@ -276,7 +278,7 @@ void Results::clear()
|
||||||
case Mode::TableView:
|
case Mode::TableView:
|
||||||
validate_write();
|
validate_write();
|
||||||
update_tableview();
|
update_tableview();
|
||||||
m_table_view.clear();
|
m_table_view.clear(RemoveMode::unordered);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -313,16 +315,18 @@ TableView Results::get_tableview()
|
||||||
|
|
||||||
Results Results::sort(realm::SortOrder&& sort) const
|
Results Results::sort(realm::SortOrder&& sort) const
|
||||||
{
|
{
|
||||||
return Results(m_realm, object_schema, get_query(), std::move(sort));
|
return Results(m_realm, get_object_schema(), get_query(), std::move(sort));
|
||||||
}
|
}
|
||||||
|
|
||||||
Results Results::filter(Query&& q) const
|
Results Results::filter(Query&& q) const
|
||||||
{
|
{
|
||||||
return Results(m_realm, object_schema, get_query().and_query(std::move(q)), get_sort());
|
return Results(m_realm, get_object_schema(), get_query().and_query(std::move(q)), get_sort());
|
||||||
}
|
}
|
||||||
|
|
||||||
Results::UnsupportedColumnTypeException::UnsupportedColumnTypeException(size_t column, const Table* table) :
|
Results::UnsupportedColumnTypeException::UnsupportedColumnTypeException(size_t column, const Table* table)
|
||||||
column_index(column), column_name(table->get_column_name(column)), column_type(table->get_column_type(column)),
|
: std::runtime_error((std::string)"Operation not supported on '" + table->get_column_name(column).data() + "' columns")
|
||||||
std::runtime_error((std::string)"Operation not supported on '" + table->get_column_name(column).data() + "' columns")
|
, column_index(column)
|
||||||
|
, column_name(table->get_column_name(column))
|
||||||
|
, column_type(table->get_column_type(column))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,20 @@
|
||||||
/* Copyright 2015 Realm Inc - All Rights Reserved
|
////////////////////////////////////////////////////////////////////////////
|
||||||
* Proprietary and Confidential
|
//
|
||||||
*/
|
// Copyright 2015 Realm Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef REALM_RESULTS_HPP
|
#ifndef REALM_RESULTS_HPP
|
||||||
#define REALM_RESULTS_HPP
|
#define REALM_RESULTS_HPP
|
||||||
|
@ -32,20 +46,20 @@ public:
|
||||||
// or a wrapper around a query and a sort order which creates and updates
|
// or a wrapper around a query and a sort order which creates and updates
|
||||||
// the tableview as needed
|
// the tableview as needed
|
||||||
Results() = default;
|
Results() = default;
|
||||||
Results(SharedRealm r, const ObjectSchema &o, Table& table);
|
Results(SharedRealm r, const ObjectSchema& o, Table& table);
|
||||||
Results(SharedRealm r, const ObjectSchema &o, Query q, SortOrder s = {});
|
Results(SharedRealm r, const ObjectSchema& o, Query q, SortOrder s = {});
|
||||||
|
|
||||||
// Results is copyable and moveable
|
// Results is copyable and moveable
|
||||||
Results(Results const&) = default;
|
Results(Results const&) = default;
|
||||||
Results(Results&&) = default;
|
Results(Results&&) = default;
|
||||||
Results& operator=(Results&&) = default;
|
Results& operator=(Results&&) = default;
|
||||||
Results& operator=(Results const&);
|
Results& operator=(Results const&) = default;
|
||||||
|
|
||||||
// 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 &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
|
||||||
|
@ -58,7 +72,7 @@ public:
|
||||||
TableView get_tableview();
|
TableView get_tableview();
|
||||||
|
|
||||||
// Get the object type which will be returned by get()
|
// Get the object type which will be returned by get()
|
||||||
StringData get_object_type() const noexcept { return object_schema.name; }
|
StringData get_object_type() const noexcept { return get_object_schema().name; }
|
||||||
|
|
||||||
// Get the size of this results
|
// Get the size of this results
|
||||||
// Can be either O(1) or O(N) depending on the state of things
|
// Can be either O(1) or O(N) depending on the state of things
|
||||||
|
@ -149,6 +163,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SharedRealm m_realm;
|
SharedRealm m_realm;
|
||||||
|
const ObjectSchema *m_object_schema;
|
||||||
Query m_query;
|
Query m_query;
|
||||||
TableView m_table_view;
|
TableView m_table_view;
|
||||||
Table* m_table = nullptr;
|
Table* m_table = nullptr;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#ifndef REALM_SCHEMA_HPP
|
#ifndef REALM_SCHEMA_HPP
|
||||||
#define REALM_SCHEMA_HPP
|
#define REALM_SCHEMA_HPP
|
||||||
|
|
||||||
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace realm {
|
namespace realm {
|
||||||
|
|
|
@ -38,6 +38,7 @@ Realm::Config::Config(const Config& c)
|
||||||
, read_only(c.read_only)
|
, read_only(c.read_only)
|
||||||
, in_memory(c.in_memory)
|
, in_memory(c.in_memory)
|
||||||
, cache(c.cache)
|
, cache(c.cache)
|
||||||
|
, disable_format_upgrade(c.disable_format_upgrade)
|
||||||
, encryption_key(c.encryption_key)
|
, encryption_key(c.encryption_key)
|
||||||
, schema_version(c.schema_version)
|
, schema_version(c.schema_version)
|
||||||
, migration_function(c.migration_function)
|
, migration_function(c.migration_function)
|
||||||
|
@ -71,7 +72,7 @@ Realm::Realm(Config config)
|
||||||
m_history = realm::make_client_history(m_config.path, m_config.encryption_key.data());
|
m_history = realm::make_client_history(m_config.path, m_config.encryption_key.data());
|
||||||
SharedGroup::DurabilityLevel durability = m_config.in_memory ? SharedGroup::durability_MemOnly :
|
SharedGroup::DurabilityLevel durability = m_config.in_memory ? SharedGroup::durability_MemOnly :
|
||||||
SharedGroup::durability_Full;
|
SharedGroup::durability_Full;
|
||||||
m_shared_group = std::make_unique<SharedGroup>(*m_history, durability, m_config.encryption_key.data());
|
m_shared_group = std::make_unique<SharedGroup>(*m_history, durability, m_config.encryption_key.data(), !m_config.disable_format_upgrade);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (util::File::PermissionDenied const& ex) {
|
catch (util::File::PermissionDenied const& ex) {
|
||||||
|
@ -92,6 +93,11 @@ Realm::Realm(Config config)
|
||||||
"Realm file is currently open in another process "
|
"Realm file is currently open in another process "
|
||||||
"which cannot share access with this process. All processes sharing a single file must be the same architecture.");
|
"which cannot share access with this process. All processes sharing a single file must be the same architecture.");
|
||||||
}
|
}
|
||||||
|
catch (FileFormatUpgradeRequired const& ex) {
|
||||||
|
throw RealmFileException(RealmFileException::Kind::FormatUpgradeRequired, m_config.path,
|
||||||
|
"The Realm file format must be allowed to be upgraded "
|
||||||
|
"in order to proceed.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Realm::~Realm() {
|
Realm::~Realm() {
|
||||||
|
@ -165,12 +171,19 @@ SharedRealm Realm::get_shared_realm(Config config)
|
||||||
throw UnitializedRealmException("Can't open an un-initialized Realm without a Schema");
|
throw UnitializedRealmException("Can't open an un-initialized Realm without a Schema");
|
||||||
}
|
}
|
||||||
target_schema->validate();
|
target_schema->validate();
|
||||||
ObjectStore::verify_schema(*realm->m_config.schema, const_cast<Schema &>(*target_schema), true);
|
ObjectStore::verify_schema(*realm->m_config.schema, *target_schema, true);
|
||||||
realm->m_config.schema = std::move(target_schema);
|
realm->m_config.schema = std::move(target_schema);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
realm->update_schema(std::move(target_schema), target_schema_version);
|
realm->update_schema(std::move(target_schema), target_schema_version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!realm->m_config.read_only) {
|
||||||
|
// End the read transaction created to validation/update the
|
||||||
|
// schema to avoid pinning the version even if the user never
|
||||||
|
// actually reads data
|
||||||
|
realm->invalidate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,13 +193,13 @@ SharedRealm Realm::get_shared_realm(Config config)
|
||||||
return realm;
|
return realm;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Realm::update_schema(std::unique_ptr<const Schema> schema, uint64_t version)
|
bool Realm::update_schema(std::unique_ptr<Schema> schema, uint64_t version)
|
||||||
{
|
{
|
||||||
schema->validate();
|
schema->validate();
|
||||||
|
|
||||||
bool needs_update = !m_config.read_only && (m_config.schema_version != version || ObjectStore::needs_update(*m_config.schema, *schema));
|
bool needs_update = !m_config.read_only && (m_config.schema_version != version || ObjectStore::needs_update(*m_config.schema, *schema));
|
||||||
if (!needs_update) {
|
if (!needs_update) {
|
||||||
ObjectStore::verify_schema(*m_config.schema, const_cast<Schema &>(*schema), m_config.read_only);
|
ObjectStore::verify_schema(*m_config.schema, *schema, m_config.read_only);
|
||||||
m_config.schema = std::move(schema);
|
m_config.schema = std::move(schema);
|
||||||
m_config.schema_version = version;
|
m_config.schema_version = version;
|
||||||
return false;
|
return false;
|
||||||
|
@ -199,6 +212,9 @@ bool Realm::update_schema(std::unique_ptr<const Schema> schema, uint64_t version
|
||||||
old_config.read_only = true;
|
old_config.read_only = true;
|
||||||
old_config.schema = std::move(old_schema);
|
old_config.schema = std::move(old_schema);
|
||||||
|
|
||||||
|
m_config.schema = std::move(schema);
|
||||||
|
m_config.schema_version = version;
|
||||||
|
|
||||||
auto migration_function = [&](Group*, Schema&) {
|
auto migration_function = [&](Group*, Schema&) {
|
||||||
SharedRealm old_realm(new Realm(old_config));
|
SharedRealm old_realm(new Realm(old_config));
|
||||||
auto updated_realm = shared_from_this();
|
auto updated_realm = shared_from_this();
|
||||||
|
@ -211,9 +227,8 @@ bool Realm::update_schema(std::unique_ptr<const Schema> schema, uint64_t version
|
||||||
// update and migrate
|
// update and migrate
|
||||||
begin_transaction();
|
begin_transaction();
|
||||||
bool changed = ObjectStore::update_realm_with_schema(read_group(), *old_config.schema,
|
bool changed = ObjectStore::update_realm_with_schema(read_group(), *old_config.schema,
|
||||||
version, const_cast<Schema &>(*schema), migration_function);
|
version, *m_config.schema,
|
||||||
m_config.schema = std::move(schema);
|
migration_function);
|
||||||
m_config.schema_version = version;
|
|
||||||
commit_transaction();
|
commit_transaction();
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,12 +19,13 @@
|
||||||
#ifndef REALM_REALM_HPP
|
#ifndef REALM_REALM_HPP
|
||||||
#define REALM_REALM_HPP
|
#define REALM_REALM_HPP
|
||||||
|
|
||||||
|
#include "object_store.hpp"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "object_store.hpp"
|
|
||||||
|
|
||||||
namespace realm {
|
namespace realm {
|
||||||
class ClientHistory;
|
class ClientHistory;
|
||||||
class Realm;
|
class Realm;
|
||||||
|
@ -48,9 +49,10 @@ namespace realm {
|
||||||
bool read_only = false;
|
bool read_only = false;
|
||||||
bool in_memory = false;
|
bool in_memory = false;
|
||||||
bool cache = true;
|
bool cache = true;
|
||||||
|
bool disable_format_upgrade = false;
|
||||||
std::vector<char> encryption_key;
|
std::vector<char> encryption_key;
|
||||||
|
|
||||||
std::unique_ptr<const Schema> schema;
|
std::unique_ptr<Schema> schema;
|
||||||
uint64_t schema_version = ObjectStore::NotVersioned;
|
uint64_t schema_version = ObjectStore::NotVersioned;
|
||||||
|
|
||||||
MigrationFunction migration_function;
|
MigrationFunction migration_function;
|
||||||
|
@ -78,7 +80,7 @@ namespace realm {
|
||||||
// on the Config, and the resulting Schema and version with updated
|
// on the Config, and the resulting Schema and version with updated
|
||||||
// column mappings are set on the realms config upon success.
|
// column mappings are set on the realms config upon success.
|
||||||
// returns if any changes were made
|
// returns if any changes were made
|
||||||
bool update_schema(std::unique_ptr<const Schema> schema, uint64_t version);
|
bool update_schema(std::unique_ptr<Schema> schema, uint64_t version);
|
||||||
|
|
||||||
static uint64_t get_schema_version(Config const& config);
|
static uint64_t get_schema_version(Config const& config);
|
||||||
|
|
||||||
|
@ -88,6 +90,7 @@ namespace realm {
|
||||||
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 { return m_in_transaction; }
|
||||||
|
bool is_in_read_transaction() const { return !!m_group; }
|
||||||
|
|
||||||
bool refresh();
|
bool refresh();
|
||||||
void set_auto_refresh(bool auto_refresh) { m_auto_refresh = auto_refresh; }
|
void set_auto_refresh(bool auto_refresh) { m_auto_refresh = auto_refresh; }
|
||||||
|
@ -161,6 +164,8 @@ namespace realm {
|
||||||
process which cannot share with the current process due to an
|
process which cannot share with the current process due to an
|
||||||
architecture mismatch. */
|
architecture mismatch. */
|
||||||
IncompatibleLockFile,
|
IncompatibleLockFile,
|
||||||
|
/** Thrown if the file needs to be upgraded to a new format, but upgrades have been explicitly disabled. */
|
||||||
|
FormatUpgradeRequired,
|
||||||
};
|
};
|
||||||
RealmFileException(Kind kind, std::string path, std::string message) :
|
RealmFileException(Kind kind, std::string path, std::string message) :
|
||||||
std::runtime_error(std::move(message)), m_kind(kind), m_path(std::move(path)) {}
|
std::runtime_error(std::move(message)), m_kind(kind), m_path(std::move(path)) {}
|
||||||
|
|
|
@ -220,7 +220,7 @@ json RPCServer::serialize_json_value(JSValueRef value) {
|
||||||
return {
|
return {
|
||||||
{"type", RJSTypeGet(realm::PropertyTypeObject)},
|
{"type", RJSTypeGet(realm::PropertyTypeObject)},
|
||||||
{"id", store_object(js_object)},
|
{"id", store_object(js_object)},
|
||||||
{"schema", serialize_object_schema(object->object_schema)}
|
{"schema", serialize_object_schema(object->get_object_schema())}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else if (JSValueIsObjectOfClass(m_context, value, RJSListClass())) {
|
else if (JSValueIsObjectOfClass(m_context, value, RJSListClass())) {
|
||||||
|
@ -229,7 +229,7 @@ json RPCServer::serialize_json_value(JSValueRef value) {
|
||||||
{"type", RJSTypeGet(realm::PropertyTypeArray)},
|
{"type", RJSTypeGet(realm::PropertyTypeArray)},
|
||||||
{"id", store_object(js_object)},
|
{"id", store_object(js_object)},
|
||||||
{"size", list->size()},
|
{"size", list->size()},
|
||||||
{"schema", serialize_object_schema(list->object_schema)}
|
{"schema", serialize_object_schema(list->get_object_schema())}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else if (JSValueIsObjectOfClass(m_context, value, RJSResultsClass())) {
|
else if (JSValueIsObjectOfClass(m_context, value, RJSResultsClass())) {
|
||||||
|
@ -238,7 +238,7 @@ json RPCServer::serialize_json_value(JSValueRef value) {
|
||||||
{"type", RealmObjectTypesResults},
|
{"type", RealmObjectTypesResults},
|
||||||
{"id", store_object(js_object)},
|
{"id", store_object(js_object)},
|
||||||
{"size", results->size()},
|
{"size", results->size()},
|
||||||
{"schema", serialize_object_schema(results->object_schema)}
|
{"schema", serialize_object_schema(results->get_object_schema())}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else if (RJSIsValueArray(m_context, value)) {
|
else if (RJSIsValueArray(m_context, value)) {
|
||||||
|
|
Loading…
Reference in New Issue