Merge branch 'master' into cm/bug/java9

# Conflicts:
#	CHANGELOG.md
This commit is contained in:
Christian Melchior 2018-05-08 12:54:03 +02:00
commit f418ae95d5
11 changed files with 100 additions and 37 deletions

View File

@ -1,4 +1,11 @@
X.Y.Z Release notes 2.4.2 Release notes (YYYY-MM-DD)
=============================================================
### Bug fixes
* Building React Native Android projects using Java version 9 used deprecated API's (#1779).
2.4.1 Release notes (2018-5-7)
============================================================= =============================================================
### Compatibility ### Compatibility
* Sync protocol: 24 * Sync protocol: 24
@ -10,11 +17,10 @@ X.Y.Z Release notes
* None. * None.
### Enhancements ### Enhancements
* None. * Added minimal support for Realm deletions to the Global Notifier (realm-js-private #443).
### Bug fixes ### Bug fixes
* Fixed TypeScript defintion for `open_ssl_verify_callback` configuration option (#1652).
* Building React Native Android projects using Java version 9 used deprecated API's (#1779).
### Internal ### Internal
* Updated to Relm Sync 3.3.0. * Updated to Relm Sync 3.3.0.

View File

@ -36,7 +36,7 @@ Prerequisites:
- Node: 4.0 <= version < 7.0 - Node: 4.0 <= version < 7.0
- Xcode 7.2+ - Xcode 7.2+
- Android SDK 23+ - Android SDK 23+
- Android NDK 10e - [Android NDK 10e](https://developer.android.com/ndk/downloads/older_releases)
First clone this repository: First clone this repository:
@ -52,17 +52,18 @@ git submodule update --init --recursive
```Note: If you have cloned the repo previously make sure you remove your node_modules directory since it may contain stale dependencies which may cause the build to fail.``` ```Note: If you have cloned the repo previously make sure you remove your node_modules directory since it may contain stale dependencies which may cause the build to fail.```
To build for iOS: ### Building for iOS:
- Open `react-native/ios/RealmReact.xcodeproj` - Open `react-native/ios/RealmReact.xcodeproj`
- Select `RealmReact.framework` as the build target - Select `RealmReact.framework` as the build target
- Build - Build
To build for Android: ### Building for Android:
- `cd react-native/android` - `cd react-native/android`
- `./gradlew publishAndroid` - `./gradlew publishAndroid`
- The compiled version of the Android module is here: `<project-root>/android` - The compiled version of the Android module is here: `<project-root>/android`
To build for nodejs: ### Building for nodejs:
Be sure you have python2.7 as the default python. 3.x won't work, and it's not enough to use `--python=python2.7` as parameter to npm.
``` ```
npm install --build-from-source=realm npm install --build-from-source=realm
@ -70,7 +71,7 @@ npm install --build-from-source=realm
- On Windows you will need to setup the environment for node-gyp - On Windows you will need to setup the environment for node-gyp
- Option 1: Install windows-build-tools node package * Option 1: Install windows-build-tools node package
- Open an elevated command prompt (As Administrator) - Open an elevated command prompt (As Administrator)

View File

@ -1,5 +1,5 @@
PACKAGE_NAME=realm-js PACKAGE_NAME=realm-js
VERSION=2.4.0 VERSION=2.4.1
REALM_CORE_VERSION=5.6.0 REALM_CORE_VERSION=5.6.0
REALM_SYNC_VERSION=3.3.0 REALM_SYNC_VERSION=3.3.0
REALM_OBJECT_SERVER_VERSION=3.0.0 REALM_OBJECT_SERVER_VERSION=3.0.0

View File

@ -95,3 +95,21 @@ Example:
// Find contacts with friends above 21 in SF // Find contacts with friends above 21 in SF
let teens = realm.objects('Contact').filtered('SUBQUERY(friends, $friend, $friend.age > 21 AND $friend.city = "SF").@count > 0'); let teens = realm.objects('Contact').filtered('SUBQUERY(friends, $friend, $friend.age > 21 AND $friend.city = "SF").@count > 0');
``` ```
### Backlink queries
Other objects can link to an object and you can query on that releationship using the `@links` and `@links.ClassName.PropertyName` syntax.
If the relationship of the LinkingObject is named, use the name in the query just like you would use any other property for readability.
If the relationship is not named, you can use the `@links.ClassName.PropertyName` syntax where `ClassName.PropertyName` describes the forward relationship.
Example:
```JS
// Find contacts where someone from SF has them as friends
realm.objects('Contact').filtered('@links.Contact.friends.city == "SF"');
// Find contacts with no incomming links (across all linked properties)
let isolated = realm.objects('Contact').filtered('@links.@count == 0');
// Find contacts with no incoming friend links
let lonely = realm.objects('Contact').filtered('@links.Contact.friends.@count == 0');
```

10
lib/index.d.ts vendored
View File

@ -376,8 +376,16 @@ declare namespace Realm.Sync {
code: number; code: number;
} }
interface SSLVerifyObject {
serverAddress: string;
serverPort: number;
pemCertificate: string;
acceptedByOpenSSL: boolean;
depth: number;
}
type ErrorCallback = (session: Session, error: SyncError) => void; type ErrorCallback = (session: Session, error: SyncError) => void;
type SSLVerifyCallback = (serverAddress: string, serverPort: number, pemCertificate: string, preverifyOk: number, depth: number) => boolean; type SSLVerifyCallback = (sslVerifyObject: SSLVerifyObject) => boolean;
interface SyncConfiguration { interface SyncConfiguration {
user: User; user: User;

View File

@ -45,11 +45,11 @@ class FunctionListener {
return this.regexStr === regex && this.event === event && this.fn === fn; return this.regexStr === regex && this.event === event && this.fn === fn;
} }
onavailable(path) { onavailable(path, id) {
if (this.regex.test(path)) { if (this.regex.test(path)) {
if (this.event === 'available' && !this.seen[path]) { if (this.event === 'available' && !this.seen[id]) {
this.fn(path); this.fn(path);
this.seen[path] = true; this.seen[id] = true;
} }
return this.event === 'change'; return this.event === 'change';
} }
@ -103,11 +103,11 @@ class OutOfProcListener {
return this.regexStr === regex && this.worker === worker; return this.regexStr === regex && this.worker === worker;
} }
onavailable(path) { onavailable(path, id) {
if (this.regex.test(path)) { if (this.regex.test(path)) {
if (!this.seen[path]) { if (!this.seen[id]) {
this.worker.onavailable(path); this.worker.onavailable(path);
this.seen[path] = true; this.seen[id] = true;
} }
return true; return true;
} }
@ -161,10 +161,11 @@ class Listener {
changes.release(); changes.release();
} }
available(virtualPath) { available(virtualPath, id) {
let watch = false; let watch = false;
id = id || virtualPath;
for (const callback of this.callbacks) { for (const callback of this.callbacks) {
if (callback.onavailable(virtualPath)) { if (callback.onavailable(virtualPath, id)) {
watch = true; watch = true;
} }
} }

View File

@ -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.4.0", "version": "2.4.1",
"license": "Apache-2.0", "license": "Apache-2.0",
"homepage": "https://realm.io", "homepage": "https://realm.io",
"keywords": [ "keywords": [

View File

@ -191,6 +191,10 @@ function getSyncRequirements(dependencies, options, required = {}) {
return required; return required;
}); });
} }
case 'linux':
required.SYNC_ARCHIVE = `realm-sync-Release-v${dependencies.REALM_SYNC_VERSION}-Linux-devel.tar.gz`;
required.SYNC_ARCHIVE_ROOT = `realm-sync-Release-v${dependencies.REALM_SYNC_VERSION}`;
return Promise.resolve(required);
default: default:
return Promise.reject(new Error(`Unsupported sync platform '${options.platform}'`)); return Promise.reject(new Error(`Unsupported sync platform '${options.platform}'`));
} }

View File

@ -969,7 +969,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 2.4.0; CURRENT_PROJECT_VERSION = 2.4.1;
CXX = "$(SRCROOT)/../scripts/ccache-clang++.sh"; CXX = "$(SRCROOT)/../scripts/ccache-clang++.sh";
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_STRICT_OBJC_MSGSEND = YES;
@ -1033,7 +1033,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 2.4.0; CURRENT_PROJECT_VERSION = 2.4.1;
CXX = "$(SRCROOT)/../scripts/ccache-clang++.sh"; CXX = "$(SRCROOT)/../scripts/ccache-clang++.sh";
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO; ENABLE_NS_ASSERTIONS = NO;

View File

@ -160,8 +160,7 @@ inline void alias_backlinks(parser::KeyPathMapping &mapping, const realm::Shared
if (property.type == realm::PropertyType::LinkingObjects) { if (property.type == realm::PropertyType::LinkingObjects) {
auto target_object_schema = schema.find(property.object_type); auto target_object_schema = schema.find(property.object_type);
const TableRef table = ObjectStore::table_for_object_type(realm->read_group(), it->name); const TableRef table = ObjectStore::table_for_object_type(realm->read_group(), it->name);
const TableRef target_table = ObjectStore::table_for_object_type(realm->read_group(), target_object_schema->name); std::string native_name = "@links." + target_object_schema->name + "." + property.link_origin_property_name;
std::string native_name = "@links." + std::string(target_table->get_name()) + "." + property.link_origin_property_name;
mapping.add_mapping(table, property.name, native_name); mapping.add_mapping(table, property.name, native_name);
} }
} }
@ -181,6 +180,7 @@ typename T::Object ResultsClass<T>::create_filtered(ContextType ctx, const U &co
auto const &object_schema = collection.get_object_schema(); auto const &object_schema = collection.get_object_schema();
DescriptorOrdering ordering; DescriptorOrdering ordering;
parser::KeyPathMapping mapping; parser::KeyPathMapping mapping;
mapping.set_backlink_class_prefix(ObjectStore::table_name_for_object_type(""));
alias_backlinks(mapping, realm); alias_backlinks(mapping, realm);
parser::ParserResult result = parser::parse(query_string); parser::ParserResult result = parser::parse(query_string);

View File

@ -109,24 +109,49 @@ module.exports = {
let english = realm.create('Language', {name: 'English'}); let english = realm.create('Language', {name: 'English'});
let french = realm.create('Language', {name: 'French'}); let french = realm.create('Language', {name: 'French'});
let danish = realm.create('Language', {name: 'Danish'}); let danish = realm.create('Language', {name: 'Danish'});
let latin = realm.create('Language', {name: 'Latin'});
let canada = realm.create('Country', {name: 'Canada', languages: [english, french]}); let canada = realm.create('Country', {name: 'Canada', languages: [english, french]});
let denmark = realm.create('Country', {name: 'Denmark', languages: [danish, english]}); let denmark = realm.create('Country', {name: 'Denmark', languages: [danish, english]});
let france = realm.create('Country', {name: 'France', languages: [french, english]}); let france = realm.create('Country', {name: 'France', languages: [french, english]});
}); });
let languages = realm.objects('Language'); let languages = realm.objects('Language');
let spokenInThreeCountries = languages.filtered('spokenIn.@count == 3'); {
TestCase.assertEqual(spokenInThreeCountries.length, 1); let spokenInThreeCountries = languages.filtered('spokenIn.@count == 3');
TestCase.assertEqual(spokenInThreeCountries[0].name, 'English'); TestCase.assertEqual(spokenInThreeCountries.length, 1);
let spokenInTwoCountries = languages.filtered('spokenIn.@count == 2'); TestCase.assertEqual(spokenInThreeCountries[0].name, 'English');
TestCase.assertEqual(spokenInTwoCountries.length, 1); let spokenInTwoCountries = languages.filtered('spokenIn.@count == 2');
TestCase.assertEqual(spokenInTwoCountries[0].name, 'French') TestCase.assertEqual(spokenInTwoCountries.length, 1);
let spokenInOneCountry = languages.filtered('spokenIn.@count == 1'); TestCase.assertEqual(spokenInTwoCountries[0].name, 'French')
TestCase.assertEqual(spokenInOneCountry.length, 1); let spokenInOneCountry = languages.filtered('spokenIn.@count == 1');
TestCase.assertEqual(spokenInOneCountry[0].name, 'Danish') TestCase.assertEqual(spokenInOneCountry.length, 1);
let languagesSpokenInCanada = languages.filtered('spokenIn.name ==[c] "canada"'); TestCase.assertEqual(spokenInOneCountry[0].name, 'Danish')
TestCase.assertEqual(languagesSpokenInCanada.length, 2); let languagesSpokenInCanada = languages.filtered('spokenIn.name ==[c] "canada"');
TestCase.assertEqual(languagesSpokenInCanada[0].name, 'English'); TestCase.assertEqual(languagesSpokenInCanada.length, 2);
TestCase.assertEqual(languagesSpokenInCanada[1].name, 'French'); TestCase.assertEqual(languagesSpokenInCanada[0].name, 'English');
TestCase.assertEqual(languagesSpokenInCanada[1].name, 'French');
}
// check the same but using the unnamed relationship which is available to users
{
let spokenInThreeCountries = languages.filtered('@links.Country.languages.@count == 3');
TestCase.assertEqual(spokenInThreeCountries.length, 1);
TestCase.assertEqual(spokenInThreeCountries[0].name, 'English');
let spokenInTwoCountries = languages.filtered('@links.Country.languages.@count == 2');
TestCase.assertEqual(spokenInTwoCountries.length, 1);
TestCase.assertEqual(spokenInTwoCountries[0].name, 'French')
let spokenInOneCountry = languages.filtered('@links.Country.languages.@count == 1');
TestCase.assertEqual(spokenInOneCountry.length, 1);
TestCase.assertEqual(spokenInOneCountry[0].name, 'Danish')
let languagesSpokenInCanada = languages.filtered('@links.Country.languages.name ==[c] "canada"');
TestCase.assertEqual(languagesSpokenInCanada.length, 2);
TestCase.assertEqual(languagesSpokenInCanada[0].name, 'English');
TestCase.assertEqual(languagesSpokenInCanada[1].name, 'French');
}
let notSpokenInAnyCountry = languages.filtered('@links.@count == 0'); // no incoming links over any relationships to the object
TestCase.assertEqual(notSpokenInAnyCountry.length, 1);
TestCase.assertEqual(notSpokenInAnyCountry[0].name, 'Latin');
let notSpokenMethod2 = languages.filtered('@links.Country.languages.@count == 0'); // links of a specific relationship are 0
TestCase.assertEqual(notSpokenMethod2.length, 1);
TestCase.assertEqual(notSpokenMethod2[0].name, 'Latin');
}, },
testMethod: function() { testMethod: function() {