Skip to content

Commit

Permalink
Merge 9db8a05 into 254b02c
Browse files Browse the repository at this point in the history
  • Loading branch information
kneth committed Mar 2, 2024
2 parents 254b02c + 9db8a05 commit 63104f4
Show file tree
Hide file tree
Showing 13 changed files with 347 additions and 37 deletions.
29 changes: 21 additions & 8 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,37 @@
## vNext (TBD)

NOTE: This version bumps the Realm file format to version 24. It is not possible to downgrade to earlier versions. Older files will automatically be upgraded to the new file format. Files created by Realm JavaScript prior to v6.0.0, might not be upgradeable. Only Realm Studio 15.0.0 or later will be able to open the new file format.

### Deprecations
* None

### Enhancements
* None
* Updated bundled OpenSSL version to 3.2.0 ([realm/realm-core#7303](https://github.com/realm/realm-core/pull/7303))
* Property keypath in RQL can be substituted with value given as argument. Use `$P<i>` in query string. ([realm/realm-core#7033](https://github.com/realm/realm-core/issues/7033))
* You can now use query substitution for the `@type` argument. ([realm/realm-core#7289](https://github.com/realm/realm-core/issues/7289))
* Storage of `Decimal128` properties has been optimized so that the individual values will take up 0 bits (if all nulls), 32 bits, 64 bits or 128 bits depending on what is needed. ([realm/realm-core#6111]https://github.com/realm/realm-core/pull/6111))
* Querying a specific entry in a collection (in particular 'first and 'last') is supported. (PR [#4269](https://github.com/realm/realm-core/issues/4269))
* Index on list of strings property now supported ([realm/realm-core#7142](https://github.com/realm/realm-core/pull/7142))
* You can set the threshold levels for trace output on individual categories. ([realm/realm-core#7004](https://github.com/realm/realm-core/pull/7004))
* Improved performance of RQL queries on a non-linked string property using `>`, `>=`, `<`, `<=` operators and fixed behavior that a null string should be evaluated as less than everything, previously nulls were not matched. ([realm/realm-core#3939](https://github.com/realm/realm-core/issues/3939))
* Added static method `Realm.needsFileFormatUpgrade()` which returns `true` if the Realm will be upgraded when opening.

### Fixed
* <How to hit and notice issue? what was the impact?> ([#????](https://github.com/realm/realm-js/issues/????), since v?.?.?)
* None
* Align dictionaries to Lists and Sets when they get cleared. ([#6205](https://github.com/realm/realm-core/issues/6205), since v10.3.0-rc.1)
* Fixed equality queries on a `Mixed` property with an index possibly returning the wrong result if values of different types happened to have the same StringIndex hash. ([realm/realm-core#6407](https://github.com/realm/realm-core/issues/6407) since v10.5.0-beta.1)
* @count/@size not supported for mixed properties ([realm/realm-core#7280](https://github.com/realm/realm-core/issues/7280), since v10.0.0)
* Fixed queries like `indexed_property == NONE {x}` which mistakenly matched on only `x` instead of not `x`. This only applies when an indexed property with equality (`==`, or `IN`) matches with `NONE` on a list of one item. If the constant list contained more than one value then it was working correctly. ([realm/realm-java#7862](https://github.com/realm/realm-java/issues/7862), since v10.20.0)
* Uploading the changesets recovered during an automatic client reset recovery may lead to `Bad server version` errors and a new client reset. ([realm/realm-core#7279](https://github.com/realm/realm-core/issues/7279), since v12.5.0)
* Fixed crash in full text index using prefix search with no matches ([realm/realm-core#7309](https://github.com/realm/realm-core/issues/7309), since v12.2.0)
* Fix a race condition when backing up Realm files before a client reset which could have lead to overwriting an existing file. ([realm/realm-core#7341](https://github.com/realm/realm-core/pull/7341)).

### Compatibility
* React Native >= v0.71.4
* Realm Studio v14.0.0.
* File format: generates Realms with format v23 (reads and upgrades file format v5 or later for non-synced Realm, upgrades file format v10 or later for synced Realms).
* Realm Studio v15.0.0.
* File format: generates Realms with format v24 (reads and upgrades file format v10 or later).

### Internal
<!-- * Either mention core version or upgrade -->
<!-- * Using Realm Core vX.Y.Z -->
<!-- * Upgraded Realm Core from vX.Y.Z to vA.B.C -->
* Upgraded Realm Core from v13.26.0 to v14.0.1. ([#6499](https://github.com/realm/realm-js/issues/6499))

## 12.6.1 (2024-02-26)

Expand Down
Binary file modified integration-tests/assets/bundled.realm
Binary file not shown.
12 changes: 6 additions & 6 deletions integration-tests/tests/src/tests/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ describe("Queries", () => {
["Unsupported comparison between type", "boolCol == 0"],
["Unsupported comparison between type", "boolCol == 1"],
["Unsupported comparison between type", "boolCol == 'not a bool'"],
["Unsupported comparison between type", "boolCol == $0", "not a bool"],
["Cannot compare argument $0 with value", "boolCol == $0", "not a bool"],
["Unsupported comparison operator", "boolCol BEGINSWITH true"],
["Unsupported comparison operator", "boolCol CONTAINS true"],
["Unsupported comparison operator", "boolCol ENDSWITH true"],
Expand Down Expand Up @@ -363,7 +363,7 @@ describe("Queries", () => {
expectQueryException(this.realm, NullableTypesObject, [
["Unsupported comparison between type", "dateCol == 'not a date'"],
["Unsupported comparison between type", "dateCol == 1"],
["Unsupported comparison between type", "dateCol == $0", 1],
["Cannot compare argument $0 with value", "dateCol == $0", 1],
]);
});
});
Expand Down Expand Up @@ -401,7 +401,7 @@ describe("Queries", () => {
expectQueryException(this.realm, NullableTypesObject, [
["Unsupported comparison between type", "intCol == false"],
["Cannot convert", "intCol == 'not an int'"],
["Unsupported comparison between type", "intCol == $0", "not an int"],
["Cannot convert", "intCol == $0", "not an int"],
["Unsupported comparison operator", "intCol BEGINSWITH 1"],
["Unsupported comparison operator", "intCol CONTAINS 1"],
["Unsupported comparison operator", "intCol ENDSWITH 1"],
Expand Down Expand Up @@ -446,7 +446,7 @@ describe("Queries", () => {
expectQueryException(this.realm, NullableTypesObject, [
["Unsupported comparison between type", "floatCol == false"],
["Cannot convert", "floatCol == 'not a float'"],
["Unsupported comparison between type", "floatCol == $0", "not a float"],
["Cannot convert", "floatCol == $0", "not a float"],
["Unsupported comparison operator", "floatCol BEGINSWITH 1"],
["Unsupported comparison operator", "floatCol CONTAINS 1"],
["Unsupported comparison operator", "floatCol ENDSWITH 1"],
Expand Down Expand Up @@ -492,7 +492,7 @@ describe("Queries", () => {
expectQueryException(this.realm, NullableTypesObject, [
["Unsupported comparison between type", "doubleCol == false"],
["Cannot convert", "doubleCol == 'not a double'"],
["Unsupported comparison between type", "doubleCol == $0", "not a double"],
["Cannot convert", "doubleCol == $0", "not a double"],
["Unsupported comparison operator", "doubleCol BEGINSWITH 1"],
["Unsupported comparison operator", "doubleCol CONTAINS 1"],
["Unsupported comparison operator", "doubleCol ENDSWITH 1"],
Expand Down Expand Up @@ -557,7 +557,7 @@ describe("Queries", () => {
expectQueryException(this.realm, NullableTypesObject, [
["Unsupported comparison between type", "stringCol == true"],
["Unsupported comparison between type", "stringCol == 123"],
["Unsupported comparison operator", "stringCol CONTAINS $0", 1],
["Cannot compare argument $0 with value", "stringCol CONTAINS $0", 1],
]);
});
});
Expand Down
2 changes: 1 addition & 1 deletion integration-tests/tests/src/tests/shared-realms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
////////////////////////////////////////////////////////////////////////////

import { expect } from "chai";
import Realm, { List } from "realm";
import Realm from "realm";

import { openRealmBefore, openRealmBeforeEach } from "../hooks";
import { createLocalConfig } from "../utils/open-realm";
Expand Down
24 changes: 24 additions & 0 deletions integration-tests/tests/src/tests/sync/realm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1986,6 +1986,30 @@ describe("Realmtest", () => {
new Realm({ path: "bundled.realm", disableFormatUpgrade: true });
}).throws("Database upgrade required but prohibited.");
});

it("checking is a bundled realm needs a file format upgrade", () => {
const config = { path: "bundled.realm" };
if (Realm.exists(config)) {
Realm.deleteFile(config);
}

Realm.copyBundledRealmFiles();
expect(Realm.needsFileFormatUpgrade(config)).to.be.true;
});

it("deleteRealmIfMigrationNeeded is not possible if file format can be upgraded", () => {
const config = { path: "bundle.realm", deleteRealmIfMigrationNeeded: true };
if (Realm.exists(config)) {
Realm.deleteFile(config);
}

Realm.copyBundledRealmFiles();
expect(() => {
new Realm(config);
}).throws(
"File format upgrade is needed and setting 'deleteRealmIfMigrationNeeded' to true will erase all objects. Only use 'deleteRealmIfMigrationNeeded' for non-production cases.",
);
});
});

describe("isEmpty property", () => {
Expand Down
7 changes: 6 additions & 1 deletion packages/realm/bindgen/js_opt_in_spec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -244,11 +244,16 @@ classes:
- get_results_description
- feed_buffer
- make_ssl_verify_callback
- needs_file_format_upgrade

LogCategoryRef:
methods:
- set_default_level_threshold
- get_category

Logger:
methods:
- set_default_logger
- set_default_level_threshold

ConstTableRef:
methods:
Expand Down
2 changes: 1 addition & 1 deletion packages/realm/bindgen/src/templates/jsi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1084,7 +1084,7 @@ export function generate({ rawSpec, spec, file: makeFile }: TemplateContext): vo
extern "C" {
void realm_jsi_invalidate_caches() {
// Clear the default logger, to prevent it from holding on to a pointer that was released
realm::util::Logger::set_default_level_threshold(realm::util::Logger::Level::off);
realm::util::LogCategory::get_category(realm::util::LogCategory::realm.get_name()).set_default_level_threshold(realm::util::Logger::Level::off);
realm::util::Logger::set_default_logger(nullptr);
// Close all cached Realms
realm::_impl::RealmCoordinator::clear_all_caches();
Expand Down
2 changes: 1 addition & 1 deletion packages/realm/bindgen/vendor/realm-core
Submodule realm-core updated 448 files
190 changes: 185 additions & 5 deletions packages/realm/src/Logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,145 @@ import { assert, binding } from "./internal";

export type LogLevel = "all" | "trace" | "debug" | "detail" | "info" | "warn" | "error" | "fatal" | "off";

/**
* Log levels used by Realm
*/
export enum NumericLogLevel {
/**
* Same as 'Trace' but with even more output.
*/
All = 0,
/**
* A version of 'Debug' that allows for very high volume
* output.
*/
Trace = 1,
/**
* Reveal information that can aid debugging, no longer paying
* attention to efficiency.
*/
Debug = 2,
/**
* Same as 'Info', but prioritize completeness over minimalism.
*/
Detail = 3,
/**
* Reveal information about what is going on, but in a
* minimalistic fashion to avoid general overhead from logging
* and to keep volume down.
*/
Info = 4,
/**
* Be silent unless when there is an error or a warning.
*/
Warn = 5,
/**
* Be silent unless when there is an error.
*/
Error = 6,
/**
* Be silent unless when an error is fatal.
*/
Fatal = 7,
/**
* Be silent.
*/
Off = 8,
}

/**
* The category to receive log messages for. The {@link LogLevel} will
* always be set for a specific category. Setting the log level on one
* category, will automatically set the log level for any subcategory.
* @note
* When debugging, you might not need log messages from everything. To narrow
* this scope, log events can be grouped by category.
*/
export enum LogCategory {
/**
* Include logs from all categories. Subcategories are {@link LogCategory.Storage},
* {@link LogCategory.Sync}, {@link LogCategory.App}, and {@link LogCategory.SDK}.
*/
Realm = "Realm",
/**
* Log database mutations and query operations.
* Subcategories are {@link LogCategory.Transaction}, {@link LogCategory.Object},
* {@link LogCategory.Query}, and {@link LogCategory.Notification}.
*/
Storage = "Realm.Storage",
/**
* Log when creating, advancing, and committing transactions.
*/
Transaction = "Realm.Storage.Transaction",
/**
* Log query operations.
*/
Query = "Realm.Storage.Query",
/**
* Log database mutations.
*/
Object = "Realm.Storage.Object",
/**
* Log notifications of changes to the database.
*/
Notification = "Realm.Storage.Notification",
/**
* Log activity related to Atlas Device Sync.
* Subcategories are {@link LogCategory.Client} and {@link LogCategory.Server}.
*/
Sync = "Realm.Sync",
/**
* Log activity related to Atlas Device Sync client operations.
* Subcategories are {@link LogCategory.Session}, {@link LogCategory.Changeset},
* {@link LogCategory.Network}, and {@link LogCategory.Reset}.
*/
Client = "Realm.Sync.Client",
/**
* Log connection level activity.
*/
Session = "Realm.Sync.Client.Session",
/**
* Log when receiving, uploading, and integrating changesets.
*/
Changeset = "Realm.Sync.Client.Changeset",
/**
* Log low level network activity.
*/
Network = "Realm.Sync.Client.Network",
/**
* Log client reset operations.
*/
Reset = "Realm.Sync.Client.Reset",
/**
* Log activity related to Atlas Device Sync server operations.
*/
Server = "Realm.Sync.Server",
/**
* Log activity at the Atlas App level.
*/
App = "Realm.App",
/**
* Log activity at the SDK level.
*/
SDK = "Realm.SDK",
}

/**
* Log options to use when setting the log level.
*/
export type LogOptions = {
/**
* The log level to be used by the logger.
* @default "info"
*/
level: LogLevel;
/**
* The category to set the log level for. If omitted, the log level
* is set for all categories ({@link LogCategory.Realm}).
*/
category?: LogCategory;
};

/**
* A callback passed to `Realm.App.Sync.setLogger` when instrumenting the Atlas Device Sync client with a custom logger.
* @param level - The level of the log entry between 0 and 8 inclusively.
Expand All @@ -40,7 +167,60 @@ export enum NumericLogLevel {
*/
export type Logger = (level: NumericLogLevel, message: string) => void;

export type LoggerCallback = (level: LogLevel, message: string) => void;
/**
* A callback passed to `Realm.setLogger`.
* @param level - The level of the log entry.
* @param message - The message of the log entry.
* @since 12.0.0
* @deprecated Will be removed in v13.0.0
*/
export type LoggerCallback1 = (level: LogLevel, message: string) => void;

/**
* Represents an entry in the log.
*/
export type LogEntry = {
/**
* The category (origin) of the log entry.
*/
category: LogCategory;
/**
* The level of the log entry.
*/
level: LogLevel;
/**
* The message of the log entry.
*/
message: string;
};

/**
* A callback passed to `Realm.setLogger`. Arguments are passed as an object.
* @since 12.7.0
*/
export type LoggerCallback2 = (entry: LogEntry) => void;
export type LoggerCallback = LoggerCallback1 | LoggerCallback2;

/** @internal */
export function toBindingLogger(logger: LoggerCallback) {
if (isLoggerWithLevel(logger)) {
return binding.Helpers.makeLogger((_, level, message) => {
logger(fromBindingLoggerLevelToLogLevel(level), message);
});
} else {
return binding.Helpers.makeLogger((category, level, message) => {
logger({
category: category as LogCategory,
level: fromBindingLoggerLevelToLogLevel(level),
message,
});
});
}
}

function isLoggerWithLevel(logger: LoggerCallback): logger is LoggerCallback1 {
return logger.length === 2;
}

/** @internal */
export function toBindingLoggerLevel(arg: LogLevel): binding.LoggerLevel {
Expand Down Expand Up @@ -77,12 +257,12 @@ export function fromBindingLoggerLevelToLogLevel(arg: binding.LoggerLevel): LogL
}

/** @internal */
export const defaultLogger: LoggerCallback = function (logLevel: LogLevel, message: string) {
const formattedLogMessage = `[${logLevel}] ${message}`;
export const defaultLogger: LoggerCallback2 = function ({ category, level, message }) {
const formattedLogMessage = `[${category} - ${level}] ${message}`;
/* eslint-disable no-console */
if (logLevel === "error" || logLevel === "fatal") {
if (level === "error" || level === "fatal") {
console.error(formattedLogMessage);
} else if (logLevel === "warn") {
} else if (level === "warn") {
console.warn(formattedLogMessage);
} else {
console.log(formattedLogMessage);
Expand Down
Loading

0 comments on commit 63104f4

Please sign in to comment.