Merge branch '2.0.x' into kneth/v1_v2-upgrade
This commit is contained in:
commit
6349d22f55
43
CHANGELOG.md
43
CHANGELOG.md
|
@ -1,16 +1,33 @@
|
||||||
x.x.x Release notes (yyyy-MM-dd)
|
X.Y.Z-rc Release notes
|
||||||
=============================================================
|
=============================================================
|
||||||
### Breaking changes
|
### Breaking changes
|
||||||
* None.
|
* None
|
||||||
|
|
||||||
### Enhancements
|
### Enhancements
|
||||||
* None.
|
* Support migration from Realms sync 1.0 to sync 2.0 versions
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
* None
|
||||||
|
|
||||||
|
2.0.0-rc16 Release notes (2017-9-29)
|
||||||
|
=============================================================
|
||||||
|
### Breaking changes
|
||||||
|
* Upgtading to Realm Core 4.0.1 (bug fixes)
|
||||||
|
* Upgrading to Realm Sync 2.0.0-rc26 (sync protocol 22 + bug fixes)
|
||||||
|
|
||||||
|
2.0.0-rc14 Release notes (2017-9-29)
|
||||||
|
=============================================================
|
||||||
|
### Breaking changes
|
||||||
|
* Upgrading to Realm Core 4.0.0 and Realm Sync 2.0.0-rc25.
|
||||||
|
|
||||||
|
### Enhancements
|
||||||
|
** Support Realm migration from sync 1.0 to sync 2.0 version
|
||||||
|
|
||||||
### Bug fixes
|
### Bug fixes
|
||||||
* Configuration of sync file system is not done on module import but later when actually needed by sync (#1351)
|
* Configuration of sync file system is not done on module import but later when actually needed by sync (#1351)
|
||||||
|
|
||||||
|
|
||||||
2.0.0 Release notes (2017-9-28)
|
2.0.0-rc12 Release notes (2017-9-28)
|
||||||
=============================================================
|
=============================================================
|
||||||
### Breaking changes
|
### Breaking changes
|
||||||
* None.
|
* None.
|
||||||
|
@ -27,18 +44,22 @@ x.x.x Release notes (yyyy-MM-dd)
|
||||||
### Breaking changes
|
### Breaking changes
|
||||||
* None
|
* None
|
||||||
|
|
||||||
### Enhancements
|
|
||||||
* Add a callback function used to verify SSL certificates in the sync config.
|
|
||||||
* Throw exception with recovery configuration when upgrading from 1.x to 2.x.
|
|
||||||
|
|
||||||
### Bug fixes
|
|
||||||
* Fixed port conflict between RN >= 0.48 inspector proxy and RPC server used for Chrome debugging (#1294).
|
|
||||||
|
|
||||||
### Internal
|
### Internal
|
||||||
* Alignment of permission schemas.
|
* Alignment of permission schemas.
|
||||||
* Updating sync (2.0.0-rc24).
|
* Updating sync (2.0.0-rc24).
|
||||||
|
|
||||||
|
1.13.0 Release notes (to be released)
|
||||||
|
=============================================================
|
||||||
|
### Breaking changes
|
||||||
|
* None.
|
||||||
|
|
||||||
|
### Enhancements
|
||||||
|
* Add a callback function used to verify SSL certificates in the sync config.
|
||||||
|
* Added aggregate functions `min()`, `max()`, `sum()`, and `avg()` to `Realm.Results` and `Realm.List` (#807).
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
* Fixed port conflict between RN >= 0.48 inspector proxy and RPC server used for Chrome debugging (#1294).
|
||||||
|
* Workaround for RN >= 0.49 metro-bundler check for single string literal argument to `require()` (#1342)
|
||||||
|
|
||||||
|
|
||||||
2.0.0-rc10 Release notes (2017-9-19)
|
2.0.0-rc10 Release notes (2017-9-19)
|
||||||
|
|
|
@ -92,6 +92,7 @@
|
||||||
"src/object-store/src/sync/sync_manager.cpp",
|
"src/object-store/src/sync/sync_manager.cpp",
|
||||||
"src/object-store/src/sync/sync_user.cpp",
|
"src/object-store/src/sync/sync_user.cpp",
|
||||||
"src/object-store/src/sync/sync_session.cpp",
|
"src/object-store/src/sync/sync_session.cpp",
|
||||||
|
"src/object-store/src/sync/sync_config.cpp",
|
||||||
"src/object-store/src/sync/impl/sync_file.cpp",
|
"src/object-store/src/sync/impl/sync_file.cpp",
|
||||||
"src/object-store/src/sync/impl/sync_metadata.cpp"
|
"src/object-store/src/sync/impl/sync_metadata.cpp"
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
PACKAGE_NAME=realm-js
|
PACKAGE_NAME=realm-js
|
||||||
VERSION=2.0.0-rc13
|
VERSION=2.0.0-rc16
|
||||||
REALM_CORE_VERSION=3.2.1
|
REALM_CORE_VERSION=4.0.1
|
||||||
REALM_SYNC_VERSION=2.0.0-rc24
|
REALM_SYNC_VERSION=2.0.0-rc26
|
||||||
REALM_OBJECT_SERVER_VERSION=2.0.0-alpha.40
|
REALM_OBJECT_SERVER_VERSION=2.0.0-alpha.42
|
||||||
|
|
|
@ -233,6 +233,42 @@ class Collection {
|
||||||
*/
|
*/
|
||||||
indexOf(object) {}
|
indexOf(object) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the minimum value of a property.
|
||||||
|
* @param {string} property - The name of the property.
|
||||||
|
* @throws {Error} If no property with the name exists or if property is not numeric/date.
|
||||||
|
* @returns {number} the minimum value.
|
||||||
|
* @since 1.12.1
|
||||||
|
*/
|
||||||
|
min(property) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the maximum value of a property.
|
||||||
|
* @param {string} property - The name of the property.
|
||||||
|
* @throws {Error} If no property with the name exists or if property is not numeric/date.
|
||||||
|
* @returns {number} the maximum value.
|
||||||
|
* @since 1.12.1
|
||||||
|
*/
|
||||||
|
max(property) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the sum of a property.
|
||||||
|
* @param {string} property - The name of the property.
|
||||||
|
* @throws {Error} If no property with the name exists or if property is not numeric/date.
|
||||||
|
* @returns {number} the sum.
|
||||||
|
* @since 1.12.1
|
||||||
|
*/
|
||||||
|
sum(property) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the average of a property.
|
||||||
|
* @param {string} property - The name of the property.
|
||||||
|
* @throws {Error} If no property with the name exists or if property is not numeric/date.
|
||||||
|
* @returns {number} the average value.
|
||||||
|
* @since 1.12.1
|
||||||
|
*/
|
||||||
|
avg(property) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach Array.prototype.forEach}
|
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach Array.prototype.forEach}
|
||||||
* @param {function} callback - Function to execute on each object in the collection.
|
* @param {function} callback - Function to execute on each object in the collection.
|
||||||
|
|
|
@ -32,6 +32,10 @@ createMethods(List.prototype, objectTypes.LIST, [
|
||||||
'snapshot',
|
'snapshot',
|
||||||
'isValid',
|
'isValid',
|
||||||
'indexOf',
|
'indexOf',
|
||||||
|
'min',
|
||||||
|
'max',
|
||||||
|
'sum',
|
||||||
|
'avg',
|
||||||
'addListener',
|
'addListener',
|
||||||
'removeListener',
|
'removeListener',
|
||||||
'removeAllListeners',
|
'removeAllListeners',
|
||||||
|
|
|
@ -31,6 +31,10 @@ createMethods(Results.prototype, objectTypes.RESULTS, [
|
||||||
'snapshot',
|
'snapshot',
|
||||||
'isValid',
|
'isValid',
|
||||||
'indexOf',
|
'indexOf',
|
||||||
|
'min',
|
||||||
|
'max',
|
||||||
|
'sum',
|
||||||
|
'avg',
|
||||||
'addListener',
|
'addListener',
|
||||||
'removeListener',
|
'removeListener',
|
||||||
'removeAllListeners',
|
'removeAllListeners',
|
||||||
|
|
|
@ -120,7 +120,7 @@ declare namespace Realm {
|
||||||
* SortDescriptor
|
* SortDescriptor
|
||||||
* @see { @link https://realm.io/docs/javascript/latest/api/Realm.Collection.html#~SortDescriptor }
|
* @see { @link https://realm.io/docs/javascript/latest/api/Realm.Collection.html#~SortDescriptor }
|
||||||
*/
|
*/
|
||||||
type SortDescriptor = string | [string, boolean] | any[];
|
type SortDescriptor = [string] | [string, boolean];
|
||||||
|
|
||||||
interface CollectionChangeSet {
|
interface CollectionChangeSet {
|
||||||
insertions: number[];
|
insertions: number[];
|
||||||
|
@ -135,11 +135,42 @@ declare namespace Realm {
|
||||||
* @see { @link https://realm.io/docs/javascript/latest/api/Realm.Collection.html }
|
* @see { @link https://realm.io/docs/javascript/latest/api/Realm.Collection.html }
|
||||||
*/
|
*/
|
||||||
interface Collection<T> extends ReadonlyArray<T> {
|
interface Collection<T> extends ReadonlyArray<T> {
|
||||||
|
readonly type: PropertyType;
|
||||||
|
readonly optional: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns boolean
|
* @returns boolean
|
||||||
*/
|
*/
|
||||||
isValid(): boolean;
|
isValid(): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the minimum value.
|
||||||
|
* @param {string} property
|
||||||
|
* @returns number
|
||||||
|
*/
|
||||||
|
min(property: string): number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the maximum value.
|
||||||
|
* @param {string} property
|
||||||
|
* @returns number
|
||||||
|
*/
|
||||||
|
max(property: string): number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the sum.
|
||||||
|
* @param {string} property
|
||||||
|
* @returns number
|
||||||
|
*/
|
||||||
|
sum(property: string): number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the average.
|
||||||
|
* @param {string} property
|
||||||
|
* @returns number
|
||||||
|
*/
|
||||||
|
avg(property: string): number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} query
|
* @param {string} query
|
||||||
* @param {any[]} ...arg
|
* @param {any[]} ...arg
|
||||||
|
@ -147,12 +178,9 @@ declare namespace Realm {
|
||||||
*/
|
*/
|
||||||
filtered(query: string, ...arg: any[]): Results<T>;
|
filtered(query: string, ...arg: any[]): Results<T>;
|
||||||
|
|
||||||
/**
|
sorted(reverse?: boolean): Results<T>;
|
||||||
* @param {string|SortDescriptor} descriptor
|
sorted(descriptor: SortDescriptor[]): Results<T>;
|
||||||
* @param {boolean} reverse?
|
sorted(descriptor: string, reverse?: boolean): Results<T>;
|
||||||
* @returns Results
|
|
||||||
*/
|
|
||||||
sorted(descriptor: string | SortDescriptor, reverse?: boolean): Results<T>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns Results
|
* @returns Results
|
||||||
|
@ -188,22 +216,21 @@ declare namespace Realm {
|
||||||
interface List<T> extends Collection<T> {
|
interface List<T> extends Collection<T> {
|
||||||
[n: number]: T;
|
[n: number]: T;
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns T
|
|
||||||
*/
|
|
||||||
pop(): T | null | undefined;
|
pop(): T | null | undefined;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {T} object
|
* @param {T} object
|
||||||
* @returns number
|
* @returns number
|
||||||
*/
|
*/
|
||||||
push(object: T): number;
|
push(...object: T[]): number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns T
|
* @returns T
|
||||||
*/
|
*/
|
||||||
shift(): T | null | undefined;
|
shift(): T | null | undefined;
|
||||||
|
|
||||||
|
unshift(...object: T[]): number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {number} index
|
* @param {number} index
|
||||||
* @param {number} count?
|
* @param {number} count?
|
||||||
|
@ -211,12 +238,6 @@ declare namespace Realm {
|
||||||
* @returns T
|
* @returns T
|
||||||
*/
|
*/
|
||||||
splice(index: number, count?: number, object?: any): T[];
|
splice(index: number, count?: number, object?: any): T[];
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {T} object
|
|
||||||
* @returns number
|
|
||||||
*/
|
|
||||||
unshift(object: T): number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const List: {
|
const List: {
|
||||||
|
@ -296,8 +317,7 @@ declare namespace Realm.Sync {
|
||||||
}
|
}
|
||||||
|
|
||||||
type PermissionCondition = {
|
type PermissionCondition = {
|
||||||
userId: string |
|
userId: string | { metadataKey: string, metadataValue: string }
|
||||||
{ metadataKey: string, metadataValue: string }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type AccessLevel = 'none' | 'read' | 'write' | 'admin';
|
type AccessLevel = 'none' | 'read' | 'write' | 'admin';
|
||||||
|
|
|
@ -18,9 +18,11 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const require_method = require;
|
||||||
|
|
||||||
// Prevent React Native packager from seeing modules required with this
|
// Prevent React Native packager from seeing modules required with this
|
||||||
function nodeRequire(module) {
|
function nodeRequire(module) {
|
||||||
return require(module);
|
return require_method(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getContext() {
|
function getContext() {
|
||||||
|
@ -91,7 +93,7 @@ switch(getContext()) {
|
||||||
var pkg = path.resolve(path.join(__dirname,'../package.json'));
|
var pkg = path.resolve(path.join(__dirname,'../package.json'));
|
||||||
var binding_path = binary.find(pkg);
|
var binding_path = binary.find(pkg);
|
||||||
|
|
||||||
realmConstructor = require(binding_path).Realm;
|
realmConstructor = require_method(binding_path).Realm;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'reactnative':
|
case 'reactnative':
|
||||||
|
|
|
@ -21,8 +21,10 @@
|
||||||
const AuthError = require('./errors').AuthError;
|
const AuthError = require('./errors').AuthError;
|
||||||
const permissionApis = require('./permission-api');
|
const permissionApis = require('./permission-api');
|
||||||
|
|
||||||
|
const require_method = require;
|
||||||
|
|
||||||
function node_require(module) {
|
function node_require(module) {
|
||||||
return require(module);
|
return require_method(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkTypes(args, types) {
|
function checkTypes(args, types) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "realm",
|
"name": "realm",
|
||||||
"description": "Realm is a mobile database: an alternative to SQLite and key-value stores",
|
"description": "Realm is a mobile database: an alternative to SQLite and key-value stores",
|
||||||
"version": "2.0.0-rc13",
|
"version": "2.0.0-rc16",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"homepage": "https://realm.io",
|
"homepage": "https://realm.io",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
|
|
@ -58,6 +58,7 @@ ifeq ($(strip $(BUILD_TYPE_SYNC)),1)
|
||||||
LOCAL_SRC_FILES += src/object-store/src/sync/sync_manager.cpp
|
LOCAL_SRC_FILES += src/object-store/src/sync/sync_manager.cpp
|
||||||
LOCAL_SRC_FILES += src/object-store/src/sync/sync_session.cpp
|
LOCAL_SRC_FILES += src/object-store/src/sync/sync_session.cpp
|
||||||
LOCAL_SRC_FILES += src/object-store/src/sync/sync_user.cpp
|
LOCAL_SRC_FILES += src/object-store/src/sync/sync_user.cpp
|
||||||
|
LOCAL_SRC_FILES += src/object-store/src/sync/sync_config.cpp
|
||||||
LOCAL_SRC_FILES += src/object-store/src/sync/impl/sync_file.cpp
|
LOCAL_SRC_FILES += src/object-store/src/sync/impl/sync_file.cpp
|
||||||
LOCAL_SRC_FILES += src/object-store/src/sync/impl/sync_metadata.cpp
|
LOCAL_SRC_FILES += src/object-store/src/sync/impl/sync_metadata.cpp
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
50C671001E1D2D31003CB63C /* thread_safe_reference.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5D02C7791E1C83650048C13E /* thread_safe_reference.cpp */; };
|
50C671001E1D2D31003CB63C /* thread_safe_reference.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5D02C7791E1C83650048C13E /* thread_safe_reference.cpp */; };
|
||||||
5D1BF0571EF1DB4800B7DC87 /* jsc_value.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5D1BF0561EF1DB4800B7DC87 /* jsc_value.cpp */; };
|
5D1BF0571EF1DB4800B7DC87 /* jsc_value.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5D1BF0561EF1DB4800B7DC87 /* jsc_value.cpp */; };
|
||||||
5D25F5A11D6284FD00EBBB30 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = F63FF3301C16434400B3B8E0 /* libz.tbd */; };
|
5D25F5A11D6284FD00EBBB30 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = F63FF3301C16434400B3B8E0 /* libz.tbd */; };
|
||||||
|
5D97DC4E1F7DAB1400B856A4 /* sync_config.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 426FCDFF1F7DA2F9005565DC /* sync_config.cpp */; };
|
||||||
8507156E1E2CFCD000E548DB /* object_notifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8507156B1E2CFC0100E548DB /* object_notifier.cpp */; };
|
8507156E1E2CFCD000E548DB /* object_notifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8507156B1E2CFC0100E548DB /* object_notifier.cpp */; };
|
||||||
F61378791C18EAC5008BFC51 /* js in Resources */ = {isa = PBXBuildFile; fileRef = F61378781C18EAAC008BFC51 /* js */; };
|
F61378791C18EAC5008BFC51 /* js in Resources */ = {isa = PBXBuildFile; fileRef = F61378781C18EAAC008BFC51 /* js */; };
|
||||||
F63FF2C61C12469E00B3B8E0 /* jsc_init.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 029048011C0428DF00ABDED4 /* jsc_init.cpp */; };
|
F63FF2C61C12469E00B3B8E0 /* jsc_init.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 029048011C0428DF00ABDED4 /* jsc_init.cpp */; };
|
||||||
|
@ -193,6 +194,7 @@
|
||||||
3FCE2A951F58BE1D00D4855B /* sync_permission.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sync_permission.cpp; path = src/sync/sync_permission.cpp; sourceTree = "<group>"; };
|
3FCE2A951F58BE1D00D4855B /* sync_permission.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sync_permission.cpp; path = src/sync/sync_permission.cpp; sourceTree = "<group>"; };
|
||||||
3FCE2A981F58BE3600D4855B /* descriptor_ordering.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = descriptor_ordering.hpp; path = "object-store/src/descriptor_ordering.hpp"; sourceTree = SOURCE_ROOT; };
|
3FCE2A981F58BE3600D4855B /* descriptor_ordering.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = descriptor_ordering.hpp; path = "object-store/src/descriptor_ordering.hpp"; sourceTree = SOURCE_ROOT; };
|
||||||
3FCE2A991F58BE3600D4855B /* feature_checks.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = feature_checks.hpp; path = "object-store/src/feature_checks.hpp"; sourceTree = SOURCE_ROOT; };
|
3FCE2A991F58BE3600D4855B /* feature_checks.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = feature_checks.hpp; path = "object-store/src/feature_checks.hpp"; sourceTree = SOURCE_ROOT; };
|
||||||
|
426FCDFF1F7DA2F9005565DC /* sync_config.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sync_config.cpp; path = src/sync/sync_config.cpp; sourceTree = "<group>"; };
|
||||||
502B07E31E2CD1FA007A84ED /* object.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = object.cpp; path = src/object.cpp; sourceTree = "<group>"; };
|
502B07E31E2CD1FA007A84ED /* object.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = object.cpp; path = src/object.cpp; sourceTree = "<group>"; };
|
||||||
502B07E51E2CD20D007A84ED /* object.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = object.hpp; path = src/object.hpp; sourceTree = "<group>"; };
|
502B07E51E2CD20D007A84ED /* object.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = object.hpp; path = src/object.hpp; sourceTree = "<group>"; };
|
||||||
504CF8541EBCAE3600A9A4B6 /* network_reachability_observer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = network_reachability_observer.cpp; sourceTree = "<group>"; };
|
504CF8541EBCAE3600A9A4B6 /* network_reachability_observer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = network_reachability_observer.cpp; sourceTree = "<group>"; };
|
||||||
|
@ -462,6 +464,7 @@
|
||||||
02E315CC1DB80DE000555337 /* sync */ = {
|
02E315CC1DB80DE000555337 /* sync */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
426FCDFF1F7DA2F9005565DC /* sync_config.cpp */,
|
||||||
504CF8521EBCAE3600A9A4B6 /* impl */,
|
504CF8521EBCAE3600A9A4B6 /* impl */,
|
||||||
02E315CD1DB80DF200555337 /* sync_client.hpp */,
|
02E315CD1DB80DF200555337 /* sync_client.hpp */,
|
||||||
02E315C21DB80DDD00555337 /* sync_config.hpp */,
|
02E315C21DB80DDD00555337 /* sync_config.hpp */,
|
||||||
|
@ -930,6 +933,7 @@
|
||||||
F63FF2CD1C12469E00B3B8E0 /* rpc.cpp in Sources */,
|
F63FF2CD1C12469E00B3B8E0 /* rpc.cpp in Sources */,
|
||||||
02F59EC41C88F17D007F774C /* schema.cpp in Sources */,
|
02F59EC41C88F17D007F774C /* schema.cpp in Sources */,
|
||||||
02F59EC51C88F17D007F774C /* shared_realm.cpp in Sources */,
|
02F59EC51C88F17D007F774C /* shared_realm.cpp in Sources */,
|
||||||
|
5D97DC4E1F7DAB1400B856A4 /* sync_config.cpp in Sources */,
|
||||||
504CF8601EBCAE3600A9A4B6 /* sync_file.cpp in Sources */,
|
504CF8601EBCAE3600A9A4B6 /* sync_file.cpp in Sources */,
|
||||||
02E315D21DB80DF200555337 /* sync_file.cpp in Sources */,
|
02E315D21DB80DF200555337 /* sync_file.cpp in Sources */,
|
||||||
02E315C91DB80DDD00555337 /* sync_manager.cpp in Sources */,
|
02E315C91DB80DDD00555337 /* sync_manager.cpp in Sources */,
|
||||||
|
|
|
@ -47,6 +47,7 @@ class List : public realm::List {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct ListClass : ClassDefinition<T, realm::js::List<T>, CollectionClass<T>> {
|
struct ListClass : ClassDefinition<T, realm::js::List<T>, CollectionClass<T>> {
|
||||||
|
using Type = T;
|
||||||
using ContextType = typename T::Context;
|
using ContextType = typename T::Context;
|
||||||
using ObjectType = typename T::Object;
|
using ObjectType = typename T::Object;
|
||||||
using ValueType = typename T::Value;
|
using ValueType = typename T::Value;
|
||||||
|
@ -77,6 +78,12 @@ struct ListClass : ClassDefinition<T, realm::js::List<T>, CollectionClass<T>> {
|
||||||
static void is_valid(ContextType, ObjectType, Arguments, ReturnValue &);
|
static void is_valid(ContextType, ObjectType, Arguments, ReturnValue &);
|
||||||
static void index_of(ContextType, ObjectType, Arguments, ReturnValue &);
|
static void index_of(ContextType, ObjectType, Arguments, ReturnValue &);
|
||||||
|
|
||||||
|
// aggregate functions
|
||||||
|
static void min(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
||||||
|
static void max(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
||||||
|
static void sum(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
||||||
|
static void avg(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
||||||
|
|
||||||
// observable
|
// observable
|
||||||
static void add_listener(ContextType, ObjectType, Arguments, ReturnValue &);
|
static void add_listener(ContextType, ObjectType, Arguments, ReturnValue &);
|
||||||
static void remove_listener(ContextType, ObjectType, Arguments, ReturnValue &);
|
static void remove_listener(ContextType, ObjectType, Arguments, ReturnValue &);
|
||||||
|
@ -95,6 +102,10 @@ struct ListClass : ClassDefinition<T, realm::js::List<T>, CollectionClass<T>> {
|
||||||
{"sorted", wrap<sorted>},
|
{"sorted", wrap<sorted>},
|
||||||
{"isValid", wrap<is_valid>},
|
{"isValid", wrap<is_valid>},
|
||||||
{"indexOf", wrap<index_of>},
|
{"indexOf", wrap<index_of>},
|
||||||
|
{"min", wrap<min>},
|
||||||
|
{"max", wrap<max>},
|
||||||
|
{"sum", wrap<sum>},
|
||||||
|
{"avg", wrap<avg>},
|
||||||
{"addListener", wrap<add_listener>},
|
{"addListener", wrap<add_listener>},
|
||||||
{"removeListener", wrap<remove_listener>},
|
{"removeListener", wrap<remove_listener>},
|
||||||
{"removeAllListeners", wrap<remove_all_listeners>},
|
{"removeAllListeners", wrap<remove_all_listeners>},
|
||||||
|
@ -124,7 +135,27 @@ void ListClass<T>::get_length(ContextType, ObjectType object, ReturnValue &retur
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void ListClass<T>::get_type(ContextType, ObjectType object, ReturnValue &return_value) {
|
void ListClass<T>::min(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
|
||||||
|
compute_aggregate_on_collection<ListClass<T>>(AggregateFunc::Min, ctx, this_object, argc, arguments, return_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void ListClass<T>::max(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
|
||||||
|
compute_aggregate_on_collection<ListClass<T>>(AggregateFunc::Max, ctx, this_object, argc, arguments, return_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void ListClass<T>::sum(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
|
||||||
|
compute_aggregate_on_collection<ListClass<T>>(AggregateFunc::Sum, ctx, this_object, argc, arguments, return_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void ListClass<T>::avg(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
|
||||||
|
compute_aggregate_on_collection<ListClass<T>>(AggregateFunc::Avg, ctx, this_object, argc, arguments, return_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void ListClass<T>::get_type(ContextType ctx, ObjectType object, ReturnValue &return_value) {
|
||||||
auto list = get_internal<T, ListClass<T>>(object);
|
auto list = get_internal<T, ListClass<T>>(object);
|
||||||
return_value.set(string_for_property_type(list->get_type() & ~realm::PropertyType::Flags));
|
return_value.set(string_for_property_type(list->get_type() & ~realm::PropertyType::Flags));
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include "js_collection.hpp"
|
#include "js_collection.hpp"
|
||||||
#include "js_realm_object.hpp"
|
#include "js_realm_object.hpp"
|
||||||
|
#include "js_util.hpp"
|
||||||
|
|
||||||
#include "results.hpp"
|
#include "results.hpp"
|
||||||
#include "list.hpp"
|
#include "list.hpp"
|
||||||
|
@ -53,6 +54,7 @@ class Results : public realm::Results {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct ResultsClass : ClassDefinition<T, realm::js::Results<T>, CollectionClass<T>> {
|
struct ResultsClass : ClassDefinition<T, realm::js::Results<T>, CollectionClass<T>> {
|
||||||
|
using Type = T;
|
||||||
using ContextType = typename T::Context;
|
using ContextType = typename T::Context;
|
||||||
using ObjectType = typename T::Object;
|
using ObjectType = typename T::Object;
|
||||||
using ValueType = typename T::Value;
|
using ValueType = typename T::Value;
|
||||||
|
@ -85,6 +87,12 @@ struct ResultsClass : ClassDefinition<T, realm::js::Results<T>, CollectionClass<
|
||||||
template<typename Fn>
|
template<typename Fn>
|
||||||
static void index_of(ContextType, Fn&, Arguments, ReturnValue &);
|
static void index_of(ContextType, Fn&, Arguments, ReturnValue &);
|
||||||
|
|
||||||
|
// aggregate functions
|
||||||
|
static void min(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
||||||
|
static void max(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
||||||
|
static void sum(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
||||||
|
static void avg(ContextType, FunctionType, ObjectType, size_t, const ValueType[], ReturnValue &);
|
||||||
|
|
||||||
// observable
|
// observable
|
||||||
static void add_listener(ContextType, ObjectType, Arguments, ReturnValue &);
|
static void add_listener(ContextType, ObjectType, Arguments, ReturnValue &);
|
||||||
static void remove_listener(ContextType, ObjectType, Arguments, ReturnValue &);
|
static void remove_listener(ContextType, ObjectType, Arguments, ReturnValue &);
|
||||||
|
@ -102,6 +110,10 @@ struct ResultsClass : ClassDefinition<T, realm::js::Results<T>, CollectionClass<
|
||||||
{"filtered", wrap<filtered>},
|
{"filtered", wrap<filtered>},
|
||||||
{"sorted", wrap<sorted>},
|
{"sorted", wrap<sorted>},
|
||||||
{"isValid", wrap<is_valid>},
|
{"isValid", wrap<is_valid>},
|
||||||
|
{"min", wrap<min>},
|
||||||
|
{"max", wrap<max>},
|
||||||
|
{"sum", wrap<sum>},
|
||||||
|
{"avg", wrap<avg>},
|
||||||
{"addListener", wrap<add_listener>},
|
{"addListener", wrap<add_listener>},
|
||||||
{"removeListener", wrap<remove_listener>},
|
{"removeListener", wrap<remove_listener>},
|
||||||
{"removeAllListeners", wrap<remove_all_listeners>},
|
{"removeAllListeners", wrap<remove_all_listeners>},
|
||||||
|
@ -199,6 +211,26 @@ void ResultsClass<T>::get_length(ContextType ctx, ObjectType object, ReturnValue
|
||||||
return_value.set((uint32_t)results->size());
|
return_value.set((uint32_t)results->size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void ResultsClass<T>::min(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
|
||||||
|
compute_aggregate_on_collection<ResultsClass<T>>(AggregateFunc::Min, ctx, this_object, argc, arguments, return_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void ResultsClass<T>::max(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
|
||||||
|
compute_aggregate_on_collection<ResultsClass<T>>(AggregateFunc::Max, ctx, this_object, argc, arguments, return_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void ResultsClass<T>::sum(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
|
||||||
|
compute_aggregate_on_collection<ResultsClass<T>>(AggregateFunc::Sum, ctx, this_object, argc, arguments, return_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void ResultsClass<T>::avg(ContextType ctx, FunctionType, ObjectType this_object, size_t argc, const ValueType arguments[], ReturnValue &return_value) {
|
||||||
|
compute_aggregate_on_collection<ResultsClass<T>>(AggregateFunc::Avg, ctx, this_object, argc, arguments, return_value);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void ResultsClass<T>::get_type(ContextType, ObjectType object, ReturnValue &return_value) {
|
void ResultsClass<T>::get_type(ContextType, ObjectType object, ReturnValue &return_value) {
|
||||||
auto results = get_internal<T, ResultsClass<T>>(object);
|
auto results = get_internal<T, ResultsClass<T>>(object);
|
||||||
|
@ -211,7 +243,6 @@ void ResultsClass<T>::get_optional(ContextType, ObjectType object, ReturnValue &
|
||||||
return_value.set(is_nullable(results->get_type()));
|
return_value.set(is_nullable(results->get_type()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void ResultsClass<T>::get_index(ContextType ctx, ObjectType object, uint32_t index, ReturnValue &return_value) {
|
void ResultsClass<T>::get_index(ContextType ctx, ObjectType object, uint32_t index, ReturnValue &return_value) {
|
||||||
auto results = get_internal<T, ResultsClass<T>>(object);
|
auto results = get_internal<T, ResultsClass<T>>(object);
|
||||||
|
|
|
@ -358,7 +358,7 @@ void SessionClass<T>::get_config(ContextType ctx, ObjectType object, ReturnValue
|
||||||
if (auto session = get_internal<T, SessionClass<T>>(object)->lock()) {
|
if (auto session = get_internal<T, SessionClass<T>>(object)->lock()) {
|
||||||
ObjectType config = Object::create_empty(ctx);
|
ObjectType config = Object::create_empty(ctx);
|
||||||
Object::set_property(ctx, config, "user", create_object<T, UserClass<T>>(ctx, new SharedUser(session->config().user)));
|
Object::set_property(ctx, config, "user", create_object<T, UserClass<T>>(ctx, new SharedUser(session->config().user)));
|
||||||
Object::set_property(ctx, config, "url", Value::from_string(ctx, session->config().realm_url));
|
Object::set_property(ctx, config, "url", Value::from_string(ctx, session->config().realm_url()));
|
||||||
if (auto* dispatcher = session->config().error_handler.template target<EventLoopDispatcher<SyncSessionErrorHandler>>()) {
|
if (auto* dispatcher = session->config().error_handler.template target<EventLoopDispatcher<SyncSessionErrorHandler>>()) {
|
||||||
auto& handler = *dispatcher->func().template target<SyncSessionErrorHandlerFunctor<T>>();
|
auto& handler = *dispatcher->func().template target<SyncSessionErrorHandlerFunctor<T>>();
|
||||||
Object::set_property(ctx, config, "error", handler.func());
|
Object::set_property(ctx, config, "error", handler.func());
|
||||||
|
@ -576,7 +576,7 @@ std::function<SyncBindSessionHandler> SyncClass<T>::session_bind_callback(Contex
|
||||||
ValueType arguments[3];
|
ValueType arguments[3];
|
||||||
arguments[0] = create_object<T, UserClass<T>>(protected_ctx, new SharedUser(config.user));
|
arguments[0] = create_object<T, UserClass<T>>(protected_ctx, new SharedUser(config.user));
|
||||||
arguments[1] = Value::from_string(protected_ctx, path);
|
arguments[1] = Value::from_string(protected_ctx, path);
|
||||||
arguments[2] = Value::from_string(protected_ctx, config.realm_url);
|
arguments[2] = Value::from_string(protected_ctx, config.realm_url());
|
||||||
Function::call(protected_ctx, refreshAccessToken, 3, arguments);
|
Function::call(protected_ctx, refreshAccessToken, 3, arguments);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
#include <realm/binary_data.hpp>
|
#include <realm/binary_data.hpp>
|
||||||
#include <realm/string_data.hpp>
|
#include <realm/string_data.hpp>
|
||||||
#include <realm/util/to_string.hpp>
|
#include <realm/util/to_string.hpp>
|
||||||
|
#include <realm/util/optional.hpp>
|
||||||
|
#include <realm/mixed.hpp>
|
||||||
|
|
||||||
#if defined(__GNUC__) && !(defined(DEBUG) && DEBUG)
|
#if defined(__GNUC__) && !(defined(DEBUG) && DEBUG)
|
||||||
# define REALM_JS_INLINE inline __attribute__((always_inline))
|
# define REALM_JS_INLINE inline __attribute__((always_inline))
|
||||||
|
@ -136,6 +138,8 @@ struct Value {
|
||||||
static ValueType from_nonnull_string(ContextType, const String<T>&);
|
static ValueType from_nonnull_string(ContextType, const String<T>&);
|
||||||
static ValueType from_nonnull_binary(ContextType, BinaryData);
|
static ValueType from_nonnull_binary(ContextType, BinaryData);
|
||||||
static ValueType from_undefined(ContextType);
|
static ValueType from_undefined(ContextType);
|
||||||
|
static ValueType from_timestamp(ContextType, Timestamp);
|
||||||
|
static ValueType from_mixed(ContextType, util::Optional<Mixed> &);
|
||||||
|
|
||||||
static ObjectType to_array(ContextType, const ValueType &);
|
static ObjectType to_array(ContextType, const ValueType &);
|
||||||
static bool to_boolean(ContextType, const ValueType &);
|
static bool to_boolean(ContextType, const ValueType &);
|
||||||
|
@ -436,5 +440,37 @@ inline bool Value<T>::is_valid_for_property_type(ContextType context, const Valu
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline typename T::Value Value<T>::from_timestamp(typename T::Context ctx, Timestamp ts) {
|
||||||
|
return Object<T>::create_date(ctx, ts.get_seconds() * 1000 + ts.get_nanoseconds() / 1000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline typename T::Value Value<T>::from_mixed(typename T::Context ctx, util::Optional<Mixed>& mixed) {
|
||||||
|
if (!mixed) {
|
||||||
|
return from_undefined(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
Mixed value = *mixed;
|
||||||
|
switch (value.get_type()) {
|
||||||
|
case type_Bool:
|
||||||
|
return from_boolean(ctx, value.get_bool());
|
||||||
|
case type_Int:
|
||||||
|
return from_number(ctx, static_cast<double>(value.get_int()));
|
||||||
|
case type_Float:
|
||||||
|
return from_number(ctx, value.get_float());
|
||||||
|
case type_Double:
|
||||||
|
return from_number(ctx, value.get_double());
|
||||||
|
case type_Timestamp:
|
||||||
|
return from_timestamp(ctx, value.get_timestamp());
|
||||||
|
case type_String:
|
||||||
|
return from_string(ctx, value.get_string().data());
|
||||||
|
case type_Binary:
|
||||||
|
return from_binary(ctx, value.get_binary());
|
||||||
|
default:
|
||||||
|
throw std::invalid_argument("Value not convertible.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // js
|
} // js
|
||||||
} // realm
|
} // realm
|
||||||
|
|
|
@ -22,11 +22,19 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include "object_schema.hpp"
|
||||||
#include "shared_realm.hpp"
|
#include "shared_realm.hpp"
|
||||||
|
|
||||||
namespace realm {
|
namespace realm {
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
|
enum class AggregateFunc {
|
||||||
|
Min,
|
||||||
|
Max,
|
||||||
|
Sum,
|
||||||
|
Avg
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class RealmDelegate;
|
class RealmDelegate;
|
||||||
|
|
||||||
|
@ -75,5 +83,51 @@ static inline void validate_argument_count_at_least(size_t count, size_t expecte
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static inline void compute_aggregate_on_collection(AggregateFunc func, typename T::ContextType ctx, typename T::ObjectType this_object, size_t argc, const typename T::ValueType arguments[], typename T::ReturnValue &return_value) {
|
||||||
|
validate_argument_count(argc, 1);
|
||||||
|
std::string property_name = T::Value::validated_to_string(ctx, arguments[0]);
|
||||||
|
|
||||||
|
auto list = get_internal<typename T::Type, T>(this_object);
|
||||||
|
|
||||||
|
const ObjectSchema& object_schema = list->get_object_schema();
|
||||||
|
const Property* property = object_schema.property_for_name(property_name);
|
||||||
|
if (!property) {
|
||||||
|
throw std::invalid_argument(util::format("No such property: %1", property_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
util::Optional<Mixed> mixed;
|
||||||
|
switch (func) {
|
||||||
|
case AggregateFunc::Min: {
|
||||||
|
mixed = list->min(property->table_column);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AggregateFunc::Max: {
|
||||||
|
mixed = list->max(property->table_column);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AggregateFunc::Sum: {
|
||||||
|
mixed = list->sum(property->table_column);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AggregateFunc::Avg: {
|
||||||
|
util::Optional<double> avg = list->average(property->table_column);
|
||||||
|
if (!avg) {
|
||||||
|
return_value.set_undefined();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return_value.set(*avg);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
REALM_ASSERT(false && "Unknown aggregate function");
|
||||||
|
REALM_UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return_value.set(T::Value::from_mixed(ctx, mixed));
|
||||||
|
}
|
||||||
|
|
||||||
} // js
|
} // js
|
||||||
} // realm
|
} // realm
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 49705c0fbdbff8536cfa134fc17b837db4385d31
|
Subproject commit 0d0615caaf0df6dbccca3f86a05303892c3a7a2e
|
|
@ -1004,4 +1004,199 @@ module.exports = {
|
||||||
TestCase.assertEqual(list.isValid(), false);
|
TestCase.assertEqual(list.isValid(), false);
|
||||||
TestCase.assertThrowsContaining(() => list.length, 'invalidated');
|
TestCase.assertThrowsContaining(() => list.length, 'invalidated');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
testListAggregateFunctions: function() {
|
||||||
|
const NullableBasicTypesList = {
|
||||||
|
name: 'NullableBasicTypesList',
|
||||||
|
properties: {
|
||||||
|
list: {type: 'list', objectType: 'NullableBasicTypesObject'},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var realm = new Realm({schema: [schemas.NullableBasicTypes, NullableBasicTypesList]});
|
||||||
|
var object;
|
||||||
|
|
||||||
|
const N = 50;
|
||||||
|
|
||||||
|
var list = [];
|
||||||
|
for(var i = 0; i < N; i++) {
|
||||||
|
list.push({
|
||||||
|
intCol: i+1,
|
||||||
|
floatCol: i+1,
|
||||||
|
doubleCol: i+1,
|
||||||
|
dateCol: new Date(i+1)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
realm.write(() => {
|
||||||
|
object = realm.create('NullableBasicTypesList', {list: list});
|
||||||
|
});
|
||||||
|
|
||||||
|
TestCase.assertEqual(object.list.length, N);
|
||||||
|
|
||||||
|
// int, float & double columns support all aggregate functions
|
||||||
|
['intCol', 'floatCol', 'doubleCol'].forEach(colName => {
|
||||||
|
TestCase.assertEqual(object.list.min(colName), 1);
|
||||||
|
TestCase.assertEqual(object.list.max(colName), N);
|
||||||
|
TestCase.assertEqual(object.list.sum(colName), N*(N+1)/2);
|
||||||
|
TestCase.assertEqual(object.list.avg(colName), (N+1)/2);
|
||||||
|
});
|
||||||
|
|
||||||
|
// date columns support only 'min' & 'max'
|
||||||
|
TestCase.assertEqual(object.list.min('dateCol').getTime(), new Date(1).getTime());
|
||||||
|
TestCase.assertEqual(object.list.max('dateCol').getTime(), new Date(N).getTime());
|
||||||
|
},
|
||||||
|
|
||||||
|
testListAggregateFunctionsWithNullColumnValues: function() {
|
||||||
|
const NullableBasicTypesList = {
|
||||||
|
name: 'NullableBasicTypesList',
|
||||||
|
properties: {
|
||||||
|
list: {type: 'list', objectType: 'NullableBasicTypesObject'},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var realm = new Realm({schema: [schemas.NullableBasicTypes, NullableBasicTypesList]});
|
||||||
|
var object;
|
||||||
|
var objectEmptyList;
|
||||||
|
|
||||||
|
const N = 50;
|
||||||
|
const M = 10;
|
||||||
|
|
||||||
|
var list = [];
|
||||||
|
for(var i = 0; i < N; i++) {
|
||||||
|
list.push({
|
||||||
|
intCol: i+1,
|
||||||
|
floatCol: i+1,
|
||||||
|
doubleCol: i+1,
|
||||||
|
dateCol: new Date(i+1)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for(var j = 0; j < M; j++) {
|
||||||
|
list.push({
|
||||||
|
intCol: null,
|
||||||
|
floatCol: null,
|
||||||
|
doubleCol: null,
|
||||||
|
dateCol: null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
realm.write(() => {
|
||||||
|
object = realm.create('NullableBasicTypesList', {list: list});
|
||||||
|
objectEmptyList = realm.create('NullableBasicTypesList', {list: []});
|
||||||
|
});
|
||||||
|
|
||||||
|
TestCase.assertEqual(object.list.length, N + M);
|
||||||
|
|
||||||
|
|
||||||
|
// int, float & double columns support all aggregate functions
|
||||||
|
// the M null valued objects should be ignored
|
||||||
|
['intCol', 'floatCol', 'doubleCol'].forEach(colName => {
|
||||||
|
TestCase.assertEqual(object.list.min(colName), 1);
|
||||||
|
TestCase.assertEqual(object.list.max(colName), N);
|
||||||
|
TestCase.assertEqual(object.list.sum(colName), N*(N+1)/2);
|
||||||
|
TestCase.assertEqual(object.list.avg(colName), (N+1)/2);
|
||||||
|
});
|
||||||
|
|
||||||
|
// date columns support only 'min' & 'max'
|
||||||
|
TestCase.assertEqual(object.list.min('dateCol').getTime(), new Date(1).getTime());
|
||||||
|
TestCase.assertEqual(object.list.max('dateCol').getTime(), new Date(N).getTime());
|
||||||
|
|
||||||
|
// call aggregate functions on empty list
|
||||||
|
TestCase.assertEqual(objectEmptyList.list.length, 0);
|
||||||
|
['intCol', 'floatCol', 'doubleCol'].forEach(colName => {
|
||||||
|
TestCase.assertUndefined(objectEmptyList.list.min(colName));
|
||||||
|
TestCase.assertUndefined(objectEmptyList.list.max(colName));
|
||||||
|
TestCase.assertEqual(objectEmptyList.list.sum(colName), 0);
|
||||||
|
TestCase.assertUndefined(objectEmptyList.list.avg(colName));
|
||||||
|
});
|
||||||
|
|
||||||
|
TestCase.assertUndefined(objectEmptyList.list.min('dateCol'));
|
||||||
|
TestCase.assertUndefined(objectEmptyList.list.max('dateCol'));
|
||||||
|
},
|
||||||
|
|
||||||
|
testListAggregateFunctionsUnsupported: function() {
|
||||||
|
const NullableBasicTypesList = {
|
||||||
|
name: 'NullableBasicTypesList',
|
||||||
|
properties: {
|
||||||
|
list: {type: 'list', objectType: 'NullableBasicTypesObject'},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var realm = new Realm({schema: [schemas.NullableBasicTypes, NullableBasicTypesList]});
|
||||||
|
var object;
|
||||||
|
|
||||||
|
const N = 5;
|
||||||
|
|
||||||
|
var list = [];
|
||||||
|
for(var i = 0; i < N; i++) {
|
||||||
|
list.push({
|
||||||
|
intCol: i+1,
|
||||||
|
floatCol: i+1,
|
||||||
|
doubleCol: i+1,
|
||||||
|
dateCol: new Date(i+1)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
realm.write(() => {
|
||||||
|
object = realm.create('NullableBasicTypesList', {list: list});
|
||||||
|
});
|
||||||
|
|
||||||
|
TestCase.assertEqual(object.list.length, N);
|
||||||
|
|
||||||
|
// bool, string & data columns don't support 'min'
|
||||||
|
['boolCol', 'stringCol', 'dataCol'].forEach(colName => {
|
||||||
|
TestCase.assertThrows(function() {
|
||||||
|
object.list.min(colName);
|
||||||
|
}
|
||||||
|
)});
|
||||||
|
|
||||||
|
// bool, string & data columns don't support 'max'
|
||||||
|
['boolCol', 'stringCol', 'dataCol'].forEach(colName => {
|
||||||
|
TestCase.assertThrows(function() {
|
||||||
|
object.list.max(colName);
|
||||||
|
}
|
||||||
|
)});
|
||||||
|
|
||||||
|
// bool, string, date & data columns don't support 'avg'
|
||||||
|
['boolCol', 'stringCol', 'dateCol', 'dataCol'].forEach(colName => {
|
||||||
|
TestCase.assertThrows(function() {
|
||||||
|
object.list.avg(colName);
|
||||||
|
}
|
||||||
|
)});
|
||||||
|
|
||||||
|
// bool, string, date & data columns don't support 'sum'
|
||||||
|
['boolCol', 'stringCol', 'dateCol', 'dataCol'].forEach(colName => {
|
||||||
|
TestCase.assertThrows(function() {
|
||||||
|
object.list.sum(colName);
|
||||||
|
}
|
||||||
|
)});
|
||||||
|
},
|
||||||
|
|
||||||
|
testListAggregateFunctionsWrongProperty: function() {
|
||||||
|
var realm = new Realm({schema: [schemas.PersonObject, schemas.PersonList]});
|
||||||
|
var object;
|
||||||
|
var list;
|
||||||
|
realm.write(() => {
|
||||||
|
object = realm.create('PersonList', {list: [
|
||||||
|
{name: 'Ari', age: 10},
|
||||||
|
{name: 'Tim', age: 11},
|
||||||
|
{name: 'Bjarne', age: 12},
|
||||||
|
]});
|
||||||
|
});
|
||||||
|
|
||||||
|
TestCase.assertThrows(function() {
|
||||||
|
object.list.min('foo')
|
||||||
|
});
|
||||||
|
TestCase.assertThrows(function() {
|
||||||
|
object.list.max('foo')
|
||||||
|
});
|
||||||
|
TestCase.assertThrows(function() {
|
||||||
|
object.list.sum('foo')
|
||||||
|
});
|
||||||
|
TestCase.assertThrows(function() {
|
||||||
|
object.list.avg('foo')
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -455,6 +455,156 @@ module.exports = {
|
||||||
});
|
});
|
||||||
resolve = r;
|
resolve = r;
|
||||||
});
|
});
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
testResultsAggregateFunctions: function() {
|
||||||
|
var realm = new Realm({ schema: [schemas.NullableBasicTypes] });
|
||||||
|
const N = 50;
|
||||||
|
realm.write(() => {
|
||||||
|
for(var i = 0; i < N; i++) {
|
||||||
|
realm.create('NullableBasicTypesObject', {
|
||||||
|
intCol: i+1,
|
||||||
|
floatCol: i+1,
|
||||||
|
doubleCol: i+1,
|
||||||
|
dateCol: new Date(i+1)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var results = realm.objects('NullableBasicTypesObject');
|
||||||
|
TestCase.assertEqual(results.length, N);
|
||||||
|
|
||||||
|
// int, float & double columns support all aggregate functions
|
||||||
|
['intCol', 'floatCol', 'doubleCol'].forEach(colName => {
|
||||||
|
TestCase.assertEqual(results.min(colName), 1);
|
||||||
|
TestCase.assertEqual(results.max(colName), N);
|
||||||
|
TestCase.assertEqual(results.sum(colName), N*(N+1)/2);
|
||||||
|
TestCase.assertEqual(results.avg(colName), (N+1)/2);
|
||||||
|
});
|
||||||
|
|
||||||
|
// date columns support only 'min' & 'max'
|
||||||
|
TestCase.assertEqual(results.min('dateCol').getTime(), new Date(1).getTime());
|
||||||
|
TestCase.assertEqual(results.max('dateCol').getTime(), new Date(N).getTime());
|
||||||
|
},
|
||||||
|
|
||||||
|
testResultsAggregateFunctionsWithNullColumnValues: function() {
|
||||||
|
var realm = new Realm({ schema: [schemas.NullableBasicTypes] });
|
||||||
|
|
||||||
|
const N = 50;
|
||||||
|
const M = 10;
|
||||||
|
|
||||||
|
realm.write(() => {
|
||||||
|
for(var i = 0; i < N; i++) {
|
||||||
|
realm.create('NullableBasicTypesObject', {
|
||||||
|
intCol: i+1,
|
||||||
|
floatCol: i+1,
|
||||||
|
doubleCol: i+1,
|
||||||
|
dateCol: new Date(i+1)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// add some null valued data, which should be ignored by the aggregate functions
|
||||||
|
for(var j = 0; j < M; j++) {
|
||||||
|
realm.create('NullableBasicTypesObject', {
|
||||||
|
intCol: null,
|
||||||
|
floatCol: null,
|
||||||
|
doubleCol: null,
|
||||||
|
dateCol: null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var results = realm.objects('NullableBasicTypesObject');
|
||||||
|
|
||||||
|
TestCase.assertEqual(results.length, N + M);
|
||||||
|
|
||||||
|
// int, float & double columns support all aggregate functions
|
||||||
|
// the M null valued objects should be ignored
|
||||||
|
['intCol', 'floatCol', 'doubleCol'].forEach(colName => {
|
||||||
|
TestCase.assertEqual(results.min(colName), 1);
|
||||||
|
TestCase.assertEqual(results.max(colName), N);
|
||||||
|
TestCase.assertEqual(results.sum(colName), N*(N+1)/2);
|
||||||
|
TestCase.assertEqual(results.avg(colName), (N+1)/2);
|
||||||
|
});
|
||||||
|
|
||||||
|
// date columns support only 'min' & 'max'
|
||||||
|
TestCase.assertEqual(results.min('dateCol').getTime(), new Date(1).getTime());
|
||||||
|
TestCase.assertEqual(results.max('dateCol').getTime(), new Date(N).getTime());
|
||||||
|
|
||||||
|
// call aggregate functions on empty results
|
||||||
|
var emptyResults = realm.objects('NullableBasicTypesObject').filtered('intCol < 0');
|
||||||
|
TestCase.assertEqual(emptyResults.length, 0);
|
||||||
|
['intCol', 'floatCol', 'doubleCol'].forEach(colName => {
|
||||||
|
TestCase.assertUndefined(emptyResults.min(colName));
|
||||||
|
TestCase.assertUndefined(emptyResults.max(colName));
|
||||||
|
TestCase.assertEqual(emptyResults.sum(colName), 0);
|
||||||
|
TestCase.assertUndefined(emptyResults.avg(colName));
|
||||||
|
});
|
||||||
|
|
||||||
|
TestCase.assertUndefined(emptyResults.min('dateCol'));
|
||||||
|
TestCase.assertUndefined(emptyResults.max('dateCol'));
|
||||||
|
},
|
||||||
|
|
||||||
|
testResultsAggregateFunctionsUnsupported: function() {
|
||||||
|
var realm = new Realm({ schema: [schemas.NullableBasicTypes] });
|
||||||
|
realm.write(() => {
|
||||||
|
realm.create('NullableBasicTypesObject', {
|
||||||
|
boolCol: true,
|
||||||
|
stringCol: "hello",
|
||||||
|
dataCol: new ArrayBuffer(12),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
var results = realm.objects('NullableBasicTypesObject');
|
||||||
|
|
||||||
|
// bool, string & data columns don't support 'min'
|
||||||
|
['boolCol', 'stringCol', 'dataCol'].forEach(colName => {
|
||||||
|
TestCase.assertThrows(function() {
|
||||||
|
results.min(colName);
|
||||||
|
}
|
||||||
|
)});
|
||||||
|
|
||||||
|
// bool, string & data columns don't support 'max'
|
||||||
|
['boolCol', 'stringCol', 'dataCol'].forEach(colName => {
|
||||||
|
TestCase.assertThrows(function() {
|
||||||
|
results.max(colName);
|
||||||
|
}
|
||||||
|
)});
|
||||||
|
|
||||||
|
// bool, string, date & data columns don't support 'avg'
|
||||||
|
['boolCol', 'stringCol', 'dateCol', 'dataCol'].forEach(colName => {
|
||||||
|
TestCase.assertThrows(function() {
|
||||||
|
results.avg(colName);
|
||||||
|
}
|
||||||
|
)});
|
||||||
|
|
||||||
|
// bool, string, date & data columns don't support 'sum'
|
||||||
|
['boolCol', 'stringCol', 'dateCol', 'dataCol'].forEach(colName => {
|
||||||
|
TestCase.assertThrows(function() {
|
||||||
|
results.sum(colName);
|
||||||
|
}
|
||||||
|
)});
|
||||||
|
},
|
||||||
|
|
||||||
|
testResultsAggregateFunctionsWrongProperty: function() {
|
||||||
|
var realm = new Realm({ schema: [ schemas.TestObject ]});
|
||||||
|
realm.write(() => {
|
||||||
|
realm.create('TestObject', { doubleCol: 42 });
|
||||||
|
});
|
||||||
|
var results = realm.objects('TestObject');
|
||||||
|
TestCase.assertThrows(function() {
|
||||||
|
results.min('foo')
|
||||||
|
});
|
||||||
|
TestCase.assertThrows(function() {
|
||||||
|
results.max('foo')
|
||||||
|
});
|
||||||
|
TestCase.assertThrows(function() {
|
||||||
|
results.sum('foo')
|
||||||
|
});
|
||||||
|
TestCase.assertThrows(function() {
|
||||||
|
results.avg('foo')
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -252,6 +252,19 @@ exports.NullQueryObject = {
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.NullableBasicTypes = {
|
||||||
|
name: 'NullableBasicTypesObject',
|
||||||
|
properties: [
|
||||||
|
{name: 'boolCol', type: 'bool?'},
|
||||||
|
{name: 'intCol', type: 'int?'},
|
||||||
|
{name: 'floatCol', type: 'float?'},
|
||||||
|
{name: 'doubleCol', type: 'double?'},
|
||||||
|
{name: 'stringCol', type: 'string?'},
|
||||||
|
{name: 'dateCol', type: 'date?'},
|
||||||
|
{name: 'dataCol', type: 'data?'},
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
exports.DateObject = {
|
exports.DateObject = {
|
||||||
name: 'Date',
|
name: 'Date',
|
||||||
properties: {
|
properties: {
|
||||||
|
|
Loading…
Reference in New Issue